]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/av1dec.c
avformat/dashdec: Fix memleaks on error to add representation to dynarray
[ffmpeg] / libavformat / av1dec.c
index 3fa8764387760381e74eb3bef2a5bf3759a5c01c..10c45609682bc92d321632378ee368be1dc3eb69 100644 (file)
 #include "avio_internal.h"
 #include "internal.h"
 
+//return < 0 if we need more data
+static int get_score(int type, int *seq)
+{
+    switch (type) {
+    case AV1_OBU_SEQUENCE_HEADER:
+        *seq = 1;
+        return -1;
+    case AV1_OBU_FRAME:
+    case AV1_OBU_FRAME_HEADER:
+        return *seq ? AVPROBE_SCORE_EXTENSION + 1 : 0;
+    case AV1_OBU_METADATA:
+    case AV1_OBU_PADDING:
+        return -1;
+    default:
+        break;
+    }
+    return 0;
+}
+
+static int read_header(AVFormatContext *s, const AVRational *framerate, AVBSFContext **bsf, void *logctx)
+{
+    const AVBitStreamFilter *filter = av_bsf_get_by_name("av1_frame_merge");
+    AVStream *st;
+    int ret;
+
+    if (!filter) {
+        av_log(logctx, AV_LOG_ERROR, "av1_frame_merge bitstream filter "
+               "not found. This is a bug, please report it.\n");
+        return AVERROR_BUG;
+    }
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_AV1;
+    st->need_parsing = AVSTREAM_PARSE_HEADERS;
+
+    st->internal->avctx->framerate = *framerate;
+    // taken from rawvideo demuxers
+    avpriv_set_pts_info(st, 64, 1, 1200000);
+
+    ret = av_bsf_alloc(filter, bsf);
+    if (ret < 0)
+        return ret;
+
+    ret = avcodec_parameters_copy((*bsf)->par_in, st->codecpar);
+    if (ret < 0) {
+        av_bsf_free(bsf);
+        return ret;
+    }
+
+    ret = av_bsf_init(*bsf);
+    if (ret < 0)
+        av_bsf_free(bsf);
+
+    return ret;
+
+}
+
+#define DEC AV_OPT_FLAG_DECODING_PARAM
+
+#if CONFIG_AV1_DEMUXER
 typedef struct AnnexBContext {
     const AVClass *class;
     AVBSFContext *bsf;
@@ -71,25 +135,6 @@ static int read_obu(const uint8_t *buf, int size, int64_t *obu_size, int *type)
     return 0;
 }
 
-//return < 0 if we need more data
-static int get_score(int type, int *seq)
-{
-    switch (type) {
-    case AV1_OBU_SEQUENCE_HEADER:
-        *seq = 1;
-        return -1;
-    case AV1_OBU_FRAME:
-    case AV1_OBU_FRAME_HEADER:
-        return *seq ? AVPROBE_SCORE_EXTENSION + 1 : 0;
-    case AV1_OBU_METADATA:
-    case AV1_OBU_PADDING:
-        return -1;
-    default:
-        break;
-    }
-    return 0;
-}
-
 static int annexb_probe(const AVProbeData *p)
 {
     AVIOContext pb;
@@ -109,13 +154,11 @@ static int annexb_probe(const AVProbeData *p)
     if (ret < 0 || ((int64_t)frame_unit_size + ret) > temporal_unit_size)
         return 0;
     cnt += ret;
-    temporal_unit_size -= ret;
     ret = leb(&pb, &obu_unit_size);
     if (ret < 0 || ((int64_t)obu_unit_size + ret) >= frame_unit_size)
         return 0;
     cnt += ret;
 
-    temporal_unit_size -= obu_unit_size + ret;
     frame_unit_size -= obu_unit_size + ret;
 
     avio_skip(&pb, obu_unit_size);
@@ -147,55 +190,12 @@ static int annexb_probe(const AVProbeData *p)
         if (ret >= 0)
             return ret;
 
-        temporal_unit_size -= obu_unit_size + ret;
         frame_unit_size -= obu_unit_size + ret;
     } while (frame_unit_size);
 
     return 0;
 }
 
-static int read_header(AVFormatContext *s, const AVRational *framerate, AVBSFContext **bsf, void *logctx)
-{
-    const AVBitStreamFilter *filter = av_bsf_get_by_name("av1_frame_merge");
-    AVStream *st;
-    int ret;
-
-    if (!filter) {
-        av_log(logctx, AV_LOG_ERROR, "av1_frame_merge bitstream filter "
-               "not found. This is a bug, please report it.\n");
-        return AVERROR_BUG;
-    }
-
-    st = avformat_new_stream(s, NULL);
-    if (!st)
-        return AVERROR(ENOMEM);
-
-    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codecpar->codec_id = AV_CODEC_ID_AV1;
-    st->need_parsing = AVSTREAM_PARSE_HEADERS;
-
-    st->internal->avctx->framerate = *framerate;
-    // taken from rawvideo demuxers
-    avpriv_set_pts_info(st, 64, 1, 1200000);
-
-    ret = av_bsf_alloc(filter, bsf);
-    if (ret < 0)
-        return ret;
-
-    ret = avcodec_parameters_copy((*bsf)->par_in, st->codecpar);
-    if (ret < 0) {
-        av_bsf_free(bsf);
-        return ret;
-    }
-
-    ret = av_bsf_init(*bsf);
-    if (ret < 0)
-        av_bsf_free(bsf);
-
-    return ret;
-
-}
-
 static int annexb_read_header(AVFormatContext *s)
 {
     AnnexBContext *c = s->priv_data;
@@ -267,6 +267,35 @@ static int annexb_read_close(AVFormatContext *s)
     return 0;
 }
 
+#define OFFSET(x) offsetof(AnnexBContext, x)
+static const AVOption annexb_options[] = {
+    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
+    { NULL },
+};
+#undef OFFSET
+
+static const AVClass annexb_demuxer_class = {
+    .class_name = "AV1 Annex B demuxer",
+    .item_name  = av_default_item_name,
+    .option     = annexb_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_av1_demuxer = {
+    .name           = "av1",
+    .long_name      = NULL_IF_CONFIG_SMALL("AV1 Annex B"),
+    .priv_data_size = sizeof(AnnexBContext),
+    .read_probe     = annexb_probe,
+    .read_header    = annexb_read_header,
+    .read_packet    = annexb_read_packet,
+    .read_close     = annexb_read_close,
+    .extensions     = "obu",
+    .flags          = AVFMT_GENERIC_INDEX,
+    .priv_class     = &annexb_demuxer_class,
+};
+#endif
+
+#if CONFIG_OBU_DEMUXER
 typedef struct ObuContext {
     const AVClass *class;
     AVBSFContext *bsf;
@@ -350,60 +379,46 @@ static int obu_read_header(AVFormatContext *s)
     return read_header(s, &c->framerate, &c->bsf, c);
 }
 
-static int obu_prefetch(AVFormatContext *s, uint8_t* dest)
+static int obu_get_packet(AVFormatContext *s, AVPacket *pkt)
 {
     ObuContext *c = s->priv_data;
+    uint8_t header[MAX_OBU_HEADER_SIZE];
+    int64_t obu_size;
     int size = av_fifo_space(c->fifo);
+    int ret, len, type;
+
     av_fifo_generic_write(c->fifo, s->pb, size,
                           (int (*)(void*, void*, int))avio_read);
     size = av_fifo_size(c->fifo);
-    if (size > 0) {
-        av_fifo_generic_peek(c->fifo, dest, size, NULL);
+    if (!size)
+        return 0;
+
+    av_fifo_generic_peek(c->fifo, header, size, NULL);
+
+    len = read_obu_with_size(header, size, &obu_size, &type);
+    if (len < 0) {
+        av_log(c, AV_LOG_ERROR, "Failed to read obu\n");
+        return len;
     }
-    return size;
-}
 
-static int obu_read_data(AVFormatContext *s, AVPacket *pkt, int len)
-{
-    int size, left;
-    ObuContext *c = s->priv_data;
-    int ret = av_new_packet(pkt, len);
+    ret = av_new_packet(pkt, len);
     if (ret < 0) {
         av_log(c, AV_LOG_ERROR, "Failed to allocate packet for obu\n");
         return ret;
     }
-    size = FFMIN(av_fifo_size(c->fifo), len);
+    size = FFMIN(size, len);
     av_fifo_generic_read(c->fifo, pkt->data, size, NULL);
-    left = len - size;
-    if (left > 0) {
-        ret = avio_read(s->pb, pkt->data + size, left);
-        if (ret != left) {
-            av_log(c, AV_LOG_ERROR, "Failed to read %d frome file\n", left);
-            return ret;
+    len -= size;
+    if (len > 0) {
+        ret = avio_read(s->pb, pkt->data + size, len);
+        if (ret != len) {
+            av_log(c, AV_LOG_ERROR, "Failed to read %d frome file\n", len);
+            return ret < 0 ? ret : AVERROR_INVALIDDATA;
         }
     }
     return 0;
 }
 
-static int obu_get_packet(AVFormatContext *s, AVPacket *pkt)
-{
-    ObuContext *c = s->priv_data;
-    int64_t obu_size;
-    int ret, type;
-    uint8_t header[MAX_OBU_HEADER_SIZE];
-
-    ret = obu_prefetch(s, header);
-    if (!ret)
-        return AVERROR(EOF);
-
-    ret = read_obu_with_size(header, ret, &obu_size, &type);
-    if (ret < 0) {
-        av_log(c, AV_LOG_ERROR, "Failed to read obu\n");
-        return ret;
-    }
-    return obu_read_data(s, pkt, ret);
-}
-
 static int obu_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     ObuContext *c = s->priv_data;
@@ -439,15 +454,6 @@ static int obu_read_close(AVFormatContext *s)
     return 0;
 }
 
-#define DEC AV_OPT_FLAG_DECODING_PARAM
-
-#define OFFSET(x) offsetof(AnnexBContext, x)
-static const AVOption annexb_options[] = {
-    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
-    { NULL },
-};
-#undef OFFSET
-
 #define OFFSET(x) offsetof(ObuContext, x)
 static const AVOption obu_options[] = {
     { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
@@ -455,26 +461,6 @@ static const AVOption obu_options[] = {
 };
 #undef OFFSET
 
-static const AVClass annexb_demuxer_class = {
-    .class_name = "AV1 Annex B demuxer",
-    .item_name  = av_default_item_name,
-    .option     = annexb_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-AVInputFormat ff_av1_demuxer = {
-    .name           = "av1",
-    .long_name      = NULL_IF_CONFIG_SMALL("AV1 Annex B"),
-    .priv_data_size = sizeof(AnnexBContext),
-    .read_probe     = annexb_probe,
-    .read_header    = annexb_read_header,
-    .read_packet    = annexb_read_packet,
-    .read_close     = annexb_read_close,
-    .extensions     = "obu",
-    .flags          = AVFMT_GENERIC_INDEX,
-    .priv_class     = &annexb_demuxer_class,
-};
-
 static const AVClass obu_demuxer_class = {
     .class_name = "AV1 low overhead OBU demuxer",
     .item_name  = av_default_item_name,
@@ -494,3 +480,4 @@ AVInputFormat ff_obu_demuxer = {
     .flags          = AVFMT_GENERIC_INDEX,
     .priv_class     = &obu_demuxer_class,
 };
+#endif