• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &reg)
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