当ffmpeg使用" h264_cuvid"解码h264时,为什么没有AVFrame-> data [2]数据?

时间:2017-07-26 08:10:06

标签: ffmpeg h.264 cuvid

env :ubuntu 16.04 64 bit; ffmpeg 3.3.2建立cuda cuvid libnpp ...
使用ffmpeg cmd:ffmpeg -vsync 0 -c:v h264_cuvid -i test.264 -f rawvideo test.yuv工作正常,生成的yuv文件没问题 但是当我通过我的代码解码这个264文件时,请使用' h264_cuvid'解码器,出现问题,这是我的代码:

#include <stdio.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#ifdef __cplusplus
};
#endif
#endif


//test different codec
#define TEST_H264  1
#define TEST_HEVC  0

int main(int argc, char* argv[])
{
    AVCodec *pCodec;
    AVCodecContext *pCodecCtx= NULL;
    AVCodecParserContext *pCodecParserCtx=NULL;

    FILE *fp_in;
    FILE *fp_out;
    AVFrame *pFrame;

    const int in_buffer_size=4096;
    unsigned char in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE]= {0};
    unsigned char *cur_ptr;
    int cur_size;
    AVPacket packet;
    int ret, got_picture;


#if TEST_HEVC
    enum AVCodecID codec_id=AV_CODEC_ID_HEVC;
    char filepath_in[]="bigbuckbunny_480x272.hevc";
#elif TEST_H264
    AVCodecID codec_id=AV_CODEC_ID_H264;
    char filepath_in[]="2_60_265to264.264";
#else
    AVCodecID codec_id=AV_CODEC_ID_MPEG2VIDEO;
    char filepath_in[]="bigbuckbunny_480x272.m2v";
#endif

    char filepath_out[]="mainSend.yuv";
    int first_time=1;


    //av_log_set_level(AV_LOG_DEBUG);

    avcodec_register_all();

//    pCodec = avcodec_find_decoder(codec_id);
    pCodec = avcodec_find_decoder_by_name("h264_cuvid");
    if (!pCodec)
    {
        printf("Codec not found\n");
        return -1;
    }
    pCodecCtx = avcodec_alloc_context3(pCodec);
    if (!pCodecCtx)
    {
        printf("Could not allocate video codec context\n");
        return -1;
    }

    pCodecParserCtx=av_parser_init(pCodec->id);
    if (!pCodecParserCtx)
    {
        printf("Could not allocate video parser context\n");
        return -1;
    }

    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("Could not open codec\n");
        return -1;
    }
    //Input File
    fp_in = fopen(filepath_in, "rb");
    if (!fp_in)
    {
        printf("Could not open input stream\n");
        return -1;
    }
    //Output File
    fp_out = fopen(filepath_out, "wb");
    if (!fp_out)
    {
        printf("Could not open output YUV file\n");
        return -1;
    }

    pFrame = av_frame_alloc();
    av_init_packet(&packet);

    while (1)
    {

        cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
        if (cur_size == 0)
            break;
        cur_ptr=in_buffer;

        while (cur_size>0)
        {

            int len = av_parser_parse2(
                          pCodecParserCtx, pCodecCtx,
                          &packet.data, &packet.size,
                          cur_ptr, cur_size,
                          AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);

            cur_ptr += len;
            cur_size -= len;

            if(packet.size==0)
                continue;

            //Some Info from AVCodecParserContext
            printf("[Packet]Size:%6d\t",packet.size);
            switch(pCodecParserCtx->pict_type)
            {
            case AV_PICTURE_TYPE_I:
                printf("Type:I\tNumber:%4d\n",pCodecParserCtx->output_picture_number);
                break;
            case AV_PICTURE_TYPE_P:
                printf("Type:P\t");
                break;
            case AV_PICTURE_TYPE_B:
                printf("Type:B\t");
                break;
            default:
                printf("Type:Other\t");
                break;
            }
            printf("Number:%4d\n",pCodecParserCtx->output_picture_number);
            AVFrame* myFrame = av_frame_alloc();
            ret = avcodec_decode_video2(pCodecCtx, myFrame, &got_picture, &packet);
            if (ret < 0)
            {
                printf("Decode Error.\n");
                return ret;
            }
            if (got_picture)
            {
                if(first_time)
                {
                    printf("\nCodec Full Name:%s\n",pCodecCtx->codec->long_name);
                    printf("width:%d\nheight:%d\n\n",pCodecCtx->width,pCodecCtx->height);
                    first_time=0;
                }
                //Y, U, V
                for(int i=0; i<myFrame->height; i++)
                {
                    fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
                }
                for(int i=0; i<myFrame->height/2; i++)
                {
                    fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width/2,fp_out);
                }
                for(int i=0; i<myFrame->height/2; i++)
                {
                    fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out);
                }
//                printf("pframe's width height %d %d\t key frame %d\n",myFrame->width,myFrame->height,myFrame->key_frame);
                printf("Succeed to decode 1 frame!\n");
                av_frame_free(&myFrame);
            }
        }

    }

    fclose(fp_in);
    fclose(fp_out);


    av_parser_close(pCodecParserCtx);

    av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    av_free(pCodecCtx);

    return 0;
}

在此演示代码中,我通过vcodec_find_decoder_by_name("h264_cuvid");调用h264_cuvid 但代码在fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out);发生崩溃 因此,在使用代码块进行调试后,我发现myFrame-&gt; data [2] codeblocks watching window

中没有数据

有什么建议吗?谢谢!

1 个答案:

答案 0 :(得分:0)

&#34; H264&#34;解码器的帧像素格式为AV_PIX_FMT_YUV420P
但&#34; h264_cuvid&#34;解码器的帧像素格式是AV_PIX_FMT_NV12
所以,编辑代码

            for(int i=0; i<myFrame->height; i++)
            {
                fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
            }
            for(int i=0; i<myFrame->height/2; i++)
            {
                fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width,fp_out);
            }

工作正常