其他分享
首页 > 其他分享> > Android:如何将MediaMuxer与video / mp4v-es一起使用,而不是video / avc?

Android:如何将MediaMuxer与video / mp4v-es一起使用,而不是video / avc?

作者:互联网

我希望能够在某些设备上使用mp4v-es而不是avc.编码器可以使用avc正常运行,但是当我将其替换为mp4v-es时,复用器报告:

E/MPEG4Writer(12517): Missing codec specific data

MediaMuxer error “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有什么区别吗?一提,我只是跳过了“ bufferInfo.flags& MediaCodec.BUFFER_FLAG_CODEC_CONFIG”,因为对于avc来说它是不需要的.谢谢.

解决方法:

正如Ganesh指出的那样,不幸的是,如果不修改平台源代码,这似乎是不可能的.

可以将编解码器特定的数据传递到内部MPEG4Writer类的方法有两种,但实际上,这两种方法都无需修改就可以正常工作.

正如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);

其次,您可以在原理上将相同的缓冲区(设置了MediaCodec.BUFFER_FLAG_CODEC_CONFIG标志)传递给MediaMuxer.writeSampleData,而不是像MediaFormat中那样将编解码器特定的数据作为csd-0传递.该方法目前不起作用,因为该方法根本不检查编解码器配置标志-可以通过以下修改来解决:

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的硬件编码器少得多.

标签:video-encoding,mediacodec,mediamuxer,android
来源: https://codeday.me/bug/20191028/1955854.html