我希望能够在某些设备上使用 mp4v-es 而不是 avc。编码器使用 avc 运行良好,但是当我用 mp4v-es 替换它时,muxer 报告:
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);
处理mp4v-es和avc有什么区别吗?一提,当它出现时我只是跳过“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);
其次,不是在 MediaFormat 中将编解码器特定数据作为 csd-0
传递,原则上您可以传递相同的缓冲区(设置 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.
据我所知,如果不修改平台源代码,目前无法在使用公共(public) API 时使用 MediaMuxer 混合 MPEG4 视频。鉴于上述 Utils.cpp 中的问题,您无法混合任何需要编解码器特定数据的视频格式,H264 除外。如果 VP8 是一个选项,您可以将它混合到 webm 文件中(连同 vorbis 音频),但是 VP8 的硬件编码器可能比 MPEG4 的硬件编码器少得多。
关于Android:如何将 MediaMuxer 与视频/mp4v-es 而不是视频/avc 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27302280/