| 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 |