OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "media/base/video_frame.h" | 5 #include "media/base/video_frame.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 scoped_refptr<VideoFrame> VideoFrame::CreateFrame( | 21 scoped_refptr<VideoFrame> VideoFrame::CreateFrame( |
22 VideoFrame::Format format, | 22 VideoFrame::Format format, |
23 const gfx::Size& coded_size, | 23 const gfx::Size& coded_size, |
24 const gfx::Rect& visible_rect, | 24 const gfx::Rect& visible_rect, |
25 const gfx::Size& natural_size, | 25 const gfx::Size& natural_size, |
26 base::TimeDelta timestamp) { | 26 base::TimeDelta timestamp) { |
27 DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); | 27 DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); |
28 scoped_refptr<VideoFrame> frame(new VideoFrame( | 28 scoped_refptr<VideoFrame> frame(new VideoFrame( |
29 format, coded_size, visible_rect, natural_size, timestamp)); | 29 format, coded_size, visible_rect, natural_size, timestamp)); |
30 switch (format) { | 30 switch (format) { |
31 case VideoFrame::RGB32: | |
32 frame->AllocateRGB(4u); | |
33 break; | |
34 case VideoFrame::YV12: | 31 case VideoFrame::YV12: |
35 case VideoFrame::YV12A: | 32 case VideoFrame::YV12A: |
36 case VideoFrame::YV16: | 33 case VideoFrame::YV16: |
37 case VideoFrame::I420: | 34 case VideoFrame::I420: |
38 frame->AllocateYUV(); | 35 frame->AllocateYUV(); |
39 break; | 36 break; |
40 default: | 37 default: |
41 LOG(FATAL) << "Unsupported frame format: " << format; | 38 LOG(FATAL) << "Unsupported frame format: " << format; |
42 } | 39 } |
43 return frame; | 40 return frame; |
44 } | 41 } |
45 | 42 |
46 // static | 43 // static |
47 std::string VideoFrame::FormatToString(VideoFrame::Format format) { | 44 std::string VideoFrame::FormatToString(VideoFrame::Format format) { |
48 switch (format) { | 45 switch (format) { |
49 case VideoFrame::UNKNOWN: | 46 case VideoFrame::UNKNOWN: |
50 return "UNKNOWN"; | 47 return "UNKNOWN"; |
51 case VideoFrame::RGB32: | |
52 return "RGB32"; | |
53 case VideoFrame::YV12: | 48 case VideoFrame::YV12: |
54 return "YV12"; | 49 return "YV12"; |
55 case VideoFrame::YV16: | 50 case VideoFrame::YV16: |
56 return "YV16"; | 51 return "YV16"; |
57 case VideoFrame::EMPTY: | 52 case VideoFrame::EMPTY: |
58 return "EMPTY"; | 53 return "EMPTY"; |
59 case VideoFrame::I420: | 54 case VideoFrame::I420: |
60 return "I420"; | 55 return "I420"; |
61 case VideoFrame::NATIVE_TEXTURE: | 56 case VideoFrame::NATIVE_TEXTURE: |
62 return "NATIVE_TEXTURE"; | 57 return "NATIVE_TEXTURE"; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 #endif | 219 #endif |
225 | 220 |
226 // static | 221 // static |
227 size_t VideoFrame::NumPlanes(Format format) { | 222 size_t VideoFrame::NumPlanes(Format format) { |
228 switch (format) { | 223 switch (format) { |
229 case VideoFrame::NATIVE_TEXTURE: | 224 case VideoFrame::NATIVE_TEXTURE: |
230 #if defined(GOOGLE_TV) | 225 #if defined(GOOGLE_TV) |
231 case VideoFrame::HOLE: | 226 case VideoFrame::HOLE: |
232 #endif | 227 #endif |
233 return 0; | 228 return 0; |
234 case VideoFrame::RGB32: | |
235 return 1; | |
236 case VideoFrame::YV12: | 229 case VideoFrame::YV12: |
237 case VideoFrame::YV16: | 230 case VideoFrame::YV16: |
238 case VideoFrame::I420: | 231 case VideoFrame::I420: |
239 return 3; | 232 return 3; |
240 case VideoFrame::YV12A: | 233 case VideoFrame::YV12A: |
241 return 4; | 234 return 4; |
242 case VideoFrame::EMPTY: | 235 case VideoFrame::EMPTY: |
243 case VideoFrame::UNKNOWN: | 236 case VideoFrame::UNKNOWN: |
244 break; | 237 break; |
245 } | 238 } |
246 NOTREACHED() << "Unsupported video frame format: " << format; | 239 NOTREACHED() << "Unsupported video frame format: " << format; |
247 return 0; | 240 return 0; |
248 } | 241 } |
249 | 242 |
250 static inline size_t RoundUp(size_t value, size_t alignment) { | 243 static inline size_t RoundUp(size_t value, size_t alignment) { |
251 // Check that |alignment| is a power of 2. | 244 // Check that |alignment| is a power of 2. |
252 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); | 245 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); |
253 return ((value + (alignment - 1)) & ~(alignment-1)); | 246 return ((value + (alignment - 1)) & ~(alignment-1)); |
254 } | 247 } |
255 | 248 |
256 // static | 249 // static |
257 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) { | 250 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) { |
258 switch (format) { | 251 switch (format) { |
259 case VideoFrame::RGB32: | |
260 return coded_size.GetArea() * 4; | |
261 case VideoFrame::YV12: | 252 case VideoFrame::YV12: |
262 case VideoFrame::I420: { | 253 case VideoFrame::I420: { |
263 const size_t rounded_size = | 254 const size_t rounded_size = |
264 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); | 255 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); |
265 return rounded_size * 3 / 2; | 256 return rounded_size * 3 / 2; |
266 } | 257 } |
267 case VideoFrame::YV12A: { | 258 case VideoFrame::YV12A: { |
268 const size_t rounded_size = | 259 const size_t rounded_size = |
269 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); | 260 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); |
270 return rounded_size * 5 / 2; | 261 return rounded_size * 5 / 2; |
271 } | 262 } |
272 case VideoFrame::YV16: { | 263 case VideoFrame::YV16: { |
273 const size_t rounded_size = | 264 const size_t rounded_size = |
274 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); | 265 RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2); |
275 return rounded_size * 2; | 266 return rounded_size * 2; |
276 } | 267 } |
277 case VideoFrame::UNKNOWN: | 268 case VideoFrame::UNKNOWN: |
278 case VideoFrame::EMPTY: | 269 case VideoFrame::EMPTY: |
279 case VideoFrame::NATIVE_TEXTURE: | 270 case VideoFrame::NATIVE_TEXTURE: |
280 #if defined(GOOGLE_TV) | 271 #if defined(GOOGLE_TV) |
281 case VideoFrame::HOLE: | 272 case VideoFrame::HOLE: |
282 #endif | 273 #endif |
283 break; | 274 break; |
284 } | 275 } |
285 NOTREACHED() << "Unsupported video frame format: " << format; | 276 NOTREACHED() << "Unsupported video frame format: " << format; |
286 return 0; | 277 return 0; |
287 } | 278 } |
288 | 279 |
289 // Release data allocated by AllocateRGB() or AllocateYUV(). | 280 // Release data allocated by AllocateYUV(). |
290 static void ReleaseData(uint8* data) { | 281 static void ReleaseData(uint8* data) { |
291 DCHECK(data); | 282 DCHECK(data); |
292 base::AlignedFree(data); | 283 base::AlignedFree(data); |
293 } | 284 } |
294 | 285 |
295 void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { | |
296 // Round up to align at least at a 16-byte boundary for each row. | |
297 // This is sufficient for MMX and SSE2 reads (movq/movdqa). | |
298 size_t bytes_per_row = RoundUp(coded_size_.width(), | |
299 kFrameSizeAlignment) * bytes_per_pixel; | |
300 size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment); | |
301 strides_[VideoFrame::kRGBPlane] = bytes_per_row; | |
302 data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( | |
303 base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, | |
304 kFrameAddressAlignment)); | |
305 no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); | |
306 DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); | |
307 COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); | |
308 } | |
309 | |
310 void VideoFrame::AllocateYUV() { | 286 void VideoFrame::AllocateYUV() { |
311 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || | 287 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || |
312 format_ == VideoFrame::YV12A || format_ == VideoFrame::I420); | 288 format_ == VideoFrame::YV12A || format_ == VideoFrame::I420); |
313 // Align Y rows at least at 16 byte boundaries. The stride for both | 289 // Align Y rows at least at 16 byte boundaries. The stride for both |
314 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for | 290 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for |
315 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in | 291 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in |
316 // the case of YV12 the strides are identical for the same width surface, but | 292 // the case of YV12 the strides are identical for the same width surface, but |
317 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as | 293 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as |
318 // YV16. We also round the height of the surface allocated to be an even | 294 // YV16. We also round the height of the surface allocated to be an even |
319 // number to avoid any potential of faulting by code that attempts to access | 295 // number to avoid any potential of faulting by code that attempts to access |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 | 363 |
388 int VideoFrame::stride(size_t plane) const { | 364 int VideoFrame::stride(size_t plane) const { |
389 DCHECK(IsValidPlane(plane)); | 365 DCHECK(IsValidPlane(plane)); |
390 return strides_[plane]; | 366 return strides_[plane]; |
391 } | 367 } |
392 | 368 |
393 int VideoFrame::row_bytes(size_t plane) const { | 369 int VideoFrame::row_bytes(size_t plane) const { |
394 DCHECK(IsValidPlane(plane)); | 370 DCHECK(IsValidPlane(plane)); |
395 int width = coded_size_.width(); | 371 int width = coded_size_.width(); |
396 switch (format_) { | 372 switch (format_) { |
397 // 32bpp. | |
398 case RGB32: | |
399 return width * 4; | |
400 | |
401 // Planar, 8bpp. | 373 // Planar, 8bpp. |
402 case YV12A: | 374 case YV12A: |
403 if (plane == kAPlane) | 375 if (plane == kAPlane) |
404 return width; | 376 return width; |
405 // Fallthrough. | 377 // Fallthrough. |
406 case YV12: | 378 case YV12: |
407 case YV16: | 379 case YV16: |
408 case I420: | 380 case I420: |
409 if (plane == kYPlane) | 381 if (plane == kYPlane) |
410 return width; | 382 return width; |
411 return RoundUp(width, 2) / 2; | 383 return RoundUp(width, 2) / 2; |
412 | 384 |
413 default: | 385 default: |
414 break; | 386 break; |
415 } | 387 } |
416 | 388 |
417 // Intentionally leave out non-production formats. | 389 // Intentionally leave out non-production formats. |
418 NOTREACHED() << "Unsupported video frame format: " << format_; | 390 NOTREACHED() << "Unsupported video frame format: " << format_; |
419 return 0; | 391 return 0; |
420 } | 392 } |
421 | 393 |
422 int VideoFrame::rows(size_t plane) const { | 394 int VideoFrame::rows(size_t plane) const { |
423 DCHECK(IsValidPlane(plane)); | 395 DCHECK(IsValidPlane(plane)); |
424 int height = coded_size_.height(); | 396 int height = coded_size_.height(); |
425 switch (format_) { | 397 switch (format_) { |
426 case RGB32: | |
427 case YV16: | 398 case YV16: |
428 return height; | 399 return height; |
429 | 400 |
430 case YV12A: | 401 case YV12A: |
431 if (plane == kAPlane) | 402 if (plane == kAPlane) |
432 return height; | 403 return height; |
433 // Fallthrough. | 404 // Fallthrough. |
434 case YV12: | 405 case YV12: |
435 case I420: | 406 case I420: |
436 if (plane == kYPlane) | 407 if (plane == kYPlane) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 : mailbox_(mailbox), | 460 : mailbox_(mailbox), |
490 sync_point_(sync_point), | 461 sync_point_(sync_point), |
491 release_callback_(release_callback) {} | 462 release_callback_(release_callback) {} |
492 | 463 |
493 VideoFrame::MailboxHolder::~MailboxHolder() { | 464 VideoFrame::MailboxHolder::~MailboxHolder() { |
494 if (!release_callback_.is_null()) | 465 if (!release_callback_.is_null()) |
495 release_callback_.Run(sync_point_); | 466 release_callback_.Run(sync_point_); |
496 } | 467 } |
497 | 468 |
498 } // namespace media | 469 } // namespace media |
OLD | NEW |