我计划将一个视频文件转换为另一个具有不同比特率、fps 等的视频文件。
基本上我遵循中的示例http://bigflake.com/mediacodec 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 标志。” https://stackoverflow.com/questions/21750790/android-mediamuxer-failed-to-stop
然而,从例子来看http://bigflake.com/mediacodec 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();
}
Error:
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)