summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
Diffstat (limited to 'media/base')
-rw-r--r--media/base/buffers.h64
-rw-r--r--media/base/video_frame.cc170
-rw-r--r--media/base/video_frame.h111
-rw-r--r--media/base/video_frame_impl.cc194
-rw-r--r--media/base/video_frame_impl.h58
-rw-r--r--media/base/video_frame_impl_unittest.cc187
-rw-r--r--media/base/video_frame_unittest.cc176
7 files changed, 458 insertions, 502 deletions
diff --git a/media/base/buffers.h b/media/base/buffers.h
index 6102ea9..d03717d 100644
--- a/media/base/buffers.h
+++ b/media/base/buffers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -122,68 +122,6 @@ class WritableBuffer : public Buffer {
virtual ~WritableBuffer() {}
};
-
-struct VideoSurface {
- static const size_t kMaxPlanes = 3;
-
- static const size_t kNumRGBPlanes = 1;
- static const size_t kRGBPlane = 0;
-
- static const size_t kNumYUVPlanes = 3;
- static const size_t kYPlane = 0;
- static const size_t kUPlane = 1;
- static const size_t kVPlane = 2;
-
- // Surface formats roughly based on FOURCC labels, see:
- // http://www.fourcc.org/rgb.php
- // http://www.fourcc.org/yuv.php
- enum Format {
- INVALID, // Invalid format value. Used for error reporting.
- RGB555, // 16bpp RGB packed 5:5:5
- RGB565, // 16bpp RGB packed 5:6:5
- RGB24, // 24bpp RGB packed 8:8:8
- RGB32, // 32bpp RGB packed with extra byte 8:8:8
- RGBA, // 32bpp RGBA packed 8:8:8:8
- YV12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples
- YV16, // 16bpp YVU planar 1x1 Y, 2x1 VU samples
- EMPTY, // An empty frame.
- };
-
- // Surface format.
- Format format;
-
- // Width and height of surface.
- size_t width;
- size_t height;
-
- // Number of planes, typically 1 for packed RGB formats and 3 for planar
- // YUV formats.
- size_t planes;
-
- // Array of strides for each plane, typically greater or equal to the width
- // of the surface divided by the horizontal sampling period. Note that
- // strides can be negative.
- int32 strides[kMaxPlanes];
-
- // Array of data pointers to each plane.
- uint8* data[kMaxPlanes];
-};
-
-
-class VideoFrame : public StreamSample {
- public:
- // Locks the underlying surface and fills out the given VideoSurface and
- // returns true if successful, false otherwise. Any additional calls to Lock
- // will fail.
- virtual bool Lock(VideoSurface* surface) = 0;
-
- // Unlocks the underlying surface, the VideoSurface acquired from Lock is no
- // longer guaranteed to be valid.
- virtual void Unlock() = 0;
-
- virtual bool IsEndOfStream() const = 0;
-};
-
} // namespace media
#endif // MEDIA_BASE_BUFFERS_H_
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
new file mode 100644
index 0000000..0b8239c
--- /dev/null
+++ b/media/base/video_frame.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/video_frame.h"
+
+namespace media {
+
+// static
+void VideoFrame::CreateFrame(VideoFrame::Format format,
+ size_t width,
+ size_t height,
+ base::TimeDelta timestamp,
+ base::TimeDelta duration,
+ scoped_refptr<VideoFrame>* frame_out) {
+ DCHECK(width > 0 && height > 0);
+ DCHECK(width * height < 100000000);
+ DCHECK(frame_out);
+ bool alloc_worked = false;
+ scoped_refptr<VideoFrame> frame =
+ new VideoFrame(format, width, height);
+ if (frame) {
+ frame->SetTimestamp(timestamp);
+ frame->SetDuration(duration);
+ switch (format) {
+ case VideoFrame::RGB555:
+ case VideoFrame::RGB565:
+ alloc_worked = frame->AllocateRGB(2u);
+ break;
+ case VideoFrame::RGB24:
+ alloc_worked = frame->AllocateRGB(3u);
+ break;
+ case VideoFrame::RGB32:
+ case VideoFrame::RGBA:
+ alloc_worked = frame->AllocateRGB(4u);
+ break;
+ case VideoFrame::YV12:
+ case VideoFrame::YV16:
+ alloc_worked = frame->AllocateYUV();
+ break;
+ default:
+ NOTREACHED();
+ alloc_worked = false;
+ break;
+ }
+ }
+ *frame_out = alloc_worked ? frame : NULL;
+}
+
+// static
+void VideoFrame::CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out) {
+ *frame_out = new VideoFrame(VideoFrame::EMPTY, 0, 0);
+}
+
+// static
+void VideoFrame::CreateBlackFrame(int width, int height,
+ scoped_refptr<VideoFrame>* frame_out) {
+ DCHECK_GT(width, 0);
+ DCHECK_GT(height, 0);
+
+ // Create our frame.
+ scoped_refptr<VideoFrame> frame;
+ const base::TimeDelta kZero;
+ VideoFrame::CreateFrame(VideoFrame::YV12, width, height, kZero, kZero,
+ &frame);
+ DCHECK(frame);
+
+ // Now set the data to YUV(0,128,128).
+ const uint8 kBlackY = 0x00;
+ const uint8 kBlackUV = 0x80;
+
+ // Fill the Y plane.
+ uint8* y_plane = frame->data(VideoFrame::kYPlane);
+ for (size_t i = 0; i < frame->height_; ++i) {
+ memset(y_plane, kBlackY, frame->width_);
+ y_plane += frame->stride(VideoFrame::kYPlane);
+ }
+
+ // Fill the U and V planes.
+ uint8* u_plane = frame->data(VideoFrame::kUPlane);
+ uint8* v_plane = frame->data(VideoFrame::kVPlane);
+ for (size_t i = 0; i < (frame->height_ / 2); ++i) {
+ memset(u_plane, kBlackUV, frame->width_ / 2);
+ memset(v_plane, kBlackUV, frame->width_ / 2);
+ u_plane += frame->stride(VideoFrame::kUPlane);
+ v_plane += frame->stride(VideoFrame::kVPlane);
+ }
+
+ // Success!
+ *frame_out = frame;
+}
+
+static inline size_t RoundUp(size_t value, size_t alignment) {
+ // Check that |alignment| is a power of 2.
+ DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
+ return ((value + (alignment - 1)) & ~(alignment-1));
+}
+
+bool VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
+ // Round up to align at a 64-bit (8 byte) boundary for each row. This
+ // is sufficient for MMX reads (movq).
+ size_t bytes_per_row = RoundUp(width_ * bytes_per_pixel, 8);
+ planes_ = VideoFrame::kNumRGBPlanes;
+ strides_[VideoFrame::kRGBPlane] = bytes_per_row;
+ data_[VideoFrame::kRGBPlane] = new uint8[bytes_per_row * height_];
+ DCHECK(data_[VideoFrame::kRGBPlane]);
+ DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
+ COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0);
+ return (NULL != data_[VideoFrame::kRGBPlane]);
+}
+
+bool VideoFrame::AllocateYUV() {
+ DCHECK(format_ == VideoFrame::YV12 ||
+ format_ == VideoFrame::YV16);
+ // Align Y rows at 32-bit (4 byte) boundaries. The stride for both YV12 and
+ // YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for U and V
+ // applies to two rows of Y (one byte of UV for 4 bytes of Y), so in the
+ // case of YV12 the strides are identical for the same width surface, but the
+ // number of bytes allocated for YV12 is 1/2 the amount for U & V as YV16.
+ // We also round the height of the surface allocated to be an even number
+ // to avoid any potential of faulting by code that attempts to access the Y
+ // values of the final row, but assumes that the last row of U & V applies to
+ // a full two rows of Y.
+ size_t alloc_height = RoundUp(height_, 2);
+ size_t y_bytes_per_row = RoundUp(width_, 4);
+ size_t uv_stride = RoundUp(y_bytes_per_row / 2, 4);
+ size_t y_bytes = alloc_height * y_bytes_per_row;
+ size_t uv_bytes = alloc_height * uv_stride;
+ if (format_ == VideoFrame::YV12) {
+ uv_bytes /= 2;
+ }
+ uint8* data = new uint8[y_bytes + (uv_bytes * 2)];
+ if (data) {
+ planes_ = VideoFrame::kNumYUVPlanes;
+ COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
+ data_[VideoFrame::kYPlane] = data;
+ data_[VideoFrame::kUPlane] = data + y_bytes;
+ data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
+ strides_[VideoFrame::kYPlane] = y_bytes_per_row;
+ strides_[VideoFrame::kUPlane] = uv_stride;
+ strides_[VideoFrame::kVPlane] = uv_stride;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+}
+
+VideoFrame::VideoFrame(VideoFrame::Format format,
+ size_t width,
+ size_t height) {
+ format_ = format;
+ width_ = width;
+ height_ = height;
+ planes_ = 0;
+ memset(&strides_, 0, sizeof(strides_));
+ memset(&data_, 0, sizeof(data_));
+}
+
+VideoFrame::~VideoFrame() {
+ // In multi-plane allocations, only a single block of memory is allocated
+ // on the heap, and other |data| pointers point inside the same, single block
+ // so just delete index 0.
+ delete[] data_[0];
+}
+
+bool VideoFrame::IsEndOfStream() const {
+ return format_ == VideoFrame::EMPTY;
+}
+
+} // namespace media
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
new file mode 100644
index 0000000..b84d77c
--- /dev/null
+++ b/media/base/video_frame.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_VIDEO_FRAME_H_
+#define MEDIA_BASE_VIDEO_FRAME_H_
+
+#include "media/base/buffers.h"
+
+namespace media {
+
+class VideoFrame : public StreamSample {
+ public:
+ static const size_t kMaxPlanes = 3;
+
+ static const size_t kNumRGBPlanes = 1;
+ static const size_t kRGBPlane = 0;
+
+ static const size_t kNumYUVPlanes = 3;
+ static const size_t kYPlane = 0;
+ static const size_t kUPlane = 1;
+ static const size_t kVPlane = 2;
+
+ // Surface formats roughly based on FOURCC labels, see:
+ // http://www.fourcc.org/rgb.php
+ // http://www.fourcc.org/yuv.php
+ enum Format {
+ INVALID, // Invalid format value. Used for error reporting.
+ RGB555, // 16bpp RGB packed 5:5:5
+ RGB565, // 16bpp RGB packed 5:6:5
+ RGB24, // 24bpp RGB packed 8:8:8
+ RGB32, // 32bpp RGB packed with extra byte 8:8:8
+ RGBA, // 32bpp RGBA packed 8:8:8:8
+ YV12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples
+ YV16, // 16bpp YVU planar 1x1 Y, 2x1 VU samples
+ EMPTY, // An empty frame.
+ };
+
+ public:
+ // Creates a new frame with given parameters. Buffers for the frame are
+ // allocated but not initialized.
+ static void CreateFrame(Format format,
+ size_t width,
+ size_t height,
+ base::TimeDelta timestamp,
+ base::TimeDelta duration,
+ scoped_refptr<VideoFrame>* frame_out);
+
+ // Creates a frame with format equals to VideoFrame::EMPTY, width, height
+ // timestamp and duration are all 0.
+ static void CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out);
+
+ // Allocates YV12 frame based on |width| and |height|, and sets its data to
+ // the YUV equivalent of RGB(0,0,0).
+ static void CreateBlackFrame(int width, int height,
+ scoped_refptr<VideoFrame>* frame_out);
+
+ Format format() const { return format_; }
+
+ size_t width() const { return width_; }
+
+ size_t height() const { return height_; }
+
+ size_t planes() const { return planes_; }
+
+ int32 stride(size_t plane) const { return strides_[plane]; }
+
+ // Returns pointer to the buffer for a given plane. The memory is owned by
+ // VideoFrame object and must not be freed by the caller.
+ uint8* data(size_t plane) const { return data_[plane]; }
+
+ // StreamSample interface.
+ virtual bool IsEndOfStream() const;
+
+ private:
+ // Clients must use the static CreateFrame() method to create a new frame.
+ VideoFrame(Format format,
+ size_t video_width,
+ size_t video_height);
+
+ virtual ~VideoFrame();
+
+ // Used internally by CreateFrame().
+ bool AllocateRGB(size_t bytes_per_pixel);
+ bool AllocateYUV();
+
+ // Frame format.
+ Format format_;
+
+ // Width and height of surface.
+ size_t width_;
+ size_t height_;
+
+ // Number of planes, typically 1 for packed RGB formats and 3 for planar
+ // YUV formats.
+ size_t planes_;
+
+ // Array of strides for each plane, typically greater or equal to the width
+ // of the surface divided by the horizontal sampling period. Note that
+ // strides can be negative.
+ int32 strides_[kMaxPlanes];
+
+ // Array of data pointers to each plane.
+ uint8* data_[kMaxPlanes];
+
+ DISALLOW_COPY_AND_ASSIGN(VideoFrame);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_VIDEO_FRAME_H_
diff --git a/media/base/video_frame_impl.cc b/media/base/video_frame_impl.cc
deleted file mode 100644
index 470e297..0000000
--- a/media/base/video_frame_impl.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/base/video_frame_impl.h"
-
-namespace media {
-
-// static
-void VideoFrameImpl::CreateFrame(VideoSurface::Format format,
- size_t width,
- size_t height,
- base::TimeDelta timestamp,
- base::TimeDelta duration,
- scoped_refptr<VideoFrame>* frame_out) {
- DCHECK(width > 0 && height > 0);
- DCHECK(width * height < 100000000);
- DCHECK(frame_out);
- bool alloc_worked = false;
- scoped_refptr<VideoFrameImpl> frame =
- new VideoFrameImpl(format, width, height);
- if (frame) {
- frame->SetTimestamp(timestamp);
- frame->SetDuration(duration);
- switch (format) {
- case VideoSurface::RGB555:
- case VideoSurface::RGB565:
- alloc_worked = frame->AllocateRGB(2u);
- break;
- case VideoSurface::RGB24:
- alloc_worked = frame->AllocateRGB(3u);
- break;
- case VideoSurface::RGB32:
- case VideoSurface::RGBA:
- alloc_worked = frame->AllocateRGB(4u);
- break;
- case VideoSurface::YV12:
- case VideoSurface::YV16:
- alloc_worked = frame->AllocateYUV();
- break;
- default:
- NOTREACHED();
- alloc_worked = false;
- break;
- }
- }
- *frame_out = alloc_worked ? frame : NULL;
-}
-
-// static
-void VideoFrameImpl::CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out) {
- *frame_out = new VideoFrameImpl(VideoSurface::EMPTY, 0, 0);
-}
-
-// static
-void VideoFrameImpl::CreateBlackFrame(int width, int height,
- scoped_refptr<VideoFrame>* frame_out) {
- DCHECK_GT(width, 0);
- DCHECK_GT(height, 0);
-
- // Create our frame.
- scoped_refptr<VideoFrame> frame;
- const base::TimeDelta kZero;
- VideoFrameImpl::CreateFrame(VideoSurface::YV12, width, height, kZero, kZero,
- &frame);
- DCHECK(frame);
-
- // Now set the data to YUV(0,128,128).
- const uint8 kBlackY = 0x00;
- const uint8 kBlackUV = 0x80;
- VideoSurface surface;
- frame->Lock(&surface);
- DCHECK_EQ(VideoSurface::YV12, surface.format) << "Expected YV12 surface";
-
- // Fill the Y plane.
- for (size_t i = 0; i < surface.height; ++i) {
- memset(surface.data[VideoSurface::kYPlane], kBlackY, surface.width);
- surface.data[VideoSurface::kYPlane]
- += surface.strides[VideoSurface::kYPlane];
- }
-
- // Fill the U and V planes.
- for (size_t i = 0; i < (surface.height / 2); ++i) {
- memset(surface.data[VideoSurface::kUPlane], kBlackUV, surface.width / 2);
- memset(surface.data[VideoSurface::kVPlane], kBlackUV, surface.width / 2);
- surface.data[VideoSurface::kUPlane] +=
- surface.strides[VideoSurface::kUPlane];
- surface.data[VideoSurface::kVPlane] +=
- surface.strides[VideoSurface::kVPlane];
- }
- frame->Unlock();
-
- // Success!
- *frame_out = frame;
-}
-
-static inline size_t RoundUp(size_t value, size_t alignment) {
- // Check that |alignment| is a power of 2.
- DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
- return ((value + (alignment - 1)) & ~(alignment-1));
-}
-
-bool VideoFrameImpl::AllocateRGB(size_t bytes_per_pixel) {
- // Round up to align at a 64-bit (8 byte) boundary for each row. This
- // is sufficient for MMX reads (movq).
- size_t bytes_per_row = RoundUp(surface_.width * bytes_per_pixel, 8);
- surface_.planes = VideoSurface::kNumRGBPlanes;
- surface_.strides[VideoSurface::kRGBPlane] = bytes_per_row;
- surface_.data[VideoSurface::kRGBPlane] = new uint8[bytes_per_row *
- surface_.height];
- DCHECK(surface_.data[VideoSurface::kRGBPlane]);
- DCHECK(!(reinterpret_cast<intptr_t>(
- surface_.data[VideoSurface::kRGBPlane]) & 7));
- COMPILE_ASSERT(0 == VideoSurface::kRGBPlane, RGB_data_must_be_index_0);
- return (NULL != surface_.data[VideoSurface::kRGBPlane]);
-}
-
-bool VideoFrameImpl::AllocateYUV() {
- DCHECK(surface_.format == VideoSurface::YV12 ||
- surface_.format == VideoSurface::YV16);
- // Align Y rows at 32-bit (4 byte) boundaries. The stride for both YV12 and
- // YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for U and V
- // applies to two rows of Y (one byte of UV for 4 bytes of Y), so in the
- // case of YV12 the strides are identical for the same width surface, but the
- // number of bytes allocated for YV12 is 1/2 the amount for U & V as YV16.
- // We also round the height of the surface allocated to be an even number
- // to avoid any potential of faulting by code that attempts to access the Y
- // values of the final row, but assumes that the last row of U & V applies to
- // a full two rows of Y.
- size_t alloc_height = RoundUp(surface_.height, 2);
- size_t y_bytes_per_row = RoundUp(surface_.width, 4);
- size_t uv_stride = RoundUp(y_bytes_per_row / 2, 4);
- size_t y_bytes = alloc_height * y_bytes_per_row;
- size_t uv_bytes = alloc_height * uv_stride;
- if (surface_.format == VideoSurface::YV12) {
- uv_bytes /= 2;
- }
- uint8* data = new uint8[y_bytes + (uv_bytes * 2)];
- if (data) {
- surface_.planes = VideoSurface::kNumYUVPlanes;
- COMPILE_ASSERT(0 == VideoSurface::kYPlane, y_plane_data_must_be_index_0);
- surface_.data[VideoSurface::kYPlane] = data;
- surface_.data[VideoSurface::kUPlane] = data + y_bytes;
- surface_.data[VideoSurface::kVPlane] = data + y_bytes + uv_bytes;
- surface_.strides[VideoSurface::kYPlane] = y_bytes_per_row;
- surface_.strides[VideoSurface::kUPlane] = uv_stride;
- surface_.strides[VideoSurface::kVPlane] = uv_stride;
- return true;
- }
- NOTREACHED();
- return false;
-}
-
-VideoFrameImpl::VideoFrameImpl(VideoSurface::Format format,
- size_t width,
- size_t height) {
- locked_ = false;
- memset(&surface_, 0, sizeof(surface_));
- surface_.format = format;
- surface_.width = width;
- surface_.height = height;
-}
-
-VideoFrameImpl::~VideoFrameImpl() {
- // In multi-plane allocations, only a single block of memory is allocated
- // on the heap, and other |data| pointers point inside the same, single block
- // so just delete index 0.
- delete[] surface_.data[0];
-}
-
-bool VideoFrameImpl::Lock(VideoSurface* surface) {
- DCHECK(!locked_);
- DCHECK_NE(surface_.format, VideoSurface::EMPTY);
- if (locked_) {
- memset(surface, 0, sizeof(*surface));
- return false;
- }
- locked_ = true;
- COMPILE_ASSERT(sizeof(*surface) == sizeof(surface_), surface_size_mismatch);
- memcpy(surface, &surface_, sizeof(*surface));
- return true;
-}
-
-void VideoFrameImpl::Unlock() {
- DCHECK(locked_);
- DCHECK_NE(surface_.format, VideoSurface::EMPTY);
- locked_ = false;
-}
-
-bool VideoFrameImpl::IsEndOfStream() const {
- return surface_.format == VideoSurface::EMPTY;
-}
-
-} // namespace media
diff --git a/media/base/video_frame_impl.h b/media/base/video_frame_impl.h
deleted file mode 100644
index cf660ea..0000000
--- a/media/base/video_frame_impl.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Simple class that implements the VideoFrame interface with memory allocated
-// on the system heap. This class supports every format defined in the
-// VideoSurface::Format enum. The implementation attempts to properly align
-// allocations for maximum system bus efficency.
-#ifndef MEDIA_BASE_VIDEO_FRAME_IMPL_H_
-#define MEDIA_BASE_VIDEO_FRAME_IMPL_H_
-
-#include "media/base/buffers.h"
-
-namespace media {
-
-class VideoFrameImpl : public VideoFrame {
- public:
- static void CreateFrame(VideoSurface::Format format,
- size_t width,
- size_t height,
- base::TimeDelta timestamp,
- base::TimeDelta duration,
- scoped_refptr<VideoFrame>* frame_out);
-
- // Creates a frame with format equals to VideoSurface::EMPTY, width, height
- // timestamp and duration are all 0.
- static void CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out);
-
- // Allocates YV12 frame based on |width| and |height|, and sets its data to
- // the YUV equivalent of RGB(0,0,0).
- static void CreateBlackFrame(int width, int height,
- scoped_refptr<VideoFrame>* frame_out);
-
- // Implementation of VideoFrame.
- virtual bool Lock(VideoSurface* surface);
- virtual void Unlock();
- virtual bool IsEndOfStream() const;
-
- private:
- // Clients must use the static CreateFrame() method to create a new frame.
- VideoFrameImpl(VideoSurface::Format format,
- size_t video_width,
- size_t video_height);
-
- virtual ~VideoFrameImpl();
-
- bool AllocateRGB(size_t bytes_per_pixel);
- bool AllocateYUV();
-
- bool locked_;
- VideoSurface surface_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
-};
-
-} // namespace media
-
-#endif // MEDIA_BASE_VIDEO_FRAME_IMPL_H_
diff --git a/media/base/video_frame_impl_unittest.cc b/media/base/video_frame_impl_unittest.cc
deleted file mode 100644
index d50db36..0000000
--- a/media/base/video_frame_impl_unittest.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/base/video_frame_impl.h"
-
-#include "base/format_macros.h"
-#include "base/string_util.h"
-#include "media/base/buffers.h"
-#include "media/base/mock_filters.h"
-#include "media/base/yuv_convert.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-// Helper function that initializes a YV12 frame with white and black scan
-// lines based on the |white_to_black| parameter. If 0, then the entire
-// frame will be black, if 1 then the entire frame will be white.
-void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
- VideoSurface surface;
- if (!frame->Lock(&surface)) {
- ADD_FAILURE();
- return;
- }
- EXPECT_EQ(VideoSurface::YV12, surface.format);
- size_t first_black_row = static_cast<size_t>(surface.height * white_to_black);
- uint8* y_plane = surface.data[VideoSurface::kYPlane];
- for (size_t row = 0; row < surface.height; ++row) {
- int color = (row < first_black_row) ? 0xFF : 0x00;
- memset(y_plane, color, surface.width);
- y_plane += surface.strides[VideoSurface::kYPlane];
- }
- uint8* u_plane = surface.data[VideoSurface::kUPlane];
- uint8* v_plane = surface.data[VideoSurface::kVPlane];
- for (size_t row = 0; row < surface.height; row += 2) {
- memset(u_plane, 0x80, surface.width / 2);
- memset(v_plane, 0x80, surface.width / 2);
- u_plane += surface.strides[VideoSurface::kUPlane];
- v_plane += surface.strides[VideoSurface::kVPlane];
- }
- frame->Unlock();
-}
-
-// Given a |yv12_frame| this method converts the YV12 frame to RGBA and
-// makes sure that all the pixels of the RBG frame equal |expect_rgb_color|.
-void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) {
- // On linux and mac builds if you directly compare using EXPECT_EQ and use
- // the VideoSurface::kNumxxxPlanes constants, it generates an error when
- // linking. These are declared so that we can compare against locals.
- const size_t expect_yuv_planes = VideoSurface::kNumYUVPlanes;
- const size_t expect_rgb_planes = VideoSurface::kNumRGBPlanes;
-
- VideoSurface yuv_surface;
- ASSERT_TRUE(yv12_frame->Lock(&yuv_surface));
- ASSERT_EQ(VideoSurface::YV12, yuv_surface.format);
- ASSERT_EQ(expect_yuv_planes, yuv_surface.planes);
- ASSERT_EQ(yuv_surface.strides[VideoSurface::kUPlane],
- yuv_surface.strides[VideoSurface::kVPlane]);
-
- scoped_refptr<media::VideoFrame> rgb_frame;
- media::VideoFrameImpl::CreateFrame(VideoSurface::RGBA,
- yuv_surface.width,
- yuv_surface.height,
- yv12_frame->GetTimestamp(),
- yv12_frame->GetDuration(),
- &rgb_frame);
- media::VideoSurface rgb_surface;
- ASSERT_TRUE(rgb_frame->Lock(&rgb_surface));
- ASSERT_EQ(yuv_surface.width, rgb_surface.width);
- ASSERT_EQ(yuv_surface.height, rgb_surface.height);
- ASSERT_EQ(expect_rgb_planes, rgb_surface.planes);
-
- media::ConvertYUVToRGB32(yuv_surface.data[VideoSurface::kYPlane],
- yuv_surface.data[VideoSurface::kUPlane],
- yuv_surface.data[VideoSurface::kVPlane],
- rgb_surface.data[VideoSurface::kRGBPlane],
- rgb_surface.width,
- rgb_surface.height,
- yuv_surface.strides[VideoSurface::kYPlane],
- yuv_surface.strides[VideoSurface::kUPlane],
- rgb_surface.strides[VideoSurface::kRGBPlane],
- media::YV12);
-
- for (size_t row = 0; row < rgb_surface.height; ++row) {
- uint32* rgb_row_data = reinterpret_cast<uint32*>(
- rgb_surface.data[VideoSurface::kRGBPlane] +
- (rgb_surface.strides[VideoSurface::kRGBPlane] * row));
- for (size_t col = 0; col < rgb_surface.width; ++col) {
- SCOPED_TRACE(StringPrintf("Checking (%" PRIuS ", %" PRIuS ")", row, col));
- EXPECT_EQ(expect_rgb_color, rgb_row_data[col]);
- }
- }
- rgb_frame->Unlock();
- yv12_frame->Unlock();
-}
-
-TEST(VideoFrameImpl, CreateFrame) {
- const size_t kWidth = 64;
- const size_t kHeight = 48;
- const base::TimeDelta kTimestampA = base::TimeDelta::FromMicroseconds(1337);
- const base::TimeDelta kDurationA = base::TimeDelta::FromMicroseconds(1667);
- const base::TimeDelta kTimestampB = base::TimeDelta::FromMicroseconds(1234);
- const base::TimeDelta kDurationB = base::TimeDelta::FromMicroseconds(5678);
-
- // Create a YV12 Video Frame.
- scoped_refptr<media::VideoFrame> frame;
- VideoFrameImpl::CreateFrame(media::VideoSurface::YV12, kWidth, kHeight,
- kTimestampA, kDurationA, &frame);
- ASSERT_TRUE(frame);
-
- // Test StreamSample implementation.
- EXPECT_EQ(kTimestampA.InMicroseconds(),
- frame->GetTimestamp().InMicroseconds());
- EXPECT_EQ(kDurationA.InMicroseconds(), frame->GetDuration().InMicroseconds());
- EXPECT_FALSE(frame->IsEndOfStream());
- EXPECT_FALSE(frame->IsDiscontinuous());
- frame->SetTimestamp(kTimestampB);
- frame->SetDuration(kDurationB);
- EXPECT_EQ(kTimestampB.InMicroseconds(),
- frame->GetTimestamp().InMicroseconds());
- EXPECT_EQ(kDurationB.InMicroseconds(), frame->GetDuration().InMicroseconds());
- EXPECT_FALSE(frame->IsEndOfStream());
- frame->SetDiscontinuous(true);
- EXPECT_TRUE(frame->IsDiscontinuous());
- frame->SetDiscontinuous(false);
- EXPECT_FALSE(frame->IsDiscontinuous());
-
- // Test VideoFrame implementation.
- {
- SCOPED_TRACE("");
- InitializeYV12Frame(frame, 0.0f);
- ExpectFrameColor(frame, 0xFF000000);
- }
- {
- SCOPED_TRACE("");
- InitializeYV12Frame(frame, 1.0f);
- ExpectFrameColor(frame, 0xFFFFFFFF);
- }
-
- // Test an empty frame.
- VideoFrameImpl::CreateEmptyFrame(&frame);
- EXPECT_TRUE(frame->IsEndOfStream());
-}
-
-TEST(VideoFrameImpl, CreateBlackFrame) {
- const size_t kWidth = 2;
- const size_t kHeight = 2;
- const uint8 kExpectedYRow[] = { 0, 0 };
- const uint8 kExpectedUVRow[] = { 128 };
-
- scoped_refptr<media::VideoFrame> frame;
- VideoFrameImpl::CreateBlackFrame(kWidth, kHeight, &frame);
- ASSERT_TRUE(frame);
-
- // Test basic properties.
- EXPECT_EQ(0, frame->GetTimestamp().InMicroseconds());
- EXPECT_EQ(0, frame->GetDuration().InMicroseconds());
- EXPECT_FALSE(frame->IsEndOfStream());
-
- // Test surface properties.
- VideoSurface surface;
- EXPECT_TRUE(frame->Lock(&surface));
- EXPECT_EQ(VideoSurface::YV12, surface.format);
- EXPECT_EQ(kWidth, surface.width);
- EXPECT_EQ(kHeight, surface.height);
- EXPECT_EQ(3u, surface.planes);
-
- // Test surfaces themselves.
- for (size_t y = 0; y < surface.height; ++y) {
- EXPECT_EQ(0, memcmp(kExpectedYRow, surface.data[VideoSurface::kYPlane],
- arraysize(kExpectedYRow)));
- surface.data[VideoSurface::kYPlane] +=
- surface.strides[VideoSurface::kYPlane];
- }
- for (size_t y = 0; y < surface.height / 2; ++y) {
- EXPECT_EQ(0, memcmp(kExpectedUVRow, surface.data[VideoSurface::kUPlane],
- arraysize(kExpectedUVRow)));
- EXPECT_EQ(0, memcmp(kExpectedUVRow, surface.data[VideoSurface::kVPlane],
- arraysize(kExpectedUVRow)));
- surface.data[VideoSurface::kUPlane] +=
- surface.strides[VideoSurface::kUPlane];
- surface.data[VideoSurface::kVPlane] +=
- surface.strides[VideoSurface::kVPlane];
- }
-}
-
-} // namespace media
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
new file mode 100644
index 0000000..27e15dc
--- /dev/null
+++ b/media/base/video_frame_unittest.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/video_frame.h"
+
+#include "base/format_macros.h"
+#include "base/string_util.h"
+#include "media/base/buffers.h"
+#include "media/base/mock_filters.h"
+#include "media/base/yuv_convert.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+// Helper function that initializes a YV12 frame with white and black scan
+// lines based on the |white_to_black| parameter. If 0, then the entire
+// frame will be black, if 1 then the entire frame will be white.
+void InitializeYV12Frame(VideoFrame* frame, double white_to_black) {
+ EXPECT_EQ(VideoFrame::YV12, frame->format());
+ size_t first_black_row = static_cast<size_t>(frame->height() *
+ white_to_black);
+ uint8* y_plane = frame->data(VideoFrame::kYPlane);
+ for (size_t row = 0; row < frame->height(); ++row) {
+ int color = (row < first_black_row) ? 0xFF : 0x00;
+ memset(y_plane, color, frame->width());
+ y_plane += frame->stride(VideoFrame::kYPlane);
+ }
+ uint8* u_plane = frame->data(VideoFrame::kUPlane);
+ uint8* v_plane = frame->data(VideoFrame::kVPlane);
+ for (size_t row = 0; row < frame->height(); row += 2) {
+ memset(u_plane, 0x80, frame->width() / 2);
+ memset(v_plane, 0x80, frame->width() / 2);
+ u_plane += frame->stride(VideoFrame::kUPlane);
+ v_plane += frame->stride(VideoFrame::kVPlane);
+ }
+}
+
+// Given a |yv12_frame| this method converts the YV12 frame to RGBA and
+// makes sure that all the pixels of the RBG frame equal |expect_rgb_color|.
+void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) {
+ // On linux and mac builds if you directly compare using EXPECT_EQ and use
+ // the VideoFrame::kNumxxxPlanes constants, it generates an error when
+ // linking. These are declared so that we can compare against locals.
+ const size_t expect_yuv_planes = VideoFrame::kNumYUVPlanes;
+ const size_t expect_rgb_planes = VideoFrame::kNumRGBPlanes;
+
+ ASSERT_EQ(VideoFrame::YV12, yv12_frame->format());
+ ASSERT_EQ(expect_yuv_planes, yv12_frame->planes());
+ ASSERT_EQ(yv12_frame->stride(VideoFrame::kUPlane),
+ yv12_frame->stride(VideoFrame::kVPlane));
+
+ scoped_refptr<media::VideoFrame> rgb_frame;
+ media::VideoFrame::CreateFrame(VideoFrame::RGBA,
+ yv12_frame->width(),
+ yv12_frame->height(),
+ yv12_frame->GetTimestamp(),
+ yv12_frame->GetDuration(),
+ &rgb_frame);
+
+ ASSERT_EQ(yv12_frame->width(), rgb_frame->width());
+ ASSERT_EQ(yv12_frame->height(), rgb_frame->height());
+ ASSERT_EQ(expect_rgb_planes, rgb_frame->planes());
+
+ media::ConvertYUVToRGB32(yv12_frame->data(VideoFrame::kYPlane),
+ yv12_frame->data(VideoFrame::kUPlane),
+ yv12_frame->data(VideoFrame::kVPlane),
+ rgb_frame->data(VideoFrame::kRGBPlane),
+ rgb_frame->width(),
+ rgb_frame->height(),
+ yv12_frame->stride(VideoFrame::kYPlane),
+ yv12_frame->stride(VideoFrame::kUPlane),
+ rgb_frame->stride(VideoFrame::kRGBPlane),
+ media::YV12);
+
+ for (size_t row = 0; row < rgb_frame->height(); ++row) {
+ uint32* rgb_row_data = reinterpret_cast<uint32*>(
+ rgb_frame->data(VideoFrame::kRGBPlane) +
+ (rgb_frame->stride(VideoFrame::kRGBPlane) * row));
+ for (size_t col = 0; col < rgb_frame->width(); ++col) {
+ SCOPED_TRACE(StringPrintf("Checking (%" PRIuS ", %" PRIuS ")",
+ row, col));
+ EXPECT_EQ(expect_rgb_color, rgb_row_data[col]);
+ }
+ }
+}
+
+TEST(VideoFrame, CreateFrame) {
+ const size_t kWidth = 64;
+ const size_t kHeight = 48;
+ const base::TimeDelta kTimestampA = base::TimeDelta::FromMicroseconds(1337);
+ const base::TimeDelta kDurationA = base::TimeDelta::FromMicroseconds(1667);
+ const base::TimeDelta kTimestampB = base::TimeDelta::FromMicroseconds(1234);
+ const base::TimeDelta kDurationB = base::TimeDelta::FromMicroseconds(5678);
+
+ // Create a YV12 Video Frame.
+ scoped_refptr<media::VideoFrame> frame;
+ VideoFrame::CreateFrame(media::VideoFrame::YV12, kWidth, kHeight,
+ kTimestampA, kDurationA, &frame);
+ ASSERT_TRUE(frame);
+
+ // Test StreamSample implementation.
+ EXPECT_EQ(kTimestampA.InMicroseconds(),
+ frame->GetTimestamp().InMicroseconds());
+ EXPECT_EQ(kDurationA.InMicroseconds(),
+ frame->GetDuration().InMicroseconds());
+ EXPECT_FALSE(frame->IsEndOfStream());
+ EXPECT_FALSE(frame->IsDiscontinuous());
+ frame->SetTimestamp(kTimestampB);
+ frame->SetDuration(kDurationB);
+ EXPECT_EQ(kTimestampB.InMicroseconds(),
+ frame->GetTimestamp().InMicroseconds());
+ EXPECT_EQ(kDurationB.InMicroseconds(),
+ frame->GetDuration().InMicroseconds());
+ EXPECT_FALSE(frame->IsEndOfStream());
+ frame->SetDiscontinuous(true);
+ EXPECT_TRUE(frame->IsDiscontinuous());
+ frame->SetDiscontinuous(false);
+ EXPECT_FALSE(frame->IsDiscontinuous());
+
+ // Test VideoFrame implementation.
+ {
+ SCOPED_TRACE("");
+ InitializeYV12Frame(frame, 0.0f);
+ ExpectFrameColor(frame, 0xFF000000);
+ }
+ {
+ SCOPED_TRACE("");
+ InitializeYV12Frame(frame, 1.0f);
+ ExpectFrameColor(frame, 0xFFFFFFFF);
+ }
+
+ // Test an empty frame.
+ VideoFrame::CreateEmptyFrame(&frame);
+ EXPECT_TRUE(frame->IsEndOfStream());
+}
+
+TEST(VideoFrame, CreateBlackFrame) {
+ const size_t kWidth = 2;
+ const size_t kHeight = 2;
+ const uint8 kExpectedYRow[] = { 0, 0 };
+ const uint8 kExpectedUVRow[] = { 128 };
+
+ scoped_refptr<media::VideoFrame> frame;
+ VideoFrame::CreateBlackFrame(kWidth, kHeight, &frame);
+ ASSERT_TRUE(frame);
+
+ // Test basic properties.
+ EXPECT_EQ(0, frame->GetTimestamp().InMicroseconds());
+ EXPECT_EQ(0, frame->GetDuration().InMicroseconds());
+ EXPECT_FALSE(frame->IsEndOfStream());
+
+ // Test |frame| properties.
+ EXPECT_EQ(VideoFrame::YV12, frame->format());
+ EXPECT_EQ(kWidth, frame->width());
+ EXPECT_EQ(kHeight, frame->height());
+ EXPECT_EQ(3u, frame->planes());
+
+ // Test frames themselves.
+ uint8* y_plane = frame->data(VideoFrame::kYPlane);
+ for (size_t y = 0; y < frame->height(); ++y) {
+ EXPECT_EQ(0, memcmp(kExpectedYRow, y_plane, arraysize(kExpectedYRow)));
+ y_plane += frame->stride(VideoFrame::kYPlane);
+ }
+
+ uint8* u_plane = frame->data(VideoFrame::kUPlane);
+ uint8* v_plane = frame->data(VideoFrame::kVPlane);
+ for (size_t y = 0; y < frame->height() / 2; ++y) {
+ EXPECT_EQ(0, memcmp(kExpectedUVRow, u_plane, arraysize(kExpectedUVRow)));
+ EXPECT_EQ(0, memcmp(kExpectedUVRow, v_plane, arraysize(kExpectedUVRow)));
+ u_plane += frame->stride(VideoFrame::kUPlane);
+ v_plane += frame->stride(VideoFrame::kVPlane);
+ }
+}
+
+} // namespace media