由金山云视频云技术团队提供: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 extension

     int32_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软编/解码方案,如果您感兴趣,可联系我们咨询或讨论。

FFmpeg从入门到出家(HEVC在RTMP中的扩展)的更多相关文章

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

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

  2. Windows下FFmpeg快速入门

    本系列文章导航 Windows下FFmpeg快速入门 ffmpeg参数解释 mencoder和ffmpeg参数详解(Java处理视频) Java 生成视频缩略图(ffmpeg) 使用ffmpeg进行视 ...

  3. Windows下FFmpeg高速入门

    本系列文章导航 Windows下FFmpeg高速入门 ffmpeg參数解释 mencoder和ffmpeg參数具体解释(Java处理视频) Java 生成视频缩略图(ffmpeg) 使用ffmpeg进 ...

  4. Windows下FFmpeg快速入门 <第二篇>

    FFmpeg简介 FFmpeg是什么? FFmpeg是用于录制.转换和流化音频和视频的完整解决方案, 包括 libavcodec ,一套领先的音/视频编解码类库.FFmpeg 在Linux上开发,当可 ...

  5. FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播

    文章来源:http://www.cuplayer.com/player/PlayerCode/RTSP/2014/0706/1419.html FFmpeg实现监控摄像头的RTSP协议转RTMP协议直 ...

  6. labview从入门到出家6(进阶篇)--移位寄存器的使用

    前面介绍了如何熟悉和使用Labview自带的库函数以及调试方式,大家后期基本可以凭借这两个方式从入门到出家了,哈哈,后面就靠各位同仁99%的努力了.这篇为啥要讲移位寄存器呢,主要是之前做的项目和经验告 ...

  7. labview从入门到出家5(进阶篇)--程序调试以及labview函数库的运用

    跟了前面几章的操作流程,相信大家对labview有了一定的认识.其实只要了解了labview的编程思路,再熟悉地运用各个变量,函数以及属性,那么我们就可以打开labview的大门了.跟其他编程语言一样 ...

  8. MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用

    摘要: 第一阶段1~10篇已经覆盖了MVC开发必要的基本知识. 第二阶段11-20篇将会侧重于专题的讲解,一篇文章解决一个实际问题. 根据园友的反馈, 本篇文章将会先对呼声最高的仓储模式进行讲解. 文 ...

  9. (转)RTMP中FLV流到标准h264、aac的转换

    这段时间,工作上的需要,在RTMP上做了flv流到标准h264.AAC的转换,服务器是开源项目CRTMPSERVER,客户端flex编写,视频编码h264,音频编码AAC,现将一些协议相关的东西记录如 ...

随机推荐

  1. jmeter测试https请求之导入证书

    jmeter测试https请求   公司最近在搞全站HTTPS改造,进一步提高网站的安全性,防止运营商劫持.那么,改造完成后,所有前后端的URL将全部为https. So ,研究下怎么用Jmeter访 ...

  2. LTE抛弃了CDMA?

    原文链接:https://blog.csdn.net/readhere/article/details/82764919 本文节选自<LTE教程:结构与实施> 大家都听说过这样的说法:LT ...

  3. 颜色空间模型 与 Opencv中的HSV模型范围

    颜色空间总结 RGB.HSV.YUV 什么是颜色 Wiki是这样说的:颜色或色彩是通过眼.脑和我们的生活经验所产生的一种对光的视觉效应.嗯,简单点说,颜色就是人对光的一种感觉,由大脑产生的一种感觉.感 ...

  4. Internet History, Technology, and Security(week6)——Technology: Transport Control Protocol(TCP)

    前言: 这周开始学习分层网络模型的第三层,传输层. Transport/Reliability: Transport Layer TCP层的目的是补偿IP层中可能出现的错误,并充分利用可用资源.由于I ...

  5. js返回上一页并刷新的几种方法

    1.返回上一页 1)<a href="javascript:history.go(-1)"></a> 2)<a href="javascri ...

  6. [LOJ2289][THUWC2017]在美妙的数学王国中畅游:Link-Cut Tree+泰勒展开

    分析 又有毒瘤出题人把数学题出在树上了. 根据泰勒展开,有: \[e^x=1+\frac{1}{1!}x+\frac{1}{2!}x^2+\frac{1}{3!}x^3+...\] \[sin(x)= ...

  7. Beauty Values

    Beauty Values 题意:给$n$个数, 定义它的Beauty Values为所有连续子区间的(区间长度*区间内不同数字的数目)求和 求Beauty Values A[i]数组表示数字i最近一 ...

  8. [CSP-S模拟测试]:连连看(图论+容斥)

    题目传送门(内部题74) 输入格式 输入文件$link.in$ 第一行三个整数$n,m,k$,之间用空格隔开,$n,m$表示地图行数和列数,$k$表示每个方块周围相邻的位置(至多有$4$个,至少有$2 ...

  9. gsxt滑动验证码

    最后,谈谈滑动验证码. 目前,工商网站已经全面改版,全部采用了滑动验证码,上面绝大多数思路都失效了.对于滑动验证码,网上能搜到的解决方案基本都是下载图片,还原图片,算出滑动距离,然后模拟js来进行拖动 ...

  10. React Native商城项目实战14 - 首页中间下部分

    1.MiddleBottomView.js /** * 首页中间下部分 */ import React, { Component } from 'react'; import { AppRegistr ...