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

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: YUVJ browsertest now passes, update expectation Created 6 years, 7 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
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_perftest.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) 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 NOTREACHED();
129 return 0;
130 }
131
132 const int16 (&GetLookupTable(YUVType type))[1024][4] {
133 switch (type) {
134 case YV12:
135 case YV16:
136 return kCoefficientsRgbY;
137 case YV12J:
138 return kCoefficientsRgbY_JPEG;
139 }
140 NOTREACHED();
141 return kCoefficientsRgbY;
142 }
143
115 void InitializeCPUSpecificYUVConversions() { 144 void InitializeCPUSpecificYUVConversions() {
116 CHECK(!g_filter_yuv_rows_proc_); 145 CHECK(!g_filter_yuv_rows_proc_);
117 CHECK(!g_convert_yuv_to_rgb32_row_proc_); 146 CHECK(!g_convert_yuv_to_rgb32_row_proc_);
118 CHECK(!g_scale_yuv_to_rgb32_row_proc_); 147 CHECK(!g_scale_yuv_to_rgb32_row_proc_);
119 CHECK(!g_linear_scale_yuv_to_rgb32_row_proc_); 148 CHECK(!g_linear_scale_yuv_to_rgb32_row_proc_);
120 CHECK(!g_convert_rgb32_to_yuv_proc_); 149 CHECK(!g_convert_rgb32_to_yuv_proc_);
121 CHECK(!g_convert_rgb24_to_yuv_proc_); 150 CHECK(!g_convert_rgb24_to_yuv_proc_);
122 CHECK(!g_convert_yuv_to_rgb32_proc_); 151 CHECK(!g_convert_yuv_to_rgb32_proc_);
123 CHECK(!g_convert_yuva_to_argb_proc_); 152 CHECK(!g_convert_yuva_to_argb_proc_);
124 CHECK(!g_empty_register_state_proc_); 153 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. 244 // Helps performance on CPU with 16K L1 cache.
216 // Large enough for 3830x2160 and 30" displays which are 2560x1600. 245 // Large enough for 3830x2160 and 30" displays which are 2560x1600.
217 const int kFilterBufferSize = 4096; 246 const int kFilterBufferSize = 4096;
218 // Disable filtering if the screen is too big (to avoid buffer overflows). 247 // 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 248 // This should never happen to regular users: they don't have monitors
220 // wider than 4096 pixels. 249 // wider than 4096 pixels.
221 // TODO(fbarchard): Allow rotated videos to filter. 250 // TODO(fbarchard): Allow rotated videos to filter.
222 if (source_width > kFilterBufferSize || view_rotate) 251 if (source_width > kFilterBufferSize || view_rotate)
223 filter = FILTER_NONE; 252 filter = FILTER_NONE;
224 253
225 unsigned int y_shift = yuv_type; 254 unsigned int y_shift = GetVerticalShift(yuv_type);
226 // Diagram showing origin and direction of source sampling. 255 // Diagram showing origin and direction of source sampling.
227 // ->0 4<- 256 // ->0 4<-
228 // 7 3 257 // 7 3
229 // 258 //
230 // 6 5 259 // 6 5
231 // ->1 2<- 260 // ->1 2<-
232 // Rotations that start at right side of image. 261 // Rotations that start at right side of image.
233 if ((view_rotate == ROTATE_180) || (view_rotate == ROTATE_270) || 262 if ((view_rotate == ROTATE_180) || (view_rotate == ROTATE_270) ||
234 (view_rotate == MIRROR_ROTATE_0) || (view_rotate == MIRROR_ROTATE_90)) { 263 (view_rotate == MIRROR_ROTATE_0) || (view_rotate == MIRROR_ROTATE_90)) {
235 y_buf += source_width - 1; 264 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]; 376 ubuf[uv_source_width] = ubuf[uv_source_width - 1];
348 vbuf[uv_source_width] = vbuf[uv_source_width - 1]; 377 vbuf[uv_source_width] = vbuf[uv_source_width - 1];
349 } else { 378 } else {
350 // Offset by 1/2 pixel for center sampling. 379 // Offset by 1/2 pixel for center sampling.
351 int source_y = (source_y_subpixel + (kFractionMax / 2)) >> kFractionBits; 380 int source_y = (source_y_subpixel + (kFractionMax / 2)) >> kFractionBits;
352 y_ptr = y_buf + source_y * y_pitch; 381 y_ptr = y_buf + source_y * y_pitch;
353 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch; 382 u_ptr = u_buf + (source_y >> y_shift) * uv_pitch;
354 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch; 383 v_ptr = v_buf + (source_y >> y_shift) * uv_pitch;
355 } 384 }
356 if (source_dx == kFractionMax) { // Not scaled 385 if (source_dx == kFractionMax) { // Not scaled
357 g_convert_yuv_to_rgb32_row_proc_(y_ptr, u_ptr, v_ptr, dest_pixel, width); 386 g_convert_yuv_to_rgb32_row_proc_(
387 y_ptr, u_ptr, v_ptr, dest_pixel, width, kCoefficientsRgbY);
358 } else { 388 } else {
359 if (filter & FILTER_BILINEAR_H) { 389 if (filter & FILTER_BILINEAR_H) {
360 g_linear_scale_yuv_to_rgb32_row_proc_( 390 g_linear_scale_yuv_to_rgb32_row_proc_(y_ptr,
361 y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 391 u_ptr,
392 v_ptr,
393 dest_pixel,
394 width,
395 source_dx,
396 kCoefficientsRgbY);
362 } else { 397 } else {
363 g_scale_yuv_to_rgb32_row_proc_( 398 g_scale_yuv_to_rgb32_row_proc_(y_ptr,
364 y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 399 u_ptr,
400 v_ptr,
401 dest_pixel,
402 width,
403 source_dx,
404 kCoefficientsRgbY);
365 } 405 }
366 } 406 }
367 } 407 }
368 408
369 g_empty_register_state_proc_(); 409 g_empty_register_state_proc_();
370 } 410 }
371 411
372 // Scale a frame of YV12 to 32 bit ARGB for a specific rectangle. 412 // Scale a frame of YV12 to 32 bit ARGB for a specific rectangle.
373 void ScaleYUVToRGB32WithRect(const uint8* y_buf, 413 void ScaleYUVToRGB32WithRect(const uint8* y_buf,
374 const uint8* u_buf, 414 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); 538 v_temp + source_uv_left, v0_ptr, v1_ptr, source_uv_width, fraction);
499 539
500 // Perform horizontal interpolation and color space conversion. 540 // Perform horizontal interpolation and color space conversion.
501 // TODO(hclam): Use the MMX version after more testing. 541 // TODO(hclam): Use the MMX version after more testing.
502 LinearScaleYUVToRGB32RowWithRange_C(y_temp, 542 LinearScaleYUVToRGB32RowWithRange_C(y_temp,
503 u_temp, 543 u_temp,
504 v_temp, 544 v_temp,
505 rgb_buf, 545 rgb_buf,
506 dest_rect_width, 546 dest_rect_width,
507 source_left, 547 source_left,
508 x_step); 548 x_step,
549 kCoefficientsRgbY);
509 } else { 550 } else {
510 // If the frame is too large then we linear scale a single row. 551 // If the frame is too large then we linear scale a single row.
511 LinearScaleYUVToRGB32RowWithRange_C(y0_ptr, 552 LinearScaleYUVToRGB32RowWithRange_C(y0_ptr,
512 u0_ptr, 553 u0_ptr,
513 v0_ptr, 554 v0_ptr,
514 rgb_buf, 555 rgb_buf,
515 dest_rect_width, 556 dest_rect_width,
516 source_left, 557 source_left,
517 x_step); 558 x_step,
559 kCoefficientsRgbY);
518 } 560 }
519 561
520 // Advance vertically in the source and destination image. 562 // Advance vertically in the source and destination image.
521 source_top += y_step; 563 source_top += y_step;
522 rgb_buf += rgb_pitch; 564 rgb_buf += rgb_pitch;
523 } 565 }
524 566
525 g_empty_register_state_proc_(); 567 g_empty_register_state_proc_();
526 } 568 }
527 569
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 width, 692 width,
651 height, 693 height,
652 ystride, 694 ystride,
653 uvstride, 695 uvstride,
654 astride, 696 astride,
655 rgbstride, 697 rgbstride,
656 yuv_type); 698 yuv_type);
657 } 699 }
658 700
659 } // namespace media 701 } // namespace media
OLDNEW
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698