1. 程式人生 > >FFMPEG系列課程-讀取視訊幀

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,參考前一篇文章。




extern "C"
{
#include<libavformat/avformat.h>
}
//引用lib庫,也可以在專案中設定,開啟視訊只需要用到這三個庫
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
	//初始化所以ffmpeg的解碼器
	av_register_all();


	char path[1024] = "video.mp4";
	//用來存放開啟的視訊流資訊
	AVFormatContext *ic = NULL;


	//用來儲存視訊流索引
	int videoStream = 0;


	//開啟視訊播放流
	//path引數表示開啟的視訊路徑,這個路徑可以包括各種視訊檔案
	//也包括rtsp和http網路視訊流
	//第三個引數表示傳入的視訊格式,我這邊不傳遞有FFmpeg內部獲取
	//最後一個引數是設定,我們這裡也不傳遞
	int re = avformat_open_input(&ic, path, 0, 0);
	if (re != 0)
	{
		//獲取到FFmpeg的錯誤資訊
		char errorbuf[1024] = { 0 };
		av_strerror(re, errorbuf, sizeof(errorbuf));
		printf("open %s failed: %s\n", path, errorbuf);
		return -1;
	}


	//遍歷視訊流,裡面包含音訊流,視訊流,或者字母流,我們這裡只處理視訊
	for (int i = 0; i < ic->nb_streams; i++)
	{
		AVCodecContext *enc = ic->streams[i]->codec;
		//確認是視訊流
		if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			//存放視訊流索引,後面的程式碼要用到
			videoStream = i;


			//找到解碼器,比如H264,解碼器的資訊也是ffmpeg內部獲取的
			AVCodec *codec = avcodec_find_decoder(enc->codec_id);
			if (!codec)
			{
				printf("video code not find!\n");
				return -2;
			}


			//開啟視訊解碼器,開啟音訊解碼器用的也是同一個函式
			int err = avcodec_open2(enc, codec, NULL);
			if (err != 0)
			{
				char buf[1024] = { 0 };
				av_strerror(err, buf, sizeof(buf));
				printf(buf);
				return -3;
			}
		}
	}


	//建立視訊幀物件
	AVPacket pkt;
	memset(&pkt, 0, sizeof(AVPacket));


	for (;;)
	{
		//讀取視訊幀
		int err = av_read_frame(ic, &pkt);
		if (err != 0)
		{
			//讀到結尾或者出錯
			char buf[1024] = { 0 };
			av_strerror(err, buf, sizeof(buf));
			printf(buf);
			break;
		}


		//判斷是否是音訊
		if (pkt.stream_index == videoStream)
		{
			printf("video pkt size is %d\n", pkt.size);
			//視訊處理,解碼或者儲存
		}


		//視訊幀資料空間
		av_packet_unref(&pkt);
	}
}
更多的資料也可以關注我csdn上的視訊課程 夏老師課程專欄http://edu.csdn.net/lecturer/961

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

http://edu.csdn.net/course/detail/3300