summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-06-10 14:02:55 +0200
committerwm4 <wm4@nowhere>2017-06-18 20:54:44 +0200
commitdeb93707791092e608b1e5f8f1d1773b0057ce59 (patch)
tree0b6c2e37a105b1bf51ccebd96818c6d25422c6d9 /video
parentc335e84230916d7d7a38288031516e8b2ec1c36b (diff)
downloadmpv-deb93707791092e608b1e5f8f1d1773b0057ce59.tar.bz2
mpv-deb93707791092e608b1e5f8f1d1773b0057ce59.tar.xz
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.
Diffstat (limited to 'video')
-rw-r--r--video/decode/dec_video.c15
-rw-r--r--video/decode/lavc.h2
-rw-r--r--video/decode/vd_lavc.c37
3 files changed, 36 insertions, 18 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index bd20dbe312..f7ca6cc477 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -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;
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index f58ee8bc1e..e567a49b4e 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -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;
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index aae6937476..226fd30bd3 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -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) {
+ AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data;
+ params->color.sig_peak = clm->MaxCLL / MP_REF_WHITE;
+ }
+#endif
+
+#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) {
- 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;
- }
- }
+ if (mdm->has_luminance)
+ params->color.sig_peak = av_q2d(mdm->max_luminance) / MP_REF_WHITE;
}
#endif
- params->color.sig_peak = ctx->cached_hdr_peak / MP_REF_WHITE;
+ 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;
}