ffmpeg 源代码简单分析 : avcodec_decode_video2()

此前写了好几篇ffmpeg源代码分析文章,列表如下:

图解FFMPEG打开媒体的函数avformat_open_input
ffmpeg 源代码简单分析 : av_register_all()
ffmpeg 源代码简单分析 : avcodec_register_all()
ffmpeg 源代码简单分析 : av_read_frame()
ffmpeg 源代码简单分析 : avcodec_decode_video2()

============================


ffmpeg中的avcodec_decode_video2()的作用是解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。


查看源代码之后发现,这个函数竟然十分的简单,源代码如下:

  1. int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,  
  2.                          int *got_picture_ptr,  
  3.                          const AVPacket *avpkt)  
  4. {  
  5.     int ret;  
  6.     // copy to ensure we do not change avpkt  
  7.     AVPacket tmp = *avpkt;  
  8.   
  9.     *got_picture_ptr= 0;  
  10.     if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))  
  11.         return -1;  
  12.   
  13.     if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){  
  14.         int did_split = av_packet_split_side_data(&tmp);  
  15.         apply_param_change(avctx, &tmp);  
  16.         avctx->pkt = &tmp;  
  17.         if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)  
  18.              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,  
  19.                                           &tmp);  
  20.         else {  
  21.             ret = avctx->codec->decode(avctx, picture, got_picture_ptr,  
  22.                               &tmp);  
  23.             picture->pkt_dts= avpkt->dts;  
  24.   
  25.             if(!avctx->has_b_frames){  
  26.             picture->pkt_pos= avpkt->pos;  
  27.             }  
  28.             //FIXME these should be under if(!avctx->has_b_frames)  
  29.             if (!picture->sample_aspect_ratio.num)  
  30.                 picture->sample_aspect_ratio = avctx->sample_aspect_ratio;  
  31.             if (!picture->width)  
  32.                 picture->width = avctx->width;  
  33.             if (!picture->height)  
  34.                 picture->height = avctx->height;  
  35.             if (picture->format == PIX_FMT_NONE)  
  36.                 picture->format = avctx->pix_fmt;  
  37.         }  
  38.   
  39.         emms_c(); //needed to avoid an emms_c() call before every return;  
  40.   
  41.         avctx->pkt = NULL;  
  42.         if (did_split)  
  43.             ff_packet_free_side_data(&tmp);  
  44.   
  45.         if (*got_picture_ptr){  
  46.             avctx->frame_number++;  
  47.             picture->best_effort_timestamp = guess_correct_pts(avctx,  
  48.                                                             picture->pkt_pts,  
  49.                                                             picture->pkt_dts);  
  50.         }  
  51.     }else  
  52.         ret= 0;  
  53.   
  54.     return ret;  
  55. }  

从代码中可以看出,通过ret = avctx->codec->decode(avctx, picture, got_picture_ptr,&tmp)这句代码,调用了相应解码器的decode()函数,完成了解码操作。

展开阅读全文

ffmpeg 工程avcodec_decode_video2() 解码fail

09-16

[size=14px]初学ffmpeg, 写个demon. 想法是用ffmpeg解码, 然后讲一帧图像转换为RGB24, 保存为bmp格式的图片。rnrn遇到的问题:rnavcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr,const AVPacket *avpkt) 调用失败。got_picture_ptr 为0.rnrn贴下关键代码,请大家指教[/size]rn[code=c]int main(int argc, char *argv[])rnrnrn int err;rn int i, j;rn int byte_cnt;rn int got_frame = 0;rn unsigned int video_stream = -1;rn unsigned char *buffer;rn char path[256];rn unsigned int index = 0;rnrnrn rn AVFormatContext *pFormatCtx = NULL;rnrn AVCodecContext *pCodecCtx = NULL;rnrn AVFrame *pFrame = NULL;rnrn AVFrame *pFrameRgb = NULL;rnrn AVCodec *pCodec = NULL; rnrn AVPacket packet = 0, out_pkt; rnrn AVCodecParserContext *pCodecParserCtx = NULL;rnrn struct SwsContext *pSwsCtx = NULL; rnrn av_log_set_level(AV_LOG_DEBUG);rnrn if (argc != 2) rn av_info_log("argument number err!\n");rn return -1;rn rnrn // register all format of video file, and codecrn av_info_log("av register!\n");rn av_register_all();rnrn // open video file, get head info from filern av_info_log("open input media file!\n");rn err = avformat_open_input(&pFormatCtx, argv[1], NULL, NULL);rn if (err<0) rn av_err_log("avformat_open_input open %s fail, err=%d\n",argv[1], err);rn return -1;rn rnrn // get stream info(AVFormatContext)rn av_info_log("get stream info!\n");rn err = avformat_find_stream_info(pFormatCtx, NULL);rn if (err<0) rn av_err_log("can not find codec parameter!\n");rn goto err1; rn rnrn // Dump information about file onto standard errorrn av_dump_format(pFormatCtx, 0, argv[1], 0);rnrn av_info_log("nb_streams = %d\n", pFormatCtx->nb_streams);rnrn // get video streamrn for (i=0; inb_streams; i++) rn if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) rn video_stream = i;rn break;rn rnrn rnrn if (video_stream == -1) rn av_err_log("not find video stream!\n");rn goto err1; rn rnrn // get AVCodecContext(codec info)rn pCodecCtx = pFormatCtx->streams[video_stream]->codec;rnrn // get AVCodec(get codec)rn pCodec = avcodec_find_decoder(pCodecCtx->codec_id);rn if (!pCodec) rn av_err_log("%s codec not support!\n", avcodec_get_name(pCodecCtx->codec_id));rn goto err1; rn rnrn av_info_log("find video decoder sucess! name=\"%s\",id=%d\n", avcodec_get_name(pCodecCtx->codec_id), pCodecCtx->codec_id);rnrn // open codecrn err = avcodec_open2(pCodecCtx, pCodec, NULL); rn if (err < 0) rn av_err_log("open %s(id=%d) codec fail!\n", avcodec_get_name(pCodecCtx->codec_id), pCodecCtx->codec_id);rn goto err1;rn rn av_info_log("open video codec sucess!\n");rnrn rn //pFrame = avcodec_alloc_frame(); rn //if (!pFrame) rn // printf("alloc frame faild! at %d\n", __LINE__);rn // goto err1;rn // rnrn pFrame = av_frame_alloc(); rn if (!pFrame) rn av_err_log("alloc frame fail at %d\n", __LINE__);rn goto err1; rn rnrn pFrameRgb = av_frame_alloc();rn if (!pFrameRgb) rn av_err_log("alloc frame fail at %d\n", __LINE__);rn goto err2;rn rnrn // caculate picture sizern byte_cnt = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);rnrn av_info_log("a frame(RGB24) image size is %d\n", byte_cnt);rnrn // alloc a size memrry of picturern buffer = (unsigned char *)av_malloc(byte_cnt * sizeof(unsigned char));rn if (!buffer) rn av_err_log("alloc frame fail at %d\n", __LINE__);rn goto err2;rn rnrn avpicture_fill((AVPicture *)pFrameRgb, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);rn //av_info_log("avpicture fill!\n");rn rn // init AVCodecParsetContext structrn pCodecParserCtx = av_parser_init(pCodecCtx->codec_id);rnrn rn do rnrn unsigned char *p_out_buf = NULL, *p_in_buf = NULL;rn unsigned int in_size = 0, out_size = 0, length = 0;rnrnrn //av_init_packet(&packet);rn av_free_packet(&packet);rnrn if (av_read_frame(pFormatCtx, &packet)<0) rn av_err_log("av_read_frame fail!\n");rn break;rn rnrn p_in_buf = packet.data;rn in_size = packet.size;rn p_out_buf = NULL;rn out_size = 0;rn rn do rn length = av_parser_parse2(pCodecParserCtx, pCodecCtx->codec,rn &p_out_buf, &out_size, rn p_in_buf, in_size,rn AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);rn rn if (p_out_buf && (out_size!=0)) rn av_info_log("av_paraser_parse2 seperate a frame as a packet: size=%dK(%dByte)\n", out_size/1024, out_size);rn rnrn av_info_log("p_out_buf=0x%x, out_size=%d, length=%d\n", p_out_buf, out_size, length);rnrn if (length <= 0) rn av_info_log("av_parser_parse2 return <=0, continue!\n");rn continue;rnrn else rn av_init_packet(&out_pkt);rn out_pkt.data = p_out_buf;rn out_pkt.size = out_size;rn p_in_buf += length;rn in_size -= length;rnrn rnrn if (pFormatCtx->streams[packet.stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) rn err = avcodec_decode_video2(pCodecCtx, pFrame, &got_frame, &out_pkt);rn if (err < 0) rn av_err_log("video decode fail!\n");rn goto err3;rn rnrn if (got_frame) rn //create SW scale contextrn av_info_log("decode a frame finished!\n");rn av_info_log("the one line data of the frame:\n");rnrn printf("\n");rn pSwsCtx = sws_getCachedContext(pSwsCtx, pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,rn pCodecCtx->width, pCodecCtx->height, AVMEDIA_TYPE_VIDEO,rn SWS_BICUBIC, NULL, NULL, NULL);rn sws_scale(pSwsCtx, (const unsigned char* const *)pFrame->data[0], pFrame->linesize, 0, pCodecCtx->height, pFrameRgb->data, pFrameRgb->linesize);rn av_info_log("cover img format finish!\n");rnrn else rn av_info_log("decode a frame fail!\n");rn break;rnrn rn rn rn while (in_size!=0);rnrn break; rn rn while (1);rnrnrn av_free_packet(&packet);rnrn av_free(buffer);rn av_frame_free(&pFrame);rn avformat_close_input(&pFormatCtx);rn return 0;rnrnerr3:rn av_frame_free(&pFrame);rn av_free_packet(&packet);rn av_free(buffer);rnrnerr2:rn av_frame_free(&pFrame);rnrnerr1:rn avformat_close_input(&pFormatCtx);rn return -1;rn[/code] 论坛

没有更多推荐了,返回首页