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

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

Issue 8954003: Revised sub-rectangle scaling for use in Chromoting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Replace bounds-check on loop with a DCHECK. Created 9 years 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // Fixed-point value of vertical and horizontal scale down factor.
302 // Values are in the format 16.16.
303 int y_step = kFractionMax * source_height / dest_height;
304 int x_step = kFractionMax * source_width / dest_width;
305
306 // Determine the coordinates of the rectangle in 16.16 coords.
307 // NB: Our origin is the *center* of the top/left pixel, NOT its top/left.
308 // If we're down-scaling by more than a factor of two, we start with a 50%
309 // fraction to avoid degenerating to point-sampling - we should really just
310 // fix the fraction at 50% for all pixels in that case.
311 int source_left = dest_rect_left * x_step;
312 int source_right = dest_rect_right * x_step;
313 if (x_step < kFractionMax * 2) {
314 source_left += ((x_step - kFractionMax) / 2);
315 source_right += ((x_step - kFractionMax) / 2);
316 } else {
317 source_left += kFractionMax / 2;
318 source_right += kFractionMax / 2;
319 }
320 int source_top = dest_rect_top * y_step;
321 if (y_step < kFractionMax * 2)
322 source_top += ((y_step - kFractionMax) / 2);
323 else
324 source_top += kFractionMax / 2;
325
326 // Determine the parts of the Y, U and V buffers to interpolate.
327 int source_y_left = source_left >> kFractionBits;
328 int source_y_right = std::min(source_width,
329 (source_right + kFractionMax - 1) >> kFractionBits);
330 int source_uv_left = source_y_left / 2;
331 int source_uv_right = std::min((source_width + 1) / 2,
332 (source_right + (kFractionMax*2 - 1)) >>
333 (kFractionBits + 1));
334 int source_y_width = source_y_right - source_y_left;
335 int source_uv_width = source_uv_right - source_uv_left;
336
337 // Determine number of pixels in each output row.
338 int dest_rect_width = dest_rect_right - dest_rect_left;
339
340 // Create intermediate buffer for vertical interpolation.
341 scoped_array<uint8> y_temp(new uint8[source_width]);
342 scoped_array<uint8> u_temp(new uint8[source_width / 2]);
343 scoped_array<uint8> v_temp(new uint8[source_width / 2]);
344
345 // Move to the top-left pixel of output.
346 rgb_buf += dest_rect_top * rgb_pitch;
347 rgb_buf += dest_rect_left * 4;
348
349 // For each destination row perform interpolation and color space
350 // conversion to produce the output.
351 for (int row = dest_rect_top; row < dest_rect_bottom; ++row) {
352 // Round the fixed-point y position to get the current row.
353 int source_row = source_top >> kFractionBits;
354 DCHECK(source_row < source_height);
355
356 // Locate the first row for each plane for interpolation.
357 const uint8* y0_ptr = y_buf + y_pitch * source_row + source_y_left;
358 const uint8* u0_ptr = u_buf + uv_pitch * (source_row / 2) + source_uv_left;
359 const uint8* v0_ptr = v_buf + uv_pitch * (source_row / 2) + source_uv_left;
360 const uint8* y1_ptr = NULL;
361 const uint8* u1_ptr = NULL;
362 const uint8* v1_ptr = NULL;
363
364 // Locate the second row for interpolation and need to be careful
365 // about bounds checking here.
366 if (source_row + 1 >= source_height) {
367 y1_ptr = y0_ptr;
368 u1_ptr = u0_ptr;
369 v1_ptr = v0_ptr;
370 } else {
371 y1_ptr = y0_ptr + y_pitch;
372 u1_ptr = u0_ptr + uv_pitch;
373 v1_ptr = v0_ptr + uv_pitch;
374 }
375
376 // Vertical scaler uses 16.8 fixed point.
377 int fraction = (source_top & kFractionMask) >> 8;
378 filter_proc(y_temp.get() + source_y_left, y0_ptr, y1_ptr,
379 source_y_width, fraction);
380 filter_proc(u_temp.get() + source_uv_left, u0_ptr, u1_ptr,
381 source_uv_width, fraction);
382 filter_proc(v_temp.get() + source_uv_left, v0_ptr, v1_ptr,
383 source_uv_width, fraction);
384
385 // Perform horizontal interpolation and color space conversion.
386 // TODO(hclam): Use the MMX version after more testing.
387 LinearScaleYUVToRGB32RowWithRange_C(
388 y_temp.get(), u_temp.get(), v_temp.get(), rgb_buf,
389 dest_rect_width, source_left, x_step);
390
391 // Advance vertically in the source and destination image.
392 source_top += y_step;
393 rgb_buf += rgb_pitch;
394 }
395
396 EmptyRegisterState();
397 }
398
280 void ConvertRGB32ToYUV(const uint8* rgbframe, 399 void ConvertRGB32ToYUV(const uint8* rgbframe,
281 uint8* yplane, 400 uint8* yplane,
282 uint8* uplane, 401 uint8* uplane,
283 uint8* vplane, 402 uint8* vplane,
284 int width, 403 int width,
285 int height, 404 int height,
286 int rgbstride, 405 int rgbstride,
287 int ystride, 406 int ystride,
288 int uvstride) { 407 int uvstride) {
289 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, 408 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 else 501 else
383 convert_proc = &ConvertYUVToRGB32_C; 502 convert_proc = &ConvertYUVToRGB32_C;
384 } 503 }
385 504
386 convert_proc(yplane, uplane, vplane, rgbframe, 505 convert_proc(yplane, uplane, vplane, rgbframe,
387 width, height, ystride, uvstride, rgbstride, yuv_type); 506 width, height, ystride, uvstride, rgbstride, yuv_type);
388 #endif 507 #endif
389 } 508 }
390 509
391 } // namespace media 510 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698