FFmpeg开发笔记(三十七)分析SRS对HLS协议里TS包的插帧操作
《FFmpeg开发实战:从零基础到短视频上线》一书的“2.1.2 音视频文件的封装格式”介绍了视频流的PS格式和TS格式。由于TS包的长度固定,从TS流的任一片段开始都能独立解码,因此可以把TS当成音视频文件的封装格式。
鉴于TS包的独立解码特性,HLS协议引入了TS格式作为传输单元。HLS协议的实现原理是对一个大的媒体分片,并将分片后的文件路径记录于m3u8文件,客户端依据该m3u8文件即可获取对应的分片列表,再依次播放分片内容。每个TS分片都以SPS与PPS等配置帧开头,其中指定了视频的规格信息及其编码参数,因此每个TS片段都能正常解析播放。关于SPS与PPS的详细说明参见之前的文章《解析H.264码流中的SPS帧和PPS帧》。
上述的分片文件便是一个个以TS格式封装的视频资源,那么当直播源来自一个MP4文件的时候,流媒体服务器又是怎么把MP4文件转化为一个个TS分片的呢?
以SRS为例,它在组装TS包时做了特殊处理,在每个TS包的开头位置,就自动插入SPS与PPS等配置帧。具体代码在SRS框架的trunk/src/main/srs_main_ingest_hls.cpp,查看该源码的SrsIngestHlsOutput::on_ts_video函数,找到以下的代码片段,可见程序在写入H.264流时,先写入SPS帧和PPS帧,再写入I帧、P帧和B帧。
if ((ret = write_h264_sps_pps(dts, pts)) != ERROR_SUCCESS) {
return ret;
}
if ((ret = write_h264_ipb_frame(ibps, frame_type, dts, pts)) != ERROR_SUCCESS) {
// drop the ts message.
if (ret == ERROR_H264_DROP_BEFORE_SPS_PPS) {
return ERROR_SUCCESS;
}
return ret;
}
找到write_h264_sps_pps函数的定义代码如下,发现函数内部在封装序列头时依次输入了SPS帧和PPS帧:
// h264 raw to h264 packet.
std::string sh;
if ((err = avc->mux_sequence_header(h264_sps, h264_pps, sh)) != srs_success) {
// TODO: FIXME: Use error
ret = srs_error_code(err);
srs_freep(err);
return ret;
}
进一步跟踪mux_sequence_header的定义来源,详细的定义代码在SRS框架的trunk/src/protocol/srs_protocol_raw_avc.cpp,查看该源码的SrsRawH264Stream::mux_sequence_header函数,找到以下的代码片段,可见程序依据ISO_IEC_14496-15的文档规范,先后写入了sequenceParameterSet的NAL单元(即SPS帧),以及pictureParameterSet的NAL单元(即PPS帧)。
// sps
if (true) {
// 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
// numOfSequenceParameterSets, always 1
stream.write_1bytes(uint8_t(0xe0 | 0x01));
// sequenceParameterSetLength
stream.write_2bytes((int16_t)sps.length());
// sequenceParameterSetNALUnit
stream.write_string(sps);
}
// pps
if (true) {
// 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
// numOfPictureParameterSets, always 1
stream.write_1bytes(0x01);
// pictureParameterSetLength
stream.write_2bytes((int16_t)pps.length());
// pictureParameterSetNALUnit
stream.write_string(pps);
}
由此可见,SRS在每个TS包头都写入了SPS帧和PPS帧,确保TS包是拥有SPS和PPS的完整H.264分片。只有加上SPS与PPS,客户端才能正常拉流解析数据,才能正常渲染视频画面。
更多详细的FFmpeg开发知识参见《FFmpeg开发实战:从零基础到短视频上线》一书。
FFmpeg开发笔记(三十七)分析SRS对HLS协议里TS包的插帧操作的更多相关文章
- FFmpeg开发笔记(三):ffmpeg介绍、windows编译以及开发环境搭建
前言 本篇章是对之前windows环境的补充,之前windows的是无需进行编译的,此篇使用源码进行编译,版本就使用3.4.8. FFmpeg简介 FFmpeg是领先的多媒体框架,能够解码 ...
- FFmpeg开发笔记(四):ffmpeg解码的基本流程详解
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- FFmpeg开发笔记(五):ffmpeg解码的基本流程详解(ffmpeg3新解码api)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放
前言 ffmpeg播放rtsp网络流和摄像头流. Demo 使用ffmpeg播放局域网rtsp1080p海康摄像头:延迟0.2s,存在马赛克 使用ffmpeg播放网络rtsp文件流 ...
- FFmpeg开发笔记(十):ffmpeg在ubuntu上的交叉编译移植到海思HI35xx平台
FFmpeg和SDL开发专栏(点击传送门) 上一篇:<FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放>下一篇:敬请期待 前言 将ffmpeg移植到海思H ...
- Django开发笔记三
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.基于类的方式重写登录:views.py: from ...
- 第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS
第三百三十七节,web爬虫讲解2—PhantomJS虚拟浏览器+selenium模块操作PhantomJS PhantomJS虚拟浏览器 phantomjs 是一个基于js的webkit内核无头浏览器 ...
- FFmpeg开发笔记(一)搭建Linux系统的开发环境
对于初学者来说,如何搭建FFmpeg的开发环境是个不小的拦路虎,因为FFmpeg用到了许多第三方开发包,所以要先编译这些第三方源码,之后才能给FFmpeg集成编译好的第三方库.不过考虑到刚开始仅仅调用 ...
- Java开发学习(三十七)----SpringBoot多环境配置及配置文件分类
一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配 ...
- FFmpeg开发笔记(二)搭建Windows系统的开发环境
由于Linux系统比较专业,个人电脑很少安装Linux,反而大都安装Windows系统,因此提高了FFmpeg的学习门槛,毕竟在Windows系统搭建FFmpeg的开发环境还是比较麻烦的.不过若有已经 ...
随机推荐
- NODEJS通过发送json数据查询目标服务,实现服务器状态监控,发现异常发送到微信群提醒
root@aea87fa6e6a2:/home/node# cat login2.js const request = require('request-promise'); const moment ...
- 全网首一份!你最需要的PPTP MS-CHAP V2 挑战响应编程模拟计算教程!代码基于RFC2759,附全部源码!
本文基于网络密码课上的实验 本来想水一水就过去,代码就网上找找,不行就GPT写,但是!一份都找不到,找到的代码都是跑不了的,总会是就是乱七八糟.所以准备认真的写一份. 代码编译成功的前提是要预先装好o ...
- LLM实战:当网页爬虫集成gpt3.5
1. 背景 最近本qiang~关注了一个开源项目Scrapegraph-ai,是关于网页爬虫结合LLM的项目,所以想一探究竟,毕竟当下及未来,LLM终将替代以往的方方面面. 这篇文章主要介绍下该项目, ...
- PHP做api开发时,签名验证你是怎么设计的
开发过程中,我们经常会与接口打交道,有的时候是调取别人网站的接口,有的时候是为他人提供自己网站的接口,但是在这调取的过程中都离不开签名验证. 我们在设计签名验证的时候,请注意要满足以下几点: 可变性: ...
- nohup Command [ Arg … ] [ & ]
nohup 英文全称:no hang up 不挂断的意思.退出终端不挂断程序的运行.在默认的情况下,会输出一个名叫 nohup.out 的文件到当前目录下.nohup Command [ Arg - ...
- KPM算法求字符串的最小周期证明
先给出公式 ans = n - LPS[n-1] 其中ans为最小周期,n为给出的由假设的周期字符串中提取出的子串长度,LPS为前缀函数,n-1为字符串最后的位置下标 证明如下 证明ans = n - ...
- 微服务实践k8s&dapr开发部署实验(2)状态管理
新建webapi项目 建项目时取消https支持,勾选docker支持, Program.cs中注释下面语句,这样部署后才能访问Swagger // Configure the HTTP reques ...
- 透过 Go 语言探索 Linux 网络通信的本质
前言 各种编程语言百花齐放.百家争鸣,但是 "万变不离其中".对于网络通信而言,每一种编程语言的实现方式都不一样:但其实,调用的底层逻辑都是一样的.linux 系统底层向上提供了统 ...
- redis 使用lua脚本 一次性获取多个hash key 字段值
客户端命令行代码: eval "local rst={};local field='schoolid'; for i,v in pairs(KEYS) do rst[i]=redis.cal ...
- 一种基于E3处理器平台的NAS完整方案(从电脑组装到网站部署)
一种基于E3处理器平台的NAS完整方案(从电脑组装到网站部署) 本文将简要简要介绍本人自建NAS的完整配置,截至发文此NAS已经连续良好运行一年,应当说具有良好的稳定性. 本文所述配置包含洋垃圾成分, ...