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)#ifndef MEDIA_BASE_VIDEO_FRAME_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_BASE_VIDEO_FRAME_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector> 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/md5.h" 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/memory/shared_memory.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/synchronization/lock.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/buffers.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX) 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <CoreVideo/CVPixelBuffer.h> 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/mac/scoped_cftyperef.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class SkBitmap; 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gpu { 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct MailboxHolder; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace gpu 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kFrameSizeAlignment = 16, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kFrameSizePadding = 16, 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kFrameAddressAlignment = 32 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum { 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kMaxPlanes = 4, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kYPlane = 0, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUPlane = 1, 44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kUVPlane = kUPlane, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kVPlane = 2, 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kAPlane = 3, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Surface formats roughly based on FOURCC labels, see: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://www.fourcc.org/rgb.php 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://www.fourcc.org/yuv.php 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Logged to UMA, so never reuse values. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Format { 540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UNKNOWN = 0, // Unknown format value. 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) YV12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) YV16 = 2, // 16bpp YVU planar 1x1 Y, 2x1 VU samples 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) I420 = 3, // 12bpp YVU planar 1x1 Y, 2x2 UV samples. 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) YV12A = 4, // 20bpp YUVA planar 1x1 Y, 2x2 VU, 1x1 A samples. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE) 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) HOLE = 5, // Hole frame. 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(VIDEO_HOLE) 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NATIVE_TEXTURE = 6, // Native texture. Pixel-format agnostic. 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) YV12J = 7, // JPEG color range version of YV12 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NV12 = 8, // 12bpp 1x1 Y plane followed by an interleaved 2x2 UV plane. 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) YV24 = 9, // 24bpp YUV planar, no subsampling. 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FORMAT_MAX = YV24, // Must always be equal to largest entry logged. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Returns the name of a Format as a string. 703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch static std::string FormatToString(Format format); 713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new frame in system memory with given parameters. Buffers for 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the frame are allocated but not initialized. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_refptr<VideoFrame> CreateFrame( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Format format, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call prior to CreateFrame to ensure validity of frame configuration. Called 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // automatically by VideoDecoderConfig::IsValidConfig(). 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scherkus): VideoDecoderConfig shouldn't call this method 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsValidConfig(Format format, const gfx::Size& coded_size, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CB to write pixels from the texture backing this frame into the 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |const SkBitmap&| parameter. 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef base::Callback<void(const SkBitmap&)> ReadPixelsCB; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // CB to be called on the mailbox backing this frame when the frame is 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // destroyed. 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typedef base::Callback<void(uint32)> ReleaseMailboxCB; 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Wraps a native texture of the given parameters with a VideoFrame. The 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // backing of the VideoFrame is held in the mailbox held by |mailbox_holder|, 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and |mailbox_holder_release_cb| will be called with |mailbox_holder| as the 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // argument when the VideoFrame is to be destroyed. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |read_pixels_cb| may be used to do (slow!) readbacks from the 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // texture to main memory. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_refptr<VideoFrame> WrapNativeTexture( 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<gpu::MailboxHolder> mailbox_holder, 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ReleaseMailboxCB& mailbox_holder_release_cb, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp, 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ReadPixelsCB& read_pixels_cb); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(MEDIA_FOR_CAST_IOS) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read pixels from the native texture backing |*this| and write 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // them to |pixels| as BGRA. |pixels| must point to a buffer at 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // least as large as 4 * visible_rect().size().GetArea(). 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void ReadPixelsFromNativeTexture(const SkBitmap& pixels); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Wraps packed image data residing in a memory buffer with a VideoFrame. 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The image data resides in |data| and is assumed to be packed tightly in a 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // buffer of logical dimensions |coded_size| with the appropriate bit depth 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // and plane count as given by |format|. The shared memory handle of the 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // backing allocation, if present, can be passed in with |handle|. When the 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // frame is destroyed, |no_longer_needed_cb.Run()| will be called. 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns NULL on failure. 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static scoped_refptr<VideoFrame> WrapExternalPackedMemory( 126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Format format, 127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const gfx::Size& coded_size, 128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const gfx::Rect& visible_rect, 129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const gfx::Size& natural_size, 130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch uint8* data, 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_t data_size, 132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::SharedMemoryHandle handle, 133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::TimeDelta timestamp, 134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const base::Closure& no_longer_needed_cb); 135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_POSIX) 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Wraps provided dmabufs 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // (https://www.kernel.org/doc/Documentation/dma-buf-sharing.txt) with a 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // VideoFrame. The dmabuf fds are dup()ed on creation, so that the VideoFrame 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // retains a reference to them, and are automatically close()d on destruction, 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // dropping the reference. The caller may safely close() its reference after 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // calling WrapExternalDmabufs(). 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The image data is only accessible via dmabuf fds, which are usually passed 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // directly to a hardware device and/or to another process, or can also be 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // mapped via mmap() for CPU access. 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // When the frame is destroyed, |no_longer_needed_cb.Run()| will be called. 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns NULL on failure. 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static scoped_refptr<VideoFrame> WrapExternalDmabufs( 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Format format, 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const gfx::Size& coded_size, 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const gfx::Rect& visible_rect, 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const gfx::Size& natural_size, 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::vector<int> dmabuf_fds, 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::TimeDelta timestamp, 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const base::Closure& no_longer_needed_cb); 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX) 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Wraps a provided CVPixelBuffer with a VideoFrame. The pixel buffer is 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // retained for the lifetime of the VideoFrame and released upon destruction. 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The image data is only accessible via the pixel buffer, which could be 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // backed by an IOSurface from another process. All the attributes of the 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // VideoFrame are derived from the pixel buffer, with the exception of the 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // timestamp. If information is missing or is incompatible (for example, a 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // pixel format that has no VideoFrame match), NULL is returned. 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // http://crbug.com/401308 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static scoped_refptr<VideoFrame> WrapCVPixelBuffer( 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CVPixelBufferRef cv_pixel_buffer, 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeDelta timestamp); 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wraps external YUV data of the given parameters with a VideoFrame. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The returned VideoFrame does not own the data passed in. When the frame 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is destroyed |no_longer_needed_cb.Run()| will be called. 175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(sheu): merge this into WrapExternalSharedMemory(). 176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // http://crbug.com/270217 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_refptr<VideoFrame> WrapExternalYuvData( 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Format format, 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& coded_size, 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& visible_rect, 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& natural_size, 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 y_stride, 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 u_stride, 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 v_stride, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8* y_data, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8* u_data, 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8* v_data, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta timestamp, 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& no_longer_needed_cb); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Wraps |frame| and calls |no_longer_needed_cb| when the wrapper VideoFrame 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // gets destroyed. |visible_rect| must be a sub rect within 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // frame->visible_rect(). 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static scoped_refptr<VideoFrame> WrapVideoFrame( 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const scoped_refptr<VideoFrame>& frame, 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Rect& visible_rect, 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Size& natural_size, 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::Closure& no_longer_needed_cb); 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Creates a frame which indicates end-of-stream. 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static scoped_refptr<VideoFrame> CreateEOSFrame(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocates YV12 frame based on |size|, and sets its data to the YUV(y,u,v). 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_refptr<VideoFrame> CreateColorFrame( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& size, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 y, uint8 u, uint8 v, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocates YV12 frame based on |size|, and sets its data to the YUV 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // equivalent of RGB(0,0,0). 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static scoped_refptr<VideoFrame> CreateBlackFrame(const gfx::Size& size); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Allocates YV12A frame based on |size|, and sets its data to the YUVA 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // equivalent of RGBA(0,0,0,0). 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static scoped_refptr<VideoFrame> CreateTransparentFrame( 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::Size& size); 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(VIDEO_HOLE) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Allocates a hole frame. 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_refptr<VideoFrame> CreateHoleFrame(const gfx::Size& size); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif // defined(VIDEO_HOLE) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static size_t NumPlanes(Format format); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Returns the required allocation size for a (tightly packed) frame of the 226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // given coded size and format. 227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) static size_t AllocationSize(Format format, const gfx::Size& coded_size); 228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Returns the plane size for a plane of the given coded size and format. 230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static gfx::Size PlaneSize(Format format, 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size_t plane, 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const gfx::Size& coded_size); 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Returns the required allocation size for a (tightly packed) plane of the 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // given coded size and format. 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static size_t PlaneAllocationSize(Format format, 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t plane, 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const gfx::Size& coded_size); 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Returns horizontal bits per pixel for given |plane| and |format|. 241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static int PlaneHorizontalBitsPerPixel(Format format, size_t plane); 242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Returns the number of bytes per row for the given plane, format, and width. 24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The width may be aligned to format requirements. 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static size_t RowBytes(size_t plane, Format format, int width); 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns the number of rows for the given plane, format, and height. 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The height may be aligned to format requirements. 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static size_t Rows(size_t plane, Format format, int height); 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Format format() const { return format_; } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size() const { return coded_size_; } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect() const { return visible_rect_; } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size() const { return natural_size_; } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int stride(size_t plane) const; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the number of bytes per row and number of rows for a given plane. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As opposed to stride(), row_bytes() refers to the bytes representing 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frame data scanlines (coded_size.width() pixels, without stride padding). 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int row_bytes(size_t plane) const; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rows(size_t plane) const; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns pointer to the buffer for a given plane. The memory is owned by 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // VideoFrame object and must not be freed by the caller. 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data(size_t plane) const; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Returns the mailbox holder of the native texture wrapped by this frame. 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only valid to call if this is a NATIVE_TEXTURE frame. Before using the 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // mailbox, the caller must wait for the included sync point. 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const gpu::MailboxHolder* mailbox_holder() const; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Returns the shared-memory handle, if present 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::SharedMemoryHandle shared_memory_handle() const; 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_POSIX) 279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Returns backing dmabuf file descriptor for given |plane|, if present. 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int dmabuf_fd(size_t plane) const; 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX) 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns the backing CVPixelBuffer, if present. 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CVPixelBufferRef cv_pixel_buffer() const; 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if this VideoFrame represents the end of the stream. 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool end_of_stream() const { return end_of_stream_; } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::TimeDelta timestamp() const { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return timestamp_; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void set_timestamp(const base::TimeDelta& timestamp) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timestamp_ = timestamp; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) class SyncPointClient { 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SyncPointClient() {} 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual uint32 InsertSyncPoint() = 0; 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void WaitSyncPoint(uint32 sync_point) = 0; 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~SyncPointClient() {} 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SyncPointClient); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // It uses |client| to insert a new sync point and potentially waits on a 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // older sync point. The final sync point will be used to release this 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // VideoFrame. 3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // This method is thread safe. Both blink and compositor threads can call it. 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void UpdateReleaseSyncPoint(SyncPointClient* client); 3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to keep a running hash of seen frames. Expects an initialized MD5 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // context. Calls MD5Update with the context and the contents of the frame. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HashFrameForTesting(base::MD5Context* context); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<VideoFrame>; 32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Returns true if |plane| is a valid plane number for the given format. This 32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // can be used to DCHECK() plane parameters. 32403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static bool IsValidPlane(size_t plane, VideoFrame::Format format); 32503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clients must use the static CreateFrame() method to create a new frame. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame(Format format, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& coded_size, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& visible_rect, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& natural_size, 3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<gpu::MailboxHolder> mailbox_holder, 332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeDelta timestamp, 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool end_of_stream); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~VideoFrame(); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AllocateYUV(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Frame format. 339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const Format format_; 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Width and height of the video frame, in pixels. This must include pixel 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // data for the whole image; i.e. for YUV formats with subsampled chroma 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // planes, in the case that the visible portion of the image does not line up 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // on a sample boundary, |coded_size_| must be rounded up appropriately and 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // the pixel data provided for the odd pixels. 346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const gfx::Size coded_size_; 347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Width, height, and offsets of the visible portion of the video frame. Must 349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // be a subrect of |coded_size_|. Can be odd with respect to the sample 350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // boundaries, e.g. for formats with subsampled chroma. 351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const gfx::Rect visible_rect_; 352effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Width and height of the visible portion of the video frame 354effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // (|visible_rect_.size()|) with aspect ratio taken into account. 355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const gfx::Size natural_size_; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Array of strides for each plane, typically greater or equal to the width 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the surface divided by the horizontal sampling period. Note that 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // strides can be negative. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 strides_[kMaxPlanes]; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Array of data pointers to each plane. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data_[kMaxPlanes]; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Native texture mailbox, if this is a NATIVE_TEXTURE frame. 3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const scoped_ptr<gpu::MailboxHolder> mailbox_holder_; 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReleaseMailboxCB mailbox_holder_release_cb_; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReadPixelsCB read_pixels_cb_; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Shared memory handle, if this frame was allocated from shared memory. 371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::SharedMemoryHandle shared_memory_handle_; 372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_POSIX) 374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Dmabufs for each plane, if this frame is wrapping memory 375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // acquired via dmabuf. 376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::ScopedFD dmabuf_fds_[kMaxPlanes]; 377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif 378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_MACOSX) 3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // CVPixelBuffer, if this frame is wrapping one. 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_; 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure no_longer_needed_cb_; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timestamp_; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::Lock release_sync_point_lock_; 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 release_sync_point_; 3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const bool end_of_stream_; 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(VideoFrame); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // MEDIA_BASE_VIDEO_FRAME_H_ 399