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
16 #include "linear_pos_time_model.h"
17
18 #include <cinttypes>
19
20 #include "audio_errors.h"
21 #include "audio_log.h"
22
23 namespace OHOS {
24 namespace AudioStandard {
25 namespace {
26 static constexpr int64_t NANO_COUNT_PER_SECOND = 1000000000;
27 static constexpr int32_t MAX_SUPPORT_SAMPLE_RETE = 384000;
28 static constexpr int64_t REASONABLE_BOUND_IN_NANO = 10000000; // 10ms
29 }
LinearPosTimeModel()30 LinearPosTimeModel::LinearPosTimeModel()
31 {
32 AUDIO_INFO_LOG("New LinearPosTimeModel");
33 }
34
ConfigSampleRate(int32_t sampleRate)35 bool LinearPosTimeModel::ConfigSampleRate(int32_t sampleRate)
36 {
37 AUDIO_INFO_LOG("ConfigSampleRate:%{public}d", sampleRate);
38 if (isConfiged) {
39 AUDIO_ERR_LOG("SampleRate already set:%{public}d", sampleRate_);
40 return false;
41 }
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_INFO_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 if (!isConfiged) {
100 AUDIO_ERR_LOG("GetFrameStamp is not configed!");
101 return false;
102 }
103 frame = stampFrame_;
104 nanoTime = stampNanoTime_;
105 return true;
106 }
107
SetSpanCount(uint64_t spanCountInFrame)108 void LinearPosTimeModel::SetSpanCount(uint64_t spanCountInFrame)
109 {
110 AUDIO_INFO_LOG("New spanCountInFrame:%{public}" PRIu64".", spanCountInFrame);
111 spanCountInFrame_ = spanCountInFrame;
112 return;
113 }
114
GetTimeOfPos(uint64_t posInFrame)115 int64_t LinearPosTimeModel::GetTimeOfPos(uint64_t posInFrame)
116 {
117 int64_t deltaFrame = 0;
118 int64_t invalidTime = -1;
119 if (!isConfiged) {
120 AUDIO_ERR_LOG("SampleRate is not configed!");
121 return invalidTime;
122 }
123 if (posInFrame >= stampFrame_) {
124 CHECK_AND_BREAK_LOG((posInFrame - stampFrame_ < (uint64_t)sampleRate_), "posInFrame %{public}" PRIu64" is too"
125 " large, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
126 deltaFrame = posInFrame - stampFrame_;
127 return stampNanoTime_ + deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
128 } else {
129 CHECK_AND_BREAK_LOG((stampFrame_ - posInFrame < (uint64_t)sampleRate_), "posInFrame %{public}" PRIu64" is too"
130 " small, stampFrame: %{public}" PRIu64"", posInFrame, stampFrame_);
131 deltaFrame = stampFrame_ - posInFrame;
132 return stampNanoTime_ - deltaFrame * NANO_COUNT_PER_SECOND / (int64_t)sampleRate_;
133 }
134 return invalidTime;
135 }
136 } // namespace AudioStandard
137 } // namespace OHOS
138
139