video_frame.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// Use of this source code is governed by a BSD-style license that can be
36fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell// found in the LICENSE file.
46fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner#include "media/base/video_frame.h"
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner
7ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman#include <algorithm>
86fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell
9ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman#include "base/bind.h"
10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner#include "base/callback_helpers.h"
11c3aae25116e66c177579b0b79182b09340b19753Chris Lattner#include "base/logging.h"
12ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman#include "base/memory/aligned_memory.h"
13cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "base/strings/string_piece.h"
14cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "gpu/command_buffer/common/mailbox_holder.h"
15cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "media/base/limits.h"
16cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "media/base/video_util.h"
17cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "third_party/skia/include/core/SkBitmap.h"
18c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene
194b84086e89d86fb16f562166d9fea8df37db6be7Dan Gohmannamespace media {
20255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth
21444b4bf5c84c80833ff283244de0885124091a13Nadav Rotemstatic inline size_t RoundUp(size_t value, size_t alignment) {
22583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  // Check that |alignment| is a power of 2.
23c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
2498a366d547772010e94609e4584489b3e5ce0043Bill Wendling  return ((value + (alignment - 1)) & ~(alignment - 1));
25acaf09dbe4a6781163857db1321bbd5795e7d410Dan Gohman}
26322812e603705e1c2037313633e72f689524b163Evan Cheng
27eb19e40efbd3cae80c908a30cdf4d33450733c45Chris Lattner// static
28255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruthscoped_refptr<VideoFrame> VideoFrame::CreateFrame(
29d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke    VideoFrame::Format format,
30d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke    const gfx::Size& coded_size,
31fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    const gfx::Rect& visible_rect,
32fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    const gfx::Size& natural_size,
33b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling    base::TimeDelta timestamp) {
34b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling  // Since we're creating a new YUV frame (and allocating memory for it
3531441b7e95e0840e1ae144e5db6f791d6a36bc60Evan Cheng  // ourselves), we can pad the requested |coded_size| if necessary if the
36b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling  // request does not line up on sample boundaries.
37bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen  gfx::Size new_coded_size(coded_size);
38b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling  switch (format) {
39ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    case VideoFrame::YV12:
40fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    case VideoFrame::YV12A:
418e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet    case VideoFrame::I420:
428e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet    case VideoFrame::YV12J:
437309be6735666143bd9835b275dc8501617a2591Gabor Greif      new_coded_size.set_height((new_coded_size.height() + 1) / 2 * 2);
44fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    // Fallthrough.
45fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    case VideoFrame::YV16:
46c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif      new_coded_size.set_width((new_coded_size.width() + 1) / 2 * 2);
47fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman      break;
48fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    default:
49fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman      LOG(FATAL) << "Only YUV formats supported: " << format;
50c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif      return NULL;
51c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  }
52f3841fcbd587c31aa9842b3f33bd57de40c9f443Gabor Greif  DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
53c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  scoped_refptr<VideoFrame> frame(new VideoFrame(
54fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman      format, new_coded_size, visible_rect, natural_size, timestamp, false));
5550bee42b54cd9aec5f49566307df2b0cf23afcf6Craig Topper  frame->AllocateYUV();
56fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  return frame;
57fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman}
58fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
59fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman// static
60c3aae25116e66c177579b0b79182b09340b19753Chris Lattnerstd::string VideoFrame::FormatToString(VideoFrame::Format format) {
61bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen  switch (format) {
62bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen    case VideoFrame::UNKNOWN:
63bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      return "UNKNOWN";
64bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::YV12:
65bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      return "YV12";
66fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen    case VideoFrame::YV16:
67fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      return "YV16";
68fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen    case VideoFrame::I420:
69fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      return "I420";
70fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen    case VideoFrame::NATIVE_TEXTURE:
71fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      return "NATIVE_TEXTURE";
72bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen#if defined(VIDEO_HOLE)
73bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::HOLE:
74fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      return "HOLE";
75d4c6c3a7c3140ce487a805138b6f53f82ff6b783Devang Patel#endif  // defined(VIDEO_HOLE)
76bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen    case VideoFrame::YV12A:
77001d3dc976d7cda8a3dd8c7fd4020b0b96033f4eCraig Topper      return "YV12A";
78001d3dc976d7cda8a3dd8c7fd4020b0b96033f4eCraig Topper    case VideoFrame::YV12J:
79bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen      return "YV12J";
80bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen  }
81bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen  NOTREACHED() << "Invalid videoframe format provided: " << format;
82fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen  return "";
83fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen}
84fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen
85fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen// static
86bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Chengbool VideoFrame::IsValidConfig(VideoFrame::Format format,
87d4c6c3a7c3140ce487a805138b6f53f82ff6b783Devang Patel                               const gfx::Size& coded_size,
88bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen                               const gfx::Rect& visible_rect,
89bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng                               const gfx::Size& natural_size) {
90bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen  // Check maximum limits for all formats.
91d4c6c3a7c3140ce487a805138b6f53f82ff6b783Devang Patel  if (coded_size.GetArea() > limits::kMaxCanvas ||
92bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      coded_size.width() > limits::kMaxDimension ||
93fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      coded_size.height() > limits::kMaxDimension ||
94bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      visible_rect.x() < 0 || visible_rect.y() < 0 ||
95bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      visible_rect.right() > coded_size.width() ||
96bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      visible_rect.bottom() > coded_size.height() ||
97fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      natural_size.GetArea() > limits::kMaxCanvas ||
98bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen      natural_size.width() > limits::kMaxDimension ||
99bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng      natural_size.height() > limits::kMaxDimension)
10022a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer    return false;
10122a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer
10222a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer  // Check format-specific width/height requirements.
10322a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer  switch (format) {
10422a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer    case VideoFrame::UNKNOWN:
10522a54c1cd711afccd4558374918d12a939e1cca5Benjamin Kramer      return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
106bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen              natural_size.IsEmpty());
107bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::YV12:
108bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::YV12J:
109bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::I420:
110bfcb3051899b7141a946d769fcf6e8a8453bc530Evan Cheng    case VideoFrame::YV12A:
111fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      // YUV formats have width/height requirements due to chroma subsampling.
112fdb42fa5fe794cc2c89e2ed7f57a89ed24d9952aDale Johannesen      if (static_cast<size_t>(coded_size.height()) <
113bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen          RoundUp(visible_rect.bottom(), 2))
114bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen        return false;
115cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene    // Fallthrough.
116cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene    case VideoFrame::YV16:
117cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene      if (static_cast<size_t>(coded_size.width()) <
118cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene          RoundUp(visible_rect.right(), 2))
119c3aae25116e66c177579b0b79182b09340b19753Chris Lattner        return false;
120c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      break;
121c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    case VideoFrame::NATIVE_TEXTURE:
122c3aae25116e66c177579b0b79182b09340b19753Chris Lattner#if defined(VIDEO_HOLE)
123c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    case VideoFrame::HOLE:
124c3aae25116e66c177579b0b79182b09340b19753Chris Lattner#endif  // defined(VIDEO_HOLE)
125c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
126c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      // allowed to skip the below check and be empty.
127c3aae25116e66c177579b0b79182b09340b19753Chris Lattner      return true;
128c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  }
129cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner
130cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  // Check that software-allocated buffer formats are not empty.
13150d2b1ac029d63500ea9b9347561b1454fa6ed6aDan Gohman  return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
132d858e90f039f5fcdc2fa93035e911a5a9505cc50Dan Gohman          !natural_size.IsEmpty());
133ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman}
1347c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman
135512063dd0f91a76b9dd904dfff72a52b4d09e89fChris Lattner// static
1360508d047fefef36d4f943ee13c82c18cf3a943abDevang Patelscoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
137cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    scoped_ptr<gpu::MailboxHolder> mailbox_holder,
138f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    const ReleaseMailboxCB& mailbox_holder_release_cb,
139f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    const gfx::Size& coded_size,
140f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    const gfx::Rect& visible_rect,
141f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    const gfx::Size& natural_size,
142f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    base::TimeDelta timestamp,
143cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    const ReadPixelsCB& read_pixels_cb) {
144213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner  scoped_refptr<VideoFrame> frame(new VideoFrame(NATIVE_TEXTURE,
145fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman                                                 coded_size,
146fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman                                                 visible_rect,
147f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman                                                 natural_size,
148f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman                                                 timestamp,
149f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman                                                 false));
150f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  frame->mailbox_holder_ = mailbox_holder.Pass();
151f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  frame->mailbox_holder_release_cb_ = mailbox_holder_release_cb;
152f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  frame->read_pixels_cb_ = read_pixels_cb;
153f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
154f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  return frame;
155691ef2ba066dda14ae4ac0ad645054fbc967785aAndrew Lenharth}
156213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner
157d23b33435ae722ff5aa5ab97135a4f31041959e2Bob Wilsonvoid VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) {
158583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey  DCHECK_EQ(format_, NATIVE_TEXTURE);
159213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner  if (!read_pixels_cb_.is_null())
160f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    read_pixels_cb_.Run(pixels);
161f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman}
162f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
163e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman// static
164e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohmanscoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory(
165e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman    Format format,
166e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman    const gfx::Size& coded_size,
167b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling    const gfx::Rect& visible_rect,
168b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling    const gfx::Size& natural_size,
169b4e6a5df5dada0cd919cc6e2717eb3118db9cc45Bill Wendling    uint8* data,
170819309efec6f11ba752bd7cbfe186495745f020bDaniel Dunbar    size_t data_size,
171bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen    base::SharedMemoryHandle handle,
172bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen    base::TimeDelta timestamp,
173bfdf7f38523bd38ae0538861a2bfd8bdc46e5c33Dale Johannesen    const base::Closure& no_longer_needed_cb) {
174bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
175bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    return NULL;
176bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen  if (data_size < AllocationSize(format, coded_size))
177bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    return NULL;
178bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen
179bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen  switch (format) {
180bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    case I420: {
181bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      scoped_refptr<VideoFrame> frame(new VideoFrame(
182bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen          format, coded_size, visible_rect, natural_size, timestamp, false));
183bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->shared_memory_handle_ = handle;
184bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->strides_[kYPlane] = coded_size.width();
185bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->strides_[kUPlane] = coded_size.width() / 2;
186bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->strides_[kVPlane] = coded_size.width() / 2;
187bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->data_[kYPlane] = data;
188bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->data_[kUPlane] = data + coded_size.GetArea();
189bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4);
190bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      frame->no_longer_needed_cb_ = no_longer_needed_cb;
191bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      return frame;
192bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    }
193bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    default:
194bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      NOTIMPLEMENTED();
195bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen      return NULL;
196bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen  }
197bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen}
198bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen
199bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen// static
200bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesenscoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
201bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    Format format,
202bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    const gfx::Size& coded_size,
203bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    const gfx::Rect& visible_rect,
204bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    const gfx::Size& natural_size,
205bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    int32 y_stride,
206bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    int32 u_stride,
207bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    int32 v_stride,
208bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    uint8* y_data,
209bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    uint8* u_data,
210bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    uint8* v_data,
211bc7d448f242b1bbc1031fb87cd69c285ff9aaffaJakob Stoklund Olesen    base::TimeDelta timestamp,
212c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene    const base::Closure& no_longer_needed_cb) {
213c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
214c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene    return NULL;
215c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif
216c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  scoped_refptr<VideoFrame> frame(new VideoFrame(
217c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene      format, coded_size, visible_rect, natural_size, timestamp, false));
218c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  frame->strides_[kYPlane] = y_stride;
219001d3dc976d7cda8a3dd8c7fd4020b0b96033f4eCraig Topper  frame->strides_[kUPlane] = u_stride;
220001d3dc976d7cda8a3dd8c7fd4020b0b96033f4eCraig Topper  frame->strides_[kVPlane] = v_stride;
221819309efec6f11ba752bd7cbfe186495745f020bDaniel Dunbar  frame->data_[kYPlane] = y_data;
222cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  frame->data_[kUPlane] = u_data;
2230508d047fefef36d4f943ee13c82c18cf3a943abDevang Patel  frame->data_[kVPlane] = v_data;
224cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  frame->no_longer_needed_cb_ = no_longer_needed_cb;
225cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  return frame;
2267c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman}
2277c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman
2287c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman// static
229de6e783b2490447866b592cd39855e6f4d25efffChris Lattnerscoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame(
2307c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      const scoped_refptr<VideoFrame>& frame,
2317c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      const gfx::Rect& visible_rect,
232f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      const gfx::Size& natural_size,
233f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman      const base::Closure& no_longer_needed_cb) {
2347c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman  // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support
235f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  // for that here yet, see http://crbug/362521.
2367c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman  CHECK(frame->format() != NATIVE_TEXTURE);
23750d2b1ac029d63500ea9b9347561b1454fa6ed6aDan Gohman
238d858e90f039f5fcdc2fa93035e911a5a9505cc50Dan Gohman  DCHECK(frame->visible_rect().Contains(visible_rect));
239ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  scoped_refptr<VideoFrame> wrapped_frame(new VideoFrame(
240d1474d09cbe5fdeec8ba0d6c6b52f316f3422532Owen Anderson      frame->format(), frame->coded_size(), visible_rect, natural_size,
241cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner      frame->timestamp(), frame->end_of_stream()));
242ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey
2431080b9ee534579c67f7c99364cc6fa11edbcd919Chris Lattner  for (size_t i = 0; i < NumPlanes(frame->format()); ++i) {
244462dc7f4960e5074ddf4769ec8b2ef1ba7a4d2c8Dan Gohman    wrapped_frame->strides_[i] = frame->stride(i);
2450b12aef49087b57d276ed760a83525d1e2602144Dan Gohman    wrapped_frame->data_[i] = frame->data(i);
246fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  }
247ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey
248ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey  wrapped_frame->no_longer_needed_cb_ = no_longer_needed_cb;
249ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey  return wrapped_frame;
2501080b9ee534579c67f7c99364cc6fa11edbcd919Chris Lattner}
251ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey
252ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey// static
253ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskeyscoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {
254fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  return new VideoFrame(VideoFrame::UNKNOWN,
255ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey                        gfx::Size(),
256ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey                        gfx::Rect(),
257ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey                        gfx::Size(),
258fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel                        kNoTimestamp(),
259ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey                        true);
260ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey}
261ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey
262fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel// static
263ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskeyscoped_refptr<VideoFrame> VideoFrame::CreateColorFrame(
264ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey    const gfx::Size& size,
265ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey    uint8 y, uint8 u, uint8 v,
2661080b9ee534579c67f7c99364cc6fa11edbcd919Chris Lattner    base::TimeDelta timestamp) {
267c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
268c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene      VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
269c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  FillYUV(frame.get(), y, u, v);
270c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  return frame;
271fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman}
272b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner
273b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner// static
274fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohmanscoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) {
275b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner  const uint8 kBlackY = 0x00;
276b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner  const uint8 kBlackUV = 0x80;
277fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  const base::TimeDelta kZero;
2780e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman  return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero);
2790e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman}
280fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel
281c3aae25116e66c177579b0b79182b09340b19753Chris Lattner#if defined(VIDEO_HOLE)
282cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner// This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not
283475871a144eb604ddaf37503397ba0941442e5fbDan Gohman// maintained by the general compositor team. Please contact the following
284cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner// people instead:
285c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//
286c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// wonsik@chromium.org
287f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman// ycheo@chromium.org
288f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
289f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman// static
290cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattnerscoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame(
291c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    const gfx::Size& size) {
292cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size));
293475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  scoped_refptr<VideoFrame> frame(new VideoFrame(
294825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta(), false));
295acaf09dbe4a6781163857db1321bbd5795e7d410Dan Gohman  return frame;
296cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene}
297cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene#endif  // defined(VIDEO_HOLE)
298cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene
299cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene// static
300cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greenesize_t VideoFrame::NumPlanes(Format format) {
301cf495bc2e505e52ad018da55bed11c7b8bc97db5David Greene  switch (format) {
302acaf09dbe4a6781163857db1321bbd5795e7d410Dan Gohman    case VideoFrame::NATIVE_TEXTURE:
303cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#if defined(VIDEO_HOLE)
3041d4d41411190dd9e62764e56713753d4155764ddNate Begeman    case VideoFrame::HOLE:
30525cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands#endif  // defined(VIDEO_HOLE)
30625cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands      return 0;
30725cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands    case VideoFrame::YV12:
30898a366d547772010e94609e4584489b3e5ce0043Bill Wendling    case VideoFrame::YV16:
30998a366d547772010e94609e4584489b3e5ce0043Bill Wendling    case VideoFrame::I420:
31025cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands    case VideoFrame::YV12J:
31101d029b82cb08367d81aa10cdc94d05360466649Chris Lattner      return 3;
31225cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands    case VideoFrame::YV12A:
31325cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands      return 4;
31401d029b82cb08367d81aa10cdc94d05360466649Chris Lattner    case VideoFrame::UNKNOWN:
31501d029b82cb08367d81aa10cdc94d05360466649Chris Lattner      break;
31601d029b82cb08367d81aa10cdc94d05360466649Chris Lattner  }
31725cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  NOTREACHED() << "Unsupported video frame format: " << format;
31825cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  return 0;
319c3aae25116e66c177579b0b79182b09340b19753Chris Lattner}
320c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
321c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
322cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner// static
323c3aae25116e66c177579b0b79182b09340b19753Chris Lattnersize_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
324c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  size_t total = 0;
325975716af1b9a09274df6c2d92683449015bd8564Dan Gohman  for (size_t i = 0; i < NumPlanes(format); ++i)
326c3aae25116e66c177579b0b79182b09340b19753Chris Lattner    total += PlaneAllocationSize(format, i, coded_size);
3275c22c8074404797f1313b1334757254fb5c6487aEli Friedman  return total;
3285c22c8074404797f1313b1334757254fb5c6487aEli Friedman}
3295c22c8074404797f1313b1334757254fb5c6487aEli Friedman
3305c22c8074404797f1313b1334757254fb5c6487aEli Friedman// static
3315c22c8074404797f1313b1334757254fb5c6487aEli Friedmangfx::Size VideoFrame::PlaneSize(Format format,
3325c22c8074404797f1313b1334757254fb5c6487aEli Friedman                                size_t plane,
3335c22c8074404797f1313b1334757254fb5c6487aEli Friedman                                const gfx::Size& coded_size) {
3345c22c8074404797f1313b1334757254fb5c6487aEli Friedman  const int width = RoundUp(coded_size.width(), 2);
3355c22c8074404797f1313b1334757254fb5c6487aEli Friedman  const int height = RoundUp(coded_size.height(), 2);
3365c22c8074404797f1313b1334757254fb5c6487aEli Friedman  switch (format) {
3375c22c8074404797f1313b1334757254fb5c6487aEli Friedman    case VideoFrame::YV12:
3385c22c8074404797f1313b1334757254fb5c6487aEli Friedman    case VideoFrame::YV12J:
3395c22c8074404797f1313b1334757254fb5c6487aEli Friedman    case VideoFrame::I420: {
340d1fc96499b7619356c7542200d32da898b79f7c1Chris Lattner      switch (plane) {
341190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner        case VideoFrame::kYPlane:
342190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner          return gfx::Size(width, height);
343130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng        case VideoFrame::kUPlane:
344130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng        case VideoFrame::kVPlane:
345130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng          return gfx::Size(width / 2, height / 2);
346130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng        default:
347130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng          break;
34870046e920fa37989a041af663ada2b2b646e258fChris Lattner      }
34970046e920fa37989a041af663ada2b2b646e258fChris Lattner    }
350e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    case VideoFrame::YV12A: {
351e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson      switch (plane) {
352e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson        case VideoFrame::kYPlane:
353e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson        case VideoFrame::kAPlane:
354e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson          return gfx::Size(width, height);
355fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel        case VideoFrame::kUPlane:
3561b1a49714ef26225a42199cf2930529f31868322Chris Lattner        case VideoFrame::kVPlane:
35770046e920fa37989a041af663ada2b2b646e258fChris Lattner          return gfx::Size(width / 2, height / 2);
35870046e920fa37989a041af663ada2b2b646e258fChris Lattner        default:
359e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson          break;
360e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson      }
361e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    }
362475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    case VideoFrame::YV16: {
363e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson      switch (plane) {
364cbea3045ce0bdd061c494a831d0ce2d5834211ccChris Lattner        case VideoFrame::kYPlane:
365cbea3045ce0bdd061c494a831d0ce2d5834211ccChris Lattner          return gfx::Size(width, height);
366e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson        case VideoFrame::kUPlane:
3676394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman        case VideoFrame::kVPlane:
3686394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman          return gfx::Size(width / 2, height);
369e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson        default:
3704fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman          break;
3714fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman      }
3720a406ae0d940d92c51ee145b48ff7a483a366849Dale Johannesen    }
3730a406ae0d940d92c51ee145b48ff7a483a366849Dale Johannesen    case VideoFrame::UNKNOWN:
374e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    case VideoFrame::NATIVE_TEXTURE:
375e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson#if defined(VIDEO_HOLE)
376e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    case VideoFrame::HOLE:
377e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson#endif  // defined(VIDEO_HOLE)
378c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner      break;
379c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  }
380e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  NOTREACHED() << "Unsupported video frame format/plane: "
381f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen               << format << "/" << plane;
382f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen  return gfx::Size();
383e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson}
3844fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman
3854fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohmansize_t VideoFrame::PlaneAllocationSize(Format format,
3860d881dabc1a4e1aefad6dd38de166d8358285638Devang Patel                                       size_t plane,
3872a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner                                       const gfx::Size& coded_size) {
3882a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner  // VideoFrame formats are (so far) all YUV and 1 byte per sample.
3890d881dabc1a4e1aefad6dd38de166d8358285638Devang Patel  return PlaneSize(format, plane, coded_size).GetArea();
3902a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner}
3912a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner
3920d881dabc1a4e1aefad6dd38de166d8358285638Devang Patel// Release data allocated by AllocateYUV().
393cbea3045ce0bdd061c494a831d0ce2d5834211ccChris Lattnerstatic void ReleaseData(uint8* data) {
394e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  DCHECK(data);
395e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  base::AlignedFree(data);
396c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner}
397c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner
398e50ed30282bb5b4a9ed952580523f2dda16215acOwen Andersonvoid VideoFrame::AllocateYUV() {
399f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
400e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson         format_ == VideoFrame::YV12A || format_ == VideoFrame::I420 ||
401f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner         format_ == VideoFrame::YV12J);
402c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  // Align Y rows at least at 16 byte boundaries.  The stride for both
40346510a73e977273ec67747eb34cbdb43f815e451Dan Gohman  // YV12 and YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for
404f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
405f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // the case of YV12 the strides are identical for the same width surface, but
40646510a73e977273ec67747eb34cbdb43f815e451Dan Gohman  // the number of bytes allocated for YV12 is 1/2 the amount for U & V as
407f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // YV16. We also round the height of the surface allocated to be an even
408f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // number to avoid any potential of faulting by code that attempts to access
409f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // the Y values of the final row, but assumes that the last row of U & V
410c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner  // applies to a full two rows of Y. YV12A is the same as YV12, but with an
411e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  // additional alpha plane that has the same size and alignment as the Y plane.
412f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner
413f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane),
414475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                            kFrameSizeAlignment);
415e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane),
416f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner                             kFrameSizeAlignment);
417f5a5546f435a261c93078defb41ed18d9cafd7d3Chris Lattner  // The *2 here is because some formats (e.g. h264) allow interlaced coding,
418d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng  // and then the size needs to be a multiple of two macroblocks (vertically).
41974500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen  // See libavcodec/utils.c:avcodec_align_dimensions2().
42074500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen  size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
4218ad9b43e690e8773cf836b30e8da26bc71e18844Dale Johannesen  size_t uv_height =
4228ad9b43e690e8773cf836b30e8da26bc71e18844Dale Johannesen      (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
423475871a144eb604ddaf37503397ba0941442e5fbDan Gohman       format_ == VideoFrame::I420)
424e8c17335c53f0f37262ee342f46b0d00ac0c1493Dale Johannesen          ? y_height / 2
425e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson          : y_height;
426e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  size_t y_bytes = y_height * y_stride;
427e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  size_t uv_bytes = uv_height * uv_stride;
4281af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner  size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
429e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson
430e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  // The extra line of UV being allocated is because h264 chroma MC
4319cf37e8b48732fccd4c301ed51aafed7074bd84eJakob Stoklund Olesen  // overreads by one line in some cases, see libavcodec/utils.c:
4327561d480953e0a2faa4af9be0a00b1180097c4bdChris Lattner  // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm:
43346510a73e977273ec67747eb34cbdb43f815e451Dan Gohman  // put_h264_chroma_mc4_ssse3().
4346c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao  uint8* data = reinterpret_cast<uint8*>(
4356c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao      base::AlignedAlloc(
4366c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao          y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding,
4376c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao          kFrameAddressAlignment));
4386c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao  no_longer_needed_cb_ = base::Bind(&ReleaseData, data);
4396c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao  COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
4406c7ccaa3fd1d6e96d0bf922554b09d2b17c3b0e3Michael Liao  data_[VideoFrame::kYPlane] = data;
441c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  data_[VideoFrame::kUPlane] = data + y_bytes;
4420f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen  data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
443825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  strides_[VideoFrame::kYPlane] = y_stride;
4440f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen  strides_[VideoFrame::kUPlane] = uv_stride;
4450f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen  strides_[VideoFrame::kVPlane] = uv_stride;
446cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  if (format_ == YV12A) {
447e3f1026683c38f6605ccaf698b7082f1b0a0f8c8Chris Lattner    data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes);
44829d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner    strides_[VideoFrame::kAPlane] = y_stride;
44929d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  }
4500f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen}
45129d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner
452f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris LattnerVideoFrame::VideoFrame(VideoFrame::Format format,
45329d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner                       const gfx::Size& coded_size,
45429d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner                       const gfx::Rect& visible_rect,
4550f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen                       const gfx::Size& natural_size,
45666a48bbc3565b40ea0e6f2d58cf5e3a8e64802efEvan Cheng                       base::TimeDelta timestamp,
457475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                       bool end_of_stream)
4580f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen    : format_(format),
45929d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner      coded_size_(coded_size),
460f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris Lattner      visible_rect_(visible_rect),
46129d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner      natural_size_(natural_size),
46229d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner      shared_memory_handle_(base::SharedMemory::NULLHandle()),
4630f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen      timestamp_(timestamp),
464fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel      end_of_stream_(end_of_stream) {
465e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_));
466825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson
4670f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen  memset(&strides_, 0, sizeof(strides_));
468fc1665793e62eb4f26d24b8a19eecf59cd872e2aDan Gohman  memset(&data_, 0, sizeof(data_));
4690f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen}
470fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel
471e3f1026683c38f6605ccaf698b7082f1b0a0f8c8Chris LattnerVideoFrame::~VideoFrame() {
47229d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  if (!mailbox_holder_release_cb_.is_null()) {
47329d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner    base::ResetAndReturn(&mailbox_holder_release_cb_)
474e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson        .Run(mailbox_holder_.Pass());
47529d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  }
476f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris Lattner  if (!no_longer_needed_cb_.is_null())
47729d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner    base::ResetAndReturn(&no_longer_needed_cb_).Run();
47829d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner}
4790f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen
48018c2f13e0f9d0e5d6227cf6d1881e9ee3d1b6109Chris Lattnerbool VideoFrame::IsValidPlane(size_t plane) const {
481475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  return (plane < NumPlanes(format_));
482cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner}
48377cdf30742284a173fe818417eb482224cdee8d4Mon P Wang
48477cdf30742284a173fe818417eb482224cdee8d4Mon P Wangint VideoFrame::stride(size_t plane) const {
485e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  DCHECK(IsValidPlane(plane));
4860f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen  return strides_[plane];
4870f502f6f44f2756f5cb7b17d8f1d8eae000d51b4Dale Johannesen}
4886154f6c9292179fab6346ae8336f2ad790b52028Owen Anderson
4899008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begemanint VideoFrame::row_bytes(size_t plane) const {
4909008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman  DCHECK(IsValidPlane(plane));
4915a5ca1519e04310f585197c20e7ae584b7f2d11fNate Begeman  int width = coded_size_.width();
4929008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman  switch (format_) {
4936154f6c9292179fab6346ae8336f2ad790b52028Owen Anderson    // Planar, 8bpp.
4949008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman    case YV12A:
49577cdf30742284a173fe818417eb482224cdee8d4Mon P Wang      if (plane == kAPlane)
496a3c42f3d4e5d14c8f4fb9bb123e7759c425d041bNadav Rotem        return width;
497a3c42f3d4e5d14c8f4fb9bb123e7759c425d041bNadav Rotem    // Fallthrough.
498a3c42f3d4e5d14c8f4fb9bb123e7759c425d041bNadav Rotem    case YV12:
499a3c42f3d4e5d14c8f4fb9bb123e7759c425d041bNadav Rotem    case YV16:
5003a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands    case I420:
5013a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands    case YV12J:
5023a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands      if (plane == kYPlane)
5033a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands        return width;
5043a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands      return RoundUp(width, 2) / 2;
5053a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands
5063a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands    default:
5073a66a68b0cc81193abfc074b1d360a4950151d38Duncan Sands      break;
5081ccae666f596d5aeca5c9942995763600b622062Chris Lattner  }
5091ccae666f596d5aeca5c9942995763600b622062Chris Lattner
510e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  // Intentionally leave out non-production formats.
511fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel  NOTREACHED() << "Unsupported video frame format: " << format_;
5124c2454623841f05c6c665659b34c214950d12d7eBob Wilson  return 0;
513e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson}
5144c2454623841f05c6c665659b34c214950d12d7eBob Wilson
5156a5b6d7633c96c72ca7d5f8ba0c855e4690ada04Chris Lattnerint VideoFrame::rows(size_t plane) const {
51629d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  DCHECK(IsValidPlane(plane));
517e8d7230f480654cdb8ff1c3d0a38e1e9ab0bd55fDale Johannesen  int height = coded_size_.height();
518475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  switch (format_) {
519f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris Lattner    case YV16:
520475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      return height;
521b494ccf02ce17318d3f2a7b2d674bec60781fc73Chris Lattner
5226a5b6d7633c96c72ca7d5f8ba0c855e4690ada04Chris Lattner    case YV12A:
5231ccae666f596d5aeca5c9942995763600b622062Chris Lattner      if (plane == kAPlane)
5240f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling        return height;
52529d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner    // Fallthrough.
526e8d7230f480654cdb8ff1c3d0a38e1e9ab0bd55fDale Johannesen    case YV12:
527475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    case I420:
52829d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner      if (plane == kYPlane)
529f1b4eafbfec976f939ec0ea3e8acf91cef5363e3Chris Lattner        return height;
530475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      return RoundUp(height, 2) / 2;
5310f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling
5320f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling    default:
5330f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling      break;
53429d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  }
535b494ccf02ce17318d3f2a7b2d674bec60781fc73Chris Lattner
53629d8f0cae425f1bba583565227eaebf58f26ce73Chris Lattner  // Intentionally leave out non-production formats.
5370f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling  NOTREACHED() << "Unsupported video frame format: " << format_;
5380f8d9c04d9feef86cee35cf5fecfb348a6b3de50Bill Wendling  return 0;
539e8d7230f480654cdb8ff1c3d0a38e1e9ab0bd55fDale Johannesen}
540e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson
541b494ccf02ce17318d3f2a7b2d674bec60781fc73Chris Lattneruint8* VideoFrame::data(size_t plane) const {
542e8d7230f480654cdb8ff1c3d0a38e1e9ab0bd55fDale Johannesen  DCHECK(IsValidPlane(plane));
543e8d7230f480654cdb8ff1c3d0a38e1e9ab0bd55fDale Johannesen  return data_[plane];
544b300d2aa3ef08b5074449e2c05804717f488f4e4Dale Johannesen}
545b300d2aa3ef08b5074449e2c05804717f488f4e4Dale Johannesen
546e50ed30282bb5b4a9ed952580523f2dda16215acOwen Andersongpu::MailboxHolder* VideoFrame::mailbox_holder() const {
547b494ccf02ce17318d3f2a7b2d674bec60781fc73Chris Lattner  DCHECK_EQ(format_, NATIVE_TEXTURE);
548b300d2aa3ef08b5074449e2c05804717f488f4e4Dale Johannesen  return mailbox_holder_.get();
549b300d2aa3ef08b5074449e2c05804717f488f4e4Dale Johannesen}
550c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
551cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattnerbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const {
552e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  return shared_memory_handle_;
553e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson}
554e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson
555e50ed30282bb5b4a9ed952580523f2dda16215acOwen Andersonvoid VideoFrame::HashFrameForTesting(base::MD5Context* context) {
5567ade28cd62f5188951387e1056a46001388a21f9Bill Wendling  for (int plane = 0; plane < kMaxPlanes; ++plane) {
557e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    if (!IsValidPlane(plane))
5587ade28cd62f5188951387e1056a46001388a21f9Bill Wendling      break;
559e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    for (int row = 0; row < rows(plane); ++row) {
5607ade28cd62f5188951387e1056a46001388a21f9Bill Wendling      base::MD5Update(context, base::StringPiece(
5617ade28cd62f5188951387e1056a46001388a21f9Bill Wendling          reinterpret_cast<char*>(data(plane) + stride(plane) * row),
562e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson          row_bytes(plane)));
5637ade28cd62f5188951387e1056a46001388a21f9Bill Wendling    }
564e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  }
5657ade28cd62f5188951387e1056a46001388a21f9Bill Wendling}
5667ade28cd62f5188951387e1056a46001388a21f9Bill Wendling
567e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson}  // namespace media
5687ade28cd62f5188951387e1056a46001388a21f9Bill Wendling