summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/host/ppapi_host.cc17
-rw-r--r--ppapi/host/ppapi_host.h8
-rw-r--r--ppapi/ppapi_proxy.gypi6
-rw-r--r--ppapi/ppapi_shared.gypi3
-rw-r--r--ppapi/proxy/media_stream_track_resource_base.cc73
-rw-r--r--ppapi/proxy/media_stream_track_resource_base.h63
-rw-r--r--ppapi/proxy/media_stream_video_track_resource.cc134
-rw-r--r--ppapi/proxy/media_stream_video_track_resource.h67
-rw-r--r--ppapi/proxy/plugin_var_tracker.cc23
-rw-r--r--ppapi/proxy/ppapi_messages.h13
-rw-r--r--ppapi/proxy/video_frame_resource.cc96
-rw-r--r--ppapi/proxy/video_frame_resource.h52
-rw-r--r--ppapi/shared_impl/media_stream_frame.h54
-rw-r--r--ppapi/shared_impl/media_stream_frame_buffer.cc78
-rw-r--r--ppapi/shared_impl/media_stream_frame_buffer.h93
-rw-r--r--ppapi/thunk/ppb_video_frame_api.h8
16 files changed, 785 insertions, 3 deletions
diff --git a/ppapi/host/ppapi_host.cc b/ppapi/host/ppapi_host.cc
index cbb989b..130bc87 100644
--- a/ppapi/host/ppapi_host.cc
+++ b/ppapi/host/ppapi_host.cc
@@ -12,11 +12,14 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/proxy/serialized_handle.h"
#include "ppapi/shared_impl/host_resource.h"
namespace ppapi {
namespace host {
+using proxy::SerializedHandle;
+
namespace {
// Put a cap on the maximum number of resources so we don't explode if the
@@ -99,11 +102,23 @@ void PpapiHost::SendReply(const ReplyMessageContext& context,
void PpapiHost::SendUnsolicitedReply(PP_Resource resource,
const IPC::Message& msg) {
- TRACE_EVENT2("ppapi proxy", "PpapiHost::SendUnsolicitedReply",
+ SendUnsolicitedReplyWithHandles(
+ resource, msg, std::vector<SerializedHandle>());
+}
+
+void PpapiHost::SendUnsolicitedReplyWithHandles(
+ PP_Resource resource,
+ const IPC::Message& msg,
+ const std::vector<SerializedHandle>& handles) {
+ TRACE_EVENT2("ppapi proxy", "PpapiHost::SendUnsolicitedReplyWithHandles",
"Class", IPC_MESSAGE_ID_CLASS(msg.type()),
"Line", IPC_MESSAGE_ID_LINE(msg.type()));
DCHECK(resource); // If this fails, host is probably pending.
proxy::ResourceMessageReplyParams params(resource, 0);
+ for (std::vector<SerializedHandle>::const_iterator it = handles.begin();
+ it != handles.end(); ++it) {
+ params.AppendHandle(*it);
+ }
Send(new PpapiPluginMsg_ResourceReply(params, msg));
}
diff --git a/ppapi/host/ppapi_host.h b/ppapi/host/ppapi_host.h
index 5a7c5c4..4280c3c 100644
--- a/ppapi/host/ppapi_host.h
+++ b/ppapi/host/ppapi_host.h
@@ -6,6 +6,7 @@
#define PPAPI_HOST_PPAPI_HOST_H_
#include <map>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h"
@@ -24,6 +25,7 @@ namespace ppapi {
namespace proxy {
class ResourceMessageCallParams;
class ResourceMessageReplyParams;
+class SerializedHandle;
}
namespace host {
@@ -61,6 +63,12 @@ class PPAPI_HOST_EXPORT PpapiHost : public IPC::Sender, public IPC::Listener {
// Sends the given unsolicited reply message to the plugin.
void SendUnsolicitedReply(PP_Resource resource, const IPC::Message& msg);
+ // Similar to |SendUnsolicitedReply()|, but also sends handles.
+ void SendUnsolicitedReplyWithHandles(
+ PP_Resource resource,
+ const IPC::Message& msg,
+ const std::vector<proxy::SerializedHandle>& handles);
+
// Create a ResourceHost with the given |nested_msg|.
scoped_ptr<ResourceHost> CreateResourceHost(
const proxy::ResourceMessageCallParams& params,
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 35186c8..6821ea4 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -80,6 +80,10 @@
'proxy/isolated_file_system_private_resource.cc',
'proxy/isolated_file_system_private_resource.h',
'proxy/locking_resource_releaser.h',
+ 'proxy/media_stream_track_resource_base.cc',
+ 'proxy/media_stream_track_resource_base.h',
+ 'proxy/media_stream_video_track_resource.cc',
+ 'proxy/media_stream_video_track_resource.h',
'proxy/net_address_resource.cc',
'proxy/net_address_resource.h',
'proxy/network_list_resource.cc',
@@ -211,6 +215,8 @@
'proxy/video_capture_resource.h',
'proxy/video_destination_resource.cc',
'proxy/video_destination_resource.h',
+ 'proxy/video_frame_resource.cc',
+ 'proxy/video_frame_resource.h',
'proxy/video_source_resource.cc',
'proxy/video_source_resource.h',
'proxy/websocket_resource.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 694a9ea..01390ae 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -37,6 +37,9 @@
'shared_impl/host_resource.h',
'shared_impl/id_assignment.cc',
'shared_impl/id_assignment.h',
+ 'shared_impl/media_stream_frame.h',
+ 'shared_impl/media_stream_frame_buffer.cc',
+ 'shared_impl/media_stream_frame_buffer.h',
'shared_impl/platform_file.cc',
'shared_impl/platform_file.h',
'shared_impl/ppapi_globals.cc',
diff --git a/ppapi/proxy/media_stream_track_resource_base.cc b/ppapi/proxy/media_stream_track_resource_base.cc
new file mode 100644
index 0000000..73aa470
--- /dev/null
+++ b/ppapi/proxy/media_stream_track_resource_base.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 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 "ppapi/proxy/media_stream_track_resource_base.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+namespace ppapi {
+namespace proxy {
+
+MediaStreamTrackResourceBase::MediaStreamTrackResourceBase(
+ Connection connection,
+ PP_Instance instance,
+ int pending_renderer_id,
+ const std::string& id)
+ : PluginResource(connection, instance),
+ frame_buffer_(this),
+ id_(id),
+ has_ended_(false) {
+ AttachToPendingHost(RENDERER, pending_renderer_id);
+}
+
+MediaStreamTrackResourceBase::~MediaStreamTrackResourceBase() {
+}
+
+void MediaStreamTrackResourceBase::SendEnqueueFrameMessageToHost(
+ int32_t index) {
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, frame_buffer()->number_of_frames());
+ Post(RENDERER, PpapiHostMsg_MediaStreamTrack_EnqueueFrame(index));
+}
+
+void MediaStreamTrackResourceBase::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(MediaStreamTrackResourceBase, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_MediaStreamTrack_InitFrames, OnPluginMsgInitFrames)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_MediaStreamTrack_EnqueueFrame, OnPluginMsgEnqueueFrame)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
+ PluginResource::OnReplyReceived(params, msg))
+ IPC_END_MESSAGE_MAP()
+}
+
+void MediaStreamTrackResourceBase::CloseInternal() {
+ if (!has_ended_) {
+ Post(RENDERER, PpapiHostMsg_MediaStreamTrack_Close());
+ has_ended_ = true;
+ }
+}
+
+void MediaStreamTrackResourceBase::OnPluginMsgInitFrames(
+ const ResourceMessageReplyParams& params,
+ int32_t number_of_frames,
+ int32_t frame_size) {
+ base::SharedMemoryHandle shm_handle = base::SharedMemory::NULLHandle();
+ params.TakeSharedMemoryHandleAtIndex(0, &shm_handle);
+ frame_buffer_.SetFrames(number_of_frames, frame_size,
+ scoped_ptr<base::SharedMemory>(new base::SharedMemory(shm_handle, true)),
+ false);
+}
+
+void MediaStreamTrackResourceBase::OnPluginMsgEnqueueFrame(
+ const ResourceMessageReplyParams& params,
+ int32_t index) {
+ frame_buffer_.EnqueueFrame(index);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/media_stream_track_resource_base.h b/ppapi/proxy/media_stream_track_resource_base.h
new file mode 100644
index 0000000..4a4aa3b
--- /dev/null
+++ b/ppapi/proxy/media_stream_track_resource_base.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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 PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_
+#define PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_
+
+#include "ppapi/proxy/plugin_resource.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/media_stream_frame_buffer.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT MediaStreamTrackResourceBase
+ : public PluginResource,
+ public MediaStreamFrameBuffer::Delegate {
+ protected:
+ MediaStreamTrackResourceBase(Connection connection,
+ PP_Instance instance,
+ int pending_renderer_id,
+ const std::string& id);
+
+ virtual ~MediaStreamTrackResourceBase();
+
+ std::string id() const { return id_; }
+
+ bool has_ended() const { return has_ended_; }
+
+ MediaStreamFrameBuffer* frame_buffer() { return &frame_buffer_; }
+
+ void CloseInternal();
+
+ // Sends a frame index to the corresponding PepperMediaStreamTrackHostBase
+ // via an IPC message. The host adds the frame index into its
+ // |frame_buffer_| for reading or writing. Also see |MediaStreamFrameBuffer|.
+ void SendEnqueueFrameMessageToHost(int32_t index);
+
+ // PluginResource overrides:
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
+ private:
+ // Message handlers:
+ void OnPluginMsgInitFrames(const ResourceMessageReplyParams& params,
+ int32_t number_of_frames,
+ int32_t frame_size);
+ void OnPluginMsgEnqueueFrame(const ResourceMessageReplyParams& params,
+ int32_t index);
+
+ MediaStreamFrameBuffer frame_buffer_;
+
+ std::string id_;
+
+ bool has_ended_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamTrackResourceBase);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_MEDIA_STREAM_TRACK_RESOURCE_BASE_H_
diff --git a/ppapi/proxy/media_stream_video_track_resource.cc b/ppapi/proxy/media_stream_video_track_resource.cc
new file mode 100644
index 0000000..0b76fb8
--- /dev/null
+++ b/ppapi/proxy/media_stream_video_track_resource.cc
@@ -0,0 +1,134 @@
+// Copyright 2014 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 "ppapi/proxy/media_stream_video_track_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/proxy/video_frame_resource.h"
+#include "ppapi/shared_impl/media_stream_frame.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+MediaStreamVideoTrackResource::MediaStreamVideoTrackResource(
+ Connection connection,
+ PP_Instance instance,
+ int pending_renderer_id,
+ const std::string& id)
+ : MediaStreamTrackResourceBase(
+ connection, instance, pending_renderer_id, id),
+ get_frame_output_(NULL) {
+}
+
+MediaStreamVideoTrackResource::~MediaStreamVideoTrackResource() {
+ Close();
+}
+
+thunk::PPB_MediaStreamVideoTrack_API*
+MediaStreamVideoTrackResource::AsPPB_MediaStreamVideoTrack_API() {
+ return this;
+}
+
+PP_Var MediaStreamVideoTrackResource::GetId() {
+ return StringVar::StringToPPVar(id());
+}
+
+PP_Bool MediaStreamVideoTrackResource::HasEnded() {
+ return PP_FromBool(has_ended());
+}
+
+int32_t MediaStreamVideoTrackResource::Configure(uint32_t max_buffered_frames) {
+ // TODO(penghuang): redesign and implement Configure() to support format,
+ // size, etc.
+ return PP_ERROR_NOTSUPPORTED;
+}
+
+int32_t MediaStreamVideoTrackResource::GetFrame(
+ PP_Resource* frame,
+ scoped_refptr<TrackedCallback> callback) {
+ if (has_ended())
+ return PP_ERROR_FAILED;
+
+ if (TrackedCallback::IsPending(get_frame_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ *frame = GetVideoFrame();
+ if (*frame)
+ return PP_OK;
+
+ get_frame_output_ = frame;
+ get_frame_callback_ = callback;
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t MediaStreamVideoTrackResource::RecycleFrame(PP_Resource frame) {
+ FrameMap::iterator it = frames_.find(frame);
+ if (it == frames_.end())
+ return PP_ERROR_BADRESOURCE;
+
+ scoped_refptr<VideoFrameResource> frame_resource = it->second;
+ frames_.erase(it);
+
+ if (has_ended())
+ return PP_OK;
+
+ DCHECK_GE(frame_resource->GetFrameBufferIndex(), 0);
+
+ SendEnqueueFrameMessageToHost(frame_resource->GetFrameBufferIndex());
+ frame_resource->Invalidate();
+ return PP_OK;
+}
+
+void MediaStreamVideoTrackResource::Close() {
+ if (has_ended())
+ return;
+
+ if (TrackedCallback::IsPending(get_frame_callback_)) {
+ *get_frame_output_ = 0;
+ get_frame_callback_->PostAbort();
+ get_frame_callback_ = NULL;
+ get_frame_output_ = 0;
+ }
+
+ ReleaseFrames();
+ MediaStreamTrackResourceBase::CloseInternal();
+}
+
+void MediaStreamVideoTrackResource::OnNewFrameEnqueued() {
+ if (TrackedCallback::IsPending(get_frame_callback_)) {
+ *get_frame_output_ = GetVideoFrame();
+ get_frame_output_ = NULL;
+ scoped_refptr<TrackedCallback> callback;
+ callback.swap(get_frame_callback_);
+ callback->Run(PP_OK);
+ }
+}
+
+PP_Resource MediaStreamVideoTrackResource::GetVideoFrame() {
+ int32_t index = frame_buffer()->DequeueFrame();
+ if (index < 0)
+ return 0;
+ MediaStreamFrame* frame = frame_buffer()->GetFramePointer(index);
+ scoped_refptr<VideoFrameResource> resource =
+ new VideoFrameResource(pp_instance(), index, frame);
+ // Add |pp_resource()| and |resource| into |frames_|.
+ // |frames_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the
+ // resource alive.
+ frames_.insert(FrameMap::value_type(resource->pp_resource(), resource));
+ return resource->GetReference();
+}
+
+void MediaStreamVideoTrackResource::ReleaseFrames() {
+ FrameMap::iterator it = frames_.begin();
+ while (it != frames_.end()) {
+ // Just invalidate and release VideoFrameResorce, but keep PP_Resource.
+ // So plugin can still use |RecycleFrame()|.
+ it->second->Invalidate();
+ it->second = NULL;
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/media_stream_video_track_resource.h b/ppapi/proxy/media_stream_video_track_resource.h
new file mode 100644
index 0000000..e402b0c
--- /dev/null
+++ b/ppapi/proxy/media_stream_video_track_resource.h
@@ -0,0 +1,67 @@
+// Copyright 2014 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 PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_
+#define PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/proxy/media_stream_track_resource_base.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/thunk/ppb_media_stream_video_track_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class VideoFrameResource;
+
+class PPAPI_PROXY_EXPORT MediaStreamVideoTrackResource
+ : public MediaStreamTrackResourceBase,
+ public thunk::PPB_MediaStreamVideoTrack_API {
+ public:
+ MediaStreamVideoTrackResource(Connection connection,
+ PP_Instance instance,
+ int pending_renderer_id,
+ const std::string& id);
+
+ virtual ~MediaStreamVideoTrackResource();
+
+ // Resource overrides:
+ virtual thunk::PPB_MediaStreamVideoTrack_API*
+ AsPPB_MediaStreamVideoTrack_API() OVERRIDE;
+
+ // PPB_MediaStreamVideoTrack_API overrides:
+ virtual PP_Var GetId() OVERRIDE;
+ virtual PP_Bool HasEnded() OVERRIDE;
+ virtual int32_t Configure(uint32_t max_buffered_frames) OVERRIDE;
+ virtual int32_t GetFrame(
+ PP_Resource* frame,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t RecycleFrame(PP_Resource frame) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ // MediaStreamFrameBuffer::Delegate overrides:
+ virtual void OnNewFrameEnqueued() OVERRIDE;
+
+ private:
+ PP_Resource GetVideoFrame();
+
+ void ReleaseFrames();
+
+ // Allocated frame resources by |GetFrame()|.
+ typedef std::map<PP_Resource, scoped_refptr<VideoFrameResource> > FrameMap;
+ FrameMap frames_;
+
+ PP_Resource* get_frame_output_;
+
+ scoped_refptr<TrackedCallback> get_frame_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrackResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_MEDIA_STREAM_VIDEO_TRACK_RESOURCE_H_
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
index a9cbd9c..e2db871 100644
--- a/ppapi/proxy/plugin_var_tracker.cc
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -10,6 +10,7 @@
#include "ppapi/c/dev/ppp_class_deprecated.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/proxy/file_system_resource.h"
+#include "ppapi/proxy/media_stream_video_track_resource.h"
#include "ppapi/proxy/plugin_array_buffer_var.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
@@ -172,10 +173,10 @@ PP_Var PluginVarTracker::MakeResourcePPVarFromMessage(
const IPC::Message& creation_message,
int pending_renderer_id,
int pending_browser_id) {
- DCHECK(pending_renderer_id);
- DCHECK(pending_browser_id);
switch (creation_message.type()) {
case PpapiPluginMsg_FileSystem_CreateFromPendingHost::ID: {
+ DCHECK(pending_renderer_id);
+ DCHECK(pending_browser_id);
PP_FileSystemType file_system_type;
if (!UnpackMessage<PpapiPluginMsg_FileSystem_CreateFromPendingHost>(
creation_message, &file_system_type)) {
@@ -194,6 +195,24 @@ PP_Var PluginVarTracker::MakeResourcePPVarFromMessage(
file_system_type))->GetReference();
return MakeResourcePPVar(pp_resource);
}
+ case PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost::ID: {
+ DCHECK(pending_renderer_id);
+ std::string track_id;
+ if (!UnpackMessage<
+ PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost>(
+ creation_message, &track_id)) {
+ NOTREACHED() <<
+ "Invalid message of type "
+ "PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost";
+ return PP_MakeNull();
+ }
+ PP_Resource pp_resource =
+ (new MediaStreamVideoTrackResource(GetConnectionForInstance(instance),
+ instance,
+ pending_renderer_id,
+ track_id))->GetReference();
+ return MakeResourcePPVar(pp_resource);
+ }
default: {
NOTREACHED() << "Creation message has unexpected type "
<< creation_message.type();
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 1318368..f1d0ead 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1412,6 +1412,19 @@ IPC_MESSAGE_CONTROL1(PpapiHostMsg_IsolatedFileSystem_BrowserOpen,
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply,
std::string /* fsid */)
+// MediaStream -----------------------------------------------------------------
+// Message for init frames. It also takes a shared memory handle.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost,
+ std::string /* track_id */)
+IPC_MESSAGE_CONTROL2(PpapiPluginMsg_MediaStreamTrack_InitFrames,
+ int32_t /* number_of_frames */,
+ int32_t /* frame_size */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamTrack_EnqueueFrame,
+ int32_t /* index */);
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_MediaStreamTrack_EnqueueFrame,
+ int32_t /* index */);
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_MediaStreamTrack_Close)
+
// NetworkMonitor.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_NetworkMonitor_Create)
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_NetworkMonitor_NetworkList,
diff --git a/ppapi/proxy/video_frame_resource.cc b/ppapi/proxy/video_frame_resource.cc
new file mode 100644
index 0000000..b314838
--- /dev/null
+++ b/ppapi/proxy/video_frame_resource.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 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 "ppapi/proxy/video_frame_resource.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+namespace proxy {
+
+VideoFrameResource::VideoFrameResource(PP_Instance instance,
+ int32_t index,
+ MediaStreamFrame* frame)
+ : Resource(OBJECT_IS_PROXY, instance),
+ index_(index),
+ frame_(frame) {
+ DCHECK_EQ(frame_->header.type, MediaStreamFrame::TYPE_VIDEO);
+}
+
+VideoFrameResource::~VideoFrameResource() {
+ CHECK(!frame_) << "An unused (or unrecycled) frame is destroyed.";
+}
+
+thunk::PPB_VideoFrame_API* VideoFrameResource::AsPPB_VideoFrame_API() {
+ return this;
+}
+
+PP_TimeDelta VideoFrameResource::GetTimestamp() {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return 0.0;
+ }
+ return frame_->video.timestamp;
+}
+
+void VideoFrameResource::SetTimestamp(PP_TimeDelta timestamp) {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return;
+ }
+ frame_->video.timestamp = timestamp;
+}
+
+PP_VideoFrame_Format VideoFrameResource::GetFormat() {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return PP_VIDEOFRAME_FORMAT_UNKNOWN;
+ }
+ return frame_->video.format;
+}
+
+PP_Bool VideoFrameResource::GetSize(PP_Size* size) {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return PP_FALSE;
+ }
+ *size = frame_->video.size;
+ return PP_TRUE;
+}
+
+void* VideoFrameResource::GetDataBuffer() {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return NULL;
+ }
+ return frame_->video.data;
+}
+
+uint32_t VideoFrameResource::GetDataBufferSize() {
+ if (!frame_) {
+ VLOG(1) << "Frame is invalid";
+ return 0;
+ }
+ return frame_->video.data_size;
+}
+
+MediaStreamFrame* VideoFrameResource::GetFrameBuffer() {
+ return frame_;
+}
+
+int32_t VideoFrameResource::GetFrameBufferIndex() {
+ return index_;
+}
+
+void VideoFrameResource::Invalidate() {
+ DCHECK(frame_);
+ DCHECK_GE(index_, 0);
+ frame_ = NULL;
+ index_ = -1;
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/video_frame_resource.h b/ppapi/proxy/video_frame_resource.h
new file mode 100644
index 0000000..ba92f4d
--- /dev/null
+++ b/ppapi/proxy/video_frame_resource.h
@@ -0,0 +1,52 @@
+// Copyright 2014 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 PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_
+#define PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/media_stream_frame.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/thunk/ppb_video_frame_api.h"
+
+namespace ppapi {
+namespace proxy {
+
+class PPAPI_PROXY_EXPORT VideoFrameResource : public Resource,
+ public thunk::PPB_VideoFrame_API {
+ public:
+ VideoFrameResource(PP_Instance instance,
+ int32_t index,
+ MediaStreamFrame* frame);
+
+ virtual ~VideoFrameResource();
+
+ // PluginResource overrides:
+ virtual thunk::PPB_VideoFrame_API* AsPPB_VideoFrame_API() OVERRIDE;
+
+ // PPB_VideoFrame_API overrides:
+ virtual PP_TimeDelta GetTimestamp() OVERRIDE;
+ virtual void SetTimestamp(PP_TimeDelta timestamp) OVERRIDE;
+ virtual PP_VideoFrame_Format GetFormat() OVERRIDE;
+ virtual PP_Bool GetSize(PP_Size* size) OVERRIDE;
+ virtual void* GetDataBuffer() OVERRIDE;
+ virtual uint32_t GetDataBufferSize() OVERRIDE;
+ virtual MediaStreamFrame* GetFrameBuffer();
+ virtual int32_t GetFrameBufferIndex();
+ virtual void Invalidate();
+
+ // Frame index
+ int32_t index_;
+
+ MediaStreamFrame* frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoFrameResource);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_VIDEO_FRAME_RESOURCE_H_
diff --git a/ppapi/shared_impl/media_stream_frame.h b/ppapi/shared_impl/media_stream_frame.h
new file mode 100644
index 0000000..b3ec8bb2
--- /dev/null
+++ b/ppapi/shared_impl/media_stream_frame.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 PPAPI_SHARED_IMPL_MEDIA_STREAM_FRAME_H_
+#define PPAPI_SHARED_IMPL_MEDIA_STREAM_FRAME_H_
+
+#include "ppapi/c/ppb_video_frame.h"
+
+namespace ppapi {
+
+union MediaStreamFrame {
+ enum Type {
+ TYPE_UNKNOWN = 0,
+ TYPE_AUDIO = 1,
+ TYPE_VIDEO = 2,
+ };
+
+ struct Header {
+ Type type;
+ uint32_t size;
+ };
+
+ struct Audio {
+ Header header;
+ // TODO(penghuang): implement the audio frame.
+ };
+
+ struct Video {
+ Header header;
+ PP_TimeDelta timestamp;
+ PP_VideoFrame_Format format;
+ PP_Size size;
+ uint32_t data_size;
+ // Uses 8 bytes to make sure the Video struct has consistent size between
+ // Nacl code and renderer code.
+ uint8_t data[8];
+ };
+
+ // Because these structs are written and read in shared memory, we need
+ // the size and alighment to be consistent between NaCl and its host trusted
+ // platform.
+ PP_COMPILE_ASSERT_SIZE_IN_BYTES(Header, 8);
+ PP_COMPILE_ASSERT_SIZE_IN_BYTES(Audio, 8);
+ PP_COMPILE_ASSERT_SIZE_IN_BYTES(Video, 40);
+
+ Header header;
+ Video video;
+ Audio audio;
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_MEDIA_STREAM_FRAME_H_
diff --git a/ppapi/shared_impl/media_stream_frame_buffer.cc b/ppapi/shared_impl/media_stream_frame_buffer.cc
new file mode 100644
index 0000000..6248830
--- /dev/null
+++ b/ppapi/shared_impl/media_stream_frame_buffer.cc
@@ -0,0 +1,78 @@
+// Copyright 2014 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 "ppapi/shared_impl/media_stream_frame_buffer.h"
+
+#include "base/logging.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace ppapi {
+
+MediaStreamFrameBuffer::Delegate::~Delegate() {}
+
+void MediaStreamFrameBuffer::Delegate::OnNewFrameEnqueued() {
+}
+
+MediaStreamFrameBuffer::MediaStreamFrameBuffer(Delegate* delegate)
+ : delegate_(delegate),
+ frame_size_(0),
+ number_of_frames_(0) {
+ DCHECK(delegate_);
+}
+
+MediaStreamFrameBuffer::~MediaStreamFrameBuffer() {
+}
+
+bool MediaStreamFrameBuffer::SetFrames(
+ int32_t number_of_frames,
+ int32_t frame_size,
+ scoped_ptr<base::SharedMemory> shm,
+ bool enqueue_all_frames) {
+ DCHECK(shm);
+ DCHECK(!shm_);
+ DCHECK_GT(number_of_frames, 0);
+ DCHECK_GT(frame_size, static_cast<int32_t>(sizeof(MediaStreamFrame::Header)));
+ DCHECK_EQ(frame_size & 0x3, 0);
+
+ number_of_frames_ = number_of_frames;
+ frame_size_ = frame_size;
+
+ int32_t size = number_of_frames_ * frame_size;
+ shm_ = shm.Pass();
+ if (!shm_->Map(size))
+ return false;
+
+ uint8_t* p = reinterpret_cast<uint8_t*>(shm_->memory());
+ for (int32_t i = 0; i < number_of_frames; ++i) {
+ if (enqueue_all_frames)
+ frame_queue_.push_back(i);
+ frames_.push_back(reinterpret_cast<MediaStreamFrame*>(p));
+ p += frame_size_;
+ }
+ return true;
+}
+
+int32_t MediaStreamFrameBuffer::DequeueFrame() {
+ if (frame_queue_.empty())
+ return PP_ERROR_FAILED;
+ int32_t frame = frame_queue_.front();
+ frame_queue_.pop_front();
+ return frame;
+}
+
+void MediaStreamFrameBuffer::EnqueueFrame(int32_t index) {
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, number_of_frames_);
+ frame_queue_.push_back(index);
+ delegate_->OnNewFrameEnqueued();
+}
+
+MediaStreamFrame* MediaStreamFrameBuffer::GetFramePointer(
+ int32_t index) {
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, number_of_frames_);
+ return frames_[index];
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/media_stream_frame_buffer.h b/ppapi/shared_impl/media_stream_frame_buffer.h
new file mode 100644
index 0000000..e950846
--- /dev/null
+++ b/ppapi/shared_impl/media_stream_frame_buffer.h
@@ -0,0 +1,93 @@
+// Copyright 2014 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 PPAPI_SHARED_IMPL_MEDIA_STREAM_FRAME_BUFFER_H_
+#define PPAPI_SHARED_IMPL_MEDIA_STREAM_FRAME_BUFFER_H_
+
+#include <deque>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "ppapi/shared_impl/media_stream_frame.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+
+namespace ppapi {
+
+// This class is used by both read side and write side of a MediaStreamTrack to
+// maintain a queue of frames for reading or writing.
+//
+// An example:
+// 1. The writer calls the writer's |frame_buffer_.Dequeue()| to get a free
+// frame.
+// 2. The writer fills data into the frame.
+// 3. The writer sends the frame index to the reader via an IPC message.
+// 4. The reader receives the frame index and calls the reader's
+// |frame_buffer.Enqueue()| to put the frame into the read's queue.
+// 5. The reader calls reader's |frame_buffer_.Dequeue()| to get a received
+// frame.
+// 6. When the frame from the step 5 is consumed, the reader sends the frame
+// index back to writer via an IPC message.
+// 7. The writer receives the frame index and puts it back to the writer's free
+// frame queue by calling the writer's |frame_buffer_.Enqueue()|.
+// 8. Go back to step 1.
+class PPAPI_SHARED_EXPORT MediaStreamFrameBuffer {
+ public:
+ class PPAPI_SHARED_EXPORT Delegate {
+ public:
+ virtual ~Delegate();
+ // It is called when a new frame is enqueued.
+ virtual void OnNewFrameEnqueued();
+ };
+
+ // MediaStreamFrameBuffer doesn't own |delegate|, the caller should keep
+ // it alive during the MediaStreamFrameBuffer's lifecycle.
+ explicit MediaStreamFrameBuffer(Delegate* delegate);
+
+ ~MediaStreamFrameBuffer();
+
+ int32_t number_of_frames() const { return number_of_frames_; }
+
+ int32_t frame_size() const { return frame_size_; }
+
+ // Initializes shared memory for frames transmission.
+ bool SetFrames(int32_t number_of_frames,
+ int32_t frame_size,
+ scoped_ptr<base::SharedMemory> shm,
+ bool enqueue_all_frames);
+
+ // Dequeues a frame from |frame_queue_|.
+ int32_t DequeueFrame();
+
+ // Puts a frame into |frame_queue_|.
+ void EnqueueFrame(int32_t index);
+
+ // Gets the frame address for the given frame index.
+ MediaStreamFrame* GetFramePointer(int32_t index);
+
+ private:
+ Delegate* delegate_;
+
+ // A queue of frame indexes.
+ std::deque<int32_t> frame_queue_;
+
+ // A vector of frame pointers. It is used for index to pointer converting.
+ std::vector<MediaStreamFrame*> frames_;
+
+ // The frame size in bytes.
+ int32_t frame_size_;
+
+ // The number of frames in the shared memory.
+ int32_t number_of_frames_;
+
+ // A memory block shared between renderer process and plugin process.
+ scoped_ptr<base::SharedMemory> shm_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamFrameBuffer);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHAERD_IMPL_MEDIA_STREAM_FRAME_BUFFER_H_
diff --git a/ppapi/thunk/ppb_video_frame_api.h b/ppapi/thunk/ppb_video_frame_api.h
index 50f2247..9a08882 100644
--- a/ppapi/thunk/ppb_video_frame_api.h
+++ b/ppapi/thunk/ppb_video_frame_api.h
@@ -9,6 +9,9 @@
#include "ppapi/thunk/ppapi_thunk_export.h"
namespace ppapi {
+
+union MediaStreamFrame;
+
namespace thunk {
class PPAPI_THUNK_EXPORT PPB_VideoFrame_API {
@@ -20,6 +23,11 @@ class PPAPI_THUNK_EXPORT PPB_VideoFrame_API {
virtual PP_Bool GetSize(PP_Size* size) = 0;
virtual void* GetDataBuffer() = 0;
virtual uint32_t GetDataBufferSize() = 0;
+
+ // Private APIs:
+ virtual MediaStreamFrame* GetFrameBuffer() = 0;
+ virtual int32_t GetFrameBufferIndex() = 0;
+ virtual void Invalidate() = 0;
};
} // namespace thunk