RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法

mpp 解码之后出现绿屏,花屏等现象,一般是由于h265数据对齐问题,

h264视频对齐方式为16位对齐方法。

h265视频对齐方式位256奇数对齐。

h265对齐之后的宽高可通过 MPP函数中的

reallyWidth = static_cast( mpp_frame_get_hor_stride(frame));
reallyHight = static_cast( mpp_frame_get_ver_stride(frame));

RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法_第1张图片

 可将hor_stride 与 ver_stride 填入RGA 中的wrapbuffer_virtualaddr() 函数

src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);
dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);

注意  上述代码中的srcWidth与srcHight是真实的宽高

此时解码出的图像有存在绿边现象。

作者用的qt,可通过Qimage 的copy函数进行拷贝,去除,也可通过rga裁剪进行去除

完整c文件如下:

mpp.c

#include "mppdecode.h"

void MppDecode::slotGetSendMppSrcImg()
{
    srcImgSend = true;
}

void MppDecode::setWidthHight(int width, int hight)
{
//    initSrcHight = hight;
//    initSrcWidth = width;
//    while(hight%16 != 0)
//    {
//        hight++;
//    }
    srcHight = hight;
    srcWidth = width;

}

size_t MppDecode::mpp_buffer_group_usage(MppBufferGroup group)
{
    if (nullptr == group)
    {
        mpp_err_f("input invalid group %p\n", group);
        return MPP_BUFFER_MODE_BUTT;
    }

    MppBufferGroupImpl *p = (MppBufferGroupImpl *)group;
    return p->usage;
}

int MppDecode::decode_simple(MppDecode::MpiDecLoopData *data, AVPacket *av_packet)
{
    RK_U32 pkt_done = 0;
    RK_U32 pkt_eos  = 0;
    RK_U32 err_info = 0;
    MPP_RET ret = MPP_OK;
    MppCtx ctx  = data->ctx;
    MppApi *mpi = data->mpi;
    MppPacket packet = nullptr;
    MppFrame  frame  = nullptr;



    ret = mpp_packet_init(&packet, av_packet->data, av_packet->size);

    if(ret < 0)
    {
        return -1;
    }
    mpp_packet_set_pts(packet, av_packet->pts);


    //qDebug()<<"av_packet->data:"<data;
    do {
        RK_S32 times = 5;
        // send the packet first if packet is not done
        if (!pkt_done) {
            ret = mpi->decode_put_packet(ctx, packet);
            if (MPP_OK == ret)
                pkt_done = 1;
        }

        // then get all available frame and release
        do {
            RK_S32 get_frm = 0;
            RK_U32 frm_eos = 0;

try_again:
            ret = mpi->decode_get_frame(ctx, &frame);
            if (MPP_ERR_TIMEOUT == ret) {
                if (times > 0) {
                    times--;
                    mmsleep(2);
                    goto try_again;
                }
                mpp_err("decode_get_frame failed too much time\n");
            }

            //qDebug()<< "mpp_log" <<"get MPP_OK"<frm_grp, MPP_BUFFER_TYPE_ION);
                    if (ret) {
                        mpp_err("get mpp buffer group  failed ret %d\n", ret);
                        break;
                    }
                    mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);

                    mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, nullptr);
                } else {
                    err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);
                    if (err_info) {
                        qDebug("decoder_get_frame get err info:%d discard:%d.\n",
                               mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame));
                    }
                    data->frame_count++;
                    //qDebug("decode_get_frame get frame %d\n", data->frame_count);


                    if (!err_info){
                        //qDebug("no err_info");
                        //qDebug("frame:%p",frame);
                        MppBuffer buff = mpp_frame_get_buffer(frame);

                        if(dst_buf == nullptr)
                        {
                            reallyWidth = static_cast( mpp_frame_get_hor_stride(frame));
                            reallyHight = static_cast( mpp_frame_get_ver_stride(frame));

//                            //RK_U32 buf_size = mpp_frame_get_buf_size(frame);

                            qDebug() << "srcHight"<frm_grp) {
                size_t usage = mpp_buffer_group_usage(data->frm_grp);
                if (usage > data->max_usage)
                    data->max_usage = usage;
            }

            // if last packet is send but last frame is not found continue
            if (pkt_eos && pkt_done && !frm_eos) {
                mmsleep(10);
                continue;
            }

            if (frm_eos) {
                qDebug("mpp_log :found last frame\n");
                break;
            }

            if (data->frame_num > 0 && data->frame_count >= data->frame_num) {
                data->eos = 1;
                break;
            }

            if (get_frm)
                continue;
            break;
        } while (1);

        if (data->frame_num > 0 && data->frame_count >= data->frame_num) {
            data->eos = 1;
            qDebug("mpp_log_reach max frame number %d\n", data->frame_count);
            break;
        }

        if (pkt_done)
            break;

        /*
         * why sleep here:
         * mpi->decode_put_packet will failed when packet in internal queue is
         * full,waiting the package is consumed .Usually hardware decode one
         * frame which resolution is 1080p needs 2 ms,so here we sleep 3ms
         * * is enough.
         */
        mmsleep(3);
    } while (1);
    mpp_packet_deinit(&packet);

    return ret;
}

int MppDecode::convertdata(char *srcdata, char *dst_buf)
{
    // rga
    im_rect 		src_rect;
    im_rect 		dst_rect;
    rga_buffer_t 	src;
    rga_buffer_t 	dst;
    IM_STATUS 		STATUS;

    int ret = 0;

    memset(&src_rect, 0, sizeof(src_rect));
    memset(&dst_rect, 0, sizeof(dst_rect));
    memset(&src, 0, sizeof(src));
    memset(&dst, 0, sizeof(dst));


    //memset(dst_buf,0x00,srcWidth*srcHight*get_bpp_from_format(DST_FORMAT));

    src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);
    dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);


    if(src.width == 0 || dst.width == 0) {
        printf("%s, %s\n", __FUNCTION__, imStrError());
        return -1;
    }
    src.format = SRC_FORMAT;
    dst.format = DST_FORMAT;

    ret = imcheck(src, dst, src_rect, dst_rect);
    if (IM_STATUS_NOERROR != ret) {
        printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
        return -1;
    }
    STATUS = imcvtcolor(src, dst, src.format, dst.format);
    //qDebug("resizing .... %s\n", imStrError(STATUS));
    return 0;
}

int MppDecode::convertdata(char *srcdata, char *dst_buf,char *dstResize_buf)
{
    im_rect 		src_rect;
    im_rect 		dst_rect;
    rga_buffer_t 	src;
    rga_buffer_t 	dst;
    rga_buffer_t    dstCrop;

    IM_STATUS 		STATUS;

    int ret = 0;

    memset(&src_rect, 0, sizeof(src_rect));
    memset(&dst_rect, 0, sizeof(dst_rect));
    memset(&src, 0, sizeof(src));
    memset(&dst, 0, sizeof(dst));
     memset(&dstCrop, 0, sizeof(dstCrop));


    //memset(dst_buf,0x00,srcWidth*srcHight*get_bpp_from_format(DST_FORMAT));

    src = wrapbuffer_virtualaddr(srcdata, reallyWidth, reallyHight, SRC_FORMAT);
    //qDebug() <<""
    dst = wrapbuffer_virtualaddr(dst_buf, srcWidth, srcHight, DST_FORMAT);
    //dstCrop = wrapbuffer_virtualaddr(dstResize_buf, srcWidth, srcHight, DST_FORMAT);

    if(src.width == 0 || dst.width == 0) {
        printf("%s, %s\n", __FUNCTION__, imStrError());
        return -1;
    }
    src.format = SRC_FORMAT;
    dst.format = DST_FORMAT;
    //dstCrop.format = DST_FORMAT;
    src_rect.x      = 0;
    src_rect.y      = 0;
    src_rect.width  = srcWidth-256;
    src_rect.height = srcHight;


//    ret = imcheck(src, dst, src_rect, dst_rect);
//    if (IM_STATUS_NOERROR != ret) {
//        printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
//        return -1;
//    }
    STATUS = imcvtcolor(src, dst, src.format, dst.format);
    //qDebug("resizing .... %s\n", imStrError(STATUS));
    //STATUS = imcrop(dst,dstCrop,src_rect);
    //qDebug("resizing .... %s\n", imStrError(STATUS));
    return 0;
}

头文件如下

#ifndef MPPDECODE_H
#define MPPDECODE_H
#define MODULE_TAG "mpi_dec_test"

#include 

#include "utils.h"
#include "rk_mpi.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_env.h"
#include "mpp_time.h"
#include "mpp_common.h"
#include "mpp_frame.h"
#include "mpp_buffer_impl.h"
#include "mpp_frame_impl.h"
#include 
#include 
#include 
#include 
#include 
#include 
extern "C"
{
    #include 
}

#define SRC_FORMAT RK_FORMAT_YCbCr_420_SP

#define DST_FORMAT RK_FORMAT_RGB_888
//#define SRC_WIDTH  2592
//#define SRC_HEIGHT 1944
//#define DST_WIDTH  2592
//#define DST_HEIGHT 1944
#define MPI_DEC_STREAM_SIZE         (SZ_4K)
#define MPI_DEC_LOOP_COUNT          4
#define MAX_FILE_NAME_LENGTH        256
class MppDecode : public QObject
{
    Q_OBJECT
signals:
     void MySigSendMppImg(QImage img);
     void MySigSendMppImgSrc(QImage img);
public slots:
     void slotGetSendMppSrcImg();
public:
    void setWidthHight(int width,int hight);


    typedef struct
    {
        MppCtx          ctx;
        MppApi          *mpi;

        RK_U32          eos;

        char            *buf;
        RK_U32          quiet;

        MppBufferGroup  frm_grp;
        MppBufferGroup  pkt_grp;
        MppPacket       packet;
        size_t          packet_size;
        MppFrame        frame;

        FILE            *fp_input;
        RK_S32          frame_count;
        RK_S32          frame_num;
        size_t          max_usage;
    } MpiDecLoopData;

    typedef struct
    {
        char            file_input[MAX_FILE_NAME_LENGTH];
        char            file_output[MAX_FILE_NAME_LENGTH];
        MppCodingType   type;
        MppFrameFormat  format;
        RK_U32          width;
        RK_U32          height;
        RK_U32          debug;

        RK_U32          have_input;
        RK_U32          have_output;

        RK_U32          simple;
        RK_S32          timeout;
        RK_S32          frame_num;
        size_t          max_usage;
    } MpiDecTestCmd;


    size_t mpp_buffer_group_usage(MppBufferGroup group);


    int decode_simple(MpiDecLoopData *data, AVPacket* av_packet);
    int convertdata(char *srcdata,char * dst_buf);
    int convertdata(char *srcdata,char * dstsrc_buf,char *dst_buf);
    char* dst_buf = nullptr;
    //char* dstResize_buf = nullptr;
    //char* dstCrop = nullptr;
    int cout =0;

    int srcWidth;
    int srcHight;

    int initSrcHight;
    int initSrcWidth;
    bool srcImgSend;
    int reallyWidth;
    int reallyHight;

};

#endif // MPPDECODE_H

关于h265的在mpp解码的对齐问题,作者还有许多不明白之处,欢迎评论交流

你可能感兴趣的:(ffmpeg,qt,arm,linux)