Index: media/base/video_frame.cc |
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc |
index 12b46d56d3f98fefae980e047eccd68a87b61070..8e323a6bd4cc9d10267e569b110a35d835bcb7f1 100644 |
--- a/media/base/video_frame.cc |
+++ b/media/base/video_frame.cc |
@@ -53,15 +53,14 @@ static gfx::Size SampleSize(VideoFrame::Format format, size_t plane) { |
case VideoFrame::YV12: |
case VideoFrame::I420: |
case VideoFrame::YV12A: |
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) |
case VideoFrame::NV12: |
+#endif |
return gfx::Size(2, 2); |
case VideoFrame::UNKNOWN: |
-#if defined(VIDEO_HOLE) |
- case VideoFrame::HOLE: |
-#endif // defined(VIDEO_HOLE) |
- case VideoFrame::NATIVE_TEXTURE: |
case VideoFrame::ARGB: |
+ case VideoFrame::XRGB: |
break; |
} |
} |
@@ -82,16 +81,11 @@ static gfx::Size CommonAlignment(VideoFrame::Format format) { |
return gfx::Size(max_sample_width, max_sample_height); |
} |
-// Returns the number of bytes per element for given |plane| and |format|. E.g. |
-// 2 for the UV plane in NV12. |
+// Returns the number of bytes per element for given |plane| and |format|. |
static int BytesPerElement(VideoFrame::Format format, size_t plane) { |
DCHECK(VideoFrame::IsValidPlane(plane, format)); |
- if (format == VideoFrame::ARGB) |
+ if (format == VideoFrame::ARGB || format == VideoFrame::XRGB) |
return 4; |
- |
- if (format == VideoFrame::NV12 && plane == VideoFrame::kUVPlane) |
- return 2; |
- |
return 1; |
} |
@@ -103,78 +97,70 @@ static gfx::Size AdjustCodedSize(VideoFrame::Format format, |
RoundUp(coded_size.height(), alignment.height())); |
} |
-// static |
-scoped_refptr<VideoFrame> VideoFrame::CreateFrame( |
- VideoFrame::Format format, |
- const gfx::Size& coded_size, |
- const gfx::Rect& visible_rect, |
- const gfx::Size& natural_size, |
- base::TimeDelta timestamp) { |
- switch (format) { |
- case VideoFrame::YV12: |
- case VideoFrame::YV16: |
- case VideoFrame::I420: |
- case VideoFrame::YV12A: |
- case VideoFrame::YV24: |
- break; |
+// Release data allocated by AllocateYUV(). |
+static void ReleaseData(uint8* data) { |
+ DCHECK(data); |
+ base::AlignedFree(data); |
+} |
- case VideoFrame::UNKNOWN: |
- case VideoFrame::NV12: |
- case VideoFrame::NATIVE_TEXTURE: |
-#if defined(VIDEO_HOLE) |
- case VideoFrame::HOLE: |
-#endif // defined(VIDEO_HOLE) |
- case VideoFrame::ARGB: |
- NOTIMPLEMENTED(); |
- return nullptr; |
+//static |
+bool VideoFrame::IsYuvPlanar(Format format) { |
+ switch (format) { |
+ case YV12: |
+ case I420: |
+ case YV16: |
+ case YV12A: |
+ case YV24: |
+ return true; |
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) |
+ case NV12: |
+#endif |
+ case UNKNOWN: |
+ case ARGB: |
+ case XRGB: |
+ return false; |
} |
+ return false; |
+} |
- // Since we're creating a new YUV frame (and allocating memory for it |
- // ourselves), we can pad the requested |coded_size| if necessary if the |
- // request does not line up on sample boundaries. |
- const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); |
- DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); |
- |
- gpu::MailboxHolder mailboxes[kMaxPlanes]; |
- scoped_refptr<VideoFrame> frame( |
- new VideoFrame(format, new_coded_size, visible_rect, natural_size, |
- mailboxes, TEXTURE_RGBA, timestamp, false)); |
- frame->AllocateYUV(); |
- return frame; |
+//static |
+bool VideoFrame::IsMappable(StorageType storage_type) { |
+ return storage_type == STORAGE_SHMEM || |
+ storage_type == STORAGE_OWNED_MEMORY || |
+ storage_type == STORAGE_UNOWNED_MEMORY; |
} |
// static |
-std::string VideoFrame::FormatToString(VideoFrame::Format format) { |
+std::string VideoFrame::FormatToString(Format format) { |
switch (format) { |
- case VideoFrame::UNKNOWN: |
+ case UNKNOWN: |
return "UNKNOWN"; |
- case VideoFrame::YV12: |
+ case YV12: |
return "YV12"; |
- case VideoFrame::YV16: |
+ case YV16: |
return "YV16"; |
- case VideoFrame::I420: |
+ case I420: |
return "I420"; |
- case VideoFrame::NATIVE_TEXTURE: |
- return "NATIVE_TEXTURE"; |
-#if defined(VIDEO_HOLE) |
- case VideoFrame::HOLE: |
- return "HOLE"; |
-#endif // defined(VIDEO_HOLE) |
- case VideoFrame::YV12A: |
+ case YV12A: |
return "YV12A"; |
- case VideoFrame::NV12: |
- return "NV12"; |
- case VideoFrame::YV24: |
+ case YV24: |
return "YV24"; |
- case VideoFrame::ARGB: |
+ case ARGB: |
return "ARGB"; |
+ case XRGB: |
+ return "XRGB"; |
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) |
+ case NV12: |
+ return "NV12"; |
+#endif |
} |
- NOTREACHED() << "Invalid videoframe format provided: " << format; |
+ NOTREACHED() << "Invalid VideoFrame format provided: " << format; |
return ""; |
} |
// static |
-bool VideoFrame::IsValidConfig(VideoFrame::Format format, |
+bool VideoFrame::IsValidConfig(Format format, |
+ StorageType storage_type, |
const gfx::Size& coded_size, |
const gfx::Rect& visible_rect, |
const gfx::Size& natural_size) { |
@@ -190,27 +176,30 @@ bool VideoFrame::IsValidConfig(VideoFrame::Format format, |
natural_size.height() > limits::kMaxDimension) |
return false; |
+// TODO(mcasas): Remove parameter |storage_type| when STORAGE_HOLE and |
+// STORAGE_TEXTURE comply with the checks below. Right now we skip them. |
+#if defined(VIDEO_HOLE) |
+ if (storage_type == STORAGE_HOLE) |
+ return true; |
+#endif |
+ if(storage_type == STORAGE_TEXTURE) |
+ return true; |
+ |
// Check format-specific width/height requirements. |
switch (format) { |
- case VideoFrame::UNKNOWN: |
+ case UNKNOWN: |
return (coded_size.IsEmpty() && visible_rect.IsEmpty() && |
natural_size.IsEmpty()); |
- |
- // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are |
- // allowed to skip the below check. |
- case VideoFrame::NATIVE_TEXTURE: |
-#if defined(VIDEO_HOLE) |
- case VideoFrame::HOLE: |
-#endif // defined(VIDEO_HOLE) |
- return true; |
- |
- case VideoFrame::YV24: |
- case VideoFrame::YV12: |
- case VideoFrame::I420: |
- case VideoFrame::YV12A: |
- case VideoFrame::NV12: |
- case VideoFrame::YV16: |
- case VideoFrame::ARGB: |
+ case YV24: |
+ case YV12: |
+ case I420: |
+ case YV12A: |
+ case YV16: |
+ case ARGB: |
+ case XRGB: |
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) |
+ case NV12: |
+#endif |
// Check that software-allocated buffer formats are aligned correctly and |
// not empty. |
const gfx::Size alignment = CommonAlignment(format); |
@@ -222,11 +211,39 @@ bool VideoFrame::IsValidConfig(VideoFrame::Format format, |
!natural_size.IsEmpty(); |
} |
+ // TODO(mcasas): Check that storage type and underlying mailboxes/dataptr are |
+ // matching. |
NOTREACHED(); |
return false; |
} |
// static |
+scoped_refptr<VideoFrame> VideoFrame::CreateFrame( |
+ Format format, |
+ const gfx::Size& coded_size, |
+ const gfx::Rect& visible_rect, |
+ const gfx::Size& natural_size, |
+ base::TimeDelta timestamp) { |
+ if (!IsYuvPlanar(format)) { |
+ NOTIMPLEMENTED(); |
+ return nullptr; |
+ } |
+ |
+ // Since we're creating a new YUV frame (and allocating memory for it |
+ // ourselves), we can pad the requested |coded_size| if necessary if the |
+ // request does not line up on sample boundaries. |
+ const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); |
+ DCHECK(IsValidConfig(format, STORAGE_OWNED_MEMORY, new_coded_size, |
+ visible_rect, natural_size)); |
+ |
+ scoped_refptr<VideoFrame> frame( |
+ new VideoFrame(format, STORAGE_OWNED_MEMORY, new_coded_size, visible_rect, |
+ natural_size, timestamp, false)); |
+ frame->AllocateYUV(); |
+ return frame; |
+} |
+ |
+// static |
scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( |
const gpu::MailboxHolder& mailbox_holder, |
const ReleaseMailboxCB& mailbox_holder_release_cb, |
@@ -238,10 +255,10 @@ scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( |
bool has_alpha) { |
gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
mailbox_holders[kARGBPlane] = mailbox_holder; |
- TextureFormat texture_format = has_alpha ? TEXTURE_RGBA : TEXTURE_RGB; |
+ Format texture_format = has_alpha ? ARGB : XRGB; |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size, |
- mailbox_holders, texture_format, timestamp, false)); |
+ new VideoFrame(texture_format, STORAGE_TEXTURE, coded_size, visible_rect, |
+ natural_size, mailbox_holders, timestamp, false)); |
frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb; |
frame->allow_overlay_ = allow_overlay; |
return frame; |
@@ -263,15 +280,29 @@ scoped_refptr<VideoFrame> VideoFrame::WrapYUV420NativeTextures( |
mailbox_holders[kUPlane] = u_mailbox_holder; |
mailbox_holders[kVPlane] = v_mailbox_holder; |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(NATIVE_TEXTURE, coded_size, visible_rect, natural_size, |
- mailbox_holders, TEXTURE_YUV_420, timestamp, false)); |
+ new VideoFrame(I420, STORAGE_TEXTURE, coded_size, visible_rect, |
+ natural_size, mailbox_holders, timestamp, false)); |
frame->mailbox_holders_release_cb_ = mailbox_holder_release_cb; |
frame->allow_overlay_ = allow_overlay; |
return frame; |
} |
// static |
-scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory( |
+scoped_refptr<VideoFrame> VideoFrame::WrapExternalData( |
+ Format format, |
+ const gfx::Size& coded_size, |
+ const gfx::Rect& visible_rect, |
+ const gfx::Size& natural_size, |
+ uint8* data, |
+ size_t data_size, |
+ base::TimeDelta timestamp) { |
+ return WrapExternalStorage(format, STORAGE_UNOWNED_MEMORY, coded_size, |
+ visible_rect, natural_size, data, data_size, |
+ timestamp, base::SharedMemory::NULLHandle(), 0); |
+} |
+ |
+// static |
+scoped_refptr<VideoFrame> VideoFrame::WrapExternalSharedMemory( |
Format format, |
const gfx::Size& coded_size, |
const gfx::Rect& visible_rect, |
@@ -281,33 +312,9 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalPackedMemory( |
base::SharedMemoryHandle handle, |
size_t data_offset, |
base::TimeDelta timestamp) { |
- const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); |
- |
- if (!IsValidConfig(format, new_coded_size, visible_rect, natural_size)) |
- return NULL; |
- if (data_size < AllocationSize(format, new_coded_size)) |
- return NULL; |
- |
- switch (format) { |
- case VideoFrame::I420: { |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
- scoped_refptr<VideoFrame> frame( |
- new VideoFrame(format, new_coded_size, visible_rect, natural_size, |
- mailbox_holders, TEXTURE_RGBA, timestamp, false)); |
- frame->shared_memory_handle_ = handle; |
- frame->shared_memory_offset_ = data_offset; |
- frame->strides_[kYPlane] = new_coded_size.width(); |
- frame->strides_[kUPlane] = new_coded_size.width() / 2; |
- frame->strides_[kVPlane] = new_coded_size.width() / 2; |
- frame->data_[kYPlane] = data; |
- frame->data_[kUPlane] = data + new_coded_size.GetArea(); |
- frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4); |
- return frame; |
- } |
- default: |
- NOTIMPLEMENTED(); |
- return NULL; |
- } |
+ return WrapExternalStorage(format, STORAGE_SHMEM, coded_size, visible_rect, |
+ natural_size, data, data_size, timestamp, handle, |
+ data_offset); |
} |
// static |
@@ -324,12 +331,12 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( |
uint8* v_data, |
base::TimeDelta timestamp) { |
const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); |
- CHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size)); |
+ CHECK(IsValidConfig(format, STORAGE_UNOWNED_MEMORY, new_coded_size, |
+ visible_rect, natural_size)); |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(format, new_coded_size, visible_rect, natural_size, |
- mailbox_holders, TEXTURE_RGBA, timestamp, false)); |
+ new VideoFrame(format, STORAGE_UNOWNED_MEMORY, new_coded_size, |
+ visible_rect, natural_size, timestamp, false)); |
frame->strides_[kYPlane] = y_stride; |
frame->strides_[kUPlane] = u_stride; |
frame->strides_[kVPlane] = v_stride; |
@@ -339,7 +346,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData( |
return frame; |
} |
-#if defined(OS_POSIX) |
+#if defined(OS_LINUX) |
// static |
scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs( |
Format format, |
@@ -348,8 +355,10 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs( |
const gfx::Size& natural_size, |
const std::vector<int> dmabuf_fds, |
base::TimeDelta timestamp) { |
- if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) |
+ if (!IsValidConfig(format, STORAGE_DMABUFS, coded_size, visible_rect, |
+ natural_size)) { |
return NULL; |
+ } |
// TODO(posciak): This is not exactly correct, it's possible for one |
// buffer to contain more than one plane. |
@@ -358,10 +367,10 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs( |
return NULL; |
} |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
+ DCHECK_EQ(format, ARGB); |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(format, coded_size, visible_rect, natural_size, |
- mailbox_holders, TEXTURE_RGBA, timestamp, false)); |
+ new VideoFrame(format, STORAGE_DMABUFS, coded_size, visible_rect, |
+ natural_size, timestamp, false)); |
for (size_t i = 0; i < dmabuf_fds.size(); ++i) { |
int duped_fd = HANDLE_EINTR(dup(dmabuf_fds[i])); |
@@ -394,13 +403,13 @@ scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer( |
Format format; |
// There are very few compatible CV pixel formats, so just check each. |
if (cv_format == kCVPixelFormatType_420YpCbCr8Planar) { |
- format = Format::I420; |
+ format = I420; |
} else if (cv_format == kCVPixelFormatType_444YpCbCr8) { |
- format = Format::YV24; |
+ 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; |
+ format = NV12; |
} else { |
DLOG(ERROR) << "CVPixelBuffer format not supported: " << cv_format; |
return NULL; |
@@ -410,13 +419,14 @@ scoped_refptr<VideoFrame> VideoFrame::WrapCVPixelBuffer( |
const gfx::Rect visible_rect(CVImageBufferGetCleanRect(cv_pixel_buffer)); |
const gfx::Size natural_size(CVImageBufferGetDisplaySize(cv_pixel_buffer)); |
- if (!IsValidConfig(format, coded_size, visible_rect, natural_size)) |
+ if (!IsValidConfig(format, STORAGE_UNOWNED_MEMORY, coded_size, visible_rect, |
+ natural_size)) { |
return NULL; |
+ } |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(format, coded_size, visible_rect, natural_size, |
- mailbox_holders, TEXTURE_RGBA, timestamp, false)); |
+ new VideoFrame(format, STORAGE_UNOWNED_MEMORY, coded_size, visible_rect, |
+ natural_size, timestamp, false)); |
frame->cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN); |
return frame; |
@@ -428,15 +438,14 @@ scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( |
const scoped_refptr<VideoFrame>& frame, |
const gfx::Rect& visible_rect, |
const gfx::Size& natural_size) { |
- // NATIVE_TEXTURE frames need mailbox info propagated, and there's no support |
+ // STORAGE_TEXTURE frames need mailbox info propagated, and there's no support |
// for that here yet, see http://crbug/362521. |
- CHECK_NE(frame->format(), NATIVE_TEXTURE); |
+ CHECK_NE(frame->storage_type(), STORAGE_TEXTURE); |
DCHECK(frame->visible_rect().Contains(visible_rect)); |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
scoped_refptr<VideoFrame> wrapped_frame( |
- new VideoFrame(frame->format(), frame->coded_size(), visible_rect, |
- natural_size, mailbox_holders, TEXTURE_RGBA, |
+ new VideoFrame(frame->format(), frame->storage_type(), |
+ frame->coded_size(), visible_rect, natural_size, |
frame->timestamp(), frame->end_of_stream())); |
for (size_t i = 0; i < NumPlanes(frame->format()); ++i) { |
@@ -449,10 +458,8 @@ scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( |
// static |
scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { |
- gpu::MailboxHolder mailbox_holders[kMaxPlanes]; |
- return new VideoFrame(VideoFrame::UNKNOWN, gfx::Size(), gfx::Rect(), |
- gfx::Size(), mailbox_holders, TEXTURE_RGBA, |
- kNoTimestamp(), true); |
+ return new VideoFrame(UNKNOWN, STORAGE_UNKNOWN, gfx::Size(), gfx::Rect(), |
+ gfx::Size(), kNoTimestamp(), true); |
} |
// static |
@@ -460,8 +467,8 @@ scoped_refptr<VideoFrame> VideoFrame::CreateColorFrame( |
const gfx::Size& size, |
uint8 y, uint8 u, uint8 v, |
base::TimeDelta timestamp) { |
- scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( |
- VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); |
+ scoped_refptr<VideoFrame> frame = |
+ CreateFrame(YV12, size, gfx::Rect(size), size, timestamp); |
FillYUV(frame.get(), y, u, v); |
return frame; |
} |
@@ -481,28 +488,24 @@ scoped_refptr<VideoFrame> VideoFrame::CreateTransparentFrame( |
const uint8 kBlackUV = 0x00; |
const uint8 kTransparentA = 0x00; |
const base::TimeDelta kZero; |
- scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( |
- VideoFrame::YV12A, size, gfx::Rect(size), size, kZero); |
+ scoped_refptr<VideoFrame> frame = |
+ CreateFrame(YV12A, size, gfx::Rect(size), size, kZero); |
FillYUVA(frame.get(), kBlackY, kBlackUV, kBlackUV, kTransparentA); |
return frame; |
} |
#if defined(VIDEO_HOLE) |
// This block and other blocks wrapped around #if defined(VIDEO_HOLE) is not |
-// maintained by the general compositor team. Please contact the following |
-// people instead: |
-// |
-// wonsik@chromium.org |
-// ycheo@chromium.org |
+// maintained by the general compositor team. Please contact |
+// wonsik@chromium.org . |
// static |
scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( |
const gfx::Size& size) { |
- DCHECK(IsValidConfig(VideoFrame::HOLE, size, gfx::Rect(size), size)); |
- gpu::MailboxHolder mailboxes[kMaxPlanes]; |
+ DCHECK(IsValidConfig(UNKNOWN, STORAGE_HOLE, size, gfx::Rect(size), size)); |
scoped_refptr<VideoFrame> frame( |
- new VideoFrame(VideoFrame::HOLE, size, gfx::Rect(size), size, mailboxes, |
- TEXTURE_RGBA, base::TimeDelta(), false)); |
+ new VideoFrame(UNKNOWN, STORAGE_HOLE, size, gfx::Rect(size), size, |
+ base::TimeDelta(), false)); |
return frame; |
} |
#endif // defined(VIDEO_HOLE) |
@@ -510,23 +513,21 @@ scoped_refptr<VideoFrame> VideoFrame::CreateHoleFrame( |
// static |
size_t VideoFrame::NumPlanes(Format format) { |
switch (format) { |
- case VideoFrame::NATIVE_TEXTURE: |
-#if defined(VIDEO_HOLE) |
- case VideoFrame::HOLE: |
-#endif // defined(VIDEO_HOLE) |
- return 0; |
- case VideoFrame::ARGB: |
+ case ARGB: |
+ case XRGB: |
return 1; |
- case VideoFrame::NV12: |
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS) |
+ case NV12: |
return 2; |
- case VideoFrame::YV12: |
- case VideoFrame::YV16: |
- case VideoFrame::I420: |
- case VideoFrame::YV24: |
+#endif |
+ case YV12: |
+ case YV16: |
+ case I420: |
+ case YV24: |
return 3; |
- case VideoFrame::YV12A: |
+ case YV12A: |
return 4; |
- case VideoFrame::UNKNOWN: |
+ case UNKNOWN: |
break; |
} |
NOTREACHED() << "Unsupported video frame format: " << format; |
@@ -534,20 +535,6 @@ size_t VideoFrame::NumPlanes(Format format) { |
} |
// static |
-size_t VideoFrame::NumTextures(TextureFormat texture_format) { |
- switch (texture_format) { |
- case TEXTURE_RGBA: |
- case TEXTURE_RGB: |
- return 1; |
- case TEXTURE_YUV_420: |
- return 3; |
- } |
- |
- NOTREACHED(); |
- return 0; |
-} |
- |
-// static |
size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) { |
size_t total = 0; |
for (size_t i = 0; i < NumPlanes(format); ++i) |
@@ -563,7 +550,7 @@ gfx::Size VideoFrame::PlaneSize(Format format, |
int width = coded_size.width(); |
int height = coded_size.height(); |
- if (format != VideoFrame::ARGB) { |
+ if (format != ARGB) { |
// Align to multiple-of-two size overall. This ensures that non-subsampled |
// planes can be addressed by pixel with the same scaling as the subsampled |
// planes. |
@@ -600,20 +587,13 @@ int VideoFrame::PlaneBitsPerPixel(Format format, size_t plane) { |
SampleSize(format, plane).height(); |
} |
-// Release data allocated by AllocateYUV(). |
-static void ReleaseData(uint8* data) { |
- DCHECK(data); |
- base::AlignedFree(data); |
-} |
- |
void VideoFrame::AllocateYUV() { |
- DCHECK(format_ == YV12 || format_ == YV16 || format_ == YV12A || |
- format_ == I420 || format_ == YV24); |
+ DCHECK_EQ(storage_type_, STORAGE_OWNED_MEMORY); |
static_assert(0 == kYPlane, "y plane data must be index 0"); |
size_t data_size = 0; |
size_t offset[kMaxPlanes]; |
- for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane) { |
+ for (size_t plane = 0; plane < NumPlanes(format_); ++plane) { |
// The *2 in alignment for height is because some formats (e.g. h264) allow |
// interlaced coding, and then the size needs to be a multiple of two |
// macroblocks (vertically). See |
@@ -637,22 +617,21 @@ void VideoFrame::AllocateYUV() { |
base::AlignedAlloc(data_size, kFrameAddressAlignment)); |
memset(data, 0, data_size); |
- for (size_t plane = 0; plane < VideoFrame::NumPlanes(format_); ++plane) |
+ for (size_t plane = 0; plane < NumPlanes(format_); ++plane) |
data_[plane] = data + offset[plane]; |
AddDestructionObserver(base::Bind(&ReleaseData, data)); |
} |
-VideoFrame::VideoFrame(VideoFrame::Format format, |
+VideoFrame::VideoFrame(Format format, |
+ StorageType storage_type, |
const gfx::Size& coded_size, |
const gfx::Rect& visible_rect, |
const gfx::Size& natural_size, |
- const gpu::MailboxHolder(&mailbox_holders)[kMaxPlanes], |
- VideoFrame::TextureFormat texture_format, |
base::TimeDelta timestamp, |
bool end_of_stream) |
: format_(format), |
- texture_format_(texture_format), |
+ storage_type_(storage_type), |
coded_size_(coded_size), |
visible_rect_(visible_rect), |
natural_size_(natural_size), |
@@ -662,12 +641,41 @@ VideoFrame::VideoFrame(VideoFrame::Format format, |
release_sync_point_(0), |
end_of_stream_(end_of_stream), |
allow_overlay_(false) { |
- DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_)); |
- memcpy(&mailbox_holders_, mailbox_holders, sizeof(mailbox_holders_)); |
+ DCHECK(IsValidConfig(format_, storage_type, coded_size_, visible_rect_, |
+ natural_size_)); |
+ memset(&mailbox_holders_, 0, sizeof(mailbox_holders_)); |
memset(&strides_, 0, sizeof(strides_)); |
memset(&data_, 0, sizeof(data_)); |
} |
+VideoFrame::VideoFrame(Format format, |
+ StorageType storage_type, |
+ const gfx::Size& coded_size, |
+ const gfx::Rect& visible_rect, |
+ const gfx::Size& natural_size, |
+ base::TimeDelta timestamp, |
+ bool end_of_stream, |
+ base::SharedMemoryHandle handle, |
+ size_t shared_memory_offset) |
+ : VideoFrame(format, storage_type, coded_size, visible_rect, natural_size, |
+ timestamp, end_of_stream) { |
+ shared_memory_handle_ = handle; |
+ shared_memory_offset_ = shared_memory_offset; |
+} |
+ |
+VideoFrame::VideoFrame(Format format, |
+ StorageType storage_type, |
+ const gfx::Size& coded_size, |
+ const gfx::Rect& visible_rect, |
+ const gfx::Size& natural_size, |
+ const gpu::MailboxHolder(&mailbox_holders)[kMaxPlanes], |
+ base::TimeDelta timestamp, |
+ bool end_of_stream) |
+ : VideoFrame(format, storage_type, coded_size, visible_rect, natural_size, |
+ timestamp, end_of_stream) { |
+ memcpy(&mailbox_holders_, mailbox_holders, sizeof(mailbox_holders_)); |
+} |
+ |
VideoFrame::~VideoFrame() { |
if (!mailbox_holders_release_cb_.is_null()) { |
uint32 release_sync_point; |
@@ -685,7 +693,48 @@ VideoFrame::~VideoFrame() { |
} |
// static |
-bool VideoFrame::IsValidPlane(size_t plane, VideoFrame::Format format) { |
+scoped_refptr<VideoFrame> VideoFrame::WrapExternalStorage( |
+ Format format, |
+ StorageType storage_type, |
+ const gfx::Size& coded_size, |
+ const gfx::Rect& visible_rect, |
+ const gfx::Size& natural_size, |
+ uint8* data, |
+ size_t data_size, |
+ base::TimeDelta timestamp, |
+ base::SharedMemoryHandle handle, |
+ size_t data_offset) { |
+ const gfx::Size new_coded_size = AdjustCodedSize(format, coded_size); |
+ |
+ if (!IsValidConfig(format, storage_type, new_coded_size, visible_rect, |
+ natural_size) || |
+ data_size < AllocationSize(format, new_coded_size)) { |
+ return NULL; |
+ } |
+ DLOG_IF(ERROR, format != I420) << "Only I420 format supported: " |
+ << FormatToString(format); |
+ if (format != I420) |
+ return NULL; |
+ |
+ scoped_refptr<VideoFrame> frame; |
+ if (storage_type == STORAGE_SHMEM) { |
+ frame = new VideoFrame(format, storage_type, new_coded_size, visible_rect, |
+ natural_size, timestamp, false, handle, data_offset); |
+ } else { |
+ frame = new VideoFrame(format, storage_type, new_coded_size, visible_rect, |
+ natural_size, timestamp, false); |
+ } |
+ frame->strides_[kYPlane] = new_coded_size.width(); |
+ frame->strides_[kUPlane] = new_coded_size.width() / 2; |
+ frame->strides_[kVPlane] = new_coded_size.width() / 2; |
+ frame->data_[kYPlane] = data; |
+ frame->data_[kUPlane] = data + new_coded_size.GetArea(); |
+ frame->data_[kVPlane] = data + (new_coded_size.GetArea() * 5 / 4); |
+ return frame; |
+} |
+ |
+// static |
+bool VideoFrame::IsValidPlane(size_t plane, Format format) { |
return (plane < NumPlanes(format)); |
} |
@@ -695,9 +744,7 @@ int VideoFrame::stride(size_t plane) const { |
} |
// static |
-size_t VideoFrame::RowBytes(size_t plane, |
- VideoFrame::Format format, |
- int width) { |
+size_t VideoFrame::RowBytes(size_t plane, Format format, int width) { |
DCHECK(IsValidPlane(plane, format)); |
return BytesPerElement(format, plane) * Columns(plane, format, width); |
} |
@@ -707,7 +754,7 @@ int VideoFrame::row_bytes(size_t plane) const { |
} |
// static |
-size_t VideoFrame::Rows(size_t plane, VideoFrame::Format format, int height) { |
+size_t VideoFrame::Rows(size_t plane, Format format, int height) { |
DCHECK(IsValidPlane(plane, format)); |
const int sample_height = SampleSize(format, plane).height(); |
return RoundUp(height, sample_height) / sample_height; |
@@ -726,16 +773,19 @@ int VideoFrame::rows(size_t plane) const { |
const uint8* VideoFrame::data(size_t plane) const { |
DCHECK(IsValidPlane(plane, format_)); |
+ DCHECK(IsMappable(storage_type_)); |
return data_[plane]; |
} |
uint8* VideoFrame::data(size_t plane) { |
DCHECK(IsValidPlane(plane, format_)); |
+ DCHECK(IsMappable(storage_type_)); |
return data_[plane]; |
} |
const uint8* VideoFrame::visible_data(size_t plane) const { |
DCHECK(IsValidPlane(plane, format_)); |
+ DCHECK(IsMappable(storage_type_)); |
// Calculate an offset that is properly aligned for all planes. |
const gfx::Size alignment = CommonAlignment(format_); |
@@ -756,17 +806,26 @@ uint8* VideoFrame::visible_data(size_t plane) { |
static_cast<const VideoFrame*>(this)->visible_data(plane)); |
} |
-const gpu::MailboxHolder& VideoFrame::mailbox_holder(size_t texture) const { |
- DCHECK_EQ(format_, NATIVE_TEXTURE); |
- DCHECK_LT(texture, NumTextures(texture_format_)); |
- return mailbox_holders_[texture]; |
+const gpu::MailboxHolder& |
+VideoFrame::mailbox_holder(size_t texture_index) const { |
+#if defined(OS_LINUX) |
+ DCHECK(storage_type_ == STORAGE_TEXTURE || storage_type_ == STORAGE_DMABUFS); |
+#else |
+ DCHECK(storage_type_ == STORAGE_TEXTURE); |
+#endif |
+ DCHECK_LT(texture_index, NumPlanes(format_)); |
+ return mailbox_holders_[texture_index]; |
} |
base::SharedMemoryHandle VideoFrame::shared_memory_handle() const { |
+ DCHECK_EQ(storage_type_, STORAGE_SHMEM); |
+ DCHECK(shared_memory_handle_ != base::SharedMemory::NULLHandle()); |
return shared_memory_handle_; |
} |
size_t VideoFrame::shared_memory_offset() const { |
+ DCHECK_EQ(storage_type_, STORAGE_SHMEM); |
+ DCHECK(shared_memory_handle_ != base::SharedMemory::NULLHandle()); |
return shared_memory_offset_; |
} |
@@ -776,7 +835,11 @@ void VideoFrame::AddDestructionObserver(const base::Closure& callback) { |
} |
void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) { |
- DCHECK_EQ(format_, NATIVE_TEXTURE); |
+#if defined(OS_LINUX) |
+ DCHECK(storage_type_ == STORAGE_TEXTURE || storage_type_ == STORAGE_DMABUFS); |
+#else |
+ DCHECK(storage_type_ == STORAGE_TEXTURE); |
+#endif |
base::AutoLock locker(release_sync_point_lock_); |
// Must wait on the previous sync point before inserting a new sync point so |
// that |mailbox_holders_release_cb_| guarantees the previous sync point |
@@ -786,8 +849,9 @@ void VideoFrame::UpdateReleaseSyncPoint(SyncPointClient* client) { |
release_sync_point_ = client->InsertSyncPoint(); |
} |
-#if defined(OS_POSIX) |
+#if defined(OS_LINUX) |
int VideoFrame::dmabuf_fd(size_t plane) const { |
+ DCHECK_EQ(storage_type_, STORAGE_DMABUFS); |
return dmabuf_fds_[plane].get(); |
} |
#endif |