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