* [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
* 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: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 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
[parent not found: <BB9E2F8E-6821-43B7-9021-C264A8AFCE35@cosmin.at>]
* 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
* 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
* [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 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 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
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