forked from FFmpeg/FFmpeg
avcodec/hevcdec: export global side data in AVCodecContext
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
6def8e3923
commit
6d0c89980c
7 changed files with 147 additions and 95 deletions
|
@ -2,6 +2,10 @@ The last version increases of all libraries were on 2024-03-07
|
||||||
|
|
||||||
API changes, most recent first:
|
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
|
2024-04-11 - xxxxxxxxxx - lavu 59.15.100 - frame.h
|
||||||
Add av_mastering_display_metadata_alloc_size().
|
Add av_mastering_display_metadata_alloc_size().
|
||||||
|
|
||||||
|
|
|
@ -2071,7 +2071,7 @@ typedef struct AVCodecContext {
|
||||||
* - encoding: may be set by user before calling avcodec_open2() for
|
* - encoding: may be set by user before calling avcodec_open2() for
|
||||||
* encoder configuration. Afterwards owned and freed by the
|
* encoder configuration. Afterwards owned and freed by the
|
||||||
* encoder.
|
* encoder.
|
||||||
* - decoding: unused
|
* - decoding: may be set by libavcodec in avcodec_open2().
|
||||||
*/
|
*/
|
||||||
AVFrameSideData **decoded_side_data;
|
AVFrameSideData **decoded_side_data;
|
||||||
int nb_decoded_side_data;
|
int nb_decoded_side_data;
|
||||||
|
|
|
@ -529,6 +529,119 @@ static int is_frame_packing_type_valid(SEIFpaType type, enum AVCodecID codec_id)
|
||||||
type >= SEI_FPA_TYPE_SIDE_BY_SIDE;
|
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,
|
int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
|
||||||
enum AVCodecID codec_id,
|
enum AVCodecID codec_id,
|
||||||
AVCodecContext *avctx, const H2645VUI *vui,
|
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;
|
avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < sei->unregistered.nb_buf_ref; i++) {
|
ret = h2645_sei_to_side_data(avctx, sei, &frame->side_data, &frame->nb_side_data);
|
||||||
H2645SEIUnregistered *unreg = &sei->unregistered;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
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;
|
|
||||||
|
|
||||||
if (sei->afd.present) {
|
if (sei->afd.present) {
|
||||||
AVFrameSideData *sd = av_frame_new_side_data(frame, AV_FRAME_DATA_AFD,
|
AVFrameSideData *sd = av_frame_new_side_data(frame, AV_FRAME_DATA_AFD,
|
||||||
|
@ -728,88 +831,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#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;
|
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)
|
void ff_h2645_sei_reset(H2645SEI *s)
|
||||||
{
|
{
|
||||||
av_buffer_unref(&s->a53_caption.buf_ref);
|
av_buffer_unref(&s->a53_caption.buf_ref);
|
||||||
|
|
|
@ -168,4 +168,6 @@ int ff_h2645_sei_to_frame(AVFrame *frame, H2645SEI *sei,
|
||||||
unsigned bit_depth_luma, unsigned bit_depth_chroma,
|
unsigned bit_depth_luma, unsigned bit_depth_chroma,
|
||||||
int seed);
|
int seed);
|
||||||
|
|
||||||
|
int ff_h2645_sei_to_context(AVCodecContext *avctx, H2645SEI *sei);
|
||||||
|
|
||||||
#endif /* AVCODEC_H2645_SEI_H */
|
#endif /* AVCODEC_H2645_SEI_H */
|
||||||
|
|
|
@ -3659,6 +3659,10 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx)
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
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);
|
sd = ff_get_coded_side_data(avctx, AV_PKT_DATA_DOVI_CONF);
|
||||||
|
|
|
@ -767,6 +767,8 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
|
||||||
if (!copy)
|
if (!copy)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
copy->priv_data = NULL;
|
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
|
/* From now on, this PerThreadContext will be cleaned up by
|
||||||
* ff_frame_thread_free in case of errors. */
|
* 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;
|
p->thread_init = NEEDS_CLOSE;
|
||||||
|
|
||||||
if (first)
|
if (first) {
|
||||||
update_context_from_thread(avctx, copy, 1);
|
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);
|
atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
|
||||||
|
|
||||||
err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
|
err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "version_major.h"
|
#include "version_major.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MINOR 5
|
#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, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
|
Loading…
Add table
Reference in a new issue