diff options
Diffstat (limited to 'chromium/ppapi/proxy/media_stream_video_track_resource.cc')
-rw-r--r-- | chromium/ppapi/proxy/media_stream_video_track_resource.cc | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/chromium/ppapi/proxy/media_stream_video_track_resource.cc b/chromium/ppapi/proxy/media_stream_video_track_resource.cc new file mode 100644 index 00000000000..2942ff574fb --- /dev/null +++ b/chromium/ppapi/proxy/media_stream_video_track_resource.cc @@ -0,0 +1,225 @@ +// 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/ppapi_messages.h" +#include "ppapi/proxy/video_frame_resource.h" +#include "ppapi/shared_impl/media_stream_buffer.h" +#include "ppapi/shared_impl/media_stream_video_track_shared.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( + Connection connection, + PP_Instance instance) + : MediaStreamTrackResourceBase(connection, instance), + get_frame_output_(NULL) { + SendCreate(RENDERER, PpapiHostMsg_MediaStreamVideoTrack_Create()); +} + +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( + const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) { + if (has_ended()) + return PP_ERROR_FAILED; + + if (TrackedCallback::IsPending(configure_callback_) || + TrackedCallback::IsPending(get_frame_callback_)) { + return PP_ERROR_INPROGRESS; + } + + // Do not support configure, if frames are hold by plugin. + if (!frames_.empty()) + return PP_ERROR_INPROGRESS; + + MediaStreamVideoTrackShared::Attributes attributes; + int i = 0; + for (;attrib_list[i] != PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE; i += 2) { + switch (attrib_list[i]) { + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES: + attributes.buffers = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH: + attributes.width = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT: + attributes.height = attrib_list[i + 1]; + break; + case PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT: + attributes.format = static_cast<PP_VideoFrame_Format>(attrib_list[i + 1]); + break; + default: + return PP_ERROR_BADARGUMENT; + } + } + + if (!MediaStreamVideoTrackShared::VerifyAttributes(attributes)) + return PP_ERROR_BADARGUMENT; + + configure_callback_ = callback; + Call<PpapiPluginMsg_MediaStreamVideoTrack_ConfigureReply>( + RENDERER, + PpapiHostMsg_MediaStreamVideoTrack_Configure(attributes), + base::Bind(&MediaStreamVideoTrackResource::OnPluginMsgConfigureReply, + base::Unretained(this)), + callback); + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamVideoTrackResource::GetAttrib( + PP_MediaStreamVideoTrack_Attrib attrib, + int32_t* value) { + // TODO(penghuang): implement this function. + 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(configure_callback_) || + 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->GetBufferIndex(), 0); + + SendEnqueueBufferMessageToHost(frame_resource->GetBufferIndex()); + 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(); +} + +int32_t MediaStreamVideoTrackResource::GetEmptyFrame( + PP_Resource* frame, scoped_refptr<TrackedCallback> callback) { + return GetFrame(frame, callback); +} + +int32_t MediaStreamVideoTrackResource::PutFrame(PP_Resource frame) { + // TODO(ronghuawu): Consider to rename RecycleFrame to PutFrame and use + // one set of GetFrame and PutFrame for both input and output. + return RecycleFrame(frame); +} + +void MediaStreamVideoTrackResource::OnNewBufferEnqueued() { + if (!TrackedCallback::IsPending(get_frame_callback_)) + return; + + *get_frame_output_ = GetVideoFrame(); + int32_t result = *get_frame_output_ ? PP_OK : PP_ERROR_FAILED; + get_frame_output_ = NULL; + scoped_refptr<TrackedCallback> callback; + callback.swap(get_frame_callback_); + callback->Run(result); +} + +PP_Resource MediaStreamVideoTrackResource::GetVideoFrame() { + int32_t index = buffer_manager()->DequeueBuffer(); + if (index < 0) + return 0; + + MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index); + DCHECK(buffer); + scoped_refptr<VideoFrameResource> resource = + new VideoFrameResource(pp_instance(), index, buffer); + // 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() { + for (FrameMap::iterator it = frames_.begin(); it != frames_.end(); ++it) { + // Just invalidate and release VideoFrameResorce, but keep PP_Resource. + // So plugin can still use |RecycleFrame()|. + it->second->Invalidate(); + it->second = NULL; + } +} + +void MediaStreamVideoTrackResource::OnPluginMsgConfigureReply( + const ResourceMessageReplyParams& params, + const std::string& track_id) { + if (id().empty()) { + set_id(track_id); + } else { + DCHECK_EQ(id(), track_id); + } + if (TrackedCallback::IsPending(configure_callback_)) { + scoped_refptr<TrackedCallback> callback; + callback.swap(configure_callback_); + callback->Run(params.result()); + } +} + +} // namespace proxy +} // namespace ppapi |