avcodec/hevcdec: export global side data in AVCodecContext

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer 2024-03-28 12:50:54 -03:00
parent 6def8e3923
commit 6d0c89980c
7 changed files with 147 additions and 95 deletions

View File

@ -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().

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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));

View File

@ -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, \