由金山云视频云技术团队提供:FFmpeg从入门到出家第三季;

为推进HEVC视频编码格式在直播方案中的落地,经过CDN联盟讨论,并和主流云服务厂商达成一致,规范了HEVC在RTMP/FLV中的扩展,具体修改内容见下。

4.1 FLV规范扩展

HEVC为视频编码格式,因此对FLV规范的扩展,只集中在Video Tag,其它部分,无任何改动。

4.1.1 支持HEVC的VideoTagHeader

扩展后的VideoTagHeader如下图所示(红色字体为新增内容):

图9. 支持HEVC的FLVTagHeader

修改点如下:

1、CodecID - 定义HEVC格式的值为12;

2、HEVCPacketType - 当CodecID == 12时,AVCPacketType为HEVCPacketType:

◦如果HEVCPacketType为0,表示HEVCVIDEOPACKET中存放的是HEVC sequence header;

◦如果HEVCPacketType为1,表示HEVCVIDEOPACKET中存放的是HEVC NALU;

◦如果HEVCPacketType为2,表示HEVCVIDEPACKET中存放的是HEVC end of sequence,即HEVCDecoderConfigurationRecord;

3、CompositionTime - 当CodecID == 12时,同样需要CompositionTime。

4.1.2 支持HEVC的VideoTagBody

当CodecID为12时,VideoTagBody中存放的就是HEVC视频帧内容。

扩展后的VideoTagBody如下图所示(红色字体为HEVC新增内容):

图10. 支持HEVC的VideoTagBody

4.2 FFmpeg中的修改

我们已在FFmpeg的各个版本上提供相关的完整修改,具体参见:https://github.com/ksvc/FFmpeg,完整patch获取及相关说明见:https://github.com/ksvc/FFmpeg/wiki。

由第二章节的阐述可知,FLV的解复用和复用功能代码分别在libavformt/flvdec.c和libavformat/flvenc.c中,扩展后的修改也都集中在这两个文件。本节将在FFmpeg3.3的基础上,说明修改的关键点。

4.2.1 编码类型定义

libavformat/flv.h中按照VideoTagHeader中的CodecID定义了一组视频编码格式的枚举值,扩展后的枚举定义如下:

enum {

FLV_CODECID_H263    = 2,FLV_CODECID_SCREEN  = 3,FLV_CODECID_VP6 = 4, FLV_CODECID_VP6A = 5, FLV_CODECID_SCREEN2 = 6, FLV_CODECID_H264 = 7, FLV_CODECID_REALH263= 8, FLV_CODECID_MPEG4 = 9, FLV_CODECID_HEVC = 12,

};

4.2.2 FLV demux

在解复用过程中,flv_read_packet方法是整个过程的核心,它里面完成了对每个Tag的读取和解析。

4.1.1中提到,如果HEVCPacketType为0时,表示HEVCVIDEOPACKET中存放的是HEVC sequence header,也就是HEVCDecoderConfigurationRecord,解码时需设置HEVCDecoderConfigurationRecord方能正确解码。

HEVC与AVC视频帧在FLV中的存放格式相同,所以只需在读取Video Tag的地方增加AV_CODEC_ID_HEVC的判断条件即可,调整后的代码如下:

if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||

st->codecpar->codec_id == AV_CODEC_ID_H264 ||

st->codecpar->codec_id == AV_CODEC_ID_HEVC ||

st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {

int type = avio_r8(s->pb);

size--;if (st->codecpar->codec_id == AV_CODEC_ID_H264 ||

st->codecpar->codec_id == AV_CODEC_ID_HEVC ||

st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {

     // sign extensionint32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;pts = dts + cts;if (cts< 0) { // dts might be wrong if (!flv->wrong_dts)

av_log(s, AV_LOG_WARNING,

"Negative cts, previous timestamps might be wrong.\n");

flv->wrong_dts = 1;

    } else if (FFABS(dts - pts) > 1000*60*15) {

av_log(s, AV_LOG_WARNING,

"invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);

dts = pts = AV_NOPTS_VALUE;

    }

}

if (type == 0 &&(!st->codecpar->extradata ||

st->codecpar->codec_id == AV_CODEC_ID_AAC ||

st->codecpar->codec_id == AV_CODEC_ID_HEVC ||

st->codecpar->codec_id == AV_CODEC_ID_H264)) {

AVDictionaryEntry *t;

   if (st->codecpar->extradata) {if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)return ret;ret = FFERROR_REDO;

goto leave;

   }if ((ret = flv_get_extradata(s, st, size)) < 0)return ret;……

}

}

AVCDecoderConfigurationRecord和HEVCDecoderConfigurationRecord都是存放在AVStream->AVCodecParameter->extradata中。

4.2.3 FLV mux

FLV mux的修改相对较多、header、packet、trailer中均有涉及。

4.2.3.1 write header

flv_write_header中主要完成了以下工作:

  1. 写入FLV Header;

  2. 写入Metadata;

  3. 如果音频编码格式为AAC,则写入第一个Audio Tag,其AudioTagBody中存放的是AAC sequence header;

  4. 如果视频编码格式为AVC,则写入第一个Video Tag,其中VideoTagBody中存放的是AVC sequence header。

同样,当视频编码格式HEVC时,也要写入第一个VideoTag,其中VideoTagBody中存放的是HEVCDecoderConfigurationRecord,修改点如下:

avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags

avio_w8(pb, 0); // AVC sequence header

avio_wb24(pb, 0); // composition time

if (par->codec_id == AV_CODEC_ID_HEVC)

ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);

else

ff_isom_write_avcc(pb, par->extradata, par->extradata_size);

ff_isom_write_hvcc的作用是将extradata转为HEVCDecoderConfigurationRecord结构并写入。

4.2.3.2 write packet

flv_write_packet的作用是写入音视频帧,其中有关写入video数据的地方,都需要加上AV_CODEC_ID_HEVC的判断条件,修改内容如下:

else if (par->codec_id == AV_CODEC_ID_HEVC ){if (par->extradata_size> 0 && *(uint8_t*)par->extradata != 1) if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0) return ret; }

ff_hevc_annexb2mp4_buf方法的作用是将Annex-B格式的HEVC视频帧转为HVCC格式。

AnnexB与AVCC/HVCC(ISO/IEC14496-15中所定义,通常也称为MPEG-4格式)的区别在于参数集与帧格式,AnnexB的参数集sps、pps以NAL的形式存在码流中(带内传输),以startcode分割NAL。而HVCC 的参数集存储在extradata中(带外传输),使用NALU长度(固定字节,通常为4字节,从extradata中解析)分隔NAL。

4.2.3.3 write trailer

结束时需要写入HEVC end of sequence,其格式与AVC end of sequence相同,直接复用即可,flv_write_trailer的修改内容如下:

if (par->codec_type == AVMEDIA_TYPE_VIDEO &&

       (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_MPEG4))

put_avc_eos_tag(pb, sc->last_ts);

5、结束语

本文只是简单介绍了如何在FFmpeg中扩展rtmp协议对HEVC编码格式的支持,而要将HEVC应用于直播整体方案,除推流端和播放端要提供相应能力外,源站、CDN、转码服务同样都需要提供这种能力。金山云的所有视频服务中,已完全支持HEVC视频编码格式,欢迎大家使用。

客户端的直播/短视频SDK,在适配了系统的HEVC硬编/解码能力外,还提供了高效的HEVC软编/解码方案,如果您感兴趣,可联系我们咨询或讨论。

转载于:https://www.cnblogs.com/KSC123/p/8316746.html

FFmpeg从入门到出家(HEVC在RTMP中的扩展)相关推荐

  1. FFmpeg代码导读——HEVC在RTMP中的扩展

    视频流媒体中视频数据的传输占据了绝大部分的带宽,如何提升编码效率.减小带宽使用.提升画面质量,成为音视频开发者努力的重点.HEVC编码格式的推出为此带来了突破点.对于直播而言,大部分推拉流协议是基于R ...

  2. FFmpeg代码导读系列(一,下半部)----HEVC在RTMP中的扩展

    金山云多媒体SDK团队在移动直播.短视频等项目中遇到了许多FFmpeg问题,特设立<FFmpeg从入门到出家>系列文稿,希望博君一笑的同时,能让大家对FFmpeg有更深入的了解. 先在前面 ...

  3. FFmpeg从入门到出家(背景介绍)

    金山云多媒体SDK团队在移动直播.短视频等项目中遇到了许多FFmpeg问题,特设立<FFmpeg从入门到出家>系列文稿,希望博君一笑的同时,能让大家对FFmpeg有更深入的了解. 视频流媒 ...

  4. FFmpeg从入门到出家(FLV文件结构解析)

    FLV(FLASH VIDEO),是一种常用的文件封装格式,目前国内外大部分视频分享网站都是采用的这种格式.其标准定义为<Adobe Flash Video File Format Specif ...

  5. FFmpeg从入门到精通:SEI那些事

    本文是"FFmpeg从入门到精通"系列的第三篇,由金山云供稿,并授权LiveVideoStack发布.此前两篇为FFmpeg代码导读--基础篇和FFmpeg代码导读--HEVC在R ...

  6. 支持HEVC/H265 RTMP接收的FFMPEG/FFPLAY WINDOWS版本

    本文镜像:https://linkpi.cn/archives/1249 本文链接:https://blog.csdn.net/weixin_45326556/article/details/1111 ...

  7. FFmpeg从入门到入魔(2):保存流到本地MP4

    1 . FFmpeg裁剪移植 之前我们简单地讲解了下如何在Linux系统中编译FFmpeg,但是编译出来的so体积太大,而且得到的多个so不便于使用.本节在此基础上,将详细讲解在编译FFmpeg时如何 ...

  8. FFmpeg从入门到精通读书笔记(1)

    笔者才开始学习音视频开发,FFmpeg从入门到精通读书笔记系列主要是基于阅读刘歧.赵文杰编著的<FFmpeg从入门到精通>以及雷霄骅博士博客总结写的入门心得体会. 官方文档资料 FFmpe ...

  9. 1 FFmpeg从入门到精通-FFmpeg简介

    1 FFmpeg从入门到精通-FFmpeg简介 2 FFmpeg从入门到精通-FFmpeg工具使用基础 3 FFmpeg从入门到精通-FFmpeg转封装 4 FFmpeg从入门到精通-FFmpeg转码 ...

最新文章

  1. 从LSTM到GRU基于门控的循环神经网络总结
  2. 鸿蒙系统手机还会出吗,华为最强手机即将到来,可能还有华为鸿蒙系统加入!你期待吗?...
  3. 【编译原理】递归下降的预测分析(真の能看懂~!)
  4. Apache Shiro Architecture--官方文档
  5. Spring全家桶中的日志框架
  6. SAP CRM WebClient UI运行时加载哪个configuration,到底是如何决定的
  7. Android 中文 API (16) —— AnalogClock
  8. exoplayer 纯java,Exoplayer不播放任何视频
  9. 好947 Mybatis 配置resultMap 带參数查询Map 注意selectOne数据库返回结果一条数据库 否则会报错...
  10. 大学生学科竞赛管理系统/竞赛管理系统的设计与实现
  11. 两种方法,word文件转换成PDF文件
  12. 如果你的电脑只能安装三个软件, 你会选择哪三个?
  13. 万年历(hao123)代码
  14. 用Burpsuite破解网站密码
  15. 优势比(Odds Ratios)
  16. 学校宿舍天翼校园网构建路由器
  17. 高德地图开发-- 自定义图标
  18. 关于虚拟机的十个基本小技巧
  19. 【用es6写个机选彩票】
  20. 台服天堂2更新服务器无响应,天堂2台服被限制怎么回事?该怎么解决?

热门文章

  1. Educational Codeforces Round 12 A. Buses Between Cities 水题
  2. PHP语言 -- 基础
  3. POJ 3982 序列 塔尔苏斯问题解决
  4. 【转】java提高篇(十)-----详解匿名内部类
  5. asp.net 创建文件夹时出错:未找到路径“D:\”的一部分。(asp.net 使用 FSO)
  6. 创建vue项目+总结使用(跨域问题+vue 创建)
  7. mybatis mapper绑定
  8. FTPFileUtil_FTP文件上传 (spring boot)
  9. uva 101 木块问题
  10. 二叉树最近公共祖先节点