瑞芯微Rockchip开发者社区
直播中

carey123

11年用户 1658经验值
擅长:可编程逻辑 嵌入式技术
私信 关注
[问答]

如何去实现RK3399中的ffmpeg对于rkmpp硬件解码的转换呢

如何去实现RK3399中的ffmpeg对于rkmpp硬件解码的转换呢?

回帖(1)

李果

2022-3-7 14:47:59
RK3399 中的ffmpeg对于rkmpp硬件解码的转换


{
        AVCodecContext *codecCtx;
      
        size_t unused;
        RKMPPDecodeContext *rk_context = codecCtx->priv_data;
        RKMPPDecoder *decoder = (RKMPPDecoder *) rk_context->decoder_ref->data;
        ret = mpp_buffer_group_limit_config(decoder->frame_group, 0, 30); //重新group为30长度
        unused = mpp_buffer_group_unused(decoder->frame_group); //获取未使用个数
        log("CH:%d, unused:%dn", mediaService->chNo, unused);
}
...
while(1) ..... 循环读取视频流并解码
//解码成AVFrame
ret=avcodec_send_packet(codecCtx,pkt);
if(ret!=0){
        avcodec_flush_buffers(codecCtx); //刷新后可以重新解码
        continue;
}
avcodec_receive_frame(codecCtx, avframe);

{  //移动avframe到其他第放使用 format 为 AV_PIX_FMT_DRM_PRIME,即rkmpp的DRM数据
        AVFrame *dst_avframe = av_frame_alloc();
        av_frame_move_ref(dst_avframe, avframe);
        av_frame_unref(avframe); //必须加
      
        //将AVFrmae转换为rkmpp的数据格式
        AVBufferRef* framecontextref = (AVBufferRef*) av_buffer_get_opaque(
                                avframe->buf[0]);
        RKMPPFrameContext *framecontext =
                                (RKMPPFrameContext *) framecontextref->data;
        MppFrame mppframe=framecontext->frame;
        MppBuffer mppbuffer = mpp_frame_get_buffer(mppframe);
        MppFrameFormat format = mpp_frame_get_fmt(mppframe); //应该为MPP_FMT_YUV420SP(NV12)
        int width = mpp_frame_get_width(mppframe);
        int height = mpp_frame_get_height(mppframe);
        int hor_stride = mpp_frame_get_hor_stride(mppframe);
        int ver_stride = mpp_frame_get_ver_stride(mppframe);
        uint8_t *yuvDataPtr=mpp_buffer_get_ptr(buffer); //YUV数据(NV12)
        //这样可以处理MPP的硬件数据,缩放,截图可以使用RGA
}

...

avcodec_flush_buffers(codecCtx);
{
                RKMPPDecodeContext *rk_context = ffContext->pCodecCtx->priv_data;
                RKMPPDecoder *decoder = (RKMPPDecoder *) rk_context->decoder_ref->data;
                //等待未使用个数为原始的30个
                while (30 != (unused = mpp_buffer_group_unused(decoder->frame_group)))
                {
                        logInfo("Media", "CH:%d, mpp_buffer_group_unused:%dn", mediaService->chNo, unused);
                        sleep(1);
                }
}

RK3399 rga转换


/格式转化
MppFrame srcframe = AVFrame2MppFrame(avframe);
int hor_stride = mpp_frame_get_hor_stride(srcframe);
int ver_stride = mpp_frame_get_ver_stride(srcframe);
int src_width = mpp_frame_get_width(srcframe);
int src_height = mpp_frame_get_height(srcframe);
MppBuffer buffer = mpp_frame_get_buffer(srcframe);
uint8_t *src_yuv_ptr = (uint8_t*) mpp_buffer_get_ptr(buffer);


rga_info_t src_info; //原图像
memset(&src_info, 0, sizeof(rga_info_t));
src_info.fd = mpp_buffer_get_fd(buffer);
src_info.mmuFlag = 1;
rga_set_rect(&src_info.rect, 0, 0, src_width, src_height,hor_stride, ver_stride, RK_FORMAT_YCbCr_420_SP);  //NV12

//目标图像存储空间分配
int dst_width = src_width;
int dst_height = src_height;
int dst_hor = MPP_ALIGN(dst_width, 1); //默认16字节对其,才能编码成JPG,这里使用1字节对齐
int dst_ver = MPP_ALIGN(dst_height, 1); //默认16字节对其
int framesize = dst_ver * dst_hor * 3 / 2;
MppBuffer dst_buffer;
mpp_buffer_get(NULL, &dst_buffer, framesize); //申请内存

rga_info_t dst_info; //目标图像
memset(&dst_info, 0, sizeof(rga_info_t));
dst_info.fd = mpp_buffer_get_fd(dst_buffer);
dst_info.mmuFlag = 1;
rga_set_rect(&dst_info.rect, 0, 0, dst_width, dst_height,dst_hor, dst_ver, RK_FORMAT_YCrCb_420_P);
ret = c_RkRgaBlit(&src_info, &dst_info, NULL);
void *yuv_ptr = mpp_buffer_get_ptr(dst_buffer);
//对yuv_ptr做运算,人脸,车辆,车牌等 因为RK3399没有NPU,故而在CPU中处理GPU数据

mpp_buffer_put(dst_buffer); //释放内存
举报

更多回帖

发帖
×
20
完善资料,
赚取积分