video_frame.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer// Copyright (c) 2012 The Chromium Authors. All rights reserved. 27196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Use of this source code is governed by a BSD-style license that can be 37196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// found in the LICENSE file. 47196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 57196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "media/base/video_frame.h" 67196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 77196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "base/logging.h" 87196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "base/string_piece.h" 97196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "media/base/limits.h" 107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "media/base/video_util.h" 117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#if !defined(OS_ANDROID) 127196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#include "media/ffmpeg/ffmpeg_common.h" 137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#endif 147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 15684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis#include <algorithm> 167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisnamespace media { 187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// static 207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisscoped_refptr<VideoFrame> VideoFrame::CreateFrame( 217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis VideoFrame::Format format, 227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const gfx::Size& coded_size, 237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const gfx::Rect& visible_rect, 24684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis const gfx::Size& natural_size, 25684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis base::TimeDelta timestamp) { 267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size)); 277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis scoped_refptr<VideoFrame> frame(new VideoFrame( 287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis format, coded_size, visible_rect, natural_size, timestamp)); 297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (format) { 307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case VideoFrame::RGB32: 317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis frame->AllocateRGB(4u); 327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis break; 335d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis case VideoFrame::YV12: 345d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis case VideoFrame::YV16: 355d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis frame->AllocateYUV(); 365d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis break; 375d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis default: 385d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis LOG(FATAL) << "Unsupported frame format: " << format; 395d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 405d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return frame; 417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// static 447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisbool VideoFrame::IsValidConfig(VideoFrame::Format format, 45471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer const gfx::Size& coded_size, 462fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer const gfx::Rect& visible_rect, 4718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis const gfx::Size& natural_size) { 482fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer return (format != VideoFrame::INVALID && 497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis !coded_size.IsEmpty() && 50471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer coded_size.GetArea() <= limits::kMaxCanvas && 51471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer coded_size.width() <= limits::kMaxDimension && 528fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer coded_size.height() <= limits::kMaxDimension && 537196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis !visible_rect.IsEmpty() && 547196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis visible_rect.x() >= 0 && visible_rect.y() >= 0 && 557196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis visible_rect.right() <= coded_size.width() && 567196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis visible_rect.bottom() <= coded_size.height() && 577196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis !natural_size.IsEmpty() && 587196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis natural_size.GetArea() <= limits::kMaxCanvas && 597196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis natural_size.width() <= limits::kMaxDimension && 607196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis natural_size.height() <= limits::kMaxDimension); 617196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 627196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// static 6476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidisscoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( 655d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis uint32 texture_id, 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uint32 texture_target, 6718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis const gfx::Size& coded_size, 687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const gfx::Rect& visible_rect, 695d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis const gfx::Size& natural_size, 707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis base::TimeDelta timestamp, 717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const ReadPixelsCB& read_pixels_cb, 727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const base::Closure& no_longer_needed) { 7376a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis scoped_refptr<VideoFrame> frame( 7476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size, 755d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis timestamp)); 7618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis frame->texture_id_ = texture_id; 7718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis frame->texture_target_ = texture_target; 7818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis frame->read_pixels_cb_ = read_pixels_cb; 7918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis frame->texture_no_longer_needed_ = no_longer_needed; 8024016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis return frame; 8124016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis} 8224016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis 8324016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidisvoid VideoFrame::ReadPixelsFromNativeTexture(void* pixels) { 8424016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis DCHECK_EQ(format_, NATIVE_TEXTURE); 8524016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis if (!read_pixels_cb_.is_null()) 8624016765c905a02c9df94ef0b8a50c5e74fff5c2Argyrios Kyrtzidis read_pixels_cb_.Run(pixels); 877196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 885d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 895d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis// static 905d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisscoped_refptr<VideoFrame> VideoFrame::CreateEmptyFrame() { 917196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return new VideoFrame( 927196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis VideoFrame::EMPTY, gfx::Size(), gfx::Rect(), gfx::Size(), 937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis base::TimeDelta()); 947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// static 975d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisscoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( 987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const gfx::Size& size, 997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis uint8 y, uint8 u, uint8 v, 1007196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis base::TimeDelta timestamp) { 1017196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size)); 1027196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 1037196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); 1047196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis FillYUV(frame, y, u, v); 1057196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return frame; 1067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 1077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// static 1097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisscoped_refptr<VideoFrame> VideoFrame::CreateBlackFrame(const gfx::Size& size) { 1107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const uint8 kBlackY = 0x00; 1117196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis const uint8 kBlackUV = 0x80; 1125d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis const base::TimeDelta kZero; 1137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return CreateColorFrame(size, kBlackY, kBlackUV, kBlackUV, kZero); 1147196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 1157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisstatic inline size_t RoundUp(size_t value, size_t alignment) { 1177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Check that |alignment| is a power of 2. 1187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); 1197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return ((value + (alignment - 1)) & ~(alignment-1)); 1207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 1217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisstatic const int kFrameSizeAlignment = 16; 1237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis// Allows faster SIMD YUV convert. Also, FFmpeg overreads/-writes occasionally. 1247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisstatic const int kFramePadBytes = 15; 1257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid VideoFrame::AllocateRGB(size_t bytes_per_pixel) { 1277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Round up to align at least at a 16-byte boundary for each row. 1287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // This is sufficient for MMX and SSE2 reads (movq/movdqa). 1297196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis size_t bytes_per_row = RoundUp(coded_size_.width(), 1307196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis kFrameSizeAlignment) * bytes_per_pixel; 1317196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis size_t aligned_height = RoundUp(coded_size_.height(), kFrameSizeAlignment); 1327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis strides_[VideoFrame::kRGBPlane] = bytes_per_row; 1337196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#if !defined(OS_ANDROID) 1347196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 1357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // doesn't need to be repeated in every single user of aligned data. 136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines data_[VideoFrame::kRGBPlane] = reinterpret_cast<uint8*>( 1377196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis av_malloc(bytes_per_row * aligned_height + kFramePadBytes)); 1387196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#else 1397196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis data_[VideoFrame::kRGBPlane] = new uint8_t[bytes_per_row * aligned_height]; 140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#endif 1417196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7)); 1427196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0); 1437196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 1447196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1457196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisvoid VideoFrame::AllocateYUV() { 1467196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16); 1477196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // Align Y rows at least at 16 byte boundaries. The stride for both 1487196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for 1497196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in 1507196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // the case of YV12 the strides are identical for the same width surface, but 1517196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // the number of bytes allocated for YV12 is 1/2 the amount for U & V as 1522908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // YV16. We also round the height of the surface allocated to be an even 1532908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // number to avoid any potential of faulting by code that attempts to access 1542908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // the Y values of the final row, but assumes that the last row of U & V 1552908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // applies to a full two rows of Y. 1562908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian size_t y_stride = RoundUp(row_bytes(VideoFrame::kYPlane), 1572908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian kFrameSizeAlignment); 158181e3ecc0907ae0103586a9f4db52241995a8267Rafael Espindola size_t uv_stride = RoundUp(row_bytes(VideoFrame::kUPlane), 1592908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian kFrameSizeAlignment); 1609c7aed308aa701e0ba573c04ebe8d17a4c1486c4Fariborz Jahanian // The *2 here is because some formats (e.g. h264) allow interlaced coding, 1612908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // and then the size needs to be a multiple of two macroblocks (vertically). 1622908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian // See libavcodec/utils.c:avcodec_align_dimensions2(). 1632908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); 1642908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian size_t uv_height = format_ == VideoFrame::YV12 ? y_height / 2 : y_height; 1652908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian size_t y_bytes = y_height * y_stride; 1662908ffbc5f54323f150405fa2b06f50788ae55c7Fariborz Jahanian size_t uv_bytes = uv_height * uv_stride; 1677196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 1687196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#if !defined(OS_ANDROID) 1697196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // TODO(dalecurtis): use DataAligned or so, so this #ifdef hackery 1707196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // doesn't need to be repeated in every single user of aligned data. 1717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // The extra line of UV being allocated is because h264 chroma MC 1727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // overreads by one line in some cases, see libavcodec/utils.c: 1737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: 1747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // put_h264_chroma_mc4_ssse3(). 1757196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis uint8* data = reinterpret_cast<uint8*>( 1767196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis av_malloc(y_bytes + (uv_bytes * 2 + uv_stride) + kFramePadBytes)); 1777196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#else 17876a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis uint8* data = new uint8_t[y_bytes + (uv_bytes * 2)]; 17976a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis#endif 18076a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0); 18176a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis data_[VideoFrame::kYPlane] = data; 18276a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis data_[VideoFrame::kUPlane] = data + y_bytes; 18376a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes; 18476a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis strides_[VideoFrame::kYPlane] = y_stride; 18576a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis strides_[VideoFrame::kUPlane] = uv_stride; 18676a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis strides_[VideoFrame::kVPlane] = uv_stride; 18776a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis} 18876a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis 18976a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios KyrtzidisVideoFrame::VideoFrame(VideoFrame::Format format, 19076a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis const gfx::Size& coded_size, 19176a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis const gfx::Rect& visible_rect, 19276a5245d7fb558625453ebe2281ee0bc9c93c245Argyrios Kyrtzidis const gfx::Size& natural_size, 1937196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis base::TimeDelta timestamp) 1947196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis : format_(format), 1957196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis coded_size_(coded_size), 1967196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis visible_rect_(visible_rect), 1977196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis natural_size_(natural_size), 1987196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis texture_id_(0), 1997196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis texture_target_(0), 20018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis timestamp_(timestamp) { 20118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis memset(&strides_, 0, sizeof(strides_)); 20218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis memset(&data_, 0, sizeof(data_)); 20318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis} 20418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis 20518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios KyrtzidisVideoFrame::~VideoFrame() { 2067196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis if (format_ == NATIVE_TEXTURE && !texture_no_longer_needed_.is_null()) { 2077196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis texture_no_longer_needed_.Run(); 2087196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis texture_no_longer_needed_.Reset(); 2097196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2107196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 21118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis // In multi-plane allocations, only a single block of memory is allocated 21218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis // on the heap, and other |data| pointers point inside the same, single block 2137196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis // so just delete index 0. 21418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (data_[0]) { 2157196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#if !defined(OS_ANDROID) 2167196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis av_free(data_[0]); 2177196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#else 2187196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis delete[] data_[0]; 2197196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis#endif 2207196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis } 2217196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 2227196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2237196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisbool VideoFrame::IsValidPlane(size_t plane) const { 2247196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis switch (format_) { 2257196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case RGB32: 2267196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return plane == kRGBPlane; 2277196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2287196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case YV12: 229684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis case YV16: 230684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis return plane == kYPlane || plane == kUPlane || plane == kVPlane; 231684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 2327196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis case NATIVE_TEXTURE: 233684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis NOTREACHED() << "NATIVE_TEXTUREs don't use plane-related methods!"; 234684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis return false; 2357196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 236684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis default: 237684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis break; 238684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } 239684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 240684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis // Intentionally leave out non-production formats. 241684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis NOTREACHED() << "Unsupported video frame format: " << format_; 242684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis return false; 243684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis} 244684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 245684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidisint VideoFrame::stride(size_t plane) const { 246684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis DCHECK(IsValidPlane(plane)); 247684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis return strides_[plane]; 248684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis} 249684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 250d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Roseint VideoFrame::row_bytes(size_t plane) const { 251d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose DCHECK(IsValidPlane(plane)); 252d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose int width = coded_size_.width(); 253d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose switch (format_) { 254d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose // 32bpp. 255d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose case RGB32: 256d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose return width * 4; 257d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose 258d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose // Planar, 8bpp. 259d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose case YV12: 260684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis case YV16: 261d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose if (plane == kYPlane) 262684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis return width; 263d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose return RoundUp(width, 2) / 2; 264684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis 265684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis default: 266d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose break; 267684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis } 268d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose 269d880b3aa6d594d1a7f2d307c29378c6f59b216ffJordan Rose // Intentionally leave out non-production formats. 270684190b8dbe5258f4708ffbd816b8c5ee5b3502dArgyrios Kyrtzidis NOTREACHED() << "Unsupported video frame format: " << format_; 2717196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis return 0; 2727196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis} 2737196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidis 2747196d06c2fb020a91a26e727be1871110b4a0dc9Argyrios Kyrtzidisint VideoFrame::rows(size_t plane) const { 27518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis DCHECK(IsValidPlane(plane)); 27618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis int height = coded_size_.height(); 27718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis switch (format_) { 27818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis case RGB32: 27918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis case YV16: 28018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis return height; 2815d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 2825d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis case YV12: 2835d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (plane == kYPlane) 2845d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return height; 2855d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return RoundUp(height, 2) / 2; 286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2875d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis default: 2885d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis break; 2895d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 2905d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 2915d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis // Intentionally leave out non-production formats. 2925d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis NOTREACHED() << "Unsupported video frame format: " << format_; 2935d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return 0; 2945d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 2955d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 2965d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisuint8* VideoFrame::data(size_t plane) const { 2975d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis DCHECK(IsValidPlane(plane)); 2985d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return data_[plane]; 2995d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 3005d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3015d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisuint32 VideoFrame::texture_id() const { 3025d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis DCHECK_EQ(format_, NATIVE_TEXTURE); 3035d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return texture_id_; 3045d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 3055d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3065d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisuint32 VideoFrame::texture_target() const { 3075d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis DCHECK_EQ(format_, NATIVE_TEXTURE); 3085d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return texture_target_; 3095d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 3105d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3115d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisbool VideoFrame::IsEndOfStream() const { 3125d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis return format_ == VideoFrame::EMPTY; 3135d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 3145d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3155d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidisvoid VideoFrame::HashFrameForTesting(base::MD5Context* context) { 3165d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis for(int plane = 0; plane < kMaxPlanes; plane++) { 3175d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis if (!IsValidPlane(plane)) 3185d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis break; 3195d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis for(int row = 0; row < rows(plane); row++) { 3205d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis base::MD5Update(context, base::StringPiece( 3215d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis reinterpret_cast<char*>(data(plane) + stride(plane) * row), 3225d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis row_bytes(plane))); 3235d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3245d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis } 3255d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} 3265d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis 3275d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis} // namespace media 3285d2faa41bc63a2a29535ae3dbbc99daabf14ea2fArgyrios Kyrtzidis