source: svn/trunk/newcon3bcm2_21bu/magnum/syslib/synclib/7552/bsynclib_video_source.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: 26.1 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_video_source.c $
11* $brcm_Revision: Hydra_Software_Devel/15 $
12* $brcm_Date: 1/19/12 8:39p $
13*
14* Revision History:
15*
16* $brcm_Log: /magnum/syslib/synclib/noarch/bsynclib_video_source.c $
17*
18* Hydra_Software_Devel/15   1/19/12 8:39p bandrews
19* SW7346-640: fix the units between estimated delay and measured delay
20* and threshold
21*
22* Hydra_Software_Devel/14   1/16/12 8:26p bandrews
23* SW7346-640: preserve delay estimation when callbacks come in an
24* unexpected order
25*
26* Hydra_Software_Devel/13   5/28/10 6:37p bandrews
27* SW7405-4436: print channel index in debug messages
28*
29* Hydra_Software_Devel/12   4/29/10 2:52p bandrews
30* SW7405-4083: forgot to change debug statements in isr to use isr
31* version of convert
32*
33* Hydra_Software_Devel/11   3/22/10 5:45p bandrews
34* sw7405-4083: fix calls to isr
35*
36* Hydra_Software_Devel/10   3/19/10 2:42p bandrews
37* SW7405-3774: mute control merge
38*
39* Hydra_Software_Devel/SW7405-3774/4   3/18/10 10:03p bandrews
40* SW7405-3774: fixed case where video may unmute even with pending
41* adjustment
42*
43* Hydra_Software_Devel/SW7405-3774/3   3/18/10 9:34p bandrews
44* SW7405-4042: rework delay estimation so that imprecise lipsync works
45* correctly
46*
47* Hydra_Software_Devel/SW7405-3774/2   3/18/10 8:20p bandrews
48* SW7405-4042: imprecise lipsync needs to assume 1/2 frame delay
49*
50* Hydra_Software_Devel/SW7405-3774/1   2/17/10 6:17p bandrews
51* SW7405-3774: attempt to fix early audio unmute then mute
52*
53* Hydra_Software_Devel/9   2/12/10 8:46p bandrews
54* SW7405-3912: assert all inputs are not null
55*
56* Hydra_Software_Devel/8   2/1/10 8:01p bandrews
57* SW7405-3774: only mute/unmute synchronized sources
58*
59* Hydra_Software_Devel/7   1/26/10 9:00p bandrews
60* SW7405-3774: added mute control support
61*
62* Hydra_Software_Devel/6   12/10/09 9:18p bandrews
63* SW7401-3634: adding PWC (now JTI) support to synclib
64*
65* Hydra_Software_Devel/5   8/4/09 4:56p bandrews
66* PR52812: added improved rmd for dmv2
67*
68* Hydra_Software_Devel/4   7/24/09 4:14p bandrews
69* PR52812: Added any-time source or display rate change support
70*
71* Hydra_Software_Devel/3   6/16/08 5:05p bandrews
72* PR43010: Units conversion not from or to 27MHz needs 2 steps
73*
74* Hydra_Software_Devel/2   4/3/08 2:33p bandrews
75* PR40090: synclib needs to have different contexts for syslib callbacks
76* and synclib callbacks
77*
78* Hydra_Software_Devel/1   3/24/08 3:10p bandrews
79* PR40865: Fixed
80*
81* Hydra_Software_Devel/8   2/26/08 10:32p bandrews
82* PR37951: Fixed validation of delay in low precision mode
83*
84* Hydra_Software_Devel/7   2/26/08 10:21p bandrews
85* PR37951: Fixed units.  Implemented static rate mismatch detection.
86*
87* Hydra_Software_Devel/6   2/26/08 3:03p bandrews
88* PR37951: Added video delay requantization
89*
90* Hydra_Software_Devel/5   2/22/08 8:28p bandrews
91* PR37951: Fixed bug in units conversion
92*
93* Hydra_Software_Devel/4   2/21/08 6:02p bandrews
94* PR37951: Default video source numbers to 45KHz domain.  Improved
95* handling of unsynchronized elements
96*
97* Hydra_Software_Devel/3   2/20/08 10:03p bandrews
98* PR37951: Updated based on feedback from usage
99*
100* Hydra_Software_Devel/2   1/3/08 5:17p bandrews
101* PR37951: Updated based on initial feedback
102*
103* Hydra_Software_Devel/1   12/12/07 2:54p bandrews
104* PR37951: Initial check-in
105***************************************************************************/
106
107#include "bstd.h"
108#include "bsynclib_priv.h"
109#include "bsynclib_video_source.h"
110#include "bsynclib_channel_priv.h"
111#include "bsynclib_mute_control.h"
112
113BDBG_MODULE(synclib);
114
115#define BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS BSYNClib_Units_e45KhzTicks
116#define BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_THRESHOLD_VALUE 90 /* 2 ms @ 45 KHz */
117#define BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_JITTER_TOLERANCE_IMPROVEMENT_THRESHOLD_VALUE 1 /* 1 ms */
118
119BSYNClib_VideoSource * BSYNClib_VideoSource_Create(void)
120{
121        BSYNClib_VideoSource * psSource = NULL;
122
123        BDBG_ENTER(BSYNClib_VideoSource_Create);
124
125        psSource = (BSYNClib_VideoSource *)BKNI_Malloc(sizeof(BSYNClib_VideoSource));
126
127        if (psSource)
128        {
129                BKNI_Memset(psSource, 0, sizeof(BSYNClib_VideoSource));
130                BSYNClib_DelayElement_Init(&psSource->sElement);
131                BSYNClib_VideoFormat_Init(&psSource->sFormat);
132                BSYNClib_VideoSource_GetDefaultConfig(&psSource->sConfig);
133                BSYNClib_VideoSource_P_GetDefaultStatus(&psSource->sStatus);
134                psSource->sElement.sDelay.sData.eOriginalUnits = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS;
135                psSource->sElement.sDelay.sSnapshot.eOriginalUnits = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS;
136                psSource->sElement.sNotification.sResults.sThreshold.eUnits = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS;
137                psSource->sElement.sNotification.sResults.sThreshold.uiValue = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_THRESHOLD_VALUE; 
138        }
139
140        BDBG_LEAVE(BSYNClib_VideoSource_Create);
141        return psSource;
142}
143
144void BSYNClib_VideoSource_Destroy(BSYNClib_VideoSource * psSource)
145{
146        BDBG_ENTER(BSYNClib_VideoSource_Destroy);
147
148        BDBG_ASSERT(psSource);
149
150        BKNI_Free(psSource);
151
152        BDBG_LEAVE(BSYNClib_VideoSource_Destroy);
153}
154
155bool BSYNClib_VideoSource_SyncCheck(BSYNClib_VideoSource * psSource)
156{
157        bool bPass = false;
158       
159        BDBG_ENTER(BSYNClib_VideoSource_SyncCheck);
160
161        BDBG_ASSERT(psSource);
162
163        bPass = !psSource->sElement.sSnapshot.bSynchronize /* if we must not synchronize this element */
164                || (psSource->sElement.sSnapshot.bStarted /* must be started */
165                && psSource->sFormat.sSnapshot.bValid /* have a valid format */
166                && psSource->sElement.sDelay.sSnapshot.bValid /* have a valid measured delay */
167                && psSource->sElement.sDelay.sResults.bAccepted); /* and be accepted */
168
169        BDBG_MSG(("[%d] Video source %u sync check:", psSource->sElement.hParent->iIndex, psSource->sElement.uiIndex));
170        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, psSource->sElement.sSnapshot.bSynchronize ? "synchronized" : "ignored"));
171        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, psSource->sElement.sSnapshot.bStarted ? "started" : "stopped"));
172        BDBG_MSG(("[%d]  format %s", psSource->sElement.hParent->iIndex, psSource->sFormat.sSnapshot.bValid ? "valid" : "invalid"));
173        if (!psSource->sElement.sDelay.sResults.bEstimated)
174        {
175                BDBG_MSG(("[%d]  delay %s, %s", psSource->sElement.hParent->iIndex, psSource->sElement.sDelay.sSnapshot.bValid ? "valid" : "invalid", 
176                        psSource->sElement.sDelay.sResults.bAccepted ? "accepted" : "unaccepted"));
177        }
178        else
179        {
180                BDBG_MSG(("[%d]  delay %s, estimated", psSource->sElement.hParent->iIndex, psSource->sElement.sDelay.sSnapshot.bValid ? "valid" : "invalid"));
181        }
182
183        BDBG_LEAVE(BSYNClib_VideoSource_SyncCheck);
184        return bPass;
185}
186
187void BSYNClib_VideoSource_Reset_isr(BSYNClib_VideoSource * psSource)
188{
189        BDBG_ENTER(BSYNClib_VideoSource_Reset_isr);
190
191        BDBG_ASSERT(psSource);
192
193        BSYNClib_Timer_Reset_isr(psSource->psTsmLockTimer);
194
195        psSource->sData.bDigital = true;
196        psSource->sData.bLastPictureHeld = false;
197        psSource->sResults.bDelaySaved = false;
198        psSource->sResults.sJtiFactor.bAdjusted = false;
199        psSource->sResults.sJtiFactor.iValue = 0;
200
201        BDBG_LEAVE(BSYNClib_VideoSource_Reset_isr);
202}
203
204BERR_Code BSYNClib_VideoSource_TsmLockTimerExpired(void * pvParm1, int iParm2, BSYSlib_Timer_Handle hTimer)
205{
206        BERR_Code rc = BERR_SUCCESS;
207        BSYNClib_VideoSource * psSource = pvParm1;
208       
209        BDBG_ENTER(BSYNClib_VideoSource_TsmLockTimerExpired);
210
211        BSTD_UNUSED(iParm2);
212
213        BDBG_ASSERT(psSource);
214        BDBG_ASSERT(hTimer);
215
216        BDBG_MSG(("[%d] Video source %u tsm lock timer expired", psSource->sElement.hParent->iIndex, psSource->sElement.uiIndex));
217
218        psSource->sElement.sDelay.sResults.bAccepted = true;
219
220        rc = BSYNClib_Channel_P_TimerExpired(psSource->sElement.hParent, hTimer);
221        if (rc) goto end;
222
223        BSYNClib_Channel_P_Process(psSource->sElement.hParent, 0);
224
225end:
226
227        BDBG_LEAVE(BSYNClib_VideoSource_TsmLockTimerExpired);
228        return rc;
229}
230
231BERR_Code BSYNClib_VideoSource_SetMute(BSYNClib_VideoSource * psSource, bool bMute)
232{
233        BERR_Code rc = BERR_SUCCESS;
234        BSYNClib_Channel_Handle hChn;
235        BSYNClib_Channel_MuteCallback * pcbMute;
236
237        BDBG_ENTER(BSYNClib_VideoSource_SetMute);
238       
239        BDBG_ASSERT(psSource);
240       
241        hChn = psSource->sElement.hParent;
242        pcbMute = &hChn->sSettings.sVideo.sSource.cbMute;
243
244        BKNI_EnterCriticalSection();
245        psSource->sResults.bMutePending = false;
246       
247        /* cancel any pending unmute timer */
248        rc = BSYNClib_Channel_P_CancelTimer_isr(hChn, psSource->psUnmuteTimer);
249        BKNI_LeaveCriticalSection();
250        if (rc) goto end;
251
252        /* cancel any pending unconditional unmute timer */
253        if (!bMute)
254        {
255                BKNI_EnterCriticalSection();
256                rc = BSYNClib_Channel_P_CancelTimer_isr(hChn, psSource->psUnconditionalUnmuteTimer);
257                BKNI_LeaveCriticalSection();
258                if (rc) goto end;
259        }
260
261        /* handling of video channel change mode is in upper layer software, as what constitutes a
262        mute depends on that mode.  May want to revisit inclusion in synclib later.
263        The logic should be something like:
264                if (sync wants to mute)
265                {
266                        switch (channel change mode)
267                        {
268                                case BXVD_ChannelChangeMode_eMute:
269                                        BXVD_EnableMute(true);
270                                        break;
271                                case BXVD_ChannelChangeMode_eLastFramePreviousChannel:
272                                case BXVD_ChannelChangeMode_eMuteWithFirstPicturePreview:
273                                case BXVD_ChannelChangeMode_eLastFramePreviousWithFirstPicturePreview:
274                                        BXVD_EnableVideoFreeze();
275                                        break;
276                                default:
277                                        break;
278                        }
279                }
280                else if (sync wants to unmute)
281                {
282                        switch (channel change mode)
283                        {
284                                case BXVD_ChannelChangeMode_eMute:
285                                        BXVD_EnableMute(false);
286                                        break;
287                                case BXVD_ChannelChangeMode_eLastFramePreviousChannel:
288                                case BXVD_ChannelChangeMode_eMuteWithFirstPicturePreview:
289                                case BXVD_ChannelChangeMode_eLastFramePreviousWithFirstPicturePreview:
290                                        BXVD_DisableVideoFreeze();
291                                        break;
292                                default:
293                                        break;
294                        }
295                }
296        This assumes that the FPP modes already show the first picture and freeze until the next
297        picture matures.  In this case, sync will just extend that freeze time a little bit.
298        */
299        if (psSource->sConfig.bSynchronize && pcbMute->pfSetMute)/* at mute time, no snapshot has been made */
300        {
301                rc = pcbMute->pfSetMute(pcbMute->pvParm1, pcbMute->iParm2, psSource->sElement.uiIndex, bMute);
302                if(rc) goto end;
303                psSource->sStatus.bMuted = bMute;
304        }
305
306end:
307        BDBG_LEAVE(BSYNClib_VideoSource_SetMute);
308        return rc;
309}
310
311static void BSYNClib_VideoSource_RestoreDelay_isr(BSYNClib_VideoSource * psSource)
312{
313        BDBG_ENTER(BSYNClib_VideoSource_RestoreDelay_isr);
314
315        BDBG_ASSERT(psSource);
316
317        if (psSource->sResults.bDelaySaved)
318        {
319                psSource->sElement.sDelay = psSource->sResults.sSavedDelay;
320                BDBG_MSG(("[%d]  restored delay state: accepted = %s, diff = %u ms", psSource->sElement.hParent->iIndex, psSource->sElement.sDelay.sResults.bAccepted ? "true" : "false", BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
321                psSource->sResults.bDelaySaved = false;
322                psSource->sElement.sDelay.sResults.bEstimated = false;
323        }
324
325        BDBG_LEAVE(BSYNClib_VideoSource_RestoreDelay_isr);
326}
327
328static void BSYNClib_VideoSource_SaveDelay_isr(BSYNClib_VideoSource * psSource)
329{
330        BDBG_ENTER(BSYNClib_VideoSource_SaveDelay_isr);
331
332        BDBG_ASSERT(psSource);
333
334        if (psSource->sElement.sDelay.sData.bValid && !psSource->sElement.sDelay.sResults.bEstimated)
335        {
336                psSource->sResults.sSavedDelay = psSource->sElement.sDelay;
337                psSource->sResults.bDelaySaved = true;
338                BDBG_MSG(("[%d]  saved delay state: accepted = %s, diff = %u ms", psSource->sElement.hParent->iIndex, psSource->sElement.sDelay.sResults.bAccepted ? "true" : "false", BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
339        }
340       
341        BDBG_LEAVE(BSYNClib_VideoSource_SaveDelay_isr);
342}
343
344bool BSYNClib_VideoSource_EstimateDelay_isr(BSYNClib_VideoSource * psSource)
345{
346    bool bChanged = false;
347    unsigned int uiOldMeasured;
348   
349        BDBG_ENTER(BSYNClib_VideoSource_EstimateDelay_isr);
350
351        BDBG_ASSERT(psSource);
352
353        psSource->sElement.sDelay.sData.bValid = true;
354        psSource->sElement.sDelay.sResults.bEstimated = true;
355       
356        if (psSource->sFormat.sData.bValid)
357        {
358            /* only accept if we actually have a value from receipt of format info */
359        psSource->sElement.sDelay.sResults.bAccepted = true;
360
361        uiOldMeasured = psSource->sElement.sDelay.sData.uiMeasured;
362       
363                /* assume we are centered in pass window */
364        psSource->sElement.sDelay.sData.eOriginalUnits = BSYNClib_Units_e27MhzTicks;
365                psSource->sElement.sDelay.sData.uiMeasured = BSYNClib_VideoFormat_P_GetFramePeriod_isr(&psSource->sFormat) / 2;
366
367                if (uiOldMeasured != psSource->sElement.sDelay.sData.uiMeasured)
368            {
369            bChanged = true;
370                }
371        }
372       
373        BDBG_LEAVE(BSYNClib_VideoSource_EstimateDelay_isr);
374        return bChanged;
375}
376
377BERR_Code BSYNClib_VideoSource_RateMismatchDetected(BSYNClib_VideoSource * psSource)
378{
379        BERR_Code rc = BERR_SUCCESS;
380        BSYNClib_Channel_Handle hChn;
381       
382        BDBG_ENTER(BSYNClib_VideoSource_RateMismatchDetected);
383
384        BDBG_ASSERT(psSource);
385
386        hChn = psSource->sElement.hParent;
387
388        BDBG_WRN(("[%d] Video source %u rate mismatch detected!  Disabling precision lipsync.", hChn->iIndex, psSource->sElement.uiIndex));
389        psSource->sElement.sNotification.sResults.bEnabled = false;
390
391        BKNI_EnterCriticalSection();
392        BSYNClib_VideoSource_SaveDelay_isr(psSource);
393        BSYNClib_VideoSource_EstimateDelay_isr(psSource);
394        BKNI_LeaveCriticalSection();
395
396        if (hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelayNotification)
397        {
398                rc = hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelayNotification(
399                        hChn->sSettings.sVideo.sSource.cbDelay.pvParm1, 
400                        hChn->sSettings.sVideo.sSource.cbDelay.iParm2, 
401                        psSource->sElement.uiIndex, 
402                        psSource->sElement.sNotification.sResults.bEnabled, 
403                        &psSource->sElement.sNotification.sResults.sThreshold);
404        }
405       
406        BDBG_LEAVE(BSYNClib_VideoSource_RateMismatchDetected);
407        return rc;
408}
409
410BERR_Code BSYNClib_VideoSource_RateRematchDetected(BSYNClib_VideoSource * psSource)
411{
412        BERR_Code rc = BERR_SUCCESS;
413        BSYNClib_Channel_Handle hChn;
414
415        BDBG_ENTER(BSYNClib_VideoSource_RateRematchDetected);
416
417        BDBG_ASSERT(psSource);
418
419        hChn = psSource->sElement.hParent;
420
421        BDBG_WRN(("[%d] Video source %u rate appears to be matched.  Precision lipsync enabled.", hChn->iIndex, psSource->sElement.uiIndex));
422        psSource->sElement.sNotification.sResults.bEnabled = true;
423
424        BKNI_EnterCriticalSection();
425        BSYNClib_VideoSource_RestoreDelay_isr(psSource);
426        BKNI_LeaveCriticalSection();
427
428        /* TODO: make this so we don't need hChn to do this */
429        if (hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelayNotification)
430        {
431                rc = hChn->sSettings.sVideo.sSource.cbDelay.pfSetDelayNotification(
432                        hChn->sSettings.sVideo.sSource.cbDelay.pvParm1, 
433                        hChn->sSettings.sVideo.sSource.cbDelay.iParm2, 
434                        psSource->sElement.uiIndex, 
435                        psSource->sElement.sNotification.sResults.bEnabled, 
436                        &psSource->sElement.sNotification.sResults.sThreshold);
437        }
438       
439        BDBG_LEAVE(BSYNClib_VideoSource_RateRematchDetected);
440        return rc;
441}
442
443void BSYNClib_VideoSource_GetDefaultConfig(BSYNClib_VideoSource_Config * psConfig)
444{
445        BDBG_ENTER(BSYNClib_VideoSource_GetDefaultConfig);
446
447        BDBG_ASSERT(psConfig);
448       
449        BKNI_Memset(psConfig, 0, sizeof(BSYNClib_VideoSource_Config));
450
451        psConfig->bDigital = true;
452        psConfig->bLastPictureHeld = true;
453        psConfig->sFormat.bInterlaced = true;
454        psConfig->sFormat.eFrameRate = BAVC_FrameRateCode_eUnknown;
455        psConfig->sDelay.sMeasured.eUnits = BSYNClib_Units_e45KhzTicks;
456        psConfig->sJitterToleranceImprovementThreshold.uiValue = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_JITTER_TOLERANCE_IMPROVEMENT_THRESHOLD_VALUE;
457        psConfig->sJitterToleranceImprovementThreshold.eUnits = BSYNClib_Units_eMilliseconds;
458
459        BDBG_LEAVE(BSYNClib_VideoSource_GetDefaultConfig);
460}
461
462void BSYNClib_VideoSource_P_SelfClearConfig_isr(BSYNClib_VideoSource * psSource)
463{
464        BDBG_ENTER(BSYNClib_VideoSource_P_SelfClearConfig_isr);
465
466        BDBG_ASSERT(psSource);
467       
468        psSource->sConfig.sDelay.bReceived = false;
469        psSource->sConfig.sFormat.bReceived = false;
470
471        BDBG_LEAVE(BSYNClib_VideoSource_P_SelfClearConfig_isr);
472}
473
474BERR_Code BSYNClib_VideoSource_P_ProcessConfig_isr(BSYNClib_VideoSource * psSource)
475{
476        BERR_Code rc = BERR_SUCCESS;
477        BSYNClib_VideoSource_Config * psConfig;
478        BSYNClib_Channel_Handle hChn;
479        bool bChanged = false;
480        bool bScheduleMuteTask = false;
481        BSYNClib_DelayElement sDesired;
482        BSYNClib_DelayElement * psCurrent;
483        BSYNClib_DelayElement_DiffResults sElementDiffResults;
484        BSYNClib_VideoFormat sFormat;
485        bool bFormatReceived;
486        BSYNClib_VideoFormat_DiffResults sFormatDiffResults;
487
488        BDBG_ENTER(BSYNClib_VideoSource_P_ProcessConfig_isr);
489       
490        BDBG_ASSERT(psSource);
491
492        hChn = psSource->sElement.hParent;
493        psConfig = &psSource->sConfig;
494        psCurrent = &psSource->sElement;
495
496        BKNI_Memset(&sElementDiffResults, 0, sizeof(BSYNClib_DelayElement_DiffResults));
497
498        /* check lifecycle first */
499        BSYNClib_DelayElement_CheckLifecycle_isr(psConfig->bStarted, psCurrent, &sElementDiffResults);
500        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
501        {
502                BSYNClib_DelayElement_Reset_isr(psCurrent);
503        }
504
505        /* create "desired" delay element config from current plus changes */
506        sDesired = *psCurrent;
507        sDesired.sData.bStarted = psConfig->bStarted;
508        sDesired.sData.bSynchronize = psConfig->bSynchronize;
509        /* if we estimated the delay previously, we shouldn't overwrite it with the measured delay, unless
510        we've really received it this time */
511        if (psConfig->sDelay.bReceived)
512        {
513        sDesired.sDelay.sData.eOriginalUnits = psConfig->sDelay.sMeasured.eUnits;
514        sDesired.sDelay.sData.uiMeasured = BSYNClib_P_Convert_isr(psConfig->sDelay.sMeasured.uiValue, psConfig->sDelay.sMeasured.eUnits, BSYNClib_Units_e27MhzTicks);
515    }
516        sDesired.sDelay.sData.uiCustom = BSYNClib_P_Convert_isr(psConfig->sDelay.sCustom.uiValue, psConfig->sDelay.sCustom.eUnits, BSYNClib_Units_e27MhzTicks);
517        sDesired.sNotification.sData.bReceived = psConfig->sDelay.bReceived;
518        /* threshold will always be converted to preferred units */
519#if 0
520        /* convert status units to user's measurement units */
521        psSource->sStatus.sDelayNotification.sThreshold.uiValue = BSYNClib_P_Convert_isr(psSource->sStatus.sDelayNotification.sThreshold.uiValue, psSource->sStatus.sDelayNotification.sThreshold.eUnits, BSYNClib_Units_e27MhzTicks);
522        /* 20080616 bandrews - conversion requires 2 steps */
523        psSource->sStatus.sDelayNotification.sThreshold.uiValue = BSYNClib_P_Convert_isr(psSource->sStatus.sDelayNotification.sThreshold.uiValue, BSYNClib_Units_e27MhzTicks, psConfig->sDelay.sMeasured.eUnits);
524        psSource->sStatus.sDelayNotification.sThreshold.eUnits = psConfig->sDelay.sMeasured.eUnits;
525#endif
526
527        BSYNClib_DelayElement_Diff_isr(&sDesired, psCurrent, &sElementDiffResults);
528
529        if (sElementDiffResults.bChanged)
530        {
531                bChanged = true;
532                BSYNClib_DelayElement_Patch_isr(&sDesired, psCurrent, &sElementDiffResults);
533        }
534       
535        /* if we want to synchronize this source, tell mute control */
536        /* must do this on sync change, not on start, otherwise it's too late */
537        switch (sElementDiffResults.eSynchronizationEvent)
538        {
539                case BSYNClib_DelayElement_SynchronizationEvent_eSynchronized:
540                        psSource->sResults.bMutePending = true;
541                        bScheduleMuteTask = true;
542                        break;
543                case BSYNClib_DelayElement_SynchronizationEvent_eIgnored:
544                        psSource->sResults.bMutePending = false;
545                        break;
546                case BSYNClib_DelayElement_SynchronizationEvent_eNone:
547                default:
548                        break;
549        }
550       
551        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
552        {
553                /* reset source data */
554                BSYNClib_VideoSource_Reset_isr(psSource);
555                BSYNClib_VideoFormat_Reset_isr(&psSource->sFormat);
556
557                /* reset rmd data */
558                rc = BSYNClib_RateMismatchDetector_ResetSourceData_isr(hChn->hDetector, psSource->sElement.uiIndex);
559                if (rc) goto error;
560
561                /* note: side effect of copying last picture held and digital here is
562                that they only apply at start time.  They cannot be changed on the fly */
563               
564                /* copy last picture held for mute controller */
565                psSource->sData.bLastPictureHeld = psConfig->bLastPictureHeld;
566
567                /* source digital or analog */
568                if (psConfig->bDigital != psSource->sData.bDigital)
569                {
570                        bChanged = true;
571                        psSource->sData.bDigital = psConfig->bDigital;
572                }
573
574                /* fire setdelay with zero */
575                psSource->sElement.sDelay.sResults.bGenerateCallback = true;
576
577                if (psConfig->bSynchronize)
578                {
579                        /* notify mute control of the start of this synchronized source */
580                        bScheduleMuteTask = true;
581                }
582        }
583
584        /* received a delay notification? */
585        if (sElementDiffResults.bDelayReceived)
586        {
587                BSYNClib_RateMismatchDetector_DelayNotificationInfo sInfo;
588
589                BDBG_MSG(("[%d] Video source %u delay received", hChn->iIndex, psSource->sElement.uiIndex));
590
591                /* inform rmd of delay timing */
592                if (hChn->sSettings.cbTime.pfGetTime_isr)
593                {
594                        unsigned long ulTime;
595                       
596                        rc = hChn->sSettings.cbTime.pfGetTime_isr(hChn->sSettings.cbTime.pvParm1, hChn->sSettings.cbTime.iParm2, &ulTime);
597                        if (rc) goto error;
598                       
599                        sInfo.ulDelayNotificationTime = ulTime;
600                       
601                        rc = BSYNClib_RateMismatchDetector_DelayNotificationHandler_isr(hChn->hDetector, psSource->sElement.uiIndex, &sInfo);
602                        if (rc) goto error;
603                }
604
605                /* need to cancel any pending unmute timers */
606                BSYNClib_MuteControl_CancelUnmuteTimers_isr(hChn);
607               
608                /* start video tsm lock timer */
609                BDBG_MSG(("[%d]  tsm lock timer started", hChn->iIndex));
610                rc = BSYNClib_Channel_P_StartTimer_isr(
611                        hChn, 
612                        psSource->psTsmLockTimer, 
613                        hChn->hParent->sSettings.sVideo.uiTsmLockTimeout,
614                        &BSYNClib_VideoSource_TsmLockTimerExpired,
615                        psSource,
616                        0
617                );
618                if (rc) goto error;
619
620                /* TODO: cancel audio unconditional unmute timer */
621        }
622
623        bFormatReceived = psConfig->sFormat.bReceived;
624
625        /* received source format info */
626        if (bFormatReceived)
627        {
628                /* create "desired" video format config */
629                sFormat.sData.bInterlaced = psConfig->sFormat.bInterlaced;
630                sFormat.sData.uiHeight = psConfig->sFormat.uiHeight;
631                sFormat.sData.eFrameRate = psConfig->sFormat.eFrameRate;
632
633                BSYNClib_VideoFormat_Diff_isr(&sFormat, &psSource->sFormat, &sFormatDiffResults);
634
635                if (sFormatDiffResults.bChanged)
636                {
637                        bChanged = true;
638                        BSYNClib_VideoFormat_Patch_isr(&sFormat, &psSource->sFormat, &sFormatDiffResults);
639                }
640               
641                /* set rmd source format */
642                rc = BSYNClib_RateMismatchDetector_SetVideoSourceFormat_isr(hChn->hDetector, psSource->sElement.uiIndex, &sFormat);
643                if (rc) goto error;
644        }
645
646        /* SW7405-4042 imprecise lipsync needs to assume 1/2 frame delay on each config change */
647    /* or if we were estimated before, force re-estimation now */
648        if (!hChn->bPrecisionLipsyncEnabled || psSource->sElement.sDelay.sResults.bEstimated)
649        {
650                if (BSYNClib_VideoSource_EstimateDelay_isr(psSource))
651                {
652            bChanged = true;
653                }
654        }
655
656        /* JTI */
657        {
658                unsigned int uiJtiThreshold = BSYNClib_P_Convert_isr(psConfig->sJitterToleranceImprovementThreshold.uiValue, 
659                                psConfig->sJitterToleranceImprovementThreshold.eUnits, BSYNClib_Units_e27MhzTicks);
660
661                if (uiJtiThreshold != psSource->sData.uiJitterToleranceImprovementThreshold)
662                {
663                        bChanged = true;
664                        psSource->sData.uiJitterToleranceImprovementThreshold = uiJtiThreshold;
665                }
666        }
667
668        if (bChanged)
669        {
670                BDBG_MSG(("[%d] Video source %u properties changed:", hChn->iIndex, psSource->sElement.uiIndex));
671                if (sElementDiffResults.eSynchronizationEvent != BSYNClib_DelayElement_SynchronizationEvent_eNone)
672                {
673                        BDBG_MSG(("[%d]  %s", hChn->iIndex, BSYNClib_DelayElement_SynchronizationEventNames[sElementDiffResults.eSynchronizationEvent]));
674                }
675                if (sElementDiffResults.eLifecycleEvent != BSYNClib_DelayElement_LifecycleEvent_eNone)
676                {
677                        BDBG_MSG(("[%d]  %s", hChn->iIndex, BSYNClib_DelayElement_LifecycleEventNames[sElementDiffResults.eLifecycleEvent]));
678                }
679                if (psSource->sElement.sDelay.sResults.bEstimated)
680                {
681                        BDBG_MSG(("[%d]  estimated delay %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
682                }
683                else
684                {
685                        BDBG_MSG(("[%d]  measured delay %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
686                }
687                BDBG_MSG(("[%d]  custom delay %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiCustom, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
688                BDBG_MSG(("[%d]  jti threshold %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSource->sData.uiJitterToleranceImprovementThreshold, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
689                BDBG_MSG(("[%d]  %s", hChn->iIndex, psSource->sData.bDigital ? "digital" : "analog"));
690                BDBG_MSG(("[%d]  %s on stop", hChn->iIndex, psSource->sData.bLastPictureHeld ? "last picture held" : "blank"));
691                BDBG_MSG(("[%d]  format:", hChn->iIndex));
692                BDBG_MSG(("[%d]    %s", hChn->iIndex, psSource->sFormat.sData.bInterlaced ? "interlaced" : "progressive"));
693                BDBG_MSG(("[%d]    height %u", hChn->iIndex, psSource->sFormat.sData.uiHeight));
694                BDBG_MSG(("[%d]    frame rate %s", hChn->iIndex, BSYNClib_VideoFormat_P_GetFrameRateName_isr(psSource->sFormat.sData.eFrameRate)));
695                if (psSource->sResults.bMutePending)
696                {
697                                BDBG_MSG(("[%d]  mute pending", hChn->iIndex));
698                }
699        }
700
701        if (bScheduleMuteTask)
702        {
703                /* TODO: probably should do this as a dynamic bind so we don't depend upwards, but ... */
704                BSYNClib_MuteControl_ScheduleTask_isr(hChn);
705        }
706       
707        if (BSYNClib_Channel_P_Enabled_isr(hChn))
708        {
709            /* if anything changed in the config, reprocess based on current state */
710                if (bChanged)
711            {
712                    BSYNClib_Channel_P_ScheduleTask_isr(hChn);
713            }
714        }
715       
716        goto end;
717       
718error:
719
720end:
721
722        BDBG_LEAVE(BSYNClib_VideoSource_P_ProcessConfig_isr);
723        return rc;
724}
725
726void BSYNClib_VideoSource_Snapshot_isr(BSYNClib_VideoSource * psSource)
727{
728        BDBG_ENTER(BSYNClib_VideoSource_Snapshot_isr);
729
730        BDBG_ASSERT(psSource);
731
732        psSource->sSnapshot = psSource->sData;
733       
734        BSYNClib_DelayElement_Snapshot_isr(&psSource->sElement);
735        BSYNClib_VideoFormat_Snapshot_isr(&psSource->sFormat);
736
737        BDBG_LEAVE(BSYNClib_VideoSource_Snapshot_isr);
738}
739
740void BSYNClib_VideoSource_P_GetDefaultStatus(
741        BSYNClib_Source_Status * psStatus
742)
743{
744        BDBG_ENTER(BSYNClib_VideoSource_P_GetDefaultStatus);
745
746        BDBG_ASSERT(psStatus);
747
748        psStatus->bMuted = false;
749        psStatus->sDelayNotification.bEnabled = true;
750        psStatus->sDelayNotification.sThreshold.uiValue = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_THRESHOLD_VALUE;
751        psStatus->sDelayNotification.sThreshold.eUnits = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS;
752        psStatus->sAppliedDelay.uiValue = 0;
753        psStatus->sAppliedDelay.eUnits = BSYNCLIB_P_VIDEO_SOURCE_DEFAULT_UNITS;
754
755        BDBG_LEAVE(BSYNClib_VideoSource_P_GetDefaultStatus);
756}
757
Note: See TracBrowser for help on using the repository browser.