Android 如何获取MediaCodec编码器的跨距和Y平面对齐值
关于这个主题,有几个相关的问题和讨论:Android 如何获取MediaCodec编码器的跨距和Y平面对齐值,android,encoding,android-mediacodec,Android,Encoding,Android Mediacodec,关于这个主题,有几个相关的问题和讨论: 我正在将相机预览帧(NV21转换为NV12)传送到MediaCodec编码器(NV12akaCOLOR\u formatYUV420半平面)。看起来,在一些装有高通编码器的设备上,运行的安卓版本低于4.3,我必须进行一些输入帧处理,以便接收正确颜色的后帧 在运行Android 4.2.2的Sony Xperia ZR上,我必须添加Y平面对齐,以便在几乎所有分辨率下都能工作。上面的代码为不能除以32的宽度添加了1024字节对齐,为其他分辨率添加了
NV21
转换为NV12
)传送到MediaCodec
编码器(NV12
akaCOLOR\u formatYUV420半平面
)。看起来,在一些装有高通编码器的设备上,运行的安卓版本低于4.3
,我必须进行一些输入帧处理,以便接收正确颜色的后帧
在运行Android 4.2.2的Sony Xperia ZR上,我必须添加Y
平面对齐,以便在几乎所有分辨率下都能工作。上面的代码为不能除以32
的宽度添加了1024
字节对齐,为其他分辨率添加了2048
字节对齐。它使MediaCodec
能够对所有分辨率的帧进行正确编码,这些分辨率可以除以16
(除了176x144
,因为UV
平面看起来未对齐)
int getYPadding(){
if(mediacodeinfo.getName()包含(“OMX.qcom”)和&android.os.Build.VERSION.SDK_INT<18){
如果((getWidth()%32)!=0){
返回值(getWidth()*getHeight())%1024;
}否则{
返回值(getWidth()*getHeight())%2048;
}
}
返回0;
}
我试着在运行相同的Android 4.2.2的LG G2上测试这种对齐方式,它有高通公司的编码器,看起来它不能正常工作<代码>UV平面未对齐(框架底部的绿色条纹)。我无法计算两款手机的填充物
我还可以使用高通公司芯片组访问运行安卓4.3
的索尼Xperia Z1
,看起来它没有这样的问题。每个分辨率的视频看起来都很好,Y
平面无论如何都不需要对齐
我知道它与硬件相关,可能很复杂,但由于我必须支持运行4.3
之前的Android系统的用户,我有一个问题。是否有可能通过编程确定给定颜色格式的编码器期望的平面对齐和垂直/水平跨距值?问题简而言之:在Android 4.3(API 18)之前,视频编码没有任何限制
因此,MediaCodec
在不同设备上的行为不一致,一些bug没有被注意到。这些测试执行您所询问的功能,因此您可以可靠地将YUV数据提供给4.3+设备(尽管您仍然需要在运行时检测它是要平面还是半平面)
对于您的具体问题,较旧的高通设备上的Y平面需要在2K边界对齐,这与您的代码所做的不完全相同。对于720p视频,这是自然发生的(720*1280==450*2048),对于176x144,您需要调整1280以在26624而不是25344处开始UV平面。您需要在缓冲区内设置绝对对齐,而不是固定的填充量——使用uvoffset=(width*height+2047)和~2047
您需要检测编解码器供应商和Android软件版本,如果是高通4.3之前版本,则需要进行此调整。如果您的需求发生变化,并且您可以针对API 18+,这些问题就会消失。(您可以使用Surface
输入到MediaCodec
,这避免了U/V交换问题,尽管这取决于您的需要,可能没有什么用处。)感谢您的回答,@fadden you's awees!:)通过正确的对齐方式,我终于能够在索尼Xperia ZR
上实现所有分辨率。LG G2上仍然有问题,但我想我会把它总结成一个单独的问题,并附上一些屏幕截图。除此之外,您更可能希望在2K边界对齐Y平面和UV平面。例如,对于480x480的RGB视频分辨率,要传递给MediaCodec的Yuv420缓冲区的大小应为:YUVBufferSize+yOffset+uvOffset,其转换为:(480*480*1.5)+(2048-((480*480)%2048))+(2048-((480*480/2)%2048))。我不知道LG_G2使用哪种编码器,如果是qcom编码器,那么您可以尝试这种逻辑。希望这有帮助。
int getYPadding() {
if (mediaCodecInfo.getName().contains("OMX.qcom") && android.os.Build.VERSION.SDK_INT < 18) {
if ((getWidth() % 32) != 0) {
return (getWidth()*getHeight()) % 1024;
} else {
return (getWidth()*getHeight()) % 2048;
}
}
return 0;
}