From b1b6e683a96ef5d23a45762a07f8dda5417177bc Mon Sep 17 00:00:00 2001 From: Franken Zeng Date: Wed, 14 Jun 2017 21:38:56 +0800 Subject: [PATCH] The RTMP protocol extensions for H.265/HEVC --- libavformat/flv.h | 1 + libavformat/flvdec.c | 15 ++++++++++++--- libavformat/flvenc.c | 29 ++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/libavformat/flv.h b/libavformat/flv.h index df5ce3d17f8c7..089bc76972d48 100644 --- a/libavformat/flv.h +++ b/libavformat/flv.h @@ -109,6 +109,7 @@ enum { FLV_CODECID_H264 = 7, FLV_CODECID_REALH263= 8, FLV_CODECID_MPEG4 = 9, + FLV_CODECID_HEVC = 12, }; enum { diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 03bbf98d5e786..dc2a382fa27d6 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -36,6 +36,7 @@ #include "internal.h" #include "avio_internal.h" #include "flv.h" +#include "hevc.h" #define VALIDATE_INDEX_TS_THRESH 2500 @@ -238,6 +239,8 @@ static int flv_same_video_codec(AVCodecContext *vcodec, int flags) return vcodec->codec_id == AV_CODEC_ID_VP6A; case FLV_CODECID_H264: return vcodec->codec_id == AV_CODEC_ID_H264; + case FLV_CODECID_HEVC: + return vcodec->codec_id == AV_CODEC_ID_HEVC; default: return vcodec->codec_tag == flv_codecid; } @@ -282,6 +285,10 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, case FLV_CODECID_MPEG4: vcodec->codec_id = AV_CODEC_ID_MPEG4; return 3; + case FLV_CODECID_HEVC: + vcodec->codec_id = AV_CODEC_ID_HEVC; + vstream->need_parsing = AVSTREAM_PARSE_NONE; + return 3; // not 4, reading packet type will consume one byte default: avpriv_request_sample(s, "Video codec (%x)", flv_codecid); vcodec->codec_tag = flv_codecid; @@ -1050,10 +1057,12 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->codec->codec_id == AV_CODEC_ID_AAC || st->codec->codec_id == AV_CODEC_ID_H264 || - st->codec->codec_id == AV_CODEC_ID_MPEG4) { + st->codec->codec_id == AV_CODEC_ID_MPEG4 || + st->codec->codec_id == AV_CODEC_ID_HEVC) { int type = avio_r8(s->pb); size--; - if (st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_MPEG4) { + if (st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_MPEG4 + || st->codec->codec_id == AV_CODEC_ID_HEVC) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = dts + cts; @@ -1069,7 +1078,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) } } if (type == 0 && (!st->codec->extradata || st->codec->codec_id == AV_CODEC_ID_AAC || - st->codec->codec_id == AV_CODEC_ID_H264)) { + st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_HEVC)) { AVDictionaryEntry *t; if (st->codec->extradata) { diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 8fd5d29431fff..92ba1c04a0b60 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -31,7 +31,7 @@ #include "libavutil/opt.h" #include "libavcodec/put_bits.h" #include "libavcodec/aacenctab.h" - +#include "hevc.h" static const AVCodecTag flv_video_codec_ids[] = { { AV_CODEC_ID_FLV1, FLV_CODECID_H263 }, @@ -43,6 +43,7 @@ static const AVCodecTag flv_video_codec_ids[] = { { AV_CODEC_ID_VP6, FLV_CODECID_VP6 }, { AV_CODEC_ID_VP6A, FLV_CODECID_VP6A }, { AV_CODEC_ID_H264, FLV_CODECID_H264 }, + { AV_CODEC_ID_HEVC, FLV_CODECID_HEVC }, { AV_CODEC_ID_NONE, 0 } }; @@ -446,7 +447,8 @@ static int flv_write_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; - if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) { + if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4 + || enc->codec_id == AV_CODEC_ID_HEVC) { int64_t pos; avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ? FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); @@ -488,7 +490,11 @@ static int flv_write_header(AVFormatContext *s) avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header avio_wb24(pb, 0); // composition time - ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); + if (enc->codec_id == AV_CODEC_ID_HEVC) { + ff_isom_write_hvcc(pb, enc->extradata, enc->extradata_size, 0); + } else { + ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); + } } data_size = avio_tell(pb) - pos; avio_seek(pb, -data_size - 10, SEEK_CUR); @@ -514,7 +520,7 @@ static int flv_write_trailer(AVFormatContext *s) AVCodecContext *enc = s->streams[i]->codec; FLVStreamContext *sc = s->streams[i]->priv_data; if (enc->codec_type == AVMEDIA_TYPE_VIDEO && - (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4)) + (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4 || enc->codec_id == AV_CODEC_ID_HEVC)) put_avc_eos_tag(pb, sc->last_ts); } @@ -546,12 +552,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) int flags = -1, flags_size, ret; if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A || - enc->codec_id == AV_CODEC_ID_VP6 || enc->codec_id == AV_CODEC_ID_AAC) + enc->codec_id == AV_CODEC_ID_VP6 || enc->codec_id == AV_CODEC_ID_AAC) { flags_size = 2; - else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) + } else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4 || enc->codec_id == AV_CODEC_ID_HEVC) { flags_size = 5; - else + } else { flags_size = 1; + } if (flv->delay == AV_NOPTS_VALUE) flv->delay = -pkt->dts; @@ -597,6 +604,10 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0) return ret; + } else if (enc->codec_id == AV_CODEC_ID_HEVC) { + if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) + if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0) + return ret; } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { @@ -667,9 +678,9 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) else avio_w8(pb, ((FFALIGN(enc->width, 16) - enc->width) << 4) | (FFALIGN(enc->height, 16) - enc->height)); - } else if (enc->codec_id == AV_CODEC_ID_AAC) + } else if (enc->codec_id == AV_CODEC_ID_AAC) { avio_w8(pb, 1); // AAC raw - else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) { + } else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4 || enc->codec_id == AV_CODEC_ID_HEVC) { avio_w8(pb, 1); // AVC NALU avio_wb24(pb, pkt->pts - pkt->dts); }