代码梳理ffmpeg解封装流程

//#include <iostream>
//1、目录要对应上
//2、头文件和lib   版本要对  ffmpeg3.42  ffmpeg4.2
//3、c++调用C语言的时候  需要一个extern

//extern "C"
//{
//	
//}

extern "C"
{
	#include <libavcodec/avcodec.h>
	#include <libavformat/avformat.h>
	#include <libswscale/swscale.h>
	#include <libavutil/opt.h>
}

#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")

int main()
{
	//const char* url = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
	const char *url = "1.mp4";
	int ret = -1;

	//测试和查看操作系统使用情况和支持库
	printf("%s\n", avcodec_configuration());
	//常规流程第一步注册
	av_register_all();//注册所有的库
	
	//注册  建立format空间 
	
	 创建封装格式上下文 结构体常用数据有 
	1.AvinputFormatContext 一些和封装格式有关的数据
	2.nb_streams: 输入文件信息和各种流的个数
	3.duration:输入文件的时长
	4.bit_rate:输入文件的码率
	AVFormatContext * pFormat = avformat_alloc_context();

	avformat_network_init();

	常规配置头文件 
	AVDictionary* opt = NULL; //=》专用头文件 opt.h
	av_dict_set(&opt, "rtsp_transport", "tcp", 0);
	av_dict_set(&opt, "max_delay", "550", 0); 

	常规流程第二步通过URL将封装信息写入开辟好的format空间 并且 设置opt
	ret = avformat_open_input(&pFormat, url,0, &opt);
	if (ret!=0)
	{
		printf("avformat_open_input error");
		system("pause");
		return -1;
	}
	//寻找流文件   新版本和老版本的方法
	//老的用的是遍历   新的是直接用新接口来做
	printf("avformat_open_input success\n");
	常规第三步1  读取媒体文件的format 以获取流信息  
	ret  = avformat_find_stream_info(pFormat, 0);
	if (ret < 0)
	{
		printf("avformat_find_stream_info error");
		system("pause");
		return -1;
	}
	printf("avformat_find_stream_info success");

	//总时长
	int time = pFormat->duration;
	int mbtimer = (time / 1000000) / 60;
	int mintimer = (time / 1000000) % 60;
	
	printf("%d分:%d秒\n", mbtimer, mintimer);

	av_dump_format(pFormat, 0, url, 0);

	AVStream  => int  寻找流
	常规第三步2  读取媒体文件的format 以获取流信息
	参数第三个为是否有指定流 如果-1 不指定走默认
	参数第四个是否找相关的流 如果-1 不着
	参数第五个是如果不为空 可以指定解码器相关的流 传0/NULL代表不需要
	int videoStream = av_find_best_stream(pFormat, AVMEDIA_TYPE_VIDEO, -1, -1, 0,0);
	int AudioStream = av_find_best_stream(pFormat, AVMEDIA_TYPE_AUDIO, -1, -1, 0,0);


	寻找解码器
	首先这四步函数在4.0已经修改 寻找对应解码器     
	结构为AvFormatContext -> AVstream[0] -> AvCodecContext ->AVCodec ->AVcodec ID 
	AVCodecContext *avctx = pFormat->streams[videoStream]->codec;
	AVCodec * avcodec = avcodec_find_decoder(avctx->codec_id);
	
	//const AVCodec *codec, AVDictionary **options
	//打开解码器
	ret  = avcodec_open2(avctx, avcodec, 0);
	if (ret !=0)
	{
		printf("avcodec_open2 error");
		system("pause");
		return -1;
	}
	printf("avcodec_open2 success");

	创建Frame 空间 Frame 为解码后的帧文件格式

	AVFrame* Frame	  = av_frame_alloc();
	AVFrame* Frameyuv = av_frame_alloc();
	从编码器上下文中 获得图像格式信息
	int width = avctx->width;
	int heigt = avctx->height;
	int fmt = avctx->pix_fmt;//AVPixelFormat
	printf("宽:%d,高:%d\n", width, heigt);
	//分配空间  进行图像转换
	 目前4.0 已经放弃 获得解码后一帧文件大小
	int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P, width, heigt);

	//数据具体格式转换  并且开辟空间
	uint8_t* buff =(uint8_t*) av_malloc(nSize);

	//目前4.0 已经放弃  一帧图像大小  这里不太懂 上面和下面的逻辑是什么  是否是写入还是缓冲区关系
	avpicture_fill((AVPicture *)Frameyuv,
		buff, 
		AV_PIX_FMT_YUV420P, width, heigt);

	开辟AVPacket  其为编码后一个视频帧文件
	AVPacket*packet = (AVPacket*)av_malloc(sizeof(AVPacket));
	
	//转换上下文   写入转换前格式和转换后格式
	SwsContext* sct = NULL;
	sct =  sws_getContext (width, heigt,
		(AVPixelFormat)fmt,
		width, heigt, AV_PIX_FMT_YUV420P,
		SWS_BICUBIC,0,0,0);

	//读帧
	int FrameCount = 0;
	int go;
	//av_read_frame 不太懂
	while (av_read_frame(pFormat,packet)>=0)
	{
		//判断是否是视频流
		if (packet->stream_index == AVMEDIA_TYPE_VIDEO)
		{
			//解码视频流
			ret = avcodec_decode_video2(avctx,Frame,&go,packet);

			if (ret < 0)
			{
				printf("avcodec_decode_video2");
				return -1;
			}
			//解码成功就转换数据
			if (go)
			{
			//转换格式 大小等等操作的地方
				int h = sws_scale(sct, (const uint8_t**)Frame->data,
						Frame->linesize,
						0, 
						heigt,
						Frameyuv->data,
						Frameyuv->linesize);

				///文件写入
				文件编码
				//fwrite  查看码流

				FrameCount++;
				printf("当前高度为:%d,当前转换第%d帧\n",h, FrameCount);

			}
		}
		av_free_packet(packet);
	}
	//free context();
	
	sws_freeContext(sct);
	av_frame_free(&Frame);
	av_frame_free(&Frameyuv);
	avformat_close_input(&pFormat);
	avformat_free_context(pFormat);

	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值