On Fri, 9 Dec 2022, Niklas Haas wrote:

So, as was discussed at the last meeting, we should move towards
removing YUVJ.

Libswscale still does have cases where it doesn't work correctly, for some conversions, unless differences in range is signalled with the YUVJ pixel formats (this, despite that swscale itself warns that the user is specifying the deprecated pixel formats).

Attached is a small testcase example, which uses swscale to convert from YUV to YUV, with various color spaces and ranges. When converting from limited to full range or vice versa, within the same colorspace, swscale fails to realize that this isn't a no-op operation, unless the YUVJ formats are used.

When running the attached test example, I get the following output (modulo swscale warnings):

red 601 limited -> 601 full YUV 49,109,184 -> 38,106,192
red 601 full -> 601 limited YUV 38,106,192 -> 49,109,184
red 709 limited -> 709 full YUV 39,115,184 -> 27,113,192
red 709 full -> 709 limited YUV 27,113,192 -> 39,115,184

If the example is modified to always set yuv_{in,out}->format to AV_PIX_FMT_YUV420P, then swscale no longer actually does any conversion:

red 601 limited -> 601 full YUV 49,109,184 -> 49,109,184
red 601 full -> 601 limited YUV 38,106,192 -> 38,106,192
red 709 limited -> 709 full YUV 39,115,184 -> 39,115,184
red 709 full -> 709 limited YUV 27,113,192 -> 27,113,192


So this is yet another small detail that needs to be fixed before we can proceed towards actually removing the YUVJ formats.


// Martin
#include <libswscale/swscale.h>
#include <stdio.h>

static void yuv2yuv(int Y, int U, int V, int in_colorspace, int param_in_full,
                    int out_colorspace, int param_out_full, const char* name)
{
    AVFrame* yuv_in = av_frame_alloc();
    yuv_in->format = param_in_full ? AV_PIX_FMT_YUVJ420P : AV_PIX_FMT_YUV420P;
    yuv_in->width = 128;
    yuv_in->height = 128;
    yuv_in->color_range = param_in_full ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
    yuv_in->color_primaries = in_colorspace;
    yuv_in->color_trc = in_colorspace;
    yuv_in->colorspace = in_colorspace;
    av_frame_get_buffer(yuv_in, 0);

    AVFrame* yuv_out = av_frame_alloc();
    yuv_out->format = param_out_full ? AV_PIX_FMT_YUVJ420P : AV_PIX_FMT_YUV420P;
    yuv_out->width = 128;
    yuv_out->height = 128;
    yuv_out->color_range = param_out_full ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
    yuv_out->color_primaries = out_colorspace;
    yuv_out->color_trc = out_colorspace;
    yuv_out->colorspace = out_colorspace;
    av_frame_get_buffer(yuv_out, 0);

    memset(yuv_in->data[0], Y, yuv_in->linesize[0] * yuv_in->height);
    memset(yuv_in->data[1], U, yuv_in->linesize[1] * (yuv_in->height / 2));
    memset(yuv_in->data[2], V, yuv_in->linesize[2] * (yuv_in->height / 2));

    struct SwsContext *sws = sws_getContext(yuv_in->width, yuv_in->height, yuv_in->format,
                                            yuv_out->width, yuv_out->height, yuv_out->format,
                                            0, NULL, NULL, NULL);

    int in_full, out_full, brightness, contrast, saturation;
    const int *inv_table, *table;
    sws_getColorspaceDetails(sws, (int **)&inv_table, &in_full, (int **)&table,
                             &out_full, &brightness, &contrast, &saturation);
    in_full = param_in_full;
    out_full = param_out_full;
    inv_table = sws_getCoefficients(in_colorspace);
    table = sws_getCoefficients(out_colorspace);
    sws_setColorspaceDetails(sws, inv_table, in_full, table, out_full,
                             brightness, contrast, saturation);

    sws_scale_frame(sws, yuv_out, yuv_in);

    printf("%s YUV %d,%d,%d -> %d,%d,%d\n", name, Y, U, V,
           yuv_out->data[0][0], yuv_out->data[1][0], yuv_out->data[2][0]);
}

int main(int argc, char* argv[])
{
    yuv2yuv(49, 109, 184, SWS_CS_ITU601, 0, SWS_CS_ITU601, 1,
            "red 601 limited -> 601 full");
    yuv2yuv(38, 106, 192, SWS_CS_ITU601, 1, SWS_CS_ITU601, 0,
            "red 601 full -> 601 limited");
    yuv2yuv(39, 115, 184, SWS_CS_ITU709, 0, SWS_CS_ITU709, 1,
            "red 709 limited -> 709 full");
    yuv2yuv(27, 113, 192, SWS_CS_ITU709, 1, SWS_CS_ITU709, 0,
            "red 709 full -> 709 limited");
    return 0;
}
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to