> > 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])); }
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".