video_frame.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoFrame::Format format,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size));
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      format, coded_size, visible_rect, natural_size, timestamp, false));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV12:
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV16:
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame->AllocateYUV();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(FATAL) << "Unsupported frame format: " << format;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::string VideoFrame::FormatToString(VideoFrame::Format format) {
473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  switch (format) {
480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return "UNKNOWN";
503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12:
513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12";
523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV16:
533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV16";
543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::I420:
553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "I420";
563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::NATIVE_TEXTURE:
573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "NATIVE_TEXTURE";
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::HOLE:
603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "HOLE";
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12A:
633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12A";
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return "YV12J";
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case VideoFrame::HISTOGRAM_MAX:
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return "HISTOGRAM_MAX";
683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NOTREACHED() << "Invalid videoframe format provided: " << format;
703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return "";
713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// static
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidConfig(VideoFrame::Format format,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& coded_size,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Rect& visible_rect,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const gfx::Size& natural_size) {
780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return (format != VideoFrame::UNKNOWN &&
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !coded_size.IsEmpty() &&
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          coded_size.GetArea() <= limits::kMaxCanvas &&
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          coded_size.width() <= limits::kMaxDimension &&
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          coded_size.height() <= limits::kMaxDimension &&
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !visible_rect.IsEmpty() &&
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visible_rect.x() >= 0 && visible_rect.y() >= 0 &&
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visible_rect.right() <= coded_size.width() &&
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visible_rect.bottom() <= coded_size.height() &&
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          !natural_size.IsEmpty() &&
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          natural_size.GetArea() <= limits::kMaxCanvas &&
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          natural_size.width() <= limits::kMaxDimension &&
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          natural_size.height() <= limits::kMaxDimension);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<gpu::MailboxHolder> mailbox_holder,
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReleaseMailboxCB& mailbox_holder_release_cb,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp,
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ReadPixelsCB& read_pixels_cb) {
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE,
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 coded_size,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 visible_rect,
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 natural_size,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 timestamp,
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 false));
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->mailbox_holder_ = mailbox_holder.Pass();
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->read_pixels_cb_ = read_pixels_cb;
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_pixels_cb_.is_null())
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_pixels_cb_.Run(pixels);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Format format,
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& coded_size,
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Rect& visible_rect,
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Size& natural_size,
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* data,
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    size_t data_size,
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::SharedMemoryHandle handle,
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    base::TimeDelta timestamp,
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& no_longer_needed_cb) {
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_size < AllocationSize(format, coded_size))
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return NULL;
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  switch (format) {
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420: {
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      scoped_refptr<VideoFrame> frame(new VideoFrame(
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          format, coded_size, visible_rect, natural_size, timestamp, false));
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->shared_memory_handle_ = handle;
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kYPlane] = coded_size.width();
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kUPlane] = coded_size.width() / 2;
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->strides_[kVPlane] = coded_size.width() / 2;
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kYPlane] = data;
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kUPlane] = data + coded_size.GetArea();
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4);
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      frame->no_longer_needed_cb_ = no_longer_needed_cb;
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return frame;
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    default:
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      NOTIMPLEMENTED();
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return NULL;
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Format format,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& coded_size,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& visible_rect,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& natural_size,
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 y_stride,
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 u_stride,
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int32 v_stride,
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* y_data,
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* u_data,
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    uint8* v_data,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timestamp,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(format == YV12 || format == YV16 || format == I420) << format;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      format, coded_size, visible_rect, natural_size, timestamp, false));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kYPlane] = y_stride;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kUPlane] = u_stride;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kVPlane] = v_stride;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kYPlane] = y_data;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kUPlane] = u_data;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kVPlane] = v_data;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const scoped_refptr<VideoFrame>& frame,
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::Closure& no_longer_needed_cb) {
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<VideoFrame> wrapped_frame(new VideoFrame(
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      frame->format(), frame->coded_size(), frame->visible_rect(),
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      frame->natural_size(), frame->GetTimestamp(), frame->end_of_stream()));
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->strides_[i] = frame->stride(i);
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wrapped_frame->data_[i] = frame->data(i);
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb;
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return wrapped_frame;
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return new VideoFrame(VideoFrame::UNKNOWN,
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Rect(),
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        gfx::Size(),
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        kNoTimestamp(),
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        true);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 y, uint8 u, uint8 v,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FillYUV(frame.get(), y, u, v);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackY = 0x00;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackUV = 0x80;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kZero;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maintained by the general compositor team. Please contact the following
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// people instead:
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wonsik@chromium.org
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ycheo@chromium.org
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& size) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta(), false));
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t VideoFrame::NumPlanes(Format format) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (format) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::HOLE:
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV12:
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV16:
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case VideoFrame::I420:
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 3;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 4;
2620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case VideoFrame::HISTOGRAM_MAX:
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline size_t RoundUp(size_t value, size_t alignment) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that |alignment| is a power of 2.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((value + (alignment - 1)) & ~(alignment-1));
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t total = 0;
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < NumPlanes(format); ++i)
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    total += PlaneAllocationSize(format, i, coded_size);
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return total;
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)size_t VideoFrame::PlaneAllocationSize(Format format,
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       size_t plane,
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       const gfx::Size& coded_size) {
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const size_t area =
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2);
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (format) {
291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV12:
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case VideoFrame::YV12J:
293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::I420: {
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area;
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area / 4;
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV12A: {
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kAPlane:
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area;
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area / 4;
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::YV16: {
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      switch (plane) {
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kYPlane:
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area;
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kUPlane:
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        case VideoFrame::kVPlane:
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          return area / 2;
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        default:
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          break;
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
326424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    case VideoFrame::UNKNOWN:
328424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case VideoFrame::HISTOGRAM_MAX:
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE)
331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case VideoFrame::HOLE:
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(VIDEO_HOLE)
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format/plane: "
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << format << "/" << plane;
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return 0;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Release data allocated by AllocateYUV().
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReleaseData(uint8* data) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(data);
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AlignedFree(data);
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateYUV() {
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 ||
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         format_ == VideoFrame::YV12J);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Align Y rows at least at 16 byte boundaries.  The stride for both
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the case of YV12 the strides are identical for the same width surface, but
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV16. We also round the height of the surface allocated to be an even
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number to avoid any potential of faulting by code that attempts to access
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Y values of the final row, but assumes that the last row of U & V
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // applies to a full two rows of Y. YV12A is the same as YV12, but with an
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // additional alpha plane that has the same size and alignment as the Y plane.
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kFrameSizeAlignment);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kFrameSizeAlignment);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The *2 here is because some formats (e.g. h264) allow interlaced coding,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then the size needs to be a multiple of two macroblocks (vertically).
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See libavcodec/utils.c:avcodec_align_dimensions2().
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  size_t uv_height =
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch       format_ == VideoFrame::I420)
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ? y_height / 2
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          : y_height;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_bytes = y_height * y_stride;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_bytes = uv_height * uv_stride;
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extra line of UV being allocated is because h264 chroma MC
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overreads by one line in some cases, see libavcodec/utils.c:
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // put_h264_chroma_mc4_ssse3().
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* data = reinterpret_cast<uint8*>(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AlignedAlloc(
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kFrameAddressAlignment));
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kYPlane] = data;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kUPlane] = data + y_bytes;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kYPlane] = y_stride;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kUPlane] = uv_stride;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kVPlane] = uv_stride;
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (format_ == YV12A) {
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    strides_[VideoFrame::kAPlane] = y_stride;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::VideoFrame(VideoFrame::Format format,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& coded_size,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Rect& visible_rect,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& natural_size,
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       base::TimeDelta timestamp,
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       bool end_of_stream)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : format_(format),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_size_(coded_size),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_rect_(visible_rect),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      natural_size_(natural_size),
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      shared_memory_handle_(base::SharedMemory::NULLHandle()),
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamp_(timestamp),
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      end_of_stream_(end_of_stream) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&strides_, 0, sizeof(strides_));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&data_, 0, sizeof(data_));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::~VideoFrame() {
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!mailbox_holder_release_cb_.is_null()) {
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ResetAndReturn(&mailbox_holder_release_cb_)
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        .Run(mailbox_holder_.Pass());
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!no_longer_needed_cb_.is_null())
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::ResetAndReturn(&no_longer_needed_cb_).Run();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidPlane(size_t plane) const {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (plane < NumPlanes(format_));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::stride(size_t plane) const {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return strides_[plane];
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::row_bytes(size_t plane) const {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = coded_size_.width();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Planar, 8bpp.
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case YV12A:
441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kAPlane)
442ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return width;
443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Fallthrough.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV12:
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420:
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case YV12J:
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kYPlane)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return width;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(width, 2) / 2;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::rows(size_t plane) const {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = coded_size_.height();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return height;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case YV12A:
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kAPlane)
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return height;
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Fallthrough.
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case YV12:
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case I420:
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (plane == kYPlane)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return height;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(height, 2) / 2;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint8* VideoFrame::data(size_t plane) const {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_[plane];
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gpu::MailboxHolder* VideoFrame::mailbox_holder() const {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return mailbox_holder_.get();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return shared_memory_handle_;
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int plane = 0; plane < kMaxPlanes; ++plane) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsValidPlane(plane))
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int row = 0; row < rows(plane); ++row) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::MD5Update(context, base::StringPiece(
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<char*>(data(plane) + stride(plane) * row),
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          row_bytes(plane)));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
514