> 
> have you confirmed that all the added codepathes produce correct
> looking output ?
> 

I've attached a test program which should cover all the modified code
paths. The new X2BGR10 code works just as well as the X2RGB10 code, but:

* converting FROM X2RGB10LE or X2BGR10LE works
* converting TO X2RGB10LE or X2BGR10LE dims all pixels by a factor of 4.
  Also, a 'full chroma interpolation [...] not yet implemented' warning 
  is printed.

The factor 4 dimming can be fixed by increasing rbase/gbase/bbase
shifts by 2 in libswscale, yuv2rgb.c, ff_yuv2rgb_c_init_tables, case 30.

So, unless otherwise recommended:
* I will send a separate patch fixing the shift values and updating
  x2rgb10le FATE test results
* Patch 2/2 will be updated to apply after this patch
* Patch 1/2 of this series will be unaffected
#include <libswscale/swscale.h>

static struct AVFrame* alloc_picture(enum AVPixelFormat fmt, int width, int  height) {
    struct AVFrame *picture = av_frame_alloc();
    picture->format = fmt;
    picture->width = width;
    picture->height = height;
    av_frame_get_buffer(picture, 32);
    return picture;
}

static void fill_u32_frame(AVFrame *frame, uint32_t val) {
    for (int y=0;y<frame->height;y++) {
        uint32_t* row = (uint32_t*)(frame->data[0] + y * frame->linesize[0]);
        for (int x=0;x<frame->width; x++) {
            row[x] = val;
        }
    }
}

static void show_frame_u32(const AVFrame *frame) {
    for (int y=0;y<frame->height;y++) {
        const uint32_t* row = (const uint32_t*)(frame->data[0] + y * frame->linesize[0]);
        for (int x=0;x<frame->width; x++) {
            fprintf(stderr, "0x%08x ", row[x]);
        }
        fprintf(stderr, "\n");
    }

}

static void copy(AVFrame *src, AVFrame *dst, int flags) {
    struct SwsContext *context = sws_getContext(
                src->width, src->height,
                src->format, dst->width, dst->height, dst->format,
                flags, NULL, NULL, NULL);
    if (!context) {
        fprintf(stderr, "Failed to create context: %d to %d\n", src->format, dst->format);
        abort();
    }
    sws_scale_frame(context, dst, src);
    sws_freeContext(context);
}

static char *x2abc10le_to_string(uint32_t val) {
    uint32_t x = (val & 0xc000000) >> 30;
    uint32_t a = (val & 0x3ff00000) >> 20;
    uint32_t b = (val & 0x000ffc00) >> 10;
    uint32_t c = (val & 0x000003ff) >> 0;
    float fx = x/3.0;
    float fa = a/1023.0;
    float fb = b/1023.0;
    float fc = c/1023.0;
    int len = snprintf(NULL, 0,  "(%0.2f,%0.4f,%0.4f,%0.4f)", fx,fa,fb,fc);
    char *buf = malloc(len + 1);
    sprintf(buf, "(%0.2f,%0.4f,%0.4f,%0.4f)", fx,fa,fb,fc);
    return buf;
}
static char *rgba64_to_string(uint64_t val) {
    uint32_t a = (val & 0xffff000000000000uLL) >> 48;
    uint32_t b = (val & 0x0000ffff00000000uLL) >> 32;
    uint32_t g = (val & 0x00000000ffff0000uLL) >> 16;
    uint32_t r = (val & 0x000000000000ffffuLL) >> 0;
    float fr = r/65535.0;
    float fg = g/65535.0;
    float fb = b/65535.0;
    float fa = a/65535.0;
    int len = snprintf(NULL, 0,  "(%0.5f,%0.5f,%0.5f,%0.5f)", fr,fg,fb,fa);
    char *buf = malloc(len + 1);
    sprintf(buf, "(%0.5f,%0.5f,%0.5f,%0.5f)",fr,fg,fb,fa);
    return buf;
}

static uint32_t float_to_x2abc10le_to_string(float x, float a, float b, float c) {
    uint32_t ux = (int)(x * 3.0 + 0.5);
    uint32_t ua = (int)(a * 1023.0 + 0.5);
    uint32_t ub = (int)(b * 1023.0 + 0.5);
    uint32_t uc = (int)(c * 1023.0 + 0.5);
    return uc | (ub << 10) | (ua << 20) | (ux << 30);
}

int main() {
    /* Conversion testing. We roundtrip convert AV_PIX_FMT_X2BGR10LE,
     * going through different sequences of intermediate frames each time */
    float tr = 0.1, tg = 0.4, tb = 1.0;
    uint32_t test_val_bgr = float_to_x2abc10le_to_string(1.0, tb, tg, tr);
    uint32_t test_val_rgb = float_to_x2abc10le_to_string(1.0, tr, tg, tb);

    int width = 6, height = 8;
    AVFrame *x2bgr_in = alloc_picture(AV_PIX_FMT_X2BGR10LE, width, height);
    fill_u32_frame(x2bgr_in, test_val_bgr);
    AVFrame *x2rgb_in = alloc_picture(AV_PIX_FMT_X2RGB10LE, width, height);
    fill_u32_frame(x2rgb_in, test_val_rgb);
    AVFrame *x2bgr_out = alloc_picture(AV_PIX_FMT_X2BGR10LE, width, height);
    fill_u32_frame(x2bgr_out, 0);
    AVFrame *x2rgb_out = alloc_picture(AV_PIX_FMT_X2RGB10LE, width, height);
    fill_u32_frame(x2rgb_out, 0);
    AVFrame *x2rgb_temp_1 = alloc_picture(AV_PIX_FMT_X2RGB10LE, width, height);
    AVFrame *x2bgr_temp_1 = alloc_picture(AV_PIX_FMT_X2BGR10LE, width, height);
    AVFrame *rgba64_temp_1 = alloc_picture(AV_PIX_FMT_RGBA64LE, width, height);

    fprintf(stderr, "X2BGR: %s\n", x2abc10le_to_string(((uint32_t*)x2bgr_in->data[0])[0]));

    // Note: these conversions are all mildly lossy, since they go through YUV
    copy(x2bgr_in, x2rgb_temp_1, SWS_FAST_BILINEAR);
    copy(x2rgb_temp_1, x2bgr_out, SWS_FAST_BILINEAR);
    fprintf(stderr, "X2BGR->X2RGB: %s\n", x2abc10le_to_string(((uint32_t*)x2rgb_temp_1->data[0])[0]));
    fprintf(stderr, "X2BGR->X2RGB->X2RGB: %s\n", x2abc10le_to_string(((uint32_t*)x2bgr_out->data[0])[0]));

    copy(x2bgr_in, x2bgr_out, SWS_FAST_BILINEAR);
    fprintf(stderr, "X2BGR->X2BGR: %s\n", x2abc10le_to_string(((uint32_t*)x2bgr_out->data[0])[0]));

    copy(x2bgr_in, rgba64_temp_1, SWS_FAST_BILINEAR);
    copy(rgba64_temp_1, x2bgr_out, SWS_FAST_BILINEAR);
    fprintf(stderr, "X2BGR->RGBA64: %s\n", rgba64_to_string(((uint64_t*)rgba64_temp_1->data[0])[0]));
    fprintf(stderr, "X2BGR->RGBA64->X2BGR: %s\n", x2abc10le_to_string(((uint32_t*)x2bgr_out->data[0])[0]));

    fprintf(stderr, "X2RGB: %s\n", x2abc10le_to_string(((uint32_t*)x2rgb_in->data[0])[0]));
    copy(x2rgb_in, x2bgr_temp_1, SWS_FAST_BILINEAR);
    copy(x2bgr_temp_1, x2rgb_out, SWS_FAST_BILINEAR);
    fprintf(stderr, "X2RGB->X2BGR: %s\n", x2abc10le_to_string(((uint32_t*)x2bgr_temp_1->data[0])[0]));
    fprintf(stderr, "X2RGB->X2BGR->X2RGB: %s\n", x2abc10le_to_string(((uint32_t*)x2rgb_out->data[0])[0]));

    copy(x2rgb_in, rgba64_temp_1, SWS_FAST_BILINEAR);
    copy(rgba64_temp_1, x2rgb_out, SWS_FAST_BILINEAR);
    fprintf(stderr, "X2RGB->RGBA64: %s\n", rgba64_to_string(((uint64_t*)rgba64_temp_1->data[0])[0]));
    fprintf(stderr, "X2RGB->RGBA64->X2RGB: %s\n", x2abc10le_to_string(((uint32_t*)x2rgb_out->data[0])[0]));
}

Attachment: pgpjyYHIv0yBX.pgp
Description: OpenPGP digital signature

_______________________________________________
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