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