1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-22 06:42:03 +00:00

vd: use ST.2086 / HDR10 MaxCLL in addition to mastering metadata

MaxCLL is the more authoritative source for the metadata we are
interested in. The use of mastering metadata is sort of a hack anyway,
since there's no clearly-defined relationship between the mastering peak
brightness and the actual content. (Unlike MaxCLL, which is an explicit
relationship)

Also move the parameter fixing to `fix_image_params`

I don't know if the avutil check is strictly necessary but I've included
it anyway to be on the safe side.
This commit is contained in:
Niklas Haas 2017-06-10 14:02:55 +02:00 committed by wm4
parent c335e84230
commit deb9370779
5 changed files with 49 additions and 20 deletions

View File

@ -568,7 +568,12 @@ static void parse_trackcolour(struct demuxer *demuxer, struct mkv_track *track,
MP_VERBOSE(demuxer, "| + Levels: %s\n",
m_opt_choice_str(mp_csp_levels_names, track->color.levels));
}
if (colour->n_mastering_metadata) {
if (colour->n_max_cll) {
track->color.sig_peak = colour->max_cll / MP_REF_WHITE;
MP_VERBOSE(demuxer, "| + MaxCLL: %lu\n", colour->max_cll);
}
// if MaxCLL is unavailable, try falling back to the mastering metadata
if (!track->color.sig_peak && colour->n_mastering_metadata) {
struct ebml_mastering_metadata *mastering = &colour->mastering_metadata;
if (mastering->n_luminance_max) {

View File

@ -188,6 +188,11 @@ bool video_init_best_codec(struct dec_video *d_video)
return !!d_video->vd_driver;
}
static bool is_valid_peak(float sig_peak)
{
return !sig_peak || (sig_peak >= 1 && sig_peak <= 100);
}
static void fix_image_params(struct dec_video *d_video,
struct mp_image_params *params)
{
@ -258,8 +263,16 @@ static void fix_image_params(struct dec_video *d_video,
}
p.stereo_out = opts->video_stereo_mode;
// Detect colorspace from resolution.
mp_colorspace_merge(&p.color, &c->color);
// Sanitize the HDR peak. Sadly necessary
if (!is_valid_peak(p.color.sig_peak)) {
MP_WARN(d_video, "Invalid HDR peak in stream: %f\n", p.color.sig_peak);
p.color.sig_peak = 0.0;
}
// Guess missing colorspace fields from metadata. This guarantees all
// fields are at least set to legal values afterwards.
mp_image_params_guess_csp(&p);
d_video->last_format = *params;

View File

@ -39,7 +39,7 @@ typedef struct lavc_ctx {
int framedrop_flags;
// For HDR side-data caching
double cached_hdr_peak;
float cached_sig_peak;
bool hw_probing;
struct demux_packet **sent_packets;

View File

@ -721,28 +721,33 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
struct mp_image_params *params)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVFrameSideData *sd;
#if LIBAVCODEC_VERSION_MICRO >= 100
// Get the reference peak (for HDR) if available. This is cached into ctx
// when it's found, since it's not available on every frame (and seems to
// be only available for keyframes)
AVFrameSideData *sd = av_frame_get_side_data(frame,
AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
#if HAVE_AVUTIL_CONTENT_LIGHT_LEVEL
// Get the content light metadata if available
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
if (sd) {
AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
if (mdm->has_luminance) {
double peak = av_q2d(mdm->max_luminance);
if (!isnormal(peak) || peak < 10 || peak > 100000) {
// Invalid data, ignore it. Sadly necessary
MP_WARN(vd, "Invalid HDR reference peak in stream: %f\n", peak);
} else {
ctx->cached_hdr_peak = peak;
}
}
AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
params->color.sig_peak = clm->MaxCLL / MP_REF_WHITE;
}
#endif
params->color.sig_peak = ctx->cached_hdr_peak / MP_REF_WHITE;
#if LIBAVCODEC_VERSION_MICRO >= 100
// Otherwise, try getting the mastering metadata if available
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
if (!params->color.sig_peak && sd) {
AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data;
if (mdm->has_luminance)
params->color.sig_peak = av_q2d(mdm->max_luminance) / MP_REF_WHITE;
}
#endif
if (params->color.sig_peak) {
ctx->cached_sig_peak = params->color.sig_peak;
} else {
params->color.sig_peak = ctx->cached_sig_peak;
}
params->rotate = vd->codec->rotate;
params->stereo_in = vd->codec->stereo_mode;
}

View File

@ -449,6 +449,12 @@ FFmpeg/Libav libraries. You need at least {0}. Aborting.".format(libav_versions_
'func': check_statement('libavutil/imgutils.h',
'av_image_copy_uc_from(0,0,0,0,0,0,0)',
use='libav'),
}, {
'name': 'avutil-content-light-level',
'desc': 'libavutil content light level struct',
'func': check_statement('libavutil/frame.h',
'AV_FRAME_DATA_CONTENT_LIGHT_LEVEL',
use='libav'),
},
]