Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1125)

Side by Side Diff: ppapi/proxy/audio_encoder_resource.cc

Issue 1348563003: ppapi: implement PPB_AudioEncoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add bitstream buffer type to MediaStreamBuffer Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/shared_memory.h"
6 #include "ppapi/c/pp_array_output.h"
7 #include "ppapi/c/pp_codecs.h"
8 #include "ppapi/proxy/audio_buffer_resource.h"
5 #include "ppapi/proxy/audio_encoder_resource.h" 9 #include "ppapi/proxy/audio_encoder_resource.h"
10 #include "ppapi/proxy/ppapi_messages.h"
11 #include "ppapi/shared_impl/array_writer.h"
12 #include "ppapi/shared_impl/media_stream_buffer.h"
13 #include "ppapi/thunk/enter.h"
6 14
7 namespace ppapi { 15 namespace ppapi {
8 namespace proxy { 16 namespace proxy {
9 17
18 namespace {
19
20 void RunCallback(scoped_refptr<TrackedCallback>* callback, int32_t error) {
21 if (TrackedCallback::IsPending(*callback)) {
22 scoped_refptr<TrackedCallback> temp;
23 callback->swap(temp);
24 temp->Run(error);
25 }
26 }
27
28 } // namespace
29
10 AudioEncoderResource::AudioEncoderResource(Connection connection, 30 AudioEncoderResource::AudioEncoderResource(Connection connection,
11 PP_Instance instance) 31 PP_Instance instance)
12 : PluginResource(connection, instance) { 32 : PluginResource(connection, instance),
33 encoder_last_error_(PP_ERROR_FAILED),
34 initialized_(false),
35 closed_(false),
bbudge 2015/11/17 20:23:59 Remove.
llandwerlin-old 2015/11/18 11:31:46 Done.
36 audio_buffer_manager_(this),
37 bitstream_buffer_manager_(this) {
38 SendCreate(RENDERER, PpapiHostMsg_AudioEncoder_Create());
13 } 39 }
14 40
15 AudioEncoderResource::~AudioEncoderResource() { 41 AudioEncoderResource::~AudioEncoderResource() {
16 } 42 }
17 43
18 thunk::PPB_AudioEncoder_API* AudioEncoderResource::AsPPB_AudioEncoder_API() { 44 thunk::PPB_AudioEncoder_API* AudioEncoderResource::AsPPB_AudioEncoder_API() {
19 return this; 45 return this;
20 } 46 }
21 47
22 int32_t AudioEncoderResource::GetSupportedProfiles( 48 int32_t AudioEncoderResource::GetSupportedProfiles(
23 const PP_ArrayOutput& output, 49 const PP_ArrayOutput& output,
24 const scoped_refptr<TrackedCallback>& callback) { 50 const scoped_refptr<TrackedCallback>& callback) {
25 return PP_ERROR_NOTSUPPORTED; 51 if (TrackedCallback::IsPending(get_supported_profiles_callback_))
52 return PP_ERROR_INPROGRESS;
53
54 get_supported_profiles_callback_ = callback;
55 Call<PpapiPluginMsg_AudioEncoder_GetSupportedProfilesReply>(
56 RENDERER, PpapiHostMsg_AudioEncoder_GetSupportedProfiles(),
57 base::Bind(&AudioEncoderResource::OnPluginMsgGetSupportedProfilesReply,
58 this, output));
59 return PP_OK_COMPLETIONPENDING;
26 } 60 }
27 61
28 int32_t AudioEncoderResource::Initialize( 62 int32_t AudioEncoderResource::Initialize(
29 uint32_t channels, 63 uint32_t channels,
30 PP_AudioBuffer_SampleRate input_sample_rate, 64 PP_AudioBuffer_SampleRate input_sample_rate,
31 PP_AudioBuffer_SampleSize input_sample_size, 65 PP_AudioBuffer_SampleSize input_sample_size,
32 PP_AudioProfile output_profile, 66 PP_AudioProfile output_profile,
33 uint32_t initial_bitrate, 67 uint32_t initial_bitrate,
34 PP_HardwareAcceleration acceleration, 68 PP_HardwareAcceleration acceleration,
35 const scoped_refptr<TrackedCallback>& callback) { 69 const scoped_refptr<TrackedCallback>& callback) {
36 return PP_ERROR_NOTSUPPORTED; 70 if (initialized_)
71 return PP_ERROR_FAILED;
72 if (TrackedCallback::IsPending(initialize_callback_))
73 return PP_ERROR_INPROGRESS;
74
75 initialize_callback_ = callback;
76
77 PPB_AudioEncodeParameters parameters;
78 parameters.channels = channels;
79 parameters.input_sample_rate = input_sample_rate;
80 parameters.input_sample_size = input_sample_size;
81 parameters.output_profile = output_profile;
82 parameters.initial_bitrate = initial_bitrate;
83 parameters.acceleration = acceleration;
84
85 Call<PpapiPluginMsg_AudioEncoder_InitializeReply>(
86 RENDERER, PpapiHostMsg_AudioEncoder_Initialize(parameters),
87 base::Bind(&AudioEncoderResource::OnPluginMsgInitializeReply, this));
88 return PP_OK_COMPLETIONPENDING;
37 } 89 }
38 90
39 int32_t AudioEncoderResource::GetNumberOfSamples() { 91 int32_t AudioEncoderResource::GetNumberOfSamples() {
40 return PP_ERROR_NOTSUPPORTED; 92 if (encoder_last_error_)
93 return encoder_last_error_;
94 return number_of_samples_;
41 } 95 }
42 96
43 int32_t AudioEncoderResource::GetBuffer( 97 int32_t AudioEncoderResource::GetBuffer(
44 PP_Resource* audio_buffer, 98 PP_Resource* audio_buffer,
45 const scoped_refptr<TrackedCallback>& callback) { 99 const scoped_refptr<TrackedCallback>& callback) {
46 return PP_ERROR_NOTSUPPORTED; 100 if (encoder_last_error_)
101 return encoder_last_error_;
102 if (TrackedCallback::IsPending(get_buffer_callback_))
103 return PP_ERROR_INPROGRESS;
104
105 get_buffer_data_ = audio_buffer;
106 get_buffer_callback_ = callback;
107
108 TryGetAudioBuffer();
109
110 return PP_OK_COMPLETIONPENDING;
47 } 111 }
48 112
49 int32_t AudioEncoderResource::Encode( 113 int32_t AudioEncoderResource::Encode(
50 PP_Resource audio_buffer, 114 PP_Resource audio_buffer,
51 const scoped_refptr<TrackedCallback>& callback) { 115 const scoped_refptr<TrackedCallback>& callback) {
52 return PP_ERROR_NOTSUPPORTED; 116 if (encoder_last_error_)
117 return encoder_last_error_;
118
119 AudioBufferMap::iterator it = audio_buffers_.find(audio_buffer);
120 if (it == audio_buffers_.end())
121 // TODO(llandwerlin): accept MediaStreamAudioTrack's audio buffers.
122 return PP_ERROR_BADRESOURCE;
123
124 scoped_refptr<AudioBufferResource> buffer_resource = it->second;
125
126 encode_callbacks_.insert(
127 std::make_pair(buffer_resource->GetBufferIndex(), callback));
128
129 Post(RENDERER,
130 PpapiHostMsg_AudioEncoder_Encode(buffer_resource->GetBufferIndex()));
131
132 // Invalidate the buffer to prevent a CHECK failure when the
133 // AudioBufferResource is destructed.
134 buffer_resource->Invalidate();
135 audio_buffers_.erase(it);
136
137 return PP_OK_COMPLETIONPENDING;
53 } 138 }
54 139
55 int32_t AudioEncoderResource::GetBitstreamBuffer( 140 int32_t AudioEncoderResource::GetBitstreamBuffer(
56 PP_AudioBitstreamBuffer* bitstream_buffer, 141 PP_AudioBitstreamBuffer* bitstream_buffer,
57 const scoped_refptr<TrackedCallback>& callback) { 142 const scoped_refptr<TrackedCallback>& callback) {
58 return PP_ERROR_NOTSUPPORTED; 143 if (encoder_last_error_)
144 return encoder_last_error_;
145 if (TrackedCallback::IsPending(get_bitstream_buffer_callback_))
146 return PP_ERROR_INPROGRESS;
147
148 get_bitstream_buffer_callback_ = callback;
149 get_bitstream_buffer_data_ = bitstream_buffer;
150
151 TryWriteBitstreamBuffer();
152
153 return PP_OK_COMPLETIONPENDING;
59 } 154 }
60 155
61 void AudioEncoderResource::RecycleBitstreamBuffer( 156 void AudioEncoderResource::RecycleBitstreamBuffer(
62 const PP_AudioBitstreamBuffer* bitstream_buffer) { 157 const PP_AudioBitstreamBuffer* bitstream_buffer) {
158 if (encoder_last_error_)
159 return;
160
161 BufferMap::const_iterator it =
162 bitstream_buffer_map_.find(bitstream_buffer->buffer);
163 if (it != bitstream_buffer_map_.end())
164 Post(RENDERER,
165 PpapiHostMsg_AudioEncoder_RecycleBitstreamBuffer(it->second));
63 } 166 }
64 167
65 void AudioEncoderResource::RequestBitrateChange(uint32_t bitrate) { 168 void AudioEncoderResource::RequestBitrateChange(uint32_t bitrate) {
169 if (encoder_last_error_)
170 return;
171 Post(RENDERER, PpapiHostMsg_AudioEncoder_RequestBitrateChange(bitrate));
66 } 172 }
67 173
68 void AudioEncoderResource::Close() { 174 void AudioEncoderResource::Close() {
175 if (encoder_last_error_)
176 return;
177 Post(RENDERER, PpapiHostMsg_AudioEncoder_Close());
178 closed_ = true;
bbudge 2015/11/17 20:23:59 Remove.
llandwerlin-old 2015/11/18 11:31:46 Done.
179 if (!encoder_last_error_ || !initialized_)
180 NotifyError(PP_ERROR_ABORTED);
181 ReleaseBuffers();
182 }
183
184 void AudioEncoderResource::OnReplyReceived(
185 const ResourceMessageReplyParams& params,
186 const IPC::Message& msg) {
187 PPAPI_BEGIN_MESSAGE_MAP(AudioEncoderResource, msg)
188 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
189 PpapiPluginMsg_AudioEncoder_BitstreamBufferReady,
190 OnPluginMsgBitstreamBufferReady)
191 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(PpapiPluginMsg_AudioEncoder_EncodeReply,
192 OnPluginMsgEncodeReply)
193 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(PpapiPluginMsg_AudioEncoder_NotifyError,
194 OnPluginMsgNotifyError)
195 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
196 PluginResource::OnReplyReceived(params, msg))
197 PPAPI_END_MESSAGE_MAP()
198 }
199
200 void AudioEncoderResource::OnPluginMsgGetSupportedProfilesReply(
201 const PP_ArrayOutput& output,
202 const ResourceMessageReplyParams& params,
203 const std::vector<PP_AudioProfileDescription>& profiles) {
204 ArrayWriter writer(output);
205 if (params.result() != PP_OK || !writer.is_valid() ||
206 !writer.StoreVector(profiles)) {
207 RunCallback(&get_supported_profiles_callback_, PP_ERROR_FAILED);
208 return;
209 }
210
211 RunCallback(&get_supported_profiles_callback_,
212 base::checked_cast<int32_t>(profiles.size()));
213 }
214
215 void AudioEncoderResource::OnPluginMsgInitializeReply(
216 const ResourceMessageReplyParams& params,
217 int32_t number_of_samples,
218 int32_t audio_buffer_count,
219 int32_t audio_buffer_size,
220 int32_t bitstream_buffer_count,
221 int32_t bitstream_buffer_size) {
222 DCHECK(!initialized_);
223
224 int32_t error = params.result();
225 if (error) {
226 RunCallback(&initialize_callback_, error);
227 return;
228 }
229
230 // Get audio buffers shared memory buffer.
231 base::SharedMemoryHandle buffer_handle;
232 if (!params.TakeSharedMemoryHandleAtIndex(0, &buffer_handle) ||
233 !audio_buffer_manager_.SetBuffers(
234 audio_buffer_count, audio_buffer_size,
235 make_scoped_ptr(new base::SharedMemory(buffer_handle, false)),
236 true)) {
237 RunCallback(&initialize_callback_, PP_ERROR_NOMEMORY);
238 return;
239 }
240
241 // Get bitstreamer buffers shared memory buffer.
bbudge 2015/11/17 20:23:59 s/bitstreamer/bitstream
llandwerlin-old 2015/11/18 11:31:46 Done.
242 if (!params.TakeSharedMemoryHandleAtIndex(1, &buffer_handle) ||
243 !bitstream_buffer_manager_.SetBuffers(
244 bitstream_buffer_count, bitstream_buffer_size,
245 make_scoped_ptr(new base::SharedMemory(buffer_handle, false)),
246 false)) {
247 RunCallback(&initialize_callback_, PP_ERROR_NOMEMORY);
248 return;
249 }
250
251 for (int32_t i = 0; i < bitstream_buffer_manager_.number_of_buffers(); i++)
252 bitstream_buffer_map_.insert(std::make_pair(
253 bitstream_buffer_manager_.GetBufferPointer(i)->bitstream.data, i));
254
255 encoder_last_error_ = PP_OK;
256 number_of_samples_ = number_of_samples;
257 initialized_ = true;
258
259 RunCallback(&initialize_callback_, PP_OK);
260 }
261
262 void AudioEncoderResource::OnPluginMsgEncodeReply(
263 const ResourceMessageReplyParams& params,
264 int32_t buffer_id) {
265 // We need to ensure there are still callbacks to be called before
266 // processing this message. We might receive a EncodeReply message
bbudge 2015/11/17 20:23:59 tiny nit: s/a/an
llandwerlin-old 2015/11/18 11:31:46 Done.
267 // after having sent a Close message to the renderer. In this case,
268 // we don't have any callback left to call.
269 if (encode_callbacks_.empty())
270 return;
271
272 EncodeMap::iterator it = encode_callbacks_.find(buffer_id);
273 DCHECK(encode_callbacks_.end() != it);
274
275 scoped_refptr<TrackedCallback> callback = it->second;
276 encode_callbacks_.erase(it);
277 RunCallback(&callback, encoder_last_error_);
278
279 audio_buffer_manager_.EnqueueBuffer(buffer_id);
280 // If the plugin is waiting for an audio buffer, we can give the one
281 // that just became available again.
282 if (TrackedCallback::IsPending(get_buffer_callback_))
283 TryGetAudioBuffer();
284 }
285
286 void AudioEncoderResource::OnPluginMsgBitstreamBufferReady(
287 const ResourceMessageReplyParams& params,
288 int32_t buffer_id) {
289 bitstream_buffer_manager_.EnqueueBuffer(buffer_id);
290
291 if (TrackedCallback::IsPending(get_bitstream_buffer_callback_))
292 TryWriteBitstreamBuffer();
293 }
294
295 void AudioEncoderResource::OnPluginMsgNotifyError(
296 const ResourceMessageReplyParams& params,
297 int32_t error) {
298 NotifyError(error);
299 }
300
301 void AudioEncoderResource::NotifyError(int32_t error) {
302 DCHECK(error);
303
304 encoder_last_error_ = error;
305 RunCallback(&get_supported_profiles_callback_, error);
306 RunCallback(&initialize_callback_, error);
307 RunCallback(&get_buffer_callback_, error);
308 get_buffer_data_ = nullptr;
309 RunCallback(&get_bitstream_buffer_callback_, error);
310 get_bitstream_buffer_data_ = nullptr;
311 for (EncodeMap::iterator it = encode_callbacks_.begin();
312 it != encode_callbacks_.end(); ++it)
313 RunCallback(&it->second, error);
314 encode_callbacks_.clear();
315 }
316
317 void AudioEncoderResource::TryGetAudioBuffer() {
318 DCHECK(TrackedCallback::IsPending(get_buffer_callback_));
319
320 if (!audio_buffer_manager_.HasAvailableBuffer())
321 return;
322
323 int32_t buffer_id = audio_buffer_manager_.DequeueBuffer();
324 scoped_refptr<AudioBufferResource> resource = new AudioBufferResource(
325 pp_instance(), buffer_id,
326 audio_buffer_manager_.GetBufferPointer(buffer_id));
327 audio_buffers_.insert(
328 AudioBufferMap::value_type(resource->pp_resource(), resource));
329
330 // Take a reference for the plugin.
331 *get_buffer_data_ = resource->GetReference();
332 get_buffer_data_ = nullptr;
333 RunCallback(&get_buffer_callback_, PP_OK);
334 }
335
336 void AudioEncoderResource::TryWriteBitstreamBuffer() {
337 DCHECK(TrackedCallback::IsPending(get_bitstream_buffer_callback_));
338
339 if (!bitstream_buffer_manager_.HasAvailableBuffer())
340 return;
341
342 int32_t buffer_id = bitstream_buffer_manager_.DequeueBuffer();
343 MediaStreamBuffer* buffer =
344 bitstream_buffer_manager_.GetBufferPointer(buffer_id);
345
346 get_bitstream_buffer_data_->buffer = buffer->bitstream.data;
347 get_bitstream_buffer_data_->size = buffer->bitstream.data_size;
348 get_bitstream_buffer_data_ = nullptr;
349 RunCallback(&get_bitstream_buffer_callback_, PP_OK);
350 }
351
352 void AudioEncoderResource::ReleaseBuffers() {
353 for (AudioBufferMap::iterator it = audio_buffers_.begin();
354 it != audio_buffers_.end(); ++it)
355 it->second->Invalidate();
356 audio_buffers_.clear();
69 } 357 }
70 358
71 } // namespace proxy 359 } // namespace proxy
72 } // namespace ppapi 360 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698