Я планирую преобразовать видеофайл в другой видеофайл с другим битрейтом, частотой кадров и т. д.
В основном я следую примерам в http://bigflake.com/mediacodec.
Однако журнал показывает ошибку отсутствия кадров синхронизации для видеодорожки:
submitted frame 5 to dec, size=47398
no output from encoder available
decoder output format changed: {height=1080, what=1869968451, color-format=2141391875, slice-height=1088, crop-left=0, width=1920, crop-bottom=1079, crop-top=0, mime=video/raw, stride=1920, crop-right=1919}
no output from encoder available
surface decoder given buffer 0 (size=3137536)
awaiting frame
E/MPEG4Writer(3464): There are no sync frames for video track
W/MPEG4Writer(3464): 0-duration samples found: 1
Stopping Video track
Затем программа выходит.
Я искал в Интернете. Фадден говорит "Убедитесь, что вы передаете все значения MediaCodec.BufferInfo в MediaMuxer - это где находятся флаги. Кадры синхронизации будут иметь установленный флаг BUFFER_FLAG_SYNC_FRAME."
Однако в примере с http://bigflake.com/mediacodec используется:
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,10);
Похоже, это означает, что кодер будет определять, какой кадр будет назначен ключевому кадру.
Кажется, в Интернете не так много связанной информации по этой проблеме. О, хотелось бы, чтобы на bigflake.com было больше примеров, связанных с некоторыми проблемами, которые интересуют разработчиков (например, изменение параметров формата одного существующего видеофайла)
==[Обновление]== Вот код, который я использую:
MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,5000000);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE,30);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,5);
encoder = MediaCodec.createEncoderByType(MIME_TYPE);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
encoder.start();
...
try {
mMuxer = new MediaMuxer(ouVideoFileName, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
} catch (IOException ioe) {
throw new RuntimeException("MediaMuxer creation failed", ioe);
}
...
// now that we have the Magic Goodies, start the muxer
mTrackIndex = mMuxer.addTrack(newFormat);
mMuxer.start();
mMuxerStarted = true;
...
mMuxer.writeSampleData(mTrackIndex, encodedData, info_encoder);
Тогда где мне не передать параметры в mMuxer? Кажется, я передал все необходимые параметры.
==[Обновление 2]== В:
int encoderStatus = encoder.dequeueOutputBuffer(info_encoder, TIMEOUT_USEC);
Я выхожу из системы info_encoder.flags: с 0 по 5 кадры, флаги = 0. Это не флаги для ключевого кадра. Входной видеофайл — короткий, записанный устройством, .mp4, и воспроизводится корректно. После кадра 5 MPEG4Write жалуется: «Нет кадров синхронизации для видеодорожки».
==[Обновление 3]== Кстати, я обнаружил, что часть кодирования между DecodeEditEncodeTest.java и EncodeDecodeTest.java отличается. Часть кодирования в EncodeDecodeTest.java включает encoder.dequeueInputBuffer, а в DecodeEditEncodeTest.java вообще нет строк, связанных с encoder.dequeueInputBuffer. Как вы думаете, это будет проблемой? Но, во-первых, почему они разные в двух примерах?
==[Обновление 4]== Я копирую код в класс ExtractMpegFramesTest
Затем в моем основном действии у меня есть кнопка. После того, как я нажму кнопку, он вызовет:
// test:
ExtractMpegFramesTest mTest = new ExtractMpegFramesTest();
try {
mTest.testExtractMpegFrames();
} catch (Throwable e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Ошибка:
E/ACodec(11342): [OMX.qcom.video.decoder.avc] storeMetaDataInBuffers failed w/ err -2147483648
java.lang.RuntimeException: frame wait timed out
ExtractMpegFramesTest$CodecOutputSurface.awaitNewImage(ExtractMpegFramesTest.java:496)
MediaMuxer
— это должно быть простым делом взять все, что вы получите от декодера, и передать егоwriteSampleData()
. - person fadden   schedule 03.03.2014CODEC_CONFIG
), должен быть кадром синхронизации. - person fadden   schedule 03.03.2014doEncodeDecodeVideoFromSurfaceToSurface()
нетencoder.dequeueInputBuffer()
. Может быть полезно увидеть полный цикл декодирования/кодирования. Вы можете вставлять большие фрагменты кода на gist.github.com . - person fadden   schedule 04.03.2014storeMetaDataInBuffers
, она появляется даже при успешных запусках. Ваша проблема заключается в том, что время ожидания кадра истекло, что произошло бы, если бы вы не сохранилиExtractMpegFramesWrapper
(который запускает все в отдельном потоке). FWIW, аналогичный вопрос: stackoverflow.com/questions/21750790/ - person fadden   schedule 04.03.2014