2016-06-16 6 views
2

Androidでビデオファイルをフレーム精度で整える機能を構築しています。トランスコードは、MediaExtractor,MediaCodec、およびMediaMuxerで実装されています。私はビデオフレームの対応するものと一致させるために任意のオーディオフレームを切り捨てる助けが必要です。Android MediaCodec正確なトリムをフレームする方法

オーディオフレームは、非圧縮オーディオデータを編集できる論理的な場所であるデコーダ出力バッファでトリムする必要があります。

/アウトトリムに私は計算していますのために必要なオフセットと生のオーディオバッファにサイズ調整が可能なエンドキャップフレームにそれを押し込もする、と私は、次のコードを使用してデータを提出しています:

MediaCodec.BufferInfo info = pendingAudioDecoderOutputBufferInfos.poll(); 
... 
ByteBuffer decoderOutputBuffer = audioDecoder.getOutputBuffer(decoderIndex).duplicate(); 
decoderOutputBuffer.position(info.offset); 
decoderOutputBuffer.limit(info.offset + info.size); 
encoderInputBuffer.position(0); 
encoderInputBuffer.put(decoderOutputBuffer); 
info.flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM; 
audioEncoder.queueInputBuffer(encoderIndex, info.offset, info.size, presentationTime, info.flags); 
audioDecoder.releaseOutputBuffer(decoderIndex, false); 

私の問題は、データ調整が出力オーディオバッファにコピーされたデータだけに影響するように見えますが、MediaMuxerに書き込まれるオーディオフレームを短くしないことです。出力ビデオは、クリップの最後に数ミリ秒の欠落したオーディオで終わるか、あまりにも多くのデータを書き込むと、オーディオフレームはクリップの最後から完全に落ちます。

オーディオフレームを正しくトリミングする方法は?

+0

私が正しく理解していれば、 'queueInputBuffer'を呼び出すときに' info.offset'を使用することに矛盾があるようです。エンコーダの入力バッファが(info.offset' + 'info.size')に' info.offset'ではなく 'info.size'から0まで実行されていませんか?おそらく、あなたが経験する時間差は正確に0とオフセットの間のデータの量ですか? – Dave

+0

@Dave私はあなたが正しいと信じています。 'decoderOutputBuffer'、' encoderInputBuffer'、 'audioEncoder.queueInputBuffer'がすべて同じ' size'と 'offset'値を使うという保証はありません。私はいくつかの組み合わせを試みました。私はまた、データのサイズだけを減らしていると思いますが、コンテナは縮小していません。私は解決策が 'MediaCodec.BUFFER_FLAG_CODEC_CONFIG'の設定変更に似たものを含むかもしれないと考え始めました。 –

答えて

1

ここに遊びにいくつかのことをあります:Daveが指摘したように、0を渡す必要があります代わりにinfo.offsetaudioEncoder.queueInputBufferへの

  • - あなたはすでにあなたが設定したときに考慮デコーダ出力バッファのオフセットましたバッファ位置はdecoderOutputBuffer.position(info.offset);です。しかし、おそらくあなたはすでに何らかの形でそれを更新しています。

  • MediaCodecオーディオエンコーダで任意のサイズのチャンクでオーディオデータを渡すことができるかどうか、または一度に完全なオーディオフレームを送信する必要があるかどうかはわかりません。私はそれを受け入れるかもしれないと思う - それからあなたは大丈夫です。そうでない場合は、オーディオをバッファリングしてエンコーダーに渡す必要があります(最初にいくつかのトリムを取り除いた場合)

  • オーディオはフレームベースですAAC、低遅延ディストーションやHE-AACを使用していない限り、1024サンプルのフレームです)、44 kHzの場合は、オーディオの持続時間を23ミリ秒でしか設定できません。正しい量のサンプルの後でオーディオを正確に終了したい場合は、これを示すためにコンテナシグナリングを使用する必要があります。私は、MediaCodecオーディオエンコーダが最終的にどのハーフフレームをフラッシュしているのかわからない場合や、最後の数サンプルを取得するために最後に余分なゼロを手動で渡す必要がある場合は、フレームサイズ。しかし、それは必要ではないかもしれません。

  • エンコーディングAACオーディオでは、オーディオストリームに遅延が発生します。デコード後、デコードされたストリームの最初にいくつかのプライミングサンプルがあります(これらの正確な数は、エンコーダによって異なります).AAC-LCのAndroidのソフトウェアエンコーダの場合、おそらく2048サンプルですが、変化する)。 2048サンプルの場合、それは2フレームのオーディオと正確に並んでいますが、それはフレームの全数ではないものでもあります。私は、MediaCodecが正確な遅延量を知らせるとは思わない。エンコーダから2つの最初の出力パケットをドロップすると(遅延が2048サンプルの場合)、余分な遅延は回避されますが、最初の数フレームの実際のデコードされたオーディオは正確には正しくありません。 (プライミングパケットは、ストリームが開始するサンプルを適切に表現できるようにするために必要です。そうでなければ、2048サンプル以内に目的のオーディオにほぼ収束します。)

+0

ありがとうございます。あなたはまた、今年の私の質問に答え、ここに私に大きな助けをもたらしました:http://stackoverflow.com/a/35885471/376829。私は@Daveとあなたにオフセットについて同意します。 –

関連する問題