Cuda ffmpeg上的视频解码器 [英] Video decoder on Cuda ffmpeg

查看:2203
本文介绍了Cuda ffmpeg上的视频解码器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



如何填充CUVIDPICPARAMSstruc ??我开始实现custum视频解码器,利用cuda HW解码器生成YUV帧为下一个编码。 ?
是否有可能?



我的算法是:



使用ffmpeg-dev libs avcodec,avformat ...



我的步骤:



1)打开输入文件:

  avformat_open_input(& ff_formatContext,in_filename,nullptr,nullptr); 

2)获取视频流属性:

  avformat_find_stream_info(ff_formatContext,nullptr); 

3)获取视频流:

  ff_video_stream = ff_formatContext-> streams [i]; 

4)获取CUDA设备并初始化:

  cuDeviceGet(& cu_device,0); 
CUcontext cu_vid_ctx;

5)Init视频CUDA解码器并设置创建参数:

  CUVIDDECODECREATEINFO * cu_decoder_info = new CUVIDDECODECREATEINFO; 
memset(cu_decoder_info,0,sizeof(CUVIDDECODECREATEINFO));
...
cuvidCreateDecoder(cu_video_decoder,cu_decoder_info);

6)将帧数据读入AVpacket

  av_read_frame(ff_formatContext,ff_packet); 

现在我需要解码CUDA视频解码器上的帧包,理论上是:

  cuvidDecodePicture(pDecoder,& picParams); 

但在我需要填写CUVIDPICPARAMS之前



CUVIDPICPARAMS picParams; // = new CUVIDPICPARAMS;
memset(& picParams,0,sizeof(CUVIDPICPARAMS));

 如何填充CUVIDPICPARAMS ??? 

typedef struct _CUVIDPICPARAMS
{
int PicWidthInMbs; // Coded Frame Size
int FrameHeightInMbs; // Coded Frame Height
int CurrPicIdx; //当前图片的输出索引
int field_pic_flag; // 0 = frame picture,1 = field picture
int bottom_field_flag; // 0 =顶场,1 =底场(如果field_pic_flag = 0,则忽略)
int second_field; //互补字段对的第二字段
//比特流数据
unsigned int nBitstreamDataLen; //比特流数据缓冲区中的字节数
const unsigned char * pBitstreamData; // Ptr到此图片的比特流数据(切片层)
unsigned int nNumSlices; //图片中的切片数量
const unsigned int * pSliceDataOffsets; // nNumSlices条目,包含位流数据缓冲区中每个切片的偏移
int ref_pic_flag; //这张图片是一个参考图片
int intra_pic_flag; //这个图片是完全帧内编码的
unsigned int保留[30]; //保留供将来使用
//编解码器特定的数据
union {
CUVIDMPEG2PICPARAMS mpeg2; //也用于MPEG-1
CUVIDH264PICPARAMS h264;
CUVIDVC1PICPARAMS vc1;
CUVIDMPEG4PICPARAMS mpeg4;
CUVIDJPEGPICPARAMS jpeg;
unsigned int CodecReserved [1024];
} CodecSpecific;
} CUVIDPICPARAMS;

typedef struct _CUVIDH264PICPARAMS
{
// SPS
int log2_max_frame_num_minus4;
int pic_order_cnt_type;
int log2_max_pic_order_cnt_lsb_minus4;
int delta_pic_order_always_zero_flag;
int frame_mbs_only_flag;
int direct_8x8_inference_flag;
int num_ref_frames; // NOTE:shall meet level 4.1 restrictions
unsigned char residual_colour_transform_flag;
unsigned char bit_depth_luma_minus8; //必须为0(仅支持8位)
unsigned char bit_depth_chroma_minus8; //必须为0(仅支持8位)
unsigned char qpprime_y_zero_transform_bypass_flag;
// PPS
int entropy_coding_mode_flag;
int pic_order_present_flag;
int num_ref_idx_l0_active_minus1;
int num_ref_idx_l1_active_minus1;
int weighted_pred_flag;
int weighted_bipred_idc;
int pic_init_qp_minus26;
int deblocking_filter_control_present_flag;
int redundant_pic_cnt_present_flag;
int transform_8x8_mode_flag;
int MbaffFrameFlag;
int constrained_intra_pred_flag;
int chroma_qp_index_offset;
int second_chroma_qp_index_offset;
int ref_pic_flag;
int frame_num;
int CurrFieldOrderCnt [2];
// DPB
CUVIDH264DPBENTRY dpb [16]; // DPB中的参考帧列表
//量化矩阵(光栅顺序)
unsigned char WeightScale4x4 [6] [16];
unsigned char WeightScale8x8 [2] [64];
// FMO / ASO
unsigned char fmo_aso_enable;
unsigned char num_slice_groups_minus1;
unsigned char slice_group_map_type;
signed char pic_init_qs_minus26;
unsigned int slice_group_change_rate_minus1;
union
{
unsigned long long slice_group_map_addr;
const unsigned char * pMb2SliceGroupMap;
} fmo;
unsigned int保留[12];
// SVC / MVC
union
{
CUVIDH264MVCEXT mvcext;
CUVIDH264SVCEXT svcext;
};
} CUVIDH264PICPARAMS;


解决方案

这是 CUvideoparser 对象。您通过 cuvidParseVideoData 逐帧提交数据流,然后使用 CUVIDPICPARAMS 调用您的数据流解码器,当它检测到它有一个完整的帧准备好。



所有这些和更多的很好说明了D3D9解码示例,可用此处。我建议详细研究它,因为没有太多的文档这个API以外的。


I starting to implement custum video decoder that utilize cuda HW decoder to generate YUV frame for next to encode it.

How can I fill "CUVIDPICPARAMS" struc ??? Is it possible?

My algorithm are:

For get video stream packet I'm use ffmpeg-dev libs avcodec, avformat...

My steps:

1) Open input file:

avformat_open_input(&ff_formatContext,in_filename,nullptr,nullptr);

2) Get video stream property's:

avformat_find_stream_info(ff_formatContext,nullptr);

3) Get video stream:

ff_video_stream=ff_formatContext->streams[i];

4) Get CUDA device and init it:

cuDeviceGet(&cu_device,0);
CUcontext cu_vid_ctx;

5) Init video CUDA decoder and set create params:

CUVIDDECODECREATEINFO *cu_decoder_info=new CUVIDDECODECREATEINFO;
memset(cu_decoder_info,0,sizeof(CUVIDDECODECREATEINFO));
...
cuvidCreateDecoder(cu_video_decoder,cu_decoder_info);

6)Read frame data to AVpacket

av_read_frame(ff_formatContext,ff_packet);

AND NOW I NEED decode frame packet on CUDA video decoder, in theoretical are:

cuvidDecodePicture(pDecoder,&picParams);

BUT before I need fill CUVIDPICPARAMS

CUVIDPICPARAMS picParams;//=new CUVIDPICPARAMS; memset(&picParams, 0, sizeof(CUVIDPICPARAMS));

HOW CAN I FILL "CUVIDPICPARAMS" struc ???

typedef struct _CUVIDPICPARAMS
{
    int PicWidthInMbs;      // Coded Frame Size
    int FrameHeightInMbs;   // Coded Frame Height
    int CurrPicIdx;         // Output index of the current picture
    int field_pic_flag;     // 0=frame picture, 1=field picture
    int bottom_field_flag;  // 0=top field, 1=bottom field (ignored if field_pic_flag=0)
    int second_field;       // Second field of a complementary field pair
    // Bitstream data
    unsigned int nBitstreamDataLen;        // Number of bytes in bitstream data buffer
    const unsigned char *pBitstreamData;   // Ptr to bitstream data for this picture (slice-layer)
    unsigned int nNumSlices;               // Number of slices in this picture
    const unsigned int *pSliceDataOffsets; // nNumSlices entries, contains offset of each slice within the bitstream data buffer
    int ref_pic_flag;       // This picture is a reference picture
    int intra_pic_flag;     // This picture is entirely intra coded
    unsigned int Reserved[30];             // Reserved for future use
    // Codec-specific data
    union {
        CUVIDMPEG2PICPARAMS mpeg2;          // Also used for MPEG-1
        CUVIDH264PICPARAMS h264;
        CUVIDVC1PICPARAMS vc1;
        CUVIDMPEG4PICPARAMS mpeg4;
        CUVIDJPEGPICPARAMS jpeg;
        unsigned int CodecReserved[1024];
    } CodecSpecific;
} CUVIDPICPARAMS;

typedef struct _CUVIDH264PICPARAMS
{
    // SPS
    int log2_max_frame_num_minus4;
    int pic_order_cnt_type;
    int log2_max_pic_order_cnt_lsb_minus4;
    int delta_pic_order_always_zero_flag;
    int frame_mbs_only_flag;
    int direct_8x8_inference_flag;
    int num_ref_frames;             // NOTE: shall meet level 4.1 restrictions
    unsigned char residual_colour_transform_flag;
    unsigned char bit_depth_luma_minus8;    // Must be 0 (only 8-bit supported)
    unsigned char bit_depth_chroma_minus8;  // Must be 0 (only 8-bit supported)
    unsigned char qpprime_y_zero_transform_bypass_flag;
    // PPS
    int entropy_coding_mode_flag;
    int pic_order_present_flag;
    int num_ref_idx_l0_active_minus1;
    int num_ref_idx_l1_active_minus1;
    int weighted_pred_flag;
    int weighted_bipred_idc;
    int pic_init_qp_minus26;
    int deblocking_filter_control_present_flag;
    int redundant_pic_cnt_present_flag;
    int transform_8x8_mode_flag;
    int MbaffFrameFlag;
    int constrained_intra_pred_flag;
    int chroma_qp_index_offset;
    int second_chroma_qp_index_offset;
    int ref_pic_flag;
    int frame_num;
    int CurrFieldOrderCnt[2];
    // DPB
    CUVIDH264DPBENTRY dpb[16];          // List of reference frames within the DPB
    // Quantization Matrices (raster-order)
    unsigned char WeightScale4x4[6][16];
    unsigned char WeightScale8x8[2][64];
    // FMO/ASO
    unsigned char fmo_aso_enable;
    unsigned char num_slice_groups_minus1;
    unsigned char slice_group_map_type;
    signed char pic_init_qs_minus26;
    unsigned int slice_group_change_rate_minus1;
    union
    {
        unsigned long long slice_group_map_addr;
        const unsigned char *pMb2SliceGroupMap;
    } fmo;
    unsigned int  Reserved[12];
    // SVC/MVC
    union
    {
        CUVIDH264MVCEXT mvcext;
        CUVIDH264SVCEXT svcext;
    };
} CUVIDH264PICPARAMS;

解决方案

This is the purpose of the CUvideoparser object. You feed it the data stream frame by frame through cuvidParseVideoData, and it calls you back with CUVIDPICPARAMS ready to pass to the decoder when it detects it has a complete frame ready.

All this and more is very well illustrated in the D3D9 decode sample, available here. I suggest studying it in detail because there's not much documentation for this API outside of it.

这篇关于Cuda ffmpeg上的视频解码器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆