ffmpeg解封装到抽取h264

对mp4封装的文件进行解封装并抽取h264

重要结构体:

AVFormatContext{
....
	unsigned int nb_streams;//流的数量
	AVStream **streams;  //存储的流数组
	void *priv_data; //存放参数信息
	AVIOContext *pb;  //I/O 在封装的时候用来写入文件
	int64_t duration; //整个媒体的时长
	int64_t bit_rate;  //整个媒体的比特率
	char *url;  //打开网络端的视频就要传这个
....
};
AVStream{
	...
	int index; //流的索引
	AVRational time_base; //时间基数
	AVRational avg_frame_rate; //帧率
	AVCodecParameters *codecpar;//包含配置参数信息, 解码用到的参数
	...
};
AVCodecParameters{
	...
	AVMediaType codec_type; //媒体类型:视频, 音频, 字幕
	AVCodecID codec_id; //编码器ID号
	int format; //像素格式
	int64_t bit_rate; //比特率
	int width; 
	int height;
	uint64_t channel_layout; //音频通道数
	int channels; //通道
	int sample_rate;//采样率
	int frame_size; //帧大小
	...
};

#include <iostream>
#include <fstream>
using namespace std;
extern "C"{
#include <libavformat/avformat.h>
}
//预处理指令导入库
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")

#define CERR(err) do{if(err!=0)\
				{printErr(err); return -1;}\
					}while(0)

void printErr(int err)
{
	char buf[1024] = { 0 };
	av_strerror(err, buf, sizeof(buf) - 1);
	cerr << buf << endl;
}

int main(int argc, char* argv[])
{
//1,打开mp4媒体文件, 初始化解封装上下文AVFormatContext, 需要释放空间的
	const char* url = "v1080.mp4";
	AVFormatContext* ic = nullptr;
	int re = avformat_open_input(&ic, 
	url,  
	NULL, //解封装格式,自动探测,以后缀名,或者文件头
	NULL);//参数设置, rtsp需要设置,里面有对应的AVOption, 解码时不需要, 填NULL, 参数配置在  libavformat/options_table.h 中
	CERR(re);


//2,获取媒体信息
	re = avformat_find_stream_info(ic, NULL);
	CERR(re);

	//打印封装信息
	av_dump_format(ic, 0, url, 0);


//3,提取出视频流/音频流
	AVStream* as = nullptr;
	AVStream* vs = nullptr;

	for (int i = 0; i < ic->nb_streams; ++i) {
		if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
			as = ic->streams[i];
			cout << "===音频===" << endl;
			cout << "sample_rate:" << as->codecpar->sample_rate << endl;
		}
		else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			vs = ic->streams[i];
			cout << "===视频===" << endl;
			cout << "width:" << vs->codecpar->width << endl;
			cout << "height" << vs->codecpar->height << endl;
		}
	}

//4,申请一个AVPacket用于存放提取的视频流
	AVPacket pkt; 






/**************************************/
//从mp4中抽取的AVPacket没有头部信息(SPS, PPS, IDR), 无法直接写入文件形成h264码流
//使用AVBSFContext包装
	AVBSFContext* absCtx = NULL;   //要释放空间
	const AVBitStreamFilter* absFilter = NULL;
	AVCodecParameters* codecpar = NULL;
	
	absFilter = av_bsf_get_by_name("h264_mp4toannexb");
	if(!absFilter){
		cout << "get bsFilter failed! << endl;
		return -1;
	}
	re = av_bsf_alloc(absFilter, &absCtx);
	CERR(re);

//流信息复制进上下文中
	codecpar = vs->codecpar;
	avcodec_parameters_copy(absCtx->par_in, codecpar);

	re = av_bsf_init(absCtx);
	CERR(re);



	ofstream ofs;
	ofs.open("test__h264.h264", ios::binary);
//申请一个用于存放添加了码流信息的包
	AVPacket pkt2;//如果是指针的形式需要初始化//av_init_packet(pkt2);
/**************************************/



//使用了AVPacket时都要考虑到其内存的释放
//5,开始从mp4提取AVPacket
	while(1){
		re = av_read_frame(ic, &pkt);
		if (re == AVERROR(EAGAIN) || re == AVERROR_EOF) break;
		else if(re != 0) break;
		if(vs && pkt.stream_index == vs->index){//抽取成功
			cout << "视频流";
			//pkt发送给过滤线程
			re = av_bsf_send_packet(absCtx, &pkt);
			CERR(re);
			while (1) {
				re = av_bsf_receive_packet(absCtx, &pkt2);
				if (re == AVERROR(EAGAIN) || re == AVERROR_EOF)
					break;
				ofs.write((char*)pkt2.data, pkt2.size);
				av_packet_unref(&pkt2);
			}
		}
		if (as && pkt.stream_index == as->index) {
			cout << "音频流";
		}
		
		av_packet_unref(&pkt);
	}

	av_bsf_free(&absCtx);
	avformat_close_input(&ic);
	ofs.close();
}
根据引用和引用的内容,使用FFmpeg可以实现解封装H.264和AAC音频。具体的步骤如下: 1. 准备FFmpeg:确保已经下载并安装最新版本的FFmpeg,并将其添加到系统的环境变量中。 2. 打开命令行终端:在命令行中输入以下命令以解封装H.264和AAC音频: ``` ffmpeg -i input.mp4 -c:v copy -c:a copy output.h264 ffmpeg -i input.mp4 -vn -c:a copy output.aac ``` 其中,`input.mp4`是要解封装的文件名,`output.h264`是输出的H.264视频文件名,`output.aac`是输出的AAC音频文件名。 3. 执行命令:按下Enter键执行命令,FFmpeg会开始解封装过程。 4. 等待完成:等待命令行显示解封装过程的进度,并等待解封装过程完成。 5. 完成解封装:完成后,你将得到一个H.264视频文件和一个AAC音频文件,用于进一步处理或播放。 需要注意的是,如果要模拟实时视频发送,需要安装FFmpeg并将其放置在可以连接到国标平台网络的位置。详细的安装步骤可以参考引用中提供的链接。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Hi3531D调试手记(四):使用ffmpeg实时封装H264视频为MP4](https://blog.csdn.net/qq_38940316/article/details/114577809)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [GB28181国标平台测试软件,模拟监控摄像头,实现了注册、注销、目录、INVITE,BYE、KEEPLIVE、OPTION信令](https://download.csdn.net/download/SE_JW/88241318)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值