2012-10-17 64 views
11

AndroidでMediaCodec APIを使用してAACストリームをデコードしようとしています。 MediaCatec.createAudioFormat()を使ってMediaCodec.configure()に渡すフォーマットオブジェクトを作成しようとしましたが、AAC(audio/mp4a-latm)を使用するとエラーが発生しました。 (MP3(audio/mpeg)でも動作しますが...)AndroidでMediaCodec APIを使用してAACをデコードする

最後に、AACファイルのMediaExtractorを作成し、作成したフォーマットオブジェクトを見ました。私は、値0x12の2バイトで構成されるByteBufferのキー "csd-0"が含まれていることがわかりました。 AACコーデックの設定に使用したフォーマットオブジェクトにそのキーと値を含めると、すべてが機能します。

何が起こっているのか考えている人はいますか?ドキュメントでは、そのキーを設定しないでください。 MediaExtractorを使わずにフォーマットオブジェクトを生成するAACファイルをデコードするMediaCodecの例へのポインタを誰かが持っていますか?

+1

詳しい調査の結果、CSD-0はESDS(エレメンタリストリーム記述)が含まれていることを信じるように私をリードしています。 Androidソースのavc_utils.cppのMakeAACCodecSpecificDataを見ると、最初の5ビットがオブジェクトタイプ(2)で、次の4つは周波数インデックス(4 = 48000)、次の4つはチャネルconfig(2)です。 [このwikiページ](http://wiki.multimedia.cx/index.php?title=Understanding_AAC)は、残りのビットがフレーム長、コアデコーダー、拡張フラグに依存することを示します。 ESDSの重要な要素をセットアップするMediaFormat.createAudioFormat()を使用しています。 –

答えて

4

はい、コーデック設定2バイトが最初に受信したものです。そして、それは生aacデータブロックです。エンコーディング中に以下のフォーマットをどのように引き出すかを見ることができます。私は最初、ドキュメンテーションに従おうとしました。彼らは、彼らがlatm形式であり、それを解析しようとしていたと言いました。私はアンドロイドのドキュメンテーションに「diff」を見つけました。その出力は実際には生のブロックであると言いました。それが分かっていれば、それは単に自分のニーズに合った容器を選ぶということでした。特に、flvやmp4ではなくadtsのコンテナが必要でした。

コンテナに十分な大きさの配列にペイロードデータをコピーするには、ビットを追加してください。このようなものを使用して

profile = (configParams[0]>>3)&0x1f; 

frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1; 

channel_config = (this.configParams[1]>>3) &0xf; 

int finallength = encoded_length + 7;  
ENCodedByteArray[0] = (byte) 0xff; 
ENCodedByteArray[1] = (byte) 0xf1; 
ENCodedByteArray[2] = (byte) (((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2)); 
ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11)); 
ENCodedByteArray[4] = (byte)((finallength & 0x7ff) >> 3); 
ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ; 
ENCodedByteArray[6] = (byte) 0xfc; 

:だから私のソリューションのためのインターネットを精練した後、私は次のコードを生成

byte chunkADTS[]=new byte[info.size + 7]; 
fillInADTSHeader(chunkADTS,info.size); 
outputBuffers[bR].get(chunkADTS,7,info.size); 
buffer.pushData(chunkADTS); 
+0

私はフォローアップの質問があります:上記の "configParams"の値は何ですか?これはSDPメッセージ(RTSPストリームの場合)のa = fmtp:nn行のconfig = xxxxの値ですか? –

+0

設定パラメータは特定のオーディオ設定であり、通常はlatmメディアコーデックによって出力される最初の2バイトです。 BufferInfoオブジェクトには、Codec_infoフラグが設定されている必要があります。 –

2

私は次のコードを使用し、ADTSヘッダを削除したESを追加し、それがうまく仕事ができますが、私は何の問題は、私がテストしたいくつかのデバイス上のAACコンテンツを再生/デコードなかった私は本当に、なぜ「CSD-0」に設定する必要があります知っていない、またはコーデックがエラー

 decoder = MediaCodec.createDecoderByType("audio/mp4a-latm"); 
     mMediaFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 44100,2); 
     byte[] bytes = new byte[]{(byte) 0x12, (byte)0x12}; 
     ByteBuffer bb = ByteBuffer.wrap(bytes); 
     mMediaFormat.setByteBuffer("csd-0", bb); 
0

を発生します。私のアプローチは、まずMediaExtractorを使用してデータソースを設定し、次にMediaFormatを初期化し、最後にMediaCodecとの間で送受信されるバッファを持つループで作業を行いました。サーフェスの場合はnullを使用しました。これはオーディオプレーヤーなので、表示するものは何もありません。

私もAndroidのライブラリとして一緒にサンプルコードを入れて、それが私のブログで提供されています:http://www.pocketmagic.net/2014/06/android-audio-player-using-mediacodec-mediaextractor/