diff options
author | penghuang@chromium.org <penghuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 02:50:23 +0000 |
---|---|---|
committer | penghuang@chromium.org <penghuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 02:50:23 +0000 |
commit | 2b7a6d39afde5917e8ccb341afdccb0a931b2636 (patch) | |
tree | 1074e567377cd34157c0755582d68143fbf040e8 /ppapi/proxy | |
parent | 8fa42fb71833ddd618b2d9c41b1ccf1a269f7e86 (diff) | |
download | chromium_src-2b7a6d39afde5917e8ccb341afdccb0a931b2636.zip chromium_src-2b7a6d39afde5917e8ccb341afdccb0a931b2636.tar.gz chromium_src-2b7a6d39afde5917e8ccb341afdccb0a931b2636.tar.bz2 |
[PPAPI] Pepper MediaStream API audio track implementation and example.
TBR=jamesr@chromium.org
BUG=330851
Review URL: https://codereview.chromium.org/140783004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249245 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/audio_frame_resource.cc | 111 | ||||
-rw-r--r-- | ppapi/proxy/audio_frame_resource.h | 54 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_audio_track_resource.cc | 148 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_audio_track_resource.h | 70 | ||||
-rw-r--r-- | ppapi/proxy/media_stream_video_track_resource.cc | 18 | ||||
-rw-r--r-- | ppapi/proxy/plugin_var_tracker.cc | 19 | ||||
-rw-r--r-- | ppapi/proxy/ppapi_messages.h | 6 |
7 files changed, 418 insertions, 8 deletions
diff --git a/ppapi/proxy/audio_frame_resource.cc b/ppapi/proxy/audio_frame_resource.cc new file mode 100644 index 0000000..4954857 --- /dev/null +++ b/ppapi/proxy/audio_frame_resource.cc @@ -0,0 +1,111 @@ +// 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/audio_frame_resource.h" + +#include "base/logging.h" +#include "ppapi/c/pp_bool.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +AudioFrameResource::AudioFrameResource(PP_Instance instance, + int32_t index, + MediaStreamFrame* frame) + : Resource(OBJECT_IS_PROXY, instance), + index_(index), + frame_(frame) { + DCHECK_EQ(frame_->header.type, MediaStreamFrame::TYPE_AUDIO); +} + +AudioFrameResource::~AudioFrameResource() { + CHECK(!frame_) << "An unused (or unrecycled) frame is destroyed."; +} + +thunk::PPB_AudioFrame_API* AudioFrameResource::AsPPB_AudioFrame_API() { + return this; +} + +PP_TimeDelta AudioFrameResource::GetTimestamp() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return 0.0; + } + return frame_->audio.timestamp; +} + +void AudioFrameResource::SetTimestamp(PP_TimeDelta timestamp) { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return; + } + frame_->audio.timestamp = timestamp; +} + +PP_AudioFrame_SampleRate AudioFrameResource::GetSampleRate() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return PP_AUDIOFRAME_SAMPLERATE_UNKNOWN; + } + return frame_->audio.sample_rate; +} + +PP_AudioFrame_SampleSize AudioFrameResource::GetSampleSize() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return PP_AUDIOFRAME_SAMPLESIZE_UNKNOWN; + } + return PP_AUDIOFRAME_SAMPLESIZE_16_BITS; +} + +uint32_t AudioFrameResource::GetNumberOfChannels() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return 0; + } + return frame_->audio.number_of_channels; +} + +uint32_t AudioFrameResource::GetNumberOfSamples() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return 0; + } + return frame_->audio.number_of_samples; +} + +void* AudioFrameResource::GetDataBuffer() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return NULL; + } + return frame_->audio.data; +} + +uint32_t AudioFrameResource::GetDataBufferSize() { + if (!frame_) { + VLOG(1) << "Frame is invalid"; + return 0; + } + return frame_->audio.data_size; +} + +MediaStreamFrame* AudioFrameResource::GetFrameBuffer() { + return frame_; +} + +int32_t AudioFrameResource::GetFrameBufferIndex() { + return index_; +} + +void AudioFrameResource::Invalidate() { + DCHECK(frame_); + DCHECK_GE(index_, 0); + frame_ = NULL; + index_ = -1; +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/audio_frame_resource.h b/ppapi/proxy/audio_frame_resource.h new file mode 100644 index 0000000..a463bba --- /dev/null +++ b/ppapi/proxy/audio_frame_resource.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_PROXY_AUDIO_FRAME_RESOURCE_H_ +#define PPAPI_PROXY_AUDIO_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_audio_frame_api.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT AudioFrameResource : public Resource, + public thunk::PPB_AudioFrame_API { + public: + AudioFrameResource(PP_Instance instance, + int32_t index, + MediaStreamFrame* frame); + + virtual ~AudioFrameResource(); + + // PluginResource overrides: + virtual thunk::PPB_AudioFrame_API* AsPPB_AudioFrame_API() OVERRIDE; + + // PPB_AudioFrame_API overrides: + virtual PP_TimeDelta GetTimestamp() OVERRIDE; + virtual void SetTimestamp(PP_TimeDelta timestamp) OVERRIDE; + virtual PP_AudioFrame_SampleRate GetSampleRate() OVERRIDE; + virtual PP_AudioFrame_SampleSize GetSampleSize() OVERRIDE; + virtual uint32_t GetNumberOfChannels() OVERRIDE; + virtual uint32_t GetNumberOfSamples() 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(AudioFrameResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_AUDIO_FRAME_RESOURCE_H_ diff --git a/ppapi/proxy/media_stream_audio_track_resource.cc b/ppapi/proxy/media_stream_audio_track_resource.cc new file mode 100644 index 0000000..10956ab --- /dev/null +++ b/ppapi/proxy/media_stream_audio_track_resource.cc @@ -0,0 +1,148 @@ +// 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_audio_track_resource.h" + +#include "ppapi/proxy/audio_frame_resource.h" +#include "ppapi/shared_impl/media_stream_frame.h" +#include "ppapi/shared_impl/var.h" + +namespace ppapi { +namespace proxy { + +MediaStreamAudioTrackResource::MediaStreamAudioTrackResource( + Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id) + : MediaStreamTrackResourceBase( + connection, instance, pending_renderer_id, id), + get_frame_output_(NULL) { +} + +MediaStreamAudioTrackResource::~MediaStreamAudioTrackResource() { + Close(); +} + +thunk::PPB_MediaStreamAudioTrack_API* +MediaStreamAudioTrackResource::AsPPB_MediaStreamAudioTrack_API() { + return this; +} + +PP_Var MediaStreamAudioTrackResource::GetId() { + return StringVar::StringToPPVar(id()); +} + +PP_Bool MediaStreamAudioTrackResource::HasEnded() { + return PP_FromBool(has_ended()); +} + +int32_t MediaStreamAudioTrackResource::Configure( + const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) { + // TODO(penghuang): Implement this function. + return PP_ERROR_NOTSUPPORTED; +} + +int32_t MediaStreamAudioTrackResource::GetAttrib( + PP_MediaStreamAudioTrack_Attrib attrib, + int32_t* value) { + // TODO(penghuang): Implement this function. + return PP_ERROR_NOTSUPPORTED; +} + +int32_t MediaStreamAudioTrackResource::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 = GetAudioFrame(); + if (*frame) + return PP_OK; + + // TODO(penghuang): Use the callback as hints to determine which thread will + // use the resource, so we could deliver frames to the target thread directly + // for better performance. + get_frame_output_ = frame; + get_frame_callback_ = callback; + return PP_OK_COMPLETIONPENDING; +} + +int32_t MediaStreamAudioTrackResource::RecycleFrame(PP_Resource frame) { + FrameMap::iterator it = frames_.find(frame); + if (it == frames_.end()) + return PP_ERROR_BADRESOURCE; + + scoped_refptr<AudioFrameResource> 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 MediaStreamAudioTrackResource::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 MediaStreamAudioTrackResource::OnNewFrameEnqueued() { + if (!TrackedCallback::IsPending(get_frame_callback_)) + return; + + *get_frame_output_ = GetAudioFrame(); + 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 MediaStreamAudioTrackResource::GetAudioFrame() { + int32_t index = frame_buffer()->DequeueFrame(); + if (index < 0) + return 0; + + MediaStreamFrame* frame = frame_buffer()->GetFramePointer(index); + DCHECK(frame); + scoped_refptr<AudioFrameResource> resource = + new AudioFrameResource(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 MediaStreamAudioTrackResource::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_audio_track_resource.h b/ppapi/proxy/media_stream_audio_track_resource.h new file mode 100644 index 0000000..2686381 --- /dev/null +++ b/ppapi/proxy/media_stream_audio_track_resource.h @@ -0,0 +1,70 @@ +// 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_AUDIO_TRACK_RESOURCE_H_ +#define PPAPI_PROXY_MEDIA_STREAM_AUDIO_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_audio_track_api.h" + +namespace ppapi { +namespace proxy { + +class AudioFrameResource; + +class PPAPI_PROXY_EXPORT MediaStreamAudioTrackResource + : public MediaStreamTrackResourceBase, + public thunk::PPB_MediaStreamAudioTrack_API { + public: + MediaStreamAudioTrackResource(Connection connection, + PP_Instance instance, + int pending_renderer_id, + const std::string& id); + + virtual ~MediaStreamAudioTrackResource(); + + // Resource overrides: + virtual thunk::PPB_MediaStreamAudioTrack_API* + AsPPB_MediaStreamAudioTrack_API() OVERRIDE; + + // PPB_MediaStreamAudioTrack_API overrides: + virtual PP_Var GetId() OVERRIDE; + virtual PP_Bool HasEnded() OVERRIDE; + virtual int32_t Configure(const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t GetAttrib(PP_MediaStreamAudioTrack_Attrib attrib, + int32_t* value) 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 GetAudioFrame(); + + void ReleaseFrames(); + + // Allocated frame resources by |GetFrame()|. + typedef std::map<PP_Resource, scoped_refptr<AudioFrameResource> > FrameMap; + FrameMap frames_; + + PP_Resource* get_frame_output_; + + scoped_refptr<TrackedCallback> get_frame_callback_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrackResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_MEDIA_STREAM_AUDIO_TRACK_RESOURCE_H_ diff --git a/ppapi/proxy/media_stream_video_track_resource.cc b/ppapi/proxy/media_stream_video_track_resource.cc index e8ab4c5..804df00 100644 --- a/ppapi/proxy/media_stream_video_track_resource.cc +++ b/ppapi/proxy/media_stream_video_track_resource.cc @@ -107,20 +107,24 @@ void MediaStreamVideoTrackResource::Close() { } 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); - } + 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 = frame_buffer()->DequeueFrame(); if (index < 0) return 0; + MediaStreamFrame* frame = frame_buffer()->GetFramePointer(index); + DCHECK(frame); scoped_refptr<VideoFrameResource> resource = new VideoFrameResource(pp_instance(), index, frame); // Add |pp_resource()| and |resource| into |frames_|. diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc index e2db871..06db224 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_audio_track_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" @@ -195,6 +196,24 @@ PP_Var PluginVarTracker::MakeResourcePPVarFromMessage( file_system_type))->GetReference(); return MakeResourcePPVar(pp_resource); } + case PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost::ID: { + DCHECK(pending_renderer_id); + std::string track_id; + if (!UnpackMessage< + PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost>( + creation_message, &track_id)) { + NOTREACHED() << + "Invalid message of type " + "PpapiPluginMsg_MediaStreamAudioTrack_CreateFromPendingHost"; + return PP_MakeNull(); + } + PP_Resource pp_resource = + (new MediaStreamAudioTrackResource(GetConnectionForInstance(instance), + instance, + pending_renderer_id, + track_id))->GetReference(); + return MakeResourcePPVar(pp_resource); + } case PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost::ID: { DCHECK(pending_renderer_id); std::string track_id; diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index 7e6543e..92ed096 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -1437,9 +1437,13 @@ 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_MediaStreamAudioTrack_CreateFromPendingHost, + std::string /* track_id */) IPC_MESSAGE_CONTROL1(PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost, std::string /* track_id */) + +// Message for init frames. It also takes a shared memory handle which is put in +// the outer ResourceReplyMessage. IPC_MESSAGE_CONTROL2(PpapiPluginMsg_MediaStreamTrack_InitFrames, int32_t /* number_of_frames */, int32_t /* frame_size */) |