FFMPEG解码流程

FFMPEG解码流程:

1. 注册全部容器格式和CODEC:av_register_all()

2. 打开文件:av_open_input_file()

3. 从文件中提取流信息:av_find_stream_info()

4. 穷举全部的流,查找其中种类为CODEC_TYPE_VIDEO

5. 查找对应的解码器:avcodec_find_decoder()

6. 打开编解码器:avcodec_open()

7. 为解码帧分配内存:avcodec_alloc_frame()

8. 不停地从码流中提取出帧数据:av_read_frame()

9. 判断帧的类型,对于视频帧调用:avcodec_decode_video()

10. 解码完后,释放解码器:avcodec_close()

11. 关闭输入文件:av_close_input_file()


       首先第一件事情就是开一个视频文件并从中获得流。咱们要作的第一件事情就是使用av_register_all();来初始化libavformat/libavcodec: 这一步注册库中含有的全部可用的文件格式和编码器,这样当打开一个文件时,它们才可以自动选择相应的文件格式和编码器。av_register_all()只需调用一次,因此,要放在初始化代码中。也能够仅仅注册我的的文件格式和编码。html

      下一步,打开文件:ide

      AVFormatContext *pFormatCtx;
      const char      *filename="myvideo.mpg";
       av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL);   // 打开视频文件
       最后三个参数描述了文件格式,缓冲区大小(size)和格式参数;咱们经过简单地指明NULL或0告诉 libavformat 去自动探测文件格式而且使用默认的缓冲区大小。这里的格式参数指的是视频输出参数,好比宽高的坐标。函数

       下一步,咱们须要取出包含在文件中的流信息:
编码

[html]  view plain copy print ?
  1. av_find_stream_info(pFormatCtx);                                // 取出流信息  
  2.   
  3. AVFormatContext 结构体  
  4.   
  5. dump_format(pFormatCtx, 0, filename, false);//咱们能够使用这个函数把获取到得参数所有输出。  
  6.   
  7. for(i=0; i<pFormatCtx->nb_streams; i++)        //区分视频流和音频流  
  8.  if(pFormatCtx->streams->codec.codec_type==CODEC_TYPE_VIDEO) //找到视频流,这里也能够换成音频  
  9.     {  
  10.         videoStream=i;  
  11.         break;  
  12.     }  


接下来就须要寻找解码器spa

[html]  view plain copy print ?
  1. AVCodec *pCodec;  
  2. pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  3.   
  4. avcodec_open(pCodecCtx, pCodec);    // 打开解码器  


给视频帧分配空间以便存储解码后的图片:.net

[html]  view plain copy print ?
  1. AVFrame *pFrame;  
  2. pFrame=avcodec_alloc_frame();  


/////////////////////////////////////////开始解码///////////////////////////////////////////指针

第一步固然是读数据:code

咱们将要作的是经过读取包来读取整个视频流,而后把它解码成帧,最后转换格式而且保存。orm

[html]  view plain copy print ?
  1. while(av_read_frame(pFormatCtx, &packet)>=0) {     //读数据  
  2.   
  3.      if(packet.stream_index==videoStream){         //判断是否视频流  
  4.   
  5.          avcodec_decode_video(pCodecCtx,pFrame, &frameFinished,  
  6.   
  7. packet.data, packet.size);                         //解码  
  8.   
  9.      if(frameFinished) {  
  10.   
  11. img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,(AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,pCodecCtx->height);//转换   }     
  12.   
  13. SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height, i); //保存数据  
  14.   
  15. av_free_packet(&packet);                       //释放  


    av_read_frame()读取一个包而且把它保存到AVPacket结构体中。这些数据能够在后面经过av_free_packet()来释 放。函数avcodec_decode_video()把包转换为帧。然而当解码一个包的时候,咱们可能没有获得咱们须要的关于帧的信息。所以,当咱们获得下一帧的时候,avcodec_decode_video()为咱们设置了帧结束标志frameFinished。最后,咱们使用 img_convert()函数来把帧从原始格式(pCodecCtx->pix_fmt)转换成为RGB格式。要记住,你能够把一个 AVFrame结构体的指针转换为AVPicture结构体的指针。最后,咱们把帧和高度宽度信息传递给咱们的SaveFrame函数。视频

原文地址

相关文章
相关标签/搜索