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_frame.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/aligned_memory.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox_holder.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_util.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(MEDIA_FOR_CAST_IOS)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic inline size_t RoundUp(size_t value, size_t alignment) {
25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check that |alignment| is a power of 2.
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return ((value + (alignment - 1)) & ~(alignment - 1));
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Rounds up |coded_size| if necessary for |format|.
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic gfx::Size AdjustCodedSize(VideoFrame::Format format,
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 const gfx::Size& coded_size) {
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  gfx::Size new_coded_size(coded_size);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV12:
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new_coded_size.set_height(RoundUp(new_coded_size.height(), 2));
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Fallthrough.
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV16:
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new_coded_size.set_width(RoundUp(new_coded_size.width(), 2));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    default:
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return new_coded_size;
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_refptr<VideoFrame> VideoFrame::CreateFrame(
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VideoFrame::Format format,
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const gfx::Size& coded_size,
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const gfx::Rect& visible_rect,
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const gfx::Size& natural_size,
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::TimeDelta timestamp) {
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(format != VideoFrame::UNKNOWN &&
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         format != VideoFrame::NV12 &&
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         format != VideoFrame::NATIVE_TEXTURE);
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(VIDEO_HOLE)
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(format != VideoFrame::HOLE);
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // defined(VIDEO_HOLE)
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Since we're creating a new YUV frame (and allocating memory for it
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // ourselves), we can pad the requested |coded_size| if necessary if the
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // request does not line up on sample boundaries.
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<VideoFrame> frame(
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new VideoFrame(format,
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     new_coded_size,
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     visible_rect,
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     natural_size,
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     scoped_ptr<gpu::MailboxHolder>(),
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     timestamp,
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     false));
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  frame->AllocateYUV();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::string VideoFrame::FormatToString(VideoFrame::Format format) {
843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  switch (format) {
850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return "UNKNOWN";
873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12:
883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12";
893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV16:
903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV16";
913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::I420:
923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "I420";
933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::NATIVE_TEXTURE:
943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "NATIVE_TEXTURE";
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::HOLE:
973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "HOLE";
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12A:
1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12A";
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return "YV12J";
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::NV12:
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return "NV12";
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return "YV24";
1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NOTREACHED() << "Invalid videoframe format provided: " << format;
1093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return "";
1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// static
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidConfig(VideoFrame::Format format,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& coded_size,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Rect& visible_rect,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& natural_size) {
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check maximum limits for all formats.
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (coded_size.GetArea() > limits::kMaxCanvas ||
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      coded_size.width() > limits::kMaxDimension ||
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      coded_size.height() > limits::kMaxDimension ||
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.x() < 0 || visible_rect.y() < 0 ||
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.right() > coded_size.width() ||
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.bottom() > coded_size.height() ||
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.GetArea() > limits::kMaxCanvas ||
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.width() > limits::kMaxDimension ||
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.height() > limits::kMaxDimension)
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check format-specific width/height requirements.
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  switch (format) {
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::UNKNOWN:
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              natural_size.IsEmpty());
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12:
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12J:
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::I420:
139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12A:
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::NV12:
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Subsampled YUV formats have width/height requirements.
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (static_cast<size_t>(coded_size.height()) <
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RoundUp(visible_rect.bottom(), 2))
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return false;
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Fallthrough.
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV16:
147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (static_cast<size_t>(coded_size.width()) <
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RoundUp(visible_rect.right(), 2))
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return false;
150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::NATIVE_TEXTURE:
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(VIDEO_HOLE)
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::HOLE:
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif  // defined(VIDEO_HOLE)
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // allowed to skip the below check and be empty.
157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return true;
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check that software-allocated buffer formats are not empty.
161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          !natural_size.IsEmpty());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<gpu::MailboxHolder> mailbox_holder,
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReleaseMailboxCB& mailbox_holder_release_cb,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp,
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadPixelsCB& read_pixels_cb) {
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE,
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 coded_size,
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 visible_rect,
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 natural_size,
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                 mailbox_holder.Pass(),
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 timestamp,
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 false));
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->read_pixels_cb_ = read_pixels_cb;
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(MEDIA_FOR_CAST_IOS)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_pixels_cb_.is_null())
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_pixels_cb_.Run(pixels);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Format format,
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& coded_size,
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Rect& visible_rect,
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& natural_size,
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* data,
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    size_t data_size,
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::SharedMemoryHandle handle,
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::TimeDelta timestamp,
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& no_longer_needed_cb) {
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size))
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return NULL;
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (data_size < AllocationSize(format, new_coded_size))
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return NULL;
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  switch (format) {
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::I420: {
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      scoped_refptr<VideoFrame> frame(
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          new VideoFrame(format,
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         new_coded_size,
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         visible_rect,
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         natural_size,
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         scoped_ptr<gpu::MailboxHolder>(),
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         timestamp,
2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         false));
223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->shared_memory_handle_ = handle;
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      frame->strides_[kYPlane] = new_coded_size.width();
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      frame->strides_[kUPlane] = new_coded_size.width() / 2;
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      frame->strides_[kVPlane] = new_coded_size.width() / 2;
227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kYPlane] = data;
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      frame->data_[kUPlane] = data + new_coded_size.GetArea();
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4);
230ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->no_longer_needed_cb_ = no_longer_needed_cb;
231ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return frame;
232ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    default:
234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      NOTIMPLEMENTED();
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return NULL;
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_POSIX)
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs(
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    Format format,
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& coded_size,
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Rect& visible_rect,
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& natural_size,
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<int> dmabuf_fds,
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::TimeDelta timestamp,
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return NULL;
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (dmabuf_fds.size() != NumPlanes(format)) {
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LOG(FATAL) << "Not enough dmabuf fds provided!";
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return NULL;
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new VideoFrame(format,
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     coded_size,
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     visible_rect,
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     natural_size,
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     scoped_ptr<gpu::MailboxHolder>(),
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     timestamp,
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     false));
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; i < dmabuf_fds.size(); ++i) {
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int duped_fd = HANDLE_EINTR(dup(dmabuf_fds[i]));
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (duped_fd == -1) {
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // The already-duped in previous iterations fds will be closed when
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // the partially-created frame drops out of scope here.
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DLOG(ERROR) << "Failed duplicating a dmabuf fd";
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return NULL;
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    frame->dmabuf_fds_[i].reset(duped_fd);
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Data is accessible only via fds.
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    frame->data_[i] = NULL;
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    frame->strides_[i] = 0;
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return frame;
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX)
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer(
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CVPixelBufferRef cv_pixel_buffer,
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeDelta timestamp) {
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(cv_pixel_buffer);
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID());
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer);
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Format format;
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // There are very few compatible CV pixel formats, so just check each.
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) {
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    format = Format::I420;
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (cv_format == kCVPixelFormatType_444YpCbCr8) {
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    format = Format::YV24;
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (cv_format == '420v') {
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // minimum OS X and iOS SDKs permits it.
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    format = Format::NV12;
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format;
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer));
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer));
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer));
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return NULL;
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<VideoFrame> frame(
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new VideoFrame(format,
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     coded_size,
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     visible_rect,
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     natural_size,
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     scoped_ptr<gpu::MailboxHolder>(),
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     timestamp,
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     false));
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return frame;
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Format format,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& coded_size,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& visible_rect,
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& natural_size,
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 y_stride,
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 u_stride,
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 v_stride,
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* y_data,
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* u_data,
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* v_data,
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timestamp,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gfx::Size new_coded_size = AdjustCodedSize(format, coded_size);
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<VideoFrame> frame(
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new VideoFrame(format,
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     new_coded_size,
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     visible_rect,
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     natural_size,
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     scoped_ptr<gpu::MailboxHolder>(),
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     timestamp,
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     false));
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kYPlane] = y_stride;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kUPlane] = u_stride;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kVPlane] = v_stride;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kYPlane] = y_data;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kUPlane] = u_data;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kVPlane] = v_data;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const scoped_refptr<VideoFrame>& frame,
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const gfx::Rect& visible_rect,
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const gfx::Size& natural_size,
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::Closure& no_longer_needed_cb) {
372a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support
373a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // for that here yet, see http://crbug/362521.
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK_NE(frame->format(), NATIVE_TEXTURE);
375a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(frame->visible_rect().Contains(visible_rect));
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<VideoFrame> wrapped_frame(
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new VideoFrame(frame->format(),
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     frame->coded_size(),
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     visible_rect,
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     natural_size,
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     scoped_ptr<gpu::MailboxHolder>(),
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     frame->timestamp(),
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     frame->end_of_stream()));
385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->strides_[i] = frame->stride(i);
388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->data_[i] = frame->data(i);
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb;
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return wrapped_frame;
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return new VideoFrame(VideoFrame::UNKNOWN,
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Rect(),
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        scoped_ptr<gpu::MailboxHolder>(),
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        kNoTimestamp(),
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        true);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 y, uint8 u, uint8 v,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FillYUV(frame.get(), y, u, v);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackY = 0x00;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackUV = 0x80;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kZero;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame(
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const gfx::Size& size) {
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const uint8 kBlackY = 0x00;
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const uint8 kBlackUV = 0x00;
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const uint8 kTransparentA = 0x00;
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const base::TimeDelta kZero;
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      VideoFrame::YV12A, size, gfx::Rect(size), size, kZero);
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FillYUVA(frame.get(), kBlackY, kBlackUV, kBlackUV, kTransparentA);
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return frame;
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maintained by the general compositor team. Please contact the following
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// people instead:
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wonsik@chromium.org
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ycheo@chromium.org
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& size) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<VideoFrame> frame(
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new VideoFrame(VideoFrame::HOLE,
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     size,
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     gfx::Rect(size),
4545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     size,
4555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     scoped_ptr<gpu::MailboxHolder>(),
4565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     base::TimeDelta(),
4575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                     false));
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t VideoFrame::NumPlanes(Format format) {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (format) {
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::HOLE:
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::NV12:
471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return 2;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV12:
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV16:
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
47646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 3;
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 4;
4800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
487424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t total = 0;
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < NumPlanes(format); ++i)
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    total += PlaneAllocationSize(format, i, coded_size);
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return total;
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
497effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochgfx::Size VideoFrame::PlaneSize(Format format,
498effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                size_t plane,
499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                const gfx::Size& coded_size) {
50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Align to multiple-of-two size overall. This ensures that non-subsampled
50146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // planes can be addressed by pixel with the same scaling as the subsampled
50246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // planes.
503effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const int width = RoundUp(coded_size.width(), 2);
504effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const int height = RoundUp(coded_size.height(), 2);
505424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (format) {
50646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
50746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case VideoFrame::kYPlane:
50946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case VideoFrame::kUPlane:
51046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case VideoFrame::kVPlane:
51146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return gfx::Size(width, height);
51246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
51346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
51446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
51546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV12:
517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::I420:
519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
521effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
524effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height / 2);
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
52846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
52946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12A:
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
531f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
532f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kAPlane:
533effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
535f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
536effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height / 2);
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
538f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
539f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
54046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
54146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV16:
542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
544effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
545f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
546f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
547effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height);
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
549f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
55246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NV12:
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch (plane) {
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case VideoFrame::kYPlane:
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return gfx::Size(width, height);
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case VideoFrame::kUVPlane:
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return gfx::Size(width, height / 2);
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        default:
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          break;
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
5620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::HOLE:
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format/plane: "
570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << format << "/" << plane;
571effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return gfx::Size();
572effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
573effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
574effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochsize_t VideoFrame::PlaneAllocationSize(Format format,
575effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                       size_t plane,
576effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                       const gfx::Size& coded_size) {
577effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // VideoFrame formats are (so far) all YUV and 1 byte per sample.
578effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return PlaneSize(format, plane, coded_size).GetArea();
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int VideoFrame::PlaneHorizontalBitsPerPixel(Format format, size_t plane) {
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (format) {
58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
58646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return 8;
59046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
59146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
594010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::YV12:
595010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::YV16:
596010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case VideoFrame::I420:
59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12J:
598010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch (plane) {
599010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case kYPlane:
600010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return 8;
601010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case kUPlane:
602010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case kVPlane:
603010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return 2;
604010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        default:
605010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          break;
606010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12A:
60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
61046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
61146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kAPlane:
61246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return 8;
61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return 2;
61646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
61746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
61846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
61946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
62046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NV12:
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch (plane) {
622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case kYPlane:
623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return 8;
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        case kUVPlane:
625010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return 4;
626010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        default:
627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          break;
628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
62946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
63046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::UNKNOWN:
63146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(VIDEO_HOLE)
63246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::HOLE:
63346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // defined(VIDEO_HOLE)
63446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
635010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
636010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
63746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format/plane: "
63846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)               << format << "/" << plane;
639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return 0;
640010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
641010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Release data allocated by AllocateYUV().
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReleaseData(uint8* data) {
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(data);
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AlignedFree(data);
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateYUV() {
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 ||
65146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         format_ == VideoFrame::YV12J || format_ == VideoFrame::YV24);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Align Y rows at least at 16 byte boundaries.  The stride for both
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the case of YV12 the strides are identical for the same width surface, but
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV16. We also round the height of the surface allocated to be an even
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number to avoid any potential of faulting by code that attempts to access
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Y values of the final row, but assumes that the last row of U & V
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // applies to a full two rows of Y. YV12A is the same as YV12, but with an
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // additional alpha plane that has the same size and alignment as the Y plane.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kFrameSizeAlignment);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kFrameSizeAlignment);
66646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The *2 here is because some formats (e.g. h264) allow interlaced coding,
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then the size needs to be a multiple of two macroblocks (vertically).
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See libavcodec/utils.c:avcodec_align_dimensions2().
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
671ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  size_t uv_height =
672ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
673ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       format_ == VideoFrame::I420)
674ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ? y_height / 2
675ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          : y_height;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_bytes = y_height * y_stride;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_bytes = uv_height * uv_stride;
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extra line of UV being allocated is because h264 chroma MC
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overreads by one line in some cases, see libavcodec/utils.c:
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // put_h264_chroma_mc4_ssse3().
684116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const size_t data_size =
685116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* data = reinterpret_cast<uint8*>(
687116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::AlignedAlloc(data_size, kFrameAddressAlignment));
688116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // FFmpeg expects the initialize allocation to be zero-initialized.  Failure
689116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // to do so can lead to unitialized value usage.  See http://crbug.com/390941
690116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memset(data, 0, data_size);
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kYPlane] = data;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kUPlane] = data + y_bytes;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kYPlane] = y_stride;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kUPlane] = uv_stride;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kVPlane] = uv_stride;
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (format_ == YV12A) {
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    strides_[VideoFrame::kAPlane] = y_stride;
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::VideoFrame(VideoFrame::Format format,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& coded_size,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Rect& visible_rect,
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& natural_size,
7095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       scoped_ptr<gpu::MailboxHolder> mailbox_holder,
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       base::TimeDelta timestamp,
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       bool end_of_stream)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : format_(format),
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_size_(coded_size),
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_rect_(visible_rect),
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      natural_size_(natural_size),
7165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      mailbox_holder_(mailbox_holder.Pass()),
717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      shared_memory_handle_(base::SharedMemory::NULLHandle()),
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamp_(timestamp),
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      release_sync_point_(0),
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      end_of_stream_(end_of_stream) {
721effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_));
722effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&strides_, 0, sizeof(strides_));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&data_, 0, sizeof(data_));
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::~VideoFrame() {
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!mailbox_holder_release_cb_.is_null()) {
7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32 release_sync_point;
7305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    {
7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // To ensure that changes to |release_sync_point_| are visible on this
7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // thread (imply a memory barrier).
7335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::AutoLock locker(release_sync_point_lock_);
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      release_sync_point = release_sync_point_;
7355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::ResetAndReturn(&mailbox_holder_release_cb_).Run(release_sync_point);
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!no_longer_needed_cb_.is_null())
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::ResetAndReturn(&no_longer_needed_cb_).Run();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static
74303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) {
74403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return (plane < NumPlanes(format));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::stride(size_t plane) const {
74803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(IsValidPlane(plane, format_));
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return strides_[plane];
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisize_t VideoFrame::RowBytes(size_t plane, VideoFrame::Format format,
7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            int width) {
75503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(IsValidPlane(plane, format));
75603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  switch (format) {
75746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
75846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
75946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
76046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return width;
76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
766010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
76746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12:
76846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV16:
76946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::I420:
77046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12J:
77146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
77246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
77346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return width;
77446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
77546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
77646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return RoundUp(width, 2) / 2;
77746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
77846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
77946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
780010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
78146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12A:
78246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
78346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
78446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kAPlane:
78546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return width;
78646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
78746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
78846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return RoundUp(width, 2) / 2;
78946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
79046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
79146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
79246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
79346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NV12:
79446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
79546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
79646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUVPlane:
79746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return width;
79846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
79946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
80046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
80146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
80246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::UNKNOWN:
80346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(VIDEO_HOLE)
80446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::HOLE:
80546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // defined(VIDEO_HOLE)
80646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
80903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format/plane: " << format << "/"
81003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)               << plane;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)int VideoFrame::row_bytes(size_t plane) const {
81503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return RowBytes(plane, format_, coded_size_.width());
81603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
81703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
8191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisize_t VideoFrame::Rows(size_t plane, VideoFrame::Format format, int height) {
8201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(IsValidPlane(plane, format));
8211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (format) {
82246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV24:
82346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV16:
82446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
82546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
82646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
82746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
82846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return height;
82946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
83046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
83146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
832010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
83346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12:
83446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12J:
83546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::I420:
83646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
83746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
83846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return height;
83946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
84046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
84146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return RoundUp(height, 2) / 2;
84246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
84346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
84446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
845010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
84646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::YV12A:
84746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
84846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
84946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kAPlane:
85046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return height;
85146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUPlane:
85246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kVPlane:
85346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return RoundUp(height, 2) / 2;
85446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
85546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
85646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
85746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
85846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NV12:
85946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      switch (plane) {
86046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kYPlane:
86146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return height;
86246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case kUVPlane:
86346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return RoundUp(height, 2) / 2;
86446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        default:
86546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
86646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
86746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
86846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::UNKNOWN:
86946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(VIDEO_HOLE)
87046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::HOLE:
87146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // defined(VIDEO_HOLE)
87246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NOTREACHED() << "Unsupported video frame format/plane: " << format << "/"
8761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               << plane;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint VideoFrame::rows(size_t plane) const {
8811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return Rows(plane, format_, coded_size_.height());
8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint8* VideoFrame::data(size_t plane) const {
88503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(IsValidPlane(plane, format_));
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_[plane];
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst gpu::MailboxHolder* VideoFrame::mailbox_holder() const {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return mailbox_holder_.get();
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return shared_memory_handle_;
896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) {
8995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_EQ(format_, NATIVE_TEXTURE);
9005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::AutoLock locker(release_sync_point_lock_);
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Must wait on the previous sync point before inserting a new sync point so
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // that |mailbox_holder_release_cb_| guarantees the previous sync point
9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // occurred when it waits on |release_sync_point_|.
9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (release_sync_point_)
9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    client->WaitSyncPoint(release_sync_point_);
9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  release_sync_point_ = client->InsertSyncPoint();
9075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
9085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
909010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_POSIX)
910010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int VideoFrame::dmabuf_fd(size_t plane) const {
911010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return dmabuf_fds_[plane].get();
912010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
913010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
914010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX)
9161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciCVPixelBufferRef VideoFrame::cv_pixel_buffer() const {
9171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return cv_pixel_buffer_.get();
9181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
9201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int plane = 0; plane < kMaxPlanes; ++plane) {
92303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!IsValidPlane(plane, format_))
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int row = 0; row < rows(plane); ++row) {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::MD5Update(context, base::StringPiece(
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<char*>(data(plane) + stride(plane) * row),
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          row_bytes(plane)));
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
934