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

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

Issue 9138050: Merge 117748 - Linear sub-rectangle scaler for use in Chromoting. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/963/src/
Patch Set: Created 8 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_unittest.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) 2011 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/logging.h" 20 #include "base/logging.h"
21 #include "base/memory/scoped_ptr.h"
21 #include "build/build_config.h" 22 #include "build/build_config.h"
22 #include "media/base/cpu_features.h" 23 #include "media/base/cpu_features.h"
23 #include "media/base/simd/convert_rgb_to_yuv.h" 24 #include "media/base/simd/convert_rgb_to_yuv.h"
24 #include "media/base/simd/convert_yuv_to_rgb.h" 25 #include "media/base/simd/convert_yuv_to_rgb.h"
25 #include "media/base/simd/filter_yuv.h" 26 #include "media/base/simd/filter_yuv.h"
26 27
27 #if defined(ARCH_CPU_X86_FAMILY) 28 #if defined(ARCH_CPU_X86_FAMILY)
28 #if defined(COMPILER_MSVC) 29 #if defined(COMPILER_MSVC)
29 #include <intrin.h> 30 #include <intrin.h>
30 #else 31 #else
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 linear_scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 271 linear_scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx);
271 } else { 272 } else {
272 scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); 273 scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx);
273 } 274 }
274 } 275 }
275 } 276 }
276 277
277 EmptyRegisterState(); 278 EmptyRegisterState();
278 } 279 }
279 280
281 // Scale a frame of YV12 to 32 bit ARGB for a specific rectangle.
282 void ScaleYUVToRGB32WithRect(const uint8* y_buf,
283 const uint8* u_buf,
284 const uint8* v_buf,
285 uint8* rgb_buf,
286 int source_width,
287 int source_height,
288 int dest_width,
289 int dest_height,
290 int dest_rect_left,
291 int dest_rect_top,
292 int dest_rect_right,
293 int dest_rect_bottom,
294 int y_pitch,
295 int uv_pitch,
296 int rgb_pitch) {
297 static FilterYUVRowsProc filter_proc = NULL;
298 if (!filter_proc)
299 filter_proc = ChooseFilterYUVRowsProc();
300
301 // This routine doesn't currently support up-scaling.
302 CHECK(dest_width <= source_width && dest_height <= source_height);
303
304 // Sanity-check the destination rectangle.
305 DCHECK(dest_rect_left >= 0 && dest_rect_right <= dest_width);
306 DCHECK(dest_rect_top >= 0 && dest_rect_bottom <= dest_height);
307 DCHECK(dest_rect_right > dest_rect_left);
308 DCHECK(dest_rect_bottom > dest_rect_top);
309
310 // Fixed-point value of vertical and horizontal scale down factor.
311 // Values are in the format 16.16.
312 int y_step = kFractionMax * source_height / dest_height;
313 int x_step = kFractionMax * source_width / dest_width;
314
315 // Determine the coordinates of the rectangle in 16.16 coords.
316 // NB: Our origin is the *center* of the top/left pixel, NOT its top/left.
317 // If we're down-scaling by more than a factor of two, we start with a 50%
318 // fraction to avoid degenerating to point-sampling - we should really just
319 // fix the fraction at 50% for all pixels in that case.
320 int source_left = dest_rect_left * x_step;
321 int source_right = (dest_rect_right - 1) * x_step;
322 if (x_step < kFractionMax * 2) {
323 source_left += ((x_step - kFractionMax) / 2);
324 source_right += ((x_step - kFractionMax) / 2);
325 } else {
326 source_left += kFractionMax / 2;
327 source_right += kFractionMax / 2;
328 }
329 int source_top = dest_rect_top * y_step;
330 if (y_step < kFractionMax * 2) {
331 source_top += ((y_step - kFractionMax) / 2);
332 } else {
333 source_top += kFractionMax / 2;
334 }
335
336 // Determine the parts of the Y, U and V buffers to interpolate.
337 int source_y_left = source_left >> kFractionBits;
338 int source_y_right = (source_right >> kFractionBits) + 2;
339 DCHECK(source_y_right <= source_width);
340
341 int source_uv_left = source_y_left / 2;
342 int source_uv_right = std::min(
343 (source_right >> (kFractionBits + 1)) + 2,
344 (source_width + 1) / 2);
345
346 int source_y_width = source_y_right - source_y_left;
347 int source_uv_width = source_uv_right - source_uv_left;
348
349 // Determine number of pixels in each output row.
350 int dest_rect_width = dest_rect_right - dest_rect_left;
351
352 // Intermediate buffer for vertical interpolation.
353 // 4096 bytes allows 3 buffers to fit in 12k, which fits in a 16K L1 cache,
354 // and is bigger than most users will generally need.
355 // The buffer is 16-byte aligned and padded with 16 extra bytes; some of the
356 // FilterYUVRowProcs have alignment requirements, and the SSE version can
357 // write up to 16 bytes past the end of the buffer.
358 const int kFilterBufferSize = 4096;
359 if (source_width > kFilterBufferSize)
360 filter_proc = NULL;
361 uint8 yuv_temp[16 + kFilterBufferSize * 3 + 16];
362 uint8* y_temp =
363 reinterpret_cast<uint8*>(
364 reinterpret_cast<uintptr_t>(yuv_temp + 15) & ~15);
365 uint8* u_temp = y_temp + kFilterBufferSize;
366 uint8* v_temp = u_temp + kFilterBufferSize;
367
368 // Move to the top-left pixel of output.
369 rgb_buf += dest_rect_top * rgb_pitch;
370 rgb_buf += dest_rect_left * 4;
371
372 // For each destination row perform interpolation and color space
373 // conversion to produce the output.
374 for (int row = dest_rect_top; row < dest_rect_bottom; ++row) {
375 // Round the fixed-point y position to get the current row.
376 int source_row = source_top >> kFractionBits;
377 int source_uv_row = source_row / 2;
378 DCHECK(source_row < source_height);
379
380 // Locate the first row for each plane for interpolation.
381 const uint8* y0_ptr = y_buf + y_pitch * source_row + source_y_left;
382 const uint8* u0_ptr = u_buf + uv_pitch * source_uv_row + source_uv_left;
383 const uint8* v0_ptr = v_buf + uv_pitch * source_uv_row + source_uv_left;
384 const uint8* y1_ptr = NULL;
385 const uint8* u1_ptr = NULL;
386 const uint8* v1_ptr = NULL;
387
388 // Locate the second row for interpolation, being careful not to overrun.
389 if (source_row + 1 >= source_height) {
390 y1_ptr = y0_ptr;
391 } else {
392 y1_ptr = y0_ptr + y_pitch;
393 }
394 if (source_uv_row + 1 >= (source_height + 1) / 2) {
395 u1_ptr = u0_ptr;
396 v1_ptr = v0_ptr;
397 } else {
398 u1_ptr = u0_ptr + uv_pitch;
399 v1_ptr = v0_ptr + uv_pitch;
400 }
401
402 if (filter_proc) {
403 // Vertical scaler uses 16.8 fixed point.
404 int fraction = (source_top & kFractionMask) >> 8;
405 filter_proc(y_temp + source_y_left, y0_ptr, y1_ptr,
406 source_y_width, fraction);
407 filter_proc(u_temp + source_uv_left, u0_ptr, u1_ptr,
408 source_uv_width, fraction);
409 filter_proc(v_temp + source_uv_left, v0_ptr, v1_ptr,
410 source_uv_width, fraction);
411
412 // Perform horizontal interpolation and color space conversion.
413 // TODO(hclam): Use the MMX version after more testing.
414 LinearScaleYUVToRGB32RowWithRange_C(
415 y_temp, u_temp, v_temp, rgb_buf,
416 dest_rect_width, source_left, x_step);
417 } else {
418 // If the frame is too large then we linear scale a single row.
419 LinearScaleYUVToRGB32RowWithRange_C(
420 y0_ptr, u0_ptr, v0_ptr, rgb_buf,
421 dest_rect_width, source_left, x_step);
422 }
423
424 // Advance vertically in the source and destination image.
425 source_top += y_step;
426 rgb_buf += rgb_pitch;
427 }
428
429 EmptyRegisterState();
430 }
431
280 void ConvertRGB32ToYUV(const uint8* rgbframe, 432 void ConvertRGB32ToYUV(const uint8* rgbframe,
281 uint8* yplane, 433 uint8* yplane,
282 uint8* uplane, 434 uint8* uplane,
283 uint8* vplane, 435 uint8* vplane,
284 int width, 436 int width,
285 int height, 437 int height,
286 int rgbstride, 438 int rgbstride,
287 int ystride, 439 int ystride,
288 int uvstride) { 440 int uvstride) {
289 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, 441 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 else 534 else
383 convert_proc = &ConvertYUVToRGB32_C; 535 convert_proc = &ConvertYUVToRGB32_C;
384 } 536 }
385 537
386 convert_proc(yplane, uplane, vplane, rgbframe, 538 convert_proc(yplane, uplane, vplane, rgbframe,
387 width, height, ystride, uvstride, rgbstride, yuv_type); 539 width, height, ystride, uvstride, rgbstride, yuv_type);
388 #endif 540 #endif
389 } 541 }
390 542
391 } // namespace media 543 } // namespace media
OLDNEW
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698