标题所谓裸流, 与封装格式:
裸流: 音频数据流 (如果用户不知道采样率, 数据格式 无法正常播放)
已封装的音频文件: 封装文件头(存储音频数据流的采样率, 数据格式) + 音频数据流 + 封装文件尾
将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;
}