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