video_frame.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
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"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_util.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoFrame::Format format,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& coded_size,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& visible_rect,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& natural_size,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size));
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      format, coded_size, visible_rect, natural_size, timestamp));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::RGB32:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame->AllocateRGB(4u);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV12:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VideoFrame::YV16:
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) {
483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::INVALID:
493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "INVALID";
503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::RGB32:
513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "RGB32";
523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12:
533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12";
543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV16:
553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV16";
563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::EMPTY:
573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "EMPTY";
583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::I420:
593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "I420";
603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::NATIVE_TEXTURE:
613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "NATIVE_TEXTURE";
623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#if defined(GOOGLE_TV)
633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::HOLE:
643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "HOLE";
653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#endif
663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    case VideoFrame::YV12A:
673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return "YV12A";
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) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (format != VideoFrame::INVALID &&
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(
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const scoped_refptr<MailboxHolder>& mailbox_holder,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 texture_target,
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,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ReadPixelsCB& read_pixels_cb,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NATIVE_TEXTURE, coded_size, visible_rect, natural_size, timestamp));
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  frame->texture_mailbox_holder_ = mailbox_holder;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->texture_target_ = texture_target;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->read_pixels_cb_ = read_pixels_cb;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_pixels_cb_.is_null())
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_pixels_cb_.Run(pixels);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Format format,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& coded_size,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Rect& visible_rect,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& natural_size,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32 y_stride, int32 u_stride, int32 v_stride,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint8* y_data, uint8* u_data, uint8* v_data,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timestamp,
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::SharedMemoryHandle shm_handle,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& no_longer_needed_cb) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(format == YV12 || format == YV16 || format == I420) << format;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      format, coded_size, visible_rect, natural_size, timestamp));
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  frame->shared_memory_handle_ = shm_handle;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kYPlane] = y_stride;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kUPlane] = u_stride;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->strides_[kVPlane] = v_stride;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kYPlane] = y_data;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kUPlane] = u_data;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->data_[kVPlane] = v_data;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  frame->no_longer_needed_cb_ = no_longer_needed_cb;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new VideoFrame(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::EMPTY, gfx::Size(), gfx::Rect(), gfx::Size(),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 y, uint8 u, uint8 v,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timestamp) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FillYUV(frame.get(), y, u, v);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackY = 0x00;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kBlackUV = 0x80;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kZero;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GOOGLE_TV)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maintained by the general compositor team. Please contact the following
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// people instead:
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wonsik@chromium.org
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ycheo@chromium.org
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& size) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<VideoFrame> frame(new VideoFrame(
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta()));
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return frame;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t VideoFrame::NumPlanes(Format format) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (format) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::NATIVE_TEXTURE:
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GOOGLE_TV)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::HOLE:
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::RGB32:
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 1;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV12:
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::YV16:
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 3;
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case VideoFrame::YV12A:
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 4;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::EMPTY:
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::I420:
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case VideoFrame::INVALID:
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline size_t RoundUp(size_t value, size_t alignment) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that |alignment| is a power of 2.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((value + (alignment - 1)) & ~(alignment-1));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Release data allocated by AllocateRGB() or AllocateYUV().
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReleaseData(uint8* data) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(data);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AlignedFree(data);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Round up to align at least at a 16-byte boundary for each row.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is sufficient for MMX and SSE2 reads (movq/movdqa).
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_per_row = RoundUp(coded_size_.width(),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 kFrameSizeAlignment) * bytes_per_pixel;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kRGBPlane] = bytes_per_row;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>(
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         kFrameAddressAlignment));
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateYUV() {
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         format_ == VideoFrame::YV12A);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Align Y rows at least at 16 byte boundaries.  The stride for both
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the case of YV12 the strides are identical for the same width surface, but
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // YV16. We also round the height of the surface allocated to be an even
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number to avoid any potential of faulting by code that attempts to access
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Y values of the final row, but assumes that the last row of U & V
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // applies to a full two rows of Y. YV12A is the same as YV12, but with an
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // additional alpha plane that has the same size and alignment as the Y plane.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            kFrameSizeAlignment);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kFrameSizeAlignment);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The *2 here is because some formats (e.g. h264) allow interlaced coding,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then the size needs to be a multiple of two macroblocks (vertically).
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See libavcodec/utils.c:avcodec_align_dimensions2().
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t uv_height = (format_ == VideoFrame::YV12 ||
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      format_ == VideoFrame::YV12A) ?
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              y_height / 2 : y_height;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t y_bytes = y_height * y_stride;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t uv_bytes = uv_height * uv_stride;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extra line of UV being allocated is because h264 chroma MC
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overreads by one line in some cases, see libavcodec/utils.c:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // put_h264_chroma_mc4_ssse3().
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* data = reinterpret_cast<uint8*>(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AlignedAlloc(
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding,
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kFrameAddressAlignment));
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kYPlane] = data;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kUPlane] = data + y_bytes;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kYPlane] = y_stride;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kUPlane] = uv_stride;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strides_[VideoFrame::kVPlane] = uv_stride;
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (format_ == YV12A) {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    strides_[VideoFrame::kAPlane] = y_stride;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::VideoFrame(VideoFrame::Format format,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& coded_size,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Rect& visible_rect,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::Size& natural_size,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::TimeDelta timestamp)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : format_(format),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coded_size_(coded_size),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible_rect_(visible_rect),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      natural_size_(natural_size),
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      texture_target_(0),
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      shared_memory_handle_(base::SharedMemory::NULLHandle()),
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timestamp_(timestamp) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&strides_, 0, sizeof(strides_));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&data_, 0, sizeof(data_));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::~VideoFrame() {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!no_longer_needed_cb_.is_null())
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::ResetAndReturn(&no_longer_needed_cb_).Run();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidPlane(size_t plane) const {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (plane < NumPlanes(format_));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::stride(size_t plane) const {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return strides_[plane];
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::row_bytes(size_t plane) const {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = coded_size_.width();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 32bpp.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RGB32:
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return width * 4;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Planar, 8bpp.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV12:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case YV12A:
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (plane == kYPlane || plane == kAPlane)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return width;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(width, 2) / 2;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::rows(size_t plane) const {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height = coded_size_.height();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (format_) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RGB32:
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV16:
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return height;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case YV12:
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case YV12A:
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (plane == kYPlane || plane == kAPlane)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return height;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return RoundUp(height, 2) / 2;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Intentionally leave out non-production formats.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Unsupported video frame format: " << format_;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint8* VideoFrame::data(size_t plane) const {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsValidPlane(plane));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_[plane];
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst scoped_refptr<VideoFrame::MailboxHolder>& VideoFrame::texture_mailbox()
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return texture_mailbox_holder_;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 VideoFrame::texture_target() const {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(format_, NATIVE_TEXTURE);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return texture_target_;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return shared_memory_handle_;
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsEndOfStream() const {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return format_ == VideoFrame::EMPTY;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int plane = 0; plane < kMaxPlanes; ++plane) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsValidPlane(plane))
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int row = 0; row < rows(plane); ++row) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::MD5Update(context, base::StringPiece(
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<char*>(data(plane) + stride(plane) * row),
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          row_bytes(plane)));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochVideoFrame::MailboxHolder::MailboxHolder(
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gpu::Mailbox& mailbox,
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    unsigned sync_point,
408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const TextureNoLongerNeededCallback& release_callback)
409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : mailbox_(mailbox),
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sync_point_(sync_point),
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      release_callback_(release_callback) {}
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochVideoFrame::MailboxHolder::~MailboxHolder() {
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!release_callback_.is_null())
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    release_callback_.Run(sync_point_);
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
419