2017-07-26 46 views
0

env:ubuntu 16.04 64 bit; ffmpeg 3.3.2 build whih cuda cuvid libnpp ...
使用ffmpeg cmd:ffmpeg -vsync 0 -c:v h264_cuvid -i test.264 -f rawvideo test.yuv工作正常,生成的yuv文件没问题。
当我通过我的代码使用解码此264文件“h264_cuvid”解码器,什么问题发生,这是我的代码:ffmpeg解码h264时为什么没有AVFrame-> data [2]数据使用“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->数据[2] codeblocks watching window

任何建议没有数据?谢谢!

+0

什么是所产生的像素格式由解码器?它可能不是平面的。 – szatmary

+0

是的,解码后使用的像素格式h264_cuvid是AV_PIX_FMT_NV12而不是AV_PIX_FMT_YUV420P –

回答

0

“H264” 解码器的帧PIX格式是AV_PIX_FMT_YUV420P
BUT “h264_cuvid” 解码器的帧PIX格式是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); 
      } 

工作正常