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 上的视频解码器的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV4.7.0FFmpeg5.1 2080TI视频硬解码

ffmpeg用于将视频编码为H264编解码器格式

FFmpeg2-视频解码

ffmpeg文档12视频解码器

ffmpeg视频解码器

ffmpeg + cuda(cuvid) 硬解码+像素格式转换(cpu主导)实战