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