播放器系列2——解复用

FFmpeg解复用过程详解

1.解复用概述

解复用(Demux)是多媒体处理中的重要步骤,主要负责将封装格式(如MP4、MKV等)中的音视频流分离出来。FFmpeg提供了完整的解复用API,可以处理各种常见的媒体格式。

2.核心API调用流程

在这里插入图片描述

3.详细步骤解析

3.1 函数介绍

avformat_open_input
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
  • 功能: 打开媒体文件并初始化AVFormatContext
  • 参数:
    • ps: 指向AVFormatContext指针的指针
    • url: 媒体文件路径
    • fmt: 指定输入格式,通常为NULL以自动检测
    • options: 额外的选项字典
  • 返回值: 成功返回0,失败返回负值错误码
  • 示例:
AVFormatContext *fmt_ctx = NULL;
if (avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL) < 0) {
    fprintf(stderr, "无法打开文件\n");
    return -1;
}
avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
  • 功能: 读取媒体文件数据包以获取流信息
  • 参数:
    • ic: AVFormatContext指针
    • options: 额外的选项字典
  • 返回值: 成功返回0,失败返回负值错误码
  • 示例:
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
    fprintf(stderr, "无法获取流信息\n");
    return -1;
}
av_find_best_stream
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, AVCodec **decoder_ret, int flags);
  • 功能: 查找指定类型的最佳流
  • 参数:
    • ic: AVFormatContext指针
    • type: 流类型(如AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO)
    • wanted_stream_nb: 期望的流索引,-1表示自动选择
    • related_stream: 相关流索引,-1表示无
    • decoder_ret: 返回解码器指针
    • flags: 标志位
  • 返回值: 成功返回流索引,失败返回负值错误码
  • 示例:
int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (video_stream_index < 0) {
    fprintf(stderr, "未找到视频流\n");
    return -1;
}
av_packet_alloc
AVPacket *av_packet_alloc(void);
  • 功能: 分配AVPacket
  • 返回值: 成功返回AVPacket指针,失败返回NULL
  • 示例:
AVPacket *pkt = av_packet_alloc();
if (!pkt) {
    fprintf(stderr, "无法分配数据包\n");
    return -1;
}
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
  • 功能: 从媒体文件中读取一个数据包
  • 参数:
    • s: AVFormatContext指针
    • pkt: AVPacket指针
  • 返回值: 成功返回0,失败返回负值错误码
  • 示例:
while (av_read_frame(fmt_ctx, pkt) >= 0) {
    if (pkt->stream_index == video_stream_index) {
        // 处理视频数据包
    }
    av_packet_unref(pkt);
}
av_packet_free
void av_packet_free(AVPacket **pkt);
  • 功能: 释放AVPacket
  • 参数:
    • pkt: 指向AVPacket指针的指针
  • 示例:
av_packet_free(&pkt);
avformat_close_input
void avformat_close_input(AVFormatContext **s);
  • 功能: 关闭输入文件并释放相关资源
  • 参数:
    • s: 指向AVFormatContext指针的指针
  • 示例:
avformat_close_input(&fmt_ctx);

3.2 完整示例流程

AVFormatContext *fmt_ctx = NULL;
AVPacket *pkt = NULL;

// 打开文件
if (avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL) < 0) {
    fprintf(stderr, "无法打开文件\n");
    return -1;
}

// 获取流信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
    fprintf(stderr, "无法获取流信息\n");
    return -1;
}

// 查找视频流
int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (video_stream_index < 0) {
    fprintf(stderr, "未找到视频流\n");
    return -1;
}

// 分配数据包
pkt = av_packet_alloc();
if (!pkt) {
    fprintf(stderr, "无法分配数据包\n");
    return -1;
}

// 读取并处理数据包
while (av_read_frame(fmt_ctx, pkt) >= 0) {
    if (pkt->stream_index == video_stream_index) {
        // 处理视频数据包
    }
    av_packet_unref(pkt);
}

// 清理
av_packet_free(&pkt);
avformat_close_input(&fmt_ctx);

4.容器介绍

在我们开始学习FFmpeg之前,我们先来了解一下容器的概念。说到容器大家一定会想到水杯、箱子、罐子等,这些都是容器的例子。在计算机领域,容器也是一个类似的概念。
在计算机领域,容器是一种用于存储和传输多媒体数据的文件格式。容器可以包含多种类型的数据流,如视频流、音频流、字幕流等。常见的容器格式包括MP4、MKV、AVI、FLV等。容器本身并不包含实际的媒体数据,而是包含了媒体数据的元数据和索引信息。实际的媒体数据通常是经过编码的,例如视频数据可能是H.264编码的,音频数据可能是AAC编码的。容器的作用是将这些编码后的数据流组合在一起,并提供必要的元数据和索引信息,以便播放器能够正确解码和播放这些数据。

4.1MP4介绍

MP4(MPEG-4 Part 14)是一种常见的多媒体容器格式,广泛用于存储和传输视频、音频和其他多媒体数据。MP4容器的设计目的是提供高效的数据存储和传输,同时支持多种编码格式。MP4容器的结构相对复杂,包含了多个层次的元数据和索引信息,以便播放器能够快速定位和解码媒体数据。MP4容器的设计考虑了多种应用场景,如流媒体、存储和传输,因此具有较高的兼容性和灵活性。MP4容器的广泛应用使其成为多媒体数据存储和传输的重要格式。

4.2MP4文件结构

在这里插入图片描述
在这里插入图片描述

MP4文件结构详解

1.主要Box及其作用

1.1 MP4

  • 全程: MP4 File Structure
  • 作用: MP4文件的根容器,包含所有其他Box。

1.2 FTYP

  • 全程: File Type Box
  • 作用: 描述文件的类型和兼容性。

1.3 MOOV

  • 全程: Movie Box
  • 作用: 包含电影的元数据,如音频信息、视频信息、时间信息、轨道信息等。

1.4 MDAT

  • 全程: Media Data Box
  • 作用: 存储实际的媒体数据,如视频帧和音频帧。音视频数据是以chuck为单位存储的,每个chuck包含多个sample。存储的位置可以通过stco获取

2.MOOV Box的子Box

2.1 MVHD

  • 全程: Movie Header Box
  • 作用: 包含电影的全局信息,如时间刻度、时长等。

2.2 TRAK

  • 全程: Track Box
  • 作用: 描述一个轨道的信息,如视频轨道或音频轨道。

3.TRAK Box的子Box

3.1 TKHD

  • 全程: Track Header Box
  • 作用: 包含轨道的头信息,如轨道ID、时长、音量、视频宽高等。

3.2 MDIA

  • 全程: Media Box
  • 作用: 包含媒体的信息,如媒体类型、媒体头等。

4.MDIA Box的子Box

4.1 MDHD

  • 全程: Media Header Box
  • 作用: 包含媒体的头信息,如时间刻度、时长等。这个时长指的是改轨道的时长

4.2 HDLR

  • 全程: Handler Reference Box
  • 作用: 描述媒体的处理程序,如视频处理程序或音频处理程序。

4.3 MINF

  • 全程: Media Information Box
  • 作用: 包含媒体的详细信息,如视频媒体信息或音频媒体信息。

5.MINF Box的子Box

5.1 VMHD

  • 全程: Video Media Header Box
  • 作用: 包含视频媒体的头信息,如图形模式等。

5.2 SMHD

  • 全程: Sound Media Header Box
  • 作用: 包含音频媒体的头信息,如平衡等。

5.3 DINF

  • 全程: Data Information Box
  • 作用: 包含数据的信息,如数据引用等。

5.4 STBL

  • 全程: Sample Table Box
  • 作用: 包含样本表的信息,如样本描述、时间戳等。

6.STBL Box的子Box

6.1 STSD

  • 全程: Sample Description Box
  • 作用: 包含样本的描述信息,如编码类型等。

6.2 STTS

  • 全程: Time-to-Sample Box
  • 作用: 包含样本的sample个数与每个sample持续的时间。已time_scale为单位

6.3 STSC

  • 全程: Sample-to-Chunk Box
  • 作用: 描述样本到块的映射关系。

6.4 STSZ

  • 全程: Sample Size Box
  • 作用: 包含样本的大小信息。

6.5 STCO

  • 全程: Chunk Offset Box
  • 作用: 包含块的偏移量信息。
  • 6.6 STSS

  • 全程: Sync Sample Box
  • 作用: 包含关键帧在哪个Chuck的信息。
  • 6.7 CTTX

  • 全程: Composition Time to Sample Box
  • 作用: 用于描述显示时间戳(PTS)和解码时间戳(DTS)之间的关系。它的主要作用是处理B帧(双向预测帧)的时间戳问题。

MP4数据存储为什么用chuck为单位,而不是使用sample为单位?

1.1 提高数据读取效率

  • 减少I/O操作:将多个sample打包成一个chunk,可以减少磁盘I/O操作的次数。读取一个chunk(包含多个sample)比逐个读取sample更高效。
  • 连续存储chunk的设计使得数据在磁盘上连续存储,减少了文件碎片化,从而提高了读取效率。

1.2 优化随机访问

  • 快速定位:通过STCO(Chunk Offset Box)可以快速定位到某个chunk的起始位置,结合STSC(Sample-to-Chunk Box)可以快速找到目标sample
  • 关键帧定位STSS(Sync Sample Box)记录了关键帧所在的chunk,便于实现视频的随机访问和快速定位。

1.3 简化数据管理

  • 减少元数据开销:将多个sample打包成一个chunk,可以减少元数据的存储开销。例如,STCO只需要记录chunk的偏移量,而不需要为每个sample单独记录偏移量。
  • 便于流媒体传输chunk的设计使得流媒体传输更加高效,可以按chunk为单位进行传输,而不是逐个sample传输。

1.4 优化存储空间

  • 压缩效率:将多个sample打包成一个chunk,可以提高数据的压缩效率,减少存储空间的占用。
  • 减少冗余chunk的设计可以减少文件中的冗余数据,使得文件更加紧凑。

ts文件结构详解

ts包可以包含多种不同的table,比如:pat、pmt、sdt、nit、tot等。这些table大多数是与DTMB有关我们不做重点分析。
ts包也可以包含多媒体数据,比如:视频、音频、字幕等。这些数据以ES(Encrypted Stream)的形式存储在pes包中,在由ts包中进行封装。结构如下图
在这里插入图片描述

从上图中我们可以看出音视频数据会被编码器封装为ES结构,然后通过PES打包器生成为PES结构,在通过TS打包器封装为TS包。

1.1 TS包结构

以ts为后缀名字的文件通常是TS文件。TS文件是由一个个TS包组成的。TS包是有固定大小的,一般为188字节。TS包的结构如下:
在这里插入图片描述

可以看一个TS包是固定字节188,并且由TS包头、TS包负载、CRC组成。我们关注的多媒体数据就在这个TS包的负载中。

1.2 PES包结构

PES包是TS包负载中包含的多媒体数据,PES包的结构如下:
在这里插入图片描述

PES由包起始码前缀、流id、PES长度、PES头、PES数据组成。PES数据数据包含的就是ES数据了。

1.3 如何查找到PES包(查找指定的audio/video数据)

1.3.1 问题引入

大家可能会有疑问:既然可以通过PES包的起始码前缀判断是否为PES包,为什么还需要专门讨论如何查找指定的PES包呢?要回答这个问题,我们需要先了解TS流在DTMB(地面数字多媒体广播)中的应用场景。

1.3.2 DTMB背景介绍

DTMB(GB 20600-2006,全称Digital Terrestrial Multimedia Broadcast,即地面数字多媒体广播),原名DMB-T/H(Digital Multimedia Broadcast-Terrestrial/Handheld,即数字多媒体广播-地面/手持),是中国制定的数字电视和流动数字广播标准。简单来说,DTMB就是我们以前使用的广播电视系统。

1.3.3 TS流的多路复用特性

在DTMB中,一个频点下可能包含多个频道,每个频道又包含多个节目,而每个节目可能包含多个流(如音频流、视频流、字幕流等)。因此,接收到的TS流实际上是多个频道数据的混合体,其中包含了大量不同频道的PES包。

1.3.4 如何查找指定的PES包?

为了从混合的TS流中提取出我们需要的PES包,需要使用PID(Packet Identifier)。PID是在PMT(Program Map Table)中定义的,用于标识不同的媒体流。例如:

一个节目可能包含一个音频流、一个视频流和一个字幕流,分别对应三个不同的PID。
在接收TS流时,通过PID可以快速定位到目标TS包,进而提取出对应的PES包。

1.3.5 解复用过程

解复用的核心步骤如下:

根据PID过滤TS包:从混合的TS流中提取出目标PID对应的TS包。
合并TS包:由于音视频帧的数据量较大,通常会被分割成多个TS包传输,因此需要将这些TS包合并成一个完整的PES包。
提取PES包:从合并后的TS包中剥离出PES包,供后续解码使用。
6. FFmpeg的简化处理
在使用FFmpeg时,解复用过程已经被封装在API中。例如,av_read_frame函数可以直接返回一帧完整的可解码数据,无需手动处理TS包的合并和PES包的提取。

TS与MP4的区别与使用场景

1. TS格式的特点与使用场景

定义与用途

TS格式主要用于流媒体传输,如数字电视广播、网络直播和卫星电视等场景。它支持多路复用、错误恢复和时间戳等功能,适合在带宽有限的情况下进行高效传输。

技术特点

  • TS文件由多个固定大小的包组成(每个包188字节),每个包包含媒体元数据,这使得TS文件即使损坏也能部分播放。
  • TS格式支持边下载边播放,具有较好的容错能力。
  • TS文件通常使用MPEG-2编码,但也可以支持其他编码格式。

兼容性

TS格式的兼容性较差,许多现代设备(如iPhone、Android手机)不支持直接播放TS文件,需要额外的软件或插件。

适用场景

TS格式广泛应用于广播和流媒体传输领域,例如HLS(HTTP Live Streaming)协议中常使用TS作为容器格式。


2. MP4格式的特点与使用场景

定义与用途

MP4是一种通用的多媒体容器格式,适用于存储各种类型的媒体数据,包括视频、音频、字幕和图像等。

技术特点

  • MP4文件是基于文件的,所有媒体信息存储在一个文件中,便于离线播放。
  • MP4支持多种编码格式,如H.264、H.265、AAC等,且文件体积相对较小。
  • MP4格式的索引信息存储在文件尾部,这可能导致部分文件无法在浏览器中直接播放。

兼容性

MP4格式的兼容性极强,几乎所有平台和设备都支持MP4文件,包括PC、手机、平板电脑和流媒体设备。

适用场景

MP4格式适用于个人视频制作、网络视频分享、电影存储和在线流媒体服务等场景。


3. TS与MP4的主要区别

特性TS格式MP4格式
用途主要用于流媒体传输(如广播、直播)。通用多媒体存储和播放(如个人视频、电影、网络视频)。
技术特点支持多路复用、错误恢复、时间戳;包大小固定(188字节)。文件式存储,索引信息在文件尾部;支持多种编码格式。
兼容性兼容性较差,需额外软件支持。兼容性极强,几乎所有平台和设备支持。
适用场景广播、流媒体传输(如HLS协议)。个人视频制作、网络视频分享、电影存储等。
文件大小文件较大,占用更多空间。文件较小,体积更高效。
播放方式支持边下载边播放,适合网络传输。文件加载完成后才能播放。

4. 总结

TS格式更适合流媒体传输和广播场景,具有高效的传输能力和较强的容错能力,但兼容性较差;而MP4格式则更通用,适用于个人视频制作和离线播放,兼容性极强。根据具体需求选择合适的容器格式是关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值