content/media/fmp4/demuxer/video_util.cc

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "mp4_demuxer/video_util.h"
michael@0 6
michael@0 7 #include <cmath>
michael@0 8
michael@0 9 namespace mp4_demuxer {
michael@0 10
michael@0 11 IntSize GetNaturalSize(const IntSize& visible_size,
michael@0 12 int aspect_ratio_numerator,
michael@0 13 int aspect_ratio_denominator) {
michael@0 14 if (aspect_ratio_denominator == 0 ||
michael@0 15 aspect_ratio_numerator < 0 ||
michael@0 16 aspect_ratio_denominator < 0)
michael@0 17 return IntSize();
michael@0 18
michael@0 19 double aspect_ratio = aspect_ratio_numerator /
michael@0 20 static_cast<double>(aspect_ratio_denominator);
michael@0 21
michael@0 22 int width = floor(visible_size.width() * aspect_ratio + 0.5);
michael@0 23 int height = visible_size.height();
michael@0 24
michael@0 25 // An even width makes things easier for YV12 and appears to be the behavior
michael@0 26 // expected by WebKit layout tests.
michael@0 27 return IntSize(width & ~1, height);
michael@0 28 }
michael@0 29
michael@0 30 /*
michael@0 31 void CopyPlane(size_t plane, const uint8_t* source, int stride, int rows,
michael@0 32 VideoFrame* frame) {
michael@0 33 uint8_t* dest = frame->data(plane);
michael@0 34 int dest_stride = frame->stride(plane);
michael@0 35
michael@0 36 // Clamp in case source frame has smaller stride.
michael@0 37 int bytes_to_copy_per_row = std::min(frame->row_bytes(plane), stride);
michael@0 38
michael@0 39 // Clamp in case source frame has smaller height.
michael@0 40 int rows_to_copy = std::min(frame->rows(plane), rows);
michael@0 41
michael@0 42 // Copy!
michael@0 43 for (int row = 0; row < rows_to_copy; ++row) {
michael@0 44 memcpy(dest, source, bytes_to_copy_per_row);
michael@0 45 source += stride;
michael@0 46 dest += dest_stride;
michael@0 47 }
michael@0 48 }
michael@0 49
michael@0 50 void CopyYPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
michael@0 51 CopyPlane(VideoFrame::kYPlane, source, stride, rows, frame);
michael@0 52 }
michael@0 53
michael@0 54 void CopyUPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
michael@0 55 CopyPlane(VideoFrame::kUPlane, source, stride, rows, frame);
michael@0 56 }
michael@0 57
michael@0 58 void CopyVPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
michael@0 59 CopyPlane(VideoFrame::kVPlane, source, stride, rows, frame);
michael@0 60 }
michael@0 61
michael@0 62 void CopyAPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
michael@0 63 CopyPlane(VideoFrame::kAPlane, source, stride, rows, frame);
michael@0 64 }
michael@0 65
michael@0 66 void MakeOpaqueAPlane(int stride, int rows, VideoFrame* frame) {
michael@0 67 int rows_to_clear = std::min(frame->rows(VideoFrame::kAPlane), rows);
michael@0 68 memset(frame->data(VideoFrame::kAPlane), 255,
michael@0 69 frame->stride(VideoFrame::kAPlane) * rows_to_clear);
michael@0 70 }
michael@0 71
michael@0 72 void FillYUV(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
michael@0 73 // Fill the Y plane.
michael@0 74 uint8_t* y_plane = frame->data(VideoFrame::kYPlane);
michael@0 75 int y_rows = frame->rows(VideoFrame::kYPlane);
michael@0 76 int y_row_bytes = frame->row_bytes(VideoFrame::kYPlane);
michael@0 77 for (int i = 0; i < y_rows; ++i) {
michael@0 78 memset(y_plane, y, y_row_bytes);
michael@0 79 y_plane += frame->stride(VideoFrame::kYPlane);
michael@0 80 }
michael@0 81
michael@0 82 // Fill the U and V planes.
michael@0 83 uint8_t* u_plane = frame->data(VideoFrame::kUPlane);
michael@0 84 uint8_t* v_plane = frame->data(VideoFrame::kVPlane);
michael@0 85 int uv_rows = frame->rows(VideoFrame::kUPlane);
michael@0 86 int u_row_bytes = frame->row_bytes(VideoFrame::kUPlane);
michael@0 87 int v_row_bytes = frame->row_bytes(VideoFrame::kVPlane);
michael@0 88 for (int i = 0; i < uv_rows; ++i) {
michael@0 89 memset(u_plane, u, u_row_bytes);
michael@0 90 memset(v_plane, v, v_row_bytes);
michael@0 91 u_plane += frame->stride(VideoFrame::kUPlane);
michael@0 92 v_plane += frame->stride(VideoFrame::kVPlane);
michael@0 93 }
michael@0 94 }
michael@0 95
michael@0 96 static void LetterboxPlane(VideoFrame* frame,
michael@0 97 int plane,
michael@0 98 const gfx::Rect& view_area,
michael@0 99 uint8_t fill_byte) {
michael@0 100 uint8_t* ptr = frame->data(plane);
michael@0 101 const int rows = frame->rows(plane);
michael@0 102 const int row_bytes = frame->row_bytes(plane);
michael@0 103 const int stride = frame->stride(plane);
michael@0 104
michael@0 105 CHECK_GE(stride, row_bytes);
michael@0 106 CHECK_GE(view_area.x(), 0);
michael@0 107 CHECK_GE(view_area.y(), 0);
michael@0 108 CHECK_LE(view_area.right(), row_bytes);
michael@0 109 CHECK_LE(view_area.bottom(), rows);
michael@0 110
michael@0 111 int y = 0;
michael@0 112 for (; y < view_area.y(); y++) {
michael@0 113 memset(ptr, fill_byte, row_bytes);
michael@0 114 ptr += stride;
michael@0 115 }
michael@0 116 if (view_area.width() < row_bytes) {
michael@0 117 for (; y < view_area.bottom(); y++) {
michael@0 118 if (view_area.x() > 0) {
michael@0 119 memset(ptr, fill_byte, view_area.x());
michael@0 120 }
michael@0 121 if (view_area.right() < row_bytes) {
michael@0 122 memset(ptr + view_area.right(),
michael@0 123 fill_byte,
michael@0 124 row_bytes - view_area.right());
michael@0 125 }
michael@0 126 ptr += stride;
michael@0 127 }
michael@0 128 } else {
michael@0 129 y += view_area.height();
michael@0 130 ptr += stride * view_area.height();
michael@0 131 }
michael@0 132 for (; y < rows; y++) {
michael@0 133 memset(ptr, fill_byte, row_bytes);
michael@0 134 ptr += stride;
michael@0 135 }
michael@0 136 }
michael@0 137
michael@0 138 void LetterboxYUV(VideoFrame* frame, const gfx::Rect& view_area) {
michael@0 139 DCHECK(!(view_area.x() & 1));
michael@0 140 DCHECK(!(view_area.y() & 1));
michael@0 141 DCHECK(!(view_area.width() & 1));
michael@0 142 DCHECK(!(view_area.height() & 1));
michael@0 143 DCHECK_EQ(frame->format(), VideoFrame::YV12);
michael@0 144 LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00);
michael@0 145 gfx::Rect half_view_area(view_area.x() / 2,
michael@0 146 view_area.y() / 2,
michael@0 147 view_area.width() / 2,
michael@0 148 view_area.height() / 2);
michael@0 149 LetterboxPlane(frame, VideoFrame::kUPlane, half_view_area, 0x80);
michael@0 150 LetterboxPlane(frame, VideoFrame::kVPlane, half_view_area, 0x80);
michael@0 151 }
michael@0 152
michael@0 153 void RotatePlaneByPixels(
michael@0 154 const uint8_t* src,
michael@0 155 uint8_t* dest,
michael@0 156 int width,
michael@0 157 int height,
michael@0 158 int rotation, // Clockwise.
michael@0 159 bool flip_vert,
michael@0 160 bool flip_horiz) {
michael@0 161 DCHECK((width > 0) && (height > 0) &&
michael@0 162 ((width & 1) == 0) && ((height & 1) == 0) &&
michael@0 163 (rotation >= 0) && (rotation < 360) && (rotation % 90 == 0));
michael@0 164
michael@0 165 // Consolidate cases. Only 0 and 90 are left.
michael@0 166 if (rotation == 180 || rotation == 270) {
michael@0 167 rotation -= 180;
michael@0 168 flip_vert = !flip_vert;
michael@0 169 flip_horiz = !flip_horiz;
michael@0 170 }
michael@0 171
michael@0 172 int num_rows = height;
michael@0 173 int num_cols = width;
michael@0 174 int src_stride = width;
michael@0 175 // During pixel copying, the corresponding incremental of dest pointer
michael@0 176 // when src pointer moves to next row.
michael@0 177 int dest_row_step = width;
michael@0 178 // During pixel copying, the corresponding incremental of dest pointer
michael@0 179 // when src pointer moves to next column.
michael@0 180 int dest_col_step = 1;
michael@0 181
michael@0 182 if (rotation == 0) {
michael@0 183 if (flip_horiz) {
michael@0 184 // Use pixel copying.
michael@0 185 dest_col_step = -1;
michael@0 186 if (flip_vert) {
michael@0 187 // Rotation 180.
michael@0 188 dest_row_step = -width;
michael@0 189 dest += height * width - 1;
michael@0 190 } else {
michael@0 191 dest += width - 1;
michael@0 192 }
michael@0 193 } else {
michael@0 194 if (flip_vert) {
michael@0 195 // Fast copy by rows.
michael@0 196 dest += width * (height - 1);
michael@0 197 for (int row = 0; row < height; ++row) {
michael@0 198 memcpy(dest, src, width);
michael@0 199 src += width;
michael@0 200 dest -= width;
michael@0 201 }
michael@0 202 } else {
michael@0 203 memcpy(dest, src, width * height);
michael@0 204 }
michael@0 205 return;
michael@0 206 }
michael@0 207 } else if (rotation == 90) {
michael@0 208 int offset;
michael@0 209 if (width > height) {
michael@0 210 offset = (width - height) / 2;
michael@0 211 src += offset;
michael@0 212 num_rows = num_cols = height;
michael@0 213 } else {
michael@0 214 offset = (height - width) / 2;
michael@0 215 src += width * offset;
michael@0 216 num_rows = num_cols = width;
michael@0 217 }
michael@0 218
michael@0 219 dest_col_step = (flip_vert ? -width : width);
michael@0 220 dest_row_step = (flip_horiz ? 1 : -1);
michael@0 221 if (flip_horiz) {
michael@0 222 if (flip_vert) {
michael@0 223 dest += (width > height ? width * (height - 1) + offset :
michael@0 224 width * (height - offset - 1));
michael@0 225 } else {
michael@0 226 dest += (width > height ? offset : width * offset);
michael@0 227 }
michael@0 228 } else {
michael@0 229 if (flip_vert) {
michael@0 230 dest += (width > height ? width * height - offset - 1 :
michael@0 231 width * (height - offset) - 1);
michael@0 232 } else {
michael@0 233 dest += (width > height ? width - offset - 1 :
michael@0 234 width * (offset + 1) - 1);
michael@0 235 }
michael@0 236 }
michael@0 237 } else {
michael@0 238 NOTREACHED();
michael@0 239 }
michael@0 240
michael@0 241 // Copy pixels.
michael@0 242 for (int row = 0; row < num_rows; ++row) {
michael@0 243 const uint8_t* src_ptr = src;
michael@0 244 uint8_t* dest_ptr = dest;
michael@0 245 for (int col = 0; col < num_cols; ++col) {
michael@0 246 *dest_ptr = *src_ptr++;
michael@0 247 dest_ptr += dest_col_step;
michael@0 248 }
michael@0 249 src += src_stride;
michael@0 250 dest += dest_row_step;
michael@0 251 }
michael@0 252 }
michael@0 253
michael@0 254 gfx::Rect ComputeLetterboxRegion(const gfx::Rect& bounds,
michael@0 255 const IntSize& content) {
michael@0 256 int64_t x = static_cast<int64_t>(content.width()) * bounds.height();
michael@0 257 int64_t y = static_cast<int64_t>(content.height()) * bounds.width();
michael@0 258
michael@0 259 IntSize letterbox(bounds.width(), bounds.height());
michael@0 260 if (y < x)
michael@0 261 letterbox.set_height(static_cast<int>(y / content.width()));
michael@0 262 else
michael@0 263 letterbox.set_width(static_cast<int>(x / content.height()));
michael@0 264 gfx::Rect result = bounds;
michael@0 265 result.ClampToCenteredSize(letterbox);
michael@0 266 return result;
michael@0 267 }
michael@0 268
michael@0 269 void CopyRGBToVideoFrame(const uint8_t* source,
michael@0 270 int stride,
michael@0 271 const gfx::Rect& region_in_frame,
michael@0 272 VideoFrame* frame) {
michael@0 273 const int kY = VideoFrame::kYPlane;
michael@0 274 const int kU = VideoFrame::kUPlane;
michael@0 275 const int kV = VideoFrame::kVPlane;
michael@0 276 CHECK_EQ(frame->stride(kU), frame->stride(kV));
michael@0 277 const int uv_stride = frame->stride(kU);
michael@0 278
michael@0 279 if (region_in_frame != gfx::Rect(frame->coded_size())) {
michael@0 280 LetterboxYUV(frame, region_in_frame);
michael@0 281 }
michael@0 282
michael@0 283 const int y_offset = region_in_frame.x()
michael@0 284 + (region_in_frame.y() * frame->stride(kY));
michael@0 285 const int uv_offset = region_in_frame.x() / 2
michael@0 286 + (region_in_frame.y() / 2 * uv_stride);
michael@0 287
michael@0 288 ConvertRGB32ToYUV(source,
michael@0 289 frame->data(kY) + y_offset,
michael@0 290 frame->data(kU) + uv_offset,
michael@0 291 frame->data(kV) + uv_offset,
michael@0 292 region_in_frame.width(),
michael@0 293 region_in_frame.height(),
michael@0 294 stride,
michael@0 295 frame->stride(kY),
michael@0 296 uv_stride);
michael@0 297 }
michael@0 298 */
michael@0 299 } // namespace mp4_demuxer

mercurial