Как показал Ганеш, к сожалению, сейчас это невозможно, без изменения источника платформы.
Фактически два способа передачи данных конкретного кодека могут быть переданы во внутренний класс MPEG4Writer, но ни один из них не работает без изменений.
Как обнаружил Ганеш, логика переназначения ключей 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
в 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.
Насколько я могу видеть, что нет никакого способа мультиплексирования MPEG4 видео с MediaMuxer прямо сейчас, используя общедоступный API, без изменения источника платформы. Учитывая проблемы в Utils.cpp выше, вы не можете мультиплексировать какой-либо видеоформат, требующий конкретных данных кодека, за исключением H264. Если VP8 является опцией, вы можете мультиплексировать это в файлы webm (вместе с аудио vorbis), но аппаратные кодеры для VP8, вероятно, гораздо менее распространены, чем аппаратные кодеры для MPEG4.
Имеет ли newFormat csd-0 и csd-1? – Marlon
@Marlon: newFormat: {height = 720, mime = video/mp4v-es, csd-0 = java.nio.ByteArrayBuffer [position = 0, limit = 30, capacity = 30], what = 1869968451, width = 1280} и csd-0: 000001B006000001B58913000001000000012000C48881F4528045A1463F. csd-1 нет, но я думаю, что он появляется только для H264. – user1592546
http://stackoverflow.com/questions/21341169/mediamuxer-fails-to-stop-if-csd-1-not-exist похоже, что csd-1 может потребоваться – Marlon