正如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) {
sp<ABuffer> csd0;
if (msg->findBuffer("csd-0", &csd0)) {
- if (mime.startsWith("video/")) {
+ if (mime == MEDIA_MIMETYPE_VIDEO_AVC) {
sp<ABuffer> csd1;
if (msg->findBuffer("csd-1", &csd1)) {
char avcc[1024];
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
传递给 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];
据我所知,目前在使用公共API时,没有办法使用MediaMuxer混合MPEG4视频,而不修改平台源代码。鉴于上面Utils.cpp中的问题,您无法混合任何需要编解码器特定数据的视频格式,除了H264。如果VP8是一个选项,您可以将其混合到webm文件中(与vorbis音频一起),但是VP8的硬件编码器可能比MPEG4的硬件编码器少得多。
编码器
到MPEG4Writer
,我认为没有必要为csd
准备2个缓冲区。MPEG4Writer
只能处理一个缓冲区。当没有CSD
时,会出现错误,即“缺少编解码器特定数据”。对于video/mp4v-es
即MPEG4
视频基本流,MPEG4Writer
期望将数据打包为ESDS
格式,而不是像这里一样使用AVCC
:http://androidxref.com/5.0.0_r2/xref/frameworks/av/media/libstagefright/MPEG4Writer.cpp#1466 - GaneshMPEG4Writer.cpp
,第1370行)。对于该轨道,视频编码器是其来源,因此您的编码器应支持getFormat
,其中数据应以ESDS
格式打包。 - Ganesh