15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/yuv_convert.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size GetNaturalSize(const gfx::Size& visible_size,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int aspect_ratio_numerator,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int aspect_ratio_denominator) {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (aspect_ratio_denominator == 0 ||
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aspect_ratio_numerator < 0 ||
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aspect_ratio_denominator < 0)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Size();
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double aspect_ratio = aspect_ratio_numerator /
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<double>(aspect_ratio_denominator);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = floor(visible_size.width() * aspect_ratio + 0.5);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = visible_size.height();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An even width makes things easier for YV12 and appears to be the behavior
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expected by WebKit layout tests.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Size(width & ~1, height);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CopyPlane(size_t plane, const uint8* source, int stride, int rows,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               VideoFrame* frame) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* dest = frame->data(plane);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dest_stride = frame->stride(plane);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp in case source frame has smaller stride.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_to_copy_per_row = std::min(frame->row_bytes(plane), stride);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp in case source frame has smaller height.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rows_to_copy = std::min(frame->rows(plane), rows);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy!
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int row = 0; row < rows_to_copy; ++row) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dest, source, bytes_to_copy_per_row);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source += stride;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dest += dest_stride;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyYPlane(const uint8* source, int stride, int rows, VideoFrame* frame) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyPlane(VideoFrame::kYPlane, source, stride, rows, frame);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyUPlane(const uint8* source, int stride, int rows, VideoFrame* frame) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyPlane(VideoFrame::kUPlane, source, stride, rows, frame);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyVPlane(const uint8* source, int stride, int rows, VideoFrame* frame) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyPlane(VideoFrame::kVPlane, source, stride, rows, frame);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CopyAPlane(const uint8* source, int stride, int rows, VideoFrame* frame) {
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CopyPlane(VideoFrame::kAPlane, source, stride, rows, frame);
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void MakeOpaqueAPlane(int stride, int rows, VideoFrame* frame) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rows_to_clear = std::min(frame->rows(VideoFrame::kAPlane), rows);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(frame->data(VideoFrame::kAPlane), 255,
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         frame->stride(VideoFrame::kAPlane) * rows_to_clear);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FillYUV(VideoFrame* frame, uint8 y, uint8 u, uint8 v) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the Y plane.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* y_plane = frame->data(VideoFrame::kYPlane);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_rows = frame->rows(VideoFrame::kYPlane);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_row_bytes = frame->row_bytes(VideoFrame::kYPlane);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < y_rows; ++i) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(y_plane, y, y_row_bytes);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_plane += frame->stride(VideoFrame::kYPlane);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the U and V planes.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* u_plane = frame->data(VideoFrame::kUPlane);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* v_plane = frame->data(VideoFrame::kVPlane);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int uv_rows = frame->rows(VideoFrame::kUPlane);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int u_row_bytes = frame->row_bytes(VideoFrame::kUPlane);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int v_row_bytes = frame->row_bytes(VideoFrame::kVPlane);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < uv_rows; ++i) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(u_plane, u, u_row_bytes);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(v_plane, v, v_row_bytes);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u_plane += frame->stride(VideoFrame::kUPlane);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v_plane += frame->stride(VideoFrame::kVPlane);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid FillYUVA(VideoFrame* frame, uint8 y, uint8 u, uint8 v, uint8 a) {
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Fill Y, U and V planes.
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FillYUV(frame, y, u, v);
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Fill the A plane.
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint8* a_plane = frame->data(VideoFrame::kAPlane);
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int a_rows = frame->rows(VideoFrame::kAPlane);
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int a_row_bytes = frame->row_bytes(VideoFrame::kAPlane);
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (int i = 0; i < a_rows; ++i) {
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    memset(a_plane, a, a_row_bytes);
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    a_plane += frame->stride(VideoFrame::kAPlane);
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void LetterboxPlane(VideoFrame* frame,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           int plane,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const gfx::Rect& view_area,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           uint8 fill_byte) {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8* ptr = frame->data(plane);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int rows = frame->rows(plane);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int row_bytes = frame->row_bytes(plane);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int stride = frame->stride(plane);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_GE(stride, row_bytes);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_GE(view_area.x(), 0);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_GE(view_area.y(), 0);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_LE(view_area.right(), row_bytes);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_LE(view_area.bottom(), rows);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int y = 0;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; y < view_area.y(); y++) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memset(ptr, fill_byte, row_bytes);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ptr += stride;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (view_area.width() < row_bytes) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (; y < view_area.bottom(); y++) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (view_area.x() > 0) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memset(ptr, fill_byte, view_area.x());
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (view_area.right() < row_bytes) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memset(ptr + view_area.right(),
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               fill_byte,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               row_bytes - view_area.right());
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ptr += stride;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    y += view_area.height();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ptr += stride * view_area.height();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; y < rows; y++) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memset(ptr, fill_byte, row_bytes);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ptr += stride;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LetterboxYUV(VideoFrame* frame, const gfx::Rect& view_area) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!(view_area.x() & 1));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!(view_area.y() & 1));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!(view_area.width() & 1));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!(view_area.height() & 1));
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(frame->format() == VideoFrame::YV12 ||
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         frame->format() == VideoFrame::YV12J ||
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         frame->format() == VideoFrame::I420);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect half_view_area(view_area.x() / 2,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           view_area.y() / 2,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           view_area.width() / 2,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           view_area.height() / 2);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LetterboxPlane(frame, VideoFrame::kUPlane, half_view_area, 0x80);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LetterboxPlane(frame, VideoFrame::kVPlane, half_view_area, 0x80);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RotatePlaneByPixels(
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const uint8* src,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint8* dest,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int width,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int height,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int rotation,  // Clockwise.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool flip_vert,
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool flip_horiz) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK((width > 0) && (height > 0) &&
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ((width & 1) == 0) && ((height & 1) == 0) &&
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         (rotation >= 0) && (rotation < 360) && (rotation % 90 == 0));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Consolidate cases. Only 0 and 90 are left.
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rotation == 180 || rotation == 270) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rotation -= 180;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flip_vert = !flip_vert;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flip_horiz = !flip_horiz;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_rows = height;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_cols = width;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int src_stride = width;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // During pixel copying, the corresponding incremental of dest pointer
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // when src pointer moves to next row.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int dest_row_step = width;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // During pixel copying, the corresponding incremental of dest pointer
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // when src pointer moves to next column.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int dest_col_step = 1;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rotation == 0) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (flip_horiz) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Use pixel copying.
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dest_col_step = -1;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (flip_vert) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Rotation 180.
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest_row_step = -width;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += height * width - 1;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += width - 1;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (flip_vert) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Fast copy by rows.
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += width * (height - 1);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int row = 0; row < height; ++row) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          memcpy(dest, src, width);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          src += width;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          dest -= width;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memcpy(dest, src, width * height);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (rotation == 90) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int offset;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (width > height) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      offset = (width - height) / 2;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      src += offset;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_rows = num_cols = height;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      offset = (height - width) / 2;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      src += width * offset;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_rows = num_cols = width;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest_col_step = (flip_vert ? -width : width);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest_row_step = (flip_horiz ? 1 : -1);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (flip_horiz) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (flip_vert) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += (width > height ? width * (height - 1) + offset :
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  width * (height - offset - 1));
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += (width > height ? offset : width * offset);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (flip_vert) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += (width > height ?  width * height - offset - 1 :
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   width * (height - offset) - 1);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dest += (width > height ? width - offset - 1 :
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  width * (offset + 1) - 1);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Copy pixels.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int row = 0; row < num_rows; ++row) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const uint8* src_ptr = src;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint8* dest_ptr = dest;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int col = 0; col < num_cols; ++col) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *dest_ptr = *src_ptr++;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dest_ptr += dest_col_step;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    src += src_stride;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest += dest_row_step;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect ComputeLetterboxRegion(const gfx::Rect& bounds,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const gfx::Size& content) {
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If |content| has an undefined aspect ratio, let's not try to divide by
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // zero.
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (content.IsEmpty())
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return gfx::Rect();
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 x = static_cast<int64>(content.width()) * bounds.height();
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 y = static_cast<int64>(content.height()) * bounds.width();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size letterbox(bounds.width(), bounds.height());
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (y < x)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    letterbox.set_height(static_cast<int>(y / content.width()));
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    letterbox.set_width(static_cast<int>(x / content.height()));
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect result = bounds;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.ClampToCenteredSize(letterbox);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CopyRGBToVideoFrame(const uint8* source,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         int stride,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const gfx::Rect& region_in_frame,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         VideoFrame* frame) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kY = VideoFrame::kYPlane;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kU = VideoFrame::kUPlane;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kV = VideoFrame::kVPlane;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(frame->stride(kU), frame->stride(kV));
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int uv_stride = frame->stride(kU);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (region_in_frame != gfx::Rect(frame->coded_size())) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LetterboxYUV(frame, region_in_frame);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int y_offset = region_in_frame.x()
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     + (region_in_frame.y() * frame->stride(kY));
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int uv_offset = region_in_frame.x() / 2
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      + (region_in_frame.y() / 2 * uv_stride);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConvertRGB32ToYUV(source,
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    frame->data(kY) + y_offset,
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    frame->data(kU) + uv_offset,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    frame->data(kV) + uv_offset,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    region_in_frame.width(),
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    region_in_frame.height(),
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    stride,
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    frame->stride(kY),
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    uv_stride);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
324