mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
Speed up 24-bit packing / unpacking in YUV / RGB conversions.
This implementation brings: - an SSE implementation of packing / unpacking - bigger buffers processed at the same time The speedup is of 4% on lossy decoding (YUV to RGB), 0.5% on lossy encoding (RGB to YUV was already optimized). Change-Id: Iec677ee17f91c08614d1adab67c6df551925767f
This commit is contained in:
parent
68eebcb0ff
commit
80ce27d34e
@ -110,46 +110,55 @@ static WEBP_INLINE void PackAndStore4(const __m128i* const R,
|
||||
_mm_storeu_si128((__m128i*)(dst + 16), RGBA_hi);
|
||||
}
|
||||
|
||||
// Pack R/G/B results into 24b output.
|
||||
static WEBP_INLINE void PackAndStore3(const __m128i* const R,
|
||||
const __m128i* const G,
|
||||
const __m128i* const B,
|
||||
uint8_t* const dst) {
|
||||
const __m128i tmp0 = _mm_packus_epi16(*R, *R);
|
||||
const __m128i tmp1 = _mm_packus_epi16(*G, *G);
|
||||
const __m128i tmp2 = _mm_packus_epi16(*B, *B);
|
||||
_mm_storel_epi64((__m128i*)(dst + 0 * 32), tmp0);
|
||||
_mm_storel_epi64((__m128i*)(dst + 1 * 32), tmp1);
|
||||
_mm_storel_epi64((__m128i*)(dst + 2 * 32), tmp2);
|
||||
// Function used several times in PlanarTo24b.
|
||||
// It samples the in buffer as follows: one every two unsigned char is stored
|
||||
// at the beginning of the buffer, while the other half is stored at the end.
|
||||
static WEBP_INLINE void PlanarTo24bHelper(const __m128i in[6], __m128i out[6]) {
|
||||
const __m128i v_mask = _mm_set1_epi16(0x00ff);
|
||||
|
||||
// Take one every two upper 8b values.
|
||||
out[0] = _mm_packus_epi16(_mm_and_si128(in[0], v_mask),
|
||||
_mm_and_si128(in[1], v_mask));
|
||||
out[1] = _mm_packus_epi16(_mm_and_si128(in[2], v_mask),
|
||||
_mm_and_si128(in[3], v_mask));
|
||||
out[2] = _mm_packus_epi16(_mm_and_si128(in[4], v_mask),
|
||||
_mm_and_si128(in[5], v_mask));
|
||||
// Take one every two lower 8b values.
|
||||
out[3] = _mm_packus_epi16(_mm_srli_epi16(in[0], 8), _mm_srli_epi16(in[1], 8));
|
||||
out[4] = _mm_packus_epi16(_mm_srli_epi16(in[2], 8), _mm_srli_epi16(in[3], 8));
|
||||
out[5] = _mm_packus_epi16(_mm_srli_epi16(in[4], 8), _mm_srli_epi16(in[5], 8));
|
||||
}
|
||||
|
||||
// Converts 32 samples in src[3][32] to interleaved RGB24 in dst[]
|
||||
#define MK_UINT32(A, B, C, D) \
|
||||
((A) << 0) | ((B) << 8) | ((C) << 16) | ((uint32_t)(D) << 24)
|
||||
static WEBP_INLINE void PlanarTo24b(const uint8_t* src, uint8_t* dst) {
|
||||
#if 1
|
||||
// This code is faster than the version below (left there for reference).
|
||||
// It's also endian-dependent but we're only targeting x86.
|
||||
const uint8_t* const end = src + 32;
|
||||
for (; src < end; src += 4, dst += 12) {
|
||||
const uint32_t A = MK_UINT32(src[0 + 0 * 32], src[0 + 1 * 32],
|
||||
src[0 + 2 * 32], src[1 + 0 * 32]);
|
||||
const uint32_t B = MK_UINT32(src[1 + 1 * 32], src[1 + 2 * 32],
|
||||
src[2 + 0 * 32], src[2 + 1 * 32]);
|
||||
const uint32_t C = MK_UINT32(src[2 + 2 * 32], src[3 + 0 * 32],
|
||||
src[3 + 1 * 32], src[3 + 2 * 32]);
|
||||
*(uint32_t*)(dst + 0) = A;
|
||||
*(uint32_t*)(dst + 4) = B;
|
||||
*(uint32_t*)(dst + 8) = C;
|
||||
}
|
||||
#else
|
||||
int n;
|
||||
for (n = 0; n < 32; ++n) {
|
||||
*dst++ = src[0 * 32 + n];
|
||||
*dst++ = src[1 * 32 + n];
|
||||
*dst++ = src[2 * 32 + n];
|
||||
}
|
||||
#endif
|
||||
// Pack the planar buffers
|
||||
// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
|
||||
// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
|
||||
static WEBP_INLINE void PlanarTo24b(__m128i in[6], uint8_t* rgb) {
|
||||
// The input is 6 registers of sixteen 8b but for the sake of explanation,
|
||||
// let's take 6 registers of four 8b values.
|
||||
// To pack, we will keep taking one every two 8b integer and move it
|
||||
// around as follows:
|
||||
// Input:
|
||||
// r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7
|
||||
// Split the 6 registers in two sets of 3 registers: the first set as the even
|
||||
// 8b bytes, the second the odd ones:
|
||||
// r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7
|
||||
// Repeat the same permutations twice more:
|
||||
// r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
|
||||
// r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
|
||||
__m128i tmp[6];
|
||||
PlanarTo24bHelper(in, tmp);
|
||||
PlanarTo24bHelper(tmp, in);
|
||||
PlanarTo24bHelper(in, tmp);
|
||||
// We need to do it two more times than the example as we have sixteen bytes.
|
||||
PlanarTo24bHelper(tmp, in);
|
||||
PlanarTo24bHelper(in, tmp);
|
||||
|
||||
_mm_storeu_si128((__m128i*)(rgb + 0), tmp[0]);
|
||||
_mm_storeu_si128((__m128i*)(rgb + 16), tmp[1]);
|
||||
_mm_storeu_si128((__m128i*)(rgb + 32), tmp[2]);
|
||||
_mm_storeu_si128((__m128i*)(rgb + 48), tmp[3]);
|
||||
_mm_storeu_si128((__m128i*)(rgb + 64), tmp[4]);
|
||||
_mm_storeu_si128((__m128i*)(rgb + 80), tmp[5]);
|
||||
}
|
||||
#undef MK_UINT32
|
||||
|
||||
@ -177,26 +186,46 @@ void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||
|
||||
void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||
uint8_t* dst) {
|
||||
int n;
|
||||
uint8_t tmp[32 * 3];
|
||||
for (n = 0; n < 32; n += 8) {
|
||||
__m128i R, G, B;
|
||||
YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
|
||||
PackAndStore3(&R, &G, &B, tmp + n);
|
||||
}
|
||||
PlanarTo24b(tmp, dst);
|
||||
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
|
||||
__m128i rgb[6];
|
||||
|
||||
YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
|
||||
YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
|
||||
YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2);
|
||||
YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
|
||||
|
||||
// Cast to 8b and store as RRRRGGGGBBBB.
|
||||
rgb[0] = _mm_packus_epi16(R0, R1);
|
||||
rgb[1] = _mm_packus_epi16(R2, R3);
|
||||
rgb[2] = _mm_packus_epi16(G0, G1);
|
||||
rgb[3] = _mm_packus_epi16(G2, G3);
|
||||
rgb[4] = _mm_packus_epi16(B0, B1);
|
||||
rgb[5] = _mm_packus_epi16(B2, B3);
|
||||
|
||||
// Pack as RGBRGBRGBRGB.
|
||||
PlanarTo24b(rgb, dst);
|
||||
}
|
||||
|
||||
void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||
uint8_t* dst) {
|
||||
int n;
|
||||
uint8_t tmp[32 * 3];
|
||||
for (n = 0; n < 32; n += 8) {
|
||||
__m128i R, G, B;
|
||||
YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B);
|
||||
PackAndStore3(&B, &G, &R, tmp + n);
|
||||
}
|
||||
PlanarTo24b(tmp, dst);
|
||||
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
|
||||
__m128i bgr[6];
|
||||
|
||||
YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
|
||||
YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
|
||||
YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2);
|
||||
YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
|
||||
|
||||
// Cast to 8b and store as BBBBGGGGRRRR.
|
||||
bgr[0] = _mm_packus_epi16(B0, B1);
|
||||
bgr[1] = _mm_packus_epi16(B2, B3);
|
||||
bgr[2] = _mm_packus_epi16(G0, G1);
|
||||
bgr[3] = _mm_packus_epi16(G2, G3);
|
||||
bgr[4] = _mm_packus_epi16(R0, R1);
|
||||
bgr[5] = _mm_packus_epi16(R2, R3);
|
||||
|
||||
// Pack as BGRBGRBGRBGR.
|
||||
PlanarTo24b(bgr, dst);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -269,17 +298,25 @@ static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||
uint8_t* dst, int len) {
|
||||
int n;
|
||||
for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
|
||||
uint8_t tmp[32 * 3];
|
||||
__m128i R, G, B;
|
||||
YUV420ToRGB(y + 0, u + 0, v + 0, &R, &G, &B);
|
||||
PackAndStore3(&R, &G, &B, tmp + 0);
|
||||
YUV420ToRGB(y + 8, u + 4, v + 4, &R, &G, &B);
|
||||
PackAndStore3(&R, &G, &B, tmp + 8);
|
||||
YUV420ToRGB(y + 16, u + 8, v + 8, &R, &G, &B);
|
||||
PackAndStore3(&R, &G, &B, tmp + 16);
|
||||
YUV420ToRGB(y + 24, u + 12, v + 12, &R, &G, &B);
|
||||
PackAndStore3(&R, &G, &B, tmp + 24);
|
||||
PlanarTo24b(tmp, dst);
|
||||
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
|
||||
__m128i rgb[6];
|
||||
|
||||
YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
|
||||
YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
|
||||
YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2);
|
||||
YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
|
||||
|
||||
// Cast to 8b and store as RRRRGGGGBBBB.
|
||||
rgb[0] = _mm_packus_epi16(R0, R1);
|
||||
rgb[1] = _mm_packus_epi16(R2, R3);
|
||||
rgb[2] = _mm_packus_epi16(G0, G1);
|
||||
rgb[3] = _mm_packus_epi16(G2, G3);
|
||||
rgb[4] = _mm_packus_epi16(B0, B1);
|
||||
rgb[5] = _mm_packus_epi16(B2, B3);
|
||||
|
||||
// Pack as RGBRGBRGBRGB.
|
||||
PlanarTo24b(rgb, dst);
|
||||
|
||||
y += 32;
|
||||
u += 16;
|
||||
v += 16;
|
||||
@ -297,17 +334,25 @@ static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
|
||||
uint8_t* dst, int len) {
|
||||
int n;
|
||||
for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
|
||||
uint8_t tmp[32 * 3];
|
||||
__m128i R, G, B;
|
||||
YUV420ToRGB(y + 0, u + 0, v + 0, &R, &G, &B);
|
||||
PackAndStore3(&B, &G, &R, tmp + 0);
|
||||
YUV420ToRGB(y + 8, u + 4, v + 4, &R, &G, &B);
|
||||
PackAndStore3(&B, &G, &R, tmp + 8);
|
||||
YUV420ToRGB(y + 16, u + 8, v + 8, &R, &G, &B);
|
||||
PackAndStore3(&B, &G, &R, tmp + 16);
|
||||
YUV420ToRGB(y + 24, u + 12, v + 12, &R, &G, &B);
|
||||
PackAndStore3(&B, &G, &R, tmp + 24);
|
||||
PlanarTo24b(tmp, dst);
|
||||
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
|
||||
__m128i bgr[6];
|
||||
|
||||
YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
|
||||
YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
|
||||
YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2);
|
||||
YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
|
||||
|
||||
// Cast to 8b and store as BBBBGGGGRRRR.
|
||||
bgr[0] = _mm_packus_epi16(B0, B1);
|
||||
bgr[1] = _mm_packus_epi16(B2, B3);
|
||||
bgr[2] = _mm_packus_epi16(G0, G1);
|
||||
bgr[3] = _mm_packus_epi16(G2, G3);
|
||||
bgr[4] = _mm_packus_epi16(R0, R1);
|
||||
bgr[5] = _mm_packus_epi16(R2, R3);
|
||||
|
||||
// Pack as BGRBGRBGRBGR.
|
||||
PlanarTo24b(bgr, dst);
|
||||
|
||||
y += 32;
|
||||
u += 16;
|
||||
v += 16;
|
||||
@ -342,52 +387,36 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) {
|
||||
// Store either 16b-words into *dst
|
||||
#define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V))
|
||||
|
||||
// Convert 8 packed RGB or BGR samples to r[], g[], b[]
|
||||
// Function that inserts a value of the second half of the in buffer in between
|
||||
// every two char of the first half.
|
||||
static WEBP_INLINE void RGB24PackedToPlanarHelper(const __m128i in[6],
|
||||
__m128i out[6]) {
|
||||
out[0] = _mm_unpacklo_epi8(in[0], in[3]);
|
||||
out[1] = _mm_unpackhi_epi8(in[0], in[3]);
|
||||
out[2] = _mm_unpacklo_epi8(in[1], in[4]);
|
||||
out[3] = _mm_unpackhi_epi8(in[1], in[4]);
|
||||
out[4] = _mm_unpacklo_epi8(in[2], in[5]);
|
||||
out[5] = _mm_unpackhi_epi8(in[2], in[5]);
|
||||
}
|
||||
|
||||
// Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers:
|
||||
// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
|
||||
// Similar to PlanarTo24bHelper(), but in reverse order.
|
||||
static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb,
|
||||
__m128i* const r,
|
||||
__m128i* const g,
|
||||
__m128i* const b,
|
||||
int input_is_bgr) {
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
// in0: r0 g0 b0 r1 | g1 b1 r2 g2 | b2 r3 g3 b3 | r4 g4 b4 r5
|
||||
// in1: b2 r3 g3 b3 | r4 g4 b4 r5 | g5 b5 r6 g6 | b6 r7 g7 b7
|
||||
const __m128i in0 = LOAD_16(rgb + 0);
|
||||
const __m128i in1 = LOAD_16(rgb + 8);
|
||||
// A0: | r2 g2 b2 r3 | g3 b3 r4 g4 | b4 r5 ...
|
||||
// A1: ... b2 r3 | g3 b3 r4 g4 | b4 r5 g5 b5 |
|
||||
const __m128i A0 = _mm_srli_si128(in0, 6);
|
||||
const __m128i A1 = _mm_slli_si128(in1, 6);
|
||||
// B0: r0 r2 g0 g2 | b0 b2 r1 r3 | g1 g3 b1 b3 | r2 r4 b2 b4
|
||||
// B1: g3 g5 b3 b5 | r4 r6 g4 g6 | b4 b6 r5 r7 | g5 g7 b5 b7
|
||||
const __m128i B0 = _mm_unpacklo_epi8(in0, A0);
|
||||
const __m128i B1 = _mm_unpackhi_epi8(A1, in1);
|
||||
// C0: r1 r3 g1 g3 | b1 b3 r2 r4 | b2 b4 ...
|
||||
// C1: ... g3 g5 | b3 b5 r4 r6 | g4 g6 b4 b6
|
||||
const __m128i C0 = _mm_srli_si128(B0, 6);
|
||||
const __m128i C1 = _mm_slli_si128(B1, 6);
|
||||
// D0: r0 r1 r2 r3 | g0 g1 g2 g3 | b0 b1 b2 b3 | r1 r2 r3 r4
|
||||
// D1: b3 b4 b5 b6 | r4 r5 r6 r7 | g4 g5 g6 g7 | b4 b5 b6 b7 |
|
||||
const __m128i D0 = _mm_unpacklo_epi8(B0, C0);
|
||||
const __m128i D1 = _mm_unpackhi_epi8(C1, B1);
|
||||
// r4 r5 r6 r7 | g4 g5 g6 g7 | b4 b5 b6 b7 | 0
|
||||
const __m128i D2 = _mm_srli_si128(D1, 4);
|
||||
// r0 r1 r2 r3 | r4 r5 r6 r7 | g0 g1 g2 g3 | g4 g5 g6 g7
|
||||
const __m128i E0 = _mm_unpacklo_epi32(D0, D2);
|
||||
// b0 b1 b2 b3 | b4 b5 b6 b7 | r1 r2 r3 r4 | 0
|
||||
const __m128i E1 = _mm_unpackhi_epi32(D0, D2);
|
||||
// g0 g1 g2 g3 | g4 g5 g6 g7 | 0
|
||||
const __m128i E2 = _mm_srli_si128(E0, 8);
|
||||
const __m128i F0 = _mm_unpacklo_epi8(E0, zero); // -> R
|
||||
const __m128i F1 = _mm_unpacklo_epi8(E1, zero); // -> B
|
||||
const __m128i F2 = _mm_unpacklo_epi8(E2, zero); // -> G
|
||||
*g = F2;
|
||||
if (input_is_bgr) {
|
||||
*r = F1;
|
||||
*b = F0;
|
||||
} else {
|
||||
*r = F0;
|
||||
*b = F1;
|
||||
}
|
||||
__m128i out[6]) {
|
||||
__m128i tmp[6];
|
||||
tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0));
|
||||
tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16));
|
||||
tmp[2] = _mm_loadu_si128((const __m128i*)(rgb + 32));
|
||||
tmp[3] = _mm_loadu_si128((const __m128i*)(rgb + 48));
|
||||
tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64));
|
||||
tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80));
|
||||
|
||||
RGB24PackedToPlanarHelper(tmp, out);
|
||||
RGB24PackedToPlanarHelper(out, tmp);
|
||||
RGB24PackedToPlanarHelper(tmp, out);
|
||||
RGB24PackedToPlanarHelper(out, tmp);
|
||||
RGB24PackedToPlanarHelper(tmp, out);
|
||||
}
|
||||
|
||||
// Convert 8 packed ARGB to r[], g[], b[]
|
||||
@ -471,15 +500,33 @@ static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R,
|
||||
#undef TRANSFORM
|
||||
|
||||
static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
|
||||
const int max_width = width & ~15;
|
||||
const int max_width = width & ~31;
|
||||
int i;
|
||||
for (i = 0; i < max_width; i += 16, rgb += 3 * 16) {
|
||||
__m128i r, g, b, Y0, Y1;
|
||||
RGB24PackedToPlanar(rgb + 0 * 8, &r, &g, &b, 0);
|
||||
ConvertRGBToY(&r, &g, &b, &Y0);
|
||||
RGB24PackedToPlanar(rgb + 3 * 8, &r, &g, &b, 0);
|
||||
ConvertRGBToY(&r, &g, &b, &Y1);
|
||||
STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
|
||||
for (i = 0; i < max_width; rgb += 3 * 16 * 2) {
|
||||
__m128i rgb_plane[6];
|
||||
int j;
|
||||
|
||||
RGB24PackedToPlanar(rgb, rgb_plane);
|
||||
|
||||
for (j = 0; j < 2; ++j, i += 16) {
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i r, g, b, Y0, Y1;
|
||||
|
||||
// Convert to 16-bit Y.
|
||||
r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero);
|
||||
g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero);
|
||||
b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero);
|
||||
ConvertRGBToY(&r, &g, &b, &Y0);
|
||||
|
||||
// Convert to 16-bit Y.
|
||||
r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero);
|
||||
g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero);
|
||||
b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero);
|
||||
ConvertRGBToY(&r, &g, &b, &Y1);
|
||||
|
||||
// Cast to 8-bit and store.
|
||||
STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
|
||||
}
|
||||
}
|
||||
for (; i < width; ++i, rgb += 3) { // left-over
|
||||
y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF);
|
||||
@ -487,15 +534,33 @@ static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) {
|
||||
}
|
||||
|
||||
static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) {
|
||||
const int max_width = width & ~31;
|
||||
int i;
|
||||
const int max_width = width & ~15;
|
||||
for (i = 0; i < max_width; i += 16, bgr += 3 * 16) {
|
||||
__m128i r, g, b, Y0, Y1;
|
||||
RGB24PackedToPlanar(bgr + 0 * 8, &r, &g, &b, 1);
|
||||
ConvertRGBToY(&r, &g, &b, &Y0);
|
||||
RGB24PackedToPlanar(bgr + 3 * 8, &r, &g, &b, 1);
|
||||
ConvertRGBToY(&r, &g, &b, &Y1);
|
||||
STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
|
||||
for (i = 0; i < max_width; bgr += 3 * 16 * 2) {
|
||||
__m128i bgr_plane[6];
|
||||
int j;
|
||||
|
||||
RGB24PackedToPlanar(bgr, bgr_plane);
|
||||
|
||||
for (j = 0; j < 2; ++j, i += 16) {
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
__m128i r, g, b, Y0, Y1;
|
||||
|
||||
// Convert to 16-bit Y.
|
||||
b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero);
|
||||
g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero);
|
||||
r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero);
|
||||
ConvertRGBToY(&r, &g, &b, &Y0);
|
||||
|
||||
// Convert to 16-bit Y.
|
||||
b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero);
|
||||
g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero);
|
||||
r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero);
|
||||
ConvertRGBToY(&r, &g, &b, &Y1);
|
||||
|
||||
// Cast to 8-bit and store.
|
||||
STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
|
||||
}
|
||||
}
|
||||
for (; i < width; ++i, bgr += 3) { // left-over
|
||||
y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF);
|
||||
|
Loading…
Reference in New Issue
Block a user