Plugin Power Saver: Force SW rendering for peripheral plugins.
[chromium-blink-merge.git] / ppapi / proxy / media_stream_audio_track_resource.cc
blob5d30362414ebec73452f6a9f17550c5c464ecb77
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/media_stream_audio_track_resource.h"
7 #include "ppapi/proxy/audio_buffer_resource.h"
8 #include "ppapi/proxy/ppapi_messages.h"
9 #include "ppapi/shared_impl/media_stream_audio_track_shared.h"
10 #include "ppapi/shared_impl/media_stream_buffer.h"
11 #include "ppapi/shared_impl/var.h"
13 namespace ppapi {
14 namespace proxy {
16 MediaStreamAudioTrackResource::MediaStreamAudioTrackResource(
17 Connection connection,
18 PP_Instance instance,
19 int pending_renderer_id,
20 const std::string& id)
21 : MediaStreamTrackResourceBase(
22 connection, instance, pending_renderer_id, id),
23 get_buffer_output_(NULL) {
26 MediaStreamAudioTrackResource::~MediaStreamAudioTrackResource() {
27 Close();
30 thunk::PPB_MediaStreamAudioTrack_API*
31 MediaStreamAudioTrackResource::AsPPB_MediaStreamAudioTrack_API() {
32 return this;
35 PP_Var MediaStreamAudioTrackResource::GetId() {
36 return StringVar::StringToPPVar(id());
39 PP_Bool MediaStreamAudioTrackResource::HasEnded() {
40 return PP_FromBool(has_ended());
43 int32_t MediaStreamAudioTrackResource::Configure(
44 const int32_t attrib_list[],
45 scoped_refptr<TrackedCallback> callback) {
46 if (has_ended())
47 return PP_ERROR_FAILED;
49 if (TrackedCallback::IsPending(configure_callback_) ||
50 TrackedCallback::IsPending(get_buffer_callback_)) {
51 return PP_ERROR_INPROGRESS;
54 // Do not support configure if audio buffers are held by plugin.
55 if (!buffers_.empty())
56 return PP_ERROR_INPROGRESS;
58 MediaStreamAudioTrackShared::Attributes attributes;
59 int i = 0;
60 for (; attrib_list[i] != PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE; i += 2) {
61 switch (attrib_list[i]) {
62 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS:
63 attributes.buffers = attrib_list[i + 1];
64 break;
65 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION:
66 attributes.duration = attrib_list[i + 1];
67 break;
68 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_RATE:
69 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_SAMPLE_SIZE:
70 case PP_MEDIASTREAMAUDIOTRACK_ATTRIB_CHANNELS:
71 return PP_ERROR_NOTSUPPORTED;
72 default:
73 return PP_ERROR_BADARGUMENT;
77 if (!MediaStreamAudioTrackShared::VerifyAttributes(attributes))
78 return PP_ERROR_BADARGUMENT;
80 configure_callback_ = callback;
81 Call<PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply>(
82 RENDERER,
83 PpapiHostMsg_MediaStreamAudioTrack_Configure(attributes),
84 base::Bind(&MediaStreamAudioTrackResource::OnPluginMsgConfigureReply,
85 base::Unretained(this)),
86 callback);
87 return PP_OK_COMPLETIONPENDING;
90 int32_t MediaStreamAudioTrackResource::GetAttrib(
91 PP_MediaStreamAudioTrack_Attrib attrib,
92 int32_t* value) {
93 // TODO(penghuang): Implement this function.
94 return PP_ERROR_NOTSUPPORTED;
97 int32_t MediaStreamAudioTrackResource::GetBuffer(
98 PP_Resource* buffer,
99 scoped_refptr<TrackedCallback> callback) {
100 if (has_ended())
101 return PP_ERROR_FAILED;
103 if (TrackedCallback::IsPending(configure_callback_) ||
104 TrackedCallback::IsPending(get_buffer_callback_))
105 return PP_ERROR_INPROGRESS;
107 *buffer = GetAudioBuffer();
108 if (*buffer)
109 return PP_OK;
111 // TODO(penghuang): Use the callback as hints to determine which thread will
112 // use the resource, so we could deliver buffers to the target thread directly
113 // for better performance.
114 get_buffer_output_ = buffer;
115 get_buffer_callback_ = callback;
116 return PP_OK_COMPLETIONPENDING;
119 int32_t MediaStreamAudioTrackResource::RecycleBuffer(PP_Resource buffer) {
120 BufferMap::iterator it = buffers_.find(buffer);
121 if (it == buffers_.end())
122 return PP_ERROR_BADRESOURCE;
124 scoped_refptr<AudioBufferResource> buffer_resource = it->second;
125 buffers_.erase(it);
127 if (has_ended())
128 return PP_OK;
130 DCHECK_GE(buffer_resource->GetBufferIndex(), 0);
132 SendEnqueueBufferMessageToHost(buffer_resource->GetBufferIndex());
133 buffer_resource->Invalidate();
134 return PP_OK;
137 void MediaStreamAudioTrackResource::Close() {
138 if (has_ended())
139 return;
141 if (TrackedCallback::IsPending(get_buffer_callback_)) {
142 *get_buffer_output_ = 0;
143 get_buffer_callback_->PostAbort();
144 get_buffer_callback_ = NULL;
145 get_buffer_output_ = 0;
148 ReleaseBuffers();
149 MediaStreamTrackResourceBase::CloseInternal();
152 void MediaStreamAudioTrackResource::OnNewBufferEnqueued() {
153 if (!TrackedCallback::IsPending(get_buffer_callback_))
154 return;
156 *get_buffer_output_ = GetAudioBuffer();
157 int32_t result = *get_buffer_output_ ? PP_OK : PP_ERROR_FAILED;
158 get_buffer_output_ = NULL;
159 scoped_refptr<TrackedCallback> callback;
160 callback.swap(get_buffer_callback_);
161 callback->Run(result);
164 PP_Resource MediaStreamAudioTrackResource::GetAudioBuffer() {
165 int32_t index = buffer_manager()->DequeueBuffer();
166 if (index < 0)
167 return 0;
169 MediaStreamBuffer* buffer = buffer_manager()->GetBufferPointer(index);
170 DCHECK(buffer);
171 scoped_refptr<AudioBufferResource> resource =
172 new AudioBufferResource(pp_instance(), index, buffer);
173 // Add |pp_resource()| and |resource| into |buffers_|.
174 // |buffers_| uses scoped_ptr<> to hold a ref of |resource|. It keeps the
175 // resource alive.
176 buffers_.insert(BufferMap::value_type(resource->pp_resource(), resource));
177 return resource->GetReference();
180 void MediaStreamAudioTrackResource::ReleaseBuffers() {
181 for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) {
182 // Just invalidate and release VideoBufferResorce, but keep PP_Resource.
183 // So plugin can still use |RecycleBuffer()|.
184 it->second->Invalidate();
185 it->second = NULL;
189 void MediaStreamAudioTrackResource::OnPluginMsgConfigureReply(
190 const ResourceMessageReplyParams& params) {
191 if (TrackedCallback::IsPending(configure_callback_)) {
192 scoped_refptr<TrackedCallback> callback;
193 callback.swap(configure_callback_);
194 callback->Run(params.result());
198 } // namespace proxy
199 } // namespace ppapi