用ffmpeg获取rtsp视频流的宽高帧率及其他信息

ffmpeg:FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表“Fast Forward,是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

库的组成:

libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;

libavcodec:用于各种类型声音/图像编解码;

libavutil:包含一些公共的工具函数;

libswscale:用于视频场景比例缩放、色彩映射转换;

libpostproc:用于后期效果处理;

ffmpeg:该项目提供的一个工具,可用于格式转换、解码或电视卡即时编码等;

ffsever:一个 HTTP 多媒体即时广播串流服务器;

ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示;

demo:(在ffmpeg交叉编译生成库时,需要编译支持增加h264的库)

扫描二维码关注公众号,回复: 5973545 查看本文章
#include <stdio.h>  

#define __STDC_CONSTANT_MACROS  
#ifdef __cplusplus  
extern "C"
{
#endif  
#include "libavcodec/avcodec.h"  
#include "libavformat/avformat.h"  
#include "libswscale/swscale.h"   
#ifdef __cplusplus  
};
#endif  


int main(int argc, char* argv[])
{
	AVFormatContext *pFormatCtx;
	int             i, videoindex;
	AVCodecContext  *pCodecCtx;
	AVCodec         *pCodec;
	AVFrame *pFrame, *pFrameYUV;
	uint8_t *out_buffer;
	AVPacket *packet;
	int ret, got_picture;
	struct SwsContext *img_convert_ctx;

	char filepath[] = "rtsp://admin:[email protected]:554/11";

	av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();

	AVDictionary* options = NULL;
	av_dict_set(&options, "buffer_size", "1024000", 0); //设置最大缓存,1080可调到最大
	av_dict_set(&options, "rtsp_transport", "tcp", 0); //以tcp的方式传送
	av_dict_set(&options, "stimeout", "5000000", 0); //设置超时断开链接时间,单位us
	av_dict_set(&options, "max_delay", "500000", 0); //设置最大时延
	av_dict_set(&options, "framerate", "20", 0); 

	//ff_dump_stream_info(filepath);

	if (avformat_open_input(&pFormatCtx, filepath, NULL, &options) != 0)  
	{
		printf("Couldn't open input stream.\n");
		return -1;
	}
	if (avformat_find_stream_info(pFormatCtx, NULL)<0)
	{
		printf("Couldn't find stream information.\n");
		return -1;
	}

	videoindex = -1;
	for (i = 0; i<pFormatCtx->nb_streams; i++)
	{
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			videoindex = i;
			break;
		} else if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){
				int aud_idx = i;
		}
	}	
	if (videoindex == -1)
	{
		printf("Didn't find a video stream.\n");
		return -1;
	}
	pCodecCtx = pFormatCtx->streams[videoindex]->codec;
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL)
	{
		printf("Codec not found.\n");
		return -1;
	}
	if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)
	{
		printf("Could not open codec.\n");
		return -1;
	}

	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();
	out_buffer = (uint8_t *)av_malloc(avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height));
	avpicture_fill((AVPicture *)pFrame, out_buffer, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

	printf("-----------------------------------------------dumping stream info------------------------------------------------\n");
	av_dump_format(pFormatCtx, 0, filepath, 0);
	printf("input format: %s",pFormatCtx->iformat->name);//
	printf("  nb_streams: %d", pFormatCtx->nb_streams);//记录了该 URL 中包含有几路流
	int64_t start_time = pFormatCtx->start_time;
	printf("  start_time: %lld\n", start_time);//第一帧的时间戳
	printf("------------------------------------------------------------------------------------------------------------------\n");

	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);

	packet = (AVPacket *)av_malloc(sizeof(AVPacket));

	FILE *fpSave;
	if ((fpSave = fopen("geth264_testi1.h265", "w+")) == NULL)
		return 0;
	int j = 0;	
	for (j; j<5 ;j++)
	{
		//------------------------------  
		if (av_read_frame(pFormatCtx, packet) >= 0)
		{
			if (packet->stream_index == videoindex)
			{

				fwrite(packet->data, 1, packet->size, fpSave);  
				int k = 0;
				for (k=0; k<5; k++){
					printf("%02X ", packet->data[k]);
				}
				printf(" len %d\n", packet->size);
				printf("-----------------------------------------------dumping stream info------------------------------------------------\n");
				AVStream *video_stream = pFormatCtx->streams[videoindex];
				printf("  video nb_frames: %lld", video_stream->nb_frames);//该码流的总帧数
				printf("  video codec_id: %d", video_stream->codecpar->codec_id); // 编码编号
				printf("  video codec_name: %s", avcodec_get_name(video_stream->codecpar->codec_id));//编码类型
				printf("  video width x height: %d x %d", video_stream->codecpar->width, video_stream->codecpar->height);//长、宽
				printf("  video pix_fmt: %d\n", video_stream->codec->pix_fmt); // 原始图像的格式,码流中不一定存在该信息,会由解码后覆盖
				printf("  video bitrate %lld kb/s\n", video_stream->codecpar->bit_rate / 1000 );// 平均码率
				//printf("read video frame, timestamp = %lld \n", packet->pts);
				printf("------------------------------------------------------------------------------------------------------------------\n");

				av_free_packet(packet);			
			}
		}	
	}
	
	//-------------- 
	fclose(fpSave);
	av_frame_free(&pFrameYUV);
	av_frame_free(&pFrame);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);

	return 0;
}

编译:arm-hisiv400-linux-gcc VedioToH264_demo.c -o ffmpegtest  -I ./ffmpeg/include/ -L ./ffmpeg/lib/ -I h264/include/ -L h264/lib/  -pthread -lm -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswresample -lswscale -lrt -lx264 -ldl

结果如下:

猜你喜欢

转载自blog.csdn.net/weixin_42432281/article/details/88351227