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函數。視頻

原文地址

相關文章
相關標籤/搜索