Commit 7eef1763 authored by jfroy's avatar jfroy Committed by Commit bot

Extend media::VideoFrame to wrap CVPixelBuffer on OS X and iOS.

This allows better integration of OS X and iOS media frameworks
with chromium code and makes buffer management less problematic,
especially when using CVPixelBufferPools provided by hardware
encoders or decoders.

BUG=401308
R=dalecurtis,hubbe

Review URL: https://codereview.chromium.org/446163003

Cr-Commit-Position: refs/heads/master@{#292023}
parent d4cb64a0
......@@ -278,6 +278,51 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs(
}
#endif
#if defined(OS_MACOSX)
// static
scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer(
CVPixelBufferRef cv_pixel_buffer,
base::TimeDelta timestamp) {
DCHECK(cv_pixel_buffer);
DCHECK(CFGetTypeID(cv_pixel_buffer) == CVPixelBufferGetTypeID());
OSType cv_format = CVPixelBufferGetPixelFormatType(cv_pixel_buffer);
Format format;
// There are very few compatible CV pixel formats, so just check each.
if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) {
format = Format::I420;
} else if (cv_format == kCVPixelFormatType_444YpCbCr8) {
format = Format::YV24;
} else if (cv_format == '420v') {
// TODO(jfroy): Use kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange when the
// minimum OS X and iOS SDKs permits it.
format = Format::NV12;
} else {
DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format;
return NULL;
}
gfx::Size coded_size(CVImageBufferGetEncodedSize(cv_pixel_buffer));
gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer));
gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer));
if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
return NULL;
scoped_refptr<VideoFrame> frame(
new VideoFrame(format,
coded_size,
visible_rect,
natural_size,
scoped_ptr<gpu::MailboxHolder>(),
timestamp,
false));
frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
return frame;
}
#endif
// static
scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
Format format,
......@@ -857,6 +902,12 @@ int VideoFrame::dmabuf_fd(size_t plane) const {
}
#endif
#if defined(OS_MACOSX)
CVPixelBufferRef VideoFrame::cv_pixel_buffer() const {
return cv_pixel_buffer_.get();
}
#endif
void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
for (int plane = 0; plane < kMaxPlanes; ++plane) {
if (!IsValidPlane(plane, format_))
......
......@@ -15,6 +15,11 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#if defined(OS_MACOSX)
#include <CoreVideo/CVPixelBuffer.h>
#include "base/mac/scoped_cftyperef.h"
#endif
class SkBitmap;
namespace gpu {
......@@ -148,6 +153,20 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
const base::Closure& no_longer_needed_cb);
#endif
#if defined(OS_MACOSX)
// Wraps a provided CVPixelBuffer with a VideoFrame. The pixel buffer is
// retained for the lifetime of the VideoFrame and released upon destruction.
// The image data is only accessible via the pixel buffer, which could be
// backed by an IOSurface from another process. All the attributes of the
// VideoFrame are derived from the pixel buffer, with the exception of the
// timestamp. If information is missing or is incompatible (for example, a
// pixel format that has no VideoFrame match), NULL is returned.
// http://crbug.com/401308
static scoped_refptr<VideoFrame> WrapCVPixelBuffer(
CVPixelBufferRef cv_pixel_buffer,
base::TimeDelta timestamp);
#endif
// 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.
......@@ -255,6 +274,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
int dmabuf_fd(size_t plane) const;
#endif
#if defined(OS_MACOSX)
// Returns the backing CVPixelBuffer, if present.
CVPixelBufferRef cv_pixel_buffer() const;
#endif
// Returns true if this VideoFrame represents the end of the stream.
bool end_of_stream() const { return end_of_stream_; }
......@@ -346,6 +370,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
base::ScopedFD dmabuf_fds_[kMaxPlanes];
#endif
#if defined(OS_MACOSX)
// CVPixelBuffer, if this frame is wrapping one.
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
#endif
base::Closure no_longer_needed_cb_;
base::TimeDelta timestamp_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment