OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 22 matching lines...) Expand all Loading... |
33 #else | 33 #else |
34 #include <mmintrin.h> | 34 #include <mmintrin.h> |
35 #endif | 35 #endif |
36 #endif | 36 #endif |
37 | 37 |
38 // Assembly functions are declared without namespace. | 38 // Assembly functions are declared without namespace. |
39 extern "C" { void EmptyRegisterState_MMX(); } // extern "C" | 39 extern "C" { void EmptyRegisterState_MMX(); } // extern "C" |
40 | 40 |
41 namespace media { | 41 namespace media { |
42 | 42 |
43 typedef void (*FilterYUVRowsProc)(uint8*, const uint8*, const uint8*, int, int); | 43 typedef void (*FilterYUVRowsProc)(uint8*, |
| 44 const uint8*, |
| 45 const uint8*, |
| 46 int, |
| 47 uint8); |
44 | 48 |
45 typedef void (*ConvertRGBToYUVProc)(const uint8*, | 49 typedef void (*ConvertRGBToYUVProc)(const uint8*, |
46 uint8*, | 50 uint8*, |
47 uint8*, | 51 uint8*, |
48 uint8*, | 52 uint8*, |
49 int, | 53 int, |
50 int, | 54 int, |
51 int, | 55 int, |
52 int, | 56 int, |
53 int); | 57 int); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 const uint8* v_ptr = NULL; | 328 const uint8* v_ptr = NULL; |
325 // Apply vertical filtering if necessary. | 329 // Apply vertical filtering if necessary. |
326 // TODO(fbarchard): Remove memcpy when not necessary. | 330 // TODO(fbarchard): Remove memcpy when not necessary. |
327 if (filter & media::FILTER_BILINEAR_V) { | 331 if (filter & media::FILTER_BILINEAR_V) { |
328 int source_y = source_y_subpixel >> kFractionBits; | 332 int source_y = source_y_subpixel >> kFractionBits; |
329 y_ptr = y_buf + source_y * y_pitch; | 333 y_ptr = y_buf + source_y * y_pitch; |
330 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch; | 334 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch; |
331 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch; | 335 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch; |
332 | 336 |
333 // Vertical scaler uses 16.8 fixed point. | 337 // Vertical scaler uses 16.8 fixed point. |
334 int source_y_fraction = (source_y_subpixel & kFractionMask) >> 8; | 338 uint8 source_y_fraction = (source_y_subpixel & kFractionMask) >> 8; |
335 if (source_y_fraction != 0) { | 339 if (source_y_fraction != 0) { |
336 g_filter_yuv_rows_proc_( | 340 g_filter_yuv_rows_proc_( |
337 ybuf, y_ptr, y_ptr + y_pitch, source_width, source_y_fraction); | 341 ybuf, y_ptr, y_ptr + y_pitch, source_width, source_y_fraction); |
338 } else { | 342 } else { |
339 memcpy(ybuf, y_ptr, source_width); | 343 memcpy(ybuf, y_ptr, source_width); |
340 } | 344 } |
341 y_ptr = ybuf; | 345 y_ptr = ybuf; |
342 ybuf[source_width] = ybuf[source_width - 1]; | 346 ybuf[source_width] = ybuf[source_width - 1]; |
343 | 347 |
344 int uv_source_width = (source_width + 1) / 2; | 348 int uv_source_width = (source_width + 1) / 2; |
345 int source_uv_fraction; | 349 uint8 source_uv_fraction; |
346 | 350 |
347 // For formats with half-height UV planes, each even-numbered pixel row | 351 // For formats with half-height UV planes, each even-numbered pixel row |
348 // should not interpolate, since the next row to interpolate from should | 352 // should not interpolate, since the next row to interpolate from should |
349 // be a duplicate of the current row. | 353 // be a duplicate of the current row. |
350 if (y_shift && (source_y & 0x1) == 0) | 354 if (y_shift && (source_y & 0x1) == 0) |
351 source_uv_fraction = 0; | 355 source_uv_fraction = 0; |
352 else | 356 else |
353 source_uv_fraction = source_y_fraction; | 357 source_uv_fraction = source_y_fraction; |
354 | 358 |
355 if (source_uv_fraction != 0) { | 359 if (source_uv_fraction != 0) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 int source_y_width = source_y_right - source_y_left; | 467 int source_y_width = source_y_right - source_y_left; |
464 int source_uv_width = source_uv_right - source_uv_left; | 468 int source_uv_width = source_uv_right - source_uv_left; |
465 | 469 |
466 // Determine number of pixels in each output row. | 470 // Determine number of pixels in each output row. |
467 int dest_rect_width = dest_rect_right - dest_rect_left; | 471 int dest_rect_width = dest_rect_right - dest_rect_left; |
468 | 472 |
469 // Intermediate buffer for vertical interpolation. | 473 // Intermediate buffer for vertical interpolation. |
470 // 4096 bytes allows 3 buffers to fit in 12k, which fits in a 16K L1 cache, | 474 // 4096 bytes allows 3 buffers to fit in 12k, which fits in a 16K L1 cache, |
471 // and is bigger than most users will generally need. | 475 // and is bigger than most users will generally need. |
472 // The buffer is 16-byte aligned and padded with 16 extra bytes; some of the | 476 // The buffer is 16-byte aligned and padded with 16 extra bytes; some of the |
473 // FilterYUVRowProcs have alignment requirements, and the SSE version can | 477 // FilterYUVRowsProcs have alignment requirements, and the SSE version can |
474 // write up to 16 bytes past the end of the buffer. | 478 // write up to 16 bytes past the end of the buffer. |
475 const int kFilterBufferSize = 4096; | 479 const int kFilterBufferSize = 4096; |
476 const bool kAvoidUsingOptimizedFilter = source_width > kFilterBufferSize; | 480 const bool kAvoidUsingOptimizedFilter = source_width > kFilterBufferSize; |
477 uint8 yuv_temp[16 + kFilterBufferSize * 3 + 16]; | 481 uint8 yuv_temp[16 + kFilterBufferSize * 3 + 16]; |
478 // memset() yuv_temp to 0 to avoid bogus warnings when running on Valgrind. | 482 // memset() yuv_temp to 0 to avoid bogus warnings when running on Valgrind. |
479 if (RunningOnValgrind()) | 483 if (RunningOnValgrind()) |
480 memset(yuv_temp, 0, sizeof(yuv_temp)); | 484 memset(yuv_temp, 0, sizeof(yuv_temp)); |
481 uint8* y_temp = reinterpret_cast<uint8*>( | 485 uint8* y_temp = reinterpret_cast<uint8*>( |
482 reinterpret_cast<uintptr_t>(yuv_temp + 15) & ~15); | 486 reinterpret_cast<uintptr_t>(yuv_temp + 15) & ~15); |
483 uint8* u_temp = y_temp + kFilterBufferSize; | 487 uint8* u_temp = y_temp + kFilterBufferSize; |
(...skipping 28 matching lines...) Expand all Loading... |
512 if (source_uv_row + 1 >= (source_height + 1) / 2) { | 516 if (source_uv_row + 1 >= (source_height + 1) / 2) { |
513 u1_ptr = u0_ptr; | 517 u1_ptr = u0_ptr; |
514 v1_ptr = v0_ptr; | 518 v1_ptr = v0_ptr; |
515 } else { | 519 } else { |
516 u1_ptr = u0_ptr + uv_pitch; | 520 u1_ptr = u0_ptr + uv_pitch; |
517 v1_ptr = v0_ptr + uv_pitch; | 521 v1_ptr = v0_ptr + uv_pitch; |
518 } | 522 } |
519 | 523 |
520 if (!kAvoidUsingOptimizedFilter) { | 524 if (!kAvoidUsingOptimizedFilter) { |
521 // Vertical scaler uses 16.8 fixed point. | 525 // Vertical scaler uses 16.8 fixed point. |
522 int fraction = (source_top & kFractionMask) >> 8; | 526 uint8 fraction = (source_top & kFractionMask) >> 8; |
523 g_filter_yuv_rows_proc_( | 527 g_filter_yuv_rows_proc_( |
524 y_temp + source_y_left, y0_ptr, y1_ptr, source_y_width, fraction); | 528 y_temp + source_y_left, y0_ptr, y1_ptr, source_y_width, fraction); |
525 g_filter_yuv_rows_proc_( | 529 g_filter_yuv_rows_proc_( |
526 u_temp + source_uv_left, u0_ptr, u1_ptr, source_uv_width, fraction); | 530 u_temp + source_uv_left, u0_ptr, u1_ptr, source_uv_width, fraction); |
527 g_filter_yuv_rows_proc_( | 531 g_filter_yuv_rows_proc_( |
528 v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction); | 532 v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction); |
529 | 533 |
530 // Perform horizontal interpolation and color space conversion. | 534 // Perform horizontal interpolation and color space conversion. |
531 // TODO(hclam): Use the MMX version after more testing. | 535 // TODO(hclam): Use the MMX version after more testing. |
532 LinearScaleYUVToRGB32RowWithRange_C(y_temp, | 536 LinearScaleYUVToRGB32RowWithRange_C(y_temp, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 width, | 686 width, |
683 height, | 687 height, |
684 ystride, | 688 ystride, |
685 uvstride, | 689 uvstride, |
686 astride, | 690 astride, |
687 rgbstride, | 691 rgbstride, |
688 yuv_type); | 692 yuv_type); |
689 } | 693 } |
690 | 694 |
691 } // namespace media | 695 } // namespace media |
OLD | NEW |