OLD | NEW |
---|---|
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 ybuf += 4; | 127 ybuf += 4; |
128 } while (ybuf < end); | 128 } while (ybuf < end); |
129 } | 129 } |
130 } | 130 } |
131 | 131 |
132 #endif // USE_SSE | 132 #endif // USE_SSE |
133 #else // no MMX or SSE | 133 #else // no MMX or SSE |
134 // C version blends 4 pixels at a time. | 134 // C version blends 4 pixels at a time. |
135 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, | 135 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, |
136 int width, int scaled_y_fraction) { | 136 int width, int scaled_y_fraction) { |
137 int y0_fraction = 65536 - scaled_y_fraction; | 137 int y0_fraction = kFractionMax - scaled_y_fraction; |
138 int y1_fraction = scaled_y_fraction; | 138 int y1_fraction = scaled_y_fraction; |
139 uint8* end = ybuf + width; | 139 uint8* end = ybuf + width; |
140 if (ybuf < end) { | 140 if (ybuf < end) { |
141 do { | 141 do { |
142 ybuf[0] = (y0_ptr[0] * (y0_fraction) + y1_ptr[0] * (y1_fraction)) >> 16; | 142 ybuf[0] = (y0_ptr[0] * (y0_fraction) + y1_ptr[0] * (y1_fraction)) >> 16; |
143 ybuf[1] = (y0_ptr[1] * (y0_fraction) + y1_ptr[1] * (y1_fraction)) >> 16; | 143 ybuf[1] = (y0_ptr[1] * (y0_fraction) + y1_ptr[1] * (y1_fraction)) >> 16; |
144 ybuf[2] = (y0_ptr[2] * (y0_fraction) + y1_ptr[2] * (y1_fraction)) >> 16; | 144 ybuf[2] = (y0_ptr[2] * (y0_fraction) + y1_ptr[2] * (y1_fraction)) >> 16; |
145 ybuf[3] = (y0_ptr[3] * (y0_fraction) + y1_ptr[3] * (y1_fraction)) >> 16; | 145 ybuf[3] = (y0_ptr[3] * (y0_fraction) + y1_ptr[3] * (y1_fraction)) >> 16; |
146 y0_ptr += 4; | 146 y0_ptr += 4; |
147 y1_ptr += 4; | 147 y1_ptr += 4; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 } | 232 } |
233 | 233 |
234 // Need padding because FilterRows() may write up to 15 extra pixels | 234 // Need padding because FilterRows() may write up to 15 extra pixels |
235 // after the end for SSE2 version. | 235 // after the end for SSE2 version. |
236 uint8 ybuf[kFilterBufferSize + 16]; | 236 uint8 ybuf[kFilterBufferSize + 16]; |
237 uint8 ubuf[kFilterBufferSize / 2 + 16]; | 237 uint8 ubuf[kFilterBufferSize / 2 + 16]; |
238 uint8 vbuf[kFilterBufferSize / 2 + 16]; | 238 uint8 vbuf[kFilterBufferSize / 2 + 16]; |
239 int yscale_fixed = (height << kFractionBits) / scaled_height; | 239 int yscale_fixed = (height << kFractionBits) / scaled_height; |
240 for (int y = 0; y < scaled_height; ++y) { | 240 for (int y = 0; y < scaled_height; ++y) { |
241 uint8* dest_pixel = rgb_buf + y * rgb_pitch; | 241 uint8* dest_pixel = rgb_buf + y * rgb_pitch; |
242 int scaled_y = (y * yscale_fixed); | 242 int source_y_subpixel = (y * yscale_fixed); |
243 int source_y = source_y_subpixel >> kFractionBits; | |
fbarchard
2010/04/14 06:21:42
source... ya thats a better name
| |
243 | 244 |
244 const uint8* y0_ptr = y_buf + (scaled_y >> kFractionBits) * y_pitch; | 245 const uint8* y0_ptr = y_buf + source_y * y_pitch; |
245 const uint8* y1_ptr = y0_ptr + y_pitch; | 246 const uint8* y1_ptr = y0_ptr + y_pitch; |
246 | 247 |
247 const uint8* u0_ptr = u_buf + | 248 const uint8* u0_ptr = u_buf + (source_y >> y_shift) * uv_pitch; |
248 ((scaled_y >> kFractionBits) >> y_shift) * uv_pitch; | |
249 const uint8* u1_ptr = u0_ptr + uv_pitch; | 249 const uint8* u1_ptr = u0_ptr + uv_pitch; |
250 const uint8* v0_ptr = v_buf + | 250 const uint8* v0_ptr = v_buf + (source_y >> y_shift) * uv_pitch; |
251 ((scaled_y >> kFractionBits) >> y_shift) * uv_pitch; | |
252 const uint8* v1_ptr = v0_ptr + uv_pitch; | 251 const uint8* v1_ptr = v0_ptr + uv_pitch; |
253 | 252 |
254 int scaled_y_fraction = scaled_y & (kFractionMax - 1); | 253 int scaled_y_fraction = source_y_subpixel & (kFractionMax - 1); |
255 int scaled_uv_fraction = (scaled_y >> y_shift) & (kFractionMax - 1); | 254 int scaled_uv_fraction = (source_y_subpixel >> y_shift) & (kFractionMax - 1) ; |
256 | 255 |
257 const uint8* y_ptr = y0_ptr; | 256 const uint8* y_ptr = y0_ptr; |
258 const uint8* u_ptr = u0_ptr; | 257 const uint8* u_ptr = u0_ptr; |
259 const uint8* v_ptr = v0_ptr; | 258 const uint8* v_ptr = v0_ptr; |
260 // Apply vertical filtering if necessary. | 259 // Apply vertical filtering if necessary. |
261 // TODO(fbarchard): Remove memcpy when not necessary. | 260 // TODO(fbarchard): Remove memcpy when not necessary. |
262 if (filter == media::FILTER_BILINEAR) { | 261 if (filter == media::FILTER_BILINEAR) { |
263 if (yscale_fixed != kFractionMax && | 262 if (yscale_fixed != kFractionMax && |
264 scaled_y_fraction && ((y + 1) < scaled_height)) { | 263 scaled_y_fraction && ((source_y + 1) < height)) { |
265 FilterRows(ybuf, y0_ptr, y1_ptr, width, scaled_y_fraction); | 264 FilterRows(ybuf, y0_ptr, y1_ptr, width, scaled_y_fraction); |
266 } else { | 265 } else { |
267 memcpy(ybuf, y0_ptr, width); | 266 memcpy(ybuf, y0_ptr, width); |
268 } | 267 } |
269 y_ptr = ybuf; | 268 y_ptr = ybuf; |
270 ybuf[width] = ybuf[width-1]; | 269 ybuf[width] = ybuf[width-1]; |
271 int uv_width = (width + 1) / 2; | 270 int uv_width = (width + 1) / 2; |
272 if (yscale_fixed != kFractionMax && | 271 if (yscale_fixed != kFractionMax && |
273 scaled_uv_fraction && | 272 scaled_uv_fraction && |
274 (((y >> y_shift) + 1) < (scaled_height >> y_shift))) { | 273 (((source_y >> y_shift) + 1) < (height >> y_shift))) { |
fbarchard
2010/04/14 06:21:42
is this the error you referred to?
| |
275 FilterRows(ubuf, u0_ptr, u1_ptr, uv_width, scaled_uv_fraction); | 274 FilterRows(ubuf, u0_ptr, u1_ptr, uv_width, scaled_uv_fraction); |
276 FilterRows(vbuf, v0_ptr, v1_ptr, uv_width, scaled_uv_fraction); | 275 FilterRows(vbuf, v0_ptr, v1_ptr, uv_width, scaled_uv_fraction); |
277 } else { | 276 } else { |
278 memcpy(ubuf, u0_ptr, uv_width); | 277 memcpy(ubuf, u0_ptr, uv_width); |
279 memcpy(vbuf, v0_ptr, uv_width); | 278 memcpy(vbuf, v0_ptr, uv_width); |
280 } | 279 } |
281 u_ptr = ubuf; | 280 u_ptr = ubuf; |
282 v_ptr = vbuf; | 281 v_ptr = vbuf; |
283 ubuf[(width + 1) / 2] = ybuf[(width + 1) / 2 -1]; | 282 ubuf[uv_width] = ubuf[uv_width - 1]; |
fbarchard
2010/04/14 06:21:42
good catch!
| |
284 vbuf[(width + 1) / 2] = vbuf[(width + 1) / 2 -1]; | 283 vbuf[uv_width] = vbuf[uv_width - 1]; |
285 } | 284 } |
286 if (scaled_dx == kFractionMax) { // Not scaled | 285 if (scaled_dx == kFractionMax) { // Not scaled |
287 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | 286 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
288 dest_pixel, scaled_width); | 287 dest_pixel, scaled_width); |
289 } else { | 288 } else { |
290 if (filter == FILTER_BILINEAR) | 289 if (filter == FILTER_BILINEAR) |
291 LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | 290 LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
292 dest_pixel, scaled_width, scaled_dx); | 291 dest_pixel, scaled_width, scaled_dx); |
293 else | 292 else |
294 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | 293 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
295 dest_pixel, scaled_width, scaled_dx); | 294 dest_pixel, scaled_width, scaled_dx); |
296 } | 295 } |
297 } | 296 } |
298 | 297 |
299 // MMX used for FastConvertYUVToRGB32Row requires emms instruction. | 298 // MMX used for FastConvertYUVToRGB32Row requires emms instruction. |
300 EMMS(); | 299 EMMS(); |
301 } | 300 } |
302 | 301 |
303 } // namespace media | 302 } // namespace media |
OLD | NEW |