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

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

Issue 242643011: Add correct support for videos with YUVJ420P color format, in the software conversion path. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@yuvnopic
Patch Set: Created 6 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
OLDNEW
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
11 // 11 //
12 // YV12 is a full plane of Y and a half height, half width chroma planes 12 // YV12 is a full plane of Y and a half height, half width chroma planes
13 // YV16 is a full plane of Y and a full height, half width chroma planes 13 // YV16 is a full plane of Y and a full height, half width chroma planes
14 // 14 //
15 // ARGB pixel format is output, which on little endian is stored as BGRA. 15 // ARGB pixel format is output, which on little endian is stored as BGRA.
16 // The alpha is set to 255, allowing the application to use RGBA or RGB32. 16 // The alpha is set to 255, allowing the application to use RGBA or RGB32.
17 17
18 #include "media/base/yuv_convert.h" 18 #include "media/base/yuv_convert.h"
19 19
20 #include "base/cpu.h" 20 #include "base/cpu.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/scoped_ptr.h"
23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
24 #include "build/build_config.h" 24 #include "build/build_config.h"
25 #include "media/base/simd/convert_rgb_to_yuv.h" 25 #include "media/base/simd/convert_rgb_to_yuv.h"
26 #include "media/base/simd/convert_yuv_to_rgb.h" 26 #include "media/base/simd/convert_yuv_to_rgb.h"
27 #include "media/base/simd/filter_yuv.h" 27 #include "media/base/simd/filter_yuv.h"
28 #include "media/base/simd/yuv_to_rgb_table.h"
28 29
29 #if defined(ARCH_CPU_X86_FAMILY) 30 #if defined(ARCH_CPU_X86_FAMILY)
30 #if defined(COMPILER_MSVC) 31 #if defined(COMPILER_MSVC)
31 #include <intrin.h> 32 #include <intrin.h>
32 #else 33 #else
33 #include <mmintrin.h> 34 #include <mmintrin.h>
34 #endif 35 #endif
35 #endif 36 #endif
36 37
37 // Assembly functions are declared without namespace. 38 // Assembly functions are declared without namespace.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 int, 73 int,
73 int, 74 int,
74 int, 75 int,
75 int, 76 int,
76 YUVType); 77 YUVType);
77 78
78 typedef void (*ConvertYUVToRGB32RowProc)(const uint8*, 79 typedef void (*ConvertYUVToRGB32RowProc)(const uint8*,
79 const uint8*, 80 const uint8*,
80 const uint8*, 81 const uint8*,
81 uint8*, 82 uint8*,
82 ptrdiff_t); 83 ptrdiff_t,
84 const int16[1024][4]);
83 85
84 typedef void (*ConvertYUVAToARGBRowProc)(const uint8*, 86 typedef void (*ConvertYUVAToARGBRowProc)(const uint8*,
85 const uint8*, 87 const uint8*,
86 const uint8*, 88 const uint8*,
87 const uint8*, 89 const uint8*,
88 uint8*, 90 uint8*,
89 ptrdiff_t); 91 ptrdiff_t,
92 const int16[1024][4]);
90 93
91 typedef void (*ScaleYUVToRGB32RowProc)(const uint8*, 94 typedef void (*ScaleYUVToRGB32RowProc)(const uint8*,
92 const uint8*, 95 const uint8*,
93 const uint8*, 96 const uint8*,
94 uint8*, 97 uint8*,
95 ptrdiff_t, 98 ptrdiff_t,
96 ptrdiff_t); 99 ptrdiff_t,
100 const int16[1024][4]);
97 101
98 static FilterYUVRowsProc g_filter_yuv_rows_proc_ = NULL; 102 static FilterYUVRowsProc g_filter_yuv_rows_proc_ = NULL;
99 static ConvertYUVToRGB32RowProc g_convert_yuv_to_rgb32_row_proc_ = NULL; 103 static ConvertYUVToRGB32RowProc g_convert_yuv_to_rgb32_row_proc_ = NULL;
100 static ScaleYUVToRGB32RowProc g_scale_yuv_to_rgb32_row_proc_ = NULL; 104 static ScaleYUVToRGB32RowProc g_scale_yuv_to_rgb32_row_proc_ = NULL;
101 static ScaleYUVToRGB32RowProc g_linear_scale_yuv_to_rgb32_row_proc_ = NULL; 105 static ScaleYUVToRGB32RowProc g_linear_scale_yuv_to_rgb32_row_proc_ = NULL;
102 static ConvertRGBToYUVProc g_convert_rgb32_to_yuv_proc_ = NULL; 106 static ConvertRGBToYUVProc g_convert_rgb32_to_yuv_proc_ = NULL;
103 static ConvertRGBToYUVProc g_convert_rgb24_to_yuv_proc_ = NULL; 107 static ConvertRGBToYUVProc g_convert_rgb24_to_yuv_proc_ = NULL;
104 static ConvertYUVToRGB32Proc g_convert_yuv_to_rgb32_proc_ = NULL; 108 static ConvertYUVToRGB32Proc g_convert_yuv_to_rgb32_proc_ = NULL;
105 static ConvertYUVAToARGBProc g_convert_yuva_to_argb_proc_ = NULL; 109 static ConvertYUVAToARGBProc g_convert_yuva_to_argb_proc_ = NULL;
106 110
107 // Empty SIMD registers state after using them. 111 // Empty SIMD registers state after using them.
108 void EmptyRegisterStateStub() {} 112 void EmptyRegisterStateStub() {}
109 #if defined(MEDIA_MMX_INTRINSICS_AVAILABLE) 113 #if defined(MEDIA_MMX_INTRINSICS_AVAILABLE)
110 void EmptyRegisterStateIntrinsic() { _mm_empty(); } 114 void EmptyRegisterStateIntrinsic() { _mm_empty(); }
111 #endif 115 #endif
112 typedef void (*EmptyRegisterStateProc)(); 116 typedef void (*EmptyRegisterStateProc)();
113 static EmptyRegisterStateProc g_empty_register_state_proc_ = NULL; 117 static EmptyRegisterStateProc g_empty_register_state_proc_ = NULL;
114 118
119 // Get the appropriate value to bitshift by for vertical indices.
120 int GetVerticalShift(YUVType type) {
121 switch (type) {
122 case YV16:
123 return 0;
124 case YV12:
125 case YV12J:
126 return 1;
127 }
128 }
129
115 void InitializeCPUSpecificYUVConversions() { 130 void InitializeCPUSpecificYUVConversions() {
116 CHECK(!g_filter_yuv_rows_proc_); 131 CHECK(!g_filter_yuv_rows_proc_);
117 CHECK(!g_convert_yuv_to_rgb32_row_proc_); 132 CHECK(!g_convert_yuv_to_rgb32_row_proc_);
118 CHECK(!g_scale_yuv_to_rgb32_row_proc_); 133 CHECK(!g_scale_yuv_to_rgb32_row_proc_);
119 CHECK(!g_linear_scale_yuv_to_rgb32_row_proc_); 134 CHECK(!g_linear_scale_yuv_to_rgb32_row_proc_);
120 CHECK(!g_convert_rgb32_to_yuv_proc_); 135 CHECK(!g_convert_rgb32_to_yuv_proc_);
121 CHECK(!g_convert_rgb24_to_yuv_proc_); 136 CHECK(!g_convert_rgb24_to_yuv_proc_);
122 CHECK(!g_convert_yuv_to_rgb32_proc_); 137 CHECK(!g_convert_yuv_to_rgb32_proc_);
123 CHECK(!g_convert_yuva_to_argb_proc_); 138 CHECK(!g_convert_yuva_to_argb_proc_);
124 CHECK(!g_empty_register_state_proc_); 139 CHECK(!g_empty_register_state_proc_);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 // Helps performance on CPU with 16K L1 cache. 230 // Helps performance on CPU with 16K L1 cache.
216 // Large enough for 3830x2160 and 30" displays which are 2560x1600. 231 // Large enough for 3830x2160 and 30" displays which are 2560x1600.
217 const int kFilterBufferSize = 4096; 232 const int kFilterBufferSize = 4096;
218 // Disable filtering if the screen is too big (to avoid buffer overflows). 233 // Disable filtering if the screen is too big (to avoid buffer overflows).
219 // This should never happen to regular users: they don't have monitors 234 // This should never happen to regular users: they don't have monitors
220 // wider than 4096 pixels. 235 // wider than 4096 pixels.
221 // TODO(fbarchard): Allow rotated videos to filter. 236 // TODO(fbarchard): Allow rotated videos to filter.
222 if (source_width > kFilterBufferSize || view_rotate) 237 if (source_width > kFilterBufferSize || view_rotate)
223 filter = FILTER_NONE; 238 filter = FILTER_NONE;
224 239
225 unsigned int y_shift = yuv_type; 240 unsigned int y_shift = GetVerticalShift(yuv_type);
226 // Diagram showing origin and direction of source sampling. 241 // Diagram showing origin and direction of source sampling.
227 // ->0 4<- 242 // ->0 4<-
228 // 7 3 243 // 7 3
229 // 244 //
230 // 6 5 245 // 6 5
231 // ->1 2<- 246 // ->1 2<-
232 // Rotations that start at right side of image. 247 // Rotations that start at right side of image.
233 if ((view_rotate == ROTATE_180) || (view_rotate == ROTATE_270) || 248 if ((view_rotate == ROTATE_180) || (view_rotate == ROTATE_270) ||
234 (view_rotate == MIRROR_ROTATE_0) || (view_rotate == MIRROR_ROTATE_90)) { 249 (view_rotate == MIRROR_ROTATE_0) || (view_rotate == MIRROR_ROTATE_90)) {
235 y_buf += source_width - 1; 250 y_buf += source_width - 1;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 ubuf[uv_source_width] = ubuf[uv_source_width - 1]; 362 ubuf[uv_source_width] = ubuf[uv_source_width - 1];
348 vbuf[uv_source_width] = vbuf[uv_source_width - 1]; 363 vbuf[uv_source_width] = vbuf[uv_source_width - 1];
349 } else { 364 } else {
350 // Offset by 1/2 pixel for center sampling. 365 // Offset by 1/2 pixel for center sampling.
351 int source_y = (source_y_subpixel + (kFractionMax / 2)) >> kFractionBits; 366 int source_y = (source_y_subpixel + (kFractionMax / 2)) >> kFractionBits;
352 y_ptr = y_buf + source_y * y_pitch; 367 y_ptr = y_buf + source_y * y_pitch;
353 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch; 368 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
354 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch; 369 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
355 } 370 }
356 if (source_dx == kFractionMax) { // Not scaled 371 if (source_dx == kFractionMax) { // Not scaled
357 g_convert_yuv_to_rgb32_row_proc_(y_ptr, u_ptr, v_ptr, dest_pixel, width); 372 g_convert_yuv_to_rgb32_row_proc_(
373 y_ptr, u_ptr, v_ptr, dest_pixel, width, kCoefficientsRgbY);
358 } else { 374 } else {
359 if (filter & FILTER_BILINEAR_H) { 375 if (filter & FILTER_BILINEAR_H) {
360 g_linear_scale_yuv_to_rgb32_row_proc_( 376 g_linear_scale_yuv_to_rgb32_row_proc_(y_ptr,
361 y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 377 u_ptr,
378 v_ptr,
379 dest_pixel,
380 width,
381 source_dx,
382 kCoefficientsRgbY);
362 } else { 383 } else {
363 g_scale_yuv_to_rgb32_row_proc_( 384 g_scale_yuv_to_rgb32_row_proc_(y_ptr,
364 y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 385 u_ptr,
386 v_ptr,
387 dest_pixel,
388 width,
389 source_dx,
390 kCoefficientsRgbY);
365 } 391 }
366 } 392 }
367 } 393 }
368 394
369 g_empty_register_state_proc_(); 395 g_empty_register_state_proc_();
370 } 396 }
371 397
372 // Scale a frame of YV12 to 32 bit ARGB for a specific rectangle. 398 // Scale a frame of YV12 to 32 bit ARGB for a specific rectangle.
373 void ScaleYUVToRGB32WithRect(const uint8* y_buf, 399 void ScaleYUVToRGB32WithRect(const uint8* y_buf,
374 const uint8* u_buf, 400 const uint8* u_buf,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction); 524 v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction);
499 525
500 // Perform horizontal interpolation and color space conversion. 526 // Perform horizontal interpolation and color space conversion.
501 // TODO(hclam): Use the MMX version after more testing. 527 // TODO(hclam): Use the MMX version after more testing.
502 LinearScaleYUVToRGB32RowWithRange_C(y_temp, 528 LinearScaleYUVToRGB32RowWithRange_C(y_temp,
503 u_temp, 529 u_temp,
504 v_temp, 530 v_temp,
505 rgb_buf, 531 rgb_buf,
506 dest_rect_width, 532 dest_rect_width,
507 source_left, 533 source_left,
508 x_step); 534 x_step,
535 kCoefficientsRgbY);
509 } else { 536 } else {
510 // If the frame is too large then we linear scale a single row. 537 // If the frame is too large then we linear scale a single row.
511 LinearScaleYUVToRGB32RowWithRange_C(y0_ptr, 538 LinearScaleYUVToRGB32RowWithRange_C(y0_ptr,
512 u0_ptr, 539 u0_ptr,
513 v0_ptr, 540 v0_ptr,
514 rgb_buf, 541 rgb_buf,
515 dest_rect_width, 542 dest_rect_width,
516 source_left, 543 source_left,
517 x_step); 544 x_step,
545 kCoefficientsRgbY);
518 } 546 }
519 547
520 // Advance vertically in the source and destination image. 548 // Advance vertically in the source and destination image.
521 source_top += y_step; 549 source_top += y_step;
522 rgb_buf += rgb_pitch; 550 rgb_buf += rgb_pitch;
523 } 551 }
524 552
525 g_empty_register_state_proc_(); 553 g_empty_register_state_proc_();
526 } 554 }
527 555
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 width, 678 width,
651 height, 679 height,
652 ystride, 680 ystride,
653 uvstride, 681 uvstride,
654 astride, 682 astride,
655 rgbstride, 683 rgbstride,
656 yuv_type); 684 yuv_type);
657 } 685 }
658 686
659 } // namespace media 687 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698