source: svn/trunk/newcon3bcm2_21bu/magnum/syslib/synclib/7552/bsynclib_channel_priv.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 36.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_channel_priv.c $
11* $brcm_Revision: Hydra_Software_Devel/23 $
12* $brcm_Date: 2/9/12 9:17p $
13*
14* Revision History:
15*
16* $brcm_Log: /magnum/syslib/synclib/noarch/bsynclib_channel_priv.c $
17*
18* Hydra_Software_Devel/23   2/9/12 9:17p bandrews
19* SW7358-219: really apply zero delay to sinks with mismatched rates
20*
21* Hydra_Software_Devel/22   2/8/12 4:07p bandrews
22* SW7358-219: apply zero delay to sinks with mismatched rates
23*
24* Hydra_Software_Devel/21   1/20/12 7:52p bandrews
25* SW7358-219: ensure that synclib never tries to apply BVN offsets
26* between displays that don't have matching refresh rates
27*
28* Hydra_Software_Devel/20   1/19/12 8:39p bandrews
29* SW7346-640: fix the units between estimated delay and measured delay
30* and threshold
31*
32* Hydra_Software_Devel/19   7/8/11 2:40p bandrews
33* SW7405-3884: punch RMD settings through properly, hParent wasn't set
34* during create
35*
36* Hydra_Software_Devel/18   7/7/11 8:36p bandrews
37* SW7405-3884: ram through RMD settings
38*
39* Hydra_Software_Devel/17   8/11/10 4:29p bandrews
40* SW7405-4436: need to get sync status before printing it at end of
41* process
42*
43* Hydra_Software_Devel/16   8/9/10 9:42p bandrews
44* SW7405-885: two step units conversion
45*
46* Hydra_Software_Devel/15   6/22/10 5:44p bandrews
47* SW7405-4471: logic should be default to false for a/v sync condition
48*
49* Hydra_Software_Devel/14   6/15/10 6:42p bandrews
50* SW7405-4471: only perform lipsync adjustments under correct conditions
51*
52* Hydra_Software_Devel/13   6/15/10 6:39p bandrews
53* SW7405-4436: add more
54*
55* Hydra_Software_Devel/12   6/15/10 6:38p bandrews
56* SW7405-4436: implemented
57*
58* Hydra_Software_Devel/11   3/22/10 5:44p bandrews
59* sw7408-83: ensure timers are initialized; add video unconditional
60* unmute
61*
62* Hydra_Software_Devel/10   3/19/10 2:47p bandrews
63* SW7405-3774: merge mute control
64*
65* Hydra_Software_Devel/SW7405-3774/1   2/17/10 6:17p bandrews
66* SW7405-3774: attempt to fix early audio unmute then mute
67*
68* Hydra_Software_Devel/9   2/12/10 8:46p bandrews
69* SW7405-3912: assert all inputs are not null
70*
71* Hydra_Software_Devel/8   1/26/10 9:00p bandrews
72* SW7405-3774: added mute control support
73*
74* Hydra_Software_Devel/7   12/10/09 9:18p bandrews
75* SW7401-3634: adding PWC (now JTI) support to synclib
76*
77* Hydra_Software_Devel/6   7/24/09 4:15p bandrews
78* PR48566: support preferred units
79*
80* Hydra_Software_Devel/5   11/26/08 5:10p bandrews
81* PR49294: Added precision lipsync flag
82*
83* Hydra_Software_Devel/4   8/6/08 10:03a erickson
84* PR45459: fix release build warnings
85*
86* Hydra_Software_Devel/3   6/30/08 9:06p bandrews
87* PR40090: Fixed copy paste error introduced by last fix
88*
89* Hydra_Software_Devel/2   4/3/08 2:33p bandrews
90* PR40090: synclib needs to have different contexts for syslib callbacks
91* and synclib callbacks
92*
93* Hydra_Software_Devel/1   3/24/08 3:09p bandrews
94* PR40865: Fixed
95*
96* Hydra_Software_Devel/7   2/26/08 10:21p bandrews
97* PR37951: Fixed units.  Implemented static rate mismatch detection.
98*
99* Hydra_Software_Devel/6   2/26/08 3:19p bandrews
100* PR37951: Fixed expiry of timers
101*
102* Hydra_Software_Devel/5   2/22/08 8:28p bandrews
103* PR37951: Fixed bug in units conversion
104*
105* Hydra_Software_Devel/4   2/22/08 3:08p bandrews
106* PR37951: Debugging callbacks
107*
108* Hydra_Software_Devel/3   2/21/08 6:02p bandrews
109* PR37951: Default video source numbers to 45KHz domain.  Improved
110* handling of unsynchronized elements
111*
112* Hydra_Software_Devel/2   2/20/08 10:03p bandrews
113* PR37951: Updated based on feedback from usage
114*
115* Hydra_Software_Devel/1   1/3/08 6:02p bandrews
116* PR37951: Updated based on initial feedback
117*
118* Hydra_Software_Devel/1   12/12/07 2:53p bandrews
119* PR37951: Initial check-in
120***************************************************************************/
121
122#include "bstd.h"
123#include "bkni.h"
124#include "bsyslib.h"
125#include "bsynclib.h"
126#include "bsynclib_priv.h"
127#include "bsynclib_channel_priv.h"
128#include "bsynclib_algo.h"
129#include "bsynclib_mute_control.h"
130
131BDBG_MODULE(synclib);
132
133/*
134Summary:
135Opens a SYNC lib channel
136Description:
137*/
138BERR_Code BSYNClib_Channel_P_Create(
139        const BSYNClib_Settings * psLibSettings,
140        const BSYNClib_Channel_Settings * psSettings,
141        BSYNClib_Channel_Handle * phChn /* [out] */
142)
143{
144        BERR_Code rc = BERR_SUCCESS;
145        BSYNClib_Channel_Handle hChn = NULL;
146        BSYNClib_StateMachine_Settings sMachineSettings;
147        BSYNClib_RateMismatchDetector_Settings sRmdSettings;
148
149        BDBG_ENTER(BSYNClib_Channel_P_Create);
150
151        BDBG_ASSERT(phChn);
152
153        hChn = (BSYNClib_Channel_Handle)BKNI_Malloc(sizeof(struct BSYNClib_Channel_Impl));
154        if (!hChn)
155        {
156                rc = BERR_OUT_OF_SYSTEM_MEMORY;
157                goto error;
158        }
159
160    BDBG_MSG(("create channel: %p", (void *)hChn));
161
162        BKNI_Memset(hChn, 0, sizeof(struct BSYNClib_Channel_Impl));
163
164        if (psSettings)
165        {
166                hChn->sSettings = *psSettings;
167        }
168
169        BSYNClib_Channel_P_GetDefaultConfig(&hChn->sConfig);
170
171        BSYNClib_Channel_P_GetDefaultStatus(&hChn->sStatus);
172
173        /* open state machine */
174        BSYNClib_StateMachine_GetDefaultSettings(&sMachineSettings);
175        rc = BSYNClib_StateMachine_Open(&sMachineSettings, &hChn->hMachine);
176        if (rc) goto error;
177
178        /* start state machine */
179    BDBG_MSG(("chn %p: start", (void *)hChn));
180        rc = BSYNClib_StateMachine_SendSignal(hChn->hMachine, BSYNClib_StateMachine_Signal_eStart);
181        if (rc) goto error;
182
183        /* allocate timers */
184        if (hChn->sSettings.cbTimer.pfCreate)
185        {
186                void *pvParm1 = hChn->sSettings.cbTimer.pvParm1;
187                int iParm2 = hChn->sSettings.cbTimer.iParm2;
188                unsigned int i = 0;
189
190                /* create timer resource pool */
191                hChn->psTimers = BSYNClib_ResourcePool_Create();
192
193                for (i = 0; i < BSYNCLIB_TIMER_COUNT; i++)
194                {
195                        BSYNClib_Timer * psTimer;
196
197                        psTimer = (BSYNClib_Timer *)BKNI_Malloc(sizeof(BSYNClib_Timer));
198                        if (!psTimer) goto error;
199
200                        BSYNClib_Timer_Init(psTimer);
201
202                        BDBG_MSG(("chn %p: Creating timer %p(%d)", hChn, psTimer, i));
203                        rc = hChn->sSettings.cbTimer.pfCreate(pvParm1, iParm2, &psTimer->hTimer);
204                        if (rc) goto error;
205
206                        BSYNClib_ResourcePool_Add(hChn->psTimers, psTimer);
207                }
208
209                /* Timer for task context switch */
210                hChn->psTaskTimer = (BSYNClib_Timer *)BKNI_Malloc(sizeof(BSYNClib_Timer));
211                if (!hChn->psTaskTimer) goto error;
212
213                BSYNClib_Timer_Init(hChn->psTaskTimer);
214
215                BDBG_MSG(("chn %p: Creating task context switch timer %p", hChn, hChn->psTaskTimer));
216                rc = hChn->sSettings.cbTimer.pfCreate(pvParm1, iParm2, &hChn->psTaskTimer->hTimer);
217                if (rc) goto error;
218
219                /* Timer for mute control task context switch */
220                hChn->psMuteControlTaskTimer = (BSYNClib_Timer *)BKNI_Malloc(sizeof(BSYNClib_Timer));
221                if (!hChn->psMuteControlTaskTimer) goto error;
222
223                BSYNClib_Timer_Init(hChn->psMuteControlTaskTimer);
224
225                BDBG_MSG(("chn %p: Creating mute control task context switch timer %p", hChn, hChn->psMuteControlTaskTimer));
226                rc = hChn->sSettings.cbTimer.pfCreate(pvParm1, iParm2, &hChn->psMuteControlTaskTimer->hTimer);
227                if (rc) goto error;
228        }
229
230        /* open rate mismatch detector */
231        BSYNClib_RateMismatchDetector_GetDefaultSettings(&sRmdSettings);
232        sRmdSettings.sMismatch.uiTimeout = psLibSettings->sVideo.sRateMismatchDetection.uiTimeout;
233        sRmdSettings.sMismatch.uiAcceptableMtbcLower = psLibSettings->sVideo.sRateMismatchDetection.uiAcceptableMtbcLower;
234        sRmdSettings.sMismatch.uiAcceptableMtbcUpper = psLibSettings->sVideo.sRateMismatchDetection.uiAcceptableMtbcUpper;
235        sRmdSettings.sMismatch.uiAcceptableTtlc = psLibSettings->sVideo.sRateMismatchDetection.uiAcceptableTtlc;
236        sRmdSettings.sRematch.uiTimeout = psLibSettings->sVideo.sRateMismatchDetection.uiTimeout;
237        sRmdSettings.sRematch.uiAcceptableTtlc = psLibSettings->sVideo.sRateRematchDetection.uiAcceptableTtlc;
238        rc = BSYNClib_RateMismatchDetector_Open(hChn, &sRmdSettings, &hChn->hDetector);
239        if (rc) goto error;
240
241        hChn->sVideo.hSources = BSYSlib_List_Create();
242        hChn->sVideo.hSinks = BSYSlib_List_Create();
243        hChn->sAudio.hSources = BSYSlib_List_Create();
244        hChn->sAudio.hSinks = BSYSlib_List_Create();
245
246#if BSYNCLIB_JITTER_TOLERANCE_IMPROVEMENT_SUPPORT
247    BDBG_MSG(("chn %p: jitter tolerance improvement supported", hChn));
248#endif
249
250#if BSYNCLIB_UNCONDITIONAL_VIDEO_UNMUTE_SUPPORT
251    BDBG_MSG(("chn %p: unconditional video unmute supported", hChn));
252#endif
253
254#if BSYNCLIB_UNCONDITIONAL_AUDIO_UNMUTE_SUPPORT
255    BDBG_MSG(("chn %p: unconditional audio unmute supported", hChn));
256#endif
257
258        *phChn = hChn;
259
260        goto end;
261
262error:
263
264        if (hChn)
265        {
266                BSYNClib_Channel_P_Destroy(hChn);
267                *phChn = NULL;
268        }
269
270end:
271
272        BDBG_LEAVE(BSYNClib_Channel_P_Create);
273        return rc;
274}
275
276
277/*
278Summary:
279Closes an SYNC lib channel
280Description:
281*/
282void BSYNClib_Channel_P_Destroy(
283        BSYNClib_Channel_Handle hChn
284)
285{
286        BSYNClib_Channel_Config sConfig;
287
288        BDBG_ENTER(BSYNClib_Channel_P_Destroy);
289
290        BDBG_ASSERT(hChn);
291
292        BSYNClib_Channel_P_Stop(hChn);
293
294        /* this will empty the lists and destroy all the elements (freeing up the timers) */
295        BSYNClib_Channel_GetConfig(hChn, &sConfig);
296        sConfig.bEnabled = false;
297        sConfig.uiVideoSourceCount = 0;
298        sConfig.uiVideoSinkCount = 0;
299        sConfig.uiAudioSourceCount = 0;
300        sConfig.uiAudioSinkCount = 0;
301        BSYNClib_Channel_SetConfig(hChn, &sConfig);
302
303        if (hChn->hMachine)
304        {
305                BSYNClib_StateMachine_Close(hChn->hMachine);
306        }
307
308        if (hChn->hDetector)
309        {
310                BSYNClib_RateMismatchDetector_Close(hChn->hDetector);
311        }
312
313        /* deallocate timers */
314        if (hChn->sSettings.cbTimer.pfDestroy)
315        {
316                BSYSlib_List_IteratorHandle hIterator;
317                void * pvParm1 = hChn->sSettings.cbTimer.pvParm1;
318                int iParm2 = hChn->sSettings.cbTimer.iParm2;
319
320                /* Timer for mute control task context switch */
321                BDBG_MSG(("chn %p: Destroying mute control task context switch timer %p", hChn, hChn->psMuteControlTaskTimer->hTimer));
322                hChn->sSettings.cbTimer.pfDestroy(pvParm1, iParm2, hChn->psMuteControlTaskTimer->hTimer);
323                hChn->psMuteControlTaskTimer->hTimer = NULL;
324                BKNI_Free(hChn->psMuteControlTaskTimer);
325
326                /* Timer for task context switch */
327                BDBG_MSG(("chn %p: Destroying task context switch timer %p", hChn, hChn->psTaskTimer->hTimer));
328                hChn->sSettings.cbTimer.pfDestroy(pvParm1, iParm2, hChn->psTaskTimer->hTimer);
329                hChn->psTaskTimer->hTimer = NULL;
330                BKNI_Free(hChn->psTaskTimer);
331
332                /* TODO: remove dependency on resource pool impl */
333                hIterator = BSYSlib_List_AcquireIterator(hChn->psTimers->hResources);
334
335                while (BSYSlib_List_HasNext(hIterator))
336                {
337                        BSYNClib_Timer * psTimer;
338
339                        psTimer = (BSYNClib_Timer *)BSYSlib_List_Next(hIterator);
340
341                        if (psTimer)
342                        {
343                                BDBG_MSG(("chn %p: Destroying timer %p", hChn, psTimer->hTimer));
344
345                                hChn->sSettings.cbTimer.pfDestroy(pvParm1, iParm2, psTimer->hTimer);
346                                psTimer->hTimer = NULL;
347
348                                BSYNClib_ResourcePool_Remove(hChn->psTimers, psTimer);
349
350                                BKNI_Free(psTimer);
351                        }
352                }
353
354                /* destroy timer resource pool */
355                BSYNClib_ResourcePool_Destroy(hChn->psTimers);
356        }
357
358        BSYSlib_List_Destroy(hChn->sVideo.hSources);
359        BSYSlib_List_Destroy(hChn->sVideo.hSinks);
360        BSYSlib_List_Destroy(hChn->sAudio.hSources);
361        BSYSlib_List_Destroy(hChn->sAudio.hSinks);
362
363        /* free me */
364        BKNI_Free(hChn);
365
366        BDBG_LEAVE(BSYNClib_Channel_P_Destroy);
367}
368
369/*******************************************
370syslib framework stuff
371*******************************************/
372
373BERR_Code BSYNClib_Channel_P_CancelTimer_isr(
374        BSYNClib_Channel_Handle hChn,
375        BSYNClib_Timer * psTimer
376)
377{
378        BERR_Code rc = BERR_SUCCESS;
379
380        BDBG_ENTER(BSYNClib_Channel_P_CancelTimer_isr);
381
382        BDBG_ASSERT(hChn);
383        BDBG_ASSERT(psTimer);
384
385        if (psTimer->bScheduled)
386        {
387                if (hChn->sSettings.cbTimer.pfCancel_isr)
388                {
389                        rc = hChn->sSettings.cbTimer.pfCancel_isr(
390                                hChn->sSettings.cbTimer.pvParm1, 
391                                hChn->sSettings.cbTimer.iParm2, 
392                                psTimer->hTimer);
393                        if (rc) goto error;
394                }
395                psTimer->bScheduled = false;
396        }
397
398        goto end;
399
400error:
401
402end:
403
404        BDBG_LEAVE(BSYNClib_Channel_P_CancelTimer_isr);
405        return rc;
406}
407
408BERR_Code BSYNClib_Channel_P_StartTimer_isr(
409        BSYNClib_Channel_Handle hChn,
410        BSYNClib_Timer * psTimer,
411        unsigned long ulTimeout,
412        BSYSlib_Timer_ExpiryHandler pfTimerExpired,
413        void * pvParm1,
414        int iParm2
415)
416{
417        BERR_Code rc = BERR_SUCCESS;
418
419        BDBG_ENTER(BSYNClib_Channel_P_StartTimer_isr);
420
421        BDBG_ASSERT(hChn);
422        BDBG_ASSERT(psTimer);
423        BDBG_ASSERT(pfTimerExpired);
424
425        if (hChn->sSettings.cbTimer.pfStart_isr)
426        {
427                BSYSlib_Timer_Settings sTimer;
428
429                sTimer.ulTimeout = ulTimeout;
430                sTimer.pvParm1 = pvParm1;
431                sTimer.iParm2 = iParm2;
432                sTimer.pfTimerExpired = pfTimerExpired;
433
434                /* just reusing stack space here to reduce typing */
435                pvParm1 = hChn->sSettings.cbTimer.pvParm1;
436                iParm2 = hChn->sSettings.cbTimer.iParm2;
437
438                /* clean up old timer if any */
439                rc = BSYNClib_Channel_P_CancelTimer_isr(hChn, psTimer);
440                if (rc) goto error;
441
442                /* reschedule timer */
443                rc = hChn->sSettings.cbTimer.pfStart_isr(pvParm1, iParm2, psTimer->hTimer, &sTimer);
444                if (rc) goto error;
445
446                psTimer->bScheduled = true;
447        }
448
449        goto end;
450
451error:
452
453end:
454
455        BDBG_LEAVE(BSYNClib_Channel_P_StartTimer_isr);
456        return rc;
457}
458
459
460/*
461Summary:
462Handles expiry of any channel timer except for the zero length context switching timer
463*/
464BERR_Code BSYNClib_Channel_P_TimerExpired(
465        BSYNClib_Channel_Handle hChn,
466        BSYSlib_Timer_Handle hTimer
467)
468{
469        BERR_Code rc = BERR_SUCCESS;
470        BSYSlib_List_IteratorHandle hIterator;
471        BDBG_ENTER(BSYNClib_Channel_P_TimerExpired);
472
473        BDBG_ASSERT(hChn);
474        BDBG_ASSERT(hTimer);
475
476        /* clean up timer that expired */
477        /* TODO: remove dependency on resource pool internals */
478        hIterator = BSYSlib_List_AcquireIterator(hChn->psTimers->hResources);
479        while (BSYSlib_List_HasNext(hIterator))
480        {
481                BSYNClib_Timer * psTimer;
482
483                psTimer = (BSYNClib_Timer *)BSYSlib_List_Next(hIterator);
484                if (psTimer->hTimer == hTimer)
485                {
486                        BKNI_EnterCriticalSection();
487                        BSYNClib_Timer_Reset_isr(psTimer);
488                        BKNI_LeaveCriticalSection();
489                        break;
490                }
491        }
492        BSYSlib_List_ReleaseIterator(hIterator);
493
494        BDBG_LEAVE(BSYNClib_Channel_P_TimerExpired);
495        return rc;
496}
497
498BERR_Code BSYNClib_Channel_P_ScheduleTask_isr(BSYNClib_Channel_Handle hChn)
499{
500        BERR_Code rc = BERR_SUCCESS;
501        BSYNClib_Channel_Results * psResults;
502
503        BDBG_ENTER(BSYNClib_Channel_P_ScheduleTask_isr);
504
505        BDBG_ASSERT(hChn);
506
507        psResults = &hChn->sResults;
508
509        if (!psResults->bSyncTaskScheduled)
510        {
511#ifdef BSYSLIB_TASK_SUPPORT
512                if (hChn->sSettings.cbTask.pfSchedule_isr)
513                {
514                        BSYSlib_Task_Settings sTask;
515
516                        sTask.pvParm1 = hChn;
517                        sTask.iParm2 = 0;
518                        sTask.pfDoTask = &BSYNClib_Channel_P_Process;
519
520                        rc = hChn->sSettings.cbTask.pfSchedule_isr(hChn->sSettings.cbTask.pvParm1, 
521                                hChn->sSettings.cbTask.iParm2, &sTask);
522                }
523#else
524                rc = BSYNClib_Channel_P_StartTimer_isr(hChn,
525                        hChn->psTaskTimer, 0,
526                        &BSYNClib_Channel_P_TaskTimerExpired, hChn, 0);
527#endif
528
529                if (!rc)
530                {
531                        psResults->bSyncTaskScheduled = true;
532                        BDBG_MSG(("[%d] Sync task scheduled", hChn->iIndex));
533                }
534                else
535                {
536                        psResults->bSyncTaskScheduled = false;
537                }
538                if (rc) goto error;
539        }
540        else
541        {
542                BDBG_MSG(("[%d] Sync task already scheduled", hChn->iIndex));
543        }
544
545        goto end;
546
547error:
548
549end:
550        BDBG_LEAVE(BSYNClib_Channel_P_ScheduleTask_isr);
551        return rc;
552}
553
554BERR_Code BSYNClib_Channel_P_TaskTimerExpired(void * pvParm1, int iParm2, BSYSlib_Timer_Handle hTimer)
555{
556        BERR_Code rc = BERR_SUCCESS;
557        BSYNClib_Channel_Handle hChn = pvParm1;
558
559        BDBG_ENTER(BSYNClib_Channel_P_TaskTimerExpired);
560
561        BSTD_UNUSED(iParm2);
562
563        BDBG_ASSERT(hChn);
564        BDBG_ASSERT(hTimer);
565
566        BDBG_MSG(("[%d] Sync task timer expired", hChn->iIndex));
567
568        rc = BSYNClib_Channel_P_TimerExpired(hChn, hTimer);
569        if (rc) goto end;
570
571        rc = BSYNClib_Channel_P_Process(hChn, 0);
572
573end:
574        BDBG_LEAVE(BSYNClib_Channel_P_TaskTimerExpired);
575        return rc;
576}
577
578bool BSYNClib_Channel_P_SyncCheck(
579        BSYNClib_Channel_Handle hChn
580)
581{
582        BSYSlib_List_IteratorHandle hIterator;
583        bool bSync = true;
584
585        BDBG_ENTER(BSYNClib_Channel_P_SyncCheck);
586
587        BDBG_ASSERT(hChn);
588
589        BDBG_MSG(("[%d] Performing sync check...", hChn->iIndex));
590
591        /* TODO: at least one video and audio source should pass and be synchronized in order to sync av */
592        /* TODO: all video sinks should pass before doing v/v sync */
593        /* TODO: all audio sinks should pass before doing a/a sync */
594        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSources);
595
596        while (BSYSlib_List_HasNext(hIterator))
597        {
598                BSYNClib_VideoSource * psSource;
599
600                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
601
602                bSync = bSync && BSYNClib_VideoSource_SyncCheck(psSource);
603        }
604
605        BSYSlib_List_ReleaseIterator(hIterator);
606
607        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSinks);
608
609        while (BSYSlib_List_HasNext(hIterator))
610        {
611                BSYNClib_VideoSink * psSink;
612
613                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
614
615                /* invisible windows are ignored */
616                if (psSink->sSnapshot.bVisible)
617                {
618                        bSync = bSync && BSYNClib_VideoSink_SyncCheck(psSink);
619                }
620        }
621
622        BSYSlib_List_ReleaseIterator(hIterator);
623
624        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSources);
625
626        while (BSYSlib_List_HasNext(hIterator))
627        {
628                BSYNClib_AudioSource * psSource;
629
630                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
631
632                bSync = bSync && BSYNClib_AudioSource_SyncCheck(psSource);
633        }
634
635        BSYSlib_List_ReleaseIterator(hIterator);
636
637        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSinks);
638
639        while (BSYSlib_List_HasNext(hIterator))
640        {
641                BSYNClib_AudioSink * psSink;
642
643                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
644
645                bSync = bSync && BSYNClib_AudioSink_SyncCheck(psSink);
646        }
647
648        BSYSlib_List_ReleaseIterator(hIterator);
649
650        BDBG_LEAVE(BSYNClib_Channel_P_SyncCheck);
651        return bSync;
652}
653
654void BSYNClib_Channel_P_Snapshot_isr(
655        BSYNClib_Channel_Handle hChn
656)
657{
658        BSYSlib_List_IteratorHandle hIterator;
659
660        BDBG_ENTER(BSYNClib_Channel_P_Snapshot_isr);
661
662        BDBG_ASSERT(hChn);
663
664        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sVideo.hSources);
665
666        while (BSYSlib_List_HasNext_isr(hIterator))
667        {
668                BSYNClib_VideoSource * psSource;
669
670                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next_isr(hIterator);
671
672                BSYNClib_VideoSource_Snapshot_isr(psSource);
673        }
674
675        BSYSlib_List_ReleaseIterator_isr(hIterator);
676
677        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sVideo.hSinks);
678
679        while (BSYSlib_List_HasNext_isr(hIterator))
680        {
681                BSYNClib_VideoSink * psSink;
682
683                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next_isr(hIterator);
684
685                BSYNClib_VideoSink_Snapshot_isr(psSink);
686        }
687
688        BSYSlib_List_ReleaseIterator_isr(hIterator);
689
690        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sAudio.hSources);
691
692        while (BSYSlib_List_HasNext_isr(hIterator))
693        {
694                BSYNClib_AudioSource * psSource;
695
696                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next_isr(hIterator);
697
698                BSYNClib_AudioSource_Snapshot_isr(psSource);
699        }
700
701        BSYSlib_List_ReleaseIterator_isr(hIterator);
702
703        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sAudio.hSinks);
704
705        while (BSYSlib_List_HasNext_isr(hIterator))
706        {
707                BSYNClib_AudioSink * psSink;
708
709                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next_isr(hIterator);
710
711                BSYNClib_AudioSink_Snapshot_isr(psSink);
712        }
713
714        BSYSlib_List_ReleaseIterator_isr(hIterator);
715
716        BDBG_LEAVE(BSYNClib_Channel_P_Snapshot_isr);
717}
718
719#if BDBG_DEBUG_BUILD
720static const char * gpcSyncStateNames[] =
721{
722        "stopped",
723        "acquire",
724        "sync",
725        "track",
726        NULL
727};
728#endif
729
730BERR_Code BSYNClib_Channel_P_Process(void * pvParm1, int iParm2)
731{
732        BERR_Code rc = BERR_SUCCESS;
733        bool bSync = true;
734        BSYNClib_Channel_Handle hChn = pvParm1;
735        BSYNClib_StateMachine_Status sStatus;
736
737        BDBG_ENTER(BSYNClib_Channel_P_Process);
738
739        BSTD_UNUSED(iParm2);
740
741        BDBG_ASSERT(hChn);
742
743        BKNI_EnterCriticalSection();
744        hChn->sResults.bSyncTaskScheduled = false;
745        BKNI_LeaveCriticalSection();
746
747        BDBG_MSG(("[%d] Sync process invoked", hChn->iIndex));
748
749        BDBG_MSG(("[%d] Snapshotting data...", hChn->iIndex));
750
751        /* snapshot all the data we will use for our calcs
752        this is so we don't hold the cs for a long time while doing those calcs */
753        BKNI_EnterCriticalSection();
754        BSYNClib_Channel_P_Snapshot_isr(hChn);
755        BKNI_LeaveCriticalSection();
756
757        if (!BSYNClib_Channel_P_Enabled(hChn))
758        {
759                goto end;
760        }
761
762        /* do a sync check */
763        bSync = BSYNClib_Channel_P_SyncCheck(hChn);
764
765        BDBG_MSG(("[%d] Sync check %s", hChn->iIndex, bSync ? "passed" : "failed"));
766
767        /* send sync check signal */
768        if (bSync)
769        {
770                rc = BSYNClib_StateMachine_SendSignal(hChn->hMachine, BSYNClib_StateMachine_Signal_eCheckPassed);
771                if (rc) goto error;
772
773                /* also send data changed signal, because we got here */
774                rc = BSYNClib_StateMachine_SendSignal(hChn->hMachine, BSYNClib_StateMachine_Signal_eDataChanged);
775                if (rc) goto error;
776        }
777        else
778        {
779                rc = BSYNClib_StateMachine_SendSignal(hChn->hMachine, BSYNClib_StateMachine_Signal_eCheckFailed);
780                if (rc) goto error;
781        }
782
783        rc = BSYNClib_StateMachine_GetStatus(hChn->hMachine, &sStatus);
784        if (rc) goto error;
785
786        /* if after all we have reached the sync state, apply delays */
787        if (sStatus.eState == BSYNClib_StateMachine_State_eSync)
788        {
789                rc = BSYNClib_Channel_P_Synchronize(hChn);
790                if (rc) goto error;
791
792                rc = BSYNClib_StateMachine_SendSignal(hChn->hMachine, BSYNClib_StateMachine_Signal_eDelayApplied);
793                if (rc) goto error;
794        }
795
796        rc = BSYNClib_StateMachine_GetStatus(hChn->hMachine, &sStatus);
797        if (rc) goto error;
798
799        BDBG_MSG(("[%d] End process sync state: %s", hChn->iIndex, gpcSyncStateNames[sStatus.eState]));
800
801        /* call callbacks that don't result from sync */
802        rc = BSYNClib_Channel_P_GenerateCallbacks(hChn);
803        if (rc) goto error;
804
805        goto end;
806
807error:
808
809end:
810
811        BDBG_LEAVE(BSYNClib_Channel_P_Process);
812        return rc;
813}
814
815BERR_Code BSYNClib_Channel_P_ApplyDelays(BSYNClib_Channel_Handle hChn)
816{
817        BERR_Code rc = BERR_SUCCESS;
818        void * pvParm1;
819        int iParm2;
820
821        BDBG_ENTER(BSYNClib_Channel_P_ApplyDelays);
822
823        BDBG_ASSERT(hChn);
824
825        pvParm1 = hChn->sSettings.sVideo.sSource.cbDelay.pvParm1;
826        iParm2 = hChn->sSettings.sVideo.sSource.cbDelay.iParm2;
827
828        rc = BSYNClib_Algo_VideoSource_Applicator(&hChn->sVideo, hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelay, pvParm1, iParm2);
829        if (rc) goto error;
830
831        pvParm1 = hChn->sSettings.sVideo.sSink.cbDelay.pvParm1;
832        iParm2 = hChn->sSettings.sVideo.sSink.cbDelay.iParm2;
833
834        rc = BSYNClib_Algo_VideoSink_Applicator(&hChn->sVideo, hChn->sSettings.sVideo.sSink.cbDelay.pfSetDelay, pvParm1, iParm2);
835        if (rc) goto error;
836
837        pvParm1 = hChn->sSettings.sAudio.sSource.cbDelay.pvParm1;
838        iParm2 = hChn->sSettings.sAudio.sSource.cbDelay.iParm2;
839
840        rc = BSYNClib_Algo_AudioSource_Applicator(&hChn->sAudio, hChn->sSettings.sAudio.sSource.cbDelay.pfSetDelay, pvParm1, iParm2);
841        if (rc) goto error;
842
843        pvParm1 = hChn->sSettings.sAudio.sSink.cbDelay.pvParm1;
844        iParm2 = hChn->sSettings.sAudio.sSink.cbDelay.iParm2;
845
846        rc = BSYNClib_Algo_AudioSink_Applicator(&hChn->sAudio, hChn->sSettings.sAudio.sSink.cbDelay.pfSetDelay, pvParm1, iParm2);
847        if (rc) goto error;
848
849        /* TODO: copy desired and applied delays to status */
850
851        /* start unmute timers after applying delays */
852        rc = BSYNClib_MuteControl_StartUnmuteTimers(hChn);
853        if (rc) goto error;
854
855        goto end;
856
857error:
858
859end:
860
861        BDBG_LEAVE((BSYNClib_Channel_P_ApplyDelays));
862        return rc;
863}
864
865/* TODO: merge these into the rework for separate state machines for a/a, v/v, a/v sync */
866bool BSYNClib_Channel_P_AudioVideoSyncCheck(BSYNClib_Channel_Handle hChn)
867{
868        BSYSlib_List_IteratorHandle hIterator;
869        bool bVideoSync = false;
870        bool bAudioSync = false;
871
872        BDBG_ENTER(BSYNClib_Channel_P_AudioVideoSyncCheck);
873
874        BDBG_ASSERT(hChn);
875
876        BDBG_MSG(("[%d] Performing a/v sync check...", hChn->iIndex));
877
878        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSources);
879
880        while (BSYSlib_List_HasNext(hIterator))
881        {
882                BSYNClib_VideoSource * psSource;
883
884                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
885
886                bVideoSync = bVideoSync || psSource->sElement.sSnapshot.bSynchronize;
887        }
888
889        BSYSlib_List_ReleaseIterator(hIterator);
890
891        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSources);
892
893        while (BSYSlib_List_HasNext(hIterator))
894        {
895                BSYNClib_AudioSource * psSource;
896
897                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
898
899                bAudioSync = bAudioSync || psSource->sElement.sSnapshot.bSynchronize;
900        }
901
902        BSYSlib_List_ReleaseIterator(hIterator);
903
904        BDBG_LEAVE(BSYNClib_Channel_P_AudioVideoSyncCheck);
905        /* at least one video and audio source should be synchronized in order to sync av */
906        return bVideoSync && bAudioSync;
907}
908
909/* TODO: merge these into the rework for separate state machines for a/a, v/v, a/v sync */
910bool BSYNClib_Channel_P_AudioAudioSyncCheck(BSYNClib_Channel_Handle hChn)
911{
912        BSYSlib_List_IteratorHandle hIterator;
913        unsigned int uiAudioSyncCount = 0;
914
915        BDBG_ENTER(BSYNClib_Channel_P_AudioAudioSyncCheck);
916
917        BDBG_ASSERT(hChn);
918
919        BDBG_MSG(("[%d] Performing a/a sync check...", hChn->iIndex));
920
921        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSinks);
922
923        while (BSYSlib_List_HasNext(hIterator))
924        {
925                BSYNClib_AudioSink * psSink;
926
927                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
928
929                if (psSink->sElement.sSnapshot.bSynchronize) 
930                {
931                        uiAudioSyncCount++; 
932                }
933        }
934
935        BSYSlib_List_ReleaseIterator(hIterator);
936
937        BDBG_LEAVE(BSYNClib_Channel_P_AudioAudioSyncCheck);
938        /* TODO: at least 2 audio sinks should be synchronized for a/a sync */
939        return (uiAudioSyncCount > 1);
940}
941
942/* TODO: merge these into the rework for separate state machines for a/a, v/v, a/v sync */
943bool BSYNClib_Channel_P_VideoVideoSyncCheck(BSYNClib_Channel_Handle hChn)
944{
945        BSYSlib_List_IteratorHandle hIterator;
946        unsigned int uiVideoSyncCount = 0;
947        BSYNClib_RateMismatchDetector_Status sRmdStatus;
948        bool bResetDelay = false;
949
950        BDBG_ENTER(BSYNClib_Channel_P_VideoVideoSyncCheck);
951
952        BDBG_ASSERT(hChn);
953
954        BDBG_MSG(("[%d] Performing v/v sync check...", hChn->iIndex));
955
956        BSYNClib_RateMismatchDetector_GetStatus(hChn->hDetector, &sRmdStatus);
957    /* TODO: move this to a better location; sync check is not the right place */
958        if (!sRmdStatus.bSinkSinkMatched)
959        {
960                BDBG_MSG(("[%d] Inconsistent sink refresh rate domains, v/v sync reset", hChn->iIndex));
961                hChn->sVideo.sResults.bInconsistentSinkDomains = true;
962        }
963        else
964        {
965                hChn->sVideo.sResults.bInconsistentSinkDomains = false;
966        }
967
968        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSinks);
969
970        while (BSYSlib_List_HasNext(hIterator))
971        {
972                BSYNClib_VideoSink * psSink;
973
974                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
975
976                /* invisible windows are ignored */
977                if ((psSink->sSnapshot.bVisible && psSink->sElement.sSnapshot.bSynchronize) || bResetDelay)
978                {
979                        uiVideoSyncCount++; 
980                }
981        }
982
983        BSYSlib_List_ReleaseIterator(hIterator);
984
985        BDBG_LEAVE(BSYNClib_Channel_P_VideoVideoSyncCheck);
986        return (uiVideoSyncCount > 1);
987}
988
989BERR_Code BSYNClib_Channel_P_Synchronize(
990        BSYNClib_Channel_Handle hChn
991)
992{
993        BERR_Code rc = BERR_SUCCESS;
994
995        BDBG_ENTER(BSYNClib_Channel_P_Synchronize);
996
997        BDBG_ASSERT(hChn);
998
999        /* TODO: change to 3 separate state machines */
1000        if (BSYNClib_Channel_P_VideoVideoSyncCheck(hChn))
1001        {
1002            BSYNClib_Algo_VideoVideo_Sync(&hChn->sVideo);
1003        }
1004        if (BSYNClib_Channel_P_AudioAudioSyncCheck(hChn))
1005        {
1006            BSYNClib_Algo_AudioAudio_Sync(&hChn->sAudio);
1007        }
1008        if (BSYNClib_Channel_P_AudioVideoSyncCheck(hChn))
1009        {
1010            BSYNClib_Algo_AudioVideo_Sync(&hChn->sAudio, &hChn->sVideo, &hChn->sResults);
1011        }
1012
1013        if (!hChn->sResults.bSyncTaskScheduled)
1014        {
1015                rc = BSYNClib_Channel_P_ApplyDelays(hChn);
1016                if (rc) goto error;
1017        }
1018        else
1019        {
1020                BDBG_MSG(("[%d] Impending sync readjustment -- deferring delay application", hChn->iIndex));
1021        }
1022
1023        goto end;
1024
1025error:
1026
1027end:
1028
1029        BDBG_LEAVE(BSYNClib_Channel_P_Synchronize);
1030        return rc;
1031}
1032
1033BERR_Code BSYNClib_Channel_P_GenerateDelayCallback(BSYNClib_Channel_SetDelay pfSetDelay, void * pvParm1, int iParm2, unsigned int uiDeviceIndex, BSYNClib_DelayElement * psElement)
1034{
1035        BERR_Code rc = BERR_SUCCESS;
1036
1037        BDBG_ENTER(BSYNClib_Channel_P_GenerateDelayCallback);
1038
1039        BDBG_ASSERT(psElement);
1040
1041        if (psElement->sDelay.sResults.bGenerateCallback && psElement->sSnapshot.bSynchronize)
1042        {
1043                if (pfSetDelay)
1044                {
1045                        BSYNClib_UnsignedValue sApplied;
1046                        sApplied.uiValue = BSYNClib_P_Convert(psElement->sDelay.sResults.uiApplied, BSYNClib_Units_e27MhzTicks, psElement->sDelay.sSnapshot.ePreferredUnits);
1047                        sApplied.eUnits = psElement->sDelay.sSnapshot.ePreferredUnits;
1048                        rc = pfSetDelay(pvParm1, iParm2, uiDeviceIndex, &sApplied);
1049                        if (rc) goto error;
1050                }
1051
1052                psElement->sDelay.sResults.bGenerateCallback = false;
1053        }
1054
1055        goto end;
1056
1057error:
1058
1059end:
1060
1061        BDBG_LEAVE(BSYNClib_Channel_P_GenerateDelayCallback);
1062        return rc;
1063}
1064
1065BERR_Code BSYNClib_Channel_P_GenerateDelayNotificationCallback(BSYNClib_Channel_SetDelayNotification pfSetDelayNotification, void * pvParm1, int iParm2, unsigned int uiDeviceIndex, BSYNClib_DelayElement * psElement)
1066{
1067        BERR_Code rc = BERR_SUCCESS;
1068
1069        BDBG_ENTER(BSYNClib_Channel_P_GenerateDelayNotificationCallback);
1070
1071        BDBG_ASSERT(psElement);
1072
1073        if (psElement->sNotification.sResults.bGenerateCallback && psElement->sSnapshot.bSynchronize)
1074        {
1075                if (pfSetDelayNotification)
1076                {
1077                        BSYNClib_UnsignedValue sThreshold;
1078                        sThreshold = psElement->sNotification.sResults.sThreshold;
1079                        /* convert to preferred units */
1080                        if (sThreshold.eUnits != psElement->sDelay.sSnapshot.ePreferredUnits)
1081                        {
1082                                sThreshold.uiValue = BSYNClib_P_Convert(sThreshold.uiValue, sThreshold.eUnits, BSYNClib_Units_e27MhzTicks);
1083                                sThreshold.uiValue = BSYNClib_P_Convert(sThreshold.uiValue, BSYNClib_Units_e27MhzTicks, psElement->sNotification.sSnapshot.ePreferredUnits);
1084                                sThreshold.eUnits = psElement->sNotification.sSnapshot.ePreferredUnits;
1085                        }
1086                        rc = pfSetDelayNotification(pvParm1, iParm2, uiDeviceIndex, psElement->sNotification.sResults.bEnabled, &sThreshold);
1087                        if (rc) goto error;
1088                }
1089
1090                psElement->sNotification.sResults.bGenerateCallback = false;
1091        }
1092
1093        goto end;
1094
1095error:
1096
1097end:
1098
1099        BDBG_LEAVE(BSYNClib_Channel_P_GenerateDelayNotificationCallback);
1100        return rc;
1101}
1102
1103BERR_Code BSYNClib_Channel_P_GenerateCallbacks(BSYNClib_Channel_Handle hChn)
1104{
1105        BERR_Code rc = BERR_SUCCESS;
1106        void * pvParm1;
1107        int iParm2;
1108        BSYSlib_List_IteratorHandle hIterator;
1109
1110        BDBG_ENTER(BSYNClib_Channel_P_GenerateCallbacks);
1111
1112        BDBG_ASSERT(hChn);
1113
1114        pvParm1 = hChn->sSettings.sVideo.sSource.cbDelay.pvParm1;
1115        iParm2 = hChn->sSettings.sVideo.sSource.cbDelay.iParm2;
1116
1117        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSources);
1118
1119        while (BSYSlib_List_HasNext(hIterator))
1120        {
1121                BSYNClib_VideoSource * psSource;
1122
1123                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next(hIterator);
1124
1125                rc = BSYNClib_Channel_P_GenerateDelayCallback(hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelay, pvParm1, iParm2, psSource->sElement.uiIndex, &psSource->sElement);
1126                if (rc) goto error;
1127
1128                /* PR49294 20081125 bandrews - added precision lipsync flag */
1129                psSource->sElement.sNotification.sResults.bEnabled &= hChn->bPrecisionLipsyncEnabled;
1130
1131                rc = BSYNClib_Channel_P_GenerateDelayNotificationCallback(hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelayNotification, pvParm1, iParm2, psSource->sElement.uiIndex, &psSource->sElement);
1132                if (rc) goto error;
1133        }
1134
1135        BSYSlib_List_ReleaseIterator(hIterator);
1136
1137        pvParm1 = hChn->sSettings.sVideo.sSink.cbDelay.pvParm1;
1138        iParm2 = hChn->sSettings.sVideo.sSink.cbDelay.iParm2;
1139
1140        hIterator = BSYSlib_List_AcquireIterator(hChn->sVideo.hSinks);
1141
1142        while (BSYSlib_List_HasNext(hIterator))
1143        {
1144                BSYNClib_VideoSink * psSink;
1145
1146                psSink = (BSYNClib_VideoSink *)BSYSlib_List_Next(hIterator);
1147
1148                rc = BSYNClib_Channel_P_GenerateDelayCallback(hChn->sSettings.sVideo.sSink.cbDelay.pfSetDelay, pvParm1, iParm2, psSink->sElement.uiIndex, &psSink->sElement);
1149                if (rc) goto error;
1150
1151                rc = BSYNClib_Channel_P_GenerateDelayNotificationCallback(hChn->sSettings.sVideo.sSink.cbDelay.pfSetDelayNotification, pvParm1, iParm2, psSink->sElement.uiIndex, &psSink->sElement);
1152                if (rc) goto error;
1153        }
1154
1155        BSYSlib_List_ReleaseIterator(hIterator);
1156
1157        pvParm1 = hChn->sSettings.sAudio.sSource.cbDelay.pvParm1;
1158        iParm2 = hChn->sSettings.sAudio.sSource.cbDelay.iParm2;
1159
1160        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSources);
1161
1162        while (BSYSlib_List_HasNext(hIterator))
1163        {
1164                BSYNClib_AudioSource * psSource;
1165
1166                psSource = (BSYNClib_AudioSource *)BSYSlib_List_Next(hIterator);
1167
1168                rc = BSYNClib_Channel_P_GenerateDelayCallback(hChn->sSettings.sAudio.sSource.cbDelay.pfSetDelay, pvParm1, iParm2, psSource->sElement.uiIndex, &psSource->sElement);
1169                if (rc) goto error;
1170
1171                rc = BSYNClib_Channel_P_GenerateDelayNotificationCallback(hChn->sSettings.sAudio.sSource.cbDelay.pfSetDelayNotification, pvParm1, iParm2, psSource->sElement.uiIndex, &psSource->sElement);
1172                if (rc) goto error;
1173        }
1174
1175        BSYSlib_List_ReleaseIterator(hIterator);
1176
1177        pvParm1 = hChn->sSettings.sAudio.sSink.cbDelay.pvParm1;
1178        iParm2 = hChn->sSettings.sAudio.sSink.cbDelay.iParm2;
1179
1180        hIterator = BSYSlib_List_AcquireIterator(hChn->sAudio.hSinks);
1181
1182        while (BSYSlib_List_HasNext(hIterator))
1183        {
1184                BSYNClib_AudioSink * psSink;
1185
1186                psSink = (BSYNClib_AudioSink *)BSYSlib_List_Next(hIterator);
1187
1188                rc = BSYNClib_Channel_P_GenerateDelayCallback(hChn->sSettings.sAudio.sSink.cbDelay.pfSetDelay, pvParm1, iParm2, psSink->sElement.uiIndex, &psSink->sElement);
1189                if (rc) goto error;
1190
1191                rc = BSYNClib_Channel_P_GenerateDelayNotificationCallback(hChn->sSettings.sAudio.sSink.cbDelay.pfSetDelayNotification, pvParm1, iParm2, psSink->sElement.uiIndex, &psSink->sElement);
1192                if (rc) goto error;
1193        }
1194
1195        BSYSlib_List_ReleaseIterator(hIterator);
1196
1197        goto end;
1198
1199error:
1200
1201end:
1202
1203        BDBG_LEAVE(BSYNClib_Channel_P_GenerateCallbacks);
1204        return rc;
1205}
1206
1207bool BSYNClib_Channel_P_Enabled(
1208        BSYNClib_Channel_Handle hChn
1209)
1210{
1211        bool bEnabled = false;
1212
1213        BDBG_ENTER(BSYNClib_Channel_P_Enabled);
1214
1215        BDBG_ASSERT(hChn);
1216
1217        BKNI_EnterCriticalSection();
1218        bEnabled = BSYNClib_Channel_P_Enabled_isr(hChn);
1219        BKNI_LeaveCriticalSection();
1220
1221        BDBG_LEAVE(BSYNClib_Channel_P_Enabled);
1222        return bEnabled;
1223}
1224
1225bool BSYNClib_Channel_P_Enabled_isr(
1226        BSYNClib_Channel_Handle hChn
1227)
1228{
1229        bool bEnabled = false;
1230
1231        BDBG_ENTER(BSYNClib_Channel_P_Enabled_isr);
1232
1233        BDBG_ASSERT(hChn);
1234
1235        bEnabled = hChn->bEnabled;
1236
1237        BDBG_LEAVE(BSYNClib_Channel_P_Enabled_isr);
1238        return bEnabled;
1239}
1240
1241/* PR26655 20061215 bandrews - added to prevent extra glitches */
1242bool BSYNClib_Channel_P_PredictMadStateChange_isr(BSYNClib_Channel_Handle hChn, BSYNClib_VideoSink * psSink)
1243{
1244        bool bPredict = false;
1245        BSYNClib_VideoSource * psSource = NULL;
1246        BSYSlib_List_IteratorHandle hIterator = NULL;
1247
1248        BDBG_ENTER(BSYNClib_Channel_P_PredictMadStateChange_isr);
1249
1250        BDBG_ASSERT(hChn);
1251        BDBG_ASSERT(psSink);
1252
1253        /* predict wrt 1st source */
1254        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sVideo.hSources);
1255
1256        if (BSYSlib_List_HasNext_isr(hIterator))
1257        {
1258                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next_isr(hIterator);
1259        }
1260
1261        BSYSlib_List_ReleaseIterator_isr(hIterator);
1262
1263        if (psSource)
1264        {
1265                bPredict = (psSource->sFormat.sData.uiHeight != psSink->sFormat.sData.uiHeight)
1266                        && (psSource->sFormat.sData.bInterlaced);
1267        }
1268
1269        BDBG_MSG(("[%d] deinterlacer state change prediction: %s", hChn->iIndex, bPredict ? "yes" : "no"));
1270
1271        BDBG_LEAVE(BSYNClib_Channel_P_PredictMadStateChange_isr);
1272        return bPredict;
1273}
1274
1275void BSYNClib_Channel_P_ResetVideoSourceJtiFactor_isr(
1276        BSYNClib_Channel_Handle hChn
1277)
1278{
1279        BSYNClib_VideoSource * psSource = NULL;
1280        BSYSlib_List_IteratorHandle hIterator = NULL;
1281
1282        BDBG_ENTER(BSYNClib_Channel_P_ResetVideoSourceJtiFactor_isr);
1283
1284        BDBG_ASSERT(hChn);
1285
1286        /* reset 1st source PWC factor */
1287        hIterator = BSYSlib_List_AcquireIterator_isr(hChn->sVideo.hSources);
1288
1289        if (BSYSlib_List_HasNext_isr(hIterator))
1290        {
1291                psSource = (BSYNClib_VideoSource *)BSYSlib_List_Next_isr(hIterator);
1292        }
1293
1294        BSYSlib_List_ReleaseIterator_isr(hIterator);
1295
1296        if (psSource)
1297        {
1298                /* TODO: this is a problem since we don't enter CS around DCF in task context */
1299                psSource->sResults.sJtiFactor.iValue = 0;
1300        }
1301
1302        BDBG_LEAVE(BSYNClib_Channel_P_ResetVideoSourceJtiFactor_isr);
1303}
1304
1305void BSYNClib_Channel_P_GetDefaultStatus(
1306        BSYNClib_Channel_Status * psStatus
1307)
1308{
1309        BDBG_ENTER(BSYNClib_Channel_P_GetDefaultStatus);
1310
1311        BDBG_ASSERT(psStatus);
1312
1313        BKNI_Memset(psStatus, 0, sizeof(BSYNClib_Channel_Status));
1314
1315        BDBG_LEAVE(BSYNClib_Channel_P_GetDefaultStatus);
1316}
1317
1318void BSYNClib_Channel_P_Stop(
1319        BSYNClib_Channel_Handle hChn
1320)
1321{
1322        BDBG_ENTER(BSYNClib_Channel_P_Stop);
1323
1324        BDBG_ASSERT(hChn);
1325
1326        /* stop any running timers */
1327        if (hChn->sSettings.cbTimer.pfCancel_isr)
1328        {
1329                BSYSlib_List_IteratorHandle hIterator;
1330                void * pvParm1 = hChn->sSettings.cbTimer.pvParm1;
1331                int iParm2 = hChn->sSettings.cbTimer.iParm2;
1332
1333                /* Timer for task context switch */
1334                BKNI_EnterCriticalSection();
1335                if (hChn->psTaskTimer->bScheduled)
1336                {
1337                        BDBG_MSG(("[%d] Cancelling task context switch timer %p", hChn->iIndex, hChn->psTaskTimer->hTimer));
1338                        hChn->sSettings.cbTimer.pfCancel_isr(pvParm1, iParm2, hChn->psTaskTimer->hTimer);
1339                }
1340                BKNI_LeaveCriticalSection();
1341
1342                /* TODO: remove dependency on resource pool impl */
1343                hIterator = BSYSlib_List_AcquireIterator(hChn->psTimers->hResources);
1344
1345                while (BSYSlib_List_HasNext(hIterator))
1346                {
1347                        BSYNClib_Timer * psTimer;
1348
1349                        psTimer = (BSYNClib_Timer *)BSYSlib_List_Next(hIterator);
1350
1351                        if (psTimer)
1352                        {
1353                                BKNI_EnterCriticalSection();
1354                                if (psTimer->bScheduled)
1355                                {
1356                                        BDBG_MSG(("[%d] Cancelling timer %p", hChn->iIndex, psTimer->hTimer));
1357                                        hChn->sSettings.cbTimer.pfCancel_isr(pvParm1, iParm2, psTimer->hTimer);
1358                                }
1359                                BKNI_LeaveCriticalSection();
1360                        }
1361                }
1362        }
1363
1364        BDBG_LEAVE(BSYNClib_Channel_P_Stop);
1365}
1366
Note: See TracBrowser for help on using the repository browser.