15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This webpage shows layout of YV12 and other YUV formats
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.fourcc.org/yuv.php
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The actual conversion is best described here
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://en.wikipedia.org/wiki/YUV
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An article on optimizing YUV conversion using tables instead of multiplies
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// YV12 is a full plane of Y and a half height, half width chroma planes
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// YV16 is a full plane of Y and a full height, half width chroma planes
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ARGB pixel format is output, which on little endian is stored as BGRA.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The alpha is set to 255, allowing the application to use RGBA or RGB32.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cpu.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/convert_rgb_to_yuv.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/convert_yuv_to_rgb.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/filter_yuv.h"
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "media/base/simd/yuv_to_rgb_table.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_FAMILY)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(COMPILER_MSVC)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <intrin.h>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmintrin.h>
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Assembly functions are declared without namespace.
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)extern "C" { void EmptyRegisterState_MMX(); }  // extern "C"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*FilterYUVRowsProc)(uint8*, const uint8*, const uint8*, int, int);
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)typedef void (*ConvertRGBToYUVProc)(const uint8*,
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    uint8*,
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    uint8*,
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    uint8*,
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int,
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int,
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int,
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int,
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    int);
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*ConvertYUVToRGB32Proc)(const uint8*,
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const uint8*,
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const uint8*,
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      uint8*,
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      YUVType);
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*ConvertYUVAToARGBProc)(const uint8*,
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const uint8*,
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const uint8*,
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      const uint8*,
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      uint8*,
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int,
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      YUVType);
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*ConvertYUVToRGB32RowProc)(const uint8*,
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const uint8*,
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const uint8*,
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         uint8*,
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                         ptrdiff_t,
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                         const int16[1024][4]);
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*ConvertYUVAToARGBRowProc)(const uint8*,
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const uint8*,
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const uint8*,
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const uint8*,
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         uint8*,
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                         ptrdiff_t,
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                         const int16[1024][4]);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef void (*ScaleYUVToRGB32RowProc)(const uint8*,
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       const uint8*,
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       const uint8*,
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       uint8*,
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       ptrdiff_t,
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       ptrdiff_t,
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       const int16[1024][4]);
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static FilterYUVRowsProc g_filter_yuv_rows_proc_ = NULL;
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ConvertYUVToRGB32RowProc g_convert_yuv_to_rgb32_row_proc_ = NULL;
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ScaleYUVToRGB32RowProc g_scale_yuv_to_rgb32_row_proc_ = NULL;
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ScaleYUVToRGB32RowProc g_linear_scale_yuv_to_rgb32_row_proc_ = NULL;
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ConvertRGBToYUVProc g_convert_rgb32_to_yuv_proc_ = NULL;
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ConvertRGBToYUVProc g_convert_rgb24_to_yuv_proc_ = NULL;
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ConvertYUVToRGB32Proc g_convert_yuv_to_rgb32_proc_ = NULL;
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static ConvertYUVAToARGBProc g_convert_yuva_to_argb_proc_ = NULL;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Empty SIMD registers state after using them.
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EmptyRegisterStateStub() {}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(MEDIA_MMX_INTRINSICS_AVAILABLE)
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EmptyRegisterStateIntrinsic() { _mm_empty(); }
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)typedef void (*EmptyRegisterStateProc)();
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static EmptyRegisterStateProc g_empty_register_state_proc_ = NULL;
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Get the appropriate value to bitshift by for vertical indices.
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int GetVerticalShift(YUVType type) {
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (type) {
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV16:
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return 0;
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV12:
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV12J:
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return 1;
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NOTREACHED();
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return 0;
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int16 (&GetLookupTable(YUVType type))[1024][4] {
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (type) {
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV12:
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV16:
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return kCoefficientsRgbY;
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case YV12J:
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return kCoefficientsRgbY_JPEG;
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NOTREACHED();
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return kCoefficientsRgbY;
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void InitializeCPUSpecificYUVConversions() {
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_filter_yuv_rows_proc_);
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_convert_yuv_to_rgb32_row_proc_);
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_scale_yuv_to_rgb32_row_proc_);
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_linear_scale_yuv_to_rgb32_row_proc_);
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_convert_rgb32_to_yuv_proc_);
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_convert_rgb24_to_yuv_proc_);
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_convert_yuv_to_rgb32_proc_);
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_convert_yuva_to_argb_proc_);
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!g_empty_register_state_proc_);
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_filter_yuv_rows_proc_ = FilterYUVRows_C;
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_yuv_to_rgb32_row_proc_ = ConvertYUVToRGB32Row_C;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_scale_yuv_to_rgb32_row_proc_ = ScaleYUVToRGB32Row_C;
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_linear_scale_yuv_to_rgb32_row_proc_ = LinearScaleYUVToRGB32Row_C;
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_rgb32_to_yuv_proc_ = ConvertRGB32ToYUV_C;
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_rgb24_to_yuv_proc_ = ConvertRGB24ToYUV_C;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_yuv_to_rgb32_proc_ = ConvertYUVToRGB32_C;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_yuva_to_argb_proc_ = ConvertYUVAToARGB_C;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_empty_register_state_proc_ = EmptyRegisterStateStub;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Assembly code confuses MemorySanitizer.
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ARCH_CPU_X86_FAMILY) && !defined(MEMORY_SANITIZER)
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_convert_yuva_to_argb_proc_ = ConvertYUVAToARGB_MMX;
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(MEDIA_MMX_INTRINSICS_AVAILABLE)
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_empty_register_state_proc_ = EmptyRegisterStateIntrinsic;
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_empty_register_state_proc_ = EmptyRegisterState_MMX;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_convert_yuv_to_rgb32_row_proc_ = ConvertYUVToRGB32Row_SSE;
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_convert_yuv_to_rgb32_proc_ = ConvertYUVToRGB32_SSE;
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_filter_yuv_rows_proc_ = FilterYUVRows_SSE2;
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_convert_rgb32_to_yuv_proc_ = ConvertRGB32ToYUV_SSE2;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_64)
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_scale_yuv_to_rgb32_row_proc_ = ScaleYUVToRGB32Row_SSE2_X64;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Technically this should be in the MMX section, but MSVC will optimize out
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the export of LinearScaleYUVToRGB32Row_MMX, which is required by the unit
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // tests, if that decision can be made at compile time.  Since all X64 CPUs
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // have SSE2, we can hack around this by making the selection here.
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_linear_scale_yuv_to_rgb32_row_proc_ = LinearScaleYUVToRGB32Row_MMX_X64;
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_scale_yuv_to_rgb32_row_proc_ = ScaleYUVToRGB32Row_SSE;
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_linear_scale_yuv_to_rgb32_row_proc_ = LinearScaleYUVToRGB32Row_SSE;
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::CPU cpu;
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cpu.has_ssse3()) {
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    g_convert_rgb24_to_yuv_proc_ = &ConvertRGB24ToYUV_SSSE3;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(hclam): Add ConvertRGB32ToYUV_SSSE3 when the cyan problem is solved.
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // See: crbug.com/100462
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Empty SIMD registers state after using them.
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EmptyRegisterState() { g_empty_register_state_proc_(); }
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 16.16 fixed point arithmetic
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFractionBits = 16;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFractionMax = 1 << kFractionBits;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFractionMask = ((1 << kFractionBits) - 1);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Scale a frame of YUV to 32 bit ARGB.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScaleYUVToRGB32(const uint8* y_buf,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const uint8* u_buf,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const uint8* v_buf,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     uint8* rgb_buf,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int source_width,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int source_height,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int width,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int height,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int y_pitch,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int uv_pitch,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int rgb_pitch,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     YUVType yuv_type,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     Rotate view_rotate,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     ScaleFilter filter) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle zero sized sources and destinations.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((yuv_type == YV12 && (source_width < 2 || source_height < 2)) ||
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (yuv_type == YV16 && (source_width < 2 || source_height < 1)) ||
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width == 0 || height == 0)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4096 allows 3 buffers to fit in 12k.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helps performance on CPU with 16K L1 cache.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Large enough for 3830x2160 and 30" displays which are 2560x1600.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kFilterBufferSize = 4096;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disable filtering if the screen is too big (to avoid buffer overflows).
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should never happen to regular users: they don't have monitors
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wider than 4096 pixels.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fbarchard): Allow rotated videos to filter.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (source_width > kFilterBufferSize || view_rotate)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter = FILTER_NONE;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  unsigned int y_shift = GetVerticalShift(yuv_type);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Diagram showing origin and direction of source sampling.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ->0   4<-
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 7       3
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 6       5
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ->1   2<-
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rotations that start at right side of image.
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if ((view_rotate == ROTATE_180) || (view_rotate == ROTATE_270) ||
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (view_rotate == MIRROR_ROTATE_0) || (view_rotate == MIRROR_ROTATE_90)) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_buf += source_width - 1;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u_buf += source_width / 2 - 1;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v_buf += source_width / 2 - 1;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_width = -source_width;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rotations that start at bottom of image.
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if ((view_rotate == ROTATE_90) || (view_rotate == ROTATE_180) ||
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      (view_rotate == MIRROR_ROTATE_90) || (view_rotate == MIRROR_ROTATE_180)) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_buf += (source_height - 1) * y_pitch;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u_buf += ((source_height >> y_shift) - 1) * uv_pitch;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v_buf += ((source_height >> y_shift) - 1) * uv_pitch;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_height = -source_height;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_dx = source_width * kFractionMax / width;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if ((view_rotate == ROTATE_90) || (view_rotate == ROTATE_270)) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tmp = height;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height = width;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width = tmp;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = source_height;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_height = source_width;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_width = tmp;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_dy = source_height * kFractionMax / height;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_dx = ((source_dy >> kFractionBits) * y_pitch) << kFractionBits;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (view_rotate == ROTATE_90) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_pitch = -1;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uv_pitch = -1;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_height = -source_height;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_pitch = 1;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uv_pitch = 1;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need padding because FilterRows() will write 1 to 16 extra pixels
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after the end for SSE2 version.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 yuvbuf[16 + kFilterBufferSize * 3 + 16];
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* ybuf =
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<uint8*>(reinterpret_cast<uintptr_t>(yuvbuf + 15) & ~15);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* ubuf = ybuf + kFilterBufferSize;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* vbuf = ubuf + kFilterBufferSize;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fbarchard): Fixed point math is off by 1 on negatives.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We take a y-coordinate in [0,1] space in the source image space, and
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // transform to a y-coordinate in [0,1] space in the destination image space.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the coordinate endpoints lie on pixel boundaries, not on pixel
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // centers: e.g. a two-pixel-high image will have pixel centers at 0.25 and
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0.75.  The formula is as follows (in fixed-point arithmetic):
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   y_dst = dst_height * ((y_src + 0.5) / src_height)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   dst_pixel = clamp([0, dst_height - 1], floor(y_dst - 0.5))
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implement this here as an accumulator + delta, to avoid expensive math
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the loop.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_y_subpixel_accum =
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ((kFractionMax / 2) * source_height) / height - (kFractionMax / 2);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_y_subpixel_delta = ((1 << kFractionBits) * source_height) / height;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fbarchard): Split this into separate function for better efficiency.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int y = 0; y < height; ++y) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* dest_pixel = rgb_buf + y * rgb_pitch;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_y_subpixel = source_y_subpixel_accum;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_y_subpixel_accum += source_y_subpixel_delta;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (source_y_subpixel < 0)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_y_subpixel = 0;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (source_y_subpixel > ((source_height - 1) << kFractionBits))
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_y_subpixel = (source_height - 1) << kFractionBits;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* y_ptr = NULL;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* u_ptr = NULL;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* v_ptr = NULL;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Apply vertical filtering if necessary.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(fbarchard): Remove memcpy when not necessary.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (filter & media::FILTER_BILINEAR_V) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int source_y = source_y_subpixel >> kFractionBits;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_ptr = y_buf + source_y * y_pitch;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Vertical scaler uses 16.8 fixed point.
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int source_y_fraction = (source_y_subpixel & kFractionMask) >> 8;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (source_y_fraction != 0) {
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        g_filter_yuv_rows_proc_(
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ybuf, y_ptr, y_ptr + y_pitch, source_width, source_y_fraction);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(ybuf, y_ptr, source_width);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_ptr = ybuf;
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ybuf[source_width] = ybuf[source_width - 1];
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int uv_source_width = (source_width + 1) / 2;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int source_uv_fraction;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For formats with half-height UV planes, each even-numbered pixel row
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // should not interpolate, since the next row to interpolate from should
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // be a duplicate of the current row.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (y_shift && (source_y & 0x1) == 0)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source_uv_fraction = 0;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source_uv_fraction = source_y_fraction;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (source_uv_fraction != 0) {
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        g_filter_yuv_rows_proc_(
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ubuf, u_ptr, u_ptr + uv_pitch, uv_source_width, source_uv_fraction);
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        g_filter_yuv_rows_proc_(
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            vbuf, v_ptr, v_ptr + uv_pitch, uv_source_width, source_uv_fraction);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(ubuf, u_ptr, uv_source_width);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(vbuf, v_ptr, uv_source_width);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u_ptr = ubuf;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v_ptr = vbuf;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ubuf[uv_source_width] = ubuf[uv_source_width - 1];
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vbuf[uv_source_width] = vbuf[uv_source_width - 1];
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Offset by 1/2 pixel for center sampling.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int source_y = (source_y_subpixel + (kFractionMax / 2)) >> kFractionBits;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y_ptr = y_buf + source_y * y_pitch;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (source_dx == kFractionMax) {  // Not scaled
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      g_convert_yuv_to_rgb32_row_proc_(
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          y_ptr, u_ptr, v_ptr, dest_pixel, width, kCoefficientsRgbY);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (filter & FILTER_BILINEAR_H) {
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        g_linear_scale_yuv_to_rgb32_row_proc_(y_ptr,
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              u_ptr,
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              v_ptr,
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              dest_pixel,
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              width,
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              source_dx,
386010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              kCoefficientsRgbY);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
388010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        g_scale_yuv_to_rgb32_row_proc_(y_ptr,
389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       u_ptr,
390010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       v_ptr,
391010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       dest_pixel,
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       width,
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       source_dx,
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       kCoefficientsRgbY);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_empty_register_state_proc_();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Scale a frame of YV12 to 32 bit ARGB for a specific rectangle.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScaleYUVToRGB32WithRect(const uint8* y_buf,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const uint8* u_buf,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const uint8* v_buf,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             uint8* rgb_buf,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int source_width,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int source_height,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_width,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_height,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_rect_left,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_rect_top,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_rect_right,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int dest_rect_bottom,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int y_pitch,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int uv_pitch,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int rgb_pitch) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This routine doesn't currently support up-scaling.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_LE(dest_width, source_width);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_LE(dest_height, source_height);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity-check the destination rectangle.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dest_rect_left >= 0 && dest_rect_right <= dest_width);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dest_rect_top >= 0 && dest_rect_bottom <= dest_height);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dest_rect_right > dest_rect_left);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(dest_rect_bottom > dest_rect_top);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fixed-point value of vertical and horizontal scale down factor.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Values are in the format 16.16.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_step = kFractionMax * source_height / dest_height;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x_step = kFractionMax * source_width / dest_width;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the coordinates of the rectangle in 16.16 coords.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NB: Our origin is the *center* of the top/left pixel, NOT its top/left.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're down-scaling by more than a factor of two, we start with a 50%
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fraction to avoid degenerating to point-sampling - we should really just
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fix the fraction at 50% for all pixels in that case.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_left = dest_rect_left * x_step;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_right = (dest_rect_right - 1) * x_step;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (x_step < kFractionMax * 2) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_left += ((x_step - kFractionMax) / 2);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_right += ((x_step - kFractionMax) / 2);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_left += kFractionMax / 2;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_right += kFractionMax / 2;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_top = dest_rect_top * y_step;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (y_step < kFractionMax * 2) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_top += ((y_step - kFractionMax) / 2);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_top += kFractionMax / 2;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the parts of the Y, U and V buffers to interpolate.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_y_left = source_left >> kFractionBits;
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int source_y_right =
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      std::min((source_right >> kFractionBits) + 2, source_width + 1);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_uv_left = source_y_left / 2;
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int source_uv_right = std::min((source_right >> (kFractionBits + 1)) + 2,
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 (source_width + 1) / 2);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_y_width = source_y_right - source_y_left;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_uv_width = source_uv_right - source_uv_left;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine number of pixels in each output row.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dest_rect_width = dest_rect_right - dest_rect_left;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intermediate buffer for vertical interpolation.
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4096 bytes allows 3 buffers to fit in 12k, which fits in a 16K L1 cache,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and is bigger than most users will generally need.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The buffer is 16-byte aligned and padded with 16 extra bytes; some of the
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FilterYUVRowProcs have alignment requirements, and the SSE version can
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // write up to 16 bytes past the end of the buffer.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kFilterBufferSize = 4096;
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const bool kAvoidUsingOptimizedFilter = source_width > kFilterBufferSize;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 yuv_temp[16 + kFilterBufferSize * 3 + 16];
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // memset() yuv_temp to 0 to avoid bogus warnings when running on Valgrind.
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (RunningOnValgrind())
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    memset(yuv_temp, 0, sizeof(yuv_temp));
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  uint8* y_temp = reinterpret_cast<uint8*>(
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      reinterpret_cast<uintptr_t>(yuv_temp + 15) & ~15);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* u_temp = y_temp + kFilterBufferSize;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* v_temp = u_temp + kFilterBufferSize;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move to the top-left pixel of output.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rgb_buf += dest_rect_top * rgb_pitch;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rgb_buf += dest_rect_left * 4;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each destination row perform interpolation and color space
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // conversion to produce the output.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int row = dest_rect_top; row < dest_rect_bottom; ++row) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Round the fixed-point y position to get the current row.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_row = source_top >> kFractionBits;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int source_uv_row = source_row / 2;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(source_row < source_height);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locate the first row for each plane for interpolation.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* y0_ptr = y_buf + y_pitch * source_row + source_y_left;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* u0_ptr = u_buf + uv_pitch * source_uv_row + source_uv_left;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* v0_ptr = v_buf + uv_pitch * source_uv_row + source_uv_left;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* y1_ptr = NULL;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* u1_ptr = NULL;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8* v1_ptr = NULL;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locate the second row for interpolation, being careful not to overrun.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (source_row + 1 >= source_height) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y1_ptr = y0_ptr;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      y1_ptr = y0_ptr + y_pitch;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (source_uv_row + 1 >= (source_height + 1) / 2) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u1_ptr = u0_ptr;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v1_ptr = v0_ptr;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u1_ptr = u0_ptr + uv_pitch;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v1_ptr = v0_ptr + uv_pitch;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!kAvoidUsingOptimizedFilter) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Vertical scaler uses 16.8 fixed point.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int fraction = (source_top & kFractionMask) >> 8;
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_filter_yuv_rows_proc_(
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          y_temp + source_y_left, y0_ptr, y1_ptr, source_y_width, fraction);
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_filter_yuv_rows_proc_(
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          u_temp + source_uv_left, u0_ptr, u1_ptr, source_uv_width, fraction);
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      g_filter_yuv_rows_proc_(
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Perform horizontal interpolation and color space conversion.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(hclam): Use the MMX version after more testing.
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LinearScaleYUVToRGB32RowWithRange_C(y_temp,
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          u_temp,
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          v_temp,
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          rgb_buf,
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          dest_rect_width,
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          source_left,
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          x_step,
539010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          kCoefficientsRgbY);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the frame is too large then we linear scale a single row.
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LinearScaleYUVToRGB32RowWithRange_C(y0_ptr,
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          u0_ptr,
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          v0_ptr,
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          rgb_buf,
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          dest_rect_width,
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          source_left,
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          x_step,
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          kCoefficientsRgbY);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Advance vertically in the source and destination image.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_top += y_step;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rgb_buf += rgb_pitch;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_empty_register_state_proc_();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertRGB32ToYUV(const uint8* rgbframe,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* yplane,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* uplane,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* vplane,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int width,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int height,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int rgbstride,
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int ystride,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int uvstride) {
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_rgb32_to_yuv_proc_(rgbframe,
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               yplane,
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uplane,
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               vplane,
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               width,
574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               height,
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbstride,
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               ystride,
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uvstride);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertRGB24ToYUV(const uint8* rgbframe,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* yplane,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* uplane,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* vplane,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int width,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int height,
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int rgbstride,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int ystride,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int uvstride) {
589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_rgb24_to_yuv_proc_(rgbframe,
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               yplane,
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uplane,
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               vplane,
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               width,
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               height,
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbstride,
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               ystride,
597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uvstride);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertYUY2ToYUV(const uint8* src,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* yplane,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* uplane,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* vplane,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int width,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int height) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < height / 2; ++i) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < (width / 2); ++j) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane[0] = src[0];
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *uplane = src[1];
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane[1] = src[2];
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *vplane = src[3];
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src += 4;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane += 2;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uplane++;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vplane++;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < (width / 2); ++j) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane[0] = src[0];
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane[1] = src[2];
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src += 4;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yplane += 2;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertNV21ToYUV(const uint8* src,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* yplane,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* uplane,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      uint8* vplane,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int width,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int height) {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_plane_size = width * height;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(yplane, src, y_plane_size);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  src += y_plane_size;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int u_plane_size = y_plane_size >> 2;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < u_plane_size; ++i) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *vplane++ = *src++;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *uplane++ = *src++;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertYUVToRGB32(const uint8* yplane,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const uint8* uplane,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const uint8* vplane,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       uint8* rgbframe,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int width,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int height,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int ystride,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int uvstride,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int rgbstride,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       YUVType yuv_type) {
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_yuv_to_rgb32_proc_(yplane,
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uplane,
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               vplane,
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbframe,
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               width,
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               height,
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               ystride,
660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uvstride,
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbstride,
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               yuv_type);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ConvertYUVAToARGB(const uint8* yplane,
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       const uint8* uplane,
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       const uint8* vplane,
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       const uint8* aplane,
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       uint8* rgbframe,
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int width,
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int height,
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int ystride,
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int uvstride,
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int astride,
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int rgbstride,
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       YUVType yuv_type) {
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_convert_yuva_to_argb_proc_(yplane,
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uplane,
679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               vplane,
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               aplane,
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbframe,
682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               width,
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               height,
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               ystride,
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               uvstride,
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               astride,
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               rgbstride,
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               yuv_type);
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
692