• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioEndpointInner"
17 #endif
18 
19 #include "audio_endpoint.h"
20 #include "audio_endpoint_private.h"
21 
22 #include <string>
23 #include <memory>
24 
25 #include "audio_service_log.h"
26 #include "manager/hdi_adapter_manager.h"
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 namespace {
31     static constexpr int64_t PLAYBACK_DELAY_STOP_HDI_TIME_NS = 3000000000; // 3s = 3 * 1000 * 1000 * 1000ns
32     static constexpr int64_t RECORDER_DELAY_STOP_HDI_TIME_NS = 200000000; // 200ms = 200 * 1000 * 1000ns
33     static constexpr int64_t DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS = 4000000000; // 4s = 4 * 1000 * 1000 * 1000ns
34 }
InitLatencyMeasurement()35 void AudioEndpointInner::InitLatencyMeasurement()
36 {
37     if (!AudioLatencyMeasurement::CheckIfEnabled()) {
38         return;
39     }
40     signalDetectAgent_ = std::make_shared<SignalDetectAgent>();
41     CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
42     signalDetectAgent_->sampleFormat_ = SAMPLE_S16LE;
43     signalDetectAgent_->formatByteSize_ = GetFormatByteSize(SAMPLE_S16LE);
44     latencyMeasEnabled_ = true;
45     signalDetected_ = false;
46 }
47 
DeinitLatencyMeasurement()48 void AudioEndpointInner::DeinitLatencyMeasurement()
49 {
50     signalDetectAgent_ = nullptr;
51     latencyMeasEnabled_ = false;
52 }
53 
CheckPlaySignal(uint8_t * buffer,size_t bufferSize)54 void AudioEndpointInner::CheckPlaySignal(uint8_t *buffer, size_t bufferSize)
55 {
56     if (!latencyMeasEnabled_) {
57         return;
58     }
59     CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
60     size_t byteSize = static_cast<size_t>(GetFormatByteSize(dstStreamInfo_.format));
61     size_t newlyCheckedTime = bufferSize / (dstStreamInfo_.samplingRate /
62         MILLISECOND_PER_SECOND) / (byteSize * sizeof(uint8_t) * dstStreamInfo_.channels);
63     detectedTime_ += newlyCheckedTime;
64     if (detectedTime_ >= MILLISECOND_PER_SECOND && signalDetectAgent_->signalDetected_ &&
65         !signalDetectAgent_->dspTimestampGot_) {
66             AudioParamKey key = NONE;
67             std::string condition = "debug_audio_latency_measurement";
68             std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
69             CHECK_AND_RETURN_LOG(sink != nullptr, "sink is nullptr!");
70             std::string dspTime = sink->GetAudioParameter(key, condition);
71             LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
72             LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(true,
73                 signalDetectAgent_->lastPeakBufferTime_);
74             AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
75             LatencyMonitor::GetInstance().ShowTimestamp(true);
76             signalDetectAgent_->dspTimestampGot_ = true;
77             signalDetectAgent_->signalDetected_ = false;
78     }
79     signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
80     if (signalDetected_) {
81         AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
82         detectedTime_ = 0;
83     }
84 }
85 
CheckRecordSignal(uint8_t * buffer,size_t bufferSize)86 void AudioEndpointInner::CheckRecordSignal(uint8_t *buffer, size_t bufferSize)
87 {
88     if (!latencyMeasEnabled_) {
89         return;
90     }
91     CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
92     signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
93     if (signalDetected_) {
94         AudioParamKey key = NONE;
95         std::string condition = "debug_audio_latency_measurement";
96         std::shared_ptr<IAudioCaptureSource> source = HdiAdapterManager::GetInstance().GetCaptureSource(fastCaptureId_);
97         CHECK_AND_RETURN_LOG(source != nullptr, "source is nullptr!");
98         std::string dspTime = source->GetAudioParameter(key, condition);
99         LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(false,
100             signalDetectAgent_->lastPeakBufferTime_);
101         LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
102         AUDIO_INFO_LOG("LatencyMeas fastSource signal detected");
103         signalDetected_ = false;
104     }
105 }
106 
ZeroVolumeCheck(const int32_t vol)107 void AudioEndpointInner::ZeroVolumeCheck(const int32_t vol)
108 {
109     if (fastSinkType_ == FAST_SINK_TYPE_BLUETOOTH) {
110         return;
111     }
112     if (std::abs(vol - 0) <= std::numeric_limits<float>::epsilon()) {
113         if (zeroVolumeState_ == INACTIVE) {
114             zeroVolumeStartTime_ = ClockTime::GetCurNano();
115             zeroVolumeState_ = IN_TIMING;
116             AUDIO_INFO_LOG("Begin zero volume, will stop fastSink in 4s.");
117             return;
118         }
119 
120         if (zeroVolumeState_ == IN_TIMING &&
121             ClockTime::GetCurNano() - zeroVolumeStartTime_ > DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS) {
122             zeroVolumeState_ = ACTIVE;
123             HandleZeroVolumeStopEvent();
124         }
125     } else {
126         if (zeroVolumeState_ == INACTIVE) {
127             return;
128         }
129         if (zeroVolumeState_ == ACTIVE) {
130             HandleZeroVolumeStartEvent();
131         }
132         ResetZeroVolumeState();
133     }
134 }
135 
HandleZeroVolumeStartEvent()136 void AudioEndpointInner::HandleZeroVolumeStartEvent()
137 {
138     if (!isStarted_) {
139         std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
140         if (sink == nullptr || sink->Start() != SUCCESS) {
141             AUDIO_INFO_LOG("Volume from zero to none-zero, start fastSink failed.");
142             isStarted_ = false;
143         } else {
144             AUDIO_INFO_LOG("Volume from zero to none-zero, start fastSink success.");
145             isStarted_ = true;
146             needReSyncPosition_ = true;
147         }
148     } else {
149         AUDIO_INFO_LOG("fastSink already started");
150     }
151 }
152 
HandleZeroVolumeStopEvent()153 void AudioEndpointInner::HandleZeroVolumeStopEvent()
154 {
155     if (isStarted_) {
156         std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
157         if (sink != nullptr && sink->Stop() == SUCCESS) {
158             AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop fastSink success.");
159             isStarted_ = false;
160         } else {
161             AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop fastSink failed.");
162             isStarted_ = true;
163         }
164     } else {
165         AUDIO_INFO_LOG("fastSink already stopped");
166     }
167 }
168 
ResetZeroVolumeState()169 void AudioEndpointInner::ResetZeroVolumeState()
170 {
171     zeroVolumeStartTime_ = INT64_MAX;
172     zeroVolumeState_ = INACTIVE;
173 }
174 
CheckStandBy()175 void AudioEndpointInner::CheckStandBy()
176 {
177     if (endpointStatus_ == RUNNING) {
178         endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
179     }
180 
181     if (endpointStatus_ == RUNNING) {
182         return;
183     }
184 
185     AUDIO_INFO_LOG("endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str());
186     if (endpointStatus_ == IDEL) {
187         // delay call sink stop when no process running
188         AUDIO_INFO_LOG("status is IDEL, need delay call stop");
189         delayStopTime_ = ClockTime::GetCurNano() + ((clientConfig_.audioMode == AUDIO_MODE_PLAYBACK)
190             ? PLAYBACK_DELAY_STOP_HDI_TIME_NS : RECORDER_DELAY_STOP_HDI_TIME_NS);
191     }
192 }
193 
Dump(std::string & dumpString)194 void AudioEndpointInner::Dump(std::string &dumpString)
195 {
196     // dump endpoint stream info
197     dumpString += "Endpoint stream info:\n";
198     AppendFormat(dumpString, "  - samplingRate: %d\n", dstStreamInfo_.samplingRate);
199     AppendFormat(dumpString, "  - channels: %u\n", dstStreamInfo_.channels);
200     AppendFormat(dumpString, "  - format: %u\n", dstStreamInfo_.format);
201     AppendFormat(dumpString, "  - sink type: %d\n", fastSinkType_);
202     AppendFormat(dumpString, "  - source type: %d\n", fastSourceType_);
203 
204     // dump status info
205     AppendFormat(dumpString, "  - Current endpoint status: %s\n", GetStatusStr(endpointStatus_).c_str());
206     if (dstAudioBuffer_ != nullptr) {
207         AppendFormat(dumpString, "  - Currend hdi read position: %u\n", dstAudioBuffer_->GetCurReadFrame());
208         AppendFormat(dumpString, "  - Currend hdi write position: %u\n", dstAudioBuffer_->GetCurWriteFrame());
209     }
210 
211     // dump linked process info
212     std::lock_guard<std::mutex> lock(listLock_);
213     AppendFormat(dumpString, "  - linked process:: %zu\n", processBufferList_.size());
214     for (auto item : processBufferList_) {
215         AppendFormat(dumpString, "  - process read position: %u\n", item->GetCurReadFrame());
216         AppendFormat(dumpString, "  - process write position: %u\n", item->GetCurWriteFrame());
217     }
218     dumpString += "\n";
219 }
220 
221 } // namespace AudioStandard
222 } // namespace OHOS
223