Skip to content

Commit 5f91b69

Browse files
committed
Fix converting 10-bit full to limited range
Without Movit, 10-bit full range was not able to convert to limited range. This regressed in 7752c68 in order to accomodate 10-bit pass- through editing (no processing). Now, it returns by going through RGB to do the conversion but only when the consumer does not request 10-bit. However, that still leaves a gap: 10-bit full to 10-bit limited or visa versa. In that case, you must either set the consumer color_range same as source, or specify mlt_image_rgb(a). With Movit, 10-bit range conversion works even when the consumer requests 10-bit Y'CbCr.
1 parent 64aa543 commit 5f91b69

File tree

3 files changed

+31
-19
lines changed

3 files changed

+31
-19
lines changed

src/modules/avformat/common.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* common.h
3-
* Copyright (C) 2018-2024 Meltytech, LLC
3+
* Copyright (C) 2018-2025 Meltytech, LLC
44
*
55
* This library is free software; you can redistribute it and/or
66
* modify it under the terms of the GNU Lesser General Public
@@ -253,14 +253,6 @@ int mlt_set_luma_transfer(struct SwsContext *context,
253253
int src_range = src_full_range ? 1 : 0;
254254
int dst_range = dst_full_range ? 1 : 0;
255255

256-
sws_getColorspaceDetails(context,
257-
(int **) &src_coefficients,
258-
&src_range,
259-
(int **) &dst_coefficients,
260-
&dst_range,
261-
&brightness,
262-
&contrast,
263-
&saturation);
264256
switch (src_colorspace) {
265257
case 170:
266258
case 470:

src/modules/avformat/producer_avformat.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,12 +1937,14 @@ static int convert_image(producer_avformat self,
19371937
mlt_log_timings_begin();
19381938

19391939
mlt_log_debug(MLT_PRODUCER_SERVICE(self->parent),
1940-
"%s @ %dx%d space %d->%d\n",
1940+
"%s @ %dx%d colorspace %d->%d range %d->%d\n",
19411941
mlt_image_format_name(*format),
19421942
width,
19431943
height,
19441944
self->yuv_colorspace,
1945-
profile->colorspace);
1945+
profile->colorspace,
1946+
self->full_range,
1947+
dst_full_range);
19461948

19471949
// extract alpha from planar formats - only supports 8-bit
19481950
if ((pix_fmt == AV_PIX_FMT_YUVA420P || pix_fmt == AV_PIX_FMT_YUVA422P
@@ -2227,10 +2229,17 @@ static int producer_get_image(mlt_frame frame,
22272229
const char *dst_color_range = mlt_properties_get(frame_properties, "consumer.color_range");
22282230
int dst_full_range = mlt_image_full_range(dst_color_range);
22292231

2230-
// if depth > 8 libswscale only changes range when scaling, not simple pix_fmt conversion
2232+
// if 10-bit libswscale only changes range when scaling, not simple pix_fmt conversion
22312233
const struct AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(self->video_codec->pix_fmt);
2232-
if (pix_desc && pix_desc->nb_components > 0 && pix_desc->comp[0].depth > 8)
2233-
dst_full_range = self->full_range;
2234+
if (dst_full_range != self->full_range && pix_desc && pix_desc->nb_components > 0
2235+
&& pix_desc->comp[0].depth == 10) {
2236+
if (*format == mlt_image_yuv420p10 || *format == mlt_image_yuv444p10)
2237+
// When the consumer requests 10-bit do not convert
2238+
dst_full_range = self->full_range;
2239+
else
2240+
// Otherwise, convert via RGB
2241+
*format = mlt_image_rgb;
2242+
}
22342243

22352244
mlt_service_lock(MLT_PRODUCER_SERVICE(producer));
22362245
pthread_mutex_lock(&self->video_mutex);

src/modules/movit/filter_movit_convert.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,13 +375,17 @@ static void finalize_movit_chain(mlt_service leaf_service, mlt_frame frame, mlt_
375375

376376
ImageFormat output_format;
377377
if (format == mlt_image_yuv444p10 || format == mlt_image_yuv420p10) {
378+
auto properties = MLT_FRAME_PROPERTIES(frame);
378379
YCbCrFormat ycbcr_format = {};
379-
get_format_from_properties(MLT_FRAME_PROPERTIES(frame), &output_format, &ycbcr_format);
380-
output_format.gamma_curve = std::max(GAMMA_REC_709,
381-
getOutputGamma(MLT_FRAME_PROPERTIES(frame)));
380+
get_format_from_properties(properties, &output_format, &ycbcr_format);
381+
output_format.gamma_curve = std::max(GAMMA_REC_709, getOutputGamma(properties));
382+
ycbcr_format.full_range = mlt_image_full_range(
383+
mlt_properties_get(properties, "consumer.color_range"));
382384
mlt_log_debug(nullptr,
383-
"[filter movit.convert] output gamma %d\n",
384-
output_format.gamma_curve);
385+
"[filter movit.convert] output gamma %d full-range %d\n",
386+
output_format.gamma_curve,
387+
ycbcr_format.full_range);
388+
mlt_properties_set_int(properties, "full_range", ycbcr_format.full_range);
385389
ycbcr_format.num_levels = 1024;
386390
ycbcr_format.chroma_subsampling_x = ycbcr_format.chroma_subsampling_y = 1;
387391
chain->effect_chain->add_ycbcr_output(output_format,
@@ -404,6 +408,13 @@ static void finalize_movit_chain(mlt_service leaf_service, mlt_frame frame, mlt_
404408
} else {
405409
// Delete all the created Effect instances to avoid memory leaks.
406410
dispose_movit_effects(leaf_service, frame);
411+
412+
auto properties = MLT_FRAME_PROPERTIES(frame);
413+
getOutputGamma(properties);
414+
mlt_properties_set_int(properties,
415+
"full_range",
416+
mlt_image_full_range(
417+
mlt_properties_get(properties, "consumer.color_range")));
407418
}
408419
}
409420

0 commit comments

Comments
 (0)