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 "foundation/utils/constants.h"
26 #include "plugin/common/plugin_time.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 }
__anon984b9c920302null104 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(const ValueType & value)292 bool AudioCapturePlugin::AssignSampleRateIfSupported(const ValueType& value)
293 {
294 FALSE_RETURN_V_MSG_E(Plugin::Any::IsSameTypeWith<uint32_t>(value), false, "Check sample rate value fail.");
295 uint32_t sampleRate = AnyCast<uint32_t>(value);
296 AudioStandard::AudioSamplingRate aRate = AudioStandard::SAMPLE_RATE_8000;
297 FALSE_RETURN_V_MSG_E(AuCapturePlugin::SampleRateNum2Enum(sampleRate, aRate), false, "sample rate " PUBLIC_LOG_U32
298 "not supported", sampleRate);
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(const ValueType & value)308 bool AudioCapturePlugin::AssignChannelNumIfSupported(const ValueType& value)
309 {
310 FALSE_RETURN_V_MSG_E(Plugin::Any::IsSameTypeWith<uint32_t>(value), false, "Check channel num value fail.");
311 uint32_t channelNum = AnyCast<uint32_t>(value);
312 if (channelNum > 2) { // 2
313 MEDIA_LOG_E("Unsupported channelNum: " PUBLIC_LOG_U32, channelNum);
314 return false;
315 }
316 AudioStandard::AudioChannel aChannel = AudioStandard::MONO;
317 FALSE_RETURN_V_MSG_E(AuCapturePlugin::ChannelNumNum2Enum(channelNum, aChannel), false, "Channel num "
318 PUBLIC_LOG_U32 "not supported", channelNum);
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(const ValueType & value)328 bool AudioCapturePlugin::AssignSampleFmtIfSupported(const ValueType& value)
329 {
330 FALSE_RETURN_V_MSG_E(Plugin::Any::IsSameTypeWith<AudioSampleFormat>(value), false,
331 "Check sample format value fail.");
332 AudioSampleFormat sampleFormat = AnyCast<AudioSampleFormat>(value);
333 AudioStandard::AudioSampleFormat aFmt = AudioStandard::AudioSampleFormat::INVALID_WIDTH;
334 FALSE_RETURN_V_MSG_E(AuCapturePlugin::PluginFmt2SampleFmt(sampleFormat, aFmt), false,
335 "sample format " PUBLIC_LOG_U8 " not supported", static_cast<uint8_t>(sampleFormat));
336 for (const auto& fmt : AudioStandard::AudioCapturer::GetSupportedFormats()) {
337 if (fmt == aFmt) {
338 capturerParams_.audioSampleFormat = fmt;
339 return true;
340 }
341 }
342 return false;
343 }
344
SetParameter(Tag tag,const ValueType & value)345 Status AudioCapturePlugin::SetParameter(Tag tag, const ValueType& value)
346 {
347 switch (tag) {
348 case Tag::AUDIO_SAMPLE_RATE: {
349 FALSE_RETURN_V_MSG_E(AssignSampleRateIfSupported(value), Status::ERROR_INVALID_PARAMETER,
350 "SampleRate is unsupported by audiocapturer");
351 break;
352 }
353 case Tag::AUDIO_CHANNELS: {
354 FALSE_RETURN_V_MSG_E(AssignChannelNumIfSupported(value), Status::ERROR_INVALID_PARAMETER,
355 "ChannelNum is unsupported by audiocapturer");
356 break;
357 }
358 case Tag::MEDIA_BITRATE: {
359 if (Any::IsSameTypeWith<int64_t>(value)) {
360 bitRate_ = Plugin::AnyCast<int64_t>(value);
361 MEDIA_LOG_D("BitRate_: " PUBLIC_LOG_D64, bitRate_);
362 }
363 break;
364 }
365 case Tag::AUDIO_SAMPLE_FORMAT: {
366 FALSE_RETURN_V_MSG_E(AssignSampleFmtIfSupported(value), Status::ERROR_INVALID_PARAMETER,
367 "SampleFormat is unsupported by audiocapturer");
368 break;
369 }
370 case Tag::APP_TOKEN_ID: {
371 if (Any::IsSameTypeWith<uint32_t>(value)) {
372 appTokenId_ = Plugin::AnyCast<uint32_t>(value);
373 }
374 break;
375 }
376 case Tag::APP_UID: {
377 if (Any::IsSameTypeWith<uint32_t>(value)) {
378 appUid_ = Plugin::AnyCast<int32_t>(value);
379 }
380 break;
381 }
382 case Tag::APP_PID: {
383 if (Any::IsSameTypeWith<uint32_t>(value)) {
384 appPid_ = Plugin::AnyCast<int32_t>(value);
385 }
386 break;
387 }
388 default:
389 MEDIA_LOG_I("Unknown key");
390 break;
391 }
392 return Status::OK;
393 }
394
GetAllocator()395 std::shared_ptr<Allocator> AudioCapturePlugin::GetAllocator()
396 {
397 return nullptr;
398 }
399
SetCallback(Callback * cb)400 Status AudioCapturePlugin::SetCallback(Callback* cb)
401 {
402 (void)cb;
403 return Status::ERROR_UNIMPLEMENTED;
404 }
405
SetSource(std::shared_ptr<MediaSource> source)406 Status AudioCapturePlugin::SetSource(std::shared_ptr<MediaSource> source)
407 {
408 (void)source;
409 return Status::ERROR_UNIMPLEMENTED;
410 }
411
GetAudioTimeLocked(int64_t & audioTimeNs)412 Status AudioCapturePlugin::GetAudioTimeLocked(int64_t& audioTimeNs)
413 {
414 OHOS::AudioStandard::Timestamp timeStamp;
415 auto timeBase = OHOS::AudioStandard::Timestamp::Timestampbase::MONOTONIC;
416 if (!audioCapturer_->GetAudioTime(timeStamp, timeBase)) {
417 MEDIA_LOG_E("audioCapturer GetAudioTimeLocked() fail");
418 return Status::ERROR_UNKNOWN;
419 }
420 if (timeStamp.time.tv_sec < 0 || timeStamp.time.tv_nsec < 0) {
421 return Status::ERROR_INVALID_PARAMETER;
422 }
423 if ((UINT64_MAX - timeStamp.time.tv_nsec) / TIME_SEC_TO_NS < static_cast<uint64_t>(timeStamp.time.tv_sec)) {
424 return Status::ERROR_INVALID_PARAMETER;
425 }
426 audioTimeNs = timeStamp.time.tv_sec * TIME_SEC_TO_NS + timeStamp.time.tv_nsec;
427 return Status::OK;
428 }
429
Read(std::shared_ptr<Buffer> & buffer,size_t expectedLen)430 Status AudioCapturePlugin::Read(std::shared_ptr<Buffer>& buffer, size_t expectedLen)
431 {
432 auto bufferMeta = buffer->GetBufferMeta();
433 if (!bufferMeta || bufferMeta->GetType() != BufferMetaType::AUDIO) {
434 return Status::ERROR_INVALID_PARAMETER;
435 }
436 std::shared_ptr<Memory> bufData;
437 if (buffer->IsEmpty()) {
438 bufData = buffer->AllocMemory(GetAllocator(), expectedLen);
439 } else {
440 bufData = buffer->GetMemory();
441 }
442 if (bufData->GetCapacity() <= 0) {
443 return Status::ERROR_NO_MEMORY;
444 }
445 auto size = 0;
446 Status ret = Status::OK;
447 int64_t timestampNs = 0;
448 {
449 OSAL::ScopedLock lock(captureMutex_);
450 if (audioCapturer_->GetStatus() != AudioStandard::CAPTURER_RUNNING) {
451 return Status::ERROR_AGAIN;
452 }
453 size = audioCapturer_->Read(*bufData->GetWritableAddr(expectedLen), expectedLen, true);
454 ret = GetAudioTimeLocked(timestampNs);
455 }
456 if (size < 0) {
457 MEDIA_LOG_E("audioCapturer Read() fail");
458 return Status::ERROR_NOT_ENOUGH_DATA;
459 }
460 if (ret != Status::OK) {
461 MEDIA_LOG_E("Get audio timestamp fail");
462 return ret;
463 }
464 Ns2HstTime(timestampNs, buffer->pts);
465 return ret;
466 }
467
GetSize(uint64_t & size)468 Status AudioCapturePlugin::GetSize(uint64_t& size)
469 {
470 if (bufferSize_ == 0) {
471 return Status::ERROR_INVALID_PARAMETER;
472 }
473 size = bufferSize_;
474 MEDIA_LOG_DD("BufferSize_: " PUBLIC_LOG_U64, size);
475 return Status::OK;
476 }
477
GetSeekable()478 Seekable AudioCapturePlugin::GetSeekable()
479 {
480 return Seekable::UNSEEKABLE;
481 }
482
SeekTo(uint64_t offset)483 Status AudioCapturePlugin::SeekTo(uint64_t offset)
484 {
485 (void)offset;
486 return Status::ERROR_UNIMPLEMENTED;
487 }
488 } // namespace AuCapturePlugin
489 } // namespace Plugin
490 } // namespace Media
491 } // namespace OHOS
492