1

マイクからのオーディオ (didGetAudioData を上書き) とカメラからのビデオ (onpreviewframe を上書き) を多重化して mp4 ファイルを生成したいと考えています。互換性のない構成またはpresentationTimeUsに関連する問題について、誰かが問題を解決する方法を教えてくれるのではないかと思いました. 以下は私のソフトウェアでした。

ビデオ構成

formatVideo = MediaFormat.createVideoFormat(MIME_TYPE_VIDEO, 640, 360);
formatVideo.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
formatVideo.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
formatVideo.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
formatVideo.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

以下のようにビデオプレゼンテーションPTSを取得しました。

if(generateIndex == 0) {
    videoAbsolutePtsUs = 132;
    StartVideoAbsolutePtsUs = System.nanoTime() / 1000L;
}else {
    CurrentVideoAbsolutePtsUs = System.nanoTime() / 1000L;
    videoAbsolutePtsUs =132+ CurrentVideoAbsolutePtsUs-StartVideoAbsolutePtsUs;
}
generateIndex++;

オーディオ構成

format = MediaFormat.createAudioFormat(MIME_TYPE, 48000/*sample rate*/, AudioFormat.CHANNEL_IN_MONO /*Channel config*/);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE,48000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT,1);
format.setInteger(MediaFormat.KEY_BIT_RATE,64000);

以下のようにオーディオプレゼンテーションPTSを取得しました。

if(generateIndex == 0) {
   audioAbsolutePtsUs = 132;
   StartAudioAbsolutePtsUs = System.nanoTime() / 1000L;
}else {
   CurrentAudioAbsolutePtsUs = System.nanoTime() / 1000L;
   audioAbsolutePtsUs =CurrentAudioAbsolutePtsUs - StartAudioAbsolutePtsUs;
}

generateIndex++;
audioAbsolutePtsUs = getJitterFreePTS(audioAbsolutePtsUs, audioInputLength / 2);

long startPTS = 0;
long totalSamplesNum = 0;
private long getJitterFreePTS(long bufferPts, long bufferSamplesNum) {
    long correctedPts = 0;
    long bufferDuration = (1000000 * bufferSamplesNum) / 48000;
    bufferPts -= bufferDuration; // accounts for the delay of acquiring the audio buffer
    if (totalSamplesNum == 0) {
        // reset
        startPTS = bufferPts;
        totalSamplesNum = 0;
    }
    correctedPts = startPTS +  (1000000 * totalSamplesNum) / 48000;
    if(bufferPts - correctedPts >= 2*bufferDuration) {
        // reset
        startPTS = bufferPts;
        totalSamplesNum = 0;
        correctedPts = startPTS;
    }
    totalSamplesNum += bufferSamplesNum;
    return correctedPts;
}

この問題は、オーディオのみにジッター機能を適用したことが原因でしたか? はいの場合、ビデオにジッター機能を適用するにはどうすればよいですか? また、 https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.javaで正しいオーディオとビデオのプレゼンテーションPTSを見つけようとしました. しかし、encodedecodeTest はビデオ PTS しか提供しませんでした。これが、私の実装でオーディオとビデオの両方にシステム ナノタイムを使用した理由です。コード化されたデコードテストでビデオ プレゼンテーションPTSを使用したい場合、互換性のあるオーディオ プレゼンテーションPTSを構築するにはどうすればよいですか? 手伝ってくれてありがとう!

以下は、参照用にyuvフレームをビデオメディアコーデックにキューに入れる方法です。オーディオ部分については、presentationPTS が異なる以外は同一です。

int videoInputBufferIndex;
int videoInputLength;
long videoAbsolutePtsUs;
long StartVideoAbsolutePtsUs, CurrentVideoAbsolutePtsUs;

int put_v =0;
int get_v =0;
int generateIndex = 0;

public void setByteBufferVideo(byte[] buffer, boolean isUsingFrontCamera, boolean Input_endOfStream){
    if(Build.VERSION.SDK_INT >=18){
        try{

            endOfStream = Input_endOfStream;
            if(!Input_endOfStream){
            ByteBuffer[] inputBuffers = mVideoCodec.getInputBuffers();
            videoInputBufferIndex = mVideoCodec.dequeueInputBuffer(-1);

                if (VERBOSE) {
                    Log.w(TAG,"[put_v]:"+(put_v)+"; videoInputBufferIndex = "+videoInputBufferIndex+"; endOfStream = "+endOfStream);
                }

                if(videoInputBufferIndex>=0) {
                    ByteBuffer inputBuffer = inputBuffers[videoInputBufferIndex];
                    inputBuffer.clear();

                    inputBuffer.put(mNV21Convertor.convert(buffer));
                    videoInputLength = buffer.length;

                    if(generateIndex == 0) {
                        videoAbsolutePtsUs = 132;
                        StartVideoAbsolutePtsUs = System.nanoTime() / 1000L;
                    }else {
                        CurrentVideoAbsolutePtsUs = System.nanoTime() / 1000L;
                        videoAbsolutePtsUs =132+ CurrentVideoAbsolutePtsUs - StartVideoAbsolutePtsUs;
                    }

                    generateIndex++;

                    if (VERBOSE) {
                        Log.w(TAG, "[put_v]:"+(put_v)+"; videoAbsolutePtsUs = " + videoAbsolutePtsUs + "; CurrentVideoAbsolutePtsUs = "+CurrentVideoAbsolutePtsUs);
                    }

                    if (videoInputLength == AudioRecord.ERROR_INVALID_OPERATION) {
                        Log.w(TAG, "[put_v]ERROR_INVALID_OPERATION");
                    } else if (videoInputLength == AudioRecord.ERROR_BAD_VALUE) {
                        Log.w(TAG, "[put_v]ERROR_ERROR_BAD_VALUE");
                    }
                    if (endOfStream) {
                        Log.w(TAG, "[put_v]:"+(put_v++)+"; [get] receive endOfStream");
                        mVideoCodec.queueInputBuffer(videoInputBufferIndex, 0, videoInputLength, videoAbsolutePtsUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    } else {
                        Log.w(TAG, "[put_v]:"+(put_v++)+"; receive videoInputLength :" + videoInputLength);
                        mVideoCodec.queueInputBuffer(videoInputBufferIndex, 0, videoInputLength, videoAbsolutePtsUs, 0);
                    }
                }
            }
        }catch (Exception x) {
            x.printStackTrace();
        }
    }
}
4

1 に答える 1

0

私のアプリケーションでこれをどのように解決したかというと、すべてのビデオおよびオーディオ フレームの PTS を最初のビデオ フレーム (その上に PTS 0 を持つ独自)をご利用いただけます。したがって、オーディオの録音がビデオよりも早く開始された場合、オーディオ データはビデオが開始されるまで無視されます (エンコーダーには入れられません)。開始が遅れた場合、最初のオーディオ PTS はビデオ全体の開始点を基準にします。

もちろん、オーディオを最初に開始することを自由に許可できますが、プレーヤーは通常スキップするか、最初のビデオ フレームを待ちます。また、エンコードされたオーディオ フレームが「順不同で」到着し、遅かれ早かれ MediaMuxer がエラーで失敗することに注意してください。私の解決策は、それらをすべて次のようにキューに入れることでした。新しいものが入ったときにptsでソートし、500ミリ秒(最新のものと比較して)より古いものすべてをMediaMuxerに書き込みますが、最新よりもPTSが高いもののみを書き込みます書き枠。理想的には、これはデータが 500 ミリ秒の遅延で MediaMuxer にスムーズに書き込まれることを意味します。最悪の場合、いくつかのオーディオ フレームが失われます。

于 2016-03-22T00:02:05.453 に答える