回顾多媒体文件的全生命周期,大致可分为4个阶段:采集、加工、传输、播放,而封装和编码便是常见的两种加工方式。
为了节省存储空间以及提高传输速度,我们要对采集的原始视频或音频进行压缩编码。对于视频,常见的编码方式是H264(MPEG-4 Advanced video coding)编码;对于音频,常见的编码方式是aac(Advanced audio coding)编码。H264编码后的视频文件后缀名为.h264,aac编码后的音频文件后缀名为.aac。
那为什么要封装呢?封装是把音频和视频整合成一个文件。试想一下,如果我们平时观看电影,还要去分别打开视频和音频,是不是很费劲呢? 封装技术有不同的实现方案,不同的实现方案会产生不同的封装格式(Container formats)。MP4(MPEG-4)、Mov(QuickTime Movie)、Flv(Flash video)都是日常生活中常见的封装格式。
有封装就有解封装。顾名思义,解封装即把封装文件拆分成视频和音频文件。
一.案例说明
这次将实现一个将“Titanic.mp4”多媒体文件分解成“Titanic.h264”和“Titanic.aac”的例子。 以下贴上主函数源代码。
int ret=0;
int video_index,audio_index;
AVFormatContext *fmt_ctx=NULL;
AVPacket pkt;
FILE *video_dst_file=NULL;
FILE *audio_dst_file=NULL;
//输入模块
//*1*
ret=avformat_open_input(&fmt_ctx,"Titanic.ts",NULL,NULL);
//*2*
avformat_find_stream_info(fmt_ctx,NULL);
//*3*
av_dump_format(fmt_ctx,-1,"Titanic.mp4",0);
//*4*
video_index=av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
audio_index=av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_AUDIO,-1,-1,NULL,0);
//输入模块
//*5*
video_dst_file=fopen("Titanic.h264","wb");
audio_dst_file=fopen("Titanic.aac","wb");
//数据传输模块
av_init_packet(&pkt);
//*6* 从封装格式中读取编码帧
while(av_read_frame(fmt_ctx,&pkt)>=0)
{
if(pkt.stream_index==video_index)
{
//*7* 将视频编码帧写到视频输出文件
fwrite(pkt.data,1,pkt.size,video_dst_file);
}
else if(pkt.stream_index==audio_index)
{
//*7* 将音频编码帧写到音频输出文件
fwrite(pkt.data,1,pkt.size,audio_dst_file);
}
av_packet_unref(&pkt);
}
fclose(video_dst_file);
fclose(audio_dst_file);
avformat_close_input(&fmt_ctx);
return 0;
二.操作步骤
*1.打开输入多媒体文件“Titanic.mp4”
*2.获取流信息
*3.分别寻找视频流和音频流
*4.打印输入文件详细信息
*5.以“wb”模式分别打开输出文件“Titanic.h264”和“Titanic.aac”
*6.从输出文件获取编码帧
*7.根据编码帧的种类分别写入文件“Titanic.h264”和“Titanic.aac”
*8.释放内存
三.模块和API
我把整个程序分为3个模块:输入模块、输出模块、数据传输模块。其中输入模块对应步骤1-4,输出模块对应步骤5,数据传输模块对应步骤6-7。
四.运行结果
打开命令提示符窗口,切换到输出文件“Titanic.h264”和“Titanic.aac”所在目录,执行“ffplay Titanic.aac”指令,我们可以看到其正常播放。
执行“ffplay Titanic.h264”指令,我们也可以看到其正常播放。