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


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏曹俊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值