diff --git a/libavformat/flv.h b/libavformat/flv.h
|
index 3571b90279..91f006520c 100644
|
--- a/libavformat/flv.h
|
+++ b/libavformat/flv.h
|
@@ -110,6 +110,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 b531a39adc..fc9be86509 100644
|
--- a/libavformat/flvdec.c
|
+++ b/libavformat/flvdec.c
|
@@ -37,6 +37,7 @@
|
#include "internal.h"
|
#include "avio_internal.h"
|
#include "flv.h"
|
+#include "hevc.h"
|
|
#define VALIDATE_INDEX_TS_THRESH 2500
|
|
@@ -319,6 +320,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
|
return vpar->codec_id == AV_CODEC_ID_VP6A;
|
case FLV_CODECID_H264:
|
return vpar->codec_id == AV_CODEC_ID_H264;
|
+ case FLV_CODECID_HEVC:
|
+ return vpar->codec_id == AV_CODEC_ID_HEVC;
|
default:
|
return vpar->codec_tag == flv_codecid;
|
}
|
@@ -368,6 +371,11 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
|
par->codec_id = AV_CODEC_ID_MPEG4;
|
ret = 3;
|
break;
|
+ case FLV_CODECID_HEVC:
|
+ par->codec_id = AV_CODEC_ID_HEVC;
|
+ vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
|
+ ret = 3;
|
+ break;
|
default:
|
avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
|
par->codec_tag = flv_codecid;
|
@@ -1223,7 +1231,8 @@ retry_duration:
|
|
if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
|
st->codecpar->codec_id == AV_CODEC_ID_H264 ||
|
- st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
|
+ st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
|
+ st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
|
int type = avio_r8(s->pb);
|
size--;
|
|
@@ -1232,7 +1241,8 @@ retry_duration:
|
goto leave;
|
}
|
|
- if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
|
+ if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4
|
+ || st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
|
// sign extension
|
int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
|
pts = dts + cts;
|
@@ -1248,7 +1258,7 @@ retry_duration:
|
}
|
}
|
if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
|
- st->codecpar->codec_id == AV_CODEC_ID_H264)) {
|
+ st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
|
AVDictionaryEntry *t;
|
|
if (st->codecpar->extradata) {
|
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
|
index fb1dede7ae..711b5dfb05 100644
|
--- a/libavformat/flvenc.c
|
+++ b/libavformat/flvenc.c
|
@@ -29,6 +29,7 @@
|
#include "avc.h"
|
#include "avformat.h"
|
#include "flv.h"
|
+#include "hevc.h"
|
#include "internal.h"
|
#include "metadata.h"
|
#include "libavutil/opt.h"
|
@@ -46,6 +47,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 }
|
};
|
|
@@ -491,7 +493,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
|
FLVContext *flv = s->priv_data;
|
|
if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
|
- || par->codec_id == AV_CODEC_ID_MPEG4) {
|
+ || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
|
int64_t pos;
|
avio_w8(pb,
|
par->codec_type == AVMEDIA_TYPE_VIDEO ?
|
@@ -537,7 +539,11 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
|
avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
|
avio_w8(pb, 0); // AVC sequence header
|
avio_wb24(pb, 0); // composition time
|
- ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
|
+ 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);
|
+ }
|
}
|
data_size = avio_tell(pb) - pos;
|
avio_seek(pb, -data_size - 10, SEEK_CUR);
|
@@ -847,7 +853,8 @@ end:
|
AVCodecParameters *par = s->streams[i]->codecpar;
|
FLVStreamContext *sc = s->streams[i]->priv_data;
|
if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
|
- (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
|
+ (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4
|
+ || par->codec_id == AV_CODEC_ID_HEVC))
|
put_avc_eos_tag(pb, sc->last_ts);
|
}
|
}
|
@@ -898,13 +905,13 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
|
if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
|
par->codec_id == AV_CODEC_ID_VP6 || par->codec_id == AV_CODEC_ID_AAC)
|
flags_size = 2;
|
- else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
|
+ else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC)
|
flags_size = 5;
|
else
|
flags_size = 1;
|
|
if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
|
- || par->codec_id == AV_CODEC_ID_MPEG4) {
|
+ || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
|
int side_size = 0;
|
uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
|
if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
|
@@ -967,6 +974,11 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
|
if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
|
if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
|
return ret;
|
+ } else if (par->codec_id == AV_CODEC_ID_HEVC) {
|
+ /* check if extradata looks like mp4 formatted */
|
+ 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;
|
} else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
|
(AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
|
if (!s->streams[pkt->stream_index]->nb_frames) {
|
@@ -1038,7 +1050,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
|
(FFALIGN(par->height, 16) - par->height));
|
} else if (par->codec_id == AV_CODEC_ID_AAC)
|
avio_w8(pb, 1); // AAC raw
|
- else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
|
+ else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
|
avio_w8(pb, 1); // AVC NALU
|
avio_wb24(pb, pkt->pts - pkt->dts);
|
}
|