Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: media/base/yuv_convert.cc

Issue 1638008: yuv use a shared table for windows, posix and C... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This webpage shows layout of YV12 and other YUV formats 5 // This webpage shows layout of YV12 and other YUV formats
6 // http://www.fourcc.org/yuv.php 6 // http://www.fourcc.org/yuv.php
7 // The actual conversion is best described here 7 // The actual conversion is best described here
8 // http://en.wikipedia.org/wiki/YUV 8 // http://en.wikipedia.org/wiki/YUV
9 // An article on optimizing YUV conversion using tables instead of multiplies 9 // An article on optimizing YUV conversion using tables instead of multiplies
10 // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf 10 // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
(...skipping 10 matching lines...) Expand all
21 #include "media/base/yuv_row.h" 21 #include "media/base/yuv_row.h"
22 22
23 #if USE_MMX 23 #if USE_MMX
24 #if defined(_MSC_VER) 24 #if defined(_MSC_VER)
25 #include <intrin.h> 25 #include <intrin.h>
26 #else 26 #else
27 #include <mmintrin.h> 27 #include <mmintrin.h>
28 #endif 28 #endif
29 #endif 29 #endif
30 30
31 #if USE_SSE 31 #if USE_SSE2
32 #include <emmintrin.h> 32 #include <emmintrin.h>
33 #endif 33 #endif
34 34
35 namespace media { 35 namespace media {
36 36
37 // 16.16 fixed point arithmetic. 37 // 16.16 fixed point arithmetic
38 const int kFractionBits = 16; 38 const int kFractionBits = 16;
39 const int kFractionMax = 1 << kFractionBits; 39 const int kFractionMax = 1 << kFractionBits;
40 const int kFractionMask = ((1 << kFractionBits) - 1);
40 41
41 // Convert a frame of YUV to 32 bit ARGB. 42 // Convert a frame of YUV to 32 bit ARGB.
42 void ConvertYUVToRGB32(const uint8* y_buf, 43 void ConvertYUVToRGB32(const uint8* y_buf,
43 const uint8* u_buf, 44 const uint8* u_buf,
44 const uint8* v_buf, 45 const uint8* v_buf,
45 uint8* rgb_buf, 46 uint8* rgb_buf,
46 int width, 47 int source_width,
47 int height, 48 int source_height,
48 int y_pitch, 49 int y_pitch,
49 int uv_pitch, 50 int uv_pitch,
50 int rgb_pitch, 51 int rgb_pitch,
51 YUVType yuv_type) { 52 YUVType yuv_type) {
52 unsigned int y_shift = yuv_type; 53 unsigned int y_shift = yuv_type;
53 for (int y = 0; y < height; ++y) { 54 for (int y = 0; y < source_height; ++y) {
54 uint8* rgb_row = rgb_buf + y * rgb_pitch; 55 uint8* rgb_row = rgb_buf + y * rgb_pitch;
55 const uint8* y_ptr = y_buf + y * y_pitch; 56 const uint8* y_ptr = y_buf + y * y_pitch;
56 const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch; 57 const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch;
57 const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch; 58 const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch;
58 59
59 FastConvertYUVToRGB32Row(y_ptr, 60 FastConvertYUVToRGB32Row(y_ptr,
60 u_ptr, 61 u_ptr,
61 v_ptr, 62 v_ptr,
62 rgb_row, 63 rgb_row,
63 width); 64 source_width);
64 } 65 }
65 66
66 // MMX used for FastConvertYUVToRGB32Row requires emms instruction. 67 // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
67 EMMS(); 68 EMMS();
68 } 69 }
69 70
70 #if USE_MMX 71 #if USE_SSE2
71 #if USE_SSE
72 // FilterRows combines two rows of the image using linear interpolation. 72 // FilterRows combines two rows of the image using linear interpolation.
73 // SSE2 version blends 8 pixels at a time. 73 // SSE2 version blends 8 pixels at a time.
74 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, 74 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
75 int width, int scaled_y_fraction) { 75 int source_width, int source_y_fraction) {
76 __m128i zero = _mm_setzero_si128(); 76 __m128i zero = _mm_setzero_si128();
77 __m128i y1_fraction = _mm_set1_epi16( 77 __m128i y1_fraction = _mm_set1_epi16(
78 static_cast<uint16>(scaled_y_fraction >> 8)); 78 static_cast<uint16>(source_y_fraction >> 8));
79 __m128i y0_fraction = _mm_set1_epi16( 79 __m128i y0_fraction = _mm_set1_epi16(
80 static_cast<uint16>((scaled_y_fraction >> 8) ^ 255)); 80 static_cast<uint16>(256 - (source_y_fraction >> 8)));
81 81
82 uint8* end = ybuf + width; 82 uint8* end = ybuf + source_width;
83 if (ybuf < end) { 83 if (ybuf < end) {
84 do { 84 do {
85 __m128i y0 = _mm_loadl_epi64(reinterpret_cast<__m128i const*>(y0_ptr)); 85 __m128i y0 = _mm_loadl_epi64(reinterpret_cast<__m128i const*>(y0_ptr));
86 __m128i y1 = _mm_loadl_epi64(reinterpret_cast<__m128i const*>(y1_ptr)); 86 __m128i y1 = _mm_loadl_epi64(reinterpret_cast<__m128i const*>(y1_ptr));
87 y0 = _mm_unpacklo_epi8(y0, zero); 87 y0 = _mm_unpacklo_epi8(y0, zero);
88 y1 = _mm_unpacklo_epi8(y1, zero); 88 y1 = _mm_unpacklo_epi8(y1, zero);
89 y0 = _mm_mullo_epi16(y0, y0_fraction); 89 y0 = _mm_mullo_epi16(y0, y0_fraction);
90 y1 = _mm_mullo_epi16(y1, y1_fraction); 90 y1 = _mm_mullo_epi16(y1, y1_fraction);
91 y0 = _mm_add_epi16(y0, y1); // 8.8 fixed point result 91 y0 = _mm_add_epi16(y0, y1); // 8.8 fixed point result
92 y0 = _mm_srli_epi16(y0, 8); 92 y0 = _mm_srli_epi16(y0, 8);
93 y0 = _mm_packus_epi16(y0, y0); 93 y0 = _mm_packus_epi16(y0, y0);
94 _mm_storel_epi64(reinterpret_cast<__m128i *>(ybuf), y0); 94 _mm_storel_epi64(reinterpret_cast<__m128i *>(ybuf), y0);
95 y0_ptr += 8; 95 y0_ptr += 8;
96 y1_ptr += 8; 96 y1_ptr += 8;
97 ybuf += 8; 97 ybuf += 8;
98 } while (ybuf < end); 98 } while (ybuf < end);
99 } 99 }
100 } 100 }
101 101
102 #else 102 #elif USE_MMX
103 // MMX version blends 4 pixels at a time. 103 // MMX version blends 4 pixels at a time.
104 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, 104 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
105 int width, int scaled_y_fraction) { 105 int source_width, int source_y_fraction) {
106 __m64 zero = _mm_setzero_si64(); 106 __m64 zero = _mm_setzero_si64();
107 __m64 y1_fraction = _mm_set1_pi16( 107 __m64 y1_fraction = _mm_set1_pi16(
108 static_cast<int16>(scaled_y_fraction >> 8)); 108 static_cast<int16>(source_y_fraction >> 8));
109 __m64 y0_fraction = _mm_set1_pi16( 109 __m64 y0_fraction = _mm_set1_pi16(
110 static_cast<int16>((scaled_y_fraction >> 8) ^ 255)); 110 static_cast<int16>(256 - (source_y_fraction >> 8)));
111 111
112 uint8* end = ybuf + width; 112 uint8* end = ybuf + source_width;
113 if (ybuf < end) { 113 if (ybuf < end) {
114 do { 114 do {
115 __m64 y0 = _mm_cvtsi32_si64(*reinterpret_cast<const int *>(y0_ptr)); 115 __m64 y0 = _mm_cvtsi32_si64(*reinterpret_cast<const int *>(y0_ptr));
116 __m64 y1 = _mm_cvtsi32_si64(*reinterpret_cast<const int *>(y1_ptr)); 116 __m64 y1 = _mm_cvtsi32_si64(*reinterpret_cast<const int *>(y1_ptr));
117 y0 = _mm_unpacklo_pi8(y0, zero); 117 y0 = _mm_unpacklo_pi8(y0, zero);
118 y1 = _mm_unpacklo_pi8(y1, zero); 118 y1 = _mm_unpacklo_pi8(y1, zero);
119 y0 = _mm_mullo_pi16(y0, y0_fraction); 119 y0 = _mm_mullo_pi16(y0, y0_fraction);
120 y1 = _mm_mullo_pi16(y1, y1_fraction); 120 y1 = _mm_mullo_pi16(y1, y1_fraction);
121 y0 = _mm_add_pi16(y0, y1); // 8.8 fixed point result 121 y0 = _mm_add_pi16(y0, y1); // 8.8 fixed point result
122 y0 = _mm_srli_pi16(y0, 8); 122 y0 = _mm_srli_pi16(y0, 8);
123 y0 = _mm_packs_pu16(y0, y0); 123 y0 = _mm_packs_pu16(y0, y0);
124 *reinterpret_cast<int *>(ybuf) = _mm_cvtsi64_si32(y0); 124 *reinterpret_cast<int *>(ybuf) = _mm_cvtsi64_si32(y0);
125 y0_ptr += 4; 125 y0_ptr += 4;
126 y1_ptr += 4; 126 y1_ptr += 4;
127 ybuf += 4; 127 ybuf += 4;
128 } while (ybuf < end); 128 } while (ybuf < end);
129 } 129 }
130 } 130 }
131 131 #else // no MMX or SSE2
132 #endif // USE_SSE
133 #else // no MMX or SSE
134 // C version blends 4 pixels at a time. 132 // C version blends 4 pixels at a time.
135 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, 133 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr,
136 int width, int scaled_y_fraction) { 134 int source_width, int source_y_fraction) {
137 int y0_fraction = kFractionMax - scaled_y_fraction; 135 int y1_fraction = source_y_fraction >> 8;
138 int y1_fraction = scaled_y_fraction; 136 int y0_fraction = 256 - (source_y_fraction >> 8);
139 uint8* end = ybuf + width; 137
138 int y0_fraction = kFractionMax - source_y_fraction;
139 int y1_fraction = source_y_fraction;
140 uint8* end = ybuf + source_width;
140 if (ybuf < end) { 141 if (ybuf < end) {
141 do { 142 do {
142 ybuf[0] = (y0_ptr[0] * (y0_fraction) + y1_ptr[0] * (y1_fraction)) >> 16; 143 ybuf[0] = (y0_ptr[0] * (y0_fraction) + y1_ptr[0] * (y1_fraction)) >> 8;
143 ybuf[1] = (y0_ptr[1] * (y0_fraction) + y1_ptr[1] * (y1_fraction)) >> 16; 144 ybuf[1] = (y0_ptr[1] * (y0_fraction) + y1_ptr[1] * (y1_fraction)) >> 8;
144 ybuf[2] = (y0_ptr[2] * (y0_fraction) + y1_ptr[2] * (y1_fraction)) >> 16; 145 ybuf[2] = (y0_ptr[2] * (y0_fraction) + y1_ptr[2] * (y1_fraction)) >> 8;
145 ybuf[3] = (y0_ptr[3] * (y0_fraction) + y1_ptr[3] * (y1_fraction)) >> 16; 146 ybuf[3] = (y0_ptr[3] * (y0_fraction) + y1_ptr[3] * (y1_fraction)) >> 8;
146 y0_ptr += 4; 147 y0_ptr += 4;
147 y1_ptr += 4; 148 y1_ptr += 4;
148 ybuf += 4; 149 ybuf += 4;
149 } while (ybuf < end); 150 } while (ybuf < end);
150 } 151 }
151 } 152 }
152 #endif // USE_MMX 153 #endif
153 154
154 // Scale a frame of YUV to 32 bit ARGB. 155 // Scale a frame of YUV to 32 bit ARGB.
155 void ScaleYUVToRGB32(const uint8* y_buf, 156 void ScaleYUVToRGB32(const uint8* y_buf,
156 const uint8* u_buf, 157 const uint8* u_buf,
157 const uint8* v_buf, 158 const uint8* v_buf,
158 uint8* rgb_buf, 159 uint8* rgb_buf,
160 int source_width,
161 int source_height,
159 int width, 162 int width,
160 int height, 163 int height,
161 int scaled_width,
162 int scaled_height,
163 int y_pitch, 164 int y_pitch,
164 int uv_pitch, 165 int uv_pitch,
165 int rgb_pitch, 166 int rgb_pitch,
166 YUVType yuv_type, 167 YUVType yuv_type,
167 Rotate view_rotate, 168 Rotate view_rotate,
168 ScaleFilter filter) { 169 ScaleFilter filter) {
169 const int kFilterBufferSize = 8192; 170 const int kFilterBufferSize = 8192;
170 // Disable filtering if the screen is too big (to avoid buffer overflows). 171 // Disable filtering if the screen is too big (to avoid buffer overflows).
171 // This should never happen to regular users: they don't have monitors 172 // This should never happen to regular users: they don't have monitors
172 // wider than 8192 pixels. 173 // wider than 8192 pixels.
173 if (width > kFilterBufferSize) 174 // TODO(fbarchard): Allow rotated videos to filter.
175 if (source_width > kFilterBufferSize || view_rotate)
174 filter = FILTER_NONE; 176 filter = FILTER_NONE;
175 177
176 unsigned int y_shift = yuv_type; 178 unsigned int y_shift = yuv_type;
177 // Diagram showing origin and direction of source sampling. 179 // Diagram showing origin and direction of source sampling.
178 // ->0 4<- 180 // ->0 4<-
179 // 7 3 181 // 7 3
180 // 182 //
181 // 6 5 183 // 6 5
182 // ->1 2<- 184 // ->1 2<-
183 // Rotations that start at right side of image. 185 // Rotations that start at right side of image.
184 if ((view_rotate == ROTATE_180) || 186 if ((view_rotate == ROTATE_180) ||
185 (view_rotate == ROTATE_270) || 187 (view_rotate == ROTATE_270) ||
186 (view_rotate == MIRROR_ROTATE_0) || 188 (view_rotate == MIRROR_ROTATE_0) ||
187 (view_rotate == MIRROR_ROTATE_90)) { 189 (view_rotate == MIRROR_ROTATE_90)) {
188 y_buf += width - 1; 190 y_buf += source_width - 1;
189 u_buf += width / 2 - 1; 191 u_buf += source_width / 2 - 1;
190 v_buf += width / 2 - 1; 192 v_buf += source_width / 2 - 1;
191 width = -width; 193 source_width = -source_width;
192 } 194 }
193 // Rotations that start at bottom of image. 195 // Rotations that start at bottom of image.
194 if ((view_rotate == ROTATE_90) || 196 if ((view_rotate == ROTATE_90) ||
195 (view_rotate == ROTATE_180) || 197 (view_rotate == ROTATE_180) ||
196 (view_rotate == MIRROR_ROTATE_90) || 198 (view_rotate == MIRROR_ROTATE_90) ||
197 (view_rotate == MIRROR_ROTATE_180)) { 199 (view_rotate == MIRROR_ROTATE_180)) {
198 y_buf += (height - 1) * y_pitch; 200 y_buf += (source_height - 1) * y_pitch;
199 u_buf += ((height >> y_shift) - 1) * uv_pitch; 201 u_buf += ((source_height >> y_shift) - 1) * uv_pitch;
200 v_buf += ((height >> y_shift) - 1) * uv_pitch; 202 v_buf += ((source_height >> y_shift) - 1) * uv_pitch;
201 height = -height; 203 source_height = -source_height;
202 } 204 }
203 205
204 // Handle zero sized destination. 206 // Handle zero sized destination.
205 if (scaled_width == 0 || scaled_height == 0) 207 if (width == 0 || height == 0)
206 return; 208 return;
207 int scaled_dx = width * kFractionMax / scaled_width; 209 int source_dx = source_width * kFractionMax / width;
208 int scaled_dy = height * kFractionMax / scaled_height; 210 int source_dy = source_height * kFractionMax / height;
209 int scaled_dx_uv = scaled_dx; 211 int source_dx_uv = source_dx;
210 212
211 if ((view_rotate == ROTATE_90) || 213 if ((view_rotate == ROTATE_90) ||
212 (view_rotate == ROTATE_270)) { 214 (view_rotate == ROTATE_270)) {
213 int tmp = scaled_height; 215 int tmp = height;
214 scaled_height = scaled_width;
215 scaled_width = tmp;
216 tmp = height;
217 height = width; 216 height = width;
218 width = tmp; 217 width = tmp;
219 int original_dx = scaled_dx; 218 tmp = source_height;
220 int original_dy = scaled_dy; 219 source_height = source_width;
221 scaled_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits; 220 source_width = tmp;
222 scaled_dx_uv = ((original_dy >> kFractionBits) * uv_pitch) << kFractionBits; 221 int original_dx = source_dx;
223 scaled_dy = original_dx; 222 int original_dy = source_dy;
223 source_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits;
224 source_dx_uv = ((original_dy >> kFractionBits) * uv_pitch) << kFractionBits;
225 source_dy = original_dx;
224 if (view_rotate == ROTATE_90) { 226 if (view_rotate == ROTATE_90) {
225 y_pitch = -1; 227 y_pitch = -1;
226 uv_pitch = -1; 228 uv_pitch = -1;
227 height = -height; 229 source_height = -source_height;
228 } else { 230 } else {
229 y_pitch = 1; 231 y_pitch = 1;
230 uv_pitch = 1; 232 uv_pitch = 1;
231 } 233 }
232 } 234 }
233 235
234 // Need padding because FilterRows() may write up to 15 extra pixels 236 // Need padding because FilterRows() may write up to 15 extra pixels
235 // after the end for SSE2 version. 237 // after the end for SSE2 version.
236 uint8 ybuf[kFilterBufferSize + 16]; 238 uint8 ybuf[kFilterBufferSize + 16];
237 uint8 ubuf[kFilterBufferSize / 2 + 16]; 239 uint8 ubuf[kFilterBufferSize / 2 + 16];
238 uint8 vbuf[kFilterBufferSize / 2 + 16]; 240 uint8 vbuf[kFilterBufferSize / 2 + 16];
239 int yscale_fixed = (height << kFractionBits) / scaled_height; 241 // TODO(fbarchard): Fixed point math is off by 1 on negatives.
240 for (int y = 0; y < scaled_height; ++y) { 242 int yscale_fixed = (source_height << kFractionBits) / height;
243 for (int y = 0; y < height; ++y) {
241 uint8* dest_pixel = rgb_buf + y * rgb_pitch; 244 uint8* dest_pixel = rgb_buf + y * rgb_pitch;
242 int source_y_subpixel = (y * yscale_fixed); 245 int source_y_subpixel = (y * yscale_fixed);
243 int source_y = source_y_subpixel >> kFractionBits; 246 int source_y = source_y_subpixel >> kFractionBits;
244 247
245 const uint8* y0_ptr = y_buf + source_y * y_pitch; 248 const uint8* y0_ptr = y_buf + source_y * y_pitch;
246 const uint8* y1_ptr = y0_ptr + y_pitch; 249 const uint8* y1_ptr = y0_ptr + y_pitch;
247 250
248 const uint8* u0_ptr = u_buf + (source_y >> y_shift) * uv_pitch; 251 const uint8* u0_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
249 const uint8* u1_ptr = u0_ptr + uv_pitch; 252 const uint8* u1_ptr = u0_ptr + uv_pitch;
250 const uint8* v0_ptr = v_buf + (source_y >> y_shift) * uv_pitch; 253 const uint8* v0_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
251 const uint8* v1_ptr = v0_ptr + uv_pitch; 254 const uint8* v1_ptr = v0_ptr + uv_pitch;
252 255
253 int scaled_y_fraction = source_y_subpixel & (kFractionMax - 1); 256 int source_y_fraction = source_y_subpixel & kFractionMask;
254 int scaled_uv_fraction = (source_y_subpixel >> y_shift) & (kFractionMax - 1) ; 257 int source_uv_fraction = (source_y_subpixel >> y_shift) & kFractionMask;
255 258
256 const uint8* y_ptr = y0_ptr; 259 const uint8* y_ptr = y0_ptr;
257 const uint8* u_ptr = u0_ptr; 260 const uint8* u_ptr = u0_ptr;
258 const uint8* v_ptr = v0_ptr; 261 const uint8* v_ptr = v0_ptr;
259 // Apply vertical filtering if necessary. 262 // Apply vertical filtering if necessary.
260 // TODO(fbarchard): Remove memcpy when not necessary. 263 // TODO(fbarchard): Remove memcpy when not necessary.
261 if (filter == media::FILTER_BILINEAR) { 264 if (filter == media::FILTER_BILINEAR) {
262 if (yscale_fixed != kFractionMax && 265 if (yscale_fixed != kFractionMax &&
263 scaled_y_fraction && ((source_y + 1) < height)) { 266 source_y_fraction && ((source_y + 1) < source_height)) {
264 FilterRows(ybuf, y0_ptr, y1_ptr, width, scaled_y_fraction); 267 FilterRows(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction);
265 } else { 268 } else {
266 memcpy(ybuf, y0_ptr, width); 269 memcpy(ybuf, y0_ptr, source_width);
267 } 270 }
268 y_ptr = ybuf; 271 y_ptr = ybuf;
269 ybuf[width] = ybuf[width-1]; 272 ybuf[source_width] = ybuf[source_width-1];
270 int uv_width = (width + 1) / 2; 273 int uv_source_width = (source_width + 1) / 2;
271 if (yscale_fixed != kFractionMax && 274 if (yscale_fixed != kFractionMax &&
272 scaled_uv_fraction && 275 source_uv_fraction &&
273 (((source_y >> y_shift) + 1) < (height >> y_shift))) { 276 (((source_y >> y_shift) + 1) < (source_height >> y_shift))) {
274 FilterRows(ubuf, u0_ptr, u1_ptr, uv_width, scaled_uv_fraction); 277 FilterRows(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction);
275 FilterRows(vbuf, v0_ptr, v1_ptr, uv_width, scaled_uv_fraction); 278 FilterRows(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction);
276 } else { 279 } else {
277 memcpy(ubuf, u0_ptr, uv_width); 280 memcpy(ubuf, u0_ptr, uv_source_width);
278 memcpy(vbuf, v0_ptr, uv_width); 281 memcpy(vbuf, v0_ptr, uv_source_width);
279 } 282 }
280 u_ptr = ubuf; 283 u_ptr = ubuf;
281 v_ptr = vbuf; 284 v_ptr = vbuf;
282 ubuf[uv_width] = ubuf[uv_width - 1]; 285 ubuf[uv_source_width] = ubuf[uv_source_width - 1];
283 vbuf[uv_width] = vbuf[uv_width - 1]; 286 vbuf[uv_source_width] = vbuf[uv_source_width - 1];
284 } 287 }
285 if (scaled_dx == kFractionMax) { // Not scaled 288 if (source_dx == kFractionMax) { // Not scaled
286 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, 289 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
287 dest_pixel, scaled_width); 290 dest_pixel, width);
288 } else { 291 } else {
289 if (filter == FILTER_BILINEAR) 292 if (filter == FILTER_BILINEAR)
290 LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, 293 LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
291 dest_pixel, scaled_width, scaled_dx); 294 dest_pixel, width, source_dx);
292 else 295 else {
296 // Specialized scalers and rotation.
297 #if USE_MMX && defined(_MSC_VER)
298 if (width == (source_width * 2)) {
299 DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
300 dest_pixel, width);
301 } else if ((source_dx & kFractionMask) == 0) {
302 // Scaling by integer scale factor. ie half.
303 ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
304 dest_pixel, width,
305 source_dx >> kFractionBits);
306 } else if (source_dx_uv == source_dx) { // Not rotated.
307 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
308 dest_pixel, width, source_dx);
309 } else {
310 RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
311 dest_pixel, width,
312 source_dx >> kFractionBits,
313 source_dx_uv >> kFractionBits);
314 }
315 #else
293 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, 316 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
294 dest_pixel, scaled_width, scaled_dx); 317 dest_pixel, width, source_dx);
318 #endif
319 }
295 } 320 }
296 } 321 }
297 322 // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
298 // MMX used for FastConvertYUVToRGB32Row requires emms instruction.
299 EMMS(); 323 EMMS();
300 } 324 }
301 325
302 } // namespace media 326 } // namespace media
OLDNEW
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698