[FFmpeg-cvslog] avcodec/hevcdec: export global side data in AVCodecContext
James Almer
git at videolan.org
Thu Apr 11 18:02:37 EEST 2024
ffmpeg | branch: master | James Almer <jamrial at gmail.com> | Thu Mar 28 12:50:54 2024 -0300| [6d0c89980c78ffd3b112676186786334c915ace7] | committer: James Almer
avcodec/hevcdec: export global side data in AVCodecContext
Signed-off-by: James Almer <jamrial at gmail.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6d0c89980c78ffd3b112676186786334c915ace7
---
doc/APIchanges | 4 +
libavcodec/avcodec.h | 2 +-
libavcodec/h2645_sei.c | 214 ++++++++++++++++++++++++++-------------------
libavcodec/h2645_sei.h | 2 +
libavcodec/hevcdec.c | 4 +
libavcodec/pthread_frame.c | 14 ++-
libavcodec/version.h | 2 +-
7 files changed, 147 insertions(+), 95 deletions(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index d7c2056f0e..63e7a47126 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2024-03-07
API changes, most recent first:
+2024-04-11 - xxxxxxxxxx - lavc 61.5.102 - avcodec.h
+ AVCodecContext.decoded_side_data may now be set by libavcodec after
+ calling avcodec_open2().
+
2024-04-11 - xxxxxxxxxx - lavu 59.15.100 - frame.h
Add av_mastering_display_metadata_alloc_size().
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 83dc487251..968009a192 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2071,7 +2071,7 @@ typedef struct AVCodecContext {
* - encoding: may be set by user before calling avcodec_open2() for
* encoder configuration. Afterwards owned and freed by the
* encoder.
- * - decoding: unused
+ * - decoding: may be set by libavcodec in avcodec_open2().
*/
AVFrameSideData **decoded_side_data;
int nb_decoded_side_data;
diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c
index f0f107f73b..933975f076 100644
--- a/libavcodec/h2645_sei.c
+++ b/libavcodec/h2645_sei.c
@@ -529,6 +529,119 @@ static int is_frame_packing_type_valid(SEIFpaType type, enum AVCodecID codec_id)
type >= SEI_FPA_TYPE_SIDE_BY_SIDE;
}
+static int h2645_sei_to_side_data(AVCodecContext *avctx, H2645SEI *sei,
+ AVFrameSideData ***sd, int *nb_sd)
+{
+ int ret;
+
+ for (unsigned i = 0; i < sei->unregistered.nb_buf_ref; i++) {
+ H2645SEIUnregistered *unreg = &sei->unregistered;
+
+ if (unreg->buf_ref[i]) {
+ AVFrameSideData *entry =
+ av_frame_side_data_add(sd, nb_sd, AV_FRAME_DATA_SEI_UNREGISTERED,
+ &unreg->buf_ref[i], 0);
+ if (!entry)
+ av_buffer_unref(&unreg->buf_ref[i]);
+ }
+ }
+ sei->unregistered.nb_buf_ref = 0;
+
+ if (sei->ambient_viewing_environment.present) {
+ H2645SEIAmbientViewingEnvironment *env = &sei->ambient_viewing_environment;
+ AVBufferRef *buf;
+ size_t size;
+
+ AVAmbientViewingEnvironment *dst_env =
+ av_ambient_viewing_environment_alloc(&size);
+ if (!dst_env)
+ return AVERROR(ENOMEM);
+
+ buf = av_buffer_create((uint8_t *)dst_env, size, NULL, NULL, 0);
+ if (!buf) {
+ av_free(dst_env);
+ return AVERROR(ENOMEM);
+ }
+
+ ret = ff_frame_new_side_data_from_buf_ext(avctx, sd, nb_sd,
+ AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT, &buf);
+
+ if (ret < 0)
+ return ret;
+
+ dst_env->ambient_illuminance = av_make_q(env->ambient_illuminance, 10000);
+ dst_env->ambient_light_x = av_make_q(env->ambient_light_x, 50000);
+ dst_env->ambient_light_y = av_make_q(env->ambient_light_y, 50000);
+ }
+
+ if (sei->mastering_display.present) {
+ // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b
+ const int mapping[3] = {2, 0, 1};
+ const int chroma_den = 50000;
+ const int luma_den = 10000;
+ int i;
+ AVMasteringDisplayMetadata *metadata;
+
+ ret = ff_decode_mastering_display_new_ext(avctx, sd, nb_sd, &metadata);
+ if (ret < 0)
+ return ret;
+
+ if (metadata) {
+ for (i = 0; i < 3; i++) {
+ const int j = mapping[i];
+ metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0];
+ metadata->display_primaries[i][0].den = chroma_den;
+ metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1];
+ metadata->display_primaries[i][1].den = chroma_den;
+ }
+ metadata->white_point[0].num = sei->mastering_display.white_point[0];
+ metadata->white_point[0].den = chroma_den;
+ metadata->white_point[1].num = sei->mastering_display.white_point[1];
+ metadata->white_point[1].den = chroma_den;
+
+ metadata->max_luminance.num = sei->mastering_display.max_luminance;
+ metadata->max_luminance.den = luma_den;
+ metadata->min_luminance.num = sei->mastering_display.min_luminance;
+ metadata->min_luminance.den = luma_den;
+ metadata->has_luminance = 1;
+ metadata->has_primaries = 1;
+
+ av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n");
+ av_log(avctx, AV_LOG_DEBUG,
+ "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n",
+ av_q2d(metadata->display_primaries[0][0]),
+ av_q2d(metadata->display_primaries[0][1]),
+ av_q2d(metadata->display_primaries[1][0]),
+ av_q2d(metadata->display_primaries[1][1]),
+ av_q2d(metadata->display_primaries[2][0]),
+ av_q2d(metadata->display_primaries[2][1]),
+ av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1]));
+ av_log(avctx, AV_LOG_DEBUG,
+ "min_luminance=%f, max_luminance=%f\n",
+ av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance));
+ }
+ }
+
+ if (sei->content_light.present) {
+ AVContentLightMetadata *metadata;
+
+ ret = ff_decode_content_light_new_ext(avctx, sd, nb_sd, &metadata);
+ if (ret < 0)
+ return ret;
+
+ if (metadata) {
+ metadata->MaxCLL = sei->content_light.max_content_light_level;
+ metadata->MaxFALL = sei->content_light.max_pic_average_light_level;
+
+ av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n");
+ av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n",
+ metadata->MaxCLL, metadata->MaxFALL);
+ }
+ }
+
+ return 0;
+}
+
int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
enum AVCodecID codec_id,
AVCodecContext *avctx, const H2645VUI *vui,
@@ -625,19 +738,9 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
}
- for (unsigned i = 0; i < sei->unregistered.nb_buf_ref; i++) {
- H2645SEIUnregistered *unreg = &sei->unregistered;
-
- if (unreg->buf_ref[i]) {
- AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame,
- AV_FRAME_DATA_SEI_UNREGISTERED,
- unreg->buf_ref[i]);
- if (!sd)
- av_buffer_unref(&unreg->buf_ref[i]);
- unreg->buf_ref[i] = NULL;
- }
- }
- sei->unregistered.nb_buf_ref = 0;
+ ret = h2645_sei_to_side_data(avctx, sei, &frame->side_data, &frame->nb_side_data);
+ if (ret < 0)
+ return ret;
if (sei->afd.present) {
AVFrameSideData *sd = av_frame_new_side_data(frame, AV_FRAME_DATA_AFD,
@@ -728,88 +831,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
return ret;
#endif
- if (sei->ambient_viewing_environment.present) {
- H2645SEIAmbientViewingEnvironment *env =
- &sei->ambient_viewing_environment;
-
- AVAmbientViewingEnvironment *dst_env =
- av_ambient_viewing_environment_create_side_data(frame);
- if (!dst_env)
- return AVERROR(ENOMEM);
-
- dst_env->ambient_illuminance = av_make_q(env->ambient_illuminance, 10000);
- dst_env->ambient_light_x = av_make_q(env->ambient_light_x, 50000);
- dst_env->ambient_light_y = av_make_q(env->ambient_light_y, 50000);
- }
-
- if (sei->mastering_display.present) {
- // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b
- const int mapping[3] = {2, 0, 1};
- const int chroma_den = 50000;
- const int luma_den = 10000;
- int i;
- AVMasteringDisplayMetadata *metadata;
-
- ret = ff_decode_mastering_display_new(avctx, frame, &metadata);
- if (ret < 0)
- return ret;
-
- if (metadata) {
- for (i = 0; i < 3; i++) {
- const int j = mapping[i];
- metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0];
- metadata->display_primaries[i][0].den = chroma_den;
- metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1];
- metadata->display_primaries[i][1].den = chroma_den;
- }
- metadata->white_point[0].num = sei->mastering_display.white_point[0];
- metadata->white_point[0].den = chroma_den;
- metadata->white_point[1].num = sei->mastering_display.white_point[1];
- metadata->white_point[1].den = chroma_den;
-
- metadata->max_luminance.num = sei->mastering_display.max_luminance;
- metadata->max_luminance.den = luma_den;
- metadata->min_luminance.num = sei->mastering_display.min_luminance;
- metadata->min_luminance.den = luma_den;
- metadata->has_luminance = 1;
- metadata->has_primaries = 1;
-
- av_log(avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n");
- av_log(avctx, AV_LOG_DEBUG,
- "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n",
- av_q2d(metadata->display_primaries[0][0]),
- av_q2d(metadata->display_primaries[0][1]),
- av_q2d(metadata->display_primaries[1][0]),
- av_q2d(metadata->display_primaries[1][1]),
- av_q2d(metadata->display_primaries[2][0]),
- av_q2d(metadata->display_primaries[2][1]),
- av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1]));
- av_log(avctx, AV_LOG_DEBUG,
- "min_luminance=%f, max_luminance=%f\n",
- av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance));
- }
- }
-
- if (sei->content_light.present) {
- AVContentLightMetadata *metadata;
-
- ret = ff_decode_content_light_new(avctx, frame, &metadata);
- if (ret < 0)
- return ret;
-
- if (metadata) {
- metadata->MaxCLL = sei->content_light.max_content_light_level;
- metadata->MaxFALL = sei->content_light.max_pic_average_light_level;
-
- av_log(avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n");
- av_log(avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n",
- metadata->MaxCLL, metadata->MaxFALL);
- }
- }
-
return 0;
}
+int ff_h2645_sei_to_context(AVCodecContext *avctx, H2645SEI *sei)
+{
+ return h2645_sei_to_side_data(avctx, sei, &avctx->decoded_side_data,
+ &avctx->nb_decoded_side_data);
+}
+
void ff_h2645_sei_reset(H2645SEI *s)
{
av_buffer_unref(&s->a53_caption.buf_ref);
diff --git a/libavcodec/h2645_sei.h b/libavcodec/h2645_sei.h
index b9a6c7587b..488dbcad7e 100644
--- a/libavcodec/h2645_sei.h
+++ b/libavcodec/h2645_sei.h
@@ -168,4 +168,6 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
unsigned bit_depth_luma, unsigned bit_depth_chroma,
int seed);
+int ff_h2645_sei_to_context(AVCodecContext *avctx, H2645SEI *sei);
+
#endif /* AVCODEC_H2645_SEI_H */
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index d3b668af00..007eae6a1e 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -3659,6 +3659,10 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx)
if (ret < 0) {
return ret;
}
+
+ ret = ff_h2645_sei_to_context(avctx, &s->sei.common);
+ if (ret < 0)
+ return ret;
}
sd = ff_get_coded_side_data(avctx, AV_PKT_DATA_DOVI_CONF);
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index fd356bd190..f19571f6f8 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -767,6 +767,8 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
if (!copy)
return AVERROR(ENOMEM);
copy->priv_data = NULL;
+ copy->decoded_side_data = NULL;
+ copy->nb_decoded_side_data = 0;
/* From now on, this PerThreadContext will be cleaned up by
* ff_frame_thread_free in case of errors. */
@@ -820,9 +822,19 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
}
p->thread_init = NEEDS_CLOSE;
- if (first)
+ if (first) {
update_context_from_thread(avctx, copy, 1);
+ av_frame_side_data_free(&avctx->decoded_side_data, &avctx->nb_decoded_side_data);
+ for (int i = 0; i < copy->nb_decoded_side_data; i++) {
+ err = av_frame_side_data_clone(&avctx->decoded_side_data,
+ &avctx->nb_decoded_side_data,
+ copy->decoded_side_data[i], 0);
+ if (err < 0)
+ return err;
+ }
+ }
+
atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 84a1c02ce4..564119396d 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 5
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MICRO 102
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
More information about the ffmpeg-cvslog
mailing list