rockchip-linux / mpp

Media Process Platform (MPP) module
581 stars 169 forks source link

MPP 解码获取的frame都是NULL,获取的width等都是0 #477

Closed alexanderdumas closed 11 months ago

alexanderdumas commented 11 months ago

主要逻辑也是参考的样例开发。

我是自己造的数据。利用opencv打开imread(这个函数相当于解码)jpg图片到mat,然后利用imencode(相当与编码到JPEG)。保存到一个vetcotbuf中。然后利用这个buf送到MPP中去解码,验证解码功能。(目前就解码一帧,实际业务也是一帧一帧放进去编码或者解码,一帧都是完整的。提前做好的一帧。) 初始化部分:(简单看核心部分,有需要可以提供完整的) ret = mpp_packet_init(&_paket, NULL, 0); if (ret) { printf("mpp_packet_init failed\n"); return; }

    ret = mpp_buffer_group_get_internal(&_buf_grp, MPP_BUFFER_TYPE_ION);
    if (ret) {
        printf("failed to get buffer group for input frame ret %d\n", ret);
        return;
    }

    //jpeg need outside buff
    ret = mpp_frame_init(&_frame);
    if (ret) {
        printf("mpp_frame_init failed %d\n", ret);
        return;
    }

    //buff space >= 3*width*height
    ret = mpp_buffer_get(_buf_grp, &_frm_buf, _hor_stride * _ver_stride * 4);
    if (ret) {
        printf("mpp_buffer_get failed %d\n", ret);
        return;
    }

    mpp_frame_set_width(_frame, _width);
    mpp_frame_set_height(_frame, _height);
    mpp_frame_set_hor_stride(_frame, _hor_stride);
    mpp_frame_set_ver_stride(_frame, _ver_stride);
    mpp_frame_set_fmt(_frame, _format);
    mpp_frame_set_buffer(_frame, _frm_buf);

解码部分: MPP_RET MppCodec::Decode(void *input, size_t len, std::vector & output) { MPP_RET ret = MPP_OK; RK_U32 pkt_done = 0;

//fill input to packet
mpp_packet_set_data(_paket, input);
mpp_packet_set_size(_paket, len);
mpp_packet_set_pos(_paket, input);
mpp_packet_set_length(_paket, len);
mpp_packet_set_eos(_paket);//this is important

//need do...while()
do {
    RK_U32 frm_eos = 0;
    ret = _mpi->decode(_ctx, _paket, &_frame);
    printf("decode_get_frame ret %d\n", ret);
    printf("decode_get_frame _frame %p\n", _frame);
    if (ret != MPP_OK) {
        printf("decode_get_frame failed ret %d\n", ret);
        break;
    }
    if (_frame) {
        printf("success\n");
        if (mpp_frame_get_info_change(_frame)) {
            RK_U32 width = mpp_frame_get_width(_frame);
            RK_U32 height = mpp_frame_get_height(_frame);
            RK_U32 hor_stride = mpp_frame_get_hor_stride(_frame);
            RK_U32 ver_stride = mpp_frame_get_ver_stride(_frame);
            RK_U32 buf_size = mpp_frame_get_buf_size(_frame);

            printf("decode_get_frame get info changed found\n");
            printf("decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size [%d]",
                    width, height, hor_stride, ver_stride, buf_size);

            /*
            * All buffer group config done. Set info change ready to let
            * decoder continue decoding
            */
            ret = _mpi->control(_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
            if (ret) {
                printf("%p info change ready failed ret %d\n", _ctx, ret);
                break;
            }
        } else {
            RK_U32 width = mpp_frame_get_width(_frame);
            RK_U32 height = mpp_frame_get_height(_frame);
            RK_U32 hor_stride = mpp_frame_get_hor_stride(_frame);
            RK_U32 ver_stride = mpp_frame_get_ver_stride(_frame);
            RK_U32 buf_size = mpp_frame_get_buf_size(_frame);
            _frm_buf   = mpp_frame_get_buffer(_frame);
            if (_frm_buf == NULL) {
                printf("%p mpp_frame_get_buffer null\n", _ctx);
                break;
            }
            _base = (RK_U8 *)mpp_buffer_get_ptr(_frm_buf);
            memcpy(&output[0], _base, buf_size);
        }

        frm_eos = mpp_frame_get_eos(_frame);

    } else {
        printf("not frame\n");
    }

    if (_paket) {
        int length = mpp_packet_get_length(_paket);
        printf("length %d\n", length);
        if (length > 0) {
            printf("length %d\n", length);
            usleep(1000);
            continue;
        }

        _paket = NULL;
        pkt_done = 1;
    }

    if (pkt_done) {
        break;
    }
    usleep(1000);
} while (1);

麻烦提供一下思路,看看哪里有问题: 我的业务场景是送过来的BGR的原始流,是一帧一帧的送,之前用opencv的imencode保存,现在想用MPP替换。 目前是_mpi->decode(_ctx, _paket, &_frame); 的到的frame是NULL

alexanderdumas commented 11 months ago

看了isuuse换成deque和enque了。结果都是空的。

//fill input to packet mpp_packet_set_data(_packet, input); mpp_packet_set_size(_packet, len); mpp_packet_set_pos(_packet, input); mpp_packet_set_length(_packet, len); mpp_packet_set_eos(_packet);//this is important

//jpeg must use this way
ret = _mpi->poll(_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK);
if (ret) {
    printf("%p mpp input poll failed\n", _ctx);
    return ret;
}

ret = _mpi->dequeue(_ctx, MPP_PORT_INPUT, &_task);  /* input queue */
if (ret) {
    printf("%p mpp task input dequeue failed\n", _ctx);
    return ret;
}

mpp_task_meta_set_packet(_task, KEY_INPUT_PACKET, _packet);
mpp_task_meta_set_frame (_task, KEY_OUTPUT_FRAME, _frame);

ret = _mpi->enqueue(_ctx, MPP_PORT_INPUT, _task);  /* input queue */
if (ret) {
    printf("%p mpp task input enqueue failed\n", _ctx);
    return ret;
}

/* poll and wait here */
ret = _mpi->poll(_ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK);
if (ret) {
    printf("%p mpp output poll failed\n", _ctx);
    return ret;
}

ret = _mpi->dequeue(_ctx, MPP_PORT_OUTPUT, &_task); /* output queue */
if (ret) {
    printf("%p mpp task output dequeue failed\n", _ctx);
    return ret;
}

if (_task) {
    printf("get task success\n");
    MppFrame frame_out = NULL;
    mpp_task_meta_get_frame(_task, KEY_OUTPUT_FRAME, &frame_out);
    if (_frame) {
        printf("get frame success\n");
        RK_U32 width = mpp_frame_get_width(_frame);
        RK_U32 height = mpp_frame_get_height(_frame);
        RK_U32 hor_stride = mpp_frame_get_hor_stride(_frame);
        RK_U32 ver_stride = mpp_frame_get_ver_stride(_frame);
        RK_U32 buf_size = mpp_frame_get_buf_size(_frame);
        printf("decoder buffer w:h [%d:%d] stride [%d:%d] buf_size [%d]",
                            width, height, hor_stride, ver_stride, buf_size);

        _frm_buf = mpp_frame_get_buffer(_frame);
        if (_frm_buf == NULL) {
            printf("%p mpp_frame_get_buffer null\n", _ctx);
            return ret;
        }

        frm_eos = mpp_frame_get_eos(frame_out);
        if (frm_eos) {
            printf("%p found eos frame\n", _ctx);
        } else {
            printf("%p not found eos frame\n", _ctx);
        }
    }
    /* output queue */
    ret = _mpi->enqueue(_ctx, MPP_PORT_OUTPUT, _task);
    if (ret) {
        printf("%p mpp task output enqueue failed\n", _ctx);
        return ret;
    }
}

mpp_packet_deinit(&_packet);

ret = ReSet();//must need
if (ret != MPP_OK) {
    printf("ReSet fail ret[%d]\n", ret);
    return ret;
}

执行的结果是0: decoder buffer w:h [0:0] stride [0:0] buf_size [0]0x55b2bd5f60 mpp_frame_get_buffer null

alexanderdumas commented 11 months ago

RK3588 上的 jpeg 编码器是 vepu2,支持 YUV420,YUV422,RGB565 以及 32bit 的 RGBX 输入,24bit 的 RGB 是不支持的

是不是解码也不行啊? 现在是解码成BGR888,自己造的数据是用rga造BGR888,然后用opencv压缩JEEG,想使用MPP解码成BGR888.

现在用的RK3588X

HermanChen commented 11 months ago

解码是 rkjpegd 应该是不带格式转换的,只能给出 YUV420/YUV422

alexanderdumas commented 11 months ago

解码是 rkjpegd 应该是不带格式转换的,只能给出 YUV420/YUV422

我的理解是MPP目前是只能输出YUVSP的。如果原始格式是YUV420SP,经过JPEG压缩后,是肯定能的到YUV420SP,对吧 如果原始格式BGR(或者RGB)是没有办法的到BGR或者RGB,对吧?还是会默认会的到YUV420SP,我测试中啥也得不到。全市空。errinfo获取frame_out是1,也就是提示出错了。

alexanderdumas commented 11 months ago

解码是 rkjpegd 应该是不带格式转换的,只能给出 YUV420/YUV422

我现在是用MPP使用JPEG压缩一个YUV420SP,没有报错,而且输出出来了,应该是成功了,接着用这个压缩的包再用MPP解压还是空的。

alexanderdumas commented 11 months ago

已经解决。需要按照样例写。编码,解码。尤其是JPEG这种压缩的。需要advance那个,不能用其他的。连分配空间都得按照样例来。有的用解码器内部分配的都不行,还得用group这种。 解码器确实只能是YUV420这种。如果原始的输入RGB这种,解码器什么也没有。会有一个错误,如果获取RK_U32 err_info = mpp_frame_get_errinfo(frame_out); 会的到一个错误信息