• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 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 
16 #include "audio_capturer_session.h"
17 
18 #include <algorithm>
19 #include <functional>
20 #include <thread>
21 #include "audio_record.h"
22 #include "audio_session_manager.h"
23 #include "audio_deferred_process.h"
24 #include "camera_log.h"
25 #include "datetime_ex.h"
26 #include "ipc_skeleton.h"
27 #include "sample_info.h"
28 #include "token_setproc.h"
29 
30 namespace OHOS {
31 namespace CameraStandard {
32 
AudioCapturerSession()33 AudioCapturerSession::AudioCapturerSession()
34     : audioBufferQueue_("audioBuffer", DEFAULT_AUDIO_CACHE_NUMBER)
35 {
36     AudioStreamInfo streamInfo;
37     streamInfo.samplingRate = static_cast<AudioSamplingRate>(AudioSamplingRate::SAMPLE_RATE_48000);
38     streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
39     streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
40     streamInfo.channels = getMicNum();
41     deferredInputOptions_ = streamInfo;
42     AudioStreamInfo outputOptions;
43     outputOptions.samplingRate = static_cast<AudioSamplingRate>(AudioSamplingRate::SAMPLE_RATE_32000);
44     outputOptions.encoding = AudioEncodingType::ENCODING_PCM;
45     outputOptions.format = AudioSampleFormat::SAMPLE_S16LE;
46     outputOptions.channels = AudioChannel::MONO;
47     deferredOutputOptions_ = outputOptions;
48 }
49 
getMicNum()50 AudioChannel AudioCapturerSession::getMicNum()
51 {
52     MEDIA_INFO_LOG("AudioCapturerSession::getMicNum");
53     std::string mainKey = "device_status";
54     std::vector<std::string> subKeys = {"hardware_info#mic_num"};
55     std::vector<std::pair<std::string, std::string>> result = {};
56     AudioSystemManager* audioSystemMgr = AudioSystemManager::GetInstance();
57     if (audioSystemMgr == nullptr) {
58         MEDIA_WARNING_LOG("AudioCapturerSession::getMicNum GetAudioSystemManagerInstance err");
59         return AudioChannel::STEREO;
60     }
61     int32_t ret = audioSystemMgr->GetExtraParameters(mainKey, subKeys, result);
62     if (ret != 0) {
63         MEDIA_WARNING_LOG("AudioCapturerSession::getMicNum GetExtraParameters err");
64         return AudioChannel::STEREO;
65     }
66     if (result.empty() || result[0].second.empty() || result[0].first.empty()) {
67         MEDIA_WARNING_LOG("AudioCapturerSession::getMicNum result empty");
68         return AudioChannel::STEREO;
69     }
70     for (auto i: result[0].second) {
71         if (!std::isdigit(i)) {
72             MEDIA_WARNING_LOG("AudioCapturerSession::getMicNum result illegal");
73             return AudioChannel::STEREO;
74         }
75     }
76     int32_t micNum = std::stoi(result[0].second);
77     MEDIA_INFO_LOG("AudioCapturerSession::getMicNum %{public}d + %{public}d", micNum, micNum % I32_TWO);
78     // odd channel should + 1
79     return static_cast<AudioChannel>(micNum + (micNum % I32_TWO));
80 }
81 
CreateAudioCapturer()82 bool AudioCapturerSession::CreateAudioCapturer()
83 {
84     auto callingTokenID = IPCSkeleton::GetCallingTokenID();
85     SetFirstCallerTokenID(callingTokenID);
86     AudioCapturerOptions capturerOptions;
87     capturerOptions.streamInfo = deferredInputOptions_;
88     capturerOptions.capturerInfo.sourceType = SourceType::SOURCE_TYPE_UNPROCESSED;
89     capturerOptions.capturerInfo.capturerFlags = 0;
90     audioCapturer_ = AudioCapturer::Create(capturerOptions);
91     if (audioCapturer_ == nullptr) {
92         MEDIA_ERR_LOG("AudioCapturerSession::Create AudioCapturer failed");
93         return false;
94     }
95     AudioSessionStrategy sessionStrategy;
96     sessionStrategy.concurrencyMode = AudioConcurrencyMode::MIX_WITH_OTHERS;
97     AudioSessionManager::GetInstance()->ActivateAudioSession(sessionStrategy);
98     return true;
99 }
100 
~AudioCapturerSession()101 AudioCapturerSession::~AudioCapturerSession()
102 {
103     MEDIA_INFO_LOG("~AudioCapturerSession enter");
104     audioBufferQueue_.SetActive(false);
105     audioBufferQueue_.Clear();
106     Stop();
107 }
108 
StartAudioCapture()109 bool AudioCapturerSession::StartAudioCapture()
110 {
111     MEDIA_INFO_LOG("Starting moving photo audio stream");
112     if (audioCapturer_ == nullptr && !CreateAudioCapturer()) {
113         MEDIA_INFO_LOG("audioCapturer is not create");
114         return false;
115     }
116     if (!audioCapturer_->Start()) {
117         MEDIA_INFO_LOG("Start stream failed");
118         audioCapturer_->Release();
119         return false;
120     }
121     if (audioThread_ && audioThread_->joinable()) {
122         MEDIA_INFO_LOG("audioThread_ is already start, reset");
123         startAudioCapture_ = false;
124         audioThread_->join();
125         audioThread_.reset();
126     }
127     startAudioCapture_ = true;
128     audioThread_ = std::make_unique<std::thread>([this]() { this->ProcessAudioBuffer(); });
129     CHECK_ERROR_RETURN_RET_LOG(audioThread_ == nullptr, false, "Create auido thread failed");
130     return true;
131 }
132 
GetAudioRecords(int64_t startTime,int64_t endTime,vector<sptr<AudioRecord>> & audioRecords)133 void AudioCapturerSession::GetAudioRecords(int64_t startTime, int64_t endTime, vector<sptr<AudioRecord>> &audioRecords)
134 {
135     vector<sptr<AudioRecord>> allRecords = audioBufferQueue_.GetAllElements();
136     for (const auto& record : allRecords) {
137         CHECK_EXECUTE(record->GetTimeStamp() >= startTime && record->GetTimeStamp() < endTime,
138             audioRecords.push_back(record));
139     }
140 }
141 
ProcessAudioBuffer()142 void AudioCapturerSession::ProcessAudioBuffer()
143 {
144     CHECK_ERROR_RETURN_LOG(audioCapturer_ == nullptr, "AudioCapturer_ is not init");
145     size_t bufferLen = static_cast<size_t>(deferredInputOptions_.samplingRate / AudioDeferredProcess::ONE_THOUSAND *
146         deferredInputOptions_.channels * AudioDeferredProcess::DURATION_EACH_AUDIO_FRAME * sizeof(short));
147     while (true) {
148         CHECK_WARNING_BREAK_LOG(!startAudioCapture_, "Audio capture work done, thread out");
149         auto buffer = std::make_unique<uint8_t[]>(bufferLen);
150         CHECK_ERROR_RETURN_LOG(buffer == nullptr, "Failed to allocate buffer");
151         size_t bytesRead = 0;
152         while (bytesRead < bufferLen) {
153             MEDIA_DEBUG_LOG("ProcessAudioBuffer loop");
154             CHECK_WARNING_BREAK_LOG(!startAudioCapture_, "ProcessAudioBuffer loop, break out");
155             int32_t len = audioCapturer_->Read(*(buffer.get() + bytesRead), bufferLen - bytesRead, true);
156             if (len >= 0) {
157                 bytesRead += static_cast<size_t>(len);
158             } else {
159                 MEDIA_ERR_LOG("ProcessAudioBuffer loop read error: %{public}d", len);
160                 startAudioCapture_ = false;
161                 break;
162             }
163         }
164         if (!startAudioCapture_) {
165             buffer.reset();
166             MEDIA_INFO_LOG("Audio capture work done, thread out");
167             break;
168         }
169         if (audioBufferQueue_.Full()) {
170             sptr<AudioRecord> audioRecord = audioBufferQueue_.Pop();
171             audioRecord->ReleaseAudioBuffer();
172             MEDIA_DEBUG_LOG("audio release popBuffer");
173         }
174         int64_t timeOffset = 32;
175         sptr<AudioRecord> audioRecord = new AudioRecord(GetTickCount() - timeOffset);
176         audioRecord->SetAudioBuffer(buffer.get());
177         MEDIA_DEBUG_LOG("audio push buffer frameId: %{public}s", audioRecord->GetFrameId().c_str());
178         buffer.release();
179         audioBufferQueue_.Push(audioRecord);
180     }
181 }
182 
Stop()183 void AudioCapturerSession::Stop()
184 {
185     CAMERA_SYNC_TRACE;
186     MEDIA_INFO_LOG("Audio capture stop enter");
187     startAudioCapture_ = false;
188     if (audioThread_ && audioThread_->joinable()) {
189         audioThread_->join();
190         audioThread_.reset();
191     }
192     AudioSessionManager::GetInstance()->DeactivateAudioSession();
193     MEDIA_INFO_LOG("Audio capture stop out");
194     Release();
195 }
196 
Release()197 void AudioCapturerSession::Release()
198 {
199     CAMERA_SYNC_TRACE;
200     if (audioCapturer_ != nullptr) {
201         MEDIA_INFO_LOG("Audio capture Release enter");
202         audioCapturer_->Release();
203     }
204     audioCapturer_ = nullptr;
205     MEDIA_INFO_LOG("Audio capture released");
206 }
207 
208 } // namespace CameraStandard
209 } // namespace OHOS
210