NVCodec 解码案例

下面是nvcodec解码案例,可以参考:

#include "nvcuvid.h"
#include <cuda_runtime.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "utils/demuxer.h"

#define START_CODE_ANNEXB 0x00000001
#define START_CODE_SIZE 4

typedef struct packet_t {
   
   
    uint8_t* data;
    int      size;
    int64_t  pts;
} packet;

typedef struct nvcuvid_test_ctx_t {
   
   
    CUvideodecoder    cudecoder;
    CUvideoparser     cuparser;
    CUVIDPARSERPARAMS cuparseinfo;
    CUVIDDECODECAPS   caps8;
    CUVIDDECODECAPS   caps10;
    CUVIDDECODECAPS   caps12;
    CUcontext         cu_ctx;
    CUvideoctxlock    cu_ctx_lock;

    FFmpegDemuxer* demuxer;

    uint64_t    frame_count;
    const char* in_file_name;
    void*       host_data;
    void*       tmp_data;
    int         tmp_data_size;

    int                      coded_width;
    int                      coded_height;
    int                      out_width;
    int                      out_height;
    cudaVideoCodec           codec_type;
    int                      bit_depth_minus8;  // 0-8bit, 2-10bit, 4-12bit
    int                      decode_surface;
    unsigned char            progressive_sequence;
    unsigned int             bit_rate;
    cudaVideoSurfaceFormat   out_pix_fmt;
    cudaVideoChromaFormat    in_pix_fmt;
    cudaVideoDeinterlaceMode deinter_lace_mode;

    struct {
   
   
        int left;
        int top;
        int right;
        int bottom;
    } crop;

    struct {
   
   
        int width;
        int height;
    } resize;

    struct {
   
   
        unsigned int num;
        unsigned int den;
    } framerate;
    int   eos;
    int   nb_surfaces;
    int   internal_error;
    int   need_resize;
    int   decoder_flushing;
    int   in_file_size;
    int   read_size;
    FILE* in_file;
    FILE* out_file;
} nvcuvid_test_ctx;

static void print_caps(CUVIDDECODECAPS* caps) {
   
   
    printf("eCodecType: %d\n", caps->eCodecType);
    printf("eChromaFormat: %d\n", caps->eChromaFormat);
    printf("nBitDepthMinus8: %d\n", caps->nBitDepthMinus8);
    printf("bIsSupported: %d\n", caps->bIsSupported);
    printf("nNumNVDECs: %d\n", caps->nNumNVDECs);
    printf("nMaxWidth: %d\n", caps->nMaxWidth);
    printf("nMaxHeight: %d\n", caps->nMaxHeight);
    printf("nMaxMBCount: %d\n", caps->nMaxMBCount);
    printf("nMinWidth: %d\n", caps->nMinWidth);
    printf("nMinHeight: %d\n", caps->nMinHeight);
    printf("nMaxMBCount: %d\n", caps->nMaxMBCount);
}

static int handle_video_sequence(void* opaque, CUVIDEOFORMAT* format) {
   
   
    nvcuvid_test_ctx*           ctx    = NULL;
    CUVIDDECODECAPS*            caps   = NULL;
    CUVIDDECODECREATEINFO       cuinfo = {
   
   0};
    CUVIDRECONFIGUREDECODERINFO cf     = {
   
   0};

    ctx                 = (nvcuvid_test_ctx*)opaque;
    ctx->internal_error = 0;

    // getcaps
    caps                = &ctx->caps8;
    caps->eCodecType    = format->codec;
    caps->eChromaFormat = format->chroma_format;
    caps->nBitDepthMinus8 =
        format->bit_depth_luma_minus8;  // 0-8bit, 2-10bit, 4-12bit
    // cuCtxPushCurrent(ctx->cu_ctx);
    ctx->internal_error = cuvidGetDecoderCaps(caps);
    if (ctx->internal_error != 0) {
   
   
        printf("cuvidGetDecoderCaps failed,ret=%d\n", ctx->internal_error);
        goto err;
    }
    // cuCtxPopCurrent(NULL);

    print_caps(caps);
    if (!caps->bIsSupported) {
   
   
        printf("Codec not supported on this GPU\n");
        goto err;
    }

    // check if need to reinit decoder
    ctx->bit_rate             = format->bitrate;
    ctx->codec_type           = format->codec;
    ctx->coded_width          = format->coded_width;
    ctx->coded_height         = format->coded_height;
    ctx->in_pix_fmt           = format->chroma_format;
    ctx->framerate.num        = format->frame_rate.numerator;
    ctx->framerate.den        = format->frame_rate.denominator;
    ctx->bit_depth_minus8     = format->bit_depth_luma_minus8;
    ctx->progressive_sequence = format->progressive_sequence;
    ctx->decode_surface       = format->min_num_decode_surfaces;
    printf(
        "bitrate:%d,codec:%d,coded_width:%d,coded_height:%d,chroma_format:%d,"
        "frame_rate:%d/%d,bit_depth_luma_minus8:%d,progressive_sequence:%d,"
        "min_num_decode_surfaces:%d\n",
        ctx->bit_rate, ctx->codec_type, ctx->coded_width, ctx->coded_height,
        ctx->in_pix_fmt, ctx->framerate.num, ctx->framerate.den,
        ctx->bit_depth_minus8, ctx->progressive_sequence, ctx->decode_surface);

    // do some checks
    // a.check max resolution supported
    // b.check max mb count supported

    // if the decoder is already created, reconfigure it
    if (ctx->cudecoder) {
   
   
        printf("Re-initializing decoder\n");
        cf.ulWidth        = ctx->coded_width;
        cf.ulHeight       = ctx->coded_height;
        cf.ulTargetWidth  = ctx->out_width;
        cf.ulTargetHeight = ctx->out_height;

        cf.display_area.left   = format->display_area.left + ctx->crop.left;
        cf.display_area.top    = format->display_area.top + ctx->crop.top;
        cf.display_area.right  = format->display_area.right - ctx->crop.right;
        cf.display_area.bottom = format->display_area.bottom - ctx->crop.bottom;
        cf.ulNumDecodeSurfaces = ctx->decode_surface;

        // reconfigure decoder
        ctx->internal_error = cuvidReconfigureDecoder(ctx->cudecoder, &cf);
        if (ctx->internal_error != 0) {
   
   
            printf("cuvidReconfigureDecoder failed\n");
            goto err;
        }
        printf("Re-initialized decoder\n");
    }

    // for the first time, create decoder
    memset(&cuinfo, 0, sizeof(CUVIDDECODECREATEINFO));
    cuinfo.CodecType      = (cudaVideoCodec)ctx->codec_type;
    cuinfo.ChromaFormat   = ctx->in_pix_fmt;
    cuinfo.OutputFormat   = ctx->out_pix_fmt;
    cuinfo.bitDepthMinus8 = ctx->bit_depth_minus8;
    if (ctx->progressive_sequence)
        cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
    else
        cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Adaptive;
    cuinfo.ulNumOutputSurfaces = 2;
    cuinfo.ulCreationFlags     = cudaVideoCreate_PreferCUVID;
    cuinfo.ulNumDecodeSurfaces = ctx->decode_surface;
    // cuinfo.vidLock             = ctx->cu_ctx_lock;
    cuinfo.ulWidth  = ctx->coded_width;
    cuinfo.ulHeight = ctx->coded_height;
    printf(
        "codec:%d,chroma_format:%d,width:%d,height:%d,output_format:%d,"
        "num_decode_surfaces:%d,num_output_surfaces:%d,creation_flags:%d,"
        "vidLock:%p,bitDepthMinus8:%d\n",
        cuinfo.CodecType, cuinfo.ChromaFormat, cuinfo.ulWidth, cuinfo.ulHeight,
        cuinfo.OutputFormat, cuinfo.ulNumDecodeSurfaces,
        cuinfo.ulNumOutputSurfaces, cuinfo.ulCreationFlags, cuinfo.vidLock,
        cuinfo.bitDepthMinus8);

    printf("createdecoder,ulNumDecodeSurfaces:%d\n",
           cuinfo.ulNumDecodeSurfaces);

    // apply cropping
    // cuinfo.display_area.left   = format->display_area.left + ctx->crop.left;
    // cuinfo.display_area.top    = format->display_area.top + ctx->crop.top;
    // cuinfo.display_area.right  = format->display_area.right -
    // ctx->crop.right; cuinfo.display_area.bottom = format->display_area.bottom
    // - ctx->crop.bottom;
    // printf("display_area:left:%d,top:%d,right:%d,bottom:%d\n",
    //        cuinfo.display_area.left, cuinfo.display_area.top,
    //        cuinfo.display_area.right, cuinfo.display_area.bottom);

    ctx->out_width = ctx->coded_width;    // cuinfo.display_area.right -
                                          // cuinfo.display_area.left;
    ctx->out_height = ctx->coded_height;  // cuinfo.display_area.bottom -
                                          // cuinfo.display_area.hecoded_height
    printf("out_width:%d,out_height:%d\n", ctx->out_width, ctx->out_height);

    // target width/height need to be multiples of two align to 2
    cuinfo.ulTargetWidth  = ctx->out_width;
    cuinfo.ulTargetHeight = ctx->out_height;
    // // aspect ratio conversion, 1:1, depends on scaled resolution
    // cuinfo.target_rect.left   = 0;
    // cuinfo.target_rect.top    = 0;
    // cuinfo.target_rect.right  = cuinfo.ulTargetWidth;
    // cuinfo.target_rect.bottom = cuinfo.ulTargetHeight;
    // printf("target_rect:left:%d,top:%d,right:%d,bottom:%d\n",
    //        cuinfo.target_rect.left, cuinfo.target_rect.top,
    //        cuinfo.target_rect.right, cuinfo.target_rect.bottom);
    // max resolution
    cuinfo.ulMaxWidth  = cuinfo.ulTargetWidth;
    cuinfo.ulMaxHeight = cuinfo.ulTargetHeight;
    printf("max resolution:width:%d,height:%d\n", cuinfo.ulMaxWidth,
           cuinfo.ulMaxHeight);

    // cuCtxPushCurrent(ctx->cu_ctx);
    ctx->internal_error = cuvidCreateDecoder(&ctx->cudecoder, &cuinfo);
    if (ctx->internal_error < 0) {
   
   
        printf("cuvidCreateDecoder failed\n");
        goto err;
    }
    // cuCtxPopCurrent(NULL);
    printf("cuvidCreateDecoder success, ret:%d\n", ctx->internal_error);

err:

    return (0 == ctx->internal_error);
}

static int handle_picture_display(void* opaque, CUVIDPARSERDISPINFO* dispinfo) {
   
   
    int                  ret       = 0;
    int                  bpp       = 1;
    void*                dst_frame = NULL;
    int                  dst_size  = 0;
    nvcuvid_test_ctx*    ctx       = NULL;
    CUVIDGETDECODESTATUS s;
    printf("<<<handle_picture_display\n");

    ctx                 = (nvcuvid_test_ctx*)opaque;
    ctx->internal_error = 0;

    if (ctx->bit_depth_minus8 > 0) {
   
   
        bpp = 2;
    }

    if (!dispinfo) {
   
   
        printf("dispinfo is null\n");
        return 0;
    }

    CUVIDPROCPARAMS map_info   = {
   
   0};
    map_info.progressive_frame = dispinfo->progressive_frame;
    map_info.second_field      = dispinfo->repeat_first_field + 1;
    map_info.top_field_first   = dispinfo->top_field_first;
    map_info.unpaired_field    = dispinfo->repeat_first_field < 0;
    map_info.output_stream     = NULL;

    CUdeviceptr  map_frame = 0;
    unsigned int map_pitch = 0;  // for 8 bit pitch=1, for 10/12 bit pitch=2
    ret = cuvidMapVideoFrame(ctx->cudecoder, dispinfo->picture_index,
                             &map_frame, &map_pitch
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值