| 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 | |
|---|
| 113 | BDBG_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 | |
|---|
| 119 | BSYNClib_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 | |
|---|
| 144 | void 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 | |
|---|
| 155 | bool 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 | |
|---|
| 187 | void 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 | |
|---|
| 204 | BERR_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 | |
|---|
| 225 | end: |
|---|
| 226 | |
|---|
| 227 | BDBG_LEAVE(BSYNClib_VideoSource_TsmLockTimerExpired); |
|---|
| 228 | return rc; |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | BERR_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 | |
|---|
| 306 | end: |
|---|
| 307 | BDBG_LEAVE(BSYNClib_VideoSource_SetMute); |
|---|
| 308 | return rc; |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | static 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 | |
|---|
| 328 | static 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 | |
|---|
| 344 | bool 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 | |
|---|
| 377 | BERR_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 | |
|---|
| 410 | BERR_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 | |
|---|
| 443 | void 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 | |
|---|
| 462 | void 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 | |
|---|
| 474 | BERR_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 | |
|---|
| 718 | error: |
|---|
| 719 | |
|---|
| 720 | end: |
|---|
| 721 | |
|---|
| 722 | BDBG_LEAVE(BSYNClib_VideoSource_P_ProcessConfig_isr); |
|---|
| 723 | return rc; |
|---|
| 724 | } |
|---|
| 725 | |
|---|
| 726 | void 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 | |
|---|
| 740 | void 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 | |
|---|