使用MediaCodec API使QualComm编码器正常工作

6
我正在尝试使用Android MediaCodec API对NV12流进行硬件编码(avc)。
当使用OMX.qcom.video.encoder.avc时,分辨率为1280x720和640x480的工作正常,而其他分辨率(即640x360、320x240、800x480)产生的输出似乎移动了色度分量(请参见snapshot)。
我已经通过将其保存为jpeg文件来双重检查输入图像是否正确。这个问题只在高通设备上出现(即三星Galaxy S4)。
有没有人能够正常地工作?还需要任何额外的设置/技巧吗?

1
Android 4.3增加了一些有用的新功能,并添加了CTS测试,可以将YUV数据输入到“MediaCodec”中。 http://bigflake.com/mediacodec/#EncodeDecodeTest中的缓冲区到缓冲区和缓冲区到表面测试可能会提供信息。 - fadden
1
顺便提一下,在android-platform Google Group中有关于QualComm编码器的讨论:https://groups.google.com/d/msg/android-platform/awaNwgb6EbY/a-YiIOwaL0QJ 其中一位评论者指出色度平面应该按照2048字节边界对齐,但这对我只有部分有效。例如,176x144的一些分辨率仍然存在问题。 - Andrey Chernih
2个回答

4

解码器(MediaCodec)有它自己的MediaFormat,可以使用getOutputFormat来接收。返回的实例可以打印到日志中。在那里,您可以看到一些有用的信息。例如,在您的情况下,“slice-height”这样的值可能很有用。我怀疑它对于1280x720和640x480的高度相等,并且对于其他分辨率不同。可能您应该使用此值来获取色度偏移。


作为一个快速解决方案,我根据解码器中 'slice-height' 和 'stride' 的数值进行了分辨率的更改。例如,将 640x360 更改为 640x384,将 320x200 更改为384x256。然后问题得到了很好的解决 :) 谢谢! - Paul Kapustin
@badbadboy,你找到一种动态计算步幅和切片高度的方法了吗?假设使用高通编码器时分辨率是固定的。 - dmarcato
我想知道什么时候应该调用getOutputFormat()?在启动MediaCodec之前和之后调用它时,我会收到IllegalStateException异常。文档说明应该在INFO_OUTPUT_FORMAT_CHANGED事件之后调用它,但编码器从未发送此事件。 - Andrey Chernih

4

是的,OMX.qcom.video.encoder.avc可以实现这一点,但并非所有设备/Android版本都支持。在我用Android 4.3的Nexus 4上,编码器运行良好,但在我的S3(运行4.1)上不行。

对于运行OMX.qcom.video.encoder.avc的4.1 S3(似乎有些S3使用另一个编码器)的解决方案是在Chroma面板之前添加1024字节。

// The encoder may need some padding before the Chroma pane
int padding = 1024;                     
if ((mWidth==640 && mHeight==480) || mWidth==1280 && mHeight==720) padding = 0;

// Interleave the U and V channel
System.arraycopy(buffer, 0, tmp, 0, mYSize); // Y
for (i = 0; i < mUVSize; i++) {
   tmp[mYSize + i*2 + padding] = buffer[mYSize + i + mUVSize]; // Cb (U)
   tmp[mYSize + i*2+1 + padding] = buffer[mYSize + i]; // Cr (V)
}
return tmp;

相机正在使用YV12,编码器使用COLOR_FormatYUV420SemiPlanar。

您截图显示的是我也遇到过的同类伪影,您可能需要进行一些类似的hack以适用于某些分辨率,甚至在4.3上也是如此(http://code.google.com/p/android/issues/detail?id=37769)!

您还应避免分辨率不是16的倍数,即使在4.3上也是如此。


如何确定我的大小(mYSize)和纹理坐标大小(mUVSize)? - Stefan Alexandru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接