1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/main/source/codec_timer.h"
12
13 #include <assert.h>
14
15 namespace webrtc
16 {
17
18 // The first kIgnoredSampleCount samples will be ignored.
19 static const int32_t kIgnoredSampleCount = 5;
20
VCMCodecTimer()21 VCMCodecTimer::VCMCodecTimer()
22 :
23 _filteredMax(0),
24 _ignoredSampleCount(0),
25 _shortMax(0),
26 _history()
27 {
28 Reset();
29 }
30
StopTimer(int64_t startTimeMs,int64_t nowMs)31 int32_t VCMCodecTimer::StopTimer(int64_t startTimeMs, int64_t nowMs)
32 {
33 const int32_t timeDiff = static_cast<int32_t>(nowMs - startTimeMs);
34 MaxFilter(timeDiff, nowMs);
35 return timeDiff;
36 }
37
Reset()38 void VCMCodecTimer::Reset()
39 {
40 _filteredMax = 0;
41 _ignoredSampleCount = 0;
42 _shortMax = 0;
43 for (int i=0; i < MAX_HISTORY_SIZE; i++)
44 {
45 _history[i].shortMax = 0;
46 _history[i].timeMs = -1;
47 }
48 }
49
50 // Update the max-value filter
MaxFilter(int32_t decodeTime,int64_t nowMs)51 void VCMCodecTimer::MaxFilter(int32_t decodeTime, int64_t nowMs)
52 {
53 if (_ignoredSampleCount >= kIgnoredSampleCount)
54 {
55 UpdateMaxHistory(decodeTime, nowMs);
56 ProcessHistory(nowMs);
57 }
58 else
59 {
60 _ignoredSampleCount++;
61 }
62 }
63
64 void
UpdateMaxHistory(int32_t decodeTime,int64_t now)65 VCMCodecTimer::UpdateMaxHistory(int32_t decodeTime, int64_t now)
66 {
67 if (_history[0].timeMs >= 0 &&
68 now - _history[0].timeMs < SHORT_FILTER_MS)
69 {
70 if (decodeTime > _shortMax)
71 {
72 _shortMax = decodeTime;
73 }
74 }
75 else
76 {
77 // Only add a new value to the history once a second
78 if(_history[0].timeMs == -1)
79 {
80 // First, no shift
81 _shortMax = decodeTime;
82 }
83 else
84 {
85 // Shift
86 for(int i = (MAX_HISTORY_SIZE - 2); i >= 0 ; i--)
87 {
88 _history[i+1].shortMax = _history[i].shortMax;
89 _history[i+1].timeMs = _history[i].timeMs;
90 }
91 }
92 if (_shortMax == 0)
93 {
94 _shortMax = decodeTime;
95 }
96
97 _history[0].shortMax = _shortMax;
98 _history[0].timeMs = now;
99 _shortMax = 0;
100 }
101 }
102
103 void
ProcessHistory(int64_t nowMs)104 VCMCodecTimer::ProcessHistory(int64_t nowMs)
105 {
106 _filteredMax = _shortMax;
107 if (_history[0].timeMs == -1)
108 {
109 return;
110 }
111 for (int i=0; i < MAX_HISTORY_SIZE; i++)
112 {
113 if (_history[i].timeMs == -1)
114 {
115 break;
116 }
117 if (nowMs - _history[i].timeMs > MAX_HISTORY_SIZE * SHORT_FILTER_MS)
118 {
119 // This sample (and all samples after this) is too old
120 break;
121 }
122 if (_history[i].shortMax > _filteredMax)
123 {
124 // This sample is the largest one this far into the history
125 _filteredMax = _history[i].shortMax;
126 }
127 }
128 }
129
130 // Get the maximum observed time within a time window
RequiredDecodeTimeMs(FrameType) const131 int32_t VCMCodecTimer::RequiredDecodeTimeMs(FrameType /*frameType*/) const
132 {
133 return _filteredMax;
134 }
135
136 }
137