ffmpeg API 视频解码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

extern "C"
{
	#include <libavcodec\avcodec.h>
	#include <libavformat\avformat.h>
	#include <libavutil\opt.h>
	#include <libswscale\swscale.h>
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
int main()
{
	// 创建三个文件,分别用来存放y数据,u数据,v数据
	FILE* f1 = fopen("11_yuv_y.y","wb+");
	FILE* f2 = fopen("11_yuv_u.y","wb+");
	FILE* f3 = fopen("11_yuv_v.y","wb+");
	//打印编解码器的信息
	printf("%s\n",avcodec_configuration());
	//  注册DLL
	av_register_all();
	//  初始化网络文件
	avformat_network_init();
    // 格式上下文
	AVFormatContext* pFormat = NULL;
	const char* path  = "11.mp4";
	//http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8
   //const char* path = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
	//打开网络文件用的结构体
	AVDictionary* opt=NULL;
	av_dict_set(&opt, "rtsp_transport", "tcp", 0);   // 使用TCP协议打开网络流文件
	av_dict_set(&opt, "max_delay", "550", 0);        // 延迟小于550毫秒
	int ret  = avformat_open_input(&pFormat,path,NULL, &opt);     // 打开文件
	if (ret)
	{
		printf(" avformat_open_input failed\n");
		return -1;
	}
	printf(" avformat_open_input success\n");
	// H264  width  height
	ret  = avformat_find_stream_info(pFormat,NULL);    // 查找流信息
	if (ret)
	{
		printf(" avformat_find_stream_info failed\n");
		return -1;
	}
	printf(" avformat_find_stream_info success\n");
	int time = pFormat->duration;                 // 得到视频的时长
	int mbittime = (time / 1000000)/60;
	int mmintime = (time / 1000000)%60;
	printf("&%d·Ö:%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;     // 将视频流的宽赋值给width
	int height   = pFormat->streams[VideoStream]->codec->height;    
	int fmt      = pFormat->streams[VideoStream]->codec->pix_fmt;   // 将视频流的pix_fmt复制给fmt
	//
	int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P,              // 得到YUV420P文件的大小
		width, height);
	uint8_t* buff = NULL;
	buff =(uint8_t*)av_malloc(nSize);

	
	avpicture_fill((AVPicture*)frameYUV, buff, AV_PIX_FMT_YUV420P, width, height);

	//av_malloc µÈ¼ÛÓÚ malloc()
	AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));

	
	//swsCtx = sws_getCachedContext(swsCtx,XXXX)
	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)   // 如果packet中的索引是 VIDEO 的话
		{
			//vCodec  pFormat->streams[VideoStream]->codec
			ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec,frame,&go,packet);    // 进行解码
			if (ret<0)     // 小于0 报错停止运行
			{
				printf(" avcodec_decode_video2 failed\n");
				return -1;
			}
			if (go)        // 如果 等于 0 的话就继续运行
			{
				sws_scale(swsCtx,                                // 进行重采样   重采样上下文
					(const uint8_t**)frame->data,                // 
					frame->linesize,                             
					0,
					height,
					frameYUV->data,
					frameYUV->linesize
					);
				fwrite(frameYUV->data[0],1,width*height,f1);       // 写入Y 数据
				fwrite(frameYUV->data[1],1,width*height/4, f2);    // 写入U 数据
				fwrite(frameYUV->data[2],1,width*height/4, f3);    // 写入V 数据
                           // fwrite(frameYUV->data[0],1,width*height,f1);    写入到一个文件
                           // fwrite(frameYUV->data[1],1,width*height,f1);    
                           // fwrite(frameYUV->data[2],1,width*height,f1);
				FrameCount++;
				printf("frame index:%d \n", FrameCount++);         // 给个提示 提示程序一直在跑
			}
		}
		av_free_packet(packet);            // 释放 packet
	}
	fclose(f1);
	fclose(f2);
	fclose(f3);
   // fclose(f1);  
	sws_freeContext(swsCtx);            // 释放重采样的上下文
	av_frame_free(&frame);              // 释放frame
	av_frame_free(&frameYUV);           // 释放frame
	avformat_close_input(&pFormat);     // 关闭格式上下文
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值