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