Manual fixups in drive code for scoped_refptr operator T* removal.
[chromium-blink-merge.git] / media / base / video_frame.cc
blob70649543578433b607021c48a395d69a26185bfc
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 "media/base/video_frame.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/logging.h"
12 #include "base/memory/aligned_memory.h"
13 #include "base/strings/string_piece.h"
14 #include "gpu/command_buffer/common/mailbox_holder.h"
15 #include "media/base/limits.h"
16 #include "media/base/video_util.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
19 namespace media {
21 static inline size_t RoundUp(size_t value, size_t alignment) {
22 // Check that |alignment| is a power of 2.
23 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
24 return ((value + (alignment - 1)) & ~(alignment - 1));
27 // Rounds up |coded_size| if necessary for |format|.
28 static gfx::Size AdjustCodedSize(VideoFrame::Format format,
29 const gfx::Size& coded_size) {
30 gfx::Size new_coded_size(coded_size);
31 switch (format) {
32 case VideoFrame::YV12:
33 case VideoFrame::YV12A:
34 case VideoFrame::I420:
35 case VideoFrame::YV12J:
36 new_coded_size.set_height(RoundUp(new_coded_size.height(), 2));
37 // Fallthrough.
38 case VideoFrame::YV16:
39 new_coded_size.set_width(RoundUp(new_coded_size.width(), 2));
40 break;
41 default:
42 break;
44 return new_coded_size;
47 // static
48 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
49 VideoFrame::Format format,
50 const gfx::Size& coded_size,
51 const gfx::Rect& visible_rect,
52 const gfx::Size& natural_size,
53 base::TimeDelta timestamp) {
54 DCHECK(format != VideoFrame::UNKNOWN &&
55 format != VideoFrame::NV12 &&
56 format != VideoFrame::NATIVE_TEXTURE);
57 #if defined(VIDEO_HOLE)
58 DCHECK(format != VideoFrame::HOLE);
59 #endif // defined(VIDEO_HOLE)
61 // Since we're creating a new YUV frame (and allocating memory for it
62 // ourselves), we can pad the requested |coded_size| if necessary if the
63 // request does not line up on sample boundaries.
64 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
65 DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
67 scoped_refptr<VideoFrame> frame(
68 new VideoFrame(format,
69 new_coded_size,
70 visible_rect,
71 natural_size,
72 scoped_ptr<gpu::MailboxHolder>(),
73 timestamp,
74 false));
75 frame->AllocateYUV();
76 return frame;
79 // static
80 std::string VideoFrame::FormatToString(VideoFrame::Format format) {
81 switch (format) {
82 case VideoFrame::UNKNOWN:
83 return "UNKNOWN";
84 case VideoFrame::YV12:
85 return "YV12";
86 case VideoFrame::YV16:
87 return "YV16";
88 case VideoFrame::I420:
89 return "I420";
90 case VideoFrame::NATIVE_TEXTURE:
91 return "NATIVE_TEXTURE";
92 #if defined(VIDEO_HOLE)
93 case VideoFrame::HOLE:
94 return "HOLE";
95 #endif // defined(VIDEO_HOLE)
96 case VideoFrame::YV12A:
97 return "YV12A";
98 case VideoFrame::YV12J:
99 return "YV12J";
100 case VideoFrame::NV12:
101 return "NV12";
102 case VideoFrame::YV24:
103 return "YV24";
105 NOTREACHED() << "Invalid videoframe format provided: " << format;
106 return "";
109 // static
110 bool VideoFrame::IsValidConfig(VideoFrame::Format format,
111 const gfx::Size& coded_size,
112 const gfx::Rect& visible_rect,
113 const gfx::Size& natural_size) {
114 // Check maximum limits for all formats.
115 if (coded_size.GetArea() > limits::kMaxCanvas ||
116 coded_size.width() > limits::kMaxDimension ||
117 coded_size.height() > limits::kMaxDimension ||
118 visible_rect.x() < 0 || visible_rect.y() < 0 ||
119 visible_rect.right() > coded_size.width() ||
120 visible_rect.bottom() > coded_size.height() ||
121 natural_size.GetArea() > limits::kMaxCanvas ||
122 natural_size.width() > limits::kMaxDimension ||
123 natural_size.height() > limits::kMaxDimension)
124 return false;
126 // Check format-specific width/height requirements.
127 switch (format) {
128 case VideoFrame::UNKNOWN:
129 return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
130 natural_size.IsEmpty());
131 case VideoFrame::YV24:
132 break;
133 case VideoFrame::YV12:
134 case VideoFrame::YV12J:
135 case VideoFrame::I420:
136 case VideoFrame::YV12A:
137 case VideoFrame::NV12:
138 // Subsampled YUV formats have width/height requirements.
139 if (static_cast<size_t>(coded_size.height()) <
140 RoundUp(visible_rect.bottom(), 2))
141 return false;
142 // Fallthrough.
143 case VideoFrame::YV16:
144 if (static_cast<size_t>(coded_size.width()) <
145 RoundUp(visible_rect.right(), 2))
146 return false;
147 break;
148 case VideoFrame::NATIVE_TEXTURE:
149 #if defined(VIDEO_HOLE)
150 case VideoFrame::HOLE:
151 #endif // defined(VIDEO_HOLE)
152 // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
153 // allowed to skip the below check and be empty.
154 return true;
157 // Check that software-allocated buffer formats are not empty.
158 return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
159 !natural_size.IsEmpty());
162 // static
163 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
164 scoped_ptr<gpu::MailboxHolder> mailbox_holder,
165 const ReleaseMailboxCB& mailbox_holder_release_cb,
166 const gfx::Size& coded_size,
167 const gfx::Rect& visible_rect,
168 const gfx::Size& natural_size,
169 base::TimeDelta timestamp,
170 const ReadPixelsCB& read_pixels_cb) {
171 scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE,
172 coded_size,
173 visible_rect,
174 natural_size,
175 mailbox_holder.Pass(),
176 timestamp,
177 false));
178 frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb;
179 frame->read_pixels_cb_ = read_pixels_cb;
181 return frame;
184 void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
185 DCHECK_EQ(format_, NATIVE_TEXTURE);
186 if (!read_pixels_cb_.is_null())
187 read_pixels_cb_.Run(pixels);
190 // static
191 scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
192 Format format,
193 const gfx::Size& coded_size,
194 const gfx::Rect& visible_rect,
195 const gfx::Size& natural_size,
196 uint8* data,
197 size_t data_size,
198 base::SharedMemoryHandle handle,
199 base::TimeDelta timestamp,
200 const base::Closure& no_longer_needed_cb) {
201 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
203 if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size))
204 return NULL;
205 if (data_size < AllocationSize(format, new_coded_size))
206 return NULL;
208 switch (format) {
209 case VideoFrame::I420: {
210 scoped_refptr<VideoFrame> frame(
211 new VideoFrame(format,
212 new_coded_size,
213 visible_rect,
214 natural_size,
215 scoped_ptr<gpu::MailboxHolder>(),
216 timestamp,
217 false));
218 frame->shared_memory_handle_ = handle;
219 frame->strides_[kYPlane] = new_coded_size.width();
220 frame->strides_[kUPlane] = new_coded_size.width() / 2;
221 frame->strides_[kVPlane] = new_coded_size.width() / 2;
222 frame->data_[kYPlane] = data;
223 frame->data_[kUPlane] = data + new_coded_size.GetArea();
224 frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4);
225 frame->no_longer_needed_cb_ = no_longer_needed_cb;
226 return frame;
228 default:
229 NOTIMPLEMENTED();
230 return NULL;
234 #if defined(OS_POSIX)
235 // static
236 scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs(
237 Format format,
238 const gfx::Size& coded_size,
239 const gfx::Rect& visible_rect,
240 const gfx::Size& natural_size,
241 const std::vector<int> dmabuf_fds,
242 base::TimeDelta timestamp,
243 const base::Closure& no_longer_needed_cb) {
244 if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
245 return NULL;
247 if (dmabuf_fds.size() != NumPlanes(format)) {
248 LOG(FATAL) << "Not enough dmabuf fds provided!";
249 return NULL;
252 scoped_refptr<VideoFrame> frame(
253 new VideoFrame(format,
254 coded_size,
255 visible_rect,
256 natural_size,
257 scoped_ptr<gpu::MailboxHolder>(),
258 timestamp,
259 false));
261 for (size_t i = 0; i < dmabuf_fds.size(); ++i) {
262 int duped_fd = HANDLE_EINTR(dup(dmabuf_fds[i]));
263 if (duped_fd == -1) {
264 // The already-duped in previous iterations fds will be closed when
265 // the partially-created frame drops out of scope here.
266 DLOG(ERROR) << "Failed duplicating a dmabuf fd";
267 return NULL;
270 frame->dmabuf_fds_[i].reset(duped_fd);
271 // Data is accessible only via fds.
272 frame->data_[i] = NULL;
273 frame->strides_[i] = 0;
276 frame->no_longer_needed_cb_ = no_longer_needed_cb;
277 return frame;
279 #endif
281 #if defined(OS_MACOSX)
282 // static
283 scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer(
284 CVPixelBufferRef cv_pixel_buffer,
285 base::TimeDelta timestamp) {
286 DCHECK(cv_pixel_buffer);
287 DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID());
289 OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer);
290 Format format;
291 // There are very few compatible CV pixel formats, so just check each.
292 if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) {
293 format = Format::I420;
294 } else if (cv_format == kCVPixelFormatType_444YpCbCr8) {
295 format = Format::YV24;
296 } else if (cv_format == '420v') {
297 // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the
298 // minimum OS X and iOS SDKs permits it.
299 format = Format::NV12;
300 } else {
301 DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format;
302 return NULL;
305 gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer));
306 gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer));
307 gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer));
309 if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
310 return NULL;
312 scoped_refptr<VideoFrame> frame(
313 new VideoFrame(format,
314 coded_size,
315 visible_rect,
316 natural_size,
317 scoped_ptr<gpu::MailboxHolder>(),
318 timestamp,
319 false));
321 frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
322 return frame;
324 #endif
326 // static
327 scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
328 Format format,
329 const gfx::Size& coded_size,
330 const gfx::Rect& visible_rect,
331 const gfx::Size& natural_size,
332 int32 y_stride,
333 int32 u_stride,
334 int32 v_stride,
335 uint8* y_data,
336 uint8* u_data,
337 uint8* v_data,
338 base::TimeDelta timestamp,
339 const base::Closure& no_longer_needed_cb) {
340 gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
341 CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
343 scoped_refptr<VideoFrame> frame(
344 new VideoFrame(format,
345 new_coded_size,
346 visible_rect,
347 natural_size,
348 scoped_ptr<gpu::MailboxHolder>(),
349 timestamp,
350 false));
351 frame->strides_[kYPlane] = y_stride;
352 frame->strides_[kUPlane] = u_stride;
353 frame->strides_[kVPlane] = v_stride;
354 frame->data_[kYPlane] = y_data;
355 frame->data_[kUPlane] = u_data;
356 frame->data_[kVPlane] = v_data;
357 frame->no_longer_needed_cb_ = no_longer_needed_cb;
358 return frame;
361 // static
362 scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
363 const scoped_refptr<VideoFrame>& frame,
364 const gfx::Rect& visible_rect,
365 const gfx::Size& natural_size,
366 const base::Closure& no_longer_needed_cb) {
367 // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support
368 // for that here yet, see http://crbug/362521.
369 CHECK_NE(frame->format(), NATIVE_TEXTURE);
371 DCHECK(frame->visible_rect().Contains(visible_rect));
372 scoped_refptr<VideoFrame> wrapped_frame(
373 new VideoFrame(frame->format(),
374 frame->coded_size(),
375 visible_rect,
376 natural_size,
377 scoped_ptr<gpu::MailboxHolder>(),
378 frame->timestamp(),
379 frame->end_of_stream()));
381 for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
382 wrapped_frame->strides_[i] = frame->stride(i);
383 wrapped_frame->data_[i] = frame->data(i);
386 wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb;
387 return wrapped_frame;
390 // static
391 scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
392 return new VideoFrame(VideoFrame::UNKNOWN,
393 gfx::Size(),
394 gfx::Rect(),
395 gfx::Size(),
396 scoped_ptr<gpu::MailboxHolder>(),
397 kNoTimestamp(),
398 true);
401 // static
402 scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
403 const gfx::Size& size,
404 uint8 y, uint8 u, uint8 v,
405 base::TimeDelta timestamp) {
406 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
407 VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
408 FillYUV(frame.get(), y, u, v);
409 return frame;
412 // static
413 scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
414 const uint8 kBlackY = 0x00;
415 const uint8 kBlackUV = 0x80;
416 const base::TimeDelta kZero;
417 return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
420 // static
421 scoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame(
422 const gfx::Size& size) {
423 const uint8 kBlackY = 0x00;
424 const uint8 kBlackUV = 0x00;
425 const uint8 kTransparentA = 0x00;
426 const base::TimeDelta kZero;
427 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
428 VideoFrame::YV12A, size, gfx::Rect(size), size, kZero);
429 FillYUVA(frame.get(), kBlackY, kBlackUV, kBlackUV, kTransparentA);
430 return frame;
433 #if defined(VIDEO_HOLE)
434 // This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
435 // maintained by the general compositor team. Please contact the following
436 // people instead:
438 // wonsik@chromium.org
439 // ycheo@chromium.org
441 // static
442 scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
443 const gfx::Size& size) {
444 DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
445 scoped_refptr<VideoFrame> frame(
446 new VideoFrame(VideoFrame::HOLE,
447 size,
448 gfx::Rect(size),
449 size,
450 scoped_ptr<gpu::MailboxHolder>(),
451 base::TimeDelta(),
452 false));
453 return frame;
455 #endif // defined(VIDEO_HOLE)
457 // static
458 size_t VideoFrame::NumPlanes(Format format) {
459 switch (format) {
460 case VideoFrame::NATIVE_TEXTURE:
461 #if defined(VIDEO_HOLE)
462 case VideoFrame::HOLE:
463 #endif // defined(VIDEO_HOLE)
464 return 0;
465 case VideoFrame::NV12:
466 return 2;
467 case VideoFrame::YV12:
468 case VideoFrame::YV16:
469 case VideoFrame::I420:
470 case VideoFrame::YV12J:
471 case VideoFrame::YV24:
472 return 3;
473 case VideoFrame::YV12A:
474 return 4;
475 case VideoFrame::UNKNOWN:
476 break;
478 NOTREACHED() << "Unsupported video frame format: " << format;
479 return 0;
483 // static
484 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
485 size_t total = 0;
486 for (size_t i = 0; i < NumPlanes(format); ++i)
487 total += PlaneAllocationSize(format, i, coded_size);
488 return total;
491 // static
492 gfx::Size VideoFrame::PlaneSize(Format format,
493 size_t plane,
494 const gfx::Size& coded_size) {
495 // Align to multiple-of-two size overall. This ensures that non-subsampled
496 // planes can be addressed by pixel with the same scaling as the subsampled
497 // planes.
498 const int width = RoundUp(coded_size.width(), 2);
499 const int height = RoundUp(coded_size.height(), 2);
500 switch (format) {
501 case VideoFrame::YV24:
502 switch (plane) {
503 case VideoFrame::kYPlane:
504 case VideoFrame::kUPlane:
505 case VideoFrame::kVPlane:
506 return gfx::Size(width, height);
507 default:
508 break;
510 break;
511 case VideoFrame::YV12:
512 case VideoFrame::YV12J:
513 case VideoFrame::I420:
514 switch (plane) {
515 case VideoFrame::kYPlane:
516 return gfx::Size(width, height);
517 case VideoFrame::kUPlane:
518 case VideoFrame::kVPlane:
519 return gfx::Size(width / 2, height / 2);
520 default:
521 break;
523 break;
524 case VideoFrame::YV12A:
525 switch (plane) {
526 case VideoFrame::kYPlane:
527 case VideoFrame::kAPlane:
528 return gfx::Size(width, height);
529 case VideoFrame::kUPlane:
530 case VideoFrame::kVPlane:
531 return gfx::Size(width / 2, height / 2);
532 default:
533 break;
535 break;
536 case VideoFrame::YV16:
537 switch (plane) {
538 case VideoFrame::kYPlane:
539 return gfx::Size(width, height);
540 case VideoFrame::kUPlane:
541 case VideoFrame::kVPlane:
542 return gfx::Size(width / 2, height);
543 default:
544 break;
546 break;
547 case VideoFrame::NV12:
548 switch (plane) {
549 case VideoFrame::kYPlane:
550 return gfx::Size(width, height);
551 case VideoFrame::kUVPlane:
552 return gfx::Size(width, height / 2);
553 default:
554 break;
556 break;
557 case VideoFrame::UNKNOWN:
558 case VideoFrame::NATIVE_TEXTURE:
559 #if defined(VIDEO_HOLE)
560 case VideoFrame::HOLE:
561 #endif // defined(VIDEO_HOLE)
562 break;
564 NOTREACHED() << "Unsupported video frame format/plane: "
565 << format << "/" << plane;
566 return gfx::Size();
569 size_t VideoFrame::PlaneAllocationSize(Format format,
570 size_t plane,
571 const gfx::Size& coded_size) {
572 // VideoFrame formats are (so far) all YUV and 1 byte per sample.
573 return PlaneSize(format, plane, coded_size).GetArea();
576 // static
577 int VideoFrame::PlaneHorizontalBitsPerPixel(Format format, size_t plane) {
578 switch (format) {
579 case VideoFrame::YV24:
580 switch (plane) {
581 case kYPlane:
582 case kUPlane:
583 case kVPlane:
584 return 8;
585 default:
586 break;
588 break;
589 case VideoFrame::YV12:
590 case VideoFrame::YV16:
591 case VideoFrame::I420:
592 case VideoFrame::YV12J:
593 switch (plane) {
594 case kYPlane:
595 return 8;
596 case kUPlane:
597 case kVPlane:
598 return 2;
599 default:
600 break;
602 break;
603 case VideoFrame::YV12A:
604 switch (plane) {
605 case kYPlane:
606 case kAPlane:
607 return 8;
608 case kUPlane:
609 case kVPlane:
610 return 2;
611 default:
612 break;
614 break;
615 case VideoFrame::NV12:
616 switch (plane) {
617 case kYPlane:
618 return 8;
619 case kUVPlane:
620 return 4;
621 default:
622 break;
624 break;
625 case VideoFrame::UNKNOWN:
626 #if defined(VIDEO_HOLE)
627 case VideoFrame::HOLE:
628 #endif // defined(VIDEO_HOLE)
629 case VideoFrame::NATIVE_TEXTURE:
630 break;
632 NOTREACHED() << "Unsupported video frame format/plane: "
633 << format << "/" << plane;
634 return 0;
637 // Release data allocated by AllocateYUV().
638 static void ReleaseData(uint8* data) {
639 DCHECK(data);
640 base::AlignedFree(data);
643 void VideoFrame::AllocateYUV() {
644 DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
645 format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 ||
646 format_ == VideoFrame::YV12J || format_ == VideoFrame::YV24);
647 // Align Y rows at least at 16 byte boundaries. The stride for both
648 // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for
649 // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
650 // the case of YV12 the strides are identical for the same width surface, but
651 // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
652 // YV16. We also round the height of the surface allocated to be an even
653 // number to avoid any potential of faulting by code that attempts to access
654 // the Y values of the final row, but assumes that the last row of U & V
655 // applies to a full two rows of Y. YV12A is the same as YV12, but with an
656 // additional alpha plane that has the same size and alignment as the Y plane.
657 size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
658 kFrameSizeAlignment);
659 size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
660 kFrameSizeAlignment);
662 // The *2 here is because some formats (e.g. h264) allow interlaced coding,
663 // and then the size needs to be a multiple of two macroblocks (vertically).
664 // See libavcodec/utils.c:avcodec_align_dimensions2().
665 size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
666 size_t uv_height =
667 (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
668 format_ == VideoFrame::I420)
669 ? y_height / 2
670 : y_height;
671 size_t y_bytes = y_height * y_stride;
672 size_t uv_bytes = uv_height * uv_stride;
673 size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
675 // The extra line of UV being allocated is because h264 chroma MC
676 // overreads by one line in some cases, see libavcodec/utils.c:
677 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
678 // put_h264_chroma_mc4_ssse3().
679 const size_t data_size =
680 y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding;
681 uint8* data = reinterpret_cast<uint8*>(
682 base::AlignedAlloc(data_size, kFrameAddressAlignment));
683 // FFmpeg expects the initialize allocation to be zero-initialized. Failure
684 // to do so can lead to unitialized value usage. See http://crbug.com/390941
685 memset(data, 0, data_size);
686 no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
687 COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
688 data_[VideoFrame::kYPlane] = data;
689 data_[VideoFrame::kUPlane] = data + y_bytes;
690 data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
691 strides_[VideoFrame::kYPlane] = y_stride;
692 strides_[VideoFrame::kUPlane] = uv_stride;
693 strides_[VideoFrame::kVPlane] = uv_stride;
694 if (format_ == YV12A) {
695 data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
696 strides_[VideoFrame::kAPlane] = y_stride;
700 VideoFrame::VideoFrame(VideoFrame::Format format,
701 const gfx::Size& coded_size,
702 const gfx::Rect& visible_rect,
703 const gfx::Size& natural_size,
704 scoped_ptr<gpu::MailboxHolder> mailbox_holder,
705 base::TimeDelta timestamp,
706 bool end_of_stream)
707 : format_(format),
708 coded_size_(coded_size),
709 visible_rect_(visible_rect),
710 natural_size_(natural_size),
711 mailbox_holder_(mailbox_holder.Pass()),
712 shared_memory_handle_(base::SharedMemory::NULLHandle()),
713 timestamp_(timestamp),
714 release_sync_point_(0),
715 end_of_stream_(end_of_stream) {
716 DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_));
718 memset(&strides_, 0, sizeof(strides_));
719 memset(&data_, 0, sizeof(data_));
722 VideoFrame::~VideoFrame() {
723 if (!mailbox_holder_release_cb_.is_null()) {
724 uint32 release_sync_point;
726 // To ensure that changes to |release_sync_point_| are visible on this
727 // thread (imply a memory barrier).
728 base::AutoLock locker(release_sync_point_lock_);
729 release_sync_point = release_sync_point_;
731 base::ResetAndReturn(&mailbox_holder_release_cb_).Run(release_sync_point);
733 if (!no_longer_needed_cb_.is_null())
734 base::ResetAndReturn(&no_longer_needed_cb_).Run();
737 // static
738 bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) {
739 return (plane < NumPlanes(format));
742 int VideoFrame::stride(size_t plane) const {
743 DCHECK(IsValidPlane(plane, format_));
744 return strides_[plane];
747 // static
748 int VideoFrame::RowBytes(size_t plane, VideoFrame::Format format, int width) {
749 DCHECK(IsValidPlane(plane, format));
750 switch (format) {
751 case VideoFrame::YV24:
752 switch (plane) {
753 case kYPlane:
754 case kUPlane:
755 case kVPlane:
756 return width;
757 default:
758 break;
760 break;
761 case VideoFrame::YV12:
762 case VideoFrame::YV16:
763 case VideoFrame::I420:
764 case VideoFrame::YV12J:
765 switch (plane) {
766 case kYPlane:
767 return width;
768 case kUPlane:
769 case kVPlane:
770 return RoundUp(width, 2) / 2;
771 default:
772 break;
774 break;
775 case VideoFrame::YV12A:
776 switch (plane) {
777 case kYPlane:
778 case kAPlane:
779 return width;
780 case kUPlane:
781 case kVPlane:
782 return RoundUp(width, 2) / 2;
783 default:
784 break;
786 break;
787 case VideoFrame::NV12:
788 switch (plane) {
789 case kYPlane:
790 case kUVPlane:
791 return width;
792 default:
793 break;
795 break;
796 case VideoFrame::UNKNOWN:
797 #if defined(VIDEO_HOLE)
798 case VideoFrame::HOLE:
799 #endif // defined(VIDEO_HOLE)
800 case VideoFrame::NATIVE_TEXTURE:
801 break;
803 NOTREACHED() << "Unsupported video frame format/plane: " << format << "/"
804 << plane;
805 return 0;
808 int VideoFrame::row_bytes(size_t plane) const {
809 return RowBytes(plane, format_, coded_size_.width());
812 int VideoFrame::rows(size_t plane) const {
813 DCHECK(IsValidPlane(plane, format_));
814 int height = coded_size_.height();
815 switch (format_) {
816 case VideoFrame::YV24:
817 case VideoFrame::YV16:
818 switch (plane) {
819 case kYPlane:
820 case kUPlane:
821 case kVPlane:
822 return height;
823 default:
824 break;
826 break;
827 case VideoFrame::YV12:
828 case VideoFrame::YV12J:
829 case VideoFrame::I420:
830 switch (plane) {
831 case kYPlane:
832 return height;
833 case kUPlane:
834 case kVPlane:
835 return RoundUp(height, 2) / 2;
836 default:
837 break;
839 break;
840 case VideoFrame::YV12A:
841 switch (plane) {
842 case kYPlane:
843 case kAPlane:
844 return height;
845 case kUPlane:
846 case kVPlane:
847 return RoundUp(height, 2) / 2;
848 default:
849 break;
851 break;
852 case VideoFrame::NV12:
853 switch (plane) {
854 case kYPlane:
855 return height;
856 case kUVPlane:
857 return RoundUp(height, 2) / 2;
858 default:
859 break;
861 break;
862 case VideoFrame::UNKNOWN:
863 #if defined(VIDEO_HOLE)
864 case VideoFrame::HOLE:
865 #endif // defined(VIDEO_HOLE)
866 case VideoFrame::NATIVE_TEXTURE:
867 break;
869 NOTREACHED() << "Unsupported video frame format/plane: "
870 << format_ << "/" << plane;
871 return 0;
874 uint8* VideoFrame::data(size_t plane) const {
875 DCHECK(IsValidPlane(plane, format_));
876 return data_[plane];
879 const gpu::MailboxHolder* VideoFrame::mailbox_holder() const {
880 DCHECK_EQ(format_, NATIVE_TEXTURE);
881 return mailbox_holder_.get();
884 base::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
885 return shared_memory_handle_;
888 void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) {
889 DCHECK_EQ(format_, NATIVE_TEXTURE);
890 base::AutoLock locker(release_sync_point_lock_);
891 // Must wait on the previous sync point before inserting a new sync point so
892 // that |mailbox_holder_release_cb_| guarantees the previous sync point
893 // occurred when it waits on |release_sync_point_|.
894 if (release_sync_point_)
895 client->WaitSyncPoint(release_sync_point_);
896 release_sync_point_ = client->InsertSyncPoint();
899 #if defined(OS_POSIX)
900 int VideoFrame::dmabuf_fd(size_t plane) const {
901 return dmabuf_fds_[plane].get();
903 #endif
905 #if defined(OS_MACOSX)
906 CVPixelBufferRef VideoFrame::cv_pixel_buffer() const {
907 return cv_pixel_buffer_.get();
909 #endif
911 void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
912 for (int plane = 0; plane < kMaxPlanes; ++plane) {
913 if (!IsValidPlane(plane, format_))
914 break;
915 for (int row = 0; row < rows(plane); ++row) {
916 base::MD5Update(context, base::StringPiece(
917 reinterpret_cast<char*>(data(plane) + stride(plane) * row),
918 row_bytes(plane)));
923 } // namespace media