标题所谓裸流, 与封装格式:

裸流: 音频数据流 (如果用户不知道采样率, 数据格式 无法正常播放)
已封装的音频文件: 封装文件头(存储音频数据流的采样率, 数据格式) + 音频数据流 + 封装文件尾

将g711u裸流封装成wav

核心步骤 写入头, 写入数据流 , 写入尾

#include <stdio.h>
#include "libavformat/avformat.h" //封装需要的头文件
#include "libavformat/avio.h"     //ffmpeg的io库

/***ffmpeg 通用的错误信息处理***/
#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);
	std::cerr << buf << std::endl;
}
/**********************/

int main()
{
	AVFormatContext* ec = nullptr;
	int re;
	//获取封包上下文 AVFormatContext
	re = avformat_alloc_output_context2(&ec, NULL, NULL, "qqq.wav");
	CERR(re);

	//封包上下文中添加一条流
	AVStream *as = avformat_new_stream(ec, NULL);


	re = avio_open(&ec->pb, "qqq.wav", AVIO_FLAG_WRITE);
	CERR(re);

	as->codecpar->codec_tag = 0;
	as->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;  //设置此流为音频
	as->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW; //g711u的编解码器
	as->codecpar->extradata_size = 0; 
	as->codecpar->format = AV_SAMPLE_FMT_S16;//g711u的数据格式
	as->codecpar->bit_rate = 64000;
	as->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
	as->codecpar->channels = 1;
	as->codecpar->sample_rate = 8000;
	as->codecpar->frame_size = 1152; //必须是16的倍数

	//写入文件头
	re = avformat_write_header(ec, NULL);
	CERR(re);

	AVPacket* pkt = av_packet_alloc();
	if (!pkt)
	{
		return -1;
	}
	
	FILE* fp = fopen("s396.g711u", "rb"); //此文件为音频裸流的存储文件
	if (!fp)
	{
		return -2;
	}
	int64_t m_pts = 0;
	while (!feof(fp))
	{
		re = av_new_packet(pkt, 1152);
		pkt->pts = m_pts;
		pkt->dts = m_pts;
		m_pts += as->codecpar->frame_size;
		CERR(re);
		fread(pkt->data, 1152, 1, fp);
		re = av_interleaved_write_frame(ec, pkt);
		CERR(re);
		av_packet_unref(pkt); 
	}


	//写入结尾
	re = av_write_trailer(ec);
	CERR(re);

	fclose(fp);
	av_packet_free(&pkt);
	avio_close(ec->pb);
	avformat_free_context(ec);


	return 0;
} 


Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐