FFMPEG:经典解码案例

FFMPEG:经典解码案例,第1张

#define _CRT_SECURE_NO_WARNINGS
#include
extern "C" {
#include
#include 
#include
#include
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
int main()
{
	FILE* fp1 = fopen("yuv420_y.y", "wb+");
	FILE* fp2 = fopen("yuv420_u.y", "wb+");
	FILE* fp3 = fopen("yuv420_v.y", "wb+");
	printf("%s\n", avcodec_configuration());//测试DLL
	av_register_all();//注册DLL
	/*avformat_network_init();//网络*/
	AVFormatContext* pFormat = NULL;//设备上下文
	const char* path = "11.mp4";
	/*const char* path = "http://121.18.168.149/cache.ott.ystenlive.itv.cmvideo.cn:80/000000001000/5000000010000030951/index.m3u8?channel-";
	AVDictionary* OPT=NULL;
	av_dict_set(&OPT,"rtsp_transport","tcp",0)//设置网络信息;
	av_dict_set(&OPT, "max_delay", "550", 0);*/
	int ret = avformat_open_input(&pFormat,path,NULL, NULL);//打开网络视频文件
	if (ret)
	{
		printf("avformat_open_input failed\n");
		return -1;
	}
	printf("avformat_open_input success\n");

    ret = avformat_find_stream_info(pFormat,NULL);//寻找流信息  h264  h w
	if (ret<0)
	{
		printf("avformat_find_stream_info failed\n");
		return -1;
	}
	printf("avformat_find_stream_info success\n");

	int time = pFormat->duration;//获取时长,单位us;
	int mbittime = (time / 1000000) / 60;//得到多少分钟
	int mmintime = (time / 1000000) % 60;//得到多少秒
	printf("mbittime=%d分,mmintime=%d秒\n", mbittime, mmintime);
	av_dump_format(pFormat,NULL,path,0);//显示文件信息

	//寻找流
	int VideoStream = -1, AudioStream = -1;
	VideoStream = av_find_best_stream(pFormat,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,NULL);
	AudioStream = av_find_best_stream(pFormat, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL);
	AVCodec *vCodec = avcodec_find_decoder(pFormat->streams[VideoStream]->codec->codec_id);
	if (!vCodec)
	{
		printf("avcodec_find_decoder failed\n");
		return -1;
	}
	printf("avcodec_find_decoder success\n");

	//打开解码器
	ret = avcodec_open2(pFormat->streams[VideoStream]->codec, vCodec,NULL);
	if (ret)
	{
		printf("avcodec_open2 failed\n");
		return -1;
	}
	printf("avcodec_open2 success\n");

	//开始解码视频
	//申请原始空间 =>>创建帧空间
	AVFrame* frame = av_frame_alloc();
	AVFrame* frameYUV = av_frame_alloc();
	int width = pFormat->streams[VideoStream]->codec->width;
	int height = pFormat->streams[VideoStream]->codec->height;
	int fmt = pFormat->streams[VideoStream]->codec->pix_fmt;
	//分配空间,进行图像转换
	int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P,width,height);
	uint8_t* buff = NULL;
	buff = (uint8_t*)av_malloc(nSize);
	//一帧图像
	avpicture_fill((AVPicture*)frameYUV, buff, AV_PIX_FMT_YUV420P, width, height);
	AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));
	//转换上下文
	//sws_getCachedContext//单线程
	SwsContext* swsCtx = NULL;
	swsCtx = sws_getContext(width, height,(AVPixelFormat)fmt,
		width, height, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);

	//读帧
	int go = 0;
	int FrameCount = 0;
	while (av_read_frame(pFormat, packet) >= 0)
	{
		//判断stream_index
		if (packet->stream_index == AVMEDIA_TYPE_VIDEO)
		{
			ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec,frame,&go,packet);
			if (ret <0)
			{
				printf("avcodec_decode_video2 failed\n");
				return -1;
			}
			if (go)
			{
				sws_scale(swsCtx,(const uint8_t**)frame->data,frame->linesize,0,
					height,frameYUV->data,frameYUV->linesize);
				fwrite(frameYUV->data[0], 1, width * height, fp1);
				fwrite(frameYUV->data[1], 1, width * height / 4, fp2);
				fwrite(frameYUV->data[2], 1, width * height / 4, fp3);
				FrameCount++;
				printf("frame index:%d\n", FrameCount);
			}
		}
		av_free_packet(packet);
	}
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
	sws_freeContext(swsCtx);
	av_frame_free(&frame);
	av_frame_free(&frameYUV);
	avformat_close_input(&pFormat);
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/739322.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存