Cuda ffmpeg 上的视频解码器
Posted
技术标签:
【中文标题】Cuda ffmpeg 上的视频解码器【英文标题】:Video decoder on Cuda ffmpeg 【发布时间】:2013-04-19 20:28:34 【问题描述】:我开始实现 custum 视频解码器,该解码器利用 cuda HW 解码器生成 YUV 帧以供下一步对其进行编码。
如何填写“CUVIDPICPARAMS”结构? 有可能吗?
我的算法是:
为了获取视频流数据包,我使用 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) 初始化视频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;//=新的 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;
【问题讨论】:
Decode video with CUDA nccuvid and ffmpeg的可能重复 你已经问过这个问题了。请不要再问了。 你看过NVIDIA视频解码samples吗? 是的,我使用了 CUDA SDK 中的示例。但它使用专有的视频文件解析器。 【参考方案1】:这是CUvideoparser
对象的用途。你通过cuvidParseVideoData
逐帧向它提供数据流,当它检测到它已经准备好完整的帧时,它会用CUVIDPICPARAMS
准备好传递给解码器。
所有这些以及更多内容都在 D3D9 解码示例中得到了很好的说明,here 可用。我建议详细研究它,因为除此之外没有太多关于此 API 的文档。
【讨论】:
是的,我知道并使用 D3D9 解码示例,但我不使用 CUvideoparser!我使用 ffmpeg -> AVpacket 从视频源获取流数据包数据。所以我需要正确填充 CUVIDPICPARAMS。我如何知道 ffmpeg 的编解码器规范以在 CUVIDPICPARAMS struc 中解析它? 我对 FFmpeg 不太熟悉,但我假设您可以简单地将 AVpacket 的数据传递给 CUvideoparser,它会为您填充 CUVIDPICPARAMS。你有什么理由不使用它吗? CUvideoparser 没有为我读取 mkv 视频文件,不同的文件 - 不同的容器 但是如果我使用 CUvideoparser 应用程序会在 cuvidParseVideoData(pParser,&cu_packet) 步骤上崩溃。 MKV 与 CUvideoparser 无关,它是一个容器。您提供给 CUvideoparser 的是给定编码(即 H264、MPEG2 等)的视频帧,它们来自哪里并不重要。以上是关于Cuda ffmpeg 上的视频解码器的主要内容,如果未能解决你的问题,请参考以下文章