source: svn/newcon3bcm2_21bu/magnum/syslib/synclib/7552/bsynclib_algo.c @ 74

Last change on this file since 74 was 74, checked in by phkim, 10 years ago
  1. phkim
  2. zasc
  3. 변경 내용
    • CT_ChMapUpdatePMTAC3AudioDescriptor 메모리 leak 버그 수정
  • Property svn:executable set to *
File size: 37.2 KB
Line 
1/***************************************************************************
2*     Copyright (c) 2004-2012, Broadcom Corporation
3*     All Rights Reserved
4*     Confidential Property of Broadcom Corporation
5*
6*  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7*  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8*  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9*
10* $brcm_Workfile: bsynclib_algo.c $
11* $brcm_Revision: Hydra_Software_Devel/15 $
12* $brcm_Date: 2/9/12 9:17p $
13*
14* Revision History:
15*
16* $brcm_Log: /magnum/syslib/synclib/noarch/bsynclib_algo.c $
17*
18* Hydra_Software_Devel/15   2/9/12 9:17p bandrews
19* SW7358-219: really apply zero delay to sinks with mismatched rates
20*
21* Hydra_Software_Devel/14   1/25/12 3:44p bandrews
22* SW7346-653: hook up custom audio delay handling in synclib
23*
24* Hydra_Software_Devel/13   1/19/12 8:39p bandrews
25* SW7346-640: fix the units between estimated delay and measured delay
26* and threshold
27*
28* Hydra_Software_Devel/12   7/2/10 6:04p bandrews
29* SW7405-4436: added channel index to algo debug messages
30*
31* Hydra_Software_Devel/11   6/23/10 8:13p bandrews
32* SW7405-4471: a/v sync relied on a/a and v/v to find max delays among
33* paths, needed to break this reliance when a/a and v/v are no longer
34* executed every time
35*
36* Hydra_Software_Devel/10   5/28/10 6:31p bandrews
37* SW7405-4436: printing channel index in dbg messages
38*
39* Hydra_Software_Devel/9   2/12/10 8:46p bandrews
40* SW7405-3912: assert all inputs are not null
41*
42* Hydra_Software_Devel/8   12/10/09 9:18p bandrews
43* SW7401-3634: adding PWC (now JTI) support to synclib
44*
45* Hydra_Software_Devel/7   7/24/09 4:15p bandrews
46* PR48566: support preferred units
47*
48* Hydra_Software_Devel/6   11/19/08 2:23p bandrews
49* PR48637: Change synclib to only zero/reapply delay if it has changed
50* from last time
51*
52* Hydra_Software_Devel/5   10/6/08 8:07p bandrews
53* PR44510: Implement delay capacity for video sinks
54*
55* Hydra_Software_Devel/4   7/2/08 6:38p bandrews
56* PR44521: Change check for HD height to only think HD is > 576
57*
58* Hydra_Software_Devel/3   6/30/08 9:16p bandrews
59* PR37951: Added todo for passing buffer counts as setting
60*
61* Hydra_Software_Devel/2   6/16/08 4:02p bandrews
62* PR42265: Include custom delay in measured so sync will compensate
63*
64* Hydra_Software_Devel/1   3/24/08 3:09p bandrews
65* PR40865: Fixed
66*
67* Hydra_Software_Devel/8   2/26/08 10:21p bandrews
68* PR37951: Fixed units.  Implemented static rate mismatch detection.
69*
70* Hydra_Software_Devel/7   2/26/08 3:05p bandrews
71* PR37951: Removed some extra ifzeroed code
72*
73* Hydra_Software_Devel/6   2/26/08 3:03p bandrews
74* PR37951: Added video delay requantization
75*
76* Hydra_Software_Devel/5   2/25/08 9:33p bandrews
77* PR37951: Fixed various bugs
78*
79* Hydra_Software_Devel/4   2/21/08 6:02p bandrews
80* PR37951: Default video source numbers to 45KHz domain.  Improved
81* handling of unsynchronized elements
82*
83* Hydra_Software_Devel/3   2/20/08 10:03p bandrews
84* PR37951: Updated based on feedback from usage
85*
86* Hydra_Software_Devel/2   1/3/08 5:17p bandrews
87* PR37951: Updated based on initial feedback
88*
89* Hydra_Software_Devel/1   12/12/07 2:53p bandrews
90* PR37951: Initial check-in
91***************************************************************************/
92
93#include "bstd.h"
94#include "bsynclib_algo.h"
95#include "bsynclib_priv.h"
96#include "bsynclib_channel_priv.h"
97
98BDBG_MODULE(synclib);
99
100void BSYNClib_Algo_AudioVideo_Sync(BSYNClib_Channel_Path * psAudio, BSYNClib_Channel_Path * psVideo, BSYNClib_Channel_Results * psResults)
101{
102        BDBG_ENTER((BSYNClib_Algo_AudioVideo_Sync));
103
104        BDBG_MSG(("[%d] Attempting to synchronize audio with video...", psAudio->hChn->iIndex));
105
106        BSYNClib_Algo_VideoSink_MaxFinder(psVideo);
107        BSYNClib_Algo_VideoSource_MaxFinder(psVideo);
108        BSYNClib_Algo_AudioSink_MaxFinder(psAudio);
109        BSYNClib_Algo_AudioSource_MaxFinder(psAudio);
110        BSYNClib_Algo_AudioVideo_MaxFinder(psAudio, psVideo, psResults);
111        BSYNClib_Algo_AudioVideo_Allocator(psAudio, psVideo, psResults);
112
113        BDBG_LEAVE((BSYNClib_Algo_AudioVideo_Sync));
114}
115
116void BSYNClib_Algo_VideoVideo_Sync(BSYNClib_Channel_Path * psPath)
117{
118        BDBG_ENTER((BSYNClib_Algo_VideoVideo_Sync));
119
120        BDBG_MSG(("[%d] Attempting to synchronize all isocontent video paths...", psPath->hChn->iIndex));
121
122        BSYNClib_Algo_VideoSink_MaxFinder(psPath);
123        BSYNClib_Algo_VideoSource_MaxFinder(psPath);
124        BSYNClib_Algo_VideoVideo_Allocator(psPath);
125
126        BDBG_LEAVE((BSYNClib_Algo_VideoVideo_Sync));
127}
128
129
130void BSYNClib_Algo_AudioAudio_Sync(BSYNClib_Channel_Path * psPath)
131{
132        BDBG_ENTER((BSYNClib_Algo_AudioAudio_Sync));
133
134        BDBG_MSG(("[%d] Attempting to synchronize all isocontent audio paths...", psPath->hChn->iIndex));
135
136        BSYNClib_Algo_AudioSink_MaxFinder(psPath);
137        BSYNClib_Algo_AudioSource_MaxFinder(psPath);
138        BSYNClib_Algo_AudioAudio_Allocator(psPath);
139
140        BDBG_LEAVE((BSYNClib_Algo_AudioAudio_Sync));
141}
142
143
144
145
146
147
148void BSYNClib_Algo_VideoVideo_Allocator(BSYNClib_Channel_Path * psPath)
149{
150        BSYSlib_List_IteratorHandle hIterator;
151       
152        BDBG_ENTER((BSYNClib_Algo_VideoVideo_Allocator));
153
154        BDBG_ASSERT(psPath);
155
156        /* TODO: this only allocates for sinks, need to handle multiple sources */
157       
158        /* allocate difference between max and current to all windows */
159
160        hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
161
162        while (BSYSlib_List_HasNext(hIterator))
163        {
164                BSYNClib_VideoSink * psSink;
165                unsigned int delay_diff;
166
167                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
168
169                if (psSink->sElement.sSnapshot.bSynchronize)
170                {
171                    if (psPath->sResults.bInconsistentSinkDomains)
172                    {
173                        delay_diff = 0;
174                                BDBG_MSG(("[%d]  Allocating video sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, BSYNClib_P_Convert(delay_diff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
175                        psSink->sElement.sDelay.sResults.uiDesired = delay_diff;
176                    }
177                    else
178                    {
179                        /* PR21616 20061128 bandrews - don't bother applying delays to hidden windows, like PiP */
180                        if (psSink->sSnapshot.bVisible)
181                        {
182                                delay_diff = psPath->sResults.uiMaxSinkDelay - psSink->sElement.sDelay.sSnapshot.uiMeasured;
183                        }
184                        else /* hidden windows get no delay */
185                        {
186                                delay_diff = 0;
187                        }
188
189#if 1
190    /* 20081006 PR44510 bandrews */
191                        if (delay_diff <= psSink->sElement.sDelay.sData.uiCapacity)
192                        {
193                                BDBG_MSG(("[%d]  Allocating video sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, BSYNClib_P_Convert(delay_diff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
194                                psSink->sElement.sDelay.sResults.uiDesired = delay_diff;
195                        }
196                        else
197                        {
198                                BDBG_WRN(("[%d]  Delay capacity reached for video sink %u; requested delay: %u ms, capacity: %u ms", 
199                                        psPath->hChn->iIndex, 
200                                        psSink->sElement.uiIndex,
201                                        BSYNClib_P_Convert(delay_diff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds),
202                                        BSYNClib_P_Convert(psSink->sElement.sDelay.sData.uiCapacity, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
203                                delay_diff = psSink->sElement.sDelay.sData.uiCapacity;
204                                BDBG_MSG(("[%d]  Allocating video sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, BSYNClib_P_Convert(delay_diff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
205                                psSink->sElement.sDelay.sResults.uiDesired = delay_diff;
206                        }
207#else
208                        {
209                                unsigned int uiCumulativeHdDelayDiff = 0;
210                                unsigned int uiCumulativeSdDelayDiff = 0;
211                                unsigned int uiVsyncPeriod = 0;
212
213                                uiVsyncPeriod = BSYNClib_VideoFormat_P_GetVsyncPeriod(&psSink->sFormat);
214
215                                /* 20070212 PR27128 bandrews - limit bsync VDC buffer requests to what was allocated at init time */
216                                /* 20080702 PR44521 bandrews - handle PAL SD height, too */
217                                if (psSink->sFormat.sSnapshot.uiHeight > 576)
218                                {
219                                        uiCumulativeHdDelayDiff += delay_diff;
220                                        uiCumulativeSdDelayDiff += BSYNCLIB_P_SD_BUFFERS_PER_HD_BUFFER * delay_diff;
221                                }
222                                else
223                                {
224#if B_HAS_LEGACY_VDC
225                                        /* 20070516 bandrews only increment the delay diff if there was already one to start */
226                                        if (delay_diff)
227                                        {
228                                                delay_diff += uiVsyncPeriod;
229                                        }
230#endif
231                                        uiCumulativeSdDelayDiff += delay_diff;
232                                }
233
234                                if ((uiCumulativeHdDelayDiff <= BSYNCLIB_P_MAX_CUMULATIVE_HD_VDC_DELAY * uiVsyncPeriod) 
235                                        && (uiCumulativeSdDelayDiff <= BSYNCLIB_P_MAX_CUMULATIVE_SD_VDC_DELAY * uiVsyncPeriod))
236                                {
237                                        BDBG_MSG(("  Allocating video sink %u delay: %u ms", psSink->sElement.uiIndex, BSYNClib_P_Convert(delay_diff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
238                                        psSink->sElement.sDelay.sResults.uiDesired = delay_diff;
239                                }
240                                else
241                                {
242                                        /* 20070412 bandrews - added because this message should only print if we are trying to exceed the max */
243                                        if (delay_diff)
244                                        {
245                                                BDBG_WRN(("  Cumulative delay limit of %u HD or %u SD ms reached for syncing simul video sinks", 
246                                                        BSYNClib_P_Convert(BSYNCLIB_P_MAX_CUMULATIVE_HD_VDC_DELAY * uiVsyncPeriod, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
247                                                        BSYNClib_P_Convert(BSYNCLIB_P_MAX_CUMULATIVE_SD_VDC_DELAY * uiVsyncPeriod, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
248                                                BDBG_WRN(("  Video sink %u will not be synced", psSink->sElement.uiIndex));
249                                        }
250                                }
251                        }
252#endif
253            }
254                }
255        }
256       
257        BSYSlib_List_ReleaseIterator(hIterator);
258
259        BDBG_LEAVE((BSYNClib_Algo_VideoVideo_Allocator));
260}
261
262void BSYNClib_Algo_AudioAudio_Allocator(BSYNClib_Channel_Path * psPath)
263{
264        BSYSlib_List_IteratorHandle hIterator;
265       
266        BDBG_ENTER((BSYNClib_Algo_AudioAudio_Allocator));
267
268        BDBG_ASSERT(psPath);
269
270        /* TODO: sources? */
271
272        hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
273
274        while (BSYSlib_List_HasNext(hIterator))
275        {
276                BSYNClib_AudioSink * psSink;
277                unsigned int uiDelayDiff;
278
279                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
280
281                if (psSink->sElement.sSnapshot.bSynchronize)
282                {
283                        uiDelayDiff = psSink->sElement.sDelay.sSnapshot.uiMeasured - psPath->sResults.uiMaxSinkDelay;
284
285                        BDBG_MSG(("[%d]  Allocating audio sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, 
286                                BSYNClib_P_Convert(uiDelayDiff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
287                        psSink->sElement.sDelay.sResults.uiDesired = uiDelayDiff;
288                }
289        }
290
291        BSYSlib_List_ReleaseIterator(hIterator);
292       
293        BDBG_LEAVE((BSYNClib_Algo_AudioAudio_Allocator));
294}
295
296void BSYNClib_Algo_AudioVideo_Allocator(BSYNClib_Channel_Path * psAudio, BSYNClib_Channel_Path * psVideo, BSYNClib_Channel_Results * psResults)
297{
298        BSYSlib_List_IteratorHandle hIterator;
299        unsigned int uiDelayDiff;
300        unsigned int uiAdditionalAudioDelay;
301#if BSYNCLIB_JITTER_TOLERANCE_IMPROVEMENT_SUPPORT
302        unsigned int uiAdditionalVideoDelay;
303        int iJtiFactor;
304#endif
305       
306        BDBG_ENTER((BSYNClib_Algo_AudioVideo_Allocator));
307
308        BDBG_ASSERT(psAudio);
309        BDBG_ASSERT(psVideo);
310        BDBG_ASSERT(psResults);
311
312        uiAdditionalAudioDelay = 0;
313
314        /* video first because of requantization */
315        /* TODO: multiple video sources? */
316        hIterator = BSYSlib_List_AcquireIterator(psVideo->hSources);
317
318        while (BSYSlib_List_HasNext(hIterator))
319        {
320                BSYNClib_VideoSource * psSource;
321
322                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
323
324                if (psSource->sElement.sSnapshot.bSynchronize)
325                {
326                        unsigned int uiSourceFramePeriod;
327                        unsigned int uiRequantizedVideoDelay;
328
329                        uiDelayDiff = psResults->uiMaxPathDelay - psVideo->sResults.uiMaxPathDelay;
330
331                        /* Requantize */
332                        uiSourceFramePeriod = BSYNClib_VideoFormat_P_GetFramePeriod(&psSource->sFormat);
333                        BSYNClib_Algo_RequantizeDelay(psVideo->hChn->iIndex, uiDelayDiff, uiSourceFramePeriod, &uiRequantizedVideoDelay);
334                        uiAdditionalAudioDelay = uiRequantizedVideoDelay - uiDelayDiff;
335                        psSource->sElement.sDelay.sResults.uiDesired = uiRequantizedVideoDelay;
336
337#if BSYNCLIB_JITTER_TOLERANCE_IMPROVEMENT_SUPPORT
338                        /* JTI */
339                        BSYNClib_Algo_CalculateJitterToleranceImprovementFactor(psVideo, psSource, uiRequantizedVideoDelay, &iJtiFactor, &uiAdditionalVideoDelay);
340                        psSource->sElement.sDelay.sResults.uiDesired += uiAdditionalVideoDelay;
341                        psSource->sElement.sDelay.sResults.uiDesired += iJtiFactor;
342#endif                 
343
344                        BDBG_MSG(("[%d]  Allocating video source %u delay: %u ms", psVideo->hChn->iIndex, psSource->sElement.uiIndex, 
345                                BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
346                }
347        }
348
349        BSYSlib_List_ReleaseIterator(hIterator);
350
351        hIterator = BSYSlib_List_AcquireIterator(psAudio->hSources);
352
353        while (BSYSlib_List_HasNext(hIterator))
354        {
355                BSYNClib_AudioSource * psSource;
356
357                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
358
359                if (psSource->sElement.sSnapshot.bSynchronize)
360                {
361                        uiDelayDiff = psResults->uiMaxPathDelay - psAudio->sResults.uiMaxPathDelay + uiAdditionalAudioDelay;
362                        BDBG_MSG(("[%d]  Allocating audio source %u delay: %u ms", psAudio->hChn->iIndex, psSource->sElement.uiIndex, 
363                                BSYNClib_P_Convert(uiDelayDiff, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
364                        psSource->sElement.sDelay.sResults.uiDesired = uiDelayDiff;
365                }
366        }
367       
368        BSYSlib_List_ReleaseIterator(hIterator);
369
370        BDBG_LEAVE((BSYNClib_Algo_AudioVideo_Allocator));
371}
372
373
374
375
376
377void BSYNClib_Algo_AudioVideo_MaxFinder(BSYNClib_Channel_Path * psAudio, BSYNClib_Channel_Path * psVideo, BSYNClib_Channel_Results * psResults)
378{
379        unsigned int uiMaxPathDelay = 0;
380        BSYNClib_Channel_Path * psMaxDelayPath;
381       
382        BDBG_ENTER((BSYNClib_Algo_AudioVideo_MaxFinder));
383
384        BDBG_ASSERT(psAudio);
385        BDBG_ASSERT(psVideo);
386        BDBG_ASSERT(psResults);
387
388        psAudio->sResults.uiMaxPathDelay = psAudio->sResults.uiMaxSinkDelay + psAudio->sResults.uiMaxSourceDelay;
389        psVideo->sResults.uiMaxPathDelay = psVideo->sResults.uiMaxSinkDelay + psVideo->sResults.uiMaxSourceDelay;
390
391        BDBG_MSG(("[%d]  Max audio path delay is %u ms", psAudio->hChn->iIndex, BSYNClib_P_Convert(psAudio->sResults.uiMaxPathDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
392        BDBG_MSG(("[%d]  Max video path delay is %u ms", psVideo->hChn->iIndex, BSYNClib_P_Convert(psVideo->sResults.uiMaxPathDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
393
394        if (psVideo->sResults.uiMaxPathDelay > psAudio->sResults.uiMaxPathDelay)
395        {
396                uiMaxPathDelay = psVideo->sResults.uiMaxPathDelay;
397                psMaxDelayPath = psVideo;
398        }
399        else
400        {
401                uiMaxPathDelay = psAudio->sResults.uiMaxPathDelay;
402                psMaxDelayPath = psAudio;
403        }
404
405        /* keep max and window index for later */
406        psResults->uiMaxPathDelay = uiMaxPathDelay;
407        psResults->psMaxDelayPath = psMaxDelayPath;
408        BDBG_MSG(("[%d]  Max path delay is %u ms from %s", psAudio->hChn->iIndex, BSYNClib_P_Convert(psResults->uiMaxPathDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), psResults->psMaxDelayPath == psAudio ? "audio" : "video"));
409
410        BDBG_LEAVE((BSYNClib_Algo_AudioVideo_MaxFinder));
411}
412
413void BSYNClib_Algo_VideoSink_MaxFinder(BSYNClib_Channel_Path * psPath)
414{
415        BSYSlib_List_IteratorHandle hIterator;
416        int iMaxSinkDelay = -1;
417        BSYNClib_VideoSink * psMaxDelaySink = NULL;
418       
419        BDBG_ENTER((BSYNClib_Algo_VideoSink_MaxFinder));
420
421        BDBG_ASSERT(psPath);
422
423        /* find max sink delay and the index of the sink that has it */
424        hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
425
426        while (BSYSlib_List_HasNext(hIterator))
427        {
428                BSYNClib_VideoSink * psSink;
429                unsigned int uiSinkDelay;
430
431                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
432
433                /* if not visible or not synchronized, ignore */
434                if (!psSink->sSnapshot.bVisible || !psSink->sElement.sSnapshot.bSynchronize)
435                {
436                        BDBG_MSG(("[%d]  Window max delay finder -- Ignoring invisible or unsynchronized window %u", psPath->hChn->iIndex, psSink->sElement.uiIndex));
437                        continue;
438                }
439
440                uiSinkDelay = psSink->sElement.sDelay.sSnapshot.uiMeasured;
441               
442                BDBG_MSG(("[%d]  Current video sink delay, sink %u: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, 
443                        BSYNClib_P_Convert(uiSinkDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
444                if ((signed)uiSinkDelay > iMaxSinkDelay)
445                {
446                        iMaxSinkDelay = uiSinkDelay;
447                        psMaxDelaySink = psSink;
448                }
449
450                /* TODO: this only does measured delay
451                need to find max of max delays between all sinks for 7038 */
452        }
453
454        BSYSlib_List_ReleaseIterator(hIterator);
455
456        if (psMaxDelaySink)
457        {
458                /* keep max and window index for later */
459                psPath->sResults.uiMaxSinkDelay = iMaxSinkDelay;
460                psPath->sResults.pvMaxDelaySink = psMaxDelaySink;
461                BDBG_MSG(("[%d]  Max video postprocessing delay is %u ms from video sink %u", psPath->hChn->iIndex, 
462                        BSYNClib_P_Convert(psPath->sResults.uiMaxSinkDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
463                        ((BSYNClib_VideoSink *)(psPath->sResults.pvMaxDelaySink))->sElement.uiIndex));
464        }
465        else
466        {
467                BDBG_MSG(("[%d]  No synchronized video windows.  Setting max window delay to 0.", psPath->hChn->iIndex));
468                psPath->sResults.uiMaxSinkDelay = 0;
469                psPath->sResults.pvMaxDelaySink = NULL;
470        }
471
472        BDBG_LEAVE((BSYNClib_Algo_VideoSink_MaxFinder));
473}
474
475
476void BSYNClib_Algo_VideoSource_MaxFinder(BSYNClib_Channel_Path * psPath)
477{
478        BSYSlib_List_IteratorHandle hIterator;
479        int iMaxSourceDelay = -1;
480        BSYNClib_VideoSource * psMaxDelaySource = NULL;
481       
482        BDBG_ENTER((BSYNClib_Algo_VideoSource_MaxFinder));
483
484        BDBG_ASSERT(psPath);
485
486        /* find max source delay and the index of the source that has it */
487        hIterator = BSYSlib_List_AcquireIterator(psPath->hSources);
488
489        while (BSYSlib_List_HasNext(hIterator))
490        {
491                BSYNClib_VideoSource * psSource;
492                unsigned int uiSourceDelay;
493
494                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
495
496                /* if not synchronized, ignore */
497                if (!psSource->sElement.sSnapshot.bSynchronize)
498                {
499                        BDBG_MSG(("[%d]  Video source max delay finder -- Ignoring unsynchronized source %u", psPath->hChn->iIndex, psSource->sElement.uiIndex));
500                        continue;
501                }
502
503                /* PR42265 20080616 bandrews - need to include custom delay in measured,
504                otherwise, sync won't compensate audio for this delay */
505                uiSourceDelay = psSource->sElement.sDelay.sSnapshot.uiMeasured + psSource->sElement.sDelay.sSnapshot.uiCustom;
506               
507                BDBG_MSG(("[%d]  Current video source delay, source %u: %u ms %s", psPath->hChn->iIndex, psSource->sElement.uiIndex, 
508                        BSYNClib_P_Convert(uiSourceDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds),
509                        psSource->sElement.sDelay.sResults.bEstimated ? "estimated" : "measured"));
510                if ((signed)uiSourceDelay > iMaxSourceDelay)
511                {
512                        iMaxSourceDelay = uiSourceDelay;
513                        psMaxDelaySource = psSource;
514                }
515        }
516
517        BSYSlib_List_ReleaseIterator(hIterator);
518
519        if (psMaxDelaySource)
520        {
521                /* keep max and decoder index for later */
522                psPath->sResults.uiMaxSourceDelay = iMaxSourceDelay;
523                psPath->sResults.pvMaxDelaySource = psMaxDelaySource;
524                BDBG_MSG(("[%d]  Max video decoder delay is %u ms from video source %u", 
525                        psPath->hChn->iIndex, 
526                        BSYNClib_P_Convert(psPath->sResults.uiMaxSourceDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
527                        ((BSYNClib_VideoSource *)(psPath->sResults.pvMaxDelaySource))->sElement.uiIndex));
528        }
529        else
530        {
531                BDBG_MSG(("[%d]  No synchronized video decoders.  Setting max decoder delay to 0.", psPath->hChn->iIndex));
532                psPath->sResults.uiMaxSourceDelay = 0;
533                psPath->sResults.pvMaxDelaySource = NULL;
534        }
535
536        BDBG_LEAVE((BSYNClib_Algo_VideoSource_MaxFinder));
537}
538
539void BSYNClib_Algo_AudioSink_MaxFinder(BSYNClib_Channel_Path * psPath)
540{
541        BSYSlib_List_IteratorHandle hIterator;
542        int iMaxSinkDelay = -1;
543        BSYNClib_AudioSink * psMaxDelaySink = NULL;
544       
545        BDBG_ENTER((BSYNClib_Algo_AudioSink_MaxFinder));
546
547        BDBG_ASSERT(psPath);
548
549        /* find max sink delay and the index of the sink that has it */
550        hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
551
552        while (BSYSlib_List_HasNext(hIterator))
553        {
554                BSYNClib_AudioSink * psSink;
555                unsigned int uiSinkDelay;
556
557                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
558
559                /* if not synchronized, ignore */
560                if (!psSink->sElement.sSnapshot.bSynchronize)
561                {
562                        BDBG_MSG(("[%d]  Audio output max delay finder -- Ignoring unsynchronized output %u", psPath->hChn->iIndex, psSink->sElement.uiIndex));
563                        continue;
564                }
565
566                uiSinkDelay = psSink->sElement.sDelay.sSnapshot.uiMeasured;
567               
568                BDBG_MSG(("[%d]  Current audio sink delay, sink %u: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, 
569                        BSYNClib_P_Convert(uiSinkDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
570                if ((signed)uiSinkDelay > iMaxSinkDelay)
571                {
572                        iMaxSinkDelay = uiSinkDelay;
573                        psMaxDelaySink = psSink;
574                }
575        }
576
577        BSYSlib_List_ReleaseIterator(hIterator);
578
579        if (psMaxDelaySink)
580        {
581                /* keep max and output index for later */
582                psPath->sResults.uiMaxSinkDelay = iMaxSinkDelay;
583                psPath->sResults.pvMaxDelaySink = psMaxDelaySink;
584                BDBG_MSG(("[%d]  Max audio output delay is %u ms from audio sink %u", 
585                        psPath->hChn->iIndex, 
586                        BSYNClib_P_Convert(psPath->sResults.uiMaxSinkDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
587                        ((BSYNClib_AudioSink *)(psPath->sResults.pvMaxDelaySink))->sElement.uiIndex));
588        }
589        else
590        {
591                BDBG_MSG(("[%d]  No synchronized audio outputs.  Setting max output delay to 0.", psPath->hChn->iIndex));
592                psPath->sResults.uiMaxSinkDelay = 0;
593                psPath->sResults.pvMaxDelaySink = NULL;
594        }
595
596        BDBG_LEAVE((BSYNClib_Algo_AudioSink_MaxFinder));
597}
598
599void BSYNClib_Algo_AudioSource_MaxFinder(BSYNClib_Channel_Path * psPath)
600{
601        BSYSlib_List_IteratorHandle hIterator;
602        int iMaxSourceDelay = -1;
603        BSYNClib_AudioSource * psMaxDelaySource = NULL;
604       
605        BDBG_ENTER((BSYNClib_Algo_AudioSource_MaxFinder));
606
607        BDBG_ASSERT(psPath);
608
609        /* find max source delay and the index of the source that has it */
610        hIterator = BSYSlib_List_AcquireIterator(psPath->hSources);
611
612        while (BSYSlib_List_HasNext(hIterator))
613        {
614                BSYNClib_AudioSource * psSource;
615                unsigned int uiSourceDelay;
616
617                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
618
619                /* if not synchronized, ignore */
620                if (!psSource->sElement.sSnapshot.bSynchronize)
621                {
622                        BDBG_MSG(("[%d]  Audio source max delay finder -- Ignoring unsynchronized source %u", psPath->hChn->iIndex, psSource->sElement.uiIndex));
623                        continue;
624                }
625
626                uiSourceDelay = psSource->sElement.sDelay.sSnapshot.uiMeasured + psSource->sElement.sDelay.sSnapshot.uiCustom;
627               
628                BDBG_MSG(("[%d]  Current audio source delay, source %u: %u ms", psPath->hChn->iIndex, psSource->sElement.uiIndex, 
629                        BSYNClib_P_Convert(uiSourceDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
630                if ((signed)uiSourceDelay > iMaxSourceDelay)
631                {
632                        iMaxSourceDelay = uiSourceDelay;
633                        psMaxDelaySource = psSource;
634                }
635        }
636
637        BSYSlib_List_ReleaseIterator(hIterator);
638
639        if (psMaxDelaySource)
640        {
641                /* keep max and decoder index for later */
642                psPath->sResults.uiMaxSourceDelay = iMaxSourceDelay;
643                psPath->sResults.pvMaxDelaySource = psMaxDelaySource;
644                BDBG_MSG(("[%d]  Max audio decoder delay is %u ms from audio source %u", 
645                        psPath->hChn->iIndex, 
646                        BSYNClib_P_Convert(psPath->sResults.uiMaxSourceDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
647                        ((BSYNClib_AudioSource *)(psPath->sResults.pvMaxDelaySource))->sElement.uiIndex));
648        }
649        else
650        {
651                BDBG_MSG(("[%d]  No synchronized audio decoders.  Setting max decoder delay to 0.", psPath->hChn->iIndex));
652                psPath->sResults.uiMaxSourceDelay = 0;
653                psPath->sResults.pvMaxDelaySource = NULL;
654        }
655
656        BDBG_LEAVE((BSYNClib_Algo_AudioSource_MaxFinder));
657}
658
659
660
661
662
663
664
665BERR_Code BSYNClib_Algo_VideoSink_Applicator(BSYNClib_Channel_Path * psPath, BSYNClib_Channel_SetDelay pfSetDelay, void * pvParm1, int iParm2)
666{
667        BERR_Code rc = BERR_SUCCESS;
668       
669        BDBG_ENTER((BSYNClib_Algo_VideoSink_Applicator));
670
671        BDBG_ASSERT(psPath);
672
673        if (pfSetDelay)
674        {
675                BSYSlib_List_IteratorHandle hIterator;
676
677                hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
678               
679                /* release all extra delay buffers first, to reduce memory required during transitions */
680                while (BSYSlib_List_HasNext(hIterator))
681                {
682                        BSYNClib_VideoSink * psSink;
683
684                        psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
685
686                        if (psSink->sElement.sSnapshot.bSynchronize)
687                        {
688                                /* PR48637 bandrews - do not zero out delay if same as last time */
689                                if (psSink->sElement.sDelay.sResults.uiApplied != psSink->sElement.sDelay.sResults.uiDesired)
690                                {
691                                        BSYNClib_UnsignedValue sDelay;
692                                        BDBG_MSG(("[%d]  Releasing %u ms of delay on video sink %u", 
693                                                psPath->hChn->iIndex, 
694                                                BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds), 
695                                                psSink->sElement.uiIndex));
696
697                                        sDelay.uiValue = 0;
698                                        sDelay.eUnits = psSink->sElement.sDelay.sSnapshot.ePreferredUnits;
699
700                                        rc = pfSetDelay(pvParm1, iParm2, psSink->sElement.uiIndex, &sDelay);
701                                        if (rc) goto error;
702
703                                        psSink->sStatus.sAppliedDelay.uiValue = 0;
704                                }
705                        }
706                }
707
708                /* start at beginning of list again */
709                BSYSlib_List_ResetIterator(hIterator);
710               
711                /* apply desired */
712                while (BSYSlib_List_HasNext(hIterator))
713                {
714                        BSYNClib_VideoSink * psSink;
715
716                        psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
717
718                        if (psSink->sElement.sSnapshot.bSynchronize)
719                        {
720                                /* PR48637 bandrews - do not re-apply delay if same as last time */
721                                if (psSink->sElement.sDelay.sResults.uiApplied != psSink->sElement.sDelay.sResults.uiDesired)
722                                {
723                                        BSYNClib_UnsignedValue sDesired;
724
725                                        BDBG_MSG(("[%d]  Applying video sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, 
726                                                BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
727
728                                        sDesired.uiValue = BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, psSink->sElement.sDelay.sSnapshot.ePreferredUnits);
729                                        sDesired.eUnits = psSink->sElement.sDelay.sSnapshot.ePreferredUnits;
730
731                                        rc = pfSetDelay(pvParm1, iParm2, psSink->sElement.uiIndex, &sDesired);
732                                        if (rc) goto error;
733                                       
734                                        psSink->sElement.sDelay.sResults.uiApplied = psSink->sElement.sDelay.sResults.uiDesired;
735                                        psSink->sStatus.sAppliedDelay.uiValue = BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, psSink->sElement.sDelay.sSnapshot.ePreferredUnits);
736                                        psSink->sStatus.sAppliedDelay.eUnits = psSink->sElement.sDelay.sSnapshot.ePreferredUnits;
737                                }
738                        }
739                }
740
741                BSYSlib_List_ReleaseIterator(hIterator);
742        }
743
744        goto end;
745       
746error:
747
748end:
749       
750        BDBG_LEAVE((BSYNClib_Algo_VideoSink_Applicator));
751        return rc;
752}
753
754BERR_Code BSYNClib_Algo_VideoSource_Applicator(BSYNClib_Channel_Path * psPath, BSYNClib_Channel_SetDelay pfSetDelay, void * pvParm1, int iParm2)
755{
756        BERR_Code rc = BERR_SUCCESS;
757       
758        BDBG_ENTER((BSYNClib_Algo_VideoSource_Applicator));
759
760        BDBG_ASSERT(psPath);
761
762        /* apply desired */
763        if (pfSetDelay)
764        {
765                BSYSlib_List_IteratorHandle hIterator;
766
767                hIterator = BSYSlib_List_AcquireIterator(psPath->hSources);
768
769                while (BSYSlib_List_HasNext(hIterator))
770                {
771                        BSYNClib_VideoSource * psSource;
772
773                        psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
774
775                        if (psSource->sElement.sSnapshot.bSynchronize)
776                        {
777                                BSYNClib_UnsignedValue sDesired;
778
779                                BDBG_MSG(("[%d]  Applying video source %u delay: %u ms", psPath->hChn->iIndex, psSource->sElement.uiIndex, 
780                                        BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
781                               
782                                sDesired.uiValue = BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, psSource->sElement.sDelay.sSnapshot.ePreferredUnits);
783                                sDesired.eUnits = psSource->sElement.sDelay.sSnapshot.ePreferredUnits;
784
785                                rc = pfSetDelay(pvParm1, iParm2, psSource->sElement.uiIndex, &sDesired);
786                                if (rc) goto error;
787                               
788                                psSource->sElement.sDelay.sResults.uiApplied = psSource->sElement.sDelay.sResults.uiDesired;
789                                psSource->sStatus.sAppliedDelay.uiValue = BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, psSource->sElement.sDelay.sSnapshot.ePreferredUnits);
790                                psSource->sStatus.sAppliedDelay.eUnits = psSource->sElement.sDelay.sSnapshot.ePreferredUnits;
791                        }
792                }
793
794                BSYSlib_List_ReleaseIterator(hIterator);
795        }
796       
797        goto end;
798       
799error:
800
801end:
802       
803        BDBG_LEAVE((BSYNClib_Algo_VideoSource_Applicator));
804        return rc;
805}
806
807BERR_Code BSYNClib_Algo_AudioSink_Applicator(BSYNClib_Channel_Path * psPath, BSYNClib_Channel_SetDelay pfSetDelay, void * pvParm1, int iParm2)
808{
809        BERR_Code rc = BERR_SUCCESS;
810       
811        BDBG_ENTER((BSYNClib_Algo_AudioSink_Applicator));
812
813        BDBG_ASSERT(psPath);
814
815        /* TODO: independent delay only to one port */
816        /* apply desired */
817        if (pfSetDelay)
818        {
819                BSYSlib_List_IteratorHandle hIterator;
820
821                hIterator = BSYSlib_List_AcquireIterator(psPath->hSinks);
822
823                while (BSYSlib_List_HasNext(hIterator))
824                {
825                        BSYNClib_AudioSink * psSink;
826
827                        psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
828
829                        if (psSink->sElement.sSnapshot.bSynchronize)
830                        {
831                                BSYNClib_UnsignedValue sDesired;
832
833                                BDBG_MSG(("[%d]  Applying audio sink %u delay: %u ms", psPath->hChn->iIndex, psSink->sElement.uiIndex, 
834                                        BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
835                               
836                                sDesired.uiValue = BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, psSink->sElement.sDelay.sSnapshot.ePreferredUnits);
837                                sDesired.eUnits = psSink->sElement.sDelay.sSnapshot.ePreferredUnits;
838
839                                rc = pfSetDelay(pvParm1, iParm2, psSink->sElement.uiIndex, &sDesired);
840                                if (rc) goto error;
841                               
842                                psSink->sElement.sDelay.sResults.uiApplied = psSink->sElement.sDelay.sResults.uiDesired;
843                                psSink->sStatus.sAppliedDelay.uiValue = BSYNClib_P_Convert(psSink->sElement.sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, psSink->sElement.sDelay.sSnapshot.ePreferredUnits);
844                                psSink->sStatus.sAppliedDelay.eUnits = psSink->sElement.sDelay.sSnapshot.ePreferredUnits;
845                        }
846                }
847
848                BSYSlib_List_ReleaseIterator(hIterator);
849        }
850       
851        goto end;
852       
853error:
854
855end:
856       
857        BDBG_LEAVE((BSYNClib_Algo_AudioSink_Applicator));
858        return rc;
859}
860
861BERR_Code BSYNClib_Algo_AudioSource_Applicator(BSYNClib_Channel_Path * psPath, BSYNClib_Channel_SetDelay pfSetDelay, void * pvParm1, int iParm2)
862{
863        BERR_Code rc = BERR_SUCCESS;
864       
865        BDBG_ENTER((BSYNClib_Algo_AudioSource_Applicator));
866
867        BDBG_ASSERT(psPath);
868
869        /* TODO: apply slowly over time using GA > d > ST method */
870        /* apply desired */
871        if (pfSetDelay)
872        {
873                BSYSlib_List_IteratorHandle hIterator;
874
875                hIterator = BSYSlib_List_AcquireIterator(psPath->hSources);
876
877                while (BSYSlib_List_HasNext(hIterator))
878                {
879                        BSYNClib_AudioSource * psSource;
880
881                        psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
882
883                        if (psSource->sElement.sSnapshot.bSynchronize)
884                        {
885                                BSYNClib_UnsignedValue sDesired;
886                               
887                                BDBG_MSG(("[%d]  Applying audio source %u delay: %u ms", psPath->hChn->iIndex, psSource->sElement.uiIndex, 
888                                        BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
889
890                                sDesired.uiValue = BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiDesired, BSYNClib_Units_e27MhzTicks, psSource->sElement.sDelay.sSnapshot.ePreferredUnits);
891                                sDesired.eUnits = psSource->sElement.sDelay.sSnapshot.ePreferredUnits;
892
893                                rc = pfSetDelay(pvParm1, iParm2, psSource->sElement.uiIndex, &sDesired);
894                                if (rc) goto error;
895                               
896                                psSource->sElement.sDelay.sResults.uiApplied = psSource->sElement.sDelay.sResults.uiDesired;
897                                psSource->sStatus.sAppliedDelay.uiValue = BSYNClib_P_Convert(psSource->sElement.sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, psSource->sElement.sDelay.sSnapshot.ePreferredUnits);
898                                psSource->sStatus.sAppliedDelay.eUnits = psSource->sElement.sDelay.sSnapshot.ePreferredUnits;
899                        }
900                }
901
902                BSYSlib_List_ReleaseIterator(hIterator);
903        }
904       
905        goto end;
906       
907error:
908
909end:
910       
911        BDBG_LEAVE((BSYNClib_Algo_AudioSource_Applicator));
912        return rc;
913}
914
915void BSYNClib_Algo_RequantizeDelay(int iChannelIndex, unsigned int uiDelay, unsigned int uiQuantizationLevel, unsigned int * puiRequantizedDelay)
916{
917        unsigned int uiQuantizedDelay;
918
919        BDBG_ASSERT(puiRequantizedDelay);
920
921        if (uiQuantizationLevel)
922        {
923                BDBG_MSG(("[%d]  Performing delay requantization", iChannelIndex));
924                BDBG_MSG(("[%d]    delay: %u ms", iChannelIndex, BSYNClib_P_Convert(uiDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
925                BDBG_MSG(("[%d]    quantization level: %u ms", iChannelIndex, BSYNClib_P_Convert(uiQuantizationLevel, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
926
927                uiQuantizedDelay = uiDelay / uiQuantizationLevel;
928                if (uiDelay % uiQuantizationLevel)
929                {
930                        uiQuantizedDelay++;
931                }
932
933                uiQuantizedDelay *= uiQuantizationLevel;
934
935                BDBG_MSG(("[%d]    requantized delay: %u ms", iChannelIndex, BSYNClib_P_Convert(uiQuantizedDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
936        }
937        else
938        {
939                BDBG_MSG(("[%d]  Cannot perform requantization with zero quantization level.", iChannelIndex));
940                uiQuantizedDelay = uiDelay;
941        }
942
943        *puiRequantizedDelay = uiQuantizedDelay;
944}
945
946#define BSYNCLIB_IABS(x) (((x) < 0) ? ((unsigned)-(x)) : ((unsigned)(x)))
947
948void BSYNClib_Algo_CalculateJitterToleranceImprovementFactor(BSYNClib_Channel_Path * psVideo, BSYNClib_VideoSource * psSource, unsigned int uiCurrentDelay, int * piJtiFactor, unsigned int * puiAdditionalDelay)
949{
950        BSYSlib_List_IteratorHandle hIterator;
951    BSYNClib_VideoSource_JitterToleranceImprovementFactor * psLastFactor;
952    unsigned int uiDisplayVsyncPeriod = 0;
953    unsigned int uiTarget;
954    unsigned int uiThreshold;
955    unsigned int uiMeasurement;
956    unsigned int uiAdditionalDelay;
957    int iFactor;
958    int iError;
959    bool bAllowBottomFieldTarget;
960    bool bFoundSyncLockedSink = false;
961    bool bMeasurementValid = false;
962
963    BDBG_ASSERT(psVideo);
964    BDBG_ASSERT(psSource);
965    BDBG_ASSERT(piJtiFactor);
966    BDBG_ASSERT(puiAdditionalDelay);
967
968        BDBG_ENTER((BSYNClib_Algo_CalculateJitterToleranceImprovementFactor));
969
970    BDBG_MSG(("[%d]  Jitter Tolerance Improvement", psVideo->hChn->iIndex));
971
972        hIterator = BSYSlib_List_AcquireIterator(psVideo->hSinks);
973
974        while (BSYSlib_List_HasNext(hIterator) && !bFoundSyncLockedSink)
975        {
976                BSYNClib_VideoSink * psSink;
977
978                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
979
980                /* use first synchronized sink as sync-locked driver */
981                /* TODO: need better way to determine which display is sync-locked */
982                if (psSink->sElement.sSnapshot.bSynchronize)
983                {
984                        bFoundSyncLockedSink = true;
985                       
986                        uiDisplayVsyncPeriod = BSYNClib_VideoFormat_P_GetVsyncPeriod(&psSink->sFormat);
987                    BDBG_MSG(("[%d]    Display %u vsync period: %u ms", psVideo->hChn->iIndex, psSink->sElement.uiIndex, 
988                                BSYNClib_P_Convert(uiDisplayVsyncPeriod, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
989                }
990        }
991
992        BSYSlib_List_ReleaseIterator(hIterator);
993
994        bAllowBottomFieldTarget = psSource->sFormat.sSnapshot.bInterlaced;
995    BDBG_MSG(("[%d]    Allow bottom field target: %s", psVideo->hChn->iIndex, bAllowBottomFieldTarget ? "true" : "false"));
996                       
997    /* We want to avoid the following PTS/STC phase boundaries:
998       0, 1 field, and 1 frame
999       Therefore, 1/2 the display vsync period gives the most amount of jitter tolerance */
1000    uiTarget = uiDisplayVsyncPeriod / 2;
1001
1002    BDBG_MSG(("[%d]    Jitter tolerance target: %u ms", psVideo->hChn->iIndex, 
1003                BSYNClib_P_Convert(uiTarget, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1004
1005        if (uiDisplayVsyncPeriod && psSource->sElement.sDelay.sSnapshot.bValid)
1006        {
1007                bMeasurementValid = true;
1008                uiMeasurement = psSource->sElement.sDelay.sSnapshot.uiMeasured;
1009                uiThreshold = psSource->sSnapshot.uiJitterToleranceImprovementThreshold;
1010                psLastFactor = &psSource->sResults.sJtiFactor;
1011                BDBG_MSG(("[%d]    Video source %u measurement: %u ms", psVideo->hChn->iIndex, psSource->sElement.uiIndex, 
1012                        BSYNClib_P_Convert(uiMeasurement, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1013
1014            /*
1015                error = reference - output
1016            */
1017                iError = (signed)uiTarget - (signed)uiMeasurement;
1018               
1019                BDBG_MSG(("[%d]    Error: %d ms", psVideo->hChn->iIndex, 
1020                        BSYNClib_P_ConvertSigned(iError, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1021
1022                if (bAllowBottomFieldTarget)
1023                {
1024                    int iBottomFieldError;
1025
1026                    iBottomFieldError = (signed)(uiTarget + uiDisplayVsyncPeriod) - (signed)uiMeasurement;
1027
1028                BDBG_MSG(("[%d]    Bottom field error: %d ms", psVideo->hChn->iIndex, 
1029                                BSYNClib_P_ConvertSigned(iBottomFieldError, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1030
1031                if (BSYNCLIB_IABS(iBottomFieldError) < BSYNCLIB_IABS(iError))
1032                {
1033                        iError = iBottomFieldError;
1034                }
1035                }
1036
1037            /* if the error is outside the threshold, might as well go ahead and correct for it */
1038                if (BSYNCLIB_IABS(iError) > uiThreshold)
1039                {
1040                        iFactor = psLastFactor->iValue - iError;
1041
1042                if (iFactor > (signed)(uiDisplayVsyncPeriod + uiThreshold))
1043                {
1044                    iFactor -= 2 * (signed)uiDisplayVsyncPeriod;
1045                }
1046                else if (iFactor < -(signed)(uiDisplayVsyncPeriod + uiThreshold))
1047                {
1048                        iFactor += 2 * (signed)uiDisplayVsyncPeriod;
1049                }
1050
1051                /* save to last factor and mark as adjusted */
1052                psLastFactor->bAdjusted = true;
1053                psLastFactor->iValue = iFactor;
1054                }
1055                else
1056                {
1057                iFactor = psLastFactor->iValue;
1058                psLastFactor->bAdjusted = false;
1059                psLastFactor->iValue = 0;
1060                }
1061        }
1062        else
1063        {
1064        iFactor = 0;
1065        uiAdditionalDelay = 0;
1066        }
1067
1068    BDBG_MSG(("[%d]    JTI factor: %d ms", psVideo->hChn->iIndex, 
1069                BSYNClib_P_ConvertSigned(iFactor, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1070
1071    /* negative correction factor means that we need to add one display period delay */
1072    if ((iFactor < 0 && !uiCurrentDelay) || 
1073        ((signed)uiCurrentDelay + iFactor < 0)) 
1074    {
1075        uiAdditionalDelay = uiDisplayVsyncPeriod;
1076    }
1077    else /* any other delay */
1078    {
1079        uiAdditionalDelay = 0;
1080    }
1081
1082    BDBG_MSG(("[%d]    Additional delay: %d ms", psVideo->hChn->iIndex, 
1083                BSYNClib_P_Convert(uiAdditionalDelay, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
1084
1085        *piJtiFactor = iFactor;
1086        *puiAdditionalDelay = uiAdditionalDelay;
1087
1088        BDBG_LEAVE((BSYNClib_Algo_CalculateJitterToleranceImprovementFactor));
1089}
1090
Note: See TracBrowser for help on using the repository browser.