* [FFmpeg-devel] [PATCH 2/4] libavcodec/h2645_sei: export raw LCEVC metadata
2024-07-20 12:45 [FFmpeg-devel] [PATCH 1/4] avutil/frame: add an LCEVC enhancement data payload side data type James Almer
@ 2024-07-20 12:45 ` James Almer
2024-07-20 23:38 ` Michael Niedermayer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 3/4] avcodec: add LCEVC decoding support via LCEVCdec James Almer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 4/4] avcodec/h264dec: add support for LCEVC enhancement James Almer
2 siblings, 1 reply; 8+ messages in thread
From: James Almer @ 2024-07-20 12:45 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 ++
3 files changed, 43 insertions(+)
diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c
index 7c83747cd0..90e59df781 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;
@@ -501,6 +523,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,
@@ -666,6 +693,14 @@ static int h2645_sei_to_side_data(AVCodecContext *avctx, 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;
}
@@ -875,6 +910,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 488dbcad7e..598f78b585 100644
--- a/libavcodec/h2645_sei.h
+++ b/libavcodec/h2645_sei.h
@@ -50,6 +50,10 @@ typedef struct HEVCSEIDynamicHDRVivid {
AVBufferRef *info;
} HEVCSEIDynamicHDRVivid;
+typedef struct HEVCSEILCEVC {
+ AVBufferRef *info;
+} HEVCSEILCEVC;
+
typedef struct H2645SEIUnregistered {
AVBufferRef **buf_ref;
unsigned nb_buf_ref;
@@ -126,6 +130,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 */
--
2.45.2
_______________________________________________
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] 8+ messages in thread
* [FFmpeg-devel] [PATCH 3/4] avcodec: add LCEVC decoding support via LCEVCdec
2024-07-20 12:45 [FFmpeg-devel] [PATCH 1/4] avutil/frame: add an LCEVC enhancement data payload side data type James Almer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 2/4] libavcodec/h2645_sei: export raw LCEVC metadata James Almer
@ 2024-07-20 12:45 ` James Almer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 4/4] avcodec/h264dec: add support for LCEVC enhancement James Almer
2 siblings, 0 replies; 8+ messages in thread
From: James Almer @ 2024-07-20 12:45 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
configure | 5 +-
doc/general_contents.texi | 13 ++
libavcodec/h264dec.c | 1 +
libavcodec/lcevcdec.c | 276 ++++++++++++++++++++++++++++++++++++++
libavcodec/lcevcdec.h | 39 ++++++
5 files changed, 333 insertions(+), 1 deletion(-)
create mode 100644 libavcodec/lcevcdec.c
create mode 100644 libavcodec/lcevcdec.h
diff --git a/configure b/configure
index f6f5c29fea..7bc8c3b0af 100755
--- a/configure
+++ b/configure
@@ -225,6 +225,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 LCEVC decoding via liblcevc_dec [no]
--enable-libdavs2 enable AVS2 decoding via libdavs2 [no]
--enable-libdc1394 enable IIDC-1394 grabbing using libdc1394
and libraw1394 [no]
@@ -1914,6 +1915,7 @@ EXTERNAL_LIBRARY_LIST="
libcelt
libcodec2
libdav1d
+ liblcevc_dec
libdc1394
libflite
libfontconfig
@@ -2966,7 +2968,7 @@ h263i_decoder_select="h263_decoder"
h263p_decoder_select="h263_decoder"
h263p_encoder_select="h263_encoder"
h264_decoder_select="cabac golomb h264chroma h264dsp h264parse h264pred h264qpel h264_sei videodsp"
-h264_decoder_suggest="error_resilience"
+h264_decoder_suggest="error_resilience liblcevc_dec"
hap_decoder_select="snappy texturedsp"
hap_encoder_deps="libsnappy"
hap_encoder_select="texturedspenc"
@@ -6854,6 +6856,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 &&
enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas
enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2
enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version
+enabled liblcevc_dec && require_pkg_config liblcevc_dec "lcevc_dec >= 2.0.0" "LCEVC/lcevc_dec.h" LCEVC_CreateDecoder
enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open
enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
enabled libdrm && check_pkg_config libdrm libdrm xf86drm.h drmGetVersion
diff --git a/doc/general_contents.texi b/doc/general_contents.texi
index e7cf4f8239..ecaf3979ce 100644
--- a/doc/general_contents.texi
+++ b/doc/general_contents.texi
@@ -245,6 +245,19 @@ Go to @url{https://github.com/google/liblc3/} and follow the instructions for
installing the library.
Then pass @code{--enable-liblc3} to configure to enable it.
+@section LCEVCdec
+
+FFmpeg can make use of the liblcevc_dec library for LCEVC enhacement layer
+decoding on supported bitstreams.
+
+Go to @url{https://github.com/v-novaltd/LCEVCdec} and follow the instructions
+for installing the library. Then pass @code{--enable-libvpx} to configure to
+enable it.
+
+@float NOTE
+LCEVCdec is under the BSD-3-Clause-Clear License.
+@end float
+
@section OpenH264
FFmpeg can make use of the OpenH264 library for H.264 decoding and encoding.
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index c77d8f42db..e186bc18dc 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -38,6 +38,7 @@
#include "libavutil/video_enc_params.h"
#include "codec_internal.h"
+#include "decode.h"
#include "internal.h"
#include "error_resilience.h"
#include "avcodec.h"
diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c
new file mode 100644
index 0000000000..4edb0b72dc
--- /dev/null
+++ b/libavcodec/lcevcdec.c
@@ -0,0 +1,276 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * 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 "libavutil/avassert.h"
+#include "libavutil/frame.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "decode.h"
+#include "lcevcdec.h"
+
+static LCEVC_ColorFormat map_format(int format)
+{
+ switch (format) {
+ case AV_PIX_FMT_YUV420P:
+ return LCEVC_I420_8;
+ case AV_PIX_FMT_YUV420P10:
+ return LCEVC_I420_10_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;
+ }
+
+ return LCEVC_ColorFormat_Unknown;
+}
+
+static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder,
+ const AVFrame *frame, LCEVC_PictureHandle *picture)
+{
+ LCEVC_PictureDesc desc;
+ LCEVC_ColorFormat fmt = map_format(frame->format);
+ LCEVC_PictureLockHandle lock;
+ uint8_t *data[4] = { NULL };
+ int linesizes[4] = { 0 };
+ uint32_t planes;
+ LCEVC_ReturnCode res;
+
+ res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ desc.cropTop = frame->crop_top;
+ desc.cropBottom = frame->crop_bottom;
+ desc.cropLeft = frame->crop_left;
+ desc.cropRight = frame->crop_right;
+ desc.sampleAspectRatioNum = frame->sample_aspect_ratio.num;
+ desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den;
+
+ /* Allocate LCEVC Picture */
+ res = LCEVC_AllocPicture(decoder, &desc, picture);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ res = LCEVC_LockPicture(decoder, *picture, LCEVC_Access_Write, &lock);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ res = LCEVC_GetPicturePlaneCount(decoder, *picture, &planes);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ for (unsigned i = 0; i < planes; i++) {
+ LCEVC_PicturePlaneDesc plane;
+
+ res = LCEVC_GetPictureLockPlaneDesc(decoder, lock, i, &plane);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ data[i] = plane.firstSample;
+ linesizes[i] = plane.rowByteStride;
+ }
+
+ av_image_copy2(data, linesizes, frame->data, frame->linesize,
+ frame->format, frame->width, frame->height);
+
+ res = LCEVC_UnlockPicture(decoder, lock);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ return 0;
+}
+
+static int alloc_enhanced_frame(void *logctx, LCEVC_DecoderHandle decoder,
+ const AVFrame *frame, LCEVC_PictureHandle *picture)
+{
+ LCEVC_PictureDesc desc ;
+ LCEVC_ColorFormat fmt = map_format(frame->format);
+ LCEVC_PicturePlaneDesc planes[4] = { 0 };
+ int width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1);
+ int height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1);
+ LCEVC_ReturnCode res;
+
+ res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ /* Set plane description */
+ for (int i = 0; i < 4; i++) {
+ planes[i].firstSample = frame->data[i];
+ planes[i].rowByteStride = frame->linesize[i];
+ }
+
+ /* Allocate LCEVC Picture */
+ res = LCEVC_AllocPictureExternal(decoder, &desc, NULL, planes, picture);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ return 0;
+}
+
+int ff_lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in)
+{
+ const AVFrameSideData *sd = av_frame_get_side_data(in, AV_FRAME_DATA_LCEVC);
+ LCEVC_PictureHandle picture;
+ LCEVC_ReturnCode res;
+ int ret = 0;
+
+ if (!sd)
+ return 0;
+
+ res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ ret = alloc_base_frame(logctx, lcevc->decoder, in, &picture);
+ if (ret < 0)
+ return ret;
+
+ res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ memset(&picture, 0, sizeof(picture));
+ ret = alloc_enhanced_frame(logctx, lcevc->decoder, in, &picture);
+ if (ret < 0)
+ return ret;
+
+ res = LCEVC_SendDecoderPicture(lcevc->decoder, picture);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ return 0;
+}
+
+static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
+{
+ LCEVC_PictureDesc desc;
+ LCEVC_DecodeInformation info;
+ LCEVC_PictureHandle picture;
+ LCEVC_ReturnCode res;
+
+ res = LCEVC_ReceiveDecoderPicture(lcevc->decoder, &picture, &info);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc);
+ if (res != LCEVC_Success)
+ 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 = desc.sampleAspectRatioNum;
+ out->sample_aspect_ratio.den = desc.sampleAspectRatioDen;
+ out->width = desc.width + out->crop_left + out->crop_right;
+ out->height = desc.height + out->crop_top + out->crop_bottom;
+
+ return 0;
+}
+
+int ff_lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out)
+{
+ LCEVC_PictureHandle picture;
+ LCEVC_ReturnCode res;
+ int ret;
+
+ ret = generate_output(logctx, lcevc, out);
+ if (ret < 0)
+ return ret;
+
+ res = LCEVC_ReceiveDecoderBase (lcevc->decoder, &picture);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ res = LCEVC_FreePicture(lcevc->decoder, picture);
+ if (res != LCEVC_Success)
+ return AVERROR_EXTERNAL;
+
+ return 0;
+}
+
+int ff_lcevc_process(void *logctx, AVFrame *frame)
+{
+ FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;
+ AVBufferRef *ref = (AVBufferRef*)fdd->post_process_opaque;
+ FFLCEVCContext *lcevc = (FFLCEVCContext*)ref->data;
+ int ret;
+
+ ret = ff_lcevc_send_frame(logctx, lcevc, frame);
+ if (ret < 0)
+ return ret;
+
+ ff_lcevc_receive_frame(logctx, lcevc, frame);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event,
+ LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info,
+ const uint8_t *data, uint32_t size, void *logctx)
+{
+ switch (event) {
+ case LCEVC_Log:
+ av_log(logctx, AV_LOG_INFO, "%s\n", data);
+ break;
+ default:
+ break;
+ }
+}
+
+int ff_lcevc_init(FFLCEVCContext *lcevc, void *logctx)
+{
+ LCEVC_AccelContextHandle dummy = { 0 };
+
+ int32_t events[] = { LCEVC_Log };
+
+ if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) {
+ av_log(logctx, AV_LOG_ERROR, "Failed to create LCEVC decoder\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ LCEVC_ConfigureDecoderInt(lcevc->decoder, "log_level", 4);
+ LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", FF_ARRAY_ELEMS(events), events);
+ LCEVC_SetDecoderEventCallback(lcevc->decoder, event_callback, logctx);
+
+ if (LCEVC_InitializeDecoder(lcevc->decoder) != LCEVC_Success) {
+ av_log(logctx, AV_LOG_ERROR, "Failed to initialize LCEVC decoder\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+}
+
+void ff_lcevc_free(void *opaque, uint8_t *data)
+{
+ FFLCEVCContext *lcevc = opaque;
+ LCEVC_DestroyDecoder(lcevc->decoder);
+ av_free(data);
+}
+
+void ff_lcevc_unref(void *opaque)
+{
+ AVBufferRef *ref = opaque;
+ av_buffer_unref(&ref);
+}
diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h
new file mode 100644
index 0000000000..436bbab7bc
--- /dev/null
+++ b/libavcodec/lcevcdec.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_LCEVCDEC_H
+#define AVCODEC_LCEVCDEC_H
+
+#include <stdint.h>
+
+#include <LCEVC/lcevc_dec.h>
+
+typedef struct FFLCEVCContext {
+ LCEVC_DecoderHandle decoder;
+} FFLCEVCContext;
+
+struct AVFrame;
+
+int ff_lcevc_process(void *logctx, struct AVFrame *frame);
+int ff_lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in);
+int ff_lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out);
+int ff_lcevc_init(FFLCEVCContext *lcevc, void *logctx);
+void ff_lcevc_unref(void *opaque);
+void ff_lcevc_free(void *opaque, uint8_t *data);
+
+#endif /* AVCODEC_LCEVCDEC_H */
--
2.45.2
_______________________________________________
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] 8+ messages in thread
* [FFmpeg-devel] [PATCH 4/4] avcodec/h264dec: add support for LCEVC enhancement
2024-07-20 12:45 [FFmpeg-devel] [PATCH 1/4] avutil/frame: add an LCEVC enhancement data payload side data type James Almer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 2/4] libavcodec/h2645_sei: export raw LCEVC metadata James Almer
2024-07-20 12:45 ` [FFmpeg-devel] [PATCH 3/4] avcodec: add LCEVC decoding support via LCEVCdec James Almer
@ 2024-07-20 12:45 ` James Almer
2 siblings, 0 replies; 8+ messages in thread
From: James Almer @ 2024-07-20 12:45 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/Makefile | 2 +-
libavcodec/avcodec.h | 5 ++++
libavcodec/h264_picture.c | 1 +
libavcodec/h264_slice.c | 19 ++++++++++++++++
libavcodec/h264dec.c | 48 ++++++++++++++++++++++++++++++++++++---
libavcodec/h264dec.h | 3 +++
6 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 771e2b597e..69492eee10 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -407,7 +407,7 @@ OBJS-$(CONFIG_H263_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
h264_direct.o h264_loopfilter.o \
h264_mb.o h264_picture.o \
- h264_refs.o \
+ h264_refs.o lcevcdec.o \
h264_slice.o h264data.o h274.o
OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2da63c87ea..ff20d22545 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -418,6 +418,11 @@ typedef struct RcOverride{
* Do not apply film grain, export it instead.
*/
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3)
+/**
+ * Decoding only.
+ * Do not apply picture enhancement layers, export them instead.
+ */
+#define AV_CODEC_EXPORT_DATA_ENHANCEMENTS (1 << 3)
/**
* The decoder will keep a reference to the frame and may reuse it later.
diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c
index 3234141dbd..1cdb926d15 100644
--- a/libavcodec/h264_picture.c
+++ b/libavcodec/h264_picture.c
@@ -103,6 +103,7 @@ static void h264_copy_picture_params(H264Picture *dst, const H264Picture *src)
dst->mb_height = src->mb_height;
dst->mb_stride = src->mb_stride;
dst->needs_fg = src->needs_fg;
+ dst->needs_lcevc = src->needs_lcevc;
}
int ff_h264_ref_picture(H264Picture *dst, const H264Picture *src)
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index a66b75ca80..263172e600 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -191,6 +191,13 @@ static int alloc_picture(H264Context *h, H264Picture *pic)
av_assert0(!pic->f->data[0]);
+#if CONFIG_LIBLCEVC_DEC
+ if (pic->needs_lcevc) {
+ pic->f->width = FFMAX(h->avctx->width, h->avctx->coded_width) * 2 / FFMAX(h->avctx->sample_aspect_ratio.den, 1);
+ pic->f->height = FFMAX(h->avctx->height, h->avctx->coded_height) * 2 / FFMAX(h->avctx->sample_aspect_ratio.num, 1);
+ }
+#endif
+
pic->tf.f = pic->f;
ret = ff_thread_get_ext_buffer(h->avctx, &pic->tf,
pic->reference ? AV_GET_BUFFER_FLAG_REF : 0);
@@ -206,6 +213,13 @@ static int alloc_picture(H264Context *h, H264Picture *pic)
goto fail;
}
+#if CONFIG_LIBLCEVC_DEC
+ if (pic->needs_lcevc) {
+ pic->f->width = FFMAX(h->avctx->width, h->avctx->coded_width);
+ pic->f->height = FFMAX(h->avctx->height, h->avctx->coded_height);
+ }
+#endif
+
ret = ff_hwaccel_frame_priv_alloc(h->avctx, &pic->hwaccel_picture_private);
if (ret < 0)
goto fail;
@@ -459,6 +473,8 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
h->recovery_frame = h1->recovery_frame;
h->non_gray = h1->non_gray;
+ av_buffer_replace(&h->lcevc, h1->lcevc);
+
return err;
}
@@ -519,6 +535,9 @@ static int h264_frame_start(H264Context *h)
pic->needs_fg = h->sei.common.film_grain_characteristics.present && !h->avctx->hwaccel &&
!(h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
+ pic->needs_lcevc = h->sei.common.lcevc.info && !h->avctx->hwaccel &&
+ !(h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_ENHANCEMENTS);
+
if ((ret = alloc_picture(h, pic)) < 0)
return ret;
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index e186bc18dc..a80d8e16d5 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -57,6 +57,10 @@
#include "thread.h"
#include "threadframe.h"
+#if CONFIG_LIBLCEVC_DEC
+#include "lcevcdec.h"
+#endif
+
const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 };
int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx)
@@ -378,6 +382,8 @@ static av_cold int h264_decode_end(AVCodecContext *avctx)
h264_free_pic(h, &h->cur_pic);
h264_free_pic(h, &h->last_pic_for_ec);
+ av_buffer_unref(&h->lcevc);
+
return 0;
}
@@ -405,6 +411,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
#endif
if (!avctx->internal->is_copy) {
+#if CONFIG_LIBLCEVC_DEC
+ FFLCEVCContext *lcevc;
+#endif
if (avctx->extradata_size > 0 && avctx->extradata) {
ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
&h->ps, &h->is_avc, &h->nal_length_size,
@@ -419,6 +428,21 @@ FF_ENABLE_DEPRECATION_WARNINGS
ret = 0;
}
}
+#if CONFIG_LIBLCEVC_DEC
+ lcevc = av_mallocz(sizeof(FFLCEVCContext));
+ ret = ff_lcevc_init(lcevc, avctx);
+ if (ret < 0) {
+ int explode = avctx->err_recognition & AV_EF_EXPLODE;
+ av_log(avctx, explode ? AV_LOG_ERROR: AV_LOG_WARNING,
+ "Error initializing LCEVC\n");
+ if (explode) {
+ av_free(lcevc);
+ return ret;
+ }
+ ret = 0;
+ }
+ h->lcevc = av_buffer_create(lcevc, sizeof(FFLCEVCContext), ff_lcevc_free, lcevc, 0);
+#endif
}
if (h->ps.sps && h->ps.sps->bitstream_restriction_flag &&
@@ -668,9 +692,23 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
h->setup_finished = 1;
}
- if (h->avctx->hwaccel &&
- (ret = FF_HW_CALL(h->avctx, start_frame, buf, buf_size)) < 0)
- goto end;
+ if (h->avctx->hwaccel) {
+ ret = FF_HW_CALL(h->avctx, start_frame, buf, buf_size);
+ if (ret < 0)
+ goto end;
+ }
+#if CONFIG_LIBLCEVC_DEC
+ else if (h->cur_pic_ptr->needs_lcevc) {
+ FrameDecodeData *fdd = (FrameDecodeData*)h->cur_pic_ptr->f->private_ref->data;
+ fdd->post_process_opaque = av_buffer_ref(h->lcevc);
+ if (!fdd->post_process_opaque) {
+ ret = -1;
+ goto end;
+ }
+ fdd->post_process_opaque_free = ff_lcevc_unref;
+ fdd->post_process = ff_lcevc_process;
+ }
+#endif
}
max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx;
@@ -905,6 +943,10 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
if (!(h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
av_frame_remove_side_data(dst, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
+#if CONFIG_LIBLCEVC_DEC
+ if (!(h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_ENHANCEMENTS))
+ av_frame_remove_side_data(dst, AV_FRAME_DATA_LCEVC);
+#endif
return 0;
fail:
diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h
index ccd7583bf4..419d699bab 100644
--- a/libavcodec/h264dec.h
+++ b/libavcodec/h264dec.h
@@ -154,6 +154,7 @@ typedef struct H264Picture {
int invalid_gap;
int sei_recovery_frame_cnt;
int needs_fg; ///< whether picture needs film grain synthesis (see `f_grain`)
+ int needs_lcevc; ///< whether picture needs LCEVC enhancement
const PPS *pps;
@@ -580,6 +581,8 @@ typedef struct H264Context {
int non_gray; ///< Did we encounter a intra frame after a gray gap frame
int noref_gray;
int skip_gray;
+
+ AVBufferRef *lcevc; // FFLCEVCContext
} H264Context;
extern const uint16_t ff_h264_mb_sizes[4];
--
2.45.2
_______________________________________________
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] 8+ messages in thread