我正在使用以下代码来准备硬件解码器。我希望outputBufferIndex为-1,然后是MediaCodec.INFO_OUTPUT_FORMAT_CHANGED。在通知格式改变之前,它不应该> = 0。
我在25个不同的设备中测试了代码,其中7个永远不会返回INFO_OUTPUT_FORMAT_CHANGED。当我得到outputBufferIndex> = 0时,mediaCodec.getOutputFormat()返回了IllegalStateException。我不知道所有设备都没有用的巧合是android 4.2.2和OMX.qcom.video.decoder.avc解码器。 / p>
for (int i = 0; i < videoExtractor.getTrackCount(); i++) {
MediaFormat mediaFormat = videoExtractor.getTrackFormat(i);
String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
videoExtractor.selectTrack(i);
videoCodec = MediaCodec.createDecoderByType(mediaFormat.getString(MediaFormat.KEY_MIME));
videoCodec.configure(mediaFormat, null, null, 0);
videoCodec.start();
}
}
ByteBuffer[] videoInputBuffers = videoCodec.getInputBuffers();
while (true) {
int sampleTrackIndex = videoExtractor.getSampleTrackIndex();
if (sampleTrackIndex == -1) {
break;
} else { // decode video
int inputBufferIndex = videoCodec.dequeueInputBuffer(0);
if (inputBufferIndex >= 0) {
int bytesRead = videoExtractor.readSampleData(videoInputBuffers[inputBufferIndex], 0);
if (bytesRead >= 0) {
videoCodec.queueInputBuffer(inputBufferIndex, 0, bytesRead,
videoExtractor.getSampleTime(), 0);
videoExtractor.advance();
}
}
MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = videoCodec.dequeueOutputBuffer(videoBufferInfo, 0);
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat format = videoCodec.getOutputFormat();
Log.w("video format changed: " + videoCodec.getOutputFormat());
//do something...
break;
} else if (outputBufferIndex >= 0) {
//not supposed to happen!
}
}
}
非常感谢您的线索和帮助!
答案 0 :(得分:0)
在Android 4.3中,一系列MediaCodec
测试被添加到CTS中。如果您查看doEncodeDecodeVideoFromBuffer()
在EncodeDecodeTest中的工作方式,您可以看到它在任何数据之前需要INFO_OUTPUT_FORMAT_CHANGED
结果。如果它没有得到它,在尝试获取颜色格式时对checkFrame()
的调用将失败。在Android 4.3之前,没有测试,任何行为都是可能的。
话虽如此,我不记得在(基于Qualcomm的)Nexus 4上看到这种行为。
无论如何,除非你能够解码Qualcomm使用的专有缓冲区布局,否则我不确定这实际上会阻止你多少。您可以在同一个checkFrame()
函数中看到它在看到OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
时发挥作用。将输出发送到Surface可能是一种可行的替代方案,具体取决于您的目标。
bigflake和Grafika中的大多数MediaCodec
代码都是针对API 18(Android 4.3),因为那时行为变得更具可预测性。 (表面输入和MediaMuxer
的可用性也具有巨大的价值。)