3

一部のデバイスで avc の代わりに mp4v-es を使用できるようにしたいと考えています。エンコーダーは avc を使用して正常に動作しますが、それを mp4v-es に置き換えると、マルチプレクサーは次のように報告します。

E/MPEG4Writer(12517): Missing codec specific data

MediaMuxer エラー "Failed to stop the muxer" のように、ビデオを再生できません。違いは、エラーを受け取ることなく、正しいトラック/フォーマットをマルチプレクサに追加していることです。

...else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
           MediaFormat newFormat = encoder.getOutputFormat();
           mTrackIndex[encID] = mMuxer.addTrack(newFormat);

avc と比較して mp4v-es の処理に違いはありますか? 1 つ言及すると、「bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG」が発生した場合はスキップするだけです。avc については不要でした。ありがとうございます。

4

2 に答える 2

2

Ganesh が指摘したように、残念ながら現在のところ、プラットフォーム ソースを変更しない限り、これは不可能のようです。

コーデック固有のデータを内部の MPEG4Writer クラスに渡すには、実際には 2 つの方法がありますが、どちらも実際には変更なしでは機能しません。

Ganesh が発見したように、MediaFormat キーを内部フォーマットに再マッピングするロジックには、H264 以外のビデオ コーデックのコーデック固有のデータの処理が欠けているようです。この問題を修正するテスト済みの変更は次のとおりです。

diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 25afc5b..304fe59 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -549,14 +549,14 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
     // reassemble the csd data into its original form
     sp<ABuffer> csd0;
     if (msg->findBuffer("csd-0", &csd0)) {
-        if (mime.startsWith("video/")) { // do we need to be stricter than this?
+        if (mime == MEDIA_MIMETYPE_VIDEO_AVC) {
             sp<ABuffer> csd1;
             if (msg->findBuffer("csd-1", &csd1)) {
                 char avcc[1024]; // that oughta be enough, right?
                 size_t outsize = reassembleAVCC(csd0, csd1, avcc);
                 meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize);
             }
-        } else if (mime.startsWith("audio/")) {
+        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
             int csd0size = csd0->size();
             char esds[csd0size + 31];
             reassembleESDS(csd0, esds);

csd-0第 2 に、 MediaFormat のようにコーデック固有のデータを渡す代わりに、原則として同じバッファを (MediaCodec.BUFFER_FLAG_CODEC_CONFIGフラグを設定して) に渡すことができますMediaMuxer.writeSampleData。このメソッドはコーデック設定フラグをまったくチェックしないため、このアプローチは現在機能しません。次の変更で修正できます。

diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index c7c6f34..d612e01 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -193,6 +193,9 @@ status_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackInde
     if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
         sampleMetaData->setInt32(kKeyIsSyncFrame, true);
     }
+    if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
+        sampleMetaData->setInt32(kKeyIsCodecConfig, true);
+    }

     sp<MediaAdapter> currentTrack = mTrackList[trackIndex];
     // This pushBuffer will wait until the mediaBuffer is consumed.

私が見る限り、プラットフォーム ソースを変更せずに、公開 API を使用している間は、現在 MediaMuxer で MPEG4 ビデオを多重化する方法はありません。上記の Utils.cpp の問題により、H264 を除き、コーデック固有のデータを必要とするビデオ フォーマットを多重化することはできません。VP8 がオプションの場合は、それを webm ファイルに (vorbis オーディオと共に) 多重化できますが、VP8 のハードウェア エンコーダーは、MPEG4 のハードウェア エンコーダーよりも一般的ではありません。

于 2014-12-27T18:17:07.957 に答える
2

ソースを変更する能力があると思います。Stagefrightしたがって、問題の解決策を提案しましたが、カスタマイズが必要です。

バックグラウンド:

エンコードがencoder完了すると、最初のバッファにcsdは通常OMX_BUFFERFLAG_CODECCONFIGフラグでタグ付けされた情報が含まれます。そのようなバッファが に返されるとMediaCodec、 と同じものが格納さcsd-0MediaCodec::amendOutputFormatWithCodecSpecificDataます。

これで、このバッファが に渡されると、呼び出されたMediaMuxerの一部として同じものが処理されます。同じの実装を参照すると、 のみが処理され、デフォルトで作成されることがわかります。addTrackconvertMessageToMetadataAVCvideoaudioESDS

編集:

ここで、このを次のように変更して、実験を試すことをお勧めします

} 
if (mime.startsWith("audio/") || (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {

この変更により、MPEG4ビデオトラックでも機能するはずです。変更は、以前の のチェックでもデータを処理しようとするため、 を にelse if変換することですが、 に対してのみです。ifvideoAVC

于 2014-12-21T13:13:28.117 に答える