1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /**
19 * @file pvmf_sync_util.cpp
20 * @brief Utility class to synchronize processing of media data to a specified clock.
21 */
22
23 #ifndef PVMF_SYNC_UTIL_H_INCLUDED
24 #include "pvmf_sync_util.h"
25 #endif
26
27 //set this to 1 to disable AV sync and frame dropping.
28 //this option is used for performance testing but must be "0" in production code.
29 #define DISABLE_AV_SYNC 0
30
PvmfSyncUtil()31 OSCL_EXPORT_REF PvmfSyncUtil::PvmfSyncUtil() :
32 iClock(NULL),
33 iFrameStepClock(NULL),
34 iEarlyMargin(DEFAULT_EARLY_MARGIN),
35 iLateMargin(DEFAULT_LATE_MARGIN),
36 iSkipMediaData(false),
37 iResumeTimestamp(0),
38 iRenderSkippedData(false)
39 {
40 iLogger = PVLogger::GetLoggerObject("PvmfSyncUtil");
41 }
42
SetClock(PVMFMediaClock * aClock)43 OSCL_EXPORT_REF PVMFStatus PvmfSyncUtil::SetClock(PVMFMediaClock* aClock)
44 {
45 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
46 (0, "PvmfSyncUtil::SetClockAndTimebase: aClock=0x%x", aClock));
47
48 iClock = aClock;
49
50 return PVMFSuccess;
51 }
52
SetFrameStepClock(PVMFMediaClock * aClock)53 OSCL_EXPORT_REF PVMFStatus PvmfSyncUtil::SetFrameStepClock(PVMFMediaClock* aClock)
54 {
55 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
56 (0, "PvmfSyncUtil::SetClockAndTimebase: SetFrameStepClock=0x%x", aClock));
57
58 iFrameStepClock = aClock;
59
60 return PVMFSuccess;
61 }
62
SetMargins(int32 aEarlyMargin,int32 aLateMargin)63 OSCL_EXPORT_REF PVMFStatus PvmfSyncUtil::SetMargins(int32 aEarlyMargin, int32 aLateMargin)
64 {
65 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
66 (0, "PvmfSyncUtil::SetMargins: aEarlyMargin=%d, aLateMargin=%d", aEarlyMargin, aLateMargin));
67
68 iEarlyMargin = aEarlyMargin;
69 iLateMargin = aLateMargin;
70 return PVMFSuccess;
71 }
72
SyncMediaData(PVMFTimestamp aDataTimestamp,uint32 aDuration,uint32 & aMillisecondsEarly)73 OSCL_EXPORT_REF PvmfSyncStatus PvmfSyncUtil::SyncMediaData(PVMFTimestamp aDataTimestamp, uint32 aDuration, uint32& aMillisecondsEarly)
74 {
75 #if DISABLE_AV_SYNC
76 iClock = NULL;
77 #endif
78
79 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
80 (0, "PvmfSyncUtil::SyncMediaData: aDataTimestamp=%d aDuration=%d", aDataTimestamp, aDuration));
81
82 // TEMPORARY UNTIL DESIGN DEALING WITH DATA WITHOUT TIMESTAMP IS IMPLEMENTED
83 if (aDataTimestamp == 0xFFFFFFFF)
84 {
85 // 0xFFFFFFFF is a special value meaning no timestamp. Change to time 0
86 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
87 (0, "PvmfSyncUtil::SyncMediaData: aDataTimestamp is 0xFFFFFFFF so changing it to 0"));
88 aDataTimestamp = 0;
89 }
90 // END TEMPORARY
91
92 if (iSkipMediaData)
93 {
94 if ((aDataTimestamp + aDuration) >= iResumeTimestamp)
95 {
96 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
97 (0, "PvmfSyncUtil::SyncMediaData: SkipMediaData complete"));
98 iSkipMediaData = false;
99 return PVMF_SYNC_SKIP_COMPLETE;
100 }
101 else
102 {
103 if (iRenderSkippedData)
104 {
105 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
106 (0, "PvmfSyncUtil::SyncMediaData: Render skipped data"));
107 return PVMF_SYNC_SKIPPED_RENDER;
108 }
109 else
110 {
111 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
112 (0, "PvmfSyncUtil::SyncMediaData: Drop skipped data"));
113 //return the skip interval
114 aMillisecondsEarly = (iResumeTimestamp - aDataTimestamp);
115 return PVMF_SYNC_SKIPPED;
116 }
117 }
118 }
119 else if (!iClock)
120 {
121 // No clock to synchronize to. Process data ASAP.
122 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
123 (0, "PvmfSyncUtil::SyncMediaData: No clock available"));
124 return PVMF_SYNC_ON_TIME;
125 }
126
127 // Get current playback clock time
128 uint32 currentTime = 0;
129 bool overflow = false;
130 iClock->GetCurrentTime32(currentTime, overflow, PVMF_MEDIA_CLOCK_MSEC);
131
132 // Check if in sync
133 if (currentTime > (uint32)iLateMargin)
134 {
135 // Normal case
136 // In sync if beginning or tail end of data is within the sync window
137 if ((aDataTimestamp >= (currentTime - iLateMargin) && aDataTimestamp <= (currentTime + iEarlyMargin)) ||
138 ((aDataTimestamp + aDuration) >= (currentTime - iLateMargin) && (aDataTimestamp + aDuration) <= (currentTime + iEarlyMargin)))
139 {
140 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
141 (0, "PvmfSyncUtil::SyncMediaData: In Sync Clock(%d), TS(%d)", currentTime, aDataTimestamp));
142 return PVMF_SYNC_ON_TIME;
143 }
144 }
145 else
146 {
147 // Special case when clock less than the late margin (to avoid substracting from 0 with unsigned int)
148 // In sync if beginning is within the sync window
149 if (aDataTimestamp <= (currentTime + iEarlyMargin))
150 {
151 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
152 (0, "PvmfSyncUtil::SyncMediaData: In Sync Clock(%d), TS(%d)", currentTime, aDataTimestamp));
153 return PVMF_SYNC_ON_TIME;
154 }
155 }
156
157 // Early if the beginning of the data is before
158 // sync window
159 if (aDataTimestamp > (currentTime + iEarlyMargin))
160 {
161 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
162 (0, "PvmfSyncUtil::SyncMediaData: Early data Clock(%d), TS(%d) Dur(%d)", currentTime, aDataTimestamp, aDuration));
163 aMillisecondsEarly = (aDataTimestamp - currentTime - iEarlyMargin);
164 return PVMF_SYNC_EARLY;
165 }
166 else
167 {
168 // Late for all other cases
169 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
170 (0, "PvmfSyncUtil::SyncMediaData: Late data Clock(%d), TS(%d) Dur(%d)", currentTime, aDataTimestamp, aDuration));
171 //return the lateness amount
172 aMillisecondsEarly = ((currentTime + iEarlyMargin) - aDataTimestamp);
173 return PVMF_SYNC_LATE; // Late frame
174 }
175 }
176
SkipMediaData(PVMFTimestamp aResumeTimestamp,bool aRenderSkippedData)177 OSCL_EXPORT_REF PVMFStatus PvmfSyncUtil::SkipMediaData(PVMFTimestamp aResumeTimestamp, bool aRenderSkippedData)
178 {
179 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
180 (0, "PvmfSyncUtil::SkipMediaData: Resume(%d), Render(%d)", aResumeTimestamp, aRenderSkippedData));
181 iSkipMediaData = true;
182 iResumeTimestamp = aResumeTimestamp;
183 iRenderSkippedData = aRenderSkippedData;
184 return PVMFSuccess;
185 }
186
CancelSkipMediaData()187 OSCL_EXPORT_REF void PvmfSyncUtil::CancelSkipMediaData()
188 {
189 iSkipMediaData = false;
190 }
191
192
193
194
195
196
197
198