summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-25 22:31:29 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-25 22:31:29 +0000
commite56f88c794704ff587fb7a0a3fdf8f7b85489cd3 (patch)
tree72854709cc97c58a8540c609776548818c78ea42 /media
parentd30268aa9bd90bd8dd885124cd1eb8f45053c08b (diff)
downloadchromium_src-e56f88c794704ff587fb7a0a3fdf8f7b85489cd3.zip
chromium_src-e56f88c794704ff587fb7a0a3fdf8f7b85489cd3.tar.gz
chromium_src-e56f88c794704ff587fb7a0a3fdf8f7b85489cd3.tar.bz2
Send hardware video frames with mailboxes.
Change media::VideoFrame from holding a raw texture id to instead hold a gpu::Mailbox. The hardware video decoders produce a mailbox on their context from the texture id before putting it in the VideoFrame, and consume the mailbox again when they receive the texture id back. In the compositor, we hold onto the VideoFrame::MailboxHolder as long as the mailboxed texture is in use in the compositor (or its parent). This keeps the video decoders from writing to the texture id, as they register a callback in the VideoFrame to be called when it is destroyed. BUG=179729 Review URL: https://chromiumcodereview.appspot.com/14199002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208568 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/DEPS1
-rw-r--r--media/base/video_frame.cc24
-rw-r--r--media/base/video_frame.h45
-rw-r--r--media/base/video_frame_unittest.cc213
-rw-r--r--media/filters/gpu_video_decoder.cc32
-rw-r--r--media/filters/gpu_video_decoder.h11
-rw-r--r--media/media.gyp2
-rw-r--r--media/video/picture.cc10
-rw-r--r--media/video/picture.h10
9 files changed, 325 insertions, 23 deletions
diff --git a/media/DEPS b/media/DEPS
index 9a92ab7..7bb03fc 100644
--- a/media/DEPS
+++ b/media/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+gpu",
"+jni",
"+third_party/ffmpeg",
"+third_party/libvpx",
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 046967c..db82649 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -64,7 +64,7 @@ bool VideoFrame::IsValidConfig(VideoFrame::Format format,
// static
scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
- uint32 texture_id,
+ const scoped_refptr<MailboxHolder>& mailbox_holder,
uint32 texture_target,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
@@ -74,10 +74,11 @@ scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture(
const base::Closure& no_longer_needed_cb) {
scoped_refptr<VideoFrame> frame(new VideoFrame(
NATIVE_TEXTURE, coded_size, visible_rect, natural_size, timestamp));
- frame->texture_id_ = texture_id;
+ frame->texture_mailbox_holder_ = mailbox_holder;
frame->texture_target_ = texture_target;
frame->read_pixels_cb_ = read_pixels_cb;
frame->no_longer_needed_cb_ = no_longer_needed_cb;
+
return frame;
}
@@ -266,7 +267,6 @@ VideoFrame::VideoFrame(VideoFrame::Format format,
coded_size_(coded_size),
visible_rect_(visible_rect),
natural_size_(natural_size),
- texture_id_(0),
texture_target_(0),
timestamp_(timestamp) {
memset(&strides_, 0, sizeof(strides_));
@@ -340,9 +340,10 @@ uint8* VideoFrame::data(size_t plane) const {
return data_[plane];
}
-uint32 VideoFrame::texture_id() const {
+const scoped_refptr<VideoFrame::MailboxHolder>& VideoFrame::texture_mailbox()
+ const {
DCHECK_EQ(format_, NATIVE_TEXTURE);
- return texture_id_;
+ return texture_mailbox_holder_;
}
uint32 VideoFrame::texture_target() const {
@@ -366,4 +367,17 @@ void VideoFrame::HashFrameForTesting(base::MD5Context* context) {
}
}
+VideoFrame::MailboxHolder::MailboxHolder(
+ const gpu::Mailbox& mailbox,
+ unsigned sync_point,
+ const TextureNoLongerNeededCallback& release_callback)
+ : mailbox_(mailbox),
+ sync_point_(sync_point),
+ release_callback_(release_callback) {}
+
+VideoFrame::MailboxHolder::~MailboxHolder() {
+ if (!release_callback_.is_null())
+ release_callback_.Run(sync_point_);
+}
+
} // namespace media
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 6cd5a0f..bfde2ef 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/md5.h"
+#include "gpu/command_buffer/common/mailbox.h"
#include "media/base/buffers.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -51,6 +52,37 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
YV12A = 14, // 20bpp YUVA planar 1x1 Y, 2x2 VU, 1x1 A samples.
};
+ // This class calls the TextureNoLongerNeededCallback when the last reference
+ // on the class is destroyed. The VideoFrame holds a reference to the mailbox
+ // but anyone else who queries the mailbox should also hold a reference while
+ // it is uses the mailbox, to ensure it remains valid. When finished with the
+ // mailbox, call Return() with a new sync point, to ensure the mailbox remains
+ // valid for the issued commands.
+ class MEDIA_EXPORT MailboxHolder
+ : public base::RefCountedThreadSafe<MailboxHolder> {
+ public:
+ typedef base::Callback<void(uint32 sync_point)>
+ TextureNoLongerNeededCallback;
+
+ MailboxHolder(const gpu::Mailbox& mailbox,
+ unsigned sync_point,
+ const TextureNoLongerNeededCallback& release_callback);
+
+ const gpu::Mailbox& mailbox() const { return mailbox_; }
+ unsigned sync_point() const { return sync_point_; }
+
+ void Return(unsigned sync_point) { sync_point_ = sync_point; }
+
+ private:
+ friend class base::RefCountedThreadSafe<MailboxHolder>;
+ ~MailboxHolder();
+
+ gpu::Mailbox mailbox_;
+ unsigned sync_point_;
+ TextureNoLongerNeededCallback release_callback_;
+ };
+
+
// Creates a new frame in system memory with given parameters. Buffers for
// the frame are allocated but not initialized.
// |coded_size| is the width and height of the frame data in pixels.
@@ -87,7 +119,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// |read_pixels_cb| may be used to do (slow!) readbacks from the
// texture to main memory.
static scoped_refptr<VideoFrame> WrapNativeTexture(
- uint32 texture_id,
+ const scoped_refptr<MailboxHolder>& mailbox_holder,
uint32 texture_target,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
@@ -158,9 +190,10 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// VideoFrame object and must not be freed by the caller.
uint8* data(size_t plane) const;
- // Returns the ID of the native texture wrapped by this frame. Only valid to
- // call if this is a NATIVE_TEXTURE frame.
- uint32 texture_id() const;
+ // Returns the mailbox of the native texture wrapped by this frame. Only
+ // valid to call if this is a NATIVE_TEXTURE frame. Before using the
+ // mailbox, the caller must wait for the included sync point.
+ const scoped_refptr<MailboxHolder>& texture_mailbox() const;
// Returns the texture target. Only valid for NATIVE_TEXTURE frames.
uint32 texture_target() const;
@@ -217,8 +250,8 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
// Array of data pointers to each plane.
uint8* data_[kMaxPlanes];
- // Native texture ID, if this is a NATIVE_TEXTURE frame.
- uint32 texture_id_;
+ // Native texture mailbox, if this is a NATIVE_TEXTURE frame.
+ scoped_refptr<MailboxHolder> texture_mailbox_holder_;
uint32 texture_target_;
ReadPixelsCB read_pixels_cb_;
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
index ce4869c..b88d20c 100644
--- a/media/base/video_frame_unittest.cc
+++ b/media/base/video_frame_unittest.cc
@@ -4,6 +4,8 @@
#include "media/base/video_frame.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/format_macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/stringprintf.h"
@@ -209,4 +211,215 @@ TEST(VideoFrame, CheckFrameExtents) {
VideoFrame::YV16, 3, 1, "9bb99ac3ff350644ebff4d28dc01b461");
}
+static void TextureCallback(uint32* called_sync_point, uint32 sync_point) {
+ *called_sync_point = sync_point;
+}
+
+// Verify the TextureNoLongerNeededCallback is called when VideoFrame is
+// destroyed with the original sync point.
+TEST(VideoFrame, TextureNoLongerNeededCallbackIsCalled) {
+ uint32 sync_point = 7;
+ uint32 called_sync_point = 0;
+
+ {
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture(
+ new VideoFrame::MailboxHolder(
+ gpu::Mailbox(),
+ sync_point,
+ base::Bind(&TextureCallback, &called_sync_point)),
+ 5, // texture_target
+ gfx::Size(10, 10), // coded_size
+ gfx::Rect(10, 10), // visible_rect
+ gfx::Size(10, 10), // natural_size
+ base::TimeDelta(), // timestamp
+ base::Callback<void(const SkBitmap&)>(), // read_pixels_cb
+ base::Closure()); // no_longer_needed_cb
+
+ EXPECT_EQ(0u, called_sync_point);
+ }
+ EXPECT_EQ(sync_point, called_sync_point);
+}
+
+// Verify the TextureNoLongerNeededCallback is called when VideoFrame is
+// destroyed with the new sync point, when the mailbox is taken by a caller.
+TEST(VideoFrame, TextureNoLongerNeededCallbackAfterTakingAndReleasingMailbox) {
+ uint32 called_sync_point = 0;
+
+ gpu::Mailbox mailbox;
+ mailbox.name[0] = 50;
+ uint32 sync_point = 7;
+ uint32 target = 9;
+
+ {
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture(
+ new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ base::Bind(&TextureCallback, &called_sync_point)),
+ target,
+ gfx::Size(10, 10), // coded_size
+ gfx::Rect(10, 10), // visible_rect
+ gfx::Size(10, 10), // natural_size
+ base::TimeDelta(), // timestamp
+ base::Callback<void(const SkBitmap&)>(), // read_pixels_cb
+ base::Closure()); // no_longer_needed_cb
+
+ {
+ scoped_refptr<VideoFrame::MailboxHolder> mailbox_holder =
+ frame->texture_mailbox();
+
+ EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox().name[0]);
+ EXPECT_EQ(sync_point, mailbox_holder->sync_point());
+ EXPECT_EQ(target, frame->texture_target());
+
+ // Misuse the callback.
+ sync_point = 12;
+ mailbox_holder->Return(sync_point);
+ EXPECT_EQ(0u, called_sync_point);
+
+ // Finish using the mailbox_holder and drop our reference.
+ sync_point = 10;
+ mailbox_holder->Return(sync_point);
+ }
+ EXPECT_EQ(0u, called_sync_point);
+ }
+ EXPECT_EQ(sync_point, called_sync_point);
+}
+
+// If a caller has taken ownership of the texture mailbox, it should
+// not be released when the VideoFrame is destroyed, but should when
+// the TextureNoLongerNeededCallback is called.
+TEST(VideoFrame,
+ TextureNoLongerNeededCallbackAfterTakingMailboxWithDestroyedFrame) {
+ uint32 called_sync_point = 0;
+
+ gpu::Mailbox mailbox;
+ mailbox.name[0] = 50;
+ uint32 sync_point = 7;
+ uint32 target = 9;
+
+ {
+ scoped_refptr<VideoFrame::MailboxHolder> mailbox_holder;
+
+ {
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture(
+ new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ base::Bind(&TextureCallback, &called_sync_point)),
+ target,
+ gfx::Size(10, 10), // coded_size
+ gfx::Rect(10, 10), // visible_rect
+ gfx::Size(10, 10), // natural_size
+ base::TimeDelta(), // timestamp
+ base::Callback<void(const SkBitmap&)>(), // read_pixels_cb
+ base::Closure()); // no_longer_needed_cb
+
+ mailbox_holder = frame->texture_mailbox();
+
+ EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox().name[0]);
+ EXPECT_EQ(sync_point, mailbox_holder->sync_point());
+ EXPECT_EQ(target, frame->texture_target());
+
+ // Keep a ref on the mailbox_holder after the VideoFrame is dropped.
+ }
+ EXPECT_EQ(0u, called_sync_point);
+
+ // Misuse the callback.
+ sync_point = 12;
+ mailbox_holder->Return(sync_point);
+ EXPECT_EQ(0u, called_sync_point);
+
+ // Finish using the mailbox_holder and drop our ref.
+ sync_point = 10;
+ mailbox_holder->Return(sync_point);
+ }
+ EXPECT_EQ(sync_point, called_sync_point);
+}
+
+// If a caller has taken ownership of the texture mailbox, but does
+// not call the callback, it should still happen with the original
+// sync point.
+TEST(VideoFrame,
+ TextureNoLongerNeededCallbackWhenNotCallingAndFrameDestroyed) {
+ uint32 called_sync_point = 0;
+
+ gpu::Mailbox mailbox;
+ mailbox.name[0] = 50;
+ uint32 sync_point = 7;
+ uint32 target = 9;
+
+ {
+ scoped_refptr<VideoFrame::MailboxHolder> mailbox_holder;
+
+ {
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture(
+ new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ base::Bind(&TextureCallback, &called_sync_point)),
+ target,
+ gfx::Size(10, 10), // coded_size
+ gfx::Rect(10, 10), // visible_rect
+ gfx::Size(10, 10), // natural_size
+ base::TimeDelta(), // timestamp
+ base::Callback<void(const SkBitmap&)>(), // read_pixels_cb
+ base::Closure()); // no_longer_needed_cb
+
+ mailbox_holder = frame->texture_mailbox();
+
+ EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox().name[0]);
+ EXPECT_EQ(sync_point, mailbox_holder->sync_point());
+ EXPECT_EQ(target, frame->texture_target());
+
+ // Destroy the video frame.
+ }
+ EXPECT_EQ(0u, called_sync_point);
+
+ // Drop the reference on the mailbox without using it at all.
+ }
+ EXPECT_EQ(sync_point, called_sync_point);
+}
+
+// If a caller has taken ownership of the texture mailbox, but does
+// not call the callback, it should still happen with the original
+// sync point.
+TEST(VideoFrame,
+ TextureNoLongerNeededCallbackAfterTakingMailboxAndNotCalling) {
+ uint32 called_sync_point = 0;
+
+ gpu::Mailbox mailbox;
+ mailbox.name[0] = 50;
+ uint32 sync_point = 7;
+ uint32 target = 9;
+
+ {
+ scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture(
+ new VideoFrame::MailboxHolder(
+ mailbox,
+ sync_point,
+ base::Bind(&TextureCallback, &called_sync_point)),
+ target,
+ gfx::Size(10, 10), // coded_size
+ gfx::Rect(10, 10), // visible_rect
+ gfx::Size(10, 10), // natural_size
+ base::TimeDelta(), // timestamp
+ base::Callback<void(const SkBitmap&)>(), // read_pixels_cb
+ base::Closure()); // no_longer_needed_cb
+
+ scoped_refptr<VideoFrame::MailboxHolder> mailbox_holder =
+ frame->texture_mailbox();
+
+ EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox().name[0]);
+ EXPECT_EQ(sync_point, mailbox_holder->sync_point());
+ EXPECT_EQ(target, frame->texture_target());
+
+ EXPECT_EQ(0u, called_sync_point);
+
+ // Don't use the mailbox at all and drop our ref on it.
+ }
+ // The VideoFrame is destroyed, it should call the callback.
+ EXPECT_EQ(sync_point, called_sync_point);
+}
+
} // namespace media
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index 31c550b3..3679a5a 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -495,13 +495,20 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
std::vector<uint32> texture_ids;
+ std::vector<gpu::Mailbox> texture_mailboxes;
decoder_texture_target_ = texture_target;
- if (!factories_->CreateTextures(
- count, size, &texture_ids, decoder_texture_target_)) {
+ // Discards the sync point returned here since PictureReady will imply that
+ // the produce has already happened, and the texture is ready for use.
+ if (!factories_->CreateTextures(count,
+ size,
+ &texture_ids,
+ &texture_mailboxes,
+ decoder_texture_target_)) {
NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
}
DCHECK_EQ(count, texture_ids.size());
+ DCHECK_EQ(count, texture_mailboxes.size());
if (!vda_)
return;
@@ -509,7 +516,7 @@ void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
std::vector<PictureBuffer> picture_buffers;
for (size_t i = 0; i < texture_ids.size(); ++i) {
picture_buffers.push_back(PictureBuffer(
- next_picture_buffer_id_++, size, texture_ids[i]));
+ next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i]));
bool inserted = assigned_picture_buffers_.insert(std::make_pair(
picture_buffers.back().id(), picture_buffers.back())).second;
DCHECK(inserted);
@@ -570,16 +577,22 @@ void GpuVideoDecoder::PictureReady(const media::Picture& picture) {
GetBufferData(picture.bitstream_buffer_id(), &timestamp, &visible_rect,
&natural_size);
DCHECK(decoder_texture_target_);
+
scoped_refptr<VideoFrame> frame(
VideoFrame::WrapNativeTexture(
- pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect,
+ new VideoFrame::MailboxHolder(
+ pb.texture_mailbox(),
+ 0, // sync_point
+ BindToCurrentLoop(base::Bind(
+ &GpuVideoDecoder::ReusePictureBuffer, weak_this_,
+ picture.picture_buffer_id()))),
+ decoder_texture_target_,
+ pb.size(), visible_rect,
natural_size, timestamp,
base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(),
decoder_texture_target_,
gfx::Size(visible_rect.width(), visible_rect.height())),
- BindToCurrentLoop(base::Bind(
- &GpuVideoDecoder::ReusePictureBuffer, weak_this_,
- picture.picture_buffer_id()))));
+ base::Closure()));
CHECK_GT(available_pictures_, 0);
--available_pictures_;
bool inserted =
@@ -610,7 +623,8 @@ void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery(
ready_video_frames_.pop_front();
}
-void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
+void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id,
+ uint32 sync_point) {
DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
if (!vda_)
@@ -633,6 +647,8 @@ void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
return;
}
+ factories_->WaitSyncPoint(sync_point);
+
++available_pictures_;
vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h
index 40311a9..6fd0a3a 100644
--- a/media/filters/gpu_video_decoder.h
+++ b/media/filters/gpu_video_decoder.h
@@ -47,11 +47,14 @@ class MEDIA_EXPORT GpuVideoDecoder
VideoCodecProfile, VideoDecodeAccelerator::Client*) = 0;
// Allocate & delete native textures.
- virtual bool CreateTextures(int32 count, const gfx::Size& size,
- std::vector<uint32>* texture_ids,
- uint32 texture_target) = 0;
+ virtual uint32 CreateTextures(int32 count, const gfx::Size& size,
+ std::vector<uint32>* texture_ids,
+ std::vector<gpu::Mailbox>* texture_mailboxes,
+ uint32 texture_target) = 0;
virtual void DeleteTexture(uint32 texture_id) = 0;
+ virtual void WaitSyncPoint(uint32 sync_point) = 0;
+
// Read pixels from a native texture and store into |pixels| as RGBA.
virtual void ReadPixels(uint32 texture_id, uint32 texture_target,
const gfx::Size& size, const SkBitmap& pixels) = 0;
@@ -132,7 +135,7 @@ class MEDIA_EXPORT GpuVideoDecoder
const scoped_refptr<VideoFrame>& frame);
// Indicate the picture buffer can be reused by the decoder.
- void ReusePictureBuffer(int64 picture_buffer_id);
+ void ReusePictureBuffer(int64 picture_buffer_id, uint32 sync_point);
void RecordBufferData(
const BitstreamBuffer& bitstream_buffer, const DecoderBuffer& buffer);
diff --git a/media/media.gyp b/media/media.gyp
index d017913..7627a9a 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -455,6 +455,7 @@
['OS!="ios"', {
'dependencies': [
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../gpu/gpu.gyp:command_buffer_common',
'shared_memory_support',
],
}],
@@ -986,6 +987,7 @@
}],
['OS!="ios"', {
'dependencies': [
+ '../gpu/gpu.gyp:command_buffer_common',
'shared_memory_support',
],
}],
diff --git a/media/video/picture.cc b/media/video/picture.cc
index 54e4a23..7b32563 100644
--- a/media/video/picture.cc
+++ b/media/video/picture.cc
@@ -12,6 +12,16 @@ PictureBuffer::PictureBuffer(int32 id, gfx::Size size, uint32 texture_id)
texture_id_(texture_id) {
}
+PictureBuffer::PictureBuffer(int32 id,
+ gfx::Size size,
+ uint32 texture_id,
+ const gpu::Mailbox& texture_mailbox)
+ : id_(id),
+ size_(size),
+ texture_id_(texture_id),
+ texture_mailbox_(texture_mailbox) {
+}
+
Picture::Picture(int32 picture_buffer_id, int32 bitstream_buffer_id)
: picture_buffer_id_(picture_buffer_id),
bitstream_buffer_id_(bitstream_buffer_id) {
diff --git a/media/video/picture.h b/media/video/picture.h
index 5d3b775..d5be227 100644
--- a/media/video/picture.h
+++ b/media/video/picture.h
@@ -6,6 +6,7 @@
#define MEDIA_VIDEO_PICTURE_H_
#include "base/basictypes.h"
+#include "gpu/command_buffer/common/mailbox.h"
#include "media/base/media_export.h"
#include "ui/gfx/size.h"
@@ -16,6 +17,10 @@ namespace media {
class MEDIA_EXPORT PictureBuffer {
public:
PictureBuffer(int32 id, gfx::Size size, uint32 texture_id);
+ PictureBuffer(int32 id,
+ gfx::Size size,
+ uint32 texture_id,
+ const gpu::Mailbox& texture_mailbox);
// Returns the client-specified id of the buffer.
int32 id() const {
@@ -34,10 +39,15 @@ class MEDIA_EXPORT PictureBuffer {
return texture_id_;
}
+ const gpu::Mailbox& texture_mailbox() const {
+ return texture_mailbox_;
+ }
+
private:
int32 id_;
gfx::Size size_;
uint32 texture_id_;
+ gpu::Mailbox texture_mailbox_;
};
// A decoded picture frame.