上一篇文章我们搭好了环境并编译出所需的ffmpeg库,本篇我们讨论如何利用ffmpeg提供的API函数进行多媒体文件的解封装(demux)过程。在讲解之前,我们需要了解一些基本的多媒体文件知识,大虾请飘过。

  • 容器格式:不管是音频文件还是视频格式的文件,都是一个多媒体的容器,即container,比如常见的视频容器格式有avi、mp4、mkv、flv、rm/rmvb、mov、ts、vob、dat,音频容器格式有MP3、WAV、AAC、APE,FLAC等等,它容纳了视频、音频、字幕(subtitle)等一个或多个基本流数据,有的甚至一个容器中存放有多个视频、音频以及字幕。

  • 压缩格式:对视频、音频数据的基本流进行的压缩方式就是音视频的压缩格式。常见的视频压缩格式如mpeg2、mpeg4、H264、VC1、Rm/Rmvb,常见音频压缩格式如MPA、AAC、AC3、DTS。注意这里的部分名字和上面的一样,但意义不同,上面是封装格式,这里是压缩格式。为什么要压缩呢?因为不压缩的话,要存储图像或声音就需要非常多的空间,比如mpeg2压缩比能达到25:1左右,而H264甚至能达到102:1的惊人程度!

  • ES:也就是ElementaryStream,也称为基本流、组件流等称呼,就是单独的一路视频、一条音频、一个subtitle字幕或者单个的附加数据。显然常见的多媒体文件一个都有一个视频ES、音频ES,有的也含有多个视频ES和音频ES以及subtitleES。比如蓝光原版的TS一般都含有多个音轨ES和字幕ES,但不是所有有字幕都有字幕ES,可能字幕已经内嵌进视频,这样的字幕其实成了视频的一部分。

  • Demux:在播放时,需要把这些视音频以及字幕等基本流分离出来,这个过程就叫Demux,或者解封装,也称为解复用。分离出来的各个基本流(ES)分别送给视频解码器、音频解码器等解码后才能得到图像声音。Demux过程如下图(subtitle也可能需要解码):

  • Remux:当然Demux反过来把基本的音频、视频、字幕等组合成一个完整的多媒体就是Remux或者封装,也称为复用。比如很多电影网站的音视频压制的人就需要先做Demux,分离成ES,在加入必要的中文字幕和音轨后、重新封装。所有的转码工具也都必须有Remux和重新Demux的过程。复用与解复用的概念对于熟悉DVB行业的读者来说应该比较清楚。

  • PTS:也就是显示时间戳,指图像或者声音在解码后应该显示或者发声的时间点。音视频不是一解码出来就播出来,否则就乱了,性能好的解码器播放的快,差的播放的慢,并且视频和音频也对不上号。所有这些都是靠PTS来同步的。至于DTS解码时间戳在现在相对以前较大解码内存缓冲下,显得不那么重要了。

有了这些基本的多媒体知识,我们就可以继续讲解如何利用ffmpeg来进行Demux这个过程。首先介绍一下主要的几个API函数:

intavformat_open_input(AVFormatContext **ps, const char *filename,

AVInputFormat *fmt, AVDictionary **options);

这个函数用于打开多媒体文件,并读取相关文件头信息。

voidavformat_close_input(AVFormatContext **ps);

这个函数用于关闭上面打开的多媒体文件,释放相关资源。

intavformat_find_stream_info(AVFormatContext *ic, AVDictionary**options);

这个函数通过注册的文件格式解析器读取文件的取各种信息,比如播放持续时间、音视频压缩格式、音轨信息、字幕信息、帧率、采样率等等。

int av_read_frame(AVFormatContext*s, AVPacket *pkt);

这个函数对于Demux过程是最重要的一个函数,它从文件中读取一帧视频、一帧或多帧音频、字幕等ES数据包,除了数据本身之外,还包括PTS、持续时间、参考帧等重要信息。

void av_free_packet(AVPacket *pkt);

这个函数用于释放ES数据包,与上面的函数成对使用。

有了这些函数和上面的基本知识,下面我们来实现一个简单的Demux框架实例。这个实例的功能是把多媒体文件中的音视频ES数据抽出来分别写入不同文件。我们为了简单,这里不处理返回错误,在实际项目中自己添加错误处理机制。本文力求用最简单最原始的方式把ffmpeg解封装的基本框架讲解清楚。

 1 #include "libavformat/avformat.h"
 2
 3 static const char *media_file = "test_media.mp4";
 4 int main(void)
 5 {
 6 int i, vid_idx, aud_idx;
 7 FILE *fp_vides = NULL, *fp_audes = NULL;
 8 AVFormatContext *pFormatCtx = NULL;
 9 AVPacket pkt;
10
11 av_register_all();
12 avformat_open_input(&pFormatCtx, media_file, NULL, NULL);
13 avformat_find_stream_info(pFormatCtx, NULL);
14
15 fp_vides = fopen("vid_es.dat", "wb");
16 fp_audes = fopen("aud_es.dat", "wb");
17 // 1, handle stream info
18 for (i=0; i<pFormatCtx->nb_streams; i++)
19 {
20 if (pFormatCtx->streams[i]->codec->codec_type ==AVMEDIA_TYPE_VIDEO)
21 vid_idx = i;
22 else if (pFormatCtx->streams[i]->codec->codec_type ==AVMEDIA_TYPE_AUDIO)
23 aud_idx = i;
24 else
25 ;//such as subtitile
26 }
27 while (av_read_frame(pFormatCtx, &pkt) >= 0)
28 {
29 // 2, handle pkt data
30 if (pkt.stream_index == vid_idx)
31 fwrite(pkt.data, pkt.size, 1, fp_vides);
32 else if (pkt.stream_index == aud_idx)
33 fwrite(pkt.data, pkt.size, 1, fp_audes);
34 else
35 ;// such as subtitile
36 av_free_packet(&pkt);
37 }
38 fclose(fp_vides);
39 fclose(fp_audes);
40 avformat_close_input(&pFormatCtx);
41 return 0;
42 }

在注释1的地方,需要处理基本流索引与音视频对应的关系和重要信息记录,这个关系会在注释2的地方用到,并且也是后续的多音轨、字幕切换的凭据,本例只处理了最简单的只有一路音视频的情况,且没有对其他信息进行记录,比如帧率、视频宽高、编码类型、时间标度、第一个PTS等等。原则上这些跟Demux的框架没有关系,且每个人有有自己的处理方式,就不在这里贴出来。

要想获得更详细信息或者Demo代码,请关注微信号:程序员互动联盟,扫一扫下方二维码或者搜索微信号coder_online即可关注,我们可以在线交流。

如需转载请注明出处:谢谢合作!

转载于:https://www.cnblogs.com/2010wuhao/p/4389274.html

解密多媒体封装解封装框架相关推荐

  1. 网络中的OSI7层模型-封装解封装

    文章目录 OSI7层模型-封装解封装 OSI七层模型 OSI七层重要层解释说明(这些记下来) TCP/IP协议栈 主机间的通信模型介绍 主机间通信(数据封装解封装) 名词解释 单位说明 OSI7层模型 ...

  2. 封装 解封装 网线制作

    封装 应用层产生数据,发给表示层 表示层会对这个信息进行加密 和压缩 会话层什么也不做 传输层会给这个信息封装原目端口号,并签订协议 网络层会给这个信息封装原目IP 数据链路层会给这个信息封装原目ma ...

  3. 音视频解封装--解封装分离音频AAC文件

    1:简介 如下图所示,解封装就是将Flv.MP4等文件解封装为视频H264或H265压缩数据,音频解封装为AAC压缩数据. 2:ADTS头结构 ADTS的全称是Audio Data Transport ...

  4. 网络数据包封装/解封装

    数据的发送和接收其实就是封装及解封装的过程. 协议栈逐层向下传递数据,并添加报文头部和报文尾部的过程称为封装.反过来就是解封装. 封装过程 封装过程:上层原始数据→数据段(segment)→数据包(p ...

  5. 详解数据包封装解封装过程

    基本概念 IP地址:指互联网协议地址,用于在整个互联网中标识设备的存在位置(私有地址除外). MAC地址:为局域网地址,用于在一个局域网内确定主机的位置,这也说明了MAC只能在局部传递. 一:当互访者 ...

  6. 网络的分层思想和数据封装与解封装概论

    网络的分层思想和数据封装与解封装概论 网络的分层思想和数据封装与解封装概论 1.网络的分层思想 2.关于OSI分层模型的概念 3.关于TCP/IP模型和协议簇 4.数据的封装与解封装 网络的分层思想和 ...

  7. 如何利用ffmpeg提供的API函数进行多媒体文件的解封装

    多媒体已经无处不在,程序员必须知道的一些多媒体封装知识 如何利用ffmpeg提供的API函数进行多媒体文件的解封装. 上一篇文章我们搭好了环境并编译出所需的ffmpeg库,本篇我们讨论如何利用ffmp ...

  8. FFmpeg入门详解之43:FFmpeg解封装的原理与实战

    FFMpeg 解封装 本例子实现的是将音视频分离,例如将封装格式为 FLV.MKV.MP4.AVI 等封装格式的文件,将音频.视频分离开来. 大致的解封装流程: 1.首先要对解复用器进行初始化. 2. ...

  9. 理解OSI七层模型(了解OSI七层模型,数据如何传输,封装,解封装)

    文章目录 理解OSI七层模型 什么是OSI七层模型 理解OSI七层模型 举例子 七层协议,分析过程: 数据传输过程 封装数据 解封装数据 数据是如何封装和解封装 理解OSI七层模型 第一层:物理层. ...

最新文章

  1. 8 iOS中KVO 的本质
  2. 在什么情况下我应该使用malloc和/或new?
  3. nginx内存占用高---内存池使用思考
  4. java中的重写与重载_java中的重写与重载
  5. springMVC3.0(文件上传,@RequestMapping加参数,@SessionAttributes,@ModelAttribute,转发,重定向,数值获取,传参,ajax,拦截器)
  6. 从零点五开始用Unity做半个2D战棋小游戏(完)
  7. php 截取某个字符,PHP_php截取指定2个字符之间字符串的方法,本文实例讲述了php截取指定2个 - phpStudy...
  8. Java21天打卡练习Day21-集合map
  9. Linux内核提供了三种不同形式的中断底半部实现机制:软中断、tasklet和工作队列。...
  10. Oracle P6培训系列:04创建EPS结构
  11. ERStudio 8.0 连接MS SQL SERVER进行反向工程
  12. 【六】【vlc-android】vlc的decoder控制层传输数据与ffmpeg视频解码模块decoder层的数据交互流程源码分析
  13. ARM 代码烧录方案与原理详解 --- SWD/JTAG + Bootloader + OTA (ICP + ISP + IAP)
  14. 畅想计算机的未来50字,新学期畅想50字
  15. 国内设计师经常逛的5个素材网站
  16. 如何看待国企纷纷卸载微软Office改用金山WPS?
  17. STEP标准执行方法-ISO-10303-21
  18. 一个简单的使用EVP框架的加密过程
  19. 读论文《Recurrent neural network based language model 》
  20. 10次机会 js 猜数_用JS实现简单的猜数小游戏

热门文章

  1. httpd 处理模型
  2. tensorflow的keras 与 原生keras几点比较
  3. 20145302张薇《Java程序设计》实验三报告
  4. [转]Xcode的重构功能
  5. mouseevent tips
  6. Re: 社团改革还让不让人活了?
  7. Android studio ERROR: Software caused connection abort: recv failed 解决方法
  8. Android 事件分发,分发机制
  9. android 原生调用js,js调用原生
  10. mysql定义shell变量_shell 变量的定义,赋值,运算