mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +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:
		| @@ -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[] | ||||
| 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; | ||||
| // 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 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,32 +500,68 @@ 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) { | ||||
|   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; | ||||
|     RGB24PackedToPlanar(rgb + 0 * 8, &r, &g, &b, 0); | ||||
|  | ||||
|       // 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); | ||||
|     RGB24PackedToPlanar(rgb + 3 * 8, &r, &g, &b, 0); | ||||
|  | ||||
|       // 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); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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) { | ||||
|   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; | ||||
|     RGB24PackedToPlanar(bgr + 0 * 8, &r, &g, &b, 1); | ||||
|  | ||||
|       // 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); | ||||
|     RGB24PackedToPlanar(bgr + 3 * 8, &r, &g, &b, 1); | ||||
|  | ||||
|       // 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); | ||||
|   } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user