【FFmpeg实战】MP4封装格式分析

news2024/11/19 6:42:40

原文地址:https://www.cnblogs.com/moonwalk/p/16244932.html

解析工具:

  • https://gpac.github.io/mp4box.js/test/filereader.html (mp4box)

1. 概述

mp4 容器格式相较于 flv、ts 容器格式来说,其定义较为复杂,本篇文章主要记录自己的学习理解。

2. mp4 结构概览

一个 mp4 文件可以看作有两个大类:

  • 记录媒体信息相关的部分
  • 媒体负载部分

典型结构如下:

  +-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  ftyp  |  moov |  mdat  |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+

其中:

  • ftyp(file type box),文件头,记录一些兼容性信息
  • moov(movie box),记录媒体信息
  • mdat(media data),媒体负载

mp4box 图示如下:

img

编辑

添加图片注释,不超过 140 字(可选)

3. box 结构

mp4 封装格式采用称为 box 的结构来组织数据。 结构如下:

  +-+-+-+-+-+-+-+-+-+-+
  |  header  |  body  |
  +-+-+-+-+-+-+-+-+-+-+

其它所有 box 都在语法上继承自此基本 box 结构。

3.1 box header

box 分为普通 box 和 fullbox。 普通 box header 结构如下:

字段类型描述
size4 Bytes包含 box header 的整个 box 的大小
type4 Bytes4 个 ascii 值,如果是 “uuid”,则表示此 box 为用户自定义,可忽略
large size8 Bytessize=1 时才有的字段,用于扩展,例如 mdat box 会需要此字段

fullbox 在上面的基础上新增了 2 个字段:

字段类型描述
version1 Bytes版本号
flags3 Bytes标识

3.2 box body

一个 box 可能会包含其它多个 box,此种 box 称为 container box。 因此 box body 可能是一种具体 box 类型,也有可能是其它 box。

4. ftyp(File Type Box)

ftyp 一般出现在文件的开头,用来指示该 mp4 文件使用的标准规范:

字段类型描述
major_brand4 bytes主版本
minor_version4 bytes次版本
compatible_brands[]4 bytes指定兼容的版本,注意此字段是一个 list,即可以包含多个 4 bytes 版本号

一个示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

5. moov(Movie Box)

moov 是一个 container box,一个文件只有一个,其包含的所有 box 用于描述媒体信息。 moov 的位置可以紧随着 ftyp 出现,也可以出现在文件末尾. 由于是一个 container box,所以除了 box header,其 box body 就是其它的 box。 一个示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

这些 box 并列出现,其中:

  • mvhd(moov header),用于简单描述一些所有媒体共享的信息
  • trak,即 track,轨道,用于描述音频流或视频流信息,可以有多个轨道,如上出现了 2 次,分别表示一路音频和一路视频流
  • udta(userdata),用户自定义,可忽略

5.1 mvhd(Movie Header Box)

mvhd 作为媒体信息的 header 出现(注意此 header 不是 box header,而是 moov 媒体信息的 header),用于描述一些所有媒体共享的基本信息。 mvhd 语法继承自 fullbox,注意下述示例出现的 version 和 flags 字段属于 fullbox header。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
creation_time64/32 bit创建时间,当 version=0 时取 32bit
modification_time64/32 bit修改时间,当 version=0 时取 32bit
timescale32 bit时间基
duration64/32 bit文件时长,当 version=0 时取 32bit
rate32 bit播放速率,默认取 0x00010000,即 1.0
volume16 bit音量,默认取 0x0100,即 1.0
reserved16 bit0
reserved2 x 32 bit0
matrix9 x 32 bit可忽略
pre_defined6 x 32 bit0
next_track_ID32 bit下一个紧邻的 track box id

6. trak

trak box 是一个 container box,其子 box 包含了该 track 的媒体信息。 一个 mp4 文件可以包含多个 track,track之间是独立的,trak box 用于描述每一路媒体流。 一个示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

其中:

  • tkhd(track header box),用于简单描述该路媒体流的信息
  • edts(),
  • mdia(media box),用于详细描述该路媒体流的信息

6.1 tkhd(track header box)

tkhd 作为媒体信息的 header 出现(注意此 header 不是 box header,而是 track 媒体信息的 header),用于描述一些该 track 的基本信息。 tkhd 语法继承自 fullbox,注意下述示例出现的 version 和 flags 字段属于 fullbox header。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
creation_time64/32 bit创建时间,当 version=0 时取 32bit
modification_time64/32 bit修改时间,当 version=0 时取 32bit
track_ID32 bit本 track id
reserved32 bit0
duration64/32 bit本 track 时长,当 version=0 时取 32bit
reserved2 x 32 bit0
layer16 bit
alternate_group16 bit
volume16 bit音量,如果是 audio track,则为 0x0100,即 1.0,否则取 0
reserved16 bit0
matrix9 x 32 bit可忽略
width32 bit宽,[16.16] 格式,不必与sample的像素尺寸一致,用于播放时的展示宽高
height32 bit高,[16.16] 格式 ,不必与sample的像素尺寸一致,用于播放时的展示宽高

6.2 edts

6.3 mdia(media box)

mdia box 是一个 container box,其子 box 描述 track 更详细的媒体信息。 一个示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

其中:

  • mdhd(Media Header Box),用于简单描述该路媒体流的信息
  • hdlr(Handler Reference Box),主要定义了 track 类型
  • stbl(Media Information Box),用于描述该路媒体流的解码相关信息和音视频位置等信息

6.3.1 mdhd(Media Header Box)

mdhd 作为媒体信息的 header 出现(注意此 header 不是 box header,而是 media 媒体信息的 header),用于描述一些该 track 的基本信息。 mdhd 语法继承自 fullbox,注意下述示例出现的 version 和 flags 字段属于 fullbox header。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
creation_time64/32 bit创建时间,当 version=0 时取 32bit
modification_time64/32 bit修改时间,当 version=0 时取 32bit
timescale32 bit时间基,同 mvhd 中 timescale
duration64/32 bit本 track 时长,当 version=0 时取 32bit
pad1 bit0
language3 x 5 bit最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)
pre_defined16 bit0

6.3.2 hdlr(Handler Reference Box)

hdlr 主要定义了 track 类型。 hdlr 语法继承自 fullbox,注意下述示例出现的 version 和 flags 字段属于 fullbox header。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
pre_defined32 bit0
handler_type32 bit取值为 vide:Video track,soun:Audio track,hint:Hint track,meta:Timed Metadata track,auxv:Auxiliary Video track
reserved3 x 32 bit0
name不定长度自定义名称,以 \0 结尾

7. 音视频 frame 与 sample、chunk 的关系

在继续介绍 stbl box 之前,需要先介绍一下 mp4 中定义的 sample 与 chunk:

  • sample,ISO/IEC 14496-12 中定义 samples 之间不能共享同一个时间戳,因此,在音视频 track 中,一个 sample 代表一个视频或音频帧
  • chunk,多个 sample 的集合,实际上音视频 track 中,chunk 与 sample 一一对应

8. stbl(Media Information Box)

stbl box 是一个 container box,是整个 track 中最重要的一个 box,其子 box 描述了该路媒体流的解码相关信息、音视频位置信息、时间戳信息等。 一个示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

其中:

  • stsd(sample description box),存储了编码类型和初始化解码器需要的信息,并与具体编解码器类型有关
  • stts(time to sample box),存储了该 track 每个 sample 到 dts 的时间映射关系
  • stss(sync sample box),针对视频 track,关键帧所属sample 的序号
  • ctts(composition time to sample box),存储了该 track 中,每个 sample 的 cts 与 dts 的时间差
  • stsc/stz2(sample to chunk box),存储了该 track 中每个 sample 与 chunk 的映射关系
  • stsz(sample size box),存储了该 track 中每个 sample 的字节大小
  • stco/co64(chunk offset box),存储了该 track 中每个 chunk 在文件中的偏移

8.1 stsd(sample description box)

stsd 是个 container box,其存储了编码类型和初始化解码器需要的信息,并与具体编解码器类型有关:

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bitentry 个数
开始循环
AudioSampleEntry()不定大小子 box,当 handler_type=‘soun’ 时才有
VisualSampleEntry()不定大小子 box,当 handler_type=‘vide’ 时才有
HintSampleEntry()不定大小子 box,当 handler_type=‘hint’ 时才有
MetadataSampleEntry()不定大小子 box,当 handler_type=‘meta’ 时才有
结束循环

8.1.1 h264 stsd

对于 h264 视频,典型结构如下:

img

编辑

添加图片注释,不超过 140 字(可选)

其上(只列出 avc1 与 avcC,其余 box 可忽略):

  • avc1,是 avc/h264/mpeg-4 part 10 视频编解码格式的代称,是一个 container box,但是 box body 也携带自身的信息
字段类型描述
reserved6 x 8 bit0
data_reference_index16 bit
pre_defined16 bit0
reserved16 bit0
pre_defined3 x 32 bit0
width16 bit像素宽度
height16 bit像素高度
horizresolution32 bit每英寸的像素值(dpi),[16.16]格式的数据,固定为 0x00480000,72 dpi
vertresolution32 bit每英寸的像素值(dpi),[16.16]格式的数据,固定为 0x00480000,72 dpi
reserved32 bit0
frame_count16 bit每个 sample 中的视频帧数,固定为 1
compressorname32 bit0
depth16 bit0x0018,rgb24 位深
pre_defined16 bit-1
  • avcC(AVC Video Stream Definition Box),存储 sps && pps,即在 ISO/IEC 14496-15 中定义的 AVCDecoderConfigurationRecord 结构
字段类型描述
configurationVersion8 bit固定 1
AVCProfileIndication8 bit编码时设置的 profile,例如 base、main、high 等,具体参见 ISO_IEC_14496-10-AVC-2003.pdf, page 45
profile_compatibility8 bit
AVCLevelIndication8 bit编码时设置的 level
reserved6 bit'111111’b
lengthSizeMinusOne2 bit
reserved3 bit'111’b
numOfSequenceParameterSets8 bitsps 个数,一般为 1
sps 循环开始
sequenceParameterSetLength16 bit
sps8 * sequenceParameterSetLengthsps
sps 循环结束
numOfPictureParameterSets8 bitpps 个数,一般为 1
pps 循环开始
pictureParameterSetLength16 bit
pps8 * pictureParameterSetLengthpps
pps 循环结束

在 srs 中,解析 avcc/AVCDecoderConfigurationRecord 结构解析参见 srs/trunk/src/kernel/srs_kerner_codec.cpp::SrsFormat::avc_demux_sps_pps() 函数。

8.1.2 aac stsd

对于 aac 音频,典型结构如下:

img

编辑

添加图片注释,不超过 140 字(可选)

可以看到,aac stsd 结构比较复杂,box 众多。实际上,在 ISO/IEC 14496-3 中,定义了 AudioSpecificConfig 类型,aac stsd 结构主要信息就来自 AudioSpecificConfig。 具体不做分析,可以参看 srs 中:

  • 解析 AudioSpecificConfig 结构的 srs/trunk/src/kernel/srs_kerner_codec.cpp::SrsFormat::audio_aac_sequence_header_demux() 函数
  • 封装 aac stsd 结构的 srs/trunk/src/kernel/srs_kernel_mp4.cpp::SrsMp4Encoder::flush() 函数

8.2 stts(time to sample box)

存储了该 track 每个 sample 到 dts 的时间映射关系:

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
sample_count32 bit播放时长为 sample_delta 的连续 sample 个数
sample_delta32 bit单个 sample 的播放时长,单位为 timescale
结束循环

这里为了节约条目的个数,采用了压缩存储的方式,即 sample_count 个连续的 sample 如果 sample_delta 时长一样,那么用一个条目就能表示了。 一个音频 track 的示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

一个视频 track 的示例如下:

img

编辑

添加图片注释,不超过 140 字(可选)

8.3 ctts(composition time to sample box)

存储了该 track 中,每个 sample 的 pts 与 dts 时间差(cts = pts - dts):

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
sample_count32 bitcts 为 sample_offset 的连续 sample 个数
sample_offsetsigned/unsigned 32 bit单个 sample 的 cts,单位为 timescale。支持负数,当 version=1 时为 signed
结束循环

注意:

  • 此 box 在 dts 和 pts 不一样的情况下必须存在,如果一样,不用包含此 box
  • 如果 box 的 version=0,意味着所有 sample 都满足 pts >= dts,因而差值用一个无符号的数字表示。只要存在一个 pts < dts,那么必须使用 version=1、有符号差值来表示
  • 关于 ctts 的生成,可以参看 srs/trunk/src/kernel/srs_kernel_mp4.cpp::SrsMp4SampleManager::write_track() 函数 pts、dts、cts 满足公式:pts - dts = cts

8.4 stss(sync sample box)

针对视频 track,关键帧所属sample 的序号。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
sample_number32 bitsample 计数,从 1 开始
结束循环

一个视频示例如下:

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

8.5 stsc/stz2(sample to chunk box)

存储了该 track 中每个 sample 与 chunk 的映射关系。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
first_chunk32 bit一组 chunk 的第一个 chunk 的序号,chunk 的编号从 1 开始
samples_per_chunk32 bit每个 chunk 有多少个 sample
sample_description_index32 bitstsd box 中 sample desc 信息的索引
结束循环

一个音频示例如下:

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

  • 第一组 chunk 的 first_chunk 序号为 1,每个 chunk 的 sample 个数为 1,因为第二组 chunk 的 first_chunk 序号为 2,可知第一组 chunk 中只有一个 chunk
  • 第二组 chunk 的 first_chunk 序号为 2,每个 chunk 的 sample 个数为 2,因为第三组 chunk 的 first_chunk 序号为 24,可知第二组 chunk 中有 22 个 chunk,有 44 个 sample

8.6 stsz(sample size box)

存储了该 track 中每个 sample 的字节大小。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
sample_size32 bit指定默认的 sample 字节大小,如果所有 sample 的大小不一样,这个字段为 0
sample_count32 bittrack 中 sample 的数量
开始循环
entry_size32 bit每个 sample 的字节大小
结束循环

8.7 stco/co64(chunk offset box)

存储了该 track 中每个 chunk 在文件中的偏移。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit
开始循环
chunk_offset32 bitchunk 在文件中的位置
结束循环

9. mdat

mdat 也是一个 box,拥有 box header 和 box body。 mdat 可以引用外部的数据,参见 moov --> udta --> meta,这里不讨论,只讨论数据存储在本文件中的形式。 对于 box body 部分,采用一个一个 samples 的形式进行存储,即一个一个音频帧或视频帧的形式进行存储。 码流组织方式采用 avcc 格式,即 AUD + slice size + slice 的形式。

9.1 通过时间进行定位寻址/随机访问

参考 https://www.jianshu.com/p/529c3729f357 6.2 节

  >>> 音视频开发 视频教程: https://ke.qq.com/course/3202131?flowToken=1031864 
  >>> 音视频开发学习资料、教学视频,免费分享有需要的可以自行添加学习交流群: 739729163  领取

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/691781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.计算机是如何工作的(上)

文章目录 1.计算机发展史2.冯诺依曼体系&#xff08;Von Neumann Architecture&#xff09;3.CPU 基本工作流程3.1逻辑门3.1.1电子开关 —— 机械继电器(Mechanical Relay)3.1.2门电路(Gate Circuit) 3.2算术逻辑单元 ALU&#xff08;Arithmetic & Logic Unit&#xff09;3…

BossPlayerCTF 靶场

sudo nmap -sn 192.168.28.0/24 sudo nmap -sT --min-rate 10000 -p- 192.168.28.40 sudo nmap -sT -sV -sC -O -p22,80 192.168.28.40 -oA nmapscan/detail sudo nmap --scriptvuln -p22,80 192.168.28.40 -oA nmapscan/vuln 访问80 查看web源码&#xff1a; robots.txt ec…

AI EXPO 2023 | 图技术激活数据资产论坛圆满落幕

2023年6月25日下午&#xff0c;由新一代人工智能产业技术创新战略联盟、苏州市人工智能协同创新中心与苏州市大数据服务中心协会联合主办&#xff0c;浙江创邻科技有限公司承办的「2023全球人工智能产品应用博览会-图技术激活数据资产主题论坛」在苏州国际博览中心圆满落幕&…

JavaWeb小记——重定向和内部转发

目录 重定向 原理图 重定向语句 重定向特点 内部转发 原理图 请求转发特点 路径的书写 请求域对象request 特点 请求转发特点 重定向特点 重定向 原理图 重定向语句 response.setStatus(302); response.setHeader("location","http://www.baidu.c…

kubectl get cs显示unhealthy的解决办法

01、问题描述 使用kubectl get cs查看K8s组件状态&#xff0c;发现scheduler和controller-manager状态为Unhealthy&#xff0c;但集群可以正常使用。 [rootk8s-master ~]# kubectl get cs Warning: v1 ComponentStatus is deprecated in v1.19 NAME STATUS …

matplotlib——2. 形状和路径(Shape and Collection)底纹(hatch)

文章目录 1. 形状和路径1.1 PatchCollection替换热力图数字1.1.1原始的数字代码1.1.2 替换为PatchCollection的代码 1.2 PatchCollection绘制目标检测&#xff08;COCO&#xff09;标签1.3 PatchCollection绘制分割&#xff08;COCO&#xff09;标签 2. 底纹&#xff08;hatch&…

搭建Zabbix服务(Linux系统)

环境&#xff1a; centos7、lamp、防火墙关闭、selinux关闭 配置阿里云zabbix yum源 [rootchenshuyi ~]# rpm -ivh https://mirrors.aliyun.com/zabbix/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm 获取https://mirrors.aliyun.com/zabbix/zabbix/…

开启iis服务器通过php获取MySQL数据

开启iis服务器通过php获取MySQL数据 第一步开启iis服务器。 具体的可以查看这个&#xff1a;http://www.wokk.cn/40547.html 1.全部勾选,把万维网服务和web管理工具全部勾选。 2.添加网站&#xff0c;在网站这里添加网站&#xff0c;物理连接路径为你的网站存放的根目录。 3…

sql知识集锦

sql执行顺序 SELECT 的执行顺序 关键字的顺序是不能颠倒的&#xff1a; SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … 2.SELECT 语句的执行顺序&#xff08;在 MySQL 和 Oracle 中&#xff0c;SELECT 执行顺序基本相同&#xff09;&#xff1a; FROM >…

基于FPGA的永磁同步伺服控制系统的设计,在FPGA实现了伺服电机的矢量控制, 坐标变换,电流环,速度环,位置环,电机反馈接口,SVPWM

一个基于FPGA的永磁同步伺服控制系统&#xff0c;利用Verilog语言在FPGA上实现了伺服电机的矢量控制、坐标变换、电流环、速度环、位置环以及电机反馈接口。这个系统具有很高的研究价值。 涉及到的知识点和领域范围主要包括&#xff1a;FPGA&#xff08;现场可编程门阵列&…

2024广西大学计算机考研828 重点知识点分享 经验分享

这是广西大学828的考试大纲和参考书目。其实细看考试内容&#xff0c;第一点“计算机程序设计基础知识”的内容是比较散的&#xff0c;很难从给定的参考书目中的固定的一章或一节找到相关知识点&#xff0c;有的能找到&#xff0c;就是分散的比较乱&#xff0c;有的甚至都没有&…

动态规划入门-数据结构与算法教程

动态规划&#xff08;DP&#xff09;是一种在多项式时间内解决某些特定类型问题的技术。动态规划解决方案比指数蛮力法更快&#xff0c;并且可以很容易地证明其正确性。 动态规划主要是对普通递归的优化。只要我们看到一个递归解决方案重复调用相同的输入&#xff0c;我们就可以…

软考电子商务设计师备考资料

中级科目还好&#xff0c;难度肯定是有点的&#xff0c;而且电子商务设计师科目是近几年新增的&#xff0c;网上资料也比较少 电子商务设计可以理解为网页设计和平面设计的结合,但同时增加了用户体验和人机交互的一-些概念,互联网变成了传播&#xff0c;最终目的是销售商品.所…

nginx配置开机启动(Windows环境)

文章目录 1、下载nginx&#xff0c;并解压2、配置nginx.conf&#xff0c;并启动Nginx3、开机自启动 1、下载nginx&#xff0c;并解压 2、配置nginx.conf&#xff0c;并启动Nginx 两种方法&#xff1a; 方法一&#xff1a;直接双击nginx.exe&#xff0c;双击后一个黑色弹窗一闪…

Redis布隆过滤器详解

目录 一、前言二、RedisBloom 安装与使用三、RedisBloom 常用命令汇总四、通过 Jedis 使用 RedisBloom五、Redisson 封装的布隆过滤器六、使用哪种方式的过滤器比较好&#xff1f; 一、前言 布隆过滤器&#xff08;Bloom Filter&#xff09;是 Redis 4.0 版本提供的新功能&…

rewrite 重写跳转

Nginx Rewrite–重写跳转 Nginx Rewrite--重写跳转 一、概述&#xff1a;1.Rewrite 跳转场景&#xff1a;2.Rewrite 跳转实现&#xff1a;3.Rewrite 实际场景&#xff1a;4.Nginx正则表达式&#xff1a;5.Rewrite 命令&#xff1a;6.location分类&#xff1a;7.比较rewrite和l…

【FFmpeg实战】音视频解封装格式

转载自原文地址&#xff1a;https://www.cnblogs.com/zuojie/p/16798273.html 一、什么是封装格式 封装格式也称为容器&#xff0c;用于打包音频、视频以及字幕等等&#xff0c;比如常见的容器有MP4、MOV、WMV、FLV、AVI、MKV等等。容器里面装的是音视频的压缩帧&#xff0c;但…

5、基于Python所写的飞机大战设计

点击以下链接获取源码资源&#xff1a; https://download.csdn.net/download/qq_64505944/87953348?spm1001.2014.3001.5503 《彩图版飞机大战》程序使用说明 在PyCharm中运行《彩图版飞机大战》即可进入如图1所示的游戏界面。 图1 游戏主界面 具体的操作步骤如下&#xff…

ASEMI代理NXP可控硅BT139-600E参数,BT139-600E规格

编辑-Z BT139-600E参数描述&#xff1a; 型号&#xff1a;BT139-600E 断态重复峰值电压VDRM&#xff1a;600V RMS导通电流IT(RMS)&#xff1a;16A 非重复峰值导通电流ITSM&#xff1a;155A 峰值栅极电流IGM&#xff1a;2A 峰值栅极功率PGM&#xff1a;5W 储存温度Tstg&…

C++进阶—二叉搜索树Key、Key-Value模型应用及二叉树OJ(非递归实现遍历)

目录 1、二叉树搜索模型实现及应用场景 1. 二叉搜索树Key模型及其应用 2. 二叉搜索树Key-Value模型及其应用 2、二叉树OJ 2.1 根据二叉树创建字符串 2.2 二叉树的层序遍历I 2.3 二叉树的层序遍历II 2.4 二叉树的最近公共祖先 2.5 二叉搜索树及双向链表 2.6 从前序与中…