2016-10-10 58 views
0

我试图捕捉到Android的views为位图,并将其保存为.mp4档案高通公司的AVC编码器。输入缓冲区编码通过Android的MediaCodec

我使用MediaCodec来编码位图,MediaMuxer将它们复合到.mp4中。

使用YUV420p彩色格式我期望MediaCodec的输入缓冲区大小为resWidth * resHeight * 1.5,但Qualcomm的OMX.qcom.video.encoder.avc给了我更多(不管我选择什么样的分辨率)。我相信它希望我在输入字节流中进行一些调整,但我不知道如何找出它期望我做什么。

这是当我使用了高通的编解码器紧紧地包在在Nexus 7(2013)输入缓冲器我的数据我得到什么:https://www.youtube.com/watch?v=JqJD5R8DiC8

而这个视频是由同样的应用进行运行在Nexus 10上(编解码器OMX.Exynos.AVC.Encoder ):https://www.youtube.com/watch?v=90RDXAibAZI

所以看起来亮度平面是在错误的视频好吧,但所发生的事情与色度平面是一个谜给我。

我准备最少(2类)工作的代码示例暴露出这个问题:https://github.com/eeprojects/MediaCodecExample

可以得到上面所示的视频只是通过运行这个程序(如果您的设备采用了高通的编解码器会出现相同的假象)。

回答

1

有在缓冲器存储YUV 420的多种方式;您需要检查您选择的单个像素格式。 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PlanarMediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar实际上是相同的,简称为平面或I420,而其他的,MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar,MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanarMediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar称为半平面或NV12。

在semiplanar,你不必为U和V分离的平面,但你必须有对交错的U,V的一个单一的平面。

请参阅 https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java(第925-949行)的示例,了解如何填充半平面格式的缓冲区。

+0

再次感谢您的帮助。但是如果编解码器支持'CodecCapabilities.COLOR_FormatYUV420Flexible'怎么办?文档说它可以是平面或半平面的。您还可以在尝试为尽可能多的编解码器提供支持的同时,指出一些我可能陷入的陷阱吗? –

+1

如果编解码器支持'CodecCapabilities.COLOR_FormatYUV420Flexible'和你选择了它,它允许编码器内部挑就是了取其格式(只要它可以被描述为一个灵活的YUV420格式)。如果你使用这个,你需要使用'MediaCodec.getInputImage'来获得缓冲区的描述(而不是旧的'getInputBuffers()'或'getInputBuffer()')。然后,你有三个直接的'ByteBuffers'用于每个平面,而一个通用的行和像素跨度来描述如何填充它。 – mstorsjo

+1

即使灵活的YUV 420格式确实允许非常疯狂的格式,但我认为它实际上实际上将是平面和半平面,而且它们仍然会通过正常的像素格式曝光。因此,如果您关心支持旧版本,那么按照您的方式进行操作并不会有太大的损失(我还没有看到过不支持平面或半平面输入的设备,因为这是CTS测试的结果也需要!)。 – mstorsjo