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> &reg)
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