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 
26 namespace OHOS {
27 namespace AudioStandard {
28 namespace {
29     static constexpr int64_t NANO_COUNT_PER_SECOND = 1000000000;
30     static constexpr int32_t MAX_SUPPORT_SAMPLE_RETE = 384000;
31     static constexpr int64_t REASONABLE_BOUND_IN_NANO = 10000000; // 10ms
32 }
LinearPosTimeModel()33 LinearPosTimeModel::LinearPosTimeModel()
34 {
35     AUDIO_INFO_LOG("New LinearPosTimeModel");
36 }
37 
ConfigSampleRate(int32_t sampleRate)38 bool LinearPosTimeModel::ConfigSampleRate(int32_t sampleRate)
39 {
40     AUDIO_INFO_LOG("ConfigSampleRate:%{public}d", sampleRate);
41     CHECK_AND_RETURN_RET_LOG(!isConfiged, false, "SampleRate already set:%{public}d", sampleRate_);
42     sampleRate_ = sampleRate;
43     if (sampleRate_ <= 0 || sampleRate_ > MAX_SUPPORT_SAMPLE_RETE) {
44         AUDIO_ERR_LOG("Invalid sample rate!");
45         return false;
46     } else {
47         nanoTimePerFrame_ = NANO_COUNT_PER_SECOND / sampleRate;
48     }
49     isConfiged = true;
50     return true;
51 }
52 
ResetFrameStamp(uint64_t frame,int64_t nanoTime)53 void LinearPosTimeModel::ResetFrameStamp(uint64_t frame, int64_t nanoTime)
54 {
55     AUDIO_INFO_LOG("Reset frame:%{public}" PRIu64" with time:%{public}" PRId64".", frame, nanoTime);
56     stampFrame_ = frame;
57     stampNanoTime_ = nanoTime;
58     return;
59 }
60 
IsReasonable(uint64_t frame,int64_t nanoTime)61 bool LinearPosTimeModel::IsReasonable(uint64_t frame, int64_t nanoTime)
62 {
63     if (frame == stampFrame_ && nanoTime == stampNanoTime_) {
64         return true;
65     }
66     int64_t deltaFrame = 0;
67     int64_t reasonableDeltaTime = 0;
68     if (frame > stampFrame_) {
69         deltaFrame = static_cast<int64_t>(frame - stampFrame_);
70     } else {
71         deltaFrame = -static_cast<int64_t>(stampFrame_ - frame);
72     }
73     reasonableDeltaTime = stampNanoTime_ + deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
74 
75     // note: compare it with current time?
76     if (nanoTime <= (reasonableDeltaTime + REASONABLE_BOUND_IN_NANO) &&
77         nanoTime >= (reasonableDeltaTime - REASONABLE_BOUND_IN_NANO)) {
78         return true;
79     }
80     return false;
81 }
82 
UpdataFrameStamp(uint64_t frame,int64_t nanoTime)83 bool LinearPosTimeModel::UpdataFrameStamp(uint64_t frame, int64_t nanoTime)
84 {
85     if (IsReasonable(frame, nanoTime)) {
86         AUDIO_DEBUG_LOG("Updata frame:%{public}" PRIu64" with time:%{public}" PRId64".", frame, nanoTime);
87         stampFrame_ = frame;
88         stampNanoTime_ = nanoTime;
89         return true;
90     }
91     AUDIO_WARNING_LOG("Unreasonable pos-time[ %{public}" PRIu64" %{public}" PRId64"] "
92         " stamp pos-time[ %{public}" PRIu64" %{public}" PRId64"].", frame, nanoTime, stampFrame_, stampNanoTime_);
93     // note: keep it in queue.
94     return false;
95 }
96 
GetFrameStamp(uint64_t & frame,int64_t & nanoTime)97 bool LinearPosTimeModel::GetFrameStamp(uint64_t &frame, int64_t &nanoTime)
98 {
99     CHECK_AND_RETURN_RET_LOG(isConfiged, false, "GetFrameStamp is not configed!");
100     frame = stampFrame_;
101     nanoTime = stampNanoTime_;
102     return true;
103 }
104 
SetSpanCount(uint64_t spanCountInFrame)105 void LinearPosTimeModel::SetSpanCount(uint64_t spanCountInFrame)
106 {
107     AUDIO_INFO_LOG("New spanCountInFrame:%{public}" PRIu64".", spanCountInFrame);
108     spanCountInFrame_ = spanCountInFrame;
109     return;
110 }
111 
GetTimeOfPos(uint64_t posInFrame)112 int64_t LinearPosTimeModel::GetTimeOfPos(uint64_t posInFrame)
113 {
114     int64_t deltaFrame = 0;
115     int64_t invalidTime = -1;
116     CHECK_AND_RETURN_RET_LOG(isConfiged, invalidTime, "SampleRate is not configed!");
117     if (posInFrame >= stampFrame_) {
118         if (posInFrame - stampFrame_ >= (uint64_t)sampleRate_) {
119             AUDIO_WARNING_LOG("posInFrame %{public}" PRIu64" is too"
120                 " large, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
121         }
122         deltaFrame = static_cast<int64_t>(posInFrame - stampFrame_);
123         return stampNanoTime_ + deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
124     } else {
125         if (stampFrame_ - posInFrame >= (uint64_t)sampleRate_) {
126             AUDIO_WARNING_LOG("posInFrame %{public}" PRIu64" is too"
127                 " small, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
128         }
129         deltaFrame = static_cast<int64_t>(stampFrame_ - posInFrame);
130         return stampNanoTime_ - deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
131     }
132     return invalidTime;
133 }
134 } // namespace AudioStandard
135 } // namespace OHOS
136 
137