diff options
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/host/ppapi_host.cc | 17 | ||||
-rw-r--r-- | ppapi/host/ppapi_host.h | 8 | ||||
-rw-r--r-- | ppapi/ppapi_proxy.gypi | 6 | ||||
-rw-r--r-- | ppapi/ppapi_shared.gypi | 3 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_track_resource_base.cc | 73 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_track_resource_base.h | 63 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_video_track_resource.cc | 134 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_video_track_resource.h | 67 | ||||
-rw-r--r-- | ppapi/proxy/plugin_var_tracker.cc | 23 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 13 | ||||
-rw-r--r-- | ppapi/proxy/video_frame_resource.cc | 96 | ||||
-rw-r--r-- | ppapi/proxy/video_frame_resource.h | 52 | ||||
-rw-r--r-- | ppapi/shared_impl/media_stream_frame.h | 54 | ||||
-rw-r--r-- | ppapi/shared_impl/media_stream_frame_buffer.cc | 78 | ||||
-rw-r--r-- | ppapi/shared_impl/media_stream_frame_buffer.h | 93 | ||||
-rw-r--r-- | ppapi/thunk/ppb_video_frame_api.h | 8 |
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 |