Как и указал Ганеш, к сожалению, сейчас это невозможно без изменения исходного кода платформы.
На самом деле существует два способа передачи конкретных данных кодека во внутренний класс 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.
person
mstorsjo
schedule
27.12.2014
encoder
доMPEG4Writer
обязательно иметь 2 буфера дляcsd
.MPEG4Writer
может обрабатывать только один буфер. Ошибка т.е.Missing codec specific data
появляется, когда нетCSD
. Для элементарного видеопотокаvideo/mp4v-es
, т.е.MPEG4
,MPEG4Writer
ожидает, что данные будут упакованы в форматеESDS
по сравнению сAVCC
, как здесь: androidxref.com/5.0.0_r2/xref/frameworks/av/media/ - person Ganesh   schedule 15.12.2014csd
читается при создании новогоTrack
(ссылка:MPEG4Writer.cpp
выше, строка № 1370). Для дорожки видеокодер является источником, поэтому ваш кодировщик должен поддерживатьgetFormat
, в котором данные должны быть упакованы в форматеESDS
. - person Ganesh   schedule 15.12.2014