Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/3] libavcodec/h2645_sei: export raw LCEVC metadata
@ 2024-03-19 14:06 James Almer
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter James Almer
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available James Almer
  0 siblings, 2 replies; 12+ messages in thread
From: James Almer @ 2024-03-19 14:06 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/h2645_sei.c | 36 ++++++++++++++++++++++++++++++++++++
 libavcodec/h2645_sei.h |  5 +++++
 libavcodec/itut35.h    |  2 ++
 libavutil/frame.c      |  1 +
 libavutil/frame.h      |  5 +++++
 5 files changed, 49 insertions(+)

diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c
index e8eb15524f..a6e71894ff 100644
--- a/libavcodec/h2645_sei.c
+++ b/libavcodec/h2645_sei.c
@@ -99,6 +99,20 @@ static int decode_registered_user_data_dynamic_hdr_vivid(HEVCSEIDynamicHDRVivid
 }
 #endif
 
+static int decode_registered_user_data_lcevc(HEVCSEILCEVC *s,
+                                             GetByteContext *gb)
+{
+    int size = bytestream2_get_bytes_left(gb);
+
+    av_buffer_unref(&s->info);
+    s->info = av_buffer_alloc(size);
+    if (!s->info)
+        return AVERROR(ENOMEM);
+
+    bytestream2_get_bufferu(gb, s->info->data, size);
+    return 0;
+}
+
 static int decode_registered_user_data_afd(H2645SEIAFD *h, GetByteContext *gb)
 {
     int flag;
@@ -142,6 +156,7 @@ static int decode_registered_user_data(H2645SEI *h, GetByteContext *gb,
     }
 
     if (country_code != ITU_T_T35_COUNTRY_CODE_US &&
+        country_code != ITU_T_T35_COUNTRY_CODE_UK &&
         country_code != ITU_T_T35_COUNTRY_CODE_CN) {
         av_log(logctx, AV_LOG_VERBOSE,
                "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n",
@@ -173,6 +188,13 @@ static int decode_registered_user_data(H2645SEI *h, GetByteContext *gb,
         }
         break;
     }
+    case ITU_T_T35_PROVIDER_CODE_LCEVC: {
+        if (bytestream2_get_bytes_left(gb) < 2)
+            return AVERROR_INVALIDDATA;
+
+        bytestream2_skipu(gb, 1); // user_data_type_code
+        return decode_registered_user_data_lcevc(&h->lcevc, gb);
+    }
 #if CONFIG_HEVC_SEI
     case ITU_T_T35_PROVIDER_CODE_CUVA: {
         const uint16_t cuva_provider_oriented_code = 0x0005;
@@ -483,6 +505,11 @@ int ff_h2645_sei_ctx_replace(H2645SEI *dst, const H2645SEI *src)
         av_buffer_unref(&dst->unregistered.buf_ref[i]);
     dst->unregistered.nb_buf_ref = 0;
 
+    ret = av_buffer_replace(&dst->lcevc.info,
+                             src->lcevc.info);
+    if (ret < 0)
+        return ret;
+
     if (src->unregistered.nb_buf_ref) {
         ret = av_reallocp_array(&dst->unregistered.buf_ref,
                                 src->unregistered.nb_buf_ref,
@@ -773,6 +800,14 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
         }
     }
 
+    if (sei->lcevc.info) {
+        HEVCSEILCEVC *lcevc = &sei->lcevc;
+        AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_LCEVC, lcevc->info);
+        if (!sd)
+            av_buffer_unref(&lcevc->info);
+        lcevc->info = NULL;
+    }
+
     return 0;
 }
 
@@ -786,6 +821,7 @@ void ff_h2645_sei_reset(H2645SEI *s)
     av_freep(&s->unregistered.buf_ref);
     av_buffer_unref(&s->dynamic_hdr_plus.info);
     av_buffer_unref(&s->dynamic_hdr_vivid.info);
+    av_buffer_unref(&s->lcevc.info);
 
     s->ambient_viewing_environment.present = 0;
     s->mastering_display.present = 0;
diff --git a/libavcodec/h2645_sei.h b/libavcodec/h2645_sei.h
index 0ebf48011a..70d7c2277c 100644
--- a/libavcodec/h2645_sei.h
+++ b/libavcodec/h2645_sei.h
@@ -48,6 +48,10 @@ typedef struct HEVCSEIDynamicHDRVivid {
     AVBufferRef *info;
 } HEVCSEIDynamicHDRVivid;
 
+typedef struct HEVCSEILCEVC {
+    AVBufferRef *info;
+} HEVCSEILCEVC;
+
 typedef struct H2645SEIUnregistered {
     AVBufferRef **buf_ref;
     unsigned nb_buf_ref;
@@ -124,6 +128,7 @@ typedef struct H2645SEI {
     H2645SEIAFD afd;
     HEVCSEIDynamicHDRPlus  dynamic_hdr_plus;     //< HEVC only
     HEVCSEIDynamicHDRVivid dynamic_hdr_vivid;    //< HEVC only
+    HEVCSEILCEVC lcevc;
     H2645SEIUnregistered unregistered;
     H2645SEIFramePacking frame_packing;
     H2645SEIDisplayOrientation display_orientation;
diff --git a/libavcodec/itut35.h b/libavcodec/itut35.h
index ffa7024981..a75ef37929 100644
--- a/libavcodec/itut35.h
+++ b/libavcodec/itut35.h
@@ -20,11 +20,13 @@
 #define AVCODEC_ITUT35_H
 
 #define ITU_T_T35_COUNTRY_CODE_CN 0x26
+#define ITU_T_T35_COUNTRY_CODE_UK 0xB4
 #define ITU_T_T35_COUNTRY_CODE_US 0xB5
 
 #define ITU_T_T35_PROVIDER_CODE_ATSC  0x31
 #define ITU_T_T35_PROVIDER_CODE_CUVA  0x04
 #define ITU_T_T35_PROVIDER_CODE_DOLBY 0x3B
+#define ITU_T_T35_PROVIDER_CODE_LCEVC 0x50
 #define ITU_T_T35_PROVIDER_CODE_SMTPE 0x3C
 
 #endif /* AVCODEC_ITUT35_H */
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 079cf6595b..f872b1c67d 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -822,6 +822,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type)
     case AV_FRAME_DATA_DOVI_RPU_BUFFER:             return "Dolby Vision RPU Data";
     case AV_FRAME_DATA_DOVI_METADATA:               return "Dolby Vision Metadata";
     case AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT: return "Ambient viewing environment";
+    case AV_FRAME_DATA_LCEVC:                       return "Raw LCEVC metadata";
     }
     return NULL;
 }
diff --git a/libavutil/frame.h b/libavutil/frame.h
index b94687941d..8959922f85 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -224,6 +224,11 @@ enum AVFrameSideDataType {
      * encoding.
      */
     AV_FRAME_DATA_VIDEO_HINT,
+
+    /**
+     * Raw LCEVC payload data, as a uint8_t array.
+     */
+    AV_FRAME_DATA_LCEVC,
 };
 
 enum AVActiveFormatDescription {
-- 
2.44.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 14:06 [FFmpeg-devel] [PATCH 1/3] libavcodec/h2645_sei: export raw LCEVC metadata James Almer
@ 2024-03-19 14:06 ` James Almer
  2024-03-19 14:56   ` Andreas Rheinhardt
  2024-03-19 15:00   ` Stefano Sabatini
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available James Almer
  1 sibling, 2 replies; 12+ messages in thread
From: James Almer @ 2024-03-19 14:06 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
 configure                |   4 +
 libavfilter/Makefile     |   1 +
 libavfilter/allfilters.c |   1 +
 libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 472 insertions(+)
 create mode 100644 libavfilter/vf_lcevc.c

diff --git a/configure b/configure
index e019d1b996..4022d13f76 100755
--- a/configure
+++ b/configure
@@ -224,6 +224,7 @@ External library support:
   --enable-libcdio         enable audio CD grabbing with libcdio [no]
   --enable-libcodec2       enable codec2 en/decoding using libcodec2 [no]
   --enable-libdav1d        enable AV1 decoding via libdav1d [no]
+  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]
   --enable-libdavs2        enable AVS2 decoding via libdavs2 [no]
   --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
                            and libraw1394 [no]
@@ -1861,6 +1862,7 @@ EXTERNAL_LIBRARY_LIST="
     libcelt
     libcodec2
     libdav1d
+    liblcevc_dec
     libdc1394
     libflite
     libfontconfig
@@ -3789,6 +3791,7 @@ iccgen_filter_deps="lcms2"
 interlace_filter_deps="gpl"
 kerndeint_filter_deps="gpl"
 ladspa_filter_deps="ladspa libdl"
+lcevc_filter_deps="liblcevc_dec"
 lensfun_filter_deps="liblensfun version3"
 libplacebo_filter_deps="libplacebo vulkan"
 lv2_filter_deps="lv2"
@@ -6801,6 +6804,7 @@ enabled libjxl            && require_pkg_config libjxl "libjxl >= 0.7.0" jxl/dec
 enabled libklvanc         && require libklvanc libklvanc/vanc.h klvanc_context_create -lklvanc
 enabled libkvazaar        && require_pkg_config libkvazaar "kvazaar >= 2.0.0" kvazaar.h kvz_api_get
 enabled liblensfun        && require_pkg_config liblensfun lensfun lensfun.h lf_db_create
+enabled liblcevc_dec      && require_pkg_config liblcevc_dec "lcevc_dec >= 2.0.0" "LCEVC/lcevc_dec.h" LCEVC_CreateDecoder
 
 if enabled libmfx && enabled libvpl; then
    die "ERROR: can not use libmfx and libvpl together"
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 994d9773ba..57f27a1221 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -359,6 +359,7 @@ OBJS-$(CONFIG_INTERLEAVE_FILTER)             += f_interleave.o
 OBJS-$(CONFIG_KERNDEINT_FILTER)              += vf_kerndeint.o
 OBJS-$(CONFIG_KIRSCH_FILTER)                 += vf_convolution.o
 OBJS-$(CONFIG_LAGFUN_FILTER)                 += vf_lagfun.o
+OBJS-$(CONFIG_LCEVC_FILTER)                  += vf_lcevc.o
 OBJS-$(CONFIG_LATENCY_FILTER)                += f_latency.o
 OBJS-$(CONFIG_LENSCORRECTION_FILTER)         += vf_lenscorrection.o
 OBJS-$(CONFIG_LENSFUN_FILTER)                += vf_lensfun.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 149bf50997..54d6ea1043 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -337,6 +337,7 @@ extern const AVFilter ff_vf_kerndeint;
 extern const AVFilter ff_vf_kirsch;
 extern const AVFilter ff_vf_lagfun;
 extern const AVFilter ff_vf_latency;
+extern const AVFilter ff_vf_lcevc;
 extern const AVFilter ff_vf_lenscorrection;
 extern const AVFilter ff_vf_lensfun;
 extern const AVFilter ff_vf_libplacebo;
diff --git a/libavfilter/vf_lcevc.c b/libavfilter/vf_lcevc.c
new file mode 100644
index 0000000000..e18f0945f9
--- /dev/null
+++ b/libavfilter/vf_lcevc.c
@@ -0,0 +1,466 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * Copyright (c) 2024 James Almer <jamrial@gmail.com>
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#include <LCEVC/lcevc_dec.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "filters.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct LCEVCContext {
+    LCEVC_DecoderHandle decoder;
+    LCEVC_PictureHandle base;
+    AVFrame *in;
+    int w, h;
+    int status;
+} LCEVCContext;
+
+static LCEVC_ColorFormat map_format(int format)
+{
+    switch (format) {
+    case AV_PIX_FMT_YUV420P:
+        return LCEVC_I420_8;
+    case AV_PIX_FMT_YUV420P10LE:
+        return LCEVC_I420_10_LE;
+    case AV_PIX_FMT_YUV420P12LE:
+        return LCEVC_I420_12_LE;
+    case AV_PIX_FMT_NV12:
+        return LCEVC_NV12_8;
+    case AV_PIX_FMT_NV21:
+        return LCEVC_NV21_8;
+    case AV_PIX_FMT_GRAY8:
+        return LCEVC_GRAY_8;
+    case AV_PIX_FMT_GRAY10LE:
+        return LCEVC_GRAY_10_LE;
+    case AV_PIX_FMT_GRAY12LE:
+        return LCEVC_GRAY_12_LE;
+    case AV_PIX_FMT_RGB24:
+        return LCEVC_RGB_8;
+    case AV_PIX_FMT_BGR24:
+        return LCEVC_BGR_8;
+    case AV_PIX_FMT_RGBA:
+        return LCEVC_RGBA_8;
+    case AV_PIX_FMT_ARGB:
+        return LCEVC_ARGB_8;
+    case AV_PIX_FMT_ABGR:
+        return LCEVC_ABGR_8;
+    case AV_PIX_FMT_BGRA:
+        return LCEVC_BGRA_8;
+    }
+
+    return LCEVC_ColorFormat_Unknown;
+}
+
+static inline LCEVC_ColorRange map_range(int range)
+{
+    switch (range) {
+    case AVCOL_RANGE_MPEG:
+        return LCEVC_ColorRange_Limited;
+    case AVCOL_RANGE_JPEG:
+        return LCEVC_ColorRange_Full;
+    }
+
+    return LCEVC_ColorRange_Unknown;
+}
+
+static inline enum AVColorRange map_av_range(int range)
+{
+    switch (range) {
+    case LCEVC_ColorRange_Limited:
+        return AVCOL_RANGE_MPEG;
+    case LCEVC_ColorRange_Full:
+        return AVCOL_RANGE_JPEG;
+    }
+
+    return AVCOL_RANGE_UNSPECIFIED;
+}
+
+static int alloc_base_frame(AVFilterLink *inlink, const AVFrame *in,
+                            LCEVC_PictureHandle *picture)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_PictureDesc desc;
+    LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 };
+    LCEVC_ColorFormat fmt = map_format(in->format);
+    int width = in->width - in->crop_left - in->crop_right;
+    int height = in->height - in->crop_top - in->crop_bottom;
+    LCEVC_ReturnCode res;
+
+    res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_DefaultPictureDesc failed\n");
+		return AVERROR_EXTERNAL;
+    }
+
+    for (int i = 0; i < AV_VIDEO_MAX_PLANES; i++) {
+        planes[i].firstSample = in->data[i];
+        planes[i].rowByteStride = in->linesize[i];
+    }
+
+    desc.cropTop    = in->crop_top;
+    desc.cropBottom = in->crop_bottom;
+    desc.cropLeft   = in->crop_left;
+    desc.cropRight  = in->crop_right;
+    desc.sampleAspectRatioNum = in->sample_aspect_ratio.num;
+    desc.sampleAspectRatioDen = in->sample_aspect_ratio.den;
+    desc.colorRange = map_range(in->color_range);
+    desc.colorPrimaries = (LCEVC_ColorPrimaries)in->color_primaries;
+    desc.matrixCoefficients = (LCEVC_MatrixCoefficients)in->colorspace;
+    desc.transferCharacteristics = (LCEVC_TransferCharacteristics)in->color_trc;
+    av_log(ctx, AV_LOG_DEBUG, "in  PTS %"PRId64", %dx%d, "
+                              "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER", "
+                              "SAR %d:%d\n",
+           in->pts, in->width, in->height,
+           in->crop_top, in->crop_bottom, in->crop_left, in->crop_right,
+           in->sample_aspect_ratio.num, in->sample_aspect_ratio.den);
+
+    res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_AllocPictureExternal to allocate a buffer for a base frame\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int send_frame(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LCEVCContext *lcevc = ctx->priv;
+    const AVFrameSideData *sd = av_frame_get_side_data(lcevc->in, AV_FRAME_DATA_LCEVC);
+    LCEVC_ReturnCode res;
+
+    // lcevc->base will be set only if a previous LCEVC_SendDecoderBase() call failed with LCEVC_Again,
+    // in which case we'll try sending the picture again after having fetched at least one enhanced frame.
+    if (!lcevc->base.hdl) {
+        int ret = alloc_base_frame(inlink, lcevc->in, &lcevc->base);
+        if (ret < 0)
+            return ret;
+    }
+
+    if (sd) {
+        res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, lcevc->in->pts, 0, sd->data, sd->size);
+        if (res == LCEVC_Again)
+            return AVERROR(EAGAIN);
+        else if (res != LCEVC_Success) {
+            av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderEnhancementData failed\n");
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    res = LCEVC_SendDecoderBase(lcevc->decoder, lcevc->in->pts, 0, lcevc->base, -1, lcevc->in);
+    if (res == LCEVC_Success) {
+        lcevc->in = NULL;
+        memset(&lcevc->base, 0, sizeof(lcevc->base));
+    } else if (res == LCEVC_Again)
+        return AVERROR(EAGAIN);
+    else {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderBase failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int alloc_enhanced_frame(AVFilterLink *inlink, const AVFrame *out,
+                                LCEVC_PictureHandle *picture)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_PictureDesc desc;
+    LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 };
+    LCEVC_ColorFormat fmt = map_format(out->format);
+    LCEVC_ReturnCode res;
+
+    res = LCEVC_DefaultPictureDesc(&desc, fmt, out->width, out->height);
+    if (res != LCEVC_Success)
+        return AVERROR_EXTERNAL;
+
+    for (int i = 0; i < AV_VIDEO_MAX_PLANES; i++) {
+        planes[i].firstSample = out->data[i];
+        planes[i].rowByteStride = out->linesize[i];
+    }
+
+    res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_AllocPictureExternal to allocate a buffer for an enhanced frame\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int generate_output(AVFilterLink *inlink, AVFrame *out)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_PictureDesc desc;
+    LCEVC_DecodeInformation info;
+    LCEVC_PictureHandle picture;
+    LCEVC_ReturnCode res;
+
+    res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info);
+    if (res == LCEVC_Again) {
+        int64_t pts;
+        if (ff_inlink_acknowledge_status(inlink, &lcevc->status, &pts)) {
+            av_frame_free(&out);
+            ff_outlink_set_status(outlink, lcevc->status, pts);
+            return 0;
+        }
+        // this shouldn't be reachable, but instead of asserting, just error out
+        return AVERROR_EXTERNAL;
+    } else if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_ReceiveDecoderPicture failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    av_frame_copy_props(out, (AVFrame *)info.baseUserData);
+    av_frame_remove_side_data(out, AV_FRAME_DATA_LCEVC);
+
+    av_frame_free((AVFrame **)&info.baseUserData);
+
+    res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_GetPictureDesc failed\n");
+        return AVERROR_EXTERNAL;
+    }
+    res = LCEVC_FreePicture(lcevc->decoder, picture);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_FreePicture enhanced failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    out->crop_top = desc.cropTop;
+    out->crop_bottom = desc.cropBottom;
+    out->crop_left = desc.cropLeft;
+    out->crop_right = desc.cropRight;
+    out->sample_aspect_ratio.num = outlink->sample_aspect_ratio.num = desc.sampleAspectRatioNum;
+    out->sample_aspect_ratio.den = outlink->sample_aspect_ratio.den = desc.sampleAspectRatioDen;
+    out->color_range = map_range(desc.colorRange);
+    out->color_primaries = (enum AVColorPrimaries)desc.colorPrimaries;
+    out->colorspace = (enum AVColorSpace)desc.matrixCoefficients;
+    out->color_trc = (enum AVColorTransferCharacteristic)desc.transferCharacteristics;
+    out->width = outlink->w = desc.width + out->crop_left + out->crop_right;
+    out->height = outlink->h = desc.height + out->crop_top + out->crop_bottom;
+
+    av_log(ctx, AV_LOG_DEBUG, "out PTS %"PRId64", %dx%d, "
+                              "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER", "
+                              "SAR %d:%d, "
+                              "hasEnhancement %d, enhanced %d\n",
+           out->pts, out->width, out->height,
+           out->crop_top, out->crop_bottom, out->crop_left, out->crop_right,
+           out->sample_aspect_ratio.num, out->sample_aspect_ratio.den,
+           info.hasEnhancement, info.enhanced);
+
+    return ff_filter_frame(outlink, out);
+}
+
+static int receive_frame(AVFilterLink *inlink, AVFrame *out)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_PictureHandle picture;
+    LCEVC_ReturnCode res;
+    int ret;
+
+    ret = alloc_enhanced_frame(inlink, out, &picture);
+    if (ret < 0)
+        return ret;
+
+    res = LCEVC_SendDecoderPicture(lcevc->decoder, picture);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderPicture failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    return generate_output(inlink, out);
+}
+
+static int config_props(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = ctx->inputs[0];
+    LCEVCContext *lcevc = ctx->priv;
+
+    outlink->w = lcevc->w = inlink->w * 2 / FFMAX(inlink->sample_aspect_ratio.den, 1);
+    outlink->h = lcevc->h = inlink->h * 2 / FFMAX(inlink->sample_aspect_ratio.den, 1);
+    outlink->sample_aspect_ratio = (AVRational) { 0, 1 };
+
+    return 0;
+}
+
+static void flush_bases(AVFilterContext *ctx)
+{
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_PictureHandle picture;
+
+    while (LCEVC_ReceiveDecoderBase(lcevc->decoder, &picture) == LCEVC_Success)
+        LCEVC_FreePicture(lcevc->decoder, picture);
+}
+
+static int activate(AVFilterContext *ctx)
+{
+    LCEVCContext *lcevc   = ctx->priv;
+    AVFilterLink *inlink  = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *out;
+    int ret;
+
+    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+    if (!lcevc->in) {
+        ret = ff_inlink_consume_frame(inlink, &lcevc->in);
+        if (ret < 0)
+            return ret;
+        if (!ret) {
+            int64_t pts;
+            if (ff_inlink_acknowledge_status(inlink, &lcevc->status, &pts)) {
+                if (!lcevc->status)
+                    ff_outlink_set_status(outlink, lcevc->status, pts);
+            }
+            if (!lcevc->status)
+                FF_FILTER_FORWARD_WANTED(outlink, inlink);
+        }
+    }
+
+    if (lcevc->in) {
+       if (lcevc->in->width  != inlink->w ||
+            lcevc->in->height != inlink->h ||
+            lcevc->in->sample_aspect_ratio.den != inlink->sample_aspect_ratio.den ||
+            lcevc->in->sample_aspect_ratio.num != inlink->sample_aspect_ratio.num) {
+            inlink->dst->inputs[0]->w                       = lcevc->in->width;
+            inlink->dst->inputs[0]->h                       = lcevc->in->height;
+            inlink->dst->inputs[0]->sample_aspect_ratio.den = lcevc->in->sample_aspect_ratio.den;
+            inlink->dst->inputs[0]->sample_aspect_ratio.num = lcevc->in->sample_aspect_ratio.num;
+
+            config_props(outlink);
+        }
+
+        ret = send_frame(inlink);
+        // Buffer as many base frames as the decoder allows
+        if (!ret) {
+            FF_FILTER_FORWARD_WANTED(outlink, inlink);
+            return FFERROR_NOT_READY;
+        } else if (ret < 0 && ret != AVERROR(EAGAIN))
+            return ret;
+    }
+
+    out = ff_get_video_buffer(outlink, lcevc->w, lcevc->h);
+    if (!out)
+        return AVERROR(ENOMEM);
+
+    ret = receive_frame(inlink, out);
+    if (ret < 0) {
+        av_frame_free(&out);
+        return ret;
+    }
+
+    flush_bases(ctx);
+
+    return ret;
+}
+
+static void log_callback(LCEVC_DecoderHandle dec, LCEVC_Event event,
+                         LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info,
+                         const uint8_t *data, uint32_t size, void *logctx)
+{
+    if (event != LCEVC_Log) // shouldn't happen
+        return;
+
+    if (strlen(data) != size) // sanitize input
+        return;
+
+    av_log(logctx, AV_LOG_INFO, "LCEVC Log: %s\n", data);
+}
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    LCEVCContext *lcevc = ctx->priv;
+    LCEVC_AccelContextHandle dummy = { 0 };
+    const int32_t event = LCEVC_Log;
+    LCEVC_ReturnCode res;
+
+    res = LCEVC_CreateDecoder(&lcevc->decoder, dummy);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_CreateDecoder failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    res = LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", 1, &event);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_ConfigureDecoderIntArray failed to set \"events\"\n");
+        return AVERROR_EXTERNAL;
+    }
+    res = LCEVC_SetDecoderEventCallback(lcevc->decoder, log_callback, ctx);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_SetDecoderEventCallback failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    res = LCEVC_InitializeDecoder(lcevc->decoder);
+    if (res != LCEVC_Success) {
+        av_log(ctx, AV_LOG_ERROR, "LCEVC_InitializeDecoder failed\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    LCEVCContext *lcevc = ctx->priv;
+
+    LCEVC_DestroyDecoder(lcevc->decoder);
+}
+
+static const AVFilterPad lcevc_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_props,
+    },
+};
+
+static const enum AVPixelFormat pix_fmts[] = {
+    AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV420P12LE,
+    AV_PIX_FMT_NV12, AV_PIX_FMT_NV21,
+    AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10LE, AV_PIX_FMT_GRAY12LE,
+    AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
+    AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA,
+    AV_PIX_FMT_NONE
+};
+
+const AVFilter ff_vf_lcevc = {
+    .name          = "lcevc",
+    .description   = NULL_IF_CONFIG_SMALL("LCEVC"),
+    .activate      = activate,
+    FILTER_INPUTS(ff_video_default_filterpad),
+    FILTER_OUTPUTS(lcevc_outputs),
+    FILTER_PIXFMTS_ARRAY(pix_fmts),
+    .priv_size     = sizeof(LCEVCContext),
+    .init          = init,
+    .uninit        = uninit,
+};
-- 
2.44.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available
  2024-03-19 14:06 [FFmpeg-devel] [PATCH 1/3] libavcodec/h2645_sei: export raw LCEVC metadata James Almer
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter James Almer
@ 2024-03-19 14:06 ` James Almer
  2024-03-19 15:01   ` Andreas Rheinhardt
  1 sibling, 1 reply; 12+ messages in thread
From: James Almer @ 2024-03-19 14:06 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
 fftools/ffmpeg.h        |  3 +++
 fftools/ffmpeg_demux.c  |  4 ++++
 fftools/ffmpeg_filter.c | 28 +++++++++++++++++++++++++++-
 fftools/ffmpeg_opt.c    |  3 +++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7454089c2d..8d54affc0a 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -155,6 +155,7 @@ typedef struct OptionsContext {
     SpecifierOptList hwaccel_devices;
     SpecifierOptList hwaccel_output_formats;
     SpecifierOptList autorotate;
+    SpecifierOptList autoenhance;
 
     /* output options */
     StreamMap *stream_maps;
@@ -239,6 +240,7 @@ enum IFilterFlags {
     IFILTER_FLAG_AUTOROTATE     = (1 << 0),
     IFILTER_FLAG_REINIT         = (1 << 1),
     IFILTER_FLAG_CFR            = (1 << 2),
+    IFILTER_FLAG_AUTOENHANCE    = (1 << 3),
 };
 
 typedef struct InputFilterOptions {
@@ -369,6 +371,7 @@ typedef struct InputStream {
 #endif
 
     int                   autorotate;
+    int                   autoenhance;
 
     int                   fix_sub_duration;
 
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 47312c9fe1..0b4ab3d7ec 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1056,6 +1056,7 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple,
         return AVERROR(ENOMEM);
 
     opts->flags |= IFILTER_FLAG_AUTOROTATE * !!(ist->autorotate) |
+                   IFILTER_FLAG_AUTOENHANCE * !!(ist->autoenhance) |
                    IFILTER_FLAG_REINIT     * !!(ds->reinit_filters);
 
     return ds->sch_idx_dec;
@@ -1238,6 +1239,9 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
     ist->autorotate = 1;
     MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
 
+    ist->autoenhance = 1;
+    MATCH_PER_STREAM_OPT(autoenhance, i, ist->autoenhance, ic, st);
+
     MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
     if (codec_tag) {
         uint32_t tag = strtol(codec_tag, &next, 0);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3d88482d07..c4d900d95b 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config_components.h"
+
 #include <stdint.h>
 
 #include "ffmpeg.h"
@@ -145,6 +147,8 @@ typedef struct InputFilterPriv {
     int                 displaymatrix_present;
     int32_t             displaymatrix[9];
 
+    int                 enhancement_present;
+
     // fallback parameters to use when no input is ever sent
     struct {
         AVRational          time_base;
@@ -1567,6 +1571,15 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
     desc = av_pix_fmt_desc_get(ifp->format);
     av_assert0(desc);
 
+#if CONFIG_LCEVC_FILTER
+    if ((ifp->opts.flags & IFILTER_FLAG_AUTOENHANCE) &&
+        !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
+        ret = insert_filter(&last_filter, &pad_idx, "lcevc", NULL);
+        if (ret < 0)
+            return ret;
+    }
+#endif
+
     // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph
     if ((ifp->opts.flags & IFILTER_FLAG_AUTOROTATE) &&
         !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
@@ -1883,6 +1896,10 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
         memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix));
     ifp->displaymatrix_present = !!sd;
 
+#if CONFIG_LCEVC_FILTER
+    ifp->enhancement_present = !!(av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC));
+#endif
+
     return 0;
 }
 
@@ -2584,7 +2601,8 @@ enum ReinitReason {
     VIDEO_CHANGED   = (1 << 0),
     AUDIO_CHANGED   = (1 << 1),
     MATRIX_CHANGED  = (1 << 2),
-    HWACCEL_CHANGED = (1 << 3)
+    HWACCEL_CHANGED = (1 << 3),
+    ENHANCEMENT_CHANGED = (1 << 4),
 };
 
 static const char *unknown_if_null(const char *str)
@@ -2625,6 +2643,12 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
     } else if (ifp->displaymatrix_present)
         need_reinit |= MATRIX_CHANGED;
 
+#if CONFIG_LCEVC_FILTER
+    if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC))
+        if (!ifp->enhancement_present)
+            need_reinit |= ENHANCEMENT_CHANGED;
+#endif
+
     if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph)
         need_reinit = 0;
 
@@ -2681,6 +2705,8 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
                 av_bprintf(&reason, "display matrix changed, ");
             if (need_reinit & HWACCEL_CHANGED)
                 av_bprintf(&reason, "hwaccel changed, ");
+            if (need_reinit & ENHANCEMENT_CHANGED)
+                av_bprintf(&reason, "enhancement data found, ");
             if (reason.len > 1)
                 reason.str[reason.len - 2] = '\0'; // remove last comma
             av_log(fg, AV_LOG_INFO, "Reconfiguring filter graph%s%s\n", reason.len ? " because " : "", reason.str);
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 4b3f9789ba..b87782806e 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1738,6 +1738,9 @@ const OptionDef options[] = {
     { "autorotate",                 OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_INPUT,
         { .off = OFFSET(autorotate) },
         "automatically insert correct rotate filters" },
+    { "autoenhance",                OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_INPUT,
+        { .off = OFFSET(autoenhance) },
+        "automatically insert enhancement filters (LCEVC)" },
     { "autoscale",                  OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_OUTPUT,
         { .off = OFFSET(autoscale) },
         "automatically insert a scale filter at the end of the filter graph" },
-- 
2.44.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter James Almer
@ 2024-03-19 14:56   ` Andreas Rheinhardt
  2024-03-19 15:05     ` James Almer
  2024-03-19 15:00   ` Stefano Sabatini
  1 sibling, 1 reply; 12+ messages in thread
From: Andreas Rheinhardt @ 2024-03-19 14:56 UTC (permalink / raw)
  To: ffmpeg-devel

James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  configure                |   4 +
>  libavfilter/Makefile     |   1 +
>  libavfilter/allfilters.c |   1 +
>  libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 472 insertions(+)
>  create mode 100644 libavfilter/vf_lcevc.c
> 
> diff --git a/configure b/configure
> index e019d1b996..4022d13f76 100755
> --- a/configure
> +++ b/configure
> @@ -224,6 +224,7 @@ External library support:
>    --enable-libcdio         enable audio CD grabbing with libcdio [no]
>    --enable-libcodec2       enable codec2 en/decoding using libcodec2 [no]
>    --enable-libdav1d        enable AV1 decoding via libdav1d [no]
> +  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]

How is this filter supposed to decode AV1 if it does not even get
AVPackets? It seems to be for decoding an EVC enhancment layer instead.

>    --enable-libdavs2        enable AVS2 decoding via libdavs2 [no]
>    --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
>                             and libraw1394 [no]
> @@ -1861,6 +1862,7 @@ EXTERNAL_LIBRARY_LIST="
>      libcelt
>      libcodec2
>      libdav1d
> +    liblcevc_dec
>      libdc1394
>      libflite
>      libfontconfig
> @@ -3789,6 +3791,7 @@ iccgen_filter_deps="lcms2"
>  interlace_filter_deps="gpl"
>  kerndeint_filter_deps="gpl"
>  ladspa_filter_deps="ladspa libdl"
> +lcevc_filter_deps="liblcevc_dec"
>  lensfun_filter_deps="liblensfun version3"
>  libplacebo_filter_deps="libplacebo vulkan"
>  lv2_filter_deps="lv2"
> @@ -6801,6 +6804,7 @@ enabled libjxl            && require_pkg_config libjxl "libjxl >= 0.7.0" jxl/dec
>  enabled libklvanc         && require libklvanc libklvanc/vanc.h klvanc_context_create -lklvanc
>  enabled libkvazaar        && require_pkg_config libkvazaar "kvazaar >= 2.0.0" kvazaar.h kvz_api_get
>  enabled liblensfun        && require_pkg_config liblensfun lensfun lensfun.h lf_db_create
> +enabled liblcevc_dec      && require_pkg_config liblcevc_dec "lcevc_dec >= 2.0.0" "LCEVC/lcevc_dec.h" LCEVC_CreateDecoder
>  
>  if enabled libmfx && enabled libvpl; then
>     die "ERROR: can not use libmfx and libvpl together"
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 994d9773ba..57f27a1221 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -359,6 +359,7 @@ OBJS-$(CONFIG_INTERLEAVE_FILTER)             += f_interleave.o
>  OBJS-$(CONFIG_KERNDEINT_FILTER)              += vf_kerndeint.o
>  OBJS-$(CONFIG_KIRSCH_FILTER)                 += vf_convolution.o
>  OBJS-$(CONFIG_LAGFUN_FILTER)                 += vf_lagfun.o
> +OBJS-$(CONFIG_LCEVC_FILTER)                  += vf_lcevc.o
>  OBJS-$(CONFIG_LATENCY_FILTER)                += f_latency.o
>  OBJS-$(CONFIG_LENSCORRECTION_FILTER)         += vf_lenscorrection.o
>  OBJS-$(CONFIG_LENSFUN_FILTER)                += vf_lensfun.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 149bf50997..54d6ea1043 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -337,6 +337,7 @@ extern const AVFilter ff_vf_kerndeint;
>  extern const AVFilter ff_vf_kirsch;
>  extern const AVFilter ff_vf_lagfun;
>  extern const AVFilter ff_vf_latency;
> +extern const AVFilter ff_vf_lcevc;
>  extern const AVFilter ff_vf_lenscorrection;
>  extern const AVFilter ff_vf_lensfun;
>  extern const AVFilter ff_vf_libplacebo;
> diff --git a/libavfilter/vf_lcevc.c b/libavfilter/vf_lcevc.c
> new file mode 100644
> index 0000000000..e18f0945f9
> --- /dev/null
> +++ b/libavfilter/vf_lcevc.c
> @@ -0,0 +1,466 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * Copyright (c) 2024 James Almer <jamrial@gmail.com>
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <stdint.h>
> +
> +#include <LCEVC/lcevc_dec.h>
> +
> +#include "libavutil/internal.h"
> +#include "libavutil/opt.h"
> +#include "filters.h"
> +#include "internal.h"
> +#include "video.h"
> +
> +typedef struct LCEVCContext {
> +    LCEVC_DecoderHandle decoder;
> +    LCEVC_PictureHandle base;
> +    AVFrame *in;
> +    int w, h;
> +    int status;
> +} LCEVCContext;
> +
> +static LCEVC_ColorFormat map_format(int format)
> +{
> +    switch (format) {
> +    case AV_PIX_FMT_YUV420P:
> +        return LCEVC_I420_8;
> +    case AV_PIX_FMT_YUV420P10LE:
> +        return LCEVC_I420_10_LE;
> +    case AV_PIX_FMT_YUV420P12LE:
> +        return LCEVC_I420_12_LE;
> +    case AV_PIX_FMT_NV12:
> +        return LCEVC_NV12_8;
> +    case AV_PIX_FMT_NV21:
> +        return LCEVC_NV21_8;
> +    case AV_PIX_FMT_GRAY8:
> +        return LCEVC_GRAY_8;
> +    case AV_PIX_FMT_GRAY10LE:
> +        return LCEVC_GRAY_10_LE;
> +    case AV_PIX_FMT_GRAY12LE:
> +        return LCEVC_GRAY_12_LE;
> +    case AV_PIX_FMT_RGB24:
> +        return LCEVC_RGB_8;
> +    case AV_PIX_FMT_BGR24:
> +        return LCEVC_BGR_8;
> +    case AV_PIX_FMT_RGBA:
> +        return LCEVC_RGBA_8;
> +    case AV_PIX_FMT_ARGB:
> +        return LCEVC_ARGB_8;
> +    case AV_PIX_FMT_ABGR:
> +        return LCEVC_ABGR_8;
> +    case AV_PIX_FMT_BGRA:
> +        return LCEVC_BGRA_8;
> +    }
> +
> +    return LCEVC_ColorFormat_Unknown;
> +}
> +
> +static inline LCEVC_ColorRange map_range(int range)
> +{
> +    switch (range) {
> +    case AVCOL_RANGE_MPEG:
> +        return LCEVC_ColorRange_Limited;
> +    case AVCOL_RANGE_JPEG:
> +        return LCEVC_ColorRange_Full;
> +    }
> +
> +    return LCEVC_ColorRange_Unknown;
> +}
> +
> +static inline enum AVColorRange map_av_range(int range)
> +{
> +    switch (range) {
> +    case LCEVC_ColorRange_Limited:
> +        return AVCOL_RANGE_MPEG;
> +    case LCEVC_ColorRange_Full:
> +        return AVCOL_RANGE_JPEG;
> +    }
> +
> +    return AVCOL_RANGE_UNSPECIFIED;
> +}
> +
> +static int alloc_base_frame(AVFilterLink *inlink, const AVFrame *in,
> +                            LCEVC_PictureHandle *picture)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_PictureDesc desc;
> +    LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 };
> +    LCEVC_ColorFormat fmt = map_format(in->format);
> +    int width = in->width - in->crop_left - in->crop_right;
> +    int height = in->height - in->crop_top - in->crop_bottom;
> +    LCEVC_ReturnCode res;
> +
> +    res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_DefaultPictureDesc failed\n");
> +		return AVERROR_EXTERNAL;
> +    }
> +
> +    for (int i = 0; i < AV_VIDEO_MAX_PLANES; i++) {
> +        planes[i].firstSample = in->data[i];
> +        planes[i].rowByteStride = in->linesize[i];
> +    }
> +
> +    desc.cropTop    = in->crop_top;
> +    desc.cropBottom = in->crop_bottom;
> +    desc.cropLeft   = in->crop_left;
> +    desc.cropRight  = in->crop_right;
> +    desc.sampleAspectRatioNum = in->sample_aspect_ratio.num;
> +    desc.sampleAspectRatioDen = in->sample_aspect_ratio.den;
> +    desc.colorRange = map_range(in->color_range);
> +    desc.colorPrimaries = (LCEVC_ColorPrimaries)in->color_primaries;
> +    desc.matrixCoefficients = (LCEVC_MatrixCoefficients)in->colorspace;
> +    desc.transferCharacteristics = (LCEVC_TransferCharacteristics)in->color_trc;
> +    av_log(ctx, AV_LOG_DEBUG, "in  PTS %"PRId64", %dx%d, "
> +                              "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER", "
> +                              "SAR %d:%d\n",
> +           in->pts, in->width, in->height,
> +           in->crop_top, in->crop_bottom, in->crop_left, in->crop_right,
> +           in->sample_aspect_ratio.num, in->sample_aspect_ratio.den);
> +
> +    res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_AllocPictureExternal to allocate a buffer for a base frame\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int send_frame(AVFilterLink *inlink)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    LCEVCContext *lcevc = ctx->priv;
> +    const AVFrameSideData *sd = av_frame_get_side_data(lcevc->in, AV_FRAME_DATA_LCEVC);
> +    LCEVC_ReturnCode res;
> +
> +    // lcevc->base will be set only if a previous LCEVC_SendDecoderBase() call failed with LCEVC_Again,
> +    // in which case we'll try sending the picture again after having fetched at least one enhanced frame.
> +    if (!lcevc->base.hdl) {
> +        int ret = alloc_base_frame(inlink, lcevc->in, &lcevc->base);
> +        if (ret < 0)
> +            return ret;
> +    }
> +
> +    if (sd) {
> +        res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, lcevc->in->pts, 0, sd->data, sd->size);
> +        if (res == LCEVC_Again)
> +            return AVERROR(EAGAIN);
> +        else if (res != LCEVC_Success) {
> +            av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderEnhancementData failed\n");
> +            return AVERROR_EXTERNAL;
> +        }
> +    }
> +
> +    res = LCEVC_SendDecoderBase(lcevc->decoder, lcevc->in->pts, 0, lcevc->base, -1, lcevc->in);
> +    if (res == LCEVC_Success) {
> +        lcevc->in = NULL;
> +        memset(&lcevc->base, 0, sizeof(lcevc->base));
> +    } else if (res == LCEVC_Again)
> +        return AVERROR(EAGAIN);
> +    else {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderBase failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int alloc_enhanced_frame(AVFilterLink *inlink, const AVFrame *out,
> +                                LCEVC_PictureHandle *picture)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_PictureDesc desc;
> +    LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 };
> +    LCEVC_ColorFormat fmt = map_format(out->format);
> +    LCEVC_ReturnCode res;
> +
> +    res = LCEVC_DefaultPictureDesc(&desc, fmt, out->width, out->height);
> +    if (res != LCEVC_Success)
> +        return AVERROR_EXTERNAL;
> +
> +    for (int i = 0; i < AV_VIDEO_MAX_PLANES; i++) {
> +        planes[i].firstSample = out->data[i];
> +        planes[i].rowByteStride = out->linesize[i];
> +    }
> +
> +    res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_AllocPictureExternal to allocate a buffer for an enhanced frame\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int generate_output(AVFilterLink *inlink, AVFrame *out)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    AVFilterLink *outlink = ctx->outputs[0];
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_PictureDesc desc;
> +    LCEVC_DecodeInformation info;
> +    LCEVC_PictureHandle picture;
> +    LCEVC_ReturnCode res;
> +
> +    res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info);
> +    if (res == LCEVC_Again) {
> +        int64_t pts;
> +        if (ff_inlink_acknowledge_status(inlink, &lcevc->status, &pts)) {
> +            av_frame_free(&out);
> +            ff_outlink_set_status(outlink, lcevc->status, pts);
> +            return 0;
> +        }
> +        // this shouldn't be reachable, but instead of asserting, just error out
> +        return AVERROR_EXTERNAL;
> +    } else if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_ReceiveDecoderPicture failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    av_frame_copy_props(out, (AVFrame *)info.baseUserData);
> +    av_frame_remove_side_data(out, AV_FRAME_DATA_LCEVC);
> +
> +    av_frame_free((AVFrame **)&info.baseUserData);
> +
> +    res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_GetPictureDesc failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +    res = LCEVC_FreePicture(lcevc->decoder, picture);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_FreePicture enhanced failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    out->crop_top = desc.cropTop;
> +    out->crop_bottom = desc.cropBottom;
> +    out->crop_left = desc.cropLeft;
> +    out->crop_right = desc.cropRight;
> +    out->sample_aspect_ratio.num = outlink->sample_aspect_ratio.num = desc.sampleAspectRatioNum;
> +    out->sample_aspect_ratio.den = outlink->sample_aspect_ratio.den = desc.sampleAspectRatioDen;
> +    out->color_range = map_range(desc.colorRange);
> +    out->color_primaries = (enum AVColorPrimaries)desc.colorPrimaries;
> +    out->colorspace = (enum AVColorSpace)desc.matrixCoefficients;
> +    out->color_trc = (enum AVColorTransferCharacteristic)desc.transferCharacteristics;
> +    out->width = outlink->w = desc.width + out->crop_left + out->crop_right;
> +    out->height = outlink->h = desc.height + out->crop_top + out->crop_bottom;
> +
> +    av_log(ctx, AV_LOG_DEBUG, "out PTS %"PRId64", %dx%d, "
> +                              "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER", "
> +                              "SAR %d:%d, "
> +                              "hasEnhancement %d, enhanced %d\n",
> +           out->pts, out->width, out->height,
> +           out->crop_top, out->crop_bottom, out->crop_left, out->crop_right,
> +           out->sample_aspect_ratio.num, out->sample_aspect_ratio.den,
> +           info.hasEnhancement, info.enhanced);
> +
> +    return ff_filter_frame(outlink, out);
> +}
> +
> +static int receive_frame(AVFilterLink *inlink, AVFrame *out)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_PictureHandle picture;
> +    LCEVC_ReturnCode res;
> +    int ret;
> +
> +    ret = alloc_enhanced_frame(inlink, out, &picture);
> +    if (ret < 0)
> +        return ret;
> +
> +    res = LCEVC_SendDecoderPicture(lcevc->decoder, picture);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderPicture failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    return generate_output(inlink, out);
> +}
> +
> +static int config_props(AVFilterLink *outlink)
> +{
> +    AVFilterContext *ctx = outlink->src;
> +    AVFilterLink *inlink = ctx->inputs[0];
> +    LCEVCContext *lcevc = ctx->priv;
> +
> +    outlink->w = lcevc->w = inlink->w * 2 / FFMAX(inlink->sample_aspect_ratio.den, 1);
> +    outlink->h = lcevc->h = inlink->h * 2 / FFMAX(inlink->sample_aspect_ratio.den, 1);
> +    outlink->sample_aspect_ratio = (AVRational) { 0, 1 };
> +
> +    return 0;
> +}
> +
> +static void flush_bases(AVFilterContext *ctx)
> +{
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_PictureHandle picture;
> +
> +    while (LCEVC_ReceiveDecoderBase(lcevc->decoder, &picture) == LCEVC_Success)
> +        LCEVC_FreePicture(lcevc->decoder, picture);
> +}
> +
> +static int activate(AVFilterContext *ctx)
> +{
> +    LCEVCContext *lcevc   = ctx->priv;
> +    AVFilterLink *inlink  = ctx->inputs[0];
> +    AVFilterLink *outlink = ctx->outputs[0];
> +    AVFrame *out;
> +    int ret;
> +
> +    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
> +
> +    if (!lcevc->in) {
> +        ret = ff_inlink_consume_frame(inlink, &lcevc->in);
> +        if (ret < 0)
> +            return ret;
> +        if (!ret) {
> +            int64_t pts;
> +            if (ff_inlink_acknowledge_status(inlink, &lcevc->status, &pts)) {
> +                if (!lcevc->status)
> +                    ff_outlink_set_status(outlink, lcevc->status, pts);
> +            }
> +            if (!lcevc->status)
> +                FF_FILTER_FORWARD_WANTED(outlink, inlink);
> +        }
> +    }
> +
> +    if (lcevc->in) {
> +       if (lcevc->in->width  != inlink->w ||
> +            lcevc->in->height != inlink->h ||
> +            lcevc->in->sample_aspect_ratio.den != inlink->sample_aspect_ratio.den ||
> +            lcevc->in->sample_aspect_ratio.num != inlink->sample_aspect_ratio.num) {
> +            inlink->dst->inputs[0]->w                       = lcevc->in->width;
> +            inlink->dst->inputs[0]->h                       = lcevc->in->height;
> +            inlink->dst->inputs[0]->sample_aspect_ratio.den = lcevc->in->sample_aspect_ratio.den;
> +            inlink->dst->inputs[0]->sample_aspect_ratio.num = lcevc->in->sample_aspect_ratio.num;
> +
> +            config_props(outlink);
> +        }
> +
> +        ret = send_frame(inlink);
> +        // Buffer as many base frames as the decoder allows
> +        if (!ret) {
> +            FF_FILTER_FORWARD_WANTED(outlink, inlink);
> +            return FFERROR_NOT_READY;
> +        } else if (ret < 0 && ret != AVERROR(EAGAIN))
> +            return ret;
> +    }
> +
> +    out = ff_get_video_buffer(outlink, lcevc->w, lcevc->h);
> +    if (!out)
> +        return AVERROR(ENOMEM);
> +
> +    ret = receive_frame(inlink, out);
> +    if (ret < 0) {
> +        av_frame_free(&out);
> +        return ret;
> +    }
> +
> +    flush_bases(ctx);
> +
> +    return ret;
> +}
> +
> +static void log_callback(LCEVC_DecoderHandle dec, LCEVC_Event event,
> +                         LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info,
> +                         const uint8_t *data, uint32_t size, void *logctx)
> +{
> +    if (event != LCEVC_Log) // shouldn't happen
> +        return;
> +
> +    if (strlen(data) != size) // sanitize input
> +        return;
> +
> +    av_log(logctx, AV_LOG_INFO, "LCEVC Log: %s\n", data);
> +}
> +
> +static av_cold int init(AVFilterContext *ctx)
> +{
> +    LCEVCContext *lcevc = ctx->priv;
> +    LCEVC_AccelContextHandle dummy = { 0 };
> +    const int32_t event = LCEVC_Log;
> +    LCEVC_ReturnCode res;
> +
> +    res = LCEVC_CreateDecoder(&lcevc->decoder, dummy);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_CreateDecoder failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    res = LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", 1, &event);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_ConfigureDecoderIntArray failed to set \"events\"\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +    res = LCEVC_SetDecoderEventCallback(lcevc->decoder, log_callback, ctx);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_SetDecoderEventCallback failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    res = LCEVC_InitializeDecoder(lcevc->decoder);
> +    if (res != LCEVC_Success) {
> +        av_log(ctx, AV_LOG_ERROR, "LCEVC_InitializeDecoder failed\n");
> +        return AVERROR_EXTERNAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static av_cold void uninit(AVFilterContext *ctx)
> +{
> +    LCEVCContext *lcevc = ctx->priv;
> +
> +    LCEVC_DestroyDecoder(lcevc->decoder);
> +}
> +
> +static const AVFilterPad lcevc_outputs[] = {
> +    {
> +        .name         = "default",
> +        .type         = AVMEDIA_TYPE_VIDEO,
> +        .config_props = config_props,
> +    },
> +};
> +
> +static const enum AVPixelFormat pix_fmts[] = {
> +    AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV420P12LE,
> +    AV_PIX_FMT_NV12, AV_PIX_FMT_NV21,
> +    AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10LE, AV_PIX_FMT_GRAY12LE,
> +    AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
> +    AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA,
> +    AV_PIX_FMT_NONE
> +};
> +
> +const AVFilter ff_vf_lcevc = {
> +    .name          = "lcevc",
> +    .description   = NULL_IF_CONFIG_SMALL("LCEVC"),
> +    .activate      = activate,
> +    FILTER_INPUTS(ff_video_default_filterpad),
> +    FILTER_OUTPUTS(lcevc_outputs),
> +    FILTER_PIXFMTS_ARRAY(pix_fmts),
> +    .priv_size     = sizeof(LCEVCContext),
> +    .init          = init,
> +    .uninit        = uninit,
> +};

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter James Almer
  2024-03-19 14:56   ` Andreas Rheinhardt
@ 2024-03-19 15:00   ` Stefano Sabatini
  1 sibling, 0 replies; 12+ messages in thread
From: Stefano Sabatini @ 2024-03-19 15:00 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On date Tuesday 2024-03-19 11:06:35 -0300, James Almer wrote:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  configure                |   4 +
>  libavfilter/Makefile     |   1 +
>  libavfilter/allfilters.c |   1 +
>  libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++

missing docs, this is also needed to clarify the use case
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available
  2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available James Almer
@ 2024-03-19 15:01   ` Andreas Rheinhardt
  2024-03-19 15:08     ` James Almer
  0 siblings, 1 reply; 12+ messages in thread
From: Andreas Rheinhardt @ 2024-03-19 15:01 UTC (permalink / raw)
  To: ffmpeg-devel

James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  fftools/ffmpeg.h        |  3 +++
>  fftools/ffmpeg_demux.c  |  4 ++++
>  fftools/ffmpeg_filter.c | 28 +++++++++++++++++++++++++++-
>  fftools/ffmpeg_opt.c    |  3 +++
>  4 files changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> index 7454089c2d..8d54affc0a 100644
> --- a/fftools/ffmpeg.h
> +++ b/fftools/ffmpeg.h
> @@ -155,6 +155,7 @@ typedef struct OptionsContext {
>      SpecifierOptList hwaccel_devices;
>      SpecifierOptList hwaccel_output_formats;
>      SpecifierOptList autorotate;
> +    SpecifierOptList autoenhance;
>  
>      /* output options */
>      StreamMap *stream_maps;
> @@ -239,6 +240,7 @@ enum IFilterFlags {
>      IFILTER_FLAG_AUTOROTATE     = (1 << 0),
>      IFILTER_FLAG_REINIT         = (1 << 1),
>      IFILTER_FLAG_CFR            = (1 << 2),
> +    IFILTER_FLAG_AUTOENHANCE    = (1 << 3),
>  };
>  
>  typedef struct InputFilterOptions {
> @@ -369,6 +371,7 @@ typedef struct InputStream {
>  #endif
>  
>      int                   autorotate;
> +    int                   autoenhance;
>  
>      int                   fix_sub_duration;
>  
> diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
> index 47312c9fe1..0b4ab3d7ec 100644
> --- a/fftools/ffmpeg_demux.c
> +++ b/fftools/ffmpeg_demux.c
> @@ -1056,6 +1056,7 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple,
>          return AVERROR(ENOMEM);
>  
>      opts->flags |= IFILTER_FLAG_AUTOROTATE * !!(ist->autorotate) |
> +                   IFILTER_FLAG_AUTOENHANCE * !!(ist->autoenhance) |
>                     IFILTER_FLAG_REINIT     * !!(ds->reinit_filters);
>  
>      return ds->sch_idx_dec;
> @@ -1238,6 +1239,9 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>      ist->autorotate = 1;
>      MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
>  
> +    ist->autoenhance = 1;
> +    MATCH_PER_STREAM_OPT(autoenhance, i, ist->autoenhance, ic, st);
> +
>      MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
>      if (codec_tag) {
>          uint32_t tag = strtol(codec_tag, &next, 0);
> diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
> index 3d88482d07..c4d900d95b 100644
> --- a/fftools/ffmpeg_filter.c
> +++ b/fftools/ffmpeg_filter.c
> @@ -18,6 +18,8 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "config_components.h"
> +
>  #include <stdint.h>
>  
>  #include "ffmpeg.h"
> @@ -145,6 +147,8 @@ typedef struct InputFilterPriv {
>      int                 displaymatrix_present;
>      int32_t             displaymatrix[9];
>  
> +    int                 enhancement_present;
> +
>      // fallback parameters to use when no input is ever sent
>      struct {
>          AVRational          time_base;
> @@ -1567,6 +1571,15 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
>      desc = av_pix_fmt_desc_get(ifp->format);
>      av_assert0(desc);
>  
> +#if CONFIG_LCEVC_FILTER
> +    if ((ifp->opts.flags & IFILTER_FLAG_AUTOENHANCE) &&
> +        !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
> +        ret = insert_filter(&last_filter, &pad_idx, "lcevc", NULL);
> +        if (ret < 0)
> +            return ret;
> +    }

If I see this correctly, this will add this filter automatically for all
videos when this filter is present, although it will be unneeded in the
vast majority of cases. I am against this.

> +#endif
> +
>      // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph
>      if ((ifp->opts.flags & IFILTER_FLAG_AUTOROTATE) &&
>          !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
> @@ -1883,6 +1896,10 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
>          memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix));
>      ifp->displaymatrix_present = !!sd;
>  
> +#if CONFIG_LCEVC_FILTER
> +    ifp->enhancement_present = !!(av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC));
> +#endif
> +
>      return 0;
>  }
>  
> @@ -2584,7 +2601,8 @@ enum ReinitReason {
>      VIDEO_CHANGED   = (1 << 0),
>      AUDIO_CHANGED   = (1 << 1),
>      MATRIX_CHANGED  = (1 << 2),
> -    HWACCEL_CHANGED = (1 << 3)
> +    HWACCEL_CHANGED = (1 << 3),
> +    ENHANCEMENT_CHANGED = (1 << 4),
>  };
>  
>  static const char *unknown_if_null(const char *str)
> @@ -2625,6 +2643,12 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
>      } else if (ifp->displaymatrix_present)
>          need_reinit |= MATRIX_CHANGED;
>  
> +#if CONFIG_LCEVC_FILTER
> +    if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC))
> +        if (!ifp->enhancement_present)
> +            need_reinit |= ENHANCEMENT_CHANGED;
> +#endif
> +
>      if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph)
>          need_reinit = 0;
>  
> @@ -2681,6 +2705,8 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
>                  av_bprintf(&reason, "display matrix changed, ");
>              if (need_reinit & HWACCEL_CHANGED)
>                  av_bprintf(&reason, "hwaccel changed, ");
> +            if (need_reinit & ENHANCEMENT_CHANGED)
> +                av_bprintf(&reason, "enhancement data found, ");
>              if (reason.len > 1)
>                  reason.str[reason.len - 2] = '\0'; // remove last comma
>              av_log(fg, AV_LOG_INFO, "Reconfiguring filter graph%s%s\n", reason.len ? " because " : "", reason.str);
> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
> index 4b3f9789ba..b87782806e 100644
> --- a/fftools/ffmpeg_opt.c
> +++ b/fftools/ffmpeg_opt.c
> @@ -1738,6 +1738,9 @@ const OptionDef options[] = {
>      { "autorotate",                 OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_INPUT,
>          { .off = OFFSET(autorotate) },
>          "automatically insert correct rotate filters" },
> +    { "autoenhance",                OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_INPUT,
> +        { .off = OFFSET(autoenhance) },
> +        "automatically insert enhancement filters (LCEVC)" },
>      { "autoscale",                  OPT_TYPE_BOOL,   OPT_PERSTREAM | OPT_EXPERT | OPT_OUTPUT,
>          { .off = OFFSET(autoscale) },
>          "automatically insert a scale filter at the end of the filter graph" },

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 14:56   ` Andreas Rheinhardt
@ 2024-03-19 15:05     ` James Almer
  2024-03-19 15:20       ` Kieran Kunhya
  0 siblings, 1 reply; 12+ messages in thread
From: James Almer @ 2024-03-19 15:05 UTC (permalink / raw)
  To: ffmpeg-devel

On 3/19/2024 11:56 AM, Andreas Rheinhardt wrote:
> James Almer:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   configure                |   4 +
>>   libavfilter/Makefile     |   1 +
>>   libavfilter/allfilters.c |   1 +
>>   libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 472 insertions(+)
>>   create mode 100644 libavfilter/vf_lcevc.c
>>
>> diff --git a/configure b/configure
>> index e019d1b996..4022d13f76 100755
>> --- a/configure
>> +++ b/configure
>> @@ -224,6 +224,7 @@ External library support:
>>     --enable-libcdio         enable audio CD grabbing with libcdio [no]
>>     --enable-libcodec2       enable codec2 en/decoding using libcodec2 [no]
>>     --enable-libdav1d        enable AV1 decoding via libdav1d [no]
>> +  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]
> 
> How is this filter supposed to decode AV1 if it does not even get
> AVPackets? It seems to be for decoding an EVC enhancment layer instead.

Simple, it doesn't. It's a copy-paste fail from my part.
Fixed locally.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available
  2024-03-19 15:01   ` Andreas Rheinhardt
@ 2024-03-19 15:08     ` James Almer
  0 siblings, 0 replies; 12+ messages in thread
From: James Almer @ 2024-03-19 15:08 UTC (permalink / raw)
  To: ffmpeg-devel

On 3/19/2024 12:01 PM, Andreas Rheinhardt wrote:
> James Almer:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   fftools/ffmpeg.h        |  3 +++
>>   fftools/ffmpeg_demux.c  |  4 ++++
>>   fftools/ffmpeg_filter.c | 28 +++++++++++++++++++++++++++-
>>   fftools/ffmpeg_opt.c    |  3 +++
>>   4 files changed, 37 insertions(+), 1 deletion(-)
>>
>> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
>> index 7454089c2d..8d54affc0a 100644
>> --- a/fftools/ffmpeg.h
>> +++ b/fftools/ffmpeg.h
>> @@ -155,6 +155,7 @@ typedef struct OptionsContext {
>>       SpecifierOptList hwaccel_devices;
>>       SpecifierOptList hwaccel_output_formats;
>>       SpecifierOptList autorotate;
>> +    SpecifierOptList autoenhance;
>>   
>>       /* output options */
>>       StreamMap *stream_maps;
>> @@ -239,6 +240,7 @@ enum IFilterFlags {
>>       IFILTER_FLAG_AUTOROTATE     = (1 << 0),
>>       IFILTER_FLAG_REINIT         = (1 << 1),
>>       IFILTER_FLAG_CFR            = (1 << 2),
>> +    IFILTER_FLAG_AUTOENHANCE    = (1 << 3),
>>   };
>>   
>>   typedef struct InputFilterOptions {
>> @@ -369,6 +371,7 @@ typedef struct InputStream {
>>   #endif
>>   
>>       int                   autorotate;
>> +    int                   autoenhance;
>>   
>>       int                   fix_sub_duration;
>>   
>> diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
>> index 47312c9fe1..0b4ab3d7ec 100644
>> --- a/fftools/ffmpeg_demux.c
>> +++ b/fftools/ffmpeg_demux.c
>> @@ -1056,6 +1056,7 @@ int ist_filter_add(InputStream *ist, InputFilter *ifilter, int is_simple,
>>           return AVERROR(ENOMEM);
>>   
>>       opts->flags |= IFILTER_FLAG_AUTOROTATE * !!(ist->autorotate) |
>> +                   IFILTER_FLAG_AUTOENHANCE * !!(ist->autoenhance) |
>>                      IFILTER_FLAG_REINIT     * !!(ds->reinit_filters);
>>   
>>       return ds->sch_idx_dec;
>> @@ -1238,6 +1239,9 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
>>       ist->autorotate = 1;
>>       MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
>>   
>> +    ist->autoenhance = 1;
>> +    MATCH_PER_STREAM_OPT(autoenhance, i, ist->autoenhance, ic, st);
>> +
>>       MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
>>       if (codec_tag) {
>>           uint32_t tag = strtol(codec_tag, &next, 0);
>> diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
>> index 3d88482d07..c4d900d95b 100644
>> --- a/fftools/ffmpeg_filter.c
>> +++ b/fftools/ffmpeg_filter.c
>> @@ -18,6 +18,8 @@
>>    * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>>    */
>>   
>> +#include "config_components.h"
>> +
>>   #include <stdint.h>
>>   
>>   #include "ffmpeg.h"
>> @@ -145,6 +147,8 @@ typedef struct InputFilterPriv {
>>       int                 displaymatrix_present;
>>       int32_t             displaymatrix[9];
>>   
>> +    int                 enhancement_present;
>> +
>>       // fallback parameters to use when no input is ever sent
>>       struct {
>>           AVRational          time_base;
>> @@ -1567,6 +1571,15 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
>>       desc = av_pix_fmt_desc_get(ifp->format);
>>       av_assert0(desc);
>>   
>> +#if CONFIG_LCEVC_FILTER
>> +    if ((ifp->opts.flags & IFILTER_FLAG_AUTOENHANCE) &&
>> +        !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
>> +        ret = insert_filter(&last_filter, &pad_idx, "lcevc", NULL);
>> +        if (ret < 0)
>> +            return ret;
>> +    }
> 
> If I see this correctly, this will add this filter automatically for all
> videos when this filter is present, although it will be unneeded in the
> vast majority of cases. I am against this.

Yeah, good catch. Missed a ifp->enhancement_present check here.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 15:05     ` James Almer
@ 2024-03-19 15:20       ` Kieran Kunhya
  2024-03-19 15:28         ` James Almer
  0 siblings, 1 reply; 12+ messages in thread
From: Kieran Kunhya @ 2024-03-19 15:20 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Tue, 19 Mar 2024 at 15:05, James Almer <jamrial@gmail.com> wrote:

> On 3/19/2024 11:56 AM, Andreas Rheinhardt wrote:
> > James Almer:
> >> Signed-off-by: James Almer <jamrial@gmail.com>
> >> ---
> >>   configure                |   4 +
> >>   libavfilter/Makefile     |   1 +
> >>   libavfilter/allfilters.c |   1 +
> >>   libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++
> >>   4 files changed, 472 insertions(+)
> >>   create mode 100644 libavfilter/vf_lcevc.c
> >>
> >> diff --git a/configure b/configure
> >> index e019d1b996..4022d13f76 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -224,6 +224,7 @@ External library support:
> >>     --enable-libcdio         enable audio CD grabbing with libcdio [no]
> >>     --enable-libcodec2       enable codec2 en/decoding using libcodec2
> [no]
> >>     --enable-libdav1d        enable AV1 decoding via libdav1d [no]
> >> +  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]
> >
> > How is this filter supposed to decode AV1 if it does not even get
> > AVPackets? It seems to be for decoding an EVC enhancment layer instead.
>
> Simple, it doesn't. It's a copy-paste fail from my part.
> Fixed locally.
>
>
From https://github.com/v-novaltd/LCEVCdec
" This software is protected by copyrights and other intellectual property
rights and no license is granted to any such rights. If you would like to
obtain a license to compile, distribute, or make any other use of this
software, please contact V-Nova Limited info@v-nova.com."

So you want to include a library that requires ffmpeg users to obtain a
licence to compile?

Kieran
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 15:20       ` Kieran Kunhya
@ 2024-03-19 15:28         ` James Almer
  2024-03-19 17:21           ` Kieran Kunhya
  0 siblings, 1 reply; 12+ messages in thread
From: James Almer @ 2024-03-19 15:28 UTC (permalink / raw)
  To: ffmpeg-devel

On 3/19/2024 12:20 PM, Kieran Kunhya wrote:
> On Tue, 19 Mar 2024 at 15:05, James Almer <jamrial@gmail.com> wrote:
> 
>> On 3/19/2024 11:56 AM, Andreas Rheinhardt wrote:
>>> James Almer:
>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>> ---
>>>>    configure                |   4 +
>>>>    libavfilter/Makefile     |   1 +
>>>>    libavfilter/allfilters.c |   1 +
>>>>    libavfilter/vf_lcevc.c   | 466 +++++++++++++++++++++++++++++++++++++++
>>>>    4 files changed, 472 insertions(+)
>>>>    create mode 100644 libavfilter/vf_lcevc.c
>>>>
>>>> diff --git a/configure b/configure
>>>> index e019d1b996..4022d13f76 100755
>>>> --- a/configure
>>>> +++ b/configure
>>>> @@ -224,6 +224,7 @@ External library support:
>>>>      --enable-libcdio         enable audio CD grabbing with libcdio [no]
>>>>      --enable-libcodec2       enable codec2 en/decoding using libcodec2
>> [no]
>>>>      --enable-libdav1d        enable AV1 decoding via libdav1d [no]
>>>> +  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]
>>>
>>> How is this filter supposed to decode AV1 if it does not even get
>>> AVPackets? It seems to be for decoding an EVC enhancment layer instead.
>>
>> Simple, it doesn't. It's a copy-paste fail from my part.
>> Fixed locally.
>>
>>
>  From https://github.com/v-novaltd/LCEVCdec
> " This software is protected by copyrights and other intellectual property
> rights and no license is granted to any such rights. If you would like to
> obtain a license to compile, distribute, or make any other use of this
> software, please contact V-Nova Limited info@v-nova.com."
> 
> So you want to include a library that requires ffmpeg users to obtain a
> licence to compile?

Would adding it to the nonfree list be enough? But it's true that most 
users would not be aware of the aforementioned limitations.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
  2024-03-19 15:28         ` James Almer
@ 2024-03-19 17:21           ` Kieran Kunhya
       [not found]             ` <BB9E2F8E-6821-43B7-9021-C264A8AFCE35@cosmin.at>
  0 siblings, 1 reply; 12+ messages in thread
From: Kieran Kunhya @ 2024-03-19 17:21 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Tue, 19 Mar 2024 at 15:27, James Almer <jamrial@gmail.com> wrote:

> On 3/19/2024 12:20 PM, Kieran Kunhya wrote:
> > On Tue, 19 Mar 2024 at 15:05, James Almer <jamrial@gmail.com> wrote:
> >
> >> On 3/19/2024 11:56 AM, Andreas Rheinhardt wrote:
> >>> James Almer:
> >>>> Signed-off-by: James Almer <jamrial@gmail.com>
> >>>> ---
> >>>>    configure                |   4 +
> >>>>    libavfilter/Makefile     |   1 +
> >>>>    libavfilter/allfilters.c |   1 +
> >>>>    libavfilter/vf_lcevc.c   | 466
> +++++++++++++++++++++++++++++++++++++++
> >>>>    4 files changed, 472 insertions(+)
> >>>>    create mode 100644 libavfilter/vf_lcevc.c
> >>>>
> >>>> diff --git a/configure b/configure
> >>>> index e019d1b996..4022d13f76 100755
> >>>> --- a/configure
> >>>> +++ b/configure
> >>>> @@ -224,6 +224,7 @@ External library support:
> >>>>      --enable-libcdio         enable audio CD grabbing with libcdio
> [no]
> >>>>      --enable-libcodec2       enable codec2 en/decoding using
> libcodec2
> >> [no]
> >>>>      --enable-libdav1d        enable AV1 decoding via libdav1d [no]
> >>>> +  --enable-liblcevc_dec    enable AV1 decoding via liblcevc_dec [no]
> >>>
> >>> How is this filter supposed to decode AV1 if it does not even get
> >>> AVPackets? It seems to be for decoding an EVC enhancment layer instead.
> >>
> >> Simple, it doesn't. It's a copy-paste fail from my part.
> >> Fixed locally.
> >>
> >>
> >  From https://github.com/v-novaltd/LCEVCdec
> > " This software is protected by copyrights and other intellectual
> property
> > rights and no license is granted to any such rights. If you would like to
> > obtain a license to compile, distribute, or make any other use of this
> > software, please contact V-Nova Limited info@v-nova.com."
> >
> > So you want to include a library that requires ffmpeg users to obtain a
> > licence to compile?
>
> Would adding it to the nonfree list be enough? But it's true that most
> users would not be aware of the aforementioned limitations.
>
>
This is a slippery slope to adding whatever binary blob. As the decoder is
de-facto a binary blob.

Kieran
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter
       [not found]             ` <BB9E2F8E-6821-43B7-9021-C264A8AFCE35@cosmin.at>
@ 2024-03-19 19:07               ` Cosmin Stejerean via ffmpeg-devel
  0 siblings, 0 replies; 12+ messages in thread
From: Cosmin Stejerean via ffmpeg-devel @ 2024-03-19 19:07 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Cosmin Stejerean

On Mar 19, 2024, at 10:21 AM, Kieran Kunhya <kierank@obe.tv> wrote:

On Tue, 19 Mar 2024 at 15:27, James Almer <jamrial@gmail.com <mailto:jamrial@gmail.com> > wrote:

On 3/19/2024 12:20 PM, Kieran Kunhya wrote:From https://github.com/v-novaltd/LCEVCdec
" This software is protected by copyrights and other intellectual
property
rights and no license is granted to any such rights. If you would like to
obtain a license to compile, distribute, or make any other use of this
software, please contact V-Nova Limited info@v-nova.com."

So you want to include a library that requires ffmpeg users to obtain a
licence to compile?

Would adding it to the nonfree list be enough? But it's true that most

users would not be aware of the aforementioned limitations.


This is a slippery slope to adding whatever binary blob. As the decoder is
de-facto a binary blob.


Yeah, source available but with a prohibition on compilation might as well be a binary blob. Even to be on non-free I'd expect something along the lines of the FDK-AAC license at a minimum.

- Cosmin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2024-03-19 19:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-19 14:06 [FFmpeg-devel] [PATCH 1/3] libavcodec/h2645_sei: export raw LCEVC metadata James Almer
2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 2/3] avfilter: add an LCEVC decoding filter James Almer
2024-03-19 14:56   ` Andreas Rheinhardt
2024-03-19 15:05     ` James Almer
2024-03-19 15:20       ` Kieran Kunhya
2024-03-19 15:28         ` James Almer
2024-03-19 17:21           ` Kieran Kunhya
     [not found]             ` <BB9E2F8E-6821-43B7-9021-C264A8AFCE35@cosmin.at>
2024-03-19 19:07               ` Cosmin Stejerean via ffmpeg-devel
2024-03-19 15:00   ` Stefano Sabatini
2024-03-19 14:06 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg: auto insert enhancement filters when available James Almer
2024-03-19 15:01   ` Andreas Rheinhardt
2024-03-19 15:08     ` James Almer

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git