如何检测一个packet中的数据是关键帧

通过AVPacket中的flags来判断。具体的代码参考如下:

#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
extern "C"
{
    #include <libavcodec/avcodec.h>
	#include <libavformat/avformat.h>
	#include <libavdevice/avdevice.h>
	#include<libswresample/swresample.h>
}
using namespace std;

int main(int argc, _TCHAR* argv[])
{
	char *url = "D:/video/sliph264/111.flv";
	AVFormatContext *ic;
	ic = avformat_alloc_context();

	av_register_all();
	AVPacket *pkt = (AVPacket *)malloc(sizeof(AVPacket));

	av_init_packet(pkt);
	int videostream, audiostream;
	int j = 0,i;
	int reference_stream_index;
	int ret = avformat_open_input(&ic, url, NULL, 0);
	if (avformat_find_stream_info(ic, NULL) < 0)
	{
		cout << "dont find stram" << endl;
		system("pause");
		return -1;
	}
	if (ret != 0)
	{
		char buf[1024] = { 0 };
		av_strerror(ret, buf, sizeof(buf)-1);
		cout << "open " << url << " failed! :" << buf << endl;
		system("pause");
		return -1;
	}
	cout << "open scucess" << url << endl;
	
	cout << "ic->nb_streams:" << ic->nb_streams << endl;
	for (int i = 0; i < ic->nb_streams; i++)
	{
		if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			videostream = i;
		}
		if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			audiostream = i;
		}
	}
	cout << "videostream:" << videostream << "audiostream:" << audiostream << endl;
	
	while (1)
	{
		if (av_read_frame(ic, pkt) >= 0)
		{
			if (pkt->stream_index == videostream && (pkt->flags & AV_PKT_FLAG_KEY))
			{
				j++;
				printf("该帧为关键帧\n  j = %d\n", j);
			}
		}
	}

	system("pause");

	return 0;
}

上述需要注意的问题是,打开mp4文件时,只需要avformat函数就可以得到ic->nb_streams值是2,但是打开flv格式文件时,仅仅avformat_open_input函数是不够的,还需要avformat_find_stream_info函数,才能得到ic->nb_streams的值为2.

在一些格式当中没有头部信息,如flv格式,h264格式,这个时候调用avformat_open_input()在打开文件之后就没有参数,也就无法获取到里面的信息。这个时候就可以调用avformat_find_stream_info此函数,因为它会试着去探测文件的格式,但是如果格式当中没有头部信息,那么它只能获取到编码、宽高这些信息,还是无法获得总时长。如果总时长无法获取到,则仍需要把整个文件读一遍,计算一下它的总帧数。

avformat_open_input函数会读文件头,对mp4文件而言,它会解析所有的box。但它知识把读到的结果保存在对应的数据结构下。这个时候,AVStream中的很多字段都是空白的。 
avformat_find_stream_info则检测这些重要字段,如果是空白的,就设法填充它们。因为我们解析文件头的时候,已经掌握了大量的信息,avformat_find_stream_info就是通过这些信息来填充自己的成员,当重要的成员都填充完毕后,该函数就返回了。这中情况下,该函数效率很高。但对于某些文件,单纯的从文件头中获取信息是不够的,比如vidoe的pix_fmt是需要调用h264_decode_frame才可以获取其pix_fmt的。因此,这个时候这个函数就会读一些数据进来,然后分析这些数据,并尝试解码这些数据,最终从中提取到所需要的信息。在所有的信息都已经获取到以后,avformat_find_stream_info函数会计算start_time,波特率等信息
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值