• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "LinearPosTimeModel"
17 #endif
18 
19 #include "linear_pos_time_model.h"
20 
21 #include <cinttypes>
22 
23 #include "audio_errors.h"
24 #include "audio_service_log.h"
25 #include "audio_utils.h"
26 
27 namespace OHOS {
28 namespace AudioStandard {
29 namespace {
30     static constexpr int64_t NANO_COUNT_PER_SECOND = 1000000000;
31     static constexpr int32_t MAX_SUPPORT_SAMPLE_RETE = 384000;
32     static constexpr int32_t MAX_STATISTICS_COUNT = 5;
33     static constexpr int64_t REASONABLE_DELTA_BOUND_IN_NANO = 3000000; // 3ms
34     static constexpr int64_t REASONABLE_BOUND_IN_NANO = 10000000; // 10ms
35 }
LinearPosTimeModel()36 LinearPosTimeModel::LinearPosTimeModel()
37 {
38     AUDIO_INFO_LOG("New LinearPosTimeModel");
39 }
40 
ConfigSampleRate(int32_t sampleRate)41 bool LinearPosTimeModel::ConfigSampleRate(int32_t sampleRate)
42 {
43     AUDIO_INFO_LOG("ConfigSampleRate:%{public}d", sampleRate);
44     CHECK_AND_RETURN_RET_LOG(!isConfiged, false, "SampleRate already set:%{public}d", sampleRate_);
45     sampleRate_ = sampleRate;
46     if (sampleRate_ <= 0 || sampleRate_ > MAX_SUPPORT_SAMPLE_RETE) {
47         AUDIO_ERR_LOG("Invalid sample rate!");
48         return false;
49     } else {
50         nanoTimePerFrame_ = NANO_COUNT_PER_SECOND / sampleRate;
51     }
52     isConfiged = true;
53     return true;
54 }
55 
ResetFrameStamp(uint64_t frame,int64_t nanoTime)56 void LinearPosTimeModel::ResetFrameStamp(uint64_t frame, int64_t nanoTime)
57 {
58     AUDIO_INFO_LOG("Reset frame:%{public}" PRIu64" with time:%{public}" PRId64".", frame, nanoTime);
59     posTimeVec_.clear();
60     stampFrame_ = frame;
61     stampNanoTime_ = nanoTime;
62     return;
63 }
64 
IsReasonable(uint64_t frame,int64_t nanoTime)65 bool LinearPosTimeModel::IsReasonable(uint64_t frame, int64_t nanoTime)
66 {
67     if (frame == stampFrame_ && nanoTime == stampNanoTime_) {
68         return true;
69     }
70     int64_t deltaFrame = 0;
71     int64_t reasonableDeltaTime = 0;
72     if (frame > stampFrame_) {
73         deltaFrame = static_cast<int64_t>(frame - stampFrame_);
74     } else {
75         deltaFrame = -static_cast<int64_t>(stampFrame_ - frame);
76     }
77     reasonableDeltaTime = stampNanoTime_ + deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
78 
79     // note: compare it with current time?
80     if (nanoTime <= (reasonableDeltaTime + REASONABLE_BOUND_IN_NANO) &&
81         nanoTime >= (reasonableDeltaTime - REASONABLE_BOUND_IN_NANO)) {
82         return true;
83     }
84     return false;
85 }
86 
CheckReasonable(uint64_t frame,int64_t nanoTime)87 CheckPosTimeRes LinearPosTimeModel::CheckReasonable(uint64_t frame, int64_t nanoTime)
88 {
89     posTimeVec_.push_back(std::make_pair(frame, nanoTime));
90     if (posTimeVec_.size() < MAX_STATISTICS_COUNT) {
91         return CHECK_FAILED;
92     }
93 
94     for (size_t i = 0; i < posTimeVec_.size() - 1; i++) {
95         if (!CheckPosTimeReasonable(posTimeVec_[i], posTimeVec_[i + 1])) {
96             Trace trace("LinearPosTimeModel::CheckReasonable Fail");
97             AUDIO_WARNING_LOG("Unreasonable data pos: %{public}zu", i);
98             posTimeVec_.clear();
99             return CHECK_FAILED;
100         }
101     }
102 
103     // todo: add DFX
104     Trace trace("LinearPosTimeModel::CheckReasonable Success");
105     AUDIO_ERR_LOG("Updata new frame:%{public}" PRIu64" with time:%{public}" PRId64".", frame, nanoTime);
106     return NEED_MODIFY;
107 }
108 
CheckPosTimeReasonable(std::pair<uint64_t,int64_t> & pre,std::pair<uint64_t,int64_t> & next)109 bool LinearPosTimeModel::CheckPosTimeReasonable(std::pair<uint64_t, int64_t> &pre, std::pair<uint64_t, int64_t> &next)
110 {
111     if (pre.first >= next.first) {
112         return false;
113     }
114     int64_t deltaFrame = static_cast<int64_t>(next.first - pre.first);
115     int64_t deltaFrameTime = deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
116     int64_t deltaTime = next.second - pre.second - deltaFrameTime;
117 
118     return std::abs(deltaTime) < REASONABLE_DELTA_BOUND_IN_NANO;
119 }
120 
UpdataFrameStamp(uint64_t frame,int64_t nanoTime)121 CheckPosTimeRes LinearPosTimeModel::UpdataFrameStamp(uint64_t frame, int64_t nanoTime)
122 {
123     if (IsReasonable(frame, nanoTime)) {
124         AUDIO_DEBUG_LOG("Updata frame:%{public}" PRIu64" with time:%{public}" PRId64".", frame, nanoTime);
125         stampFrame_ = frame;
126         stampNanoTime_ = nanoTime;
127         posTimeVec_.clear();
128         return CHECK_SUCCESS;
129     }
130 
131     AUDIO_WARNING_LOG("Unreasonable pos-time[ %{public}" PRIu64" %{public}" PRId64"] "
132         " stamp pos-time[ %{public}" PRIu64" %{public}" PRId64"].", frame, nanoTime, stampFrame_, stampNanoTime_);
133 
134     return CheckReasonable(frame, nanoTime);
135 }
136 
GetFrameStamp(uint64_t & frame,int64_t & nanoTime)137 bool LinearPosTimeModel::GetFrameStamp(uint64_t &frame, int64_t &nanoTime)
138 {
139     CHECK_AND_RETURN_RET_LOG(isConfiged, false, "GetFrameStamp is not configed!");
140     frame = stampFrame_;
141     nanoTime = stampNanoTime_;
142     return true;
143 }
144 
SetSpanCount(uint64_t spanCountInFrame)145 void LinearPosTimeModel::SetSpanCount(uint64_t spanCountInFrame)
146 {
147     AUDIO_INFO_LOG("New spanCountInFrame:%{public}" PRIu64".", spanCountInFrame);
148     spanCountInFrame_ = spanCountInFrame;
149     return;
150 }
151 
GetTimeOfPos(uint64_t posInFrame)152 int64_t LinearPosTimeModel::GetTimeOfPos(uint64_t posInFrame)
153 {
154     int64_t deltaFrame = 0;
155     int64_t invalidTime = -1;
156     CHECK_AND_RETURN_RET_LOG(isConfiged, invalidTime, "SampleRate is not configed!");
157     if (posInFrame >= stampFrame_) {
158         if (posInFrame - stampFrame_ >= (uint64_t)sampleRate_) {
159             AUDIO_WARNING_LOG("posInFrame %{public}" PRIu64" is too"
160                 " large, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
161         }
162         deltaFrame = static_cast<int64_t>(posInFrame - stampFrame_);
163         return stampNanoTime_ + deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
164     } else {
165         if (stampFrame_ - posInFrame >= (uint64_t)sampleRate_) {
166             AUDIO_WARNING_LOG("posInFrame %{public}" PRIu64" is too"
167                 " small, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
168         }
169         deltaFrame = static_cast<int64_t>(stampFrame_ - posInFrame);
170         return stampNanoTime_ - deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
171     }
172     return invalidTime;
173 }
174 } // namespace AudioStandard
175 } // namespace OHOS
176 
177