From 638a259cd8565892bb55deacc1c4d95471eafcf9 Mon Sep 17 00:00:00 2001 From: "sheu@chromium.org" Date: Fri, 9 Aug 2013 08:04:35 +0000 Subject: media::VideoFrame::WrapExternalSharedMemory Add WrapExternalSharedMemory() for wrapping base::SharedMemory-backed buffers in a media::VideoFrame Also: add support for I420 in YUV handling paths for media::VideoFrame. BUG=None TEST=local build, run, unittests on desktop Linux Review URL: https://chromiumcodereview.appspot.com/22645005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216641 0039d316-1c4b-4281-b951-d872f2087c98 --- media/base/video_frame.cc | 69 ++++++++++++++++++++++++++++++++++++++--------- media/base/video_frame.h | 18 ++++++++++++- media/base/video_util.cc | 3 ++- 3 files changed, 75 insertions(+), 15 deletions(-) (limited to 'media') diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 10ad051..08e7e1a 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc @@ -34,6 +34,7 @@ scoped_refptr VideoFrame::CreateFrame( case VideoFrame::YV12: case VideoFrame::YV12A: case VideoFrame::YV16: + case VideoFrame::I420: frame->AllocateYUV(); break; default: @@ -117,20 +118,52 @@ void VideoFrame::ReadPixelsFromNativeTexture(const SkBitmap& pixels) { } // static +scoped_refptr VideoFrame::WrapExternalSharedMemory( + Format format, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + uint8* data, + base::SharedMemoryHandle handle, + base::TimeDelta timestamp, + const base::Closure& no_longer_needed_cb) { + switch (format) { + case I420: { + scoped_refptr frame(new VideoFrame( + format, coded_size, visible_rect, natural_size, timestamp)); + frame->shared_memory_handle_ = handle; + frame->strides_[kYPlane] = coded_size.width(); + frame->strides_[kUPlane] = coded_size.width() / 2; + frame->strides_[kVPlane] = coded_size.width() / 2; + frame->data_[kYPlane] = data; + frame->data_[kUPlane] = data + coded_size.GetArea(); + frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4); + frame->no_longer_needed_cb_ = no_longer_needed_cb; + return frame; + } + default: + NOTIMPLEMENTED(); + return NULL; + } +} + +// static scoped_refptr VideoFrame::WrapExternalYuvData( Format format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, const gfx::Size& natural_size, - int32 y_stride, int32 u_stride, int32 v_stride, - uint8* y_data, uint8* u_data, uint8* v_data, + int32 y_stride, + int32 u_stride, + int32 v_stride, + uint8* y_data, + uint8* u_data, + uint8* v_data, base::TimeDelta timestamp, - base::SharedMemoryHandle shm_handle, const base::Closure& no_longer_needed_cb) { DCHECK(format == YV12 || format == YV16 || format == I420) << format; scoped_refptr frame(new VideoFrame( format, coded_size, visible_rect, natural_size, timestamp)); - frame->shared_memory_handle_ = shm_handle; frame->strides_[kYPlane] = y_stride; frame->strides_[kUPlane] = u_stride; frame->strides_[kVPlane] = v_stride; @@ -198,11 +231,11 @@ size_t VideoFrame::NumPlanes(Format format) { return 1; case VideoFrame::YV12: case VideoFrame::YV16: + case VideoFrame::I420: return 3; case VideoFrame::YV12A: return 4; case VideoFrame::EMPTY: - case VideoFrame::I420: case VideoFrame::INVALID: break; } @@ -239,7 +272,7 @@ void VideoFrame::AllocateRGB(size_t bytes_per_pixel) { void VideoFrame::AllocateYUV() { DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 || - format_ == VideoFrame::YV12A); + format_ == VideoFrame::YV12A || format_ == VideoFrame::I420); // Align Y rows at least at 16 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 @@ -259,9 +292,11 @@ void VideoFrame::AllocateYUV() { // and then the size needs to be a multiple of two macroblocks (vertically). // See libavcodec/utils.c:avcodec_align_dimensions2(). size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2); - size_t uv_height = (format_ == VideoFrame::YV12 || - format_ == VideoFrame::YV12A) ? - y_height / 2 : y_height; + size_t uv_height = + (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A || + format_ == VideoFrame::I420) + ? y_height / 2 + : y_height; size_t y_bytes = y_height * y_stride; size_t uv_bytes = uv_height * uv_stride; size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0; @@ -327,10 +362,14 @@ int VideoFrame::row_bytes(size_t plane) const { return width * 4; // Planar, 8bpp. + case YV12A: + if (plane == kAPlane) + return width; + // Fallthrough. case YV12: case YV16: - case YV12A: - if (plane == kYPlane || plane == kAPlane) + case I420: + if (plane == kYPlane) return width; return RoundUp(width, 2) / 2; @@ -351,9 +390,13 @@ int VideoFrame::rows(size_t plane) const { case YV16: return height; - case YV12: case YV12A: - if (plane == kYPlane || plane == kAPlane) + if (plane == kAPlane) + return height; + // Fallthrough. + case YV12: + case I420: + if (plane == kYPlane) return height; return RoundUp(height, 2) / 2; diff --git a/media/base/video_frame.h b/media/base/video_frame.h index 8207d9b..82a08a9 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h @@ -137,9 +137,26 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { // least as large as 4*visible_rect().width()*visible_rect().height(). void ReadPixelsFromNativeTexture(const SkBitmap& pixels); + // Wraps image data in a buffer backed by a base::SharedMemoryHandle with a + // VideoFrame. The image data resides in |data| and is assumed to be packed + // tightly in a buffer of logical dimensions |coded_size| with the appropriate + // bit depth and plane count as given by |format|. When the frame is + // destroyed |no_longer_needed_cb.Run()| will be called. + static scoped_refptr WrapExternalSharedMemory( + Format format, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + uint8* data, + base::SharedMemoryHandle handle, + base::TimeDelta timestamp, + const base::Closure& no_longer_needed_cb); + // Wraps external YUV data of the given parameters with a VideoFrame. // The returned VideoFrame does not own the data passed in. When the frame // is destroyed |no_longer_needed_cb.Run()| will be called. + // TODO(sheu): merge this into WrapExternalSharedMemory(). + // http://crbug.com/270217 static scoped_refptr WrapExternalYuvData( Format format, const gfx::Size& coded_size, @@ -152,7 +169,6 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe { uint8* u_data, uint8* v_data, base::TimeDelta timestamp, - base::SharedMemoryHandle shm_handle, // may be NULLHandle() const base::Closure& no_longer_needed_cb); // Creates a frame with format equals to VideoFrame::EMPTY, width, height, diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 9da651f..fda758e 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc @@ -143,7 +143,8 @@ void LetterboxYUV(VideoFrame* frame, const gfx::Rect& view_area) { DCHECK(!(view_area.y() & 1)); DCHECK(!(view_area.width() & 1)); DCHECK(!(view_area.height() & 1)); - DCHECK_EQ(frame->format(), VideoFrame::YV12); + DCHECK(frame->format() == VideoFrame::YV12 || + frame->format() == VideoFrame::I420); LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00); gfx::Rect half_view_area(view_area.x() / 2, view_area.y() / 2, -- cgit v1.1