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