FFMPEG系列課程(二)讀取視頻幀

再來介紹下如何讀取視頻幀,打開視頻參考前面的文章,首先需要創建一個幀的存放對象

AVPacket pkt;

memset(&pkt, 0, sizeof(AVPacket)); 

     再通過 int err = av_read_frame(ic, &pkt); 讀取幀數據,其中ic是之前打開的視頻流句柄。讀取視頻幀後要注意一點av_read_frame會自動給視頻幀分配空間,返回值0表示成功。

    可以通過 av_packet_unref(&pkt);刪除packet的控制,注意這裏刪除的不是packet對象的空間,而是packet對象指向的數據空間。

   通過判斷pkt的stream_index 成員可以判斷此幀數據是不是視頻

    if (pkt.stream_index == videoStream),

    videoStream是打開視頻時存放的視頻流索引,大部分文件都是0,參考前一篇文章。

  1. extern "C"  

  2. {  

  3. #include<libavformat/avformat.h>  

  4. }  

  5. //引用lib庫,也可以在項目中設置,打開視頻只需要用到這三個庫  

  6. #pragma comment(lib,"avformat.lib")  

  7. #pragma comment(lib,"avutil.lib")  

  8. #pragma comment(lib,"avcodec.lib")  

  9. #include <iostream>  

  10. using namespace std;  

  11. int main(int argc, char *argv[])  

  12. {  

  13.     //初始化所以ffmpeg的解碼器  

  14.     av_register_all();  

  15.   

  16.   

  17.     char path[1024] = "video.mp4";  

  18.     //用來存放打開的視頻流信息  

  19.     AVFormatContext *ic = NULL;  

  20.   

  21.   

  22.     //用來存儲視頻流索引  

  23.     int videoStream = 0;  

  24.   

  25.   

  26.     //打開視頻播放流  

  27.     //path參數表示打開的視頻路徑,這個路徑可以包括各種視頻文件  

  28.     //也包括rtsp和http網絡視頻流  

  29.     //第三個參數表示傳入的視頻格式,我這邊不傳遞有FFmpeg內部獲取  

  30.     //最後一個參數是設置,我們這裏也不傳遞  

  31.     int re = avformat_open_input(&ic, path, 0, 0);  

  32.     if (re != 0)  

  33.     {  

  34.         //獲取到FFmpeg的錯誤信息  

  35.         char errorbuf[1024] = { 0 };  

  36.         av_strerror(re, errorbuf, sizeof(errorbuf));  

  37.         printf("open %s failed: %s\n", path, errorbuf);  

  38.         return -1;  

  39.     }  

  40.   

  41.   

  42.     //遍歷視頻流,裏面包含音頻流,視頻流,或者字母流,我們這裏只處理視頻  

  43.     for (int i = 0; i < ic->nb_streams; i++)  

  44.     {  

  45.         AVCodecContext *enc = ic->streams[i]->codec;  

  46.         //確認是視頻流  

  47.         if (enc->codec_type == AVMEDIA_TYPE_VIDEO)  

  48.         {  

  49.             //存放視頻流索引,後面的代碼要用到  

  50.             videoStream = i;  

  51.   

  52.   

  53.             //找到解碼器,比如H264,解碼器的信息也是ffmpeg內部獲取的  

  54.             AVCodec *codec = avcodec_find_decoder(enc->codec_id);  

  55.             if (!codec)  

  56.             {  

  57.                 printf("video code not find!\n");  

  58.                 return -2;  

  59.             }  

  60.   

  61.   

  62.             //打開視頻解碼器,打開音頻解碼器用的也是同一個函數  

  63.             int err = avcodec_open2(enc, codec, NULL);  

  64.             if (err != 0)  

  65.             {  

  66.                 char buf[1024] = { 0 };  

  67.                 av_strerror(err, buf, sizeof(buf));  

  68.                 printf(buf);  

  69.                 return -3;  

  70.             }  

  71.         }  

  72.     }  

  73.   

  74.   

  75.     //創建視頻幀對象  

  76.     AVPacket pkt;  

  77.     memset(&pkt, 0, sizeof(AVPacket));  

  78.   

  79.   

  80.     for (;;)  

  81.     {  

  82.         //讀取視頻幀  

  83.         int err = av_read_frame(ic, &pkt);  

  84.         if (err != 0)  

  85.         {  

  86.             //讀到結尾或者出錯  

  87.             char buf[1024] = { 0 };  

  88.             av_strerror(err, buf, sizeof(buf));  

  89.             printf(buf);  

  90.             break;  

  91.         }  

  92.   

  93.   

  94.         //判斷是否是音頻  

  95.         if (pkt.stream_index == videoStream)  

  96.         {  

  97.             printf("video pkt size is %d\n", pkt.size);  

  98.             //視頻處理,解碼或者存儲  

  99.         }  

  100.   

  101.   

  102.         //視頻幀數據空間  

  103.         av_packet_unref(&pkt);  

  104.     }  

  105. }  

更多的資料也可以關注我51CTO上的視頻課程

夏老師的課堂 http://edu.51cto.com/lecturer/12016059.html

手把手教您開發視頻播放器

http://edu.51cto.com/course/course_id-8059.html


wKiom1hhpxiBk1CeAAHvubpXcZo754.png-wh_50


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章