av_cold int ff_yuv2rgb_c_init_tables(SwsContext *c, const int inv_table[4], int fullRange, int brightness, int contrast, int saturation) { const int isRgb = c->dstFormat == AV_PIX_FMT_RGB32 || c->dstFormat == AV_PIX_FMT_RGB32_1 || c->dstFormat == AV_PIX_FMT_BGR24 || c->dstFormat == AV_PIX_FMT_RGB565BE || c->dstFormat == AV_PIX_FMT_RGB565LE || c->dstFormat == AV_PIX_FMT_RGB555BE || c->dstFormat == AV_PIX_FMT_RGB555LE || c->dstFormat == AV_PIX_FMT_RGB444BE || c->dstFormat == AV_PIX_FMT_RGB444LE || c->dstFormat == AV_PIX_FMT_RGB8 || c->dstFormat == AV_PIX_FMT_RGB4 || c->dstFormat == AV_PIX_FMT_RGB4_BYTE || c->dstFormat == AV_PIX_FMT_MONOBLACK; const int isNotNe = c->dstFormat == AV_PIX_FMT_NE(RGB565LE, RGB565BE) || c->dstFormat == AV_PIX_FMT_NE(RGB555LE, RGB555BE) || c->dstFormat == AV_PIX_FMT_NE(RGB444LE, RGB444BE) || c->dstFormat == AV_PIX_FMT_NE(BGR565LE, BGR565BE) || c->dstFormat == AV_PIX_FMT_NE(BGR555LE, BGR555BE) || c->dstFormat == AV_PIX_FMT_NE(BGR444LE, BGR444BE); const int bpp = c->dstFormatBpp; uint8_t *y_table; uint16_t *y_table16; uint32_t *y_table32; int i, base, rbase, gbase, bbase, av_uninit(abase), needAlpha; const int yoffs = fullRange ? 384 : 326; int64_t crv = inv_table[0]; int64_t cbu = inv_table[1]; int64_t cgu = -inv_table[2]; int64_t cgv = -inv_table[3]; int64_t cy = 1 << 16; int64_t oy = 0; int64_t yb = 0; if (!fullRange) { cy = (cy * 255) / 219; oy = 16 << 16; } else { crv = (crv * 224) / 255; cbu = (cbu * 224) / 255; cgu = (cgu * 224) / 255; cgv = (cgv * 224) / 255; } cy = (cy * contrast) >> 16; crv = (crv * contrast * saturation) >> 32; cbu = (cbu * contrast * saturation) >> 32; cgu = (cgu * contrast * saturation) >> 32; cgv = (cgv * contrast * saturation) >> 32; oy -= 256 * brightness; c->uOffset = 0x0400040004000400LL; c->vOffset = 0x0400040004000400LL; c->yCoeff = roundToInt16(cy * 8192) * 0x0001000100010001ULL; c->vrCoeff = roundToInt16(crv * 8192) * 0x0001000100010001ULL; c->ubCoeff = roundToInt16(cbu * 8192) * 0x0001000100010001ULL; c->vgCoeff = roundToInt16(cgv * 8192) * 0x0001000100010001ULL; c->ugCoeff = roundToInt16(cgu * 8192) * 0x0001000100010001ULL; c->yOffset = roundToInt16(oy * 8) * 0x0001000100010001ULL; c->yuv2rgb_y_coeff = (int16_t)roundToInt16(cy << 13); c->yuv2rgb_y_offset = (int16_t)roundToInt16(oy << 9); c->yuv2rgb_v2r_coeff = (int16_t)roundToInt16(crv << 13); c->yuv2rgb_v2g_coeff = (int16_t)roundToInt16(cgv << 13); c->yuv2rgb_u2g_coeff = (int16_t)roundToInt16(cgu << 13); c->yuv2rgb_u2b_coeff = (int16_t)roundToInt16(cbu << 13); //scale coefficients by cy crv = ((crv << 16) + 0x8000) / cy; cbu = ((cbu << 16) + 0x8000) / cy; cgu = ((cgu << 16) + 0x8000) / cy; cgv = ((cgv << 16) + 0x8000) / cy; av_freep(&c->yuvTable); switch (bpp) { case 1: c->yuvTable = av_malloc(1024); y_table = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024 - 110; i++) { y_table[i + 110] = av_clip_uint8((yb + 0x8000) >> 16) >> 7; yb += cy; } fill_table(c->table_gU, 1, cgu, y_table + yoffs); fill_gv_table(c->table_gV, 1, cgv); break; case 4: case 4 | 128: rbase = isRgb ? 3 : 0; gbase = 1; bbase = isRgb ? 0 : 3; c->yuvTable = av_malloc(1024 * 3); y_table = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024 - 110; i++) { int yval = av_clip_uint8((yb + 0x8000) >> 16); y_table[i + 110] = (yval >> 7) << rbase; y_table[i + 37 + 1024] = ((yval + 43) / 85) << gbase; y_table[i + 110 + 2048] = (yval >> 7) << bbase; yb += cy; } fill_table(c->table_rV, 1, crv, y_table + yoffs); fill_table(c->table_gU, 1, cgu, y_table + yoffs + 1024); fill_table(c->table_bU, 1, cbu, y_table + yoffs + 2048); fill_gv_table(c->table_gV, 1, cgv); break; case 8: rbase = isRgb ? 5 : 0; gbase = isRgb ? 2 : 3; bbase = isRgb ? 0 : 6; c->yuvTable = av_malloc(1024 * 3); y_table = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024 - 38; i++) { int yval = av_clip_uint8((yb + 0x8000) >> 16); y_table[i + 16] = ((yval + 18) / 36) << rbase; y_table[i + 16 + 1024] = ((yval + 18) / 36) << gbase; y_table[i + 37 + 2048] = ((yval + 43) / 85) << bbase; yb += cy; } fill_table(c->table_rV, 1, crv, y_table + yoffs); fill_table(c->table_gU, 1, cgu, y_table + yoffs + 1024); fill_table(c->table_bU, 1, cbu, y_table + yoffs + 2048); fill_gv_table(c->table_gV, 1, cgv); break; case 12: rbase = isRgb ? 8 : 0; gbase = 4; bbase = isRgb ? 0 : 8; c->yuvTable = av_malloc(1024 * 3 * 2); y_table16 = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024; i++) { uint8_t yval = av_clip_uint8((yb + 0x8000) >> 16); y_table16[i] = (yval >> 4) << rbase; y_table16[i + 1024] = (yval >> 4) << gbase; y_table16[i + 2048] = (yval >> 4) << bbase; yb += cy; } if (isNotNe) for (i = 0; i < 1024 * 3; i++) y_table16[i] = av_bswap16(y_table16[i]); fill_table(c->table_rV, 2, crv, y_table16 + yoffs); fill_table(c->table_gU, 2, cgu, y_table16 + yoffs + 1024); fill_table(c->table_bU, 2, cbu, y_table16 + yoffs + 2048); fill_gv_table(c->table_gV, 2, cgv); break; case 15: case 16: rbase = isRgb ? bpp - 5 : 0; gbase = 5; bbase = isRgb ? 0 : (bpp - 5); c->yuvTable = av_malloc(1024 * 3 * 2); y_table16 = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024; i++) { uint8_t yval = av_clip_uint8((yb + 0x8000) >> 16); y_table16[i] = (yval >> 3) << rbase; y_table16[i + 1024] = (yval >> (18 - bpp)) << gbase; y_table16[i + 2048] = (yval >> 3) << bbase; yb += cy; } if (isNotNe) for (i = 0; i < 1024 * 3; i++) y_table16[i] = av_bswap16(y_table16[i]); fill_table(c->table_rV, 2, crv, y_table16 + yoffs); fill_table(c->table_gU, 2, cgu, y_table16 + yoffs + 1024); fill_table(c->table_bU, 2, cbu, y_table16 + yoffs + 2048); fill_gv_table(c->table_gV, 2, cgv); break; case 24: case 48: c->yuvTable = av_malloc(1024); y_table = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024; i++) { y_table[i] = av_clip_uint8((yb + 0x8000) >> 16); yb += cy; } fill_table(c->table_rV, 1, crv, y_table + yoffs); fill_table(c->table_gU, 1, cgu, y_table + yoffs); fill_table(c->table_bU, 1, cbu, y_table + yoffs); fill_gv_table(c->table_gV, 1, cgv); break; case 32: case 64: base = (c->dstFormat == AV_PIX_FMT_RGB32_1 || c->dstFormat == AV_PIX_FMT_BGR32_1) ? 8 : 0; rbase = base + (isRgb ? 16 : 0); gbase = base + 8; bbase = base + (isRgb ? 0 : 16); needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat); if (!needAlpha) abase = (base + 24) & 31; c->yuvTable = av_malloc(1024 * 3 * 4); y_table32 = c->yuvTable; yb = -(384 << 16) - oy; for (i = 0; i < 1024; i++) { unsigned yval = av_clip_uint8((yb + 0x8000) >> 16); y_table32[i] = (yval << rbase) + (needAlpha ? 0 : (255u << abase)); y_table32[i + 1024] = yval << gbase; y_table32[i + 2048] = yval << bbase; yb += cy; } fill_table(c->table_rV, 4, crv, y_table32 + yoffs); fill_table(c->table_gU, 4, cgu, y_table32 + yoffs + 1024); fill_table(c->table_bU, 4, cbu, y_table32 + yoffs + 2048); fill_gv_table(c->table_gV, 4, cgv); break; default: if(!isPlanar(c->dstFormat) || bpp <= 24) av_log(c, AV_LOG_ERROR, "%ibpp not supported by yuv2rgb\n", bpp); return -1; } return 0; }