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