source: svn/trunk/newcon3bcm2_21bu/magnum/syslib/synclib/7552/bsynclib_video_sink.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: 16.6 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_sink.c $
11* $brcm_Revision: Hydra_Software_Devel/10 $
12* $brcm_Date: 1/31/12 8:35p $
13*
14* Revision History:
15*
16* $brcm_Log: /magnum/syslib/synclib/noarch/bsynclib_video_sink.c $
17*
18* Hydra_Software_Devel/10   1/31/12 8:35p bandrews
19* SW7358-219: master frame rate needs to get copied from incoming
20* settings
21*
22* Hydra_Software_Devel/9   8/9/10 9:43p bandrews
23* SW7405-885: two step units conversion
24*
25* Hydra_Software_Devel/8   5/28/10 6:31p bandrews
26* SW7405-4436: printing channel index in dbg messages
27*
28* Hydra_Software_Devel/7   2/4/10 3:43p bandrews
29* SW7405-3774: fix PIG behavior
30*
31* Hydra_Software_Devel/6   12/10/09 9:18p bandrews
32* SW7401-3634: adding PWC (now JTI) support to synclib
33*
34* Hydra_Software_Devel/5   8/4/09 4:56p bandrews
35* PR52812: added improved rmd for dmv2
36*
37* Hydra_Software_Devel/4   7/24/09 4:14p bandrews
38* PR52812: Added any-time source or display rate change support
39*
40* Hydra_Software_Devel/3   10/15/08 2:50p bandrews
41* PR47923: Added support for 24 Hz units
42*
43* Hydra_Software_Devel/2   10/6/08 8:07p bandrews
44* PR44510: Implement delay capacity for video sinks
45*
46* Hydra_Software_Devel/1   3/24/08 3:10p bandrews
47* PR40865: Fixed
48*
49* Hydra_Software_Devel/9   2/28/08 10:01p bandrews
50* PR37951: Correct compensation for sync-slipped displays
51*
52* Hydra_Software_Devel/8   2/28/08 9:32p bandrews
53* PR37951: Add back VDC delay adjustment
54*
55* Hydra_Software_Devel/7   2/27/08 2:57p bandrews
56* PR37951: Fixed problem decrementing vsync count from VDC when the count
57* is already zero
58*
59* Hydra_Software_Devel/6   2/26/08 10:21p bandrews
60* PR37951: Fixed units.  Implemented static rate mismatch detection.
61*
62* Hydra_Software_Devel/5   2/25/08 9:33p bandrews
63* PR37951: Fixed various bugs
64*
65* Hydra_Software_Devel/4   2/22/08 8:28p bandrews
66* PR37951: Fixed bug in units conversion
67*
68* Hydra_Software_Devel/3   2/20/08 10:03p bandrews
69* PR37951: Updated based on feedback from usage
70*
71* Hydra_Software_Devel/2   1/3/08 5:17p bandrews
72* PR37951: Updated based on initial feedback
73*
74* Hydra_Software_Devel/1   12/12/07 2:54p bandrews
75* PR37951: Initial check-in
76***************************************************************************/
77
78#include "bstd.h"
79#include "bsynclib_priv.h"
80#include "bsynclib_channel_priv.h"
81#include "bsynclib_video_format.h"
82#include "bsynclib_rate_mismatch_detector.h"
83#include "bsynclib_video_sink.h"
84#include "bsynclib_mute_control.h"
85
86#define BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS BSYNClib_Units_e60HzVsyncs
87#define BSYNCLIB_P_VIDEO_SINK_DEFAULT_THRESHOLD_VALUE 1 /* 1 60Hz vsync */
88#define BSYNCLIB_P_VIDEO_SINK_DEFAULT_CAPACITY 4 /* 4 60Hz vsyncs */
89
90BDBG_MODULE(synclib);
91
92BSYNClib_VideoSink * BSYNClib_VideoSink_Create(void)
93{
94        BSYNClib_VideoSink * psSink = NULL;
95
96        BDBG_ENTER(BSYNClib_VideoSink_Create);
97
98        psSink = (BSYNClib_VideoSink *)BKNI_Malloc(sizeof(BSYNClib_VideoSink));
99
100        if (psSink)
101        {
102                BKNI_Memset(psSink, 0, sizeof(BSYNClib_VideoSink));
103                BSYNClib_DelayElement_Init(&psSink->sElement);
104                BSYNClib_VideoFormat_Init(&psSink->sFormat);
105                BSYNClib_VideoSink_GetDefaultConfig(&psSink->sConfig);
106                BSYNClib_VideoSink_P_GetDefaultStatus(&psSink->sStatus);
107                /* TODO: remove started var */
108                psSink->sElement.sData.bStarted = true;
109                psSink->sElement.sDelay.sData.eOriginalUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
110                psSink->sElement.sDelay.sSnapshot.eOriginalUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
111                psSink->sElement.sNotification.sResults.sThreshold.eUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
112                psSink->sElement.sNotification.sResults.sThreshold.uiValue = BSYNCLIB_P_VIDEO_SINK_DEFAULT_THRESHOLD_VALUE;
113        }
114
115        BDBG_LEAVE(BSYNClib_VideoSink_Create);
116        return psSink;
117}
118
119void BSYNClib_VideoSink_Destroy(BSYNClib_VideoSink * psSink)
120{
121        BDBG_ENTER(BSYNClib_VideoSink_Destroy);
122
123        BDBG_ASSERT(psSink);
124
125        BKNI_Free(psSink);
126
127        BDBG_LEAVE(BSYNClib_VideoSink_Destroy);
128}
129
130bool BSYNClib_VideoSink_SyncCheck(BSYNClib_VideoSink * psSink)
131{
132        bool bPass = false;
133       
134        BDBG_ENTER(BSYNClib_VideoSink_SyncCheck);
135
136        BDBG_ASSERT(psSink);
137
138        bPass = !psSink->sElement.sSnapshot.bSynchronize
139                || (psSink->sFormat.sSnapshot.bValid /* must have a valid format */
140                && psSink->sElement.sDelay.sSnapshot.bValid /* have a valid measured delay */
141                && psSink->sElement.sDelay.sResults.bAccepted); /* and be accepted */
142
143        BDBG_MSG(("[%d] Video sink %d sync check:", psSink->sElement.hParent->iIndex, psSink->sElement.uiIndex));
144        BDBG_MSG(("[%d]  %s", psSink->sElement.hParent->iIndex, psSink->sElement.sSnapshot.bSynchronize ? "synchronized" : "ignored"));
145        BDBG_MSG(("[%d]  format %s", psSink->sElement.hParent->iIndex, psSink->sFormat.sSnapshot.bValid ? "valid" : "invalid"));
146        BDBG_MSG(("[%d]  delay %s, %s", psSink->sElement.hParent->iIndex, psSink->sElement.sDelay.sSnapshot.bValid ? "valid" : "invalid", 
147                psSink->sElement.sDelay.sResults.bAccepted ? "accepted" : "unaccepted"));
148
149        /* TODO: is there a better way to get these settings? */
150        if (psSink->sElement.hParent->hParent->sSettings.sVideo.bRequireFullScreen)
151        {
152                bPass = bPass && psSink->sSnapshot.bFullScreen;
153                BDBG_MSG(("[%d]  full screen required, %s screen found", psSink->sElement.hParent->iIndex, 
154                        psSink->sSnapshot.bFullScreen ? "full" : "partial"));
155        }
156
157        BDBG_LEAVE(BSYNClib_VideoSink_SyncCheck);
158        return bPass;
159}
160
161void BSYNClib_VideoSink_Reset_isr(BSYNClib_VideoSink * psSink)
162{
163        BDBG_ENTER(BSYNClib_VideoSink_Reset_isr);
164
165        BDBG_ASSERT(psSink);
166
167        psSink->sData.bForcedCaptureEnabled = false;
168        psSink->sData.bMasterFrameRateEnabled = false;
169        psSink->sData.bVisible = false;
170        psSink->sData.bFullScreen = false;
171
172        BDBG_LEAVE(BSYNClib_VideoSink_Reset_isr);
173}
174
175void BSYNClib_VideoSink_GetDefaultConfig(BSYNClib_VideoSink_Config * psConfig)
176{
177        BDBG_ENTER(BSYNClib_VideoSink_GetDefaultConfig);
178
179        BDBG_ASSERT(psConfig);
180       
181        BKNI_Memset(psConfig, 0, sizeof(BSYNClib_VideoSink_Config));
182
183        psConfig->bForcedCaptureEnabled = true;
184        psConfig->bMasterFrameRateEnabled = true;
185        psConfig->sFormat.bInterlaced = true;
186        psConfig->sFormat.eFrameRate = BAVC_FrameRateCode_eUnknown;
187        psConfig->sDelay.sMeasured.eUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
188        psConfig->sDelay.sMax.eUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
189        psConfig->sDelay.sMax.uiValue = BSYNCLIB_P_VIDEO_SINK_DEFAULT_CAPACITY;
190
191        BDBG_LEAVE(BSYNClib_VideoSink_GetDefaultConfig);
192}
193
194void BSYNClib_VideoSink_P_SelfClearConfig_isr(BSYNClib_VideoSink * psSink)
195{
196        BDBG_ENTER(BSYNClib_VideoSink_P_SelfClearConfig_isr);
197
198        BDBG_ASSERT(psSink);
199       
200        psSink->sConfig.sDelay.bReceived = false;
201        psSink->sConfig.sFormat.bReceived = false;
202
203        BDBG_LEAVE(BSYNClib_VideoSink_P_SelfClearConfig_isr);
204}
205
206BERR_Code BSYNClib_VideoSink_P_ProcessConfig_isr(BSYNClib_VideoSink * psSink)
207{
208        BERR_Code rc = BERR_SUCCESS;
209        BSYNClib_VideoSink_Config * psConfig;
210        BSYNClib_Channel_Handle hChn;
211        bool bChanged = false;
212        bool bPrediction = false;
213        BSYNClib_DelayElement sDesired;
214        BSYNClib_DelayElement * psCurrent;
215        BSYNClib_DelayElement_DiffResults sElementDiffResults;
216        BSYNClib_VideoFormat sFormat;
217        bool bFormatReceived = false;
218        BSYNClib_VideoFormat_DiffResults sFormatDiffResults;
219
220        BDBG_ENTER(BSYNClib_VideoSink_P_ProcessConfig_isr);
221       
222        BDBG_ASSERT(psSink);
223       
224        hChn = psSink->sElement.hParent;
225        psConfig = &psSink->sConfig;
226        psCurrent = &psSink->sElement;
227
228        BKNI_Memset(&sElementDiffResults, 0, sizeof(BSYNClib_DelayElement_DiffResults));
229
230        /* check lifecycle first, not yet available for sinks */
231        BSYNClib_DelayElement_CheckLifecycle_isr(true, psCurrent, &sElementDiffResults);
232        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
233        {
234                BSYNClib_DelayElement_Reset_isr(psCurrent);
235        }
236
237        /* create "desired" delay element config */
238        sDesired = *psCurrent;
239        sDesired.sData.bStarted = true;
240        sDesired.sData.bSynchronize = psConfig->bSynchronize;
241        sDesired.sDelay.sData.eOriginalUnits = psConfig->sDelay.sMeasured.eUnits;
242        sDesired.sDelay.sData.uiMeasured = BSYNClib_P_Convert_isr(psConfig->sDelay.sMeasured.uiValue, psConfig->sDelay.sMeasured.eUnits, BSYNClib_Units_e27MhzTicks);
243        sDesired.sDelay.sData.uiCustom = BSYNClib_P_Convert_isr(psConfig->sDelay.sCustom.uiValue, psConfig->sDelay.sCustom.eUnits, BSYNClib_Units_e27MhzTicks);
244        sDesired.sDelay.sData.uiCapacity = BSYNClib_P_Convert_isr(psConfig->sDelay.sMax.uiValue, psConfig->sDelay.sMax.eUnits, BSYNClib_Units_e27MhzTicks);
245        sDesired.sNotification.sData.bReceived = psConfig->sDelay.bReceived;
246        /* TODO: reexamine assumption of 1 vsync'edness here */
247        /* if the units are vsyncs, we want a threshold of 1 vsync, don't convert 1 vsync @ 60Hz to x.y vsyncs @ 50 Hz */
248        if (psConfig->sDelay.sMeasured.eUnits == BSYNClib_Units_e24HzVsyncs
249                || psConfig->sDelay.sMeasured.eUnits == BSYNClib_Units_e50HzVsyncs
250                || psConfig->sDelay.sMeasured.eUnits == BSYNClib_Units_e60HzVsyncs)
251        {
252                sDesired.sNotification.sResults.sThreshold.eUnits = psConfig->sDelay.sMeasured.eUnits;
253        }
254        else
255        {
256                if (psSink->sStatus.sDelayNotification.sThreshold.eUnits != psConfig->sDelay.sMeasured.eUnits)
257                {
258                        /* convert status units to user's measurement units */
259                        psSink->sStatus.sDelayNotification.sThreshold.uiValue = BSYNClib_P_Convert_isr(psSink->sStatus.sDelayNotification.sThreshold.uiValue, psSink->sStatus.sDelayNotification.sThreshold.eUnits, BSYNClib_Units_e27MhzTicks);
260                        psSink->sStatus.sDelayNotification.sThreshold.uiValue = BSYNClib_P_Convert_isr(psSink->sStatus.sDelayNotification.sThreshold.uiValue, BSYNClib_Units_e27MhzTicks, psConfig->sDelay.sMeasured.eUnits);
261                }
262        }
263
264        psSink->sStatus.sDelayNotification.sThreshold.eUnits = psConfig->sDelay.sMeasured.eUnits;
265        /* TODO: copy max delay for 7038 */
266
267        BSYNClib_DelayElement_Diff_isr(&sDesired, &psSink->sElement, &sElementDiffResults);
268
269        if (sElementDiffResults.bChanged)
270        {
271                bChanged = true;
272                BSYNClib_DelayElement_Patch_isr(&sDesired, &psSink->sElement, &sElementDiffResults);
273        }
274
275        /* TODO: need to remove this because we don't have started lifecycle event anymore */
276        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
277        {
278                /* reset sink data */
279                BSYNClib_VideoSink_Reset_isr(psSink);
280        }
281
282        bFormatReceived = psConfig->sFormat.bReceived;
283
284        /* received sink format info */
285        if (bFormatReceived)
286        {
287                /* TODO: this code needs to know the current state of MAD and the user MAD enable flag */
288                /* note, MAD now on in PIG mode, so prediction doesn't work anymore */
289#if 0
290                /* if there is a change in display height, do MAD prediction */
291                if (psSink->sFormat.sData.uiHeight != psConfig->sFormat.uiHeight)
292                {
293                        /* predicting a state change means we should not adjust */
294                        bPrediction = BSYNClib_Channel_P_PredictMadStateChange_isr(hChn, psSink);
295                }
296#endif
297
298                /* create "desired" video format config */
299                sFormat.sData.bInterlaced = psConfig->sFormat.bInterlaced;
300                sFormat.sData.uiHeight = psConfig->sFormat.uiHeight;
301                sFormat.sData.eFrameRate = psConfig->sFormat.eFrameRate;
302
303                BSYNClib_VideoFormat_Diff_isr(&sFormat, &psSink->sFormat, &sFormatDiffResults);
304
305                if (sFormatDiffResults.bChanged)
306                {
307                        bChanged = true;
308                        BSYNClib_Channel_P_ResetVideoSourceJtiFactor_isr(hChn);
309                        BSYNClib_VideoFormat_Patch_isr(&sFormat, &psSink->sFormat, &sFormatDiffResults);
310                }
311               
312                /* set rmd sink format */
313                rc = BSYNClib_RateMismatchDetector_SetVideoSinkFormat_isr(hChn->hDetector, psSink->sElement.uiIndex, &sFormat, psConfig->bMasterFrameRateEnabled);
314                if (rc) goto error;
315        }
316
317        /* do this after format processing, in case we received both at the same time */
318        if (sElementDiffResults.bDelayReceived)
319        {
320#if 0
321                if (psSink->sElement.sDelay.sData.uiMeasured > 0)
322                {
323                        /* TODO: we need to convert this into knowing which sink is sync-locked to the decoder */
324                        if (!psSink->sData.bMasterFrameRateEnabled)
325                        {
326                                /* if we are sync-slipping, VDC will not report the correct number for progressive
327                                sync slipped displays.  It *will* report the correct number for interlaced sync
328                                slipped displays. This is because the vsync callback does not support fractional
329                                numbers, so where we should use 1/2 vsync for average progressive sync slip delay
330                                we are told 1 vsync. The following code compensates for this. */
331                                /* adjust results from VDC by 1 vsync down and then 1/2 frame up */
332                                psSink->sElement.sDelay.sData.uiMeasured -= BSYNClib_VideoFormat_P_GetVsyncPeriod_isr(&psSink->sFormat);
333                                psSink->sElement.sDelay.sData.uiMeasured += BSYNClib_VideoFormat_P_GetFramePeriod_isr(&psSink->sFormat) / 2;
334                        }
335                }
336#endif
337
338                BDBG_MSG(("[%d] Video sink %u delay received: %u ms", hChn->iIndex, psSink->sElement.uiIndex,
339                        BSYNClib_P_Convert_isr(psSink->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
340                       
341                /* all window delays are immediately accepted, no timeout necessary */
342                psSink->sElement.sDelay.sResults.bAccepted = true;
343        }
344
345        /* copy window-specific data */
346        if 
347        (
348                (psSink->sData.bForcedCaptureEnabled != psConfig->bForcedCaptureEnabled)
349                || (psSink->sData.bMasterFrameRateEnabled != psConfig->bMasterFrameRateEnabled)
350                || (psSink->sData.bVisible != psConfig->bVisible)
351        )
352        {
353                psSink->sData.bForcedCaptureEnabled = psConfig->bForcedCaptureEnabled;
354                psSink->sData.bMasterFrameRateEnabled = psConfig->bMasterFrameRateEnabled;
355                psSink->sData.bVisible = psConfig->bVisible;
356
357                bChanged = true;
358
359                /* TODO: find min delay */
360                /*psSink->sData.uiMinDelay = */
361        }
362
363        /* copy window-specific data */
364        if (psSink->sData.bFullScreen != psConfig->bFullScreen)
365        {
366                psSink->sData.bFullScreen = psConfig->bFullScreen;
367                bChanged = true;
368
369                /* TODO: old code resets rmd when window resized, still necessary? */
370                /* tell mute control that something happened that needs processing */
371                BSYNClib_MuteControl_ScheduleTask_isr(hChn);
372        }
373
374        if (bChanged)
375        {
376                BDBG_MSG(("[%d] Video sink %u properties changed:", hChn->iIndex, psSink->sElement.uiIndex));
377                BDBG_MSG(("[%d]  %s", hChn->iIndex, psSink->sElement.sData.bSynchronize ? "synchronized" : "ignored"));
378                if (sElementDiffResults.eLifecycleEvent != BSYNClib_DelayElement_LifecycleEvent_eNone)
379                {
380                        BDBG_MSG(("  %s", BSYNClib_DelayElement_LifecycleEventNames[sElementDiffResults.eLifecycleEvent]));
381                }
382                BDBG_MSG(("[%d]  measured delay %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSink->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
383                BDBG_MSG(("[%d]  custom delay %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSink->sElement.sDelay.sData.uiCustom, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
384                BDBG_MSG(("[%d]  delay capacity %u ms", hChn->iIndex, BSYNClib_P_Convert_isr(psSink->sElement.sDelay.sData.uiCapacity, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
385                BDBG_MSG(("[%d]  forced capture %s", hChn->iIndex, psSink->sData.bForcedCaptureEnabled ? "enabled" : "disabled"));
386                BDBG_MSG(("[%d]  master frame rate %s", hChn->iIndex, psSink->sData.bMasterFrameRateEnabled ? "enabled" : "disabled"));
387                BDBG_MSG(("[%d]  %s screen", hChn->iIndex, psSink->sData.bFullScreen ? "full" : "partial"));
388                BDBG_MSG(("[%d]  %s", hChn->iIndex, psSink->sData.bVisible ? "visible" : "hidden"));
389                BDBG_MSG(("[%d]  format:", hChn->iIndex));
390                BDBG_MSG(("[%d]    %s", hChn->iIndex, psSink->sFormat.sData.bInterlaced ? "interlaced" : "progressive"));
391                BDBG_MSG(("[%d]    height %u", hChn->iIndex, psSink->sFormat.sData.uiHeight));
392                BDBG_MSG(("[%d]    frame rate %s", hChn->iIndex, BSYNClib_VideoFormat_P_GetFrameRateName_isr(psSink->sFormat.sData.eFrameRate)));
393        }
394       
395        /* if anything changed in the config, reprocess based on current state */
396        if (bChanged && !bPrediction && BSYNClib_Channel_P_Enabled_isr(hChn))
397        {
398                BSYNClib_Channel_P_ScheduleTask_isr(hChn);
399        }
400       
401        goto end;
402       
403error:
404
405end:
406
407        BDBG_LEAVE(BSYNClib_VideoSink_P_ProcessConfig_isr);
408        return rc;
409}
410
411void BSYNClib_VideoSink_Snapshot_isr(BSYNClib_VideoSink * psSink)
412{
413        BDBG_ENTER(BSYNClib_VideoSink_Snapshot_isr);
414
415        BDBG_ASSERT(psSink);
416
417        psSink->sSnapshot = psSink->sData;
418       
419        BSYNClib_DelayElement_Snapshot_isr(&psSink->sElement);
420        BSYNClib_VideoFormat_Snapshot_isr(&psSink->sFormat);
421
422        BDBG_LEAVE(BSYNClib_VideoSink_Snapshot_isr);
423}
424
425void BSYNClib_VideoSink_P_GetDefaultStatus(
426        BSYNClib_Sink_Status * psStatus
427)
428{
429        BDBG_ENTER(BSYNClib_VideoSink_P_GetDefaultStatus);
430
431        BDBG_ASSERT(psStatus);
432
433        psStatus->sDelayNotification.bEnabled = true;
434        psStatus->sDelayNotification.sThreshold.uiValue = BSYNCLIB_P_VIDEO_SINK_DEFAULT_THRESHOLD_VALUE;
435        psStatus->sDelayNotification.sThreshold.eUnits = BSYNCLIB_P_VIDEO_SINK_DEFAULT_UNITS;
436        psStatus->sAppliedDelay.uiValue = 0;
437
438        BDBG_LEAVE(BSYNClib_VideoSink_P_GetDefaultStatus);
439}
440
Note: See TracBrowser for help on using the repository browser.