1 /*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define HST_LOG_TAG "AudioCapturePlugin"
16
17 #include "audio_capture_plugin.h"
18 #include <algorithm>
19 #include <cmath>
20 #include "audio_errors.h"
21 #include "audio_info.h"
22 #include "audio_type_translate.h"
23 #include "foundation/log.h"
24 #include "foundation/osal/thread/scoped_lock.h"
25 #include "plugin/common/plugin_time.h"
26 #include "utils/constants.h"
27
28 namespace {
29 using namespace OHOS::Media::Plugin;
30 using namespace AuCapturePlugin;
31
32 constexpr size_t MAX_CAPTURE_BUFFER_SIZE = 100000;
33 constexpr size_t TIME_SEC_TO_NS = 1000000000;
34
UpdateSupportedSampleRate(Capability & outCaps)35 void UpdateSupportedSampleRate(Capability& outCaps)
36 {
37 auto supportedSampleRateList = OHOS::AudioStandard::AudioCapturer::GetSupportedSamplingRates();
38 if (!supportedSampleRateList.empty()) {
39 DiscreteCapability<uint32_t> values;
40 for (const auto& rate : supportedSampleRateList) {
41 uint32_t sampleRate = 0;
42 if (AuCapturePlugin::SampleRateEnum2Num(rate, sampleRate)) {
43 values.push_back(sampleRate);
44 }
45 }
46 if (!values.empty()) {
47 outCaps.AppendDiscreteKeys<uint32_t>(Capability::Key::AUDIO_SAMPLE_RATE, values);
48 }
49 }
50 }
51
UpdateSupportedChannels(Capability & outCaps)52 void UpdateSupportedChannels(Capability& outCaps)
53 {
54 auto supportedChannelsList = OHOS::AudioStandard::AudioCapturer::GetSupportedChannels();
55 if (!supportedChannelsList.empty()) {
56 DiscreteCapability<uint32_t> values;
57 for (const auto& channel : supportedChannelsList) {
58 uint32_t channelNum = 0;
59 if (AuCapturePlugin::ChannelNumEnum2Num(channel, channelNum)) {
60 values.push_back(channelNum);
61 }
62 }
63 if (!values.empty()) {
64 outCaps.AppendDiscreteKeys<uint32_t>(Capability::Key::AUDIO_CHANNELS, values);
65 }
66 }
67 }
68
UpdateSupportedSampleFormat(Capability & outCaps)69 void UpdateSupportedSampleFormat(Capability& outCaps)
70 {
71 auto supportedFormatsList = OHOS::AudioStandard::AudioCapturer::GetSupportedFormats();
72 if (!supportedFormatsList.empty()) {
73 DiscreteCapability<AudioSampleFormat> values;
74 for (const auto& fmt : supportedFormatsList) {
75 auto pFmt = AudioSampleFormat::U8;
76 if (AuCapturePlugin::SampleFmt2PluginFmt(fmt, pFmt)) {
77 values.emplace_back(pFmt);
78 }
79 }
80 if (!values.empty()) {
81 outCaps.AppendDiscreteKeys<AudioSampleFormat>(Capability::Key::AUDIO_SAMPLE_FORMAT, values);
82 }
83 }
84 }
85
AudioCaptureRegister(const std::shared_ptr<Register> & reg)86 Status AudioCaptureRegister(const std::shared_ptr<Register> ®)
87 {
88 SourcePluginDef definition;
89 definition.name = "AudioCapture";
90 definition.description = "Audio capture from audio service";
91 definition.rank = 100; // 100: max rank
92 definition.inputType = SrcInputType::AUD_MIC;
93 definition.creator = [](const std::string& name) -> std::shared_ptr<SourcePlugin> {
94 return std::make_shared<AudioCapturePlugin>(name);
95 };
96 Capability outCaps(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
97 UpdateSupportedSampleRate(outCaps);
98 UpdateSupportedChannels(outCaps);
99 UpdateSupportedSampleFormat(outCaps);
100 definition.outCaps.push_back(outCaps);
101 // add es outCaps later
102 return reg->AddPlugin(definition);
103 }
__anonb8b514d80302null104 PLUGIN_DEFINITION(StdAudioCapture, LicenseType::APACHE_V2, AudioCaptureRegister, [] {});
105 }
106
107 namespace OHOS {
108 namespace Media {
109 namespace Plugin {
110 namespace AuCapturePlugin {
111 #define FAIL_LOG_RETURN(exec, msg) \
112 do { \
113 auto ret = exec; \
114 if (ret != OHOS::AudioStandard::SUCCESS) { \
115 MEDIA_LOG_E(msg " failed return " PUBLIC_LOG_D32, ret); \
116 return Error2Status(ret); \
117 } \
118 } while (0)
119
AudioCapturePlugin(std::string name)120 AudioCapturePlugin::AudioCapturePlugin(std::string name) : SourcePlugin(std::move(name)) {}
121
~AudioCapturePlugin()122 AudioCapturePlugin::~AudioCapturePlugin()
123 {
124 DoDeinit();
125 }
126
Init()127 Status AudioCapturePlugin::Init()
128 {
129 OSAL::ScopedLock lock(captureMutex_);
130 if (audioCapturer_ == nullptr) {
131 AudioStandard::AppInfo appInfo;
132 appInfo.appTokenId = appTokenId_;
133 appInfo.appUid = appUid_;
134 appInfo.appPid = appPid_;
135 audioCapturer_ = AudioStandard::AudioCapturer::Create(AudioStandard::AudioStreamType::STREAM_MUSIC, appInfo);
136 if (audioCapturer_ == nullptr) {
137 MEDIA_LOG_E("Create audioCapturer fail");
138 return Status::ERROR_UNKNOWN;
139 }
140 }
141 return Status::OK;
142 }
143
DoDeinit()144 Status AudioCapturePlugin::DoDeinit()
145 {
146 OSAL::ScopedLock lock(captureMutex_);
147 if (audioCapturer_) {
148 if (audioCapturer_->GetStatus() == AudioStandard::CapturerState::CAPTURER_RUNNING) {
149 if (!audioCapturer_->Stop()) {
150 MEDIA_LOG_E("Stop audioCapturer fail");
151 }
152 }
153 if (!audioCapturer_->Release()) {
154 MEDIA_LOG_E("Release audioCapturer fail");
155 }
156 audioCapturer_ = nullptr;
157 }
158 return Status::OK;
159 }
160
Deinit()161 Status AudioCapturePlugin::Deinit()
162 {
163 MEDIA_LOG_D("Deinit");
164 return DoDeinit();
165 }
166
Prepare()167 Status AudioCapturePlugin::Prepare()
168 {
169 MEDIA_LOG_D("IN");
170 AudioStandard::AudioEncodingType audioEncoding = AudioStandard::ENCODING_INVALID;
171 auto supportedEncodingTypes = OHOS::AudioStandard::AudioCapturer::GetSupportedEncodingTypes();
172 for (auto& supportedEncodingType : supportedEncodingTypes) {
173 if (supportedEncodingType == AudioStandard::ENCODING_PCM) {
174 audioEncoding = AudioStandard::ENCODING_PCM;
175 break;
176 }
177 }
178
179 if (audioEncoding != AudioStandard::ENCODING_PCM) {
180 MEDIA_LOG_E("audioCapturer do not support pcm encoding");
181 return Status::ERROR_UNKNOWN;
182 }
183 capturerParams_.audioEncoding = AudioStandard::ENCODING_PCM;
184 size_t size;
185 {
186 OSAL::ScopedLock lock (captureMutex_);
187 FALSE_RETURN_V_MSG_E(audioCapturer_ != nullptr, Status::ERROR_WRONG_STATE, "no available audio capture");
188 FAIL_LOG_RETURN(audioCapturer_->SetParams(capturerParams_), "audioCapturer SetParam");
189 FAIL_LOG_RETURN(audioCapturer_->GetBufferSize(size), "audioCapturer GetBufferSize");
190 }
191 if (size >= MAX_CAPTURE_BUFFER_SIZE) {
192 MEDIA_LOG_E("bufferSize is too big: " PUBLIC_LOG_ZU, size);
193 return Status::ERROR_INVALID_PARAMETER;
194 }
195 bufferSize_ = size;
196 MEDIA_LOG_D("bufferSize is: " PUBLIC_LOG_ZU, bufferSize_);
197 return Status::OK;
198 }
199
Reset()200 Status AudioCapturePlugin::Reset()
201 {
202 MEDIA_LOG_D("Reset");
203 {
204 OSAL::ScopedLock lock (captureMutex_);
205 FALSE_RETURN_V_MSG_E(audioCapturer_ != nullptr, Status::ERROR_WRONG_STATE, "no available audio capture");
206 if (audioCapturer_->GetStatus() == AudioStandard::CapturerState::CAPTURER_RUNNING) {
207 if (!audioCapturer_->Stop()) {
208 MEDIA_LOG_E("Stop audioCapturer fail");
209 }
210 }
211 }
212 bufferSize_ = 0;
213 bitRate_ = 0;
214 capturerParams_ = AudioStandard::AudioCapturerParams();
215 return Status::OK;
216 }
217
Start()218 Status AudioCapturePlugin::Start()
219 {
220 MEDIA_LOG_D("start capture");
221 OSAL::ScopedLock lock (captureMutex_);
222 FALSE_RETURN_V_MSG_E(audioCapturer_ != nullptr, Status::ERROR_WRONG_STATE, "no available audio capture");
223 if (audioCapturer_->GetStatus() != AudioStandard::CapturerState::CAPTURER_RUNNING) {
224 if (!audioCapturer_->Start()) {
225 MEDIA_LOG_E("audioCapturer start failed");
226 return Status::ERROR_UNKNOWN;
227 }
228 }
229 return Status::OK;
230 }
231
Stop()232 Status AudioCapturePlugin::Stop()
233 {
234 MEDIA_LOG_D("stop capture");
235 OSAL::ScopedLock lock (captureMutex_);
236 if (audioCapturer_ && audioCapturer_->GetStatus() == AudioStandard::CAPTURER_RUNNING) {
237 if (!audioCapturer_->Stop()) {
238 MEDIA_LOG_E("Stop audioCapturer fail");
239 return Status::ERROR_UNKNOWN;
240 }
241 }
242 return Status::OK;
243 }
244
GetParameter(Tag tag,ValueType & value)245 Status AudioCapturePlugin::GetParameter(Tag tag, ValueType& value)
246 {
247 MEDIA_LOG_D("GetParameter");
248 AudioStandard::AudioCapturerParams params;
249 {
250 OSAL::ScopedLock lock (captureMutex_);
251 if (!audioCapturer_) {
252 return Plugin::Status::ERROR_WRONG_STATE;
253 }
254 FAIL_LOG_RETURN(audioCapturer_->GetParams(params), "audioCapturer GetParams");
255 }
256 switch (tag) {
257 case Tag::AUDIO_SAMPLE_RATE: {
258 if (params.samplingRate != capturerParams_.samplingRate) {
259 MEDIA_LOG_W("samplingRate has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
260 capturerParams_.samplingRate, params.samplingRate);
261 }
262 value = params.samplingRate;
263 break;
264 }
265 case Tag::AUDIO_CHANNELS: {
266 if (params.audioChannel != capturerParams_.audioChannel) {
267 MEDIA_LOG_W("audioChannel has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
268 capturerParams_.audioChannel, params.audioChannel);
269 }
270 value = params.audioChannel;
271 break;
272 }
273 case Tag::MEDIA_BITRATE: {
274 value = bitRate_;
275 break;
276 }
277 case Tag::AUDIO_SAMPLE_FORMAT: {
278 if (params.audioSampleFormat != capturerParams_.audioSampleFormat) {
279 MEDIA_LOG_W("audioSampleFormat has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
280 capturerParams_.audioSampleFormat, params.audioSampleFormat);
281 }
282 value = params.audioSampleFormat;
283 break;
284 }
285 default:
286 MEDIA_LOG_I("Unknown key");
287 break;
288 }
289 return Status::OK;
290 }
291
AssignSampleRateIfSupported(uint32_t sampleRate)292 bool AudioCapturePlugin::AssignSampleRateIfSupported(uint32_t sampleRate)
293 {
294 AudioStandard::AudioSamplingRate aRate = AudioStandard::SAMPLE_RATE_8000;
295 if (!AuCapturePlugin::SampleRateNum2Enum(sampleRate, aRate)) {
296 MEDIA_LOG_E("sample rate " PUBLIC_LOG_U32 "not supported", sampleRate);
297 return false;
298 }
299 for (const auto& rate : AudioStandard::AudioCapturer::GetSupportedSamplingRates()) {
300 if (rate == sampleRate) {
301 capturerParams_.samplingRate = rate;
302 return true;
303 }
304 }
305 return false;
306 }
307
AssignChannelNumIfSupported(uint32_t channelNum)308 bool AudioCapturePlugin::AssignChannelNumIfSupported(uint32_t channelNum)
309 {
310 if (channelNum > 2) { // 2
311 MEDIA_LOG_E("Unsupported channelNum: " PUBLIC_LOG_U32, channelNum);
312 return false;
313 }
314 AudioStandard::AudioChannel aChannel = AudioStandard::MONO;
315 if (!AuCapturePlugin::ChannelNumNum2Enum(channelNum, aChannel)) {
316 MEDIA_LOG_E("sample rate " PUBLIC_LOG_U32 "not supported", channelNum);
317 return false;
318 }
319 for (const auto& channel : AudioStandard::AudioCapturer::GetSupportedChannels()) {
320 if (channel == channelNum) {
321 capturerParams_.audioChannel = channel;
322 return true;
323 }
324 }
325 return false;
326 }
327
AssignSampleFmtIfSupported(AudioSampleFormat sampleFormat)328 bool AudioCapturePlugin::AssignSampleFmtIfSupported(AudioSampleFormat sampleFormat)
329 {
330 AudioStandard::AudioSampleFormat aFmt = AudioStandard::AudioSampleFormat::INVALID_WIDTH;
331 if (!AuCapturePlugin::PluginFmt2SampleFmt(sampleFormat, aFmt)) {
332 MEDIA_LOG_E("sample format " PUBLIC_LOG_U8 " not supported", static_cast<uint8_t>(sampleFormat));
333 return false;
334 }
335 for (const auto& fmt : AudioStandard::AudioCapturer::GetSupportedFormats()) {
336 if (fmt == aFmt) {
337 capturerParams_.audioSampleFormat = fmt;
338 return true;
339 }
340 }
341 return false;
342 }
343
SetParameter(Tag tag,const ValueType & value)344 Status AudioCapturePlugin::SetParameter(Tag tag, const ValueType& value)
345 {
346 switch (tag) {
347 case Tag::AUDIO_SAMPLE_RATE: {
348 if (value.SameTypeWith(typeid(uint32_t))) {
349 if (!AssignSampleRateIfSupported(AnyCast<uint32_t>(value))) {
350 MEDIA_LOG_E("sampleRate is not supported by audiocapturer");
351 return Status::ERROR_INVALID_PARAMETER;
352 }
353 }
354 break;
355 }
356 case Tag::AUDIO_CHANNELS: {
357 if (value.SameTypeWith(typeid(uint32_t))) {
358 if (!AssignChannelNumIfSupported(AnyCast<uint32_t>(value))) {
359 MEDIA_LOG_E("channelNum is not supported by audiocapturer");
360 return Status::ERROR_INVALID_PARAMETER;
361 }
362 }
363 break;
364 }
365 case Tag::MEDIA_BITRATE: {
366 if (value.SameTypeWith(typeid(int64_t))) {
367 bitRate_ = Plugin::AnyCast<int64_t>(value);
368 MEDIA_LOG_D("bitRate_: " PUBLIC_LOG_D64, bitRate_);
369 }
370 break;
371 }
372 case Tag::AUDIO_SAMPLE_FORMAT: {
373 if (value.SameTypeWith(typeid(AudioSampleFormat))) {
374 if (!AssignSampleFmtIfSupported(AnyCast<AudioSampleFormat>(value))) {
375 MEDIA_LOG_E("sampleFormat is not supported by audiocapturer");
376 return Status::ERROR_INVALID_PARAMETER;
377 }
378 }
379 break;
380 }
381 case Tag::APP_TOKEN_ID: {
382 if (value.SameTypeWith(typeid(uint32_t))) {
383 appTokenId_ = Plugin::AnyCast<uint32_t>(value);
384 }
385 break;
386 }
387 case Tag::APP_UID: {
388 if (value.SameTypeWith(typeid(int32_t))) {
389 appUid_ = Plugin::AnyCast<int32_t>(value);
390 }
391 break;
392 }
393 case Tag::APP_PID: {
394 if (value.SameTypeWith(typeid(int32_t))) {
395 appPid_ = Plugin::AnyCast<int32_t>(value);
396 }
397 break;
398 }
399 default:
400 MEDIA_LOG_I("Unknown key");
401 break;
402 }
403 return Status::OK;
404 }
405
GetAllocator()406 std::shared_ptr<Allocator> AudioCapturePlugin::GetAllocator()
407 {
408 return nullptr;
409 }
410
SetCallback(Callback * cb)411 Status AudioCapturePlugin::SetCallback(Callback* cb)
412 {
413 (void)cb;
414 return Status::ERROR_UNIMPLEMENTED;
415 }
416
SetSource(std::shared_ptr<MediaSource> source)417 Status AudioCapturePlugin::SetSource(std::shared_ptr<MediaSource> source)
418 {
419 (void)source;
420 return Status::ERROR_UNIMPLEMENTED;
421 }
422
GetAudioTimeLocked(int64_t & audioTimeNs)423 Status AudioCapturePlugin::GetAudioTimeLocked(int64_t& audioTimeNs)
424 {
425 OHOS::AudioStandard::Timestamp timeStamp;
426 auto timeBase = OHOS::AudioStandard::Timestamp::Timestampbase::MONOTONIC;
427 if (!audioCapturer_->GetAudioTime(timeStamp, timeBase)) {
428 MEDIA_LOG_E("audioCapturer GetAudioTimeLocked() fail");
429 return Status::ERROR_UNKNOWN;
430 }
431 if (timeStamp.time.tv_sec < 0 || timeStamp.time.tv_nsec < 0) {
432 return Status::ERROR_INVALID_PARAMETER;
433 }
434 if ((UINT64_MAX - timeStamp.time.tv_nsec) / TIME_SEC_TO_NS < timeStamp.time.tv_sec) {
435 return Status::ERROR_INVALID_PARAMETER;
436 }
437 audioTimeNs = timeStamp.time.tv_sec * TIME_SEC_TO_NS + timeStamp.time.tv_nsec;
438 return Status::OK;
439 }
440
Read(std::shared_ptr<Buffer> & buffer,size_t expectedLen)441 Status AudioCapturePlugin::Read(std::shared_ptr<Buffer>& buffer, size_t expectedLen)
442 {
443 auto bufferMeta = buffer->GetBufferMeta();
444 if (!bufferMeta || bufferMeta->GetType() != BufferMetaType::AUDIO) {
445 return Status::ERROR_INVALID_PARAMETER;
446 }
447 std::shared_ptr<Memory> bufData;
448 if (buffer->IsEmpty()) {
449 bufData = buffer->AllocMemory(GetAllocator(), expectedLen);
450 } else {
451 bufData = buffer->GetMemory();
452 }
453 if (bufData->GetCapacity() <= 0) {
454 return Status::ERROR_NO_MEMORY;
455 }
456 auto size = 0;
457 Status ret = Status::OK;
458 int64_t timestampNs = 0;
459 {
460 OSAL::ScopedLock lock(captureMutex_);
461 if (audioCapturer_->GetStatus() != AudioStandard::CAPTURER_RUNNING) {
462 return Status::ERROR_AGAIN;
463 }
464 size = audioCapturer_->Read(*bufData->GetWritableAddr(expectedLen), expectedLen, true);
465 ret = GetAudioTimeLocked(timestampNs);
466 }
467 if (size < 0) {
468 MEDIA_LOG_E("audioCapturer Read() fail");
469 return Status::ERROR_NOT_ENOUGH_DATA;
470 }
471 if (ret != Status::OK) {
472 MEDIA_LOG_E("Get audio timestamp fail");
473 return ret;
474 }
475 Ns2HstTime(timestampNs, buffer->pts);
476 return ret;
477 }
478
GetSize(size_t & size)479 Status AudioCapturePlugin::GetSize(size_t& size)
480 {
481 if (bufferSize_ == 0) {
482 return Status::ERROR_INVALID_PARAMETER;
483 }
484 size = bufferSize_;
485 MEDIA_LOG_DD("bufferSize_: " PUBLIC_LOG_ZU, size);
486 return Status::OK;
487 }
488
GetSeekable()489 Seekable AudioCapturePlugin::GetSeekable()
490 {
491 return Seekable::UNSEEKABLE;
492 }
493
SeekTo(uint64_t offset)494 Status AudioCapturePlugin::SeekTo(uint64_t offset)
495 {
496 (void)offset;
497 return Status::ERROR_UNIMPLEMENTED;
498 }
499 } // namespace AuCapturePlugin
500 } // namespace Plugin
501 } // namespace Media
502 } // namespace OHOS
503