[FFmpeg-devel] [PATCH] libavformat/flvdec: add HEVC demuxing support

Xiaolei Yu dreifachstein at gmail.com
Sun Jul 25 16:04:10 EEST 2021


Explicitly supply an HEVC codec id to enable this feature.
---
 libavformat/flv.h    |  1 +
 libavformat/flvdec.c | 21 ++++++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/libavformat/flv.h b/libavformat/flv.h
index 3571b90279..7cb1b72b4c 100644
--- a/libavformat/flv.h
+++ b/libavformat/flv.h
@@ -42,6 +42,7 @@
 #define FLV_AUDIO_CODECID_MASK    0xf0
 
 #define FLV_VIDEO_CODECID_MASK    0x0f
+#define FLV_VIDEO_CODECID_MAX     0x0f
 #define FLV_VIDEO_FRAMETYPE_MASK  0xf0
 
 #define AMF_END_OF_OBJECT         0x09
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index b4a419177a..e44aa693b7 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -74,6 +74,7 @@ typedef struct FLVContext {
     int64_t *keyframe_times;
     int64_t *keyframe_filepositions;
     int missing_streams;
+    int hevc_codec_id;
     AVRational framerate;
     int64_t last_ts;
     int64_t time_offset;
@@ -301,7 +302,7 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
     }
 }
 
-static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
+static int flv_same_video_codec(FLVContext *flv, AVCodecParameters *vpar, int flags)
 {
     int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
 
@@ -322,6 +323,8 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
     case FLV_CODECID_H264:
         return vpar->codec_id == AV_CODEC_ID_H264;
     default:
+        if (flv->hevc_codec_id && flv_codecid == flv->hevc_codec_id)
+            return vpar->codec_id == AV_CODEC_ID_HEVC;
         return vpar->codec_tag == flv_codecid;
     }
 }
@@ -329,6 +332,7 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
                                int flv_codecid, int read)
 {
+    FLVContext *flv = s->priv_data;
     int ret = 0;
     AVCodecParameters *par = vstream->codecpar;
     enum AVCodecID old_codec_id = vstream->codecpar->codec_id;
@@ -371,6 +375,12 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
         ret = 3;
         break;
     default:
+        if (flv->hevc_codec_id && flv_codecid == flv->hevc_codec_id) {
+            par->codec_id = AV_CODEC_ID_HEVC;
+            vstream->internal->need_parsing = AVSTREAM_PARSE_HEADERS;
+            ret = 3;     // not 4, reading packet type will consume one byte
+            break;
+        }
         avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
         par->codec_tag = flv_codecid;
     }
@@ -1126,7 +1136,7 @@ skip:
                 break;
         } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
             if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
-                (s->video_codec_id || flv_same_video_codec(st->codecpar, flags)))
+                (s->video_codec_id || flv_same_video_codec(flv, st->codecpar, flags)))
                 break;
         } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
             if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
@@ -1241,6 +1251,7 @@ 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_HEVC ||
         st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
         int type = avio_r8(s->pb);
         size--;
@@ -1250,7 +1261,9 @@ 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_HEVC ||
+            st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
             // sign extension
             int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
             pts = av_sat_add64(dts, cts);
@@ -1266,6 +1279,7 @@ retry_duration:
             }
         }
         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;
 
@@ -1361,6 +1375,7 @@ static const AVOption options[] = {
     { "flv_metadata", "Allocate streams according to the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
     { "flv_full_metadata", "Dump full metadata of the onMetadata", OFFSET(dump_full_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
     { "flv_ignore_prevtag", "Ignore the Size of previous tag", OFFSET(trust_datasize), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
+    { "flv_hevc_codec_id", "Assign HEVC stream codec ID", OFFSET(hevc_codec_id), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, FLV_VIDEO_CODECID_MAX, VD },
     { "missing_streams", "", OFFSET(missing_streams), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xFF, VD | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
     { NULL }
 };
-- 
2.32.0



More information about the ffmpeg-devel mailing list