video_frame.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic inline size_t RoundUp(size_t value, size_t alignment) {
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check that |alignment| is a power of 2.
23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return ((value + (alignment - 1)) & ~(alignment - 1));
25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoFrame::Format format,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Since we're creating a new YUV frame (and allocating memory for it
35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // ourselves), we can pad the requested |coded_size| if necessary if the
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // request does not line up on sample boundaries.
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  gfx::Size new_coded_size(coded_size);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV12:
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new_coded_size.set_height((new_coded_size.height() + 1) / 2 * 2);
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Fallthrough.
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV16:
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new_coded_size.set_width((new_coded_size.width() + 1) / 2 * 2);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      LOG(FATAL) << "Only YUV formats supported: " << format;
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return NULL;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_refptr<VideoFrame> frame(new VideoFrame(
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      format, new_coded_size, visible_rect, natural_size, timestamp, false));
55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  frame->AllocateYUV();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::string VideoFrame::FormatToString(VideoFrame::Format format) {
613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  switch (format) {
620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return "UNKNOWN";
643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12:
653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12";
663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV16:
673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV16";
683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::I420:
693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "I420";
703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::NATIVE_TEXTURE:
713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "NATIVE_TEXTURE";
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::HOLE:
743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "HOLE";
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12A:
773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12A";
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return "YV12J";
803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NOTREACHED() << "Invalid videoframe format provided: " << format;
823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return "";
833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// static
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidConfig(VideoFrame::Format format,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& coded_size,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Rect& visible_rect,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& natural_size) {
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check maximum limits for all formats.
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (coded_size.GetArea() > limits::kMaxCanvas ||
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      coded_size.width() > limits::kMaxDimension ||
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      coded_size.height() > limits::kMaxDimension ||
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.x() < 0 || visible_rect.y() < 0 ||
95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.right() > coded_size.width() ||
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      visible_rect.bottom() > coded_size.height() ||
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.GetArea() > limits::kMaxCanvas ||
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.width() > limits::kMaxDimension ||
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      natural_size.height() > limits::kMaxDimension)
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check format-specific width/height requirements.
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  switch (format) {
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::UNKNOWN:
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              natural_size.IsEmpty());
107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12:
108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12J:
109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::I420:
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV12A:
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // YUV formats have width/height requirements due to chroma subsampling.
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (static_cast<size_t>(coded_size.height()) <
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RoundUp(visible_rect.bottom(), 2))
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return false;
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Fallthrough.
116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::YV16:
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (static_cast<size_t>(coded_size.width()) <
118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RoundUp(visible_rect.right(), 2))
119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return false;
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::NATIVE_TEXTURE:
122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(VIDEO_HOLE)
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    case VideoFrame::HOLE:
124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif  // defined(VIDEO_HOLE)
125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // allowed to skip the below check and be empty.
127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return true;
128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Check that software-allocated buffer formats are not empty.
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          !natural_size.IsEmpty());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<gpu::MailboxHolder> mailbox_holder,
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReleaseMailboxCB& mailbox_holder_release_cb,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadPixelsCB& read_pixels_cb) {
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE,
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 coded_size,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 visible_rect,
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 natural_size,
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 timestamp,
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 false));
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->mailbox_holder_ = mailbox_holder.Pass();
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->read_pixels_cb_ = read_pixels_cb;
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_pixels_cb_.is_null())
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_pixels_cb_.Run(pixels);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Format format,
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& coded_size,
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Rect& visible_rect,
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& natural_size,
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* data,
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    size_t data_size,
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::SharedMemoryHandle handle,
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::TimeDelta timestamp,
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& no_longer_needed_cb) {
174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return NULL;
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_size < AllocationSize(format, coded_size))
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return NULL;
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  switch (format) {
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420: {
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      scoped_refptr<VideoFrame> frame(new VideoFrame(
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          format, coded_size, visible_rect, natural_size, timestamp, false));
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->shared_memory_handle_ = handle;
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kYPlane] = coded_size.width();
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kUPlane] = coded_size.width() / 2;
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kVPlane] = coded_size.width() / 2;
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kYPlane] = data;
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kUPlane] = data + coded_size.GetArea();
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4);
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->no_longer_needed_cb_ = no_longer_needed_cb;
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return frame;
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    default:
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      NOTIMPLEMENTED();
195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return NULL;
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Format format,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& coded_size,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& visible_rect,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& natural_size,
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 y_stride,
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 u_stride,
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 v_stride,
208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* y_data,
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* u_data,
210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* v_data,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timestamp,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return NULL;
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      format, coded_size, visible_rect, natural_size, timestamp, false));
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kYPlane] = y_stride;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kUPlane] = u_stride;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kVPlane] = v_stride;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kYPlane] = y_data;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kUPlane] = u_data;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kVPlane] = v_data;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const scoped_refptr<VideoFrame>& frame,
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const gfx::Rect& visible_rect,
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const gfx::Size& natural_size,
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::Closure& no_longer_needed_cb) {
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(frame->visible_rect().Contains(visible_rect));
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<VideoFrame> wrapped_frame(new VideoFrame(
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      frame->format(), frame->coded_size(), visible_rect, natural_size,
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      frame->GetTimestamp(), frame->end_of_stream()));
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->strides_[i] = frame->stride(i);
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->data_[i] = frame->data(i);
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb;
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return wrapped_frame;
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return new VideoFrame(VideoFrame::UNKNOWN,
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Rect(),
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        kNoTimestamp(),
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        true);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 y, uint8 u, uint8 v,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FillYUV(frame.get(), y, u, v);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackY = 0x00;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackUV = 0x80;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kZero;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maintained by the general compositor team. Please contact the following
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// people instead:
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wonsik@chromium.org
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ycheo@chromium.org
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& size) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta(), false));
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t VideoFrame::NumPlanes(Format format) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (format) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::HOLE:
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV12:
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV16:
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 3;
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 4;
3100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t total = 0;
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < NumPlanes(format); ++i)
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    total += PlaneAllocationSize(format, i, coded_size);
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return total;
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochgfx::Size VideoFrame::PlaneSize(Format format,
328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                size_t plane,
329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                const gfx::Size& coded_size) {
330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const int width = RoundUp(coded_size.width(), 2);
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const int height = RoundUp(coded_size.height(), 2);
332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (format) {
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV12:
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::I420: {
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height / 2);
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV12A: {
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kAPlane:
350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height / 2);
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
357424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV16: {
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width, height);
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          return gfx::Size(width / 2, height);
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
3690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::HOLE:
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format/plane: "
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << format << "/" << plane;
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return gfx::Size();
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochsize_t VideoFrame::PlaneAllocationSize(Format format,
382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                       size_t plane,
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                       const gfx::Size& coded_size) {
384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // VideoFrame formats are (so far) all YUV and 1 byte per sample.
385effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return PlaneSize(format, plane, coded_size).GetArea();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Release data allocated by AllocateYUV().
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReleaseData(uint8* data) {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(data);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AlignedFree(data);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateYUV() {
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 ||
397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         format_ == VideoFrame::YV12J);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Align Y rows at least at 16 byte boundaries.  The stride for both
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the case of YV12 the strides are identical for the same width surface, but
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV16. We also round the height of the surface allocated to be an even
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number to avoid any potential of faulting by code that attempts to access
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Y values of the final row, but assumes that the last row of U & V
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // applies to a full two rows of Y. YV12A is the same as YV12, but with an
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // additional alpha plane that has the same size and alignment as the Y plane.
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kFrameSizeAlignment);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kFrameSizeAlignment);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The *2 here is because some formats (e.g. h264) allow interlaced coding,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then the size needs to be a multiple of two macroblocks (vertically).
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See libavcodec/utils.c:avcodec_align_dimensions2().
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
417ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  size_t uv_height =
418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       format_ == VideoFrame::I420)
420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ? y_height / 2
421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          : y_height;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_bytes = y_height * y_stride;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_bytes = uv_height * uv_stride;
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extra line of UV being allocated is because h264 chroma MC
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overreads by one line in some cases, see libavcodec/utils.c:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // put_h264_chroma_mc4_ssse3().
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* data = reinterpret_cast<uint8*>(
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AlignedAlloc(
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kFrameAddressAlignment));
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kYPlane] = data;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kUPlane] = data + y_bytes;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kYPlane] = y_stride;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kUPlane] = uv_stride;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kVPlane] = uv_stride;
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (format_ == YV12A) {
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    strides_[VideoFrame::kAPlane] = y_stride;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::VideoFrame(VideoFrame::Format format,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& coded_size,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Rect& visible_rect,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& natural_size,
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       base::TimeDelta timestamp,
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       bool end_of_stream)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : format_(format),
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_size_(coded_size),
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_rect_(visible_rect),
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      natural_size_(natural_size),
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      shared_memory_handle_(base::SharedMemory::NULLHandle()),
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamp_(timestamp),
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      end_of_stream_(end_of_stream) {
461effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_));
462effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&strides_, 0, sizeof(strides_));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&data_, 0, sizeof(data_));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::~VideoFrame() {
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!mailbox_holder_release_cb_.is_null()) {
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ResetAndReturn(&mailbox_holder_release_cb_)
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        .Run(mailbox_holder_.Pass());
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!no_longer_needed_cb_.is_null())
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::ResetAndReturn(&no_longer_needed_cb_).Run();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidPlane(size_t plane) const {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (plane < NumPlanes(format_));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::stride(size_t plane) const {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return strides_[plane];
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::row_bytes(size_t plane) const {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = coded_size_.width();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Planar, 8bpp.
490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case YV12A:
491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kAPlane)
492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return width;
493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Fallthrough.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV12:
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420:
497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case YV12J:
498ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kYPlane)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return width;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(width, 2) / 2;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::rows(size_t plane) const {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = coded_size_.height();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return height;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case YV12A:
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kAPlane)
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return height;
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Fallthrough.
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case YV12:
523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420:
524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kYPlane)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return height;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(height, 2) / 2;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint8* VideoFrame::data(size_t plane) const {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_[plane];
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gpu::MailboxHolder* VideoFrame::mailbox_holder() const {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return mailbox_holder_.get();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return shared_memory_handle_;
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int plane = 0; plane < kMaxPlanes; ++plane) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsValidPlane(plane))
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int row = 0; row < rows(plane); ++row) {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::MD5Update(context, base::StringPiece(
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<char*>(data(plane) + stride(plane) * row),
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          row_bytes(plane)));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
564