概述
Rockchip平台的mpp硬件编码器:mpp enc 仅接受硬件buf作为输入。当然如果使用malloc开辟的内存,硬件编解码器则无法完成“Zero Copy”,从而大大降低编码性能。本文主要介绍如何组织DRM buf的像素格式,从而避免内存搬运,实现“0拷贝”。
官方示例解说
官方提供的mpi_enc_test示例,其开辟drm buf大小是按照宽高16对齐后来计算的。比如:1920x1080的yuv420p图像,16对齐后的宽高为:1920x1088. 那么实际开辟的drm buf大小应为1920x1088x3/2. 之所以实际开辟的内存要16字节对齐,是因为mpp模块最小宏块是按照16x16处理。
既然引入的对齐,那么像素排布就必须必须依照对齐后的分辨率去处理。比如mpi_enc_test中提供的默认组织方式:
/* 针对1080P的分辨率,16对齐后的内存大小:1920x1088。
*
* 像素排布,比如8x4的YUV420P的图像,
* 开辟DMA内存大小为:8x8:
* Y Y Y Y Y Y Y Y
* Y Y Y Y Y Y Y Y
* Y Y Y Y Y Y Y Y
* Y Y Y Y Y Y Y Y
* - - - - - - - - //虚高行空出
* - - - - - - - - //虚高行空出。
* - - - - - - - - //虚高行空出。
* - - - - - - - - //虚高行空出。
* U U U U
* U U U U
* - - - -
* - - - -
* V V V V
* V V V V
* - - - -
* - - - -
*
* 注意,上面面二维buffer图,本质对应一维8x8的buffer数组,
* 数据组织格式如下:
* Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y(紧挨着下一行)
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* U U U U U U U U - - - - - - - - V V V V V V V V - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
MPP_RET read_yuv_image(RK_U8 *buf, FILE *fp, RK_U32 width, RK_U32 height,
RK_U32 hor_stride, RK_U32 ver_stride, MppFrameFormat fmt)
{
MPP_RET ret = MPP_OK;
RK_U32 read_size;
RK_U32 row = 0;
RK_U8 *buf_y = buf;
RK_U8 *buf_u = buf_y + hor_stride * ver_stride; // NOTE: diff from gen_yuv_image
RK_U8 *buf_v = buf_u + hor_stride * ver_stride / 4; // NOTE: diff from gen_yuv_image
switch (fmt) {
case MPP_FMT_YUV420SP : {
for (row = 0; row < height; row++) {
read_size = fread(buf_y + row * hor_stride, 1, width, fp);
if (read_size != width) {
mpp_err_f("read ori yuv file luma failed");
ret = MPP_NOK;
goto err;
}
}
for (row = 0; row < height / 2; row++) {
read_size = fread(buf_u + row * hor_stride, 1, width, fp);
if (read_size != width) {
mpp_err_f("read ori yuv file cb failed");
ret = MPP_NOK;
goto err;
}
}
} break;
case MPP_FMT_YUV420P : {
for (row = 0