video_frame.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback_helpers.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/aligned_memory.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_util.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateFrame( 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame::Format format, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<VideoFrame> frame(new VideoFrame( 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format, coded_size, visible_rect, natural_size, timestamp)); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (format) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VideoFrame::RGB32: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->AllocateRGB(4u); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VideoFrame::YV12: 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case VideoFrame::YV12A: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case VideoFrame::YV16: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->AllocateYUV(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << "Unsupported frame format: " << format; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidConfig(VideoFrame::Format format, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (format != VideoFrame::INVALID && 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !coded_size.IsEmpty() && 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coded_size.GetArea() <= limits::kMaxCanvas && 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coded_size.width() <= limits::kMaxDimension && 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coded_size.height() <= limits::kMaxDimension && 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !visible_rect.IsEmpty() && 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_rect.x() >= 0 && visible_rect.y() >= 0 && 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_rect.right() <= coded_size.width() && 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_rect.bottom() <= coded_size.height() && 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !natural_size.IsEmpty() && 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natural_size.GetArea() <= limits::kMaxCanvas && 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natural_size.width() <= limits::kMaxDimension && 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natural_size.height() <= limits::kMaxDimension); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const scoped_refptr<MailboxHolder>& mailbox_holder, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 texture_target, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ReadPixelsCB& read_pixels_cb, 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& no_longer_needed_cb) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<VideoFrame> frame(new VideoFrame( 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NATIVE_TEXTURE, coded_size, visible_rect, natural_size, timestamp)); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame->texture_mailbox_holder_ = mailbox_holder; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->texture_target_ = texture_target; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->read_pixels_cb_ = read_pixels_cb; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->no_longer_needed_cb_ = no_longer_needed_cb; 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(format_, NATIVE_TEXTURE); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_pixels_cb_.is_null()) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_pixels_cb_.Run(pixels); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Format format, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& coded_size, 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& visible_rect, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& natural_size, 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 y_stride, int32 u_stride, int32 v_stride, 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8* y_data, uint8* u_data, uint8* v_data, 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta timestamp, 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::SharedMemoryHandle shm_handle, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& no_longer_needed_cb) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(format == YV12 || format == YV16 || format == I420) << format; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<VideoFrame> frame(new VideoFrame( 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) format, coded_size, visible_rect, natural_size, timestamp)); 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame->shared_memory_handle_ = shm_handle; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->strides_[kYPlane] = y_stride; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->strides_[kUPlane] = u_stride; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->strides_[kVPlane] = v_stride; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->data_[kYPlane] = y_data; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->data_[kUPlane] = u_data; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->data_[kVPlane] = v_data; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->no_longer_needed_cb_ = no_longer_needed_cb; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return frame; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new VideoFrame( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame::EMPTY, gfx::Size(), gfx::Rect(), gfx::Size(), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& size, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 y, uint8 u, uint8 v, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FillYUV(frame.get(), y, u, v); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frame; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 kBlackY = 0x00; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 kBlackUV = 0x80; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta kZero; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GOOGLE_TV) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This block and other blocks wrapped around #if defined(GOOGLE_TV) is not 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maintained by the general compositor team. Please contact the following 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// people instead: 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wonsik@chromium.org 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ycheo@chromium.org 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& size) { 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<VideoFrame> frame(new VideoFrame( 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VideoFrame::HOLE, size, gfx::Rect(size), size, base::TimeDelta())); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return frame; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t VideoFrame::NumPlanes(Format format) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (format) { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::NATIVE_TEXTURE: 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(GOOGLE_TV) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::HOLE: 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::RGB32: 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 1; 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::YV12: 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::YV16: 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 3; 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case VideoFrame::YV12A: 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 4; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::EMPTY: 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::I420: 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case VideoFrame::INVALID: 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Unsupported video frame format: " << format; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline size_t RoundUp(size_t value, size_t alignment) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that |alignment| is a power of 2. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((value + (alignment - 1)) & ~(alignment-1)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Release data allocated by AllocateRGB() or AllocateYUV(). 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReleaseData(uint8* data) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(data); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AlignedFree(data); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Round up to align at least at a 16-byte boundary for each row. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is sufficient for MMX and SSE2 reads (movq/movdqa). 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_per_row = RoundUp(coded_size_.width(), 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFrameSizeAlignment) * bytes_per_pixel; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strides_[VideoFrame::kRGBPlane] = bytes_per_row; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AlignedAlloc(bytes_per_row * aligned_height + kFrameSizePadding, 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kFrameAddressAlignment)); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) no_longer_needed_cb_ = base::Bind(&ReleaseData, data_[VideoFrame::kRGBPlane]); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::AllocateYUV() { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) format_ == VideoFrame::YV12A); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Align Y rows at least at 16 byte boundaries. The stride for both 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the case of YV12 the strides are identical for the same width surface, but 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the number of bytes allocated for YV12 is 1/2 the amount for U & V as 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // YV16. We also round the height of the surface allocated to be an even 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number to avoid any potential of faulting by code that attempts to access 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Y values of the final row, but assumes that the last row of U & V 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // applies to a full two rows of Y. YV12A is the same as YV12, but with an 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // additional alpha plane that has the same size and alignment as the Y plane. 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFrameSizeAlignment); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFrameSizeAlignment); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The *2 here is because some formats (e.g. h264) allow interlaced coding, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then the size needs to be a multiple of two macroblocks (vertically). 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See libavcodec/utils.c:avcodec_align_dimensions2(). 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t uv_height = (format_ == VideoFrame::YV12 || 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) format_ == VideoFrame::YV12A) ? 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y_height / 2 : y_height; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t y_bytes = y_height * y_stride; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t uv_bytes = uv_height * uv_stride; 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extra line of UV being allocated is because h264 chroma MC 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overreads by one line in some cases, see libavcodec/utils.c: 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // put_h264_chroma_mc4_ssse3(). 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data = reinterpret_cast<uint8*>( 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AlignedAlloc( 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) y_bytes + (uv_bytes * 2 + uv_stride) + a_bytes + kFrameSizePadding, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kFrameAddressAlignment)); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) no_longer_needed_cb_ = base::Bind(&ReleaseData, data); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[VideoFrame::kYPlane] = data; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[VideoFrame::kUPlane] = data + y_bytes; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strides_[VideoFrame::kYPlane] = y_stride; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strides_[VideoFrame::kUPlane] = uv_stride; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strides_[VideoFrame::kVPlane] = uv_stride; 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (format_ == YV12A) { 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_[VideoFrame::kAPlane] = data + y_bytes + (2 * uv_bytes); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strides_[VideoFrame::kAPlane] = y_stride; 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::VideoFrame(VideoFrame::Format format, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : format_(format), 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) coded_size_(coded_size), 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_rect_(visible_rect), 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natural_size_(natural_size), 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) texture_target_(0), 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch shared_memory_handle_(base::SharedMemory::NULLHandle()), 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timestamp_(timestamp) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&strides_, 0, sizeof(strides_)); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&data_, 0, sizeof(data_)); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoFrame::~VideoFrame() { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!no_longer_needed_cb_.is_null()) 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ResetAndReturn(&no_longer_needed_cb_).Run(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsValidPlane(size_t plane) const { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (plane < NumPlanes(format_)); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::stride(size_t plane) const { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidPlane(plane)); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return strides_[plane]; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::row_bytes(size_t plane) const { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidPlane(plane)); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = coded_size_.width(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (format_) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 32bpp. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RGB32: 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return width * 4; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Planar, 8bpp. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case YV12: 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case YV16: 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case YV12A: 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (plane == kYPlane || plane == kAPlane) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return width; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RoundUp(width, 2) / 2; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Intentionally leave out non-production formats. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unsupported video frame format: " << format_; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VideoFrame::rows(size_t plane) const { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidPlane(plane)); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height = coded_size_.height(); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (format_) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RGB32: 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case YV16: 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return height; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case YV12: 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case YV12A: 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (plane == kYPlane || plane == kAPlane) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return height; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RoundUp(height, 2) / 2; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Intentionally leave out non-production formats. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unsupported video frame format: " << format_; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint8* VideoFrame::data(size_t plane) const { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsValidPlane(plane)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_[plane]; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst scoped_refptr<VideoFrame::MailboxHolder>& VideoFrame::texture_mailbox() 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(format_, NATIVE_TEXTURE); 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return texture_mailbox_holder_; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 VideoFrame::texture_target() const { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(format_, NATIVE_TEXTURE); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return texture_target_; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::SharedMemoryHandle VideoFrame::shared_memory_handle() const { 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return shared_memory_handle_; 359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoFrame::IsEndOfStream() const { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return format_ == VideoFrame::EMPTY; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoFrame::HashFrameForTesting(base::MD5Context* context) { 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int plane = 0; plane < kMaxPlanes; ++plane) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidPlane(plane)) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int row = 0; row < rows(plane); ++row) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(context, base::StringPiece( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(data(plane) + stride(plane) * row), 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_bytes(plane))); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochVideoFrame::MailboxHolder::MailboxHolder( 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const gpu::Mailbox& mailbox, 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned sync_point, 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const TextureNoLongerNeededCallback& release_callback) 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : mailbox_(mailbox), 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sync_point_(sync_point), 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch release_callback_(release_callback) {} 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochVideoFrame::MailboxHolder::~MailboxHolder() { 386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!release_callback_.is_null()) 387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch release_callback_.Run(sync_point_); 388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 391