Cuda ffmpeg上的视频解码器 [英] Video decoder on 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屋!