> > 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 [email protected] https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email [email protected] with subject "unsubscribe".
