第一篇主要介绍了Chrome加载音视频的缓冲控制机制和编解码基础,本篇将比较深入地介绍解码播放的过程。以Chromium 69版本做研究。
由于Chromium默认不能播放Mp4,所以需要需要改一下源码重新编译一下。
1. 编译一个能播放mp4的Chromium
自行编译出来的Chromium是无法播放mp4视频,在官网下载的也不行,终端会提示这个错误:
[69542:775:0714/132557.522659:ERROR:render_media_log.cc(30)] MediaEvent: PIPELINE_ERROR DEMUXER_ERROR_NO_SUPPORTED_STREAMS
说是在demux即多路解复用的时候发生了错误,不支持当前流格式,也就是Chromium不支持mp4格式的解析,这是为什么呢?经过一番搜索和摸索,发现只要把ffmpeg的编译模式从Chromium改成Chrome就可以。编辑third_party/ffmpeg/ffmpeg_options.gni这个文件,把前面几行代码改一下——把_default_ffmpeg_branding强制设置成Chrome,再重新编译一下就行了,如下代码所示:
# if (is_chrome_branded) {
_default_ffmpeg_branding = "Chrome"
# } else {
# _default_ffmpeg_branding = "Chromium"
# }复制代码
编译出来的Chromium就能播放视频了。Chromium工程的编译目标branding可以设置成Chrome(正式版)/Chromium/Chrome OS三种模式,ffmpeg的编译设定会根据这个branding类型自动选择它自己的branding,如上代码的判断,如果branding是Chrome,会额外多加一些解码器,就能够播放mp4了。
不过如果你想编译成正式版Chrome,由于缺少相关的主题theme文件,是编译不了的。
另外它还有一个proprietary_codecs的设置:
proprietary_codecs = is_chrome_branded || is_chromecast复制代码
编译正式版的Chrome会默认打开,它的作用是增加一些额外的解码器,如对EME(Encrypted Media Extensions)加密媒体扩展的支持。
最后一开始不能打开和能打开播放的效果对比如下图所示:
那么为什么Chromium不直接打开mp4支持呢,它可能受到mp4或者ffmpeg的一些开源协议和专利限制。
2. mp4格式和解复用
一个视频可以有3个轨道(Track):视频、音频和文本,但是数据的存储是一维的,从1个字节到第n个字节,那么视频应该放哪里,音频应该放哪里,mp4/avi等格式此做了规定,把视轨音轨合成一个mp4文件的过程就叫多路复用(mux),而把mp4文件里的音视频轨分离出来就叫多路解复用(demux),这两个词是从通信领域来的。
假设现在有个需求,需要取出用户上传视频的第一帧做为封面。这就要求我们去解析mp4文件,并做解码。
我们以这个 mountain.mp4时长为1s大小487kB的mp4视频做为研究对象,用sublime等编辑器打开显示其原始的二进制内容,如下图所示:
上图是用16进制表示的原始二进制内容,两个16进制(0000)就表示1个字节,如上图第4个字节是0x18。
6674 7970 => ftyp
ftyp盒子的作用是用来标志当前文件类型,紧接着的4个字节表示它是一个微软的MPEG-4格式,即平常说的mp4:
6d70 3432 => mp42
综上,第1个盒子整体解析如下图所示: