source: svn/newcon3bcm2_21bu/nexus/modules/display/7552/src/nexus_video_input.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 70.3 KB
Line 
1/***************************************************************************
2 *     (c)2007-2011 Broadcom Corporation
3 *
4 *  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 *  and may only be used, duplicated, modified or distributed pursuant to the terms and
6 *  conditions of a separate, written license agreement executed between you and Broadcom
7 *  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 *  no license (express or implied), right to use, or waiver of any kind with respect to the
9 *  Software, and Broadcom expressly reserves all rights in and to the Software and all
10 *  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 *  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 *  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 *  Except as expressly set forth in the Authorized License,
15 *
16 *  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 *  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 *  and to use this information only in connection with your use of Broadcom integrated circuit products.
19 *
20 *  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 *  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 *  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 *  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 *  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 *  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 *  USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 *  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 *  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 *  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 *  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 *  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 *  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 *  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 *  ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: nexus_video_input.c $
39 * $brcm_Revision: 142 $
40 * $brcm_Date: 12/21/11 12:48p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/display/7400/src/nexus_video_input.c $
47 *
48 * 142   12/21/11 12:48p erickson
49 * SW7425-1971: improve debug, remove unused code
50 *
51 * 141   12/16/11 5:28p erickson
52 * SW7425-1878: merge XUDlib support for video encoder userdata
53 *
54 * SW7425-1878/5   12/16/11 7:55p ajagmag
55 * SW7425-1878: simple cleanup
56 *
57 * SW7425-1878/4   12/16/11 5:13p ajagmag
58 * SW7425-1878: Updated for easier merge
59 *
60 * 140   12/16/11 10:17a erickson
61 * SW7425-1877: clarify VideoInput connection logic, add TODO's for future
62 *  simplification
63 *
64 * SW7425-1878/3   12/16/11 2:11p ajagmag
65 * SW7425-1878: Update based on discussions with David E.
66 *
67 * SW7425-1878/2   12/15/11 10:31a ajagmag
68 * SW7425-1878: changes for user data encode use case
69 *
70 * SW7425-1878/1   12/15/11 7:20a ajagmag
71 * SW7425-1878: Bug fixes for user data encode use case
72 *
73 * 139   10/20/11 10:44a erickson
74 * SW7425-1546: set display->status.refreshRate when format changes
75 *
76 * 138   10/19/11 5:00p hongtaoz
77 * SW7425-1546: update display refresh rate according to current display
78 *  status; set stgIndex correctly for dual;
79 *
80 * 137   10/18/11 6:15p jtna
81 * SW7425-1531: add helper code to resize video windows when switching
82 *  between half-res 3D formats
83 *
84 * 136   7/8/11 1:17p erickson
85 * SW7346-306: VideoImageInput must set eInterruptRefreshRate with display
86 *  format
87 *
88 * 135   6/29/11 10:43a erickson
89 * SW7425-466: clean up on failed NEXUS_VideoWindow_AddInput
90 *
91 * 134   6/23/11 2:52p hongtaoz
92 * SW7425-466: add 3x decodes support;
93 *
94 * 133   6/14/11 3:11p vsilyaev
95 * SW7425-654: Propagate STG/trigger index from display to the video
96 *  decoder
97 *
98 * 132   5/16/11 5:38p jtna
99 * SW7422-446: add correct fix
100 *
101 * 131   5/16/11 5:33p jtna
102 * SW7422-446: pass in correct setting to BVDC_Source_SetOrientation()
103 *
104 * 130   4/22/11 3:13p vsilyaev
105 * SW7425-416: Updated 3D display API
106 *
107 * 129   12/10/10 5:06p erickson
108 * SW35230-2209: add NEXUS_VideoDecoderSettings.scanMode
109 *
110 * 128   8/24/10 4:27p erickson
111 * SW3548-2795: ForcePending should set sourcePending status to true
112 *
113 * 127   8/24/10 8:40a erickson
114 * SW35230-1059: fix uninitialized data caused by NEXUS_VideoInputSettings
115 *  change. use a GetDefaultSettings instead of static initialization.
116 *
117 * 126   7/8/10 9:30a erickson
118 * SW3548-3021: don't call VDB when in NEXUS_VideoInputResumeMode_eManual.
119 *  VDC doesn't need new RTS applied until
120 *  NEXUS_VideoInputResumeMode_eNow. this removes unnecessary error
121 *  messages and state machine churn.
122 *
123 * 125   6/11/10 2:30p erickson
124 * SW3556-1124: check pDirty->bFrameRate. derive nexus frameRate and
125 *  refreshRate from eFrameRateCode, not pFmtInfo.
126 *
127 * 124   6/1/10 9:39p bandrews
128 * SW3548-2323: unlinked work on 7420 with 35230, input and display only
129 *  tuned on latter
130 *
131 * 123   5/5/10 7:26p bandrews
132 * SW3548-2323: updated to use apply changes if update mode says so
133 *
134 * 122   3/30/10 6:39p bandrews
135 * SW3548-2323: proxy code generator doesn't like arrays as parameters to
136 *  public APIs
137 *
138 * 121   3/30/10 4:49p bandrews
139 * SW3548-2323: merge to main, need to match header
140 *
141 * 120   3/29/10 3:39p bandrews
142 * SW3548-2323: merge to main
143 *
144 * SW3548-2323/6   3/8/10 3:54p bandrews
145 * SW3548-2323: merge from latest
146 *
147 * 119   3/26/10 2:19p erickson
148 * SW7405-3965: refactor mosaic to support hd/sd simul mode
149 *
150 * 118   3/23/10 3:25p petlee
151 * SW35230-106: Merging branch SW35230-106 to mainline
152 *
153 * SW35230-106a/9   3/22/10 1:20p petlee
154 * SW35230-106: Minor updates according to code review
155 *
156 * SW35230-106a/8   3/9/10 2:57p petlee
157 * SW35230-106: Minor cleanups
158 *
159 * SW35230-106a/6   3/9/10 2:00p petlee
160 * SW35230-106: Update the re-work done for VideoInput.
161 *
162 * SW35230-106a/5   2/26/10 5:46p petlee
163 * SW35230-106: Wrap g_VideoInputState with #if NEXUS_DTV_PLATFORM > 2
164 *
165 * SW35230-106a/4   2/26/10 5:31p petlee
166 * SW35230-106: Add check for existing sourceVdc before creating a VDC
167 *  handle
168 *
169 * SW35230-106a/3   2/26/10 3:12p petlee
170 * SW35230-106: Move destruction of sourceVdc to VideoInput_Shutdown()
171 *
172 * SW35230-106a/2   2/26/10 10:33a petlee
173 * SW35230-106: Handle cases where sourceVdc is used when it has not been
174 *  created yet. Public APIs should store state and set it later once
175 *  sourceVdc gets created.
176 *
177 * SW35230-106a/1   2/25/10 3:01p petlee
178 * SW35230-106: Update to accomodate new requirements in 35230 h/w where
179 *  three analog video decoders are routed through two ports, and the two
180 *  ports + hdmi input are routed through two hd_dvi blocks for routing to
181 *  the BVN.
182 *
183 * 117   2/22/10 12:50p erickson
184 * SW7405-3625: update backendMosaic impl
185 *
186 * 116   2/19/10 3:30p erickson
187 * SW7405-3625: fix non-mosaic capable systems
188 *
189 * 115   2/19/10 1:23p erickson
190 * SW7405-3625: add NEXUS_VideoWindowMosaicSettings for backendMosaic
191 *  support
192 *
193 * SW3548_2323/5   12/15/09 8:54p bandrews
194 * SW3548-2323: updated per bvdc_tune.h
195 *
196 * SW3548_2323/4   12/15/09 8:50p bandrews
197 * SW3548-2323: updated from VDC team's vdc_tune impl
198 *
199 * SW3548_2323/3   12/15/09 8:38p bandrews
200 * SW3548-2323: merge from latest
201 *
202 * 114   12/9/09 3:10p erickson
203 * SW7405-3394: refactor mosaic mode API
204 *
205 * 113   11/2/09 10:43a erickson
206 * SW3548-2584: allow NULL color matrix for
207 *  NEXUS_VideoInput_SetColorMatrix
208 *
209 * 112   10/15/09 4:31p erickson
210 * SWDEPRECATED-3881: don't use deprecated struct members. use NEXUS_NUM
211 *  defines
212 *
213 * SW3548_2323/2   9/28/09 8:23p bandrews
214 * 3548-2323: initial check-in of libtune port
215 *
216 * SW3548_2323/1   9/22/09 6:50p bandrews
217 * SW3548-2323: libTune nexus passthrough
218 *
219 * 111   9/21/09 2:53p erickson
220 * SW3548-2475: clarify meaning and use of VDC source callback params re:
221 *  format change
222 *
223 * 110   9/9/09 1:20p erickson
224 * SW7405-2977: allow build with no video decoder
225 *
226 * 109   8/28/09 9:36a gmohile
227 * SW7403-796 : Add legacy vdc support
228 *
229 * 108   8/19/09 3:39p erickson
230 * PR57822: set NEXUS_VideoInputStatus.videoPresent to true if digital
231 *  picture not muted
232 *
233 * 107   8/10/09 10:09a erickson
234 * PR56325: only feedback display information to sync-locked inputs
235 *
236 * 106   8/10/09 8:17a gmohile
237 * PR 56400 : Merge legacy vdc support to main line
238 *
239 * 105   8/6/09 2:23p erickson
240 * PR57387: add BDBG_ERR to catch BFMT_VideoFmt/NEXUS_VideoFormat
241 *  mismatches in the future
242 *
243 * 104   8/3/09 8:57a erickson
244 * PR57220: added new framerates to switch
245 *
246 * 103   7/31/09 11:17a gmohile
247 * PR 56512 : Add 7403 support
248 *
249 * 102   7/23/09 10:39a erickson
250 * PR56969: add hddvi input
251 *
252 * 101   7/10/09 3:58p erickson
253 * PR56558: add NEXUS_DisplayModule_SetVideoDecoderModule to allow faster
254 *  start up time
255 *
256 * 100   7/8/09 2:50p erickson
257 * PR56634: disable DNR in the BVDC_Source when the VideoInput is
258 *  disconnect from the last Nexus VideoWindow
259 *
260 * 99   6/15/09 5:01p erickson
261 * PR56022: deprecated numWindows and numDisplays
262 *
263 * 98   5/20/09 3:29p erickson
264 * PR54880: keep track of whether VDC heaps were created and only destroy
265 *  what was created
266 *
267 * 97   5/19/09 10:59a erickson
268 * PR54880: fix heap handling. don't assume VideoDecoder will return NULL
269 *  heap for default.
270 *
271 * 96   4/24/09 11:58a erickson
272 * PR54572: replace calls to NEXUS_VideoInput_P_Get with input-
273 *  >destination. we can't recreate a NEXUS_VideoInput_P_Link as a result
274 *  of an internal event.
275 *
276 * 95   4/20/09 5:06p jgarrett
277 * PR 54346: Adding better recovery from invalid app states.
278 *
279 * 94   4/6/09 11:49a erickson
280 * PR53137: don't tear down vbi until NEXUS_VideoInput_P_DestroyLink.
281 *  NEXUS_VideoInput_Shutdown may not actually tear down input.
282 *
283 * 93   4/2/09 9:38a jgarrett
284 * PR 53654: Adding option to suspend dynamic RTS for a source
285 *
286 * 92   3/30/09 11:17a erickson
287 * PR48963: use NEXUS_VideoDecoder_GetHeap_priv
288 *
289 * 91   3/26/09 10:49a erickson
290 * PR53613: allow NEXUS_VideoInput_GetColorMatrix to read from VDC is user
291 *  has not set the NEXUS_ColorMatrix
292 *
293 * 90   3/23/09 1:43p erickson
294 * PR48984: destroy checkFormatChanged event and event handler
295 *
296 * 89   3/20/09 1:59p jgarrett
297 * PR 53465: Adding numeric refresh rate
298 *
299 * 88   3/10/09 4:30p erickson
300 * PR53042: check for NULL on every call to NEXUS_VideoInput_P_Get
301 *
302 * 87   3/6/09 7:39p jgarrett
303 * PR 52600: Bailing out of resume of VDB fails
304 *
305 * 86   3/4/09 1:03p jgarrett
306 * PR 52618: Adding forcePcFormat option to HdmiInput
307 *
308 * 85   2/10/09 11:47a jgarrett
309 * PR 48984: Incorporating comments from vdb review
310 *
311 * 84   1/30/09 12:02p vsilyaev
312 * PR 51741: Don't free unallocated pointers
313 *
314 * 83   1/9/09 2:38a erickson
315 * PR50502: defer source pending callback until the video has an active
316 *  picture so that there's a valid format
317 *
318 * 82   1/6/09 11:49a jgarrett
319 * PR 48984: Merging dynamic RTS code to main branch
320 *
321 * 81   12/23/08 6:03p vsilyaev
322 * PR 50432: Added options for the closed caption decoder
323 *
324 * 80   12/16/08 11:50a jgarrett
325 * PR 50002: Adding NEXUS_VideoInput_ForcePending
326 *
327 * PR48984/3   12/10/08 11:29a jgarrett
328 * PR 48984: Merge to latest baseline
329 *
330 * 79   12/9/08 10:35a erickson
331 * PR35457: clarify BDBG_ERR
332 *
333 * 78   12/8/08 5:04p erickson
334 * PR50058: rework internal VideoInput vbi accounting, don't store refcnt
335 *
336 * PR48984/2   11/26/08 6:19p jgarrett
337 * PR 48984: Merging to latest baseline
338 *
339 * 77   11/21/08 12:53p erickson
340 * PR43413: added vps decode
341 *
342 * PR48984/1   11/20/08 6:47p jgarrett
343 * PR 48984: Adding vdb hooks for auto source pending
344 *
345 * 76   11/17/08 12:28p erickson
346 * PR49203: ensure there are no unnecessary unguarded BVDC_ApplyChanges
347 *  calls in Nexus
348 *
349 * 75   11/6/08 5:22p erickson
350 * PR47030: rename NEXUS_VideoInput_P_DestroyLink
351 *
352 * 74   11/4/08 4:24p erickson
353 * PR47030: pass VideoDecoder heap when creating link
354 *
355 * 73   11/4/08 12:38p erickson
356 * PR47030: add NEXUS_Display_P_DestroyHeap, refactor so that all VDC
357 *  Sources are created by NEXUS_VideoInput_P_CreateLink
358 *
359 * 72   11/3/08 2:27p erickson
360 * PR47030: add HdmiInput heap
361 *
362 * 71   10/31/08 12:15a erickson
363 * PR47392: use value of 0xFFFF for no WSS data
364 *
365 * 70   10/30/08 8:56p erickson
366 * PR47030: use NEXUS_HeapHandle for per-window and per-source heaps
367 *
368 * 69   10/29/08 12:15p erickson
369 * PR48373: set defaults based on bvbi.c defaults
370 *
371 * 68   10/29/08 11:55a erickson
372 * PR47895: merge
373 *
374 * PR46000/2   10/28/08 9:16p mlei
375 * PR47895: fire soure pending callback when analog video goes stable.
376 *
377 * 67   10/24/08 1:38p erickson
378 * PR47030: added fullHd/hd/sd buffer settings for digital when
379 *  analog/digital memory sharing is enabled
380 *
381 * 66   10/24/08 11:16a erickson
382 * PR48006: memset link for easier init, protect against NULL pFmtInfo
383 *
384 * 65   10/17/08 3:23p erickson
385 * PR47030: impl shared analog/digital heap
386 *
387 * 64   10/17/08 12:24p erickson
388 * PR47030: impl shared analog/digital heap
389 *
390 * 63   10/16/08 5:25p erickson
391 * PR48006: call NEXUS_AnalogVideoDecoder_P_SetVbi with VDC source
392 *  callback format
393 *
394 * 62   10/16/08 12:32p erickson
395 * PR47070: fix gemStar naming convention
396 *
397 * 61   10/5/08 11:42p erickson
398 * PR40799: ensure atomic access to info.mfd
399 *
400 * 60   10/2/08 12:55p erickson
401 * PR40799: create/destroy BVDC_Source when AnalogVideoDecoder is
402 *  connected/disconnected
403 *
404 * 59   9/26/08 2:44p erickson
405 * PR43944: merge
406 *
407 * 58   9/26/08 11:58a erickson
408 * PR46515: add VDEC and VBI power management
409 *
410 * 57   9/24/08 5:21p erickson
411 * PR47070: add vbi closedCaption, teletext and gemStar DataReady
412 *  callbacks
413 *
414 * 56   9/8/08 9:46a erickson
415 * PR46068: added BDBG_OBJECT_ASSERT for isr-time link
416 *
417 * 55   9/2/08 10:27p katrep
418 * PR46457: Configure nexus features at the run time based on board strap
419 *  options
420 *
421 * 54   9/2/08 5:23p erickson
422 * PR46473: NEXUS_VideoInput_Shutdown will call
423 *  NEXUS_VideoWindow_RemoveInput if needed
424 *
425 * 53   8/22/08 11:08p erickson
426 * PR45711: must call BVDC_ApplyChanges after clearing VDC source
427 *  callback. don't recreate the video input link during
428 *  NEXUS_VideoInput_Shutdown if it doesn't already exist.
429 *
430 * 52   8/22/08 7:05p erickson
431 * PR45794: change internal storage
432 *
433 * 51   8/21/08 12:24p erickson
434 * PR45711: stop BVDC_Source_InstallCallback before destroying the video
435 *  input
436 *
437 * 50   8/20/08 12:10p erickson
438 * PR45616: prefer data from VDC Source callback over
439 *  BVDC_Source_GetInputStatus
440 *
441 * 49   8/19/08 12:21p erickson
442 * PR45794: strengthen ERR message
443 *
444 * 48   8/8/08 5:34p vishk
445 * PR 45390: Nexus VBI reports "No CloseCaption buffer" when VBI not
446 *  configured.
447 *
448 * 47   7/23/08 10:11a erickson
449 * PR45073: protect access to NEXUS_P_VertFreq_FromMagnum
450 *
451 * 46   7/17/08 9:41a erickson
452 * PR44764: added BDBG_ERR
453 *
454 * 45   7/11/08 4:09p erickson
455 * PR44764: default MFD info to zero. someone may query status before the
456 *  first picture data ready isr
457 *
458 * 44   7/8/08 4:10p erickson
459 * PR44524: fix race condition where multiple sourcePending callbacks
460 *  occur. Nexus should not block callbacks if status.sourcePending is
461 *  set. app may have already read the status in response to the 1st
462 *  callback and so it needs the 2nd callback.
463 *
464 * 43   7/3/08 5:07p erickson
465 * PR43699: Remove unnecessary VDC Get functions from Nexus to avoid race
466 *  conditions
467 *
468 * 42   6/30/08 10:30a erickson
469 * PR43785: use pDirty->bCrcValue for CRC check
470 *
471 * 41   6/26/08 9:07a erickson
472 * PR44050: merge
473 *
474 * PR44050/1   6/25/08 5:42p dyzhang
475 * PR44050: h/w and s/w jpeg doesn't work after enabling source pending.
476 *  need to apply change after set resume.
477 *
478 * 40   6/20/08 2:10p erickson
479 * PR43859: merge
480 *
481 * PR43859/5   6/20/08 1:13p dyzhang
482 * PR43859: need to return the framerate information by format info. The
483 *  framerate code from callback data is not reliable which causes dynamic
484 *  rts calculation fail.
485 *
486 * PR43859/4   6/20/08 1:07p dyzhang
487 * PR43859: merge from mainline
488 *
489 * 39   6/20/08 9:44a erickson
490 * PR43859: merge
491 *
492 * PR43859/3   6/19/08 8:18p dyzhang
493 * PR43859: link status sourc pending need to be set to false are resume
494 *  now
495 *
496 * PR43859/2   6/19/08 8:15p dyzhang
497 * PR43859: merge from main line
498 *
499 * 38   6/19/08 4:29p erickson
500 * PR43859: merge
501 *
502 * PR43859/1   6/19/08 3:27p dyzhang
503 * PR43859: Need apply change for set resume. And fix a few bugs
504 *
505 * 37   6/11/08 12:46p vsilyaev
506 * PR 43491: Added support for CCIR-656 input
507 *
508 * 36   5/30/08 5:08p rjlewis
509 * PR40352: warnings.
510 *
511 * 35   5/30/08 3:29p erickson
512 * PR41202: fix warning
513 *
514 * 34   5/20/08 4:34p erickson
515 * PR41202: fixed VDC source/window heap support for WXGA support
516 *
517 * 33   5/12/08 9:28a erickson
518 * PR42365: fix crc logic
519 *
520 * 32   5/9/08 12:44p erickson
521 * PR39453: add sourcePending callback, set status.sourcePending based on
522 *  VDC dirty bits.
523 *
524 * 31   5/8/08 2:48p erickson
525 * PR42438: derive NEXUS_VideoInputStatus.format for digital decode using
526 *  common function
527 *
528 * 30   5/7/08 2:47p erickson
529 * PR42329: fix NEXUS_VideoInput_P_DisconnectVideoDecoder
530 *
531 * 29   5/5/08 3:02p erickson
532 * PR41202: fix logic for when to create a heap
533 *
534 * 28   5/1/08 12:57p erickson
535 * PR41202: call BVDC_Heap_Create for sharedAnalogDigitalHeap mode
536 *
537 * 27   4/30/08 3:08p erickson
538 * PR39453: add 3548/3556 features
539 *
540 * 26   4/28/08 4:10p erickson
541 * PR41533: unify EIA-608 and EIA-708 closed caption data capture in
542 *  NEXUS_VideoInput_ReadClosedCaption
543 *
544 * 25   4/23/08 4:29p erickson
545 * PR42071: remove dangling ;
546 *
547 * 24   4/7/08 4:10p erickson
548 * PR32888: added NEXUS_CRC_CAPTURE
549 *
550 * 23   4/4/08 10:08a erickson
551 * PR40513: add repeat
552 *
553 * 22   3/31/08 1:41p erickson
554 * PR41077: added NEXUS_ASSERT_MODULE to _priv function
555 *
556 * 21   3/31/08 12:32p erickson
557 * PR41073: check result of malloc and fail graciously
558 *
559 * 20   3/27/08 6:51p vsilyaev
560 * PR 40818: Fixed 7401 build
561 *
562 * 19   3/27/08 6:20p vsilyaev
563 * PR 40818: Added management of VDC heaps
564 *
565 * 18   3/27/08 4:22p vsilyaev
566 * PR 40818: Improved internal API to allow source private heaps
567 *
568 * 17   3/26/08 3:38p vsilyaev
569 * PR 40862: Added code to propagate display framerate to the decoder
570 *
571 * 16   3/26/08 10:54a erickson
572 * PR40742: added more HdmiInput which is passed in from VDC source
573 *  changed callback
574 *
575 * 15   3/21/08 12:44p vsilyaev
576 * PR 39986: Added support for VideoImageInput
577 *
578 * 14   3/21/08 11:40a erickson
579 * PR40716: merge
580 *
581 * PR40716/1   3/21/08 3:43p dyzhang
582 * PR40716: timebase settings for analog inputs are not correct. need to
583 *  use the framerate from callback data. the framerate from the format
584 *  information is the vertical framerate defined bfmt.c. This is the
585 *  value defined in standard and it's the value signal suppose to be but
586 *  sometime the real signal doesn't match the standard. The framerate
587 *  code from callback data is the real framerate of coming in signal
588 *  which is detected by decoder.
589 *
590 * 12   3/12/08 5:25p erickson
591 * PR40412: get analog VideoInputStatus from the VDC source callback.
592 *  BVDC_Source_GetInputStatus does not return reliable data.
593 *
594 * 11   3/12/08 4:32p erickson
595 * PR40412: fixed use of BVDC_Source_InstallCallback
596 *
597 * 10   3/6/08 3:07p erickson
598 * PR40103: convert to NEXUS_TaskCallback
599 *
600 * 9   3/3/08 9:21a erickson
601 * PR40156: fix legacy VDC
602 *
603 * 8   2/29/08 5:39p erickson
604 * PR40156: implement ColorMatrix function
605 *
606 * 7   2/28/08 10:42p vsilyaev
607 * PR 40103: Added interfaceHandle and settings for the
608 *  NEXUS_IsrCallbackCreate
609 *
610 * 6   2/19/08 5:24p erickson
611 * PR39748: added null check
612 *
613 * 5   2/19/08 4:12p erickson
614 * PR39746: BAVC_MFD_Picture should never be NULL
615 *
616 * 4   2/5/08 10:13a erickson
617 * PR38679: change private FindWindow
618 *
619 * 3   2/1/08 3:20p erickson
620 * PR38679: add vbi support
621 *
622 * 2   1/31/08 9:55a erickson
623 * PR36808: added SyncChannel interface
624 *
625 * 1   1/18/08 2:20p jgarrett
626 * PR 38808: Merging to main branch
627 *
628 * Nexus_Devel/29   1/11/08 1:51p erickson
629 * PR38679: add vbi read/write api's
630 *
631 * Nexus_Devel/28   1/11/08 12:33p erickson
632 * PR36159: set/unset input->destination
633 *
634 * Nexus_Devel/27   1/9/08 3:55p erickson
635 * PR36159: NEXUS_VideoInput_Shutdown should call
636 * NEXUS_VideoInput_P_Destroy
637 *
638 * Nexus_Devel/26   1/9/08 2:51p erickson
639 * PR34662: convert 7401 code for digital NEXUS_VideoInput_GetStatus to
640 * all platforms
641 *
642 * Nexus_Devel/25   1/9/08 12:14p vsilyaev
643 * PR 34662: Implemented VideoInput_GetStatus for legacy VDC
644 *
645 * Nexus_Devel/24   1/9/08 10:45a erickson
646 * PR34662: implemented sourceChanged callback and all
647 * NEXUS_VideoInputStatus members
648 *
649 * Nexus_Devel/23   1/3/08 9:20p erickson
650 * PR38213: rename to AnalogVideoDecoder
651 *
652 * Nexus_Devel/22   12/18/07 1:49p jgarrett
653 * PR 38213: Removing warnings
654 *
655 * Nexus_Devel/21   12/18/07 1:34p erickson
656 * PR38213: analog video input rework
657 *
658 * Nexus_Devel/20   12/5/07 3:09p vsilyaev
659 * PR 37934: Implemented BLST_S_DICT
660 *
661 * Nexus_Devel/19   11/28/07 1:43p vsilyaev
662 * PR 36159: Added global UpdateMode, removed per-function ApplyChanges
663 *
664 * Nexus_Devel/18   11/26/07 12:51p vsilyaev
665 * PR36159: PR36159: Bring up Nexus on 93563 platform
666 *
667 * Nexus_Devel/PR36159/1   11/26/07 10:09a gezhang
668 * PR36159: Bring up Nexus on 93563 platform
669 *
670 * Nexus_Devel/17   11/9/07 11:51a erickson
671 * PR36814: hdmi updaets
672 *
673 * Nexus_Devel/16   11/8/07 2:43p erickson
674 * PR36814: added HdmiInput
675 *
676 * Nexus_Devel/15   11/6/07 1:13p erickson
677 * PR36570: merge 3563
678 *
679 * Nexus_Devel/14   11/5/07 10:06a vsilyaev
680 * PR 36696: Fixed build problem with 7400/7405
681 *
682 * Nexus_Devel/13   11/2/07 4:42p vsilyaev
683 * PR 36696: Used connector model for VideoInput's and VideoOutput's
684 *
685 * Nexus_Devel/12   10/8/07 12:11p vsilyaev
686 * PR 34662: PR34926: reworked VBI interface
687 *
688 * Nexus_Devel/11   10/4/07 4:15p vsilyaev
689 * PR 34662: Removed hardcoded use of videoSource
690 *
691 * Nexus_Devel/10   10/4/07 3:34p vsilyaev
692 * PR 34662: Removed VideoInput descriptor
693 *
694 * Nexus_Devel/9   10/4/07 12:21p vsilyaev
695 * PR 34662: Coded VBI support
696 *
697 * Nexus_Devel/8   9/28/07 4:24p jgarrett
698 * PR 35002: Successful 7400 build
699 *
700 * Nexus_Devel/7   9/28/07 11:32a erickson
701 * PR34926: rename videodecoder to video_decoder
702 *
703 * Nexus_Devel/6   9/25/07 3:13p vsilyaev
704 * PR 34662: Fixed video output
705 *
706 * Nexus_Devel/5   9/25/07 12:33p vsilyaev
707 * PR 34662: Fixed warnings
708 *
709 * Nexus_Devel/4   9/24/07 2:42p vsilyaev
710 * PR 34662: Added code to disconnect input
711 *
712 * Nexus_Devel/3   9/24/07 12:20p vsilyaev
713 * PR 34662: Added connection of window and source
714 *
715 * Nexus_Devel/2   9/24/07 10:35a vsilyaev
716 * PR 34662: Added function to create VDC window
717 *
718 * Nexus_Devel/1   9/21/07 4:09p vsilyaev
719 * PR 34662: Implementation of Video Input API
720 *
721 **************************************************************************/
722#include "nexus_base.h"
723#include "nexus_display_module.h"
724#if NEXUS_NUM_VIDEO_DECODERS
725#include "priv/nexus_video_decoder_priv.h"
726#endif
727
728BDBG_MODULE(nexus_video_input);
729
730BDBG_OBJECT_ID(NEXUS_VideoInput_P_Link);
731
732#define pVideo (&g_NEXUS_DisplayModule_State)
733
734static void NEXUS_VideoInput_P_CheckFormatChanged(void *pParam);
735static NEXUS_VideoInput_P_Link *NEXUS_VideoInput_P_CreateLink_Init( NEXUS_VideoInput source, const NEXUS_VideoInput_P_LinkData *data, const NEXUS_VideoInput_P_Iface *iface );
736static void NEXUS_VideoInput_P_DestroyLink_Uninit( NEXUS_VideoInput_P_Link *link );
737static NEXUS_Error NEXUS_VideoInput_P_Create_VdcSource( NEXUS_VideoInput source, NEXUS_VideoInput_P_Link *link, const NEXUS_VideoInput_P_LinkData *data );
738static void NEXUS_VideoInput_P_Destroy_VdcSource( NEXUS_VideoInput_P_Link *link );
739
740/* this can be called from a SourceCallback or connecting an input to a window. */
741void NEXUS_VideoInput_P_TriggerSourceChanged_isr(NEXUS_VideoInput_P_Link *link, bool sourcePending)
742{
743    if ( sourcePending )
744    {
745        BDBG_MSG(("Source Pending ISR"));
746        link->status.sourcePending = true;
747        if ( link->resumeMode == NEXUS_VideoInputResumeMode_eManual )
748        {
749            BDBG_MSG(("Manual source pending.  VDB will be handled on resume."));
750            NEXUS_IsrCallback_Fire_isr(link->sourcePendingCallback);
751        }
752        else if ( link->sourcePendingEvent )
753        {
754            BDBG_MSG(("Auto VDB source pending"));
755            BKNI_SetEvent(link->sourcePendingEvent);
756        }
757    }
758    NEXUS_IsrCallback_Fire_isr(link->sourceChangedCallback);
759}
760
761static void NEXUS_VideoInput_P_SourceCallback_isr(void *pParam1, int pParam2, void *vdcData)
762{
763    NEXUS_VideoInput_P_Link *link = pParam1;
764    const BVDC_Source_CallbackData *pSrcData = (const BVDC_Source_CallbackData*)vdcData;
765    const BVDC_Source_DirtyBits *pDirty = &pSrcData->stDirty;
766    NEXUS_VideoInputStatus *pStatus;
767    bool srcPending;
768    bool formatChanged = false;
769
770    BSTD_UNUSED(pParam2);
771    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
772    pStatus = &link->status;
773
774    /* save all the data for later source calls */
775    link->vdcSourceCallbackData = *pSrcData;
776
777    switch(link->id) {
778    case BAVC_SourceId_eMpeg0:
779    case BAVC_SourceId_eMpeg1:
780    case BAVC_SourceId_eMpeg2:
781#if NEXUS_CRC_CAPTURE
782        if (pDirty->bCrcValue) {
783            NEXUS_VideoInputCrcData *pData = &link->crc.data[link->crc.wptr];
784            pData->idrPictureId = pSrcData->ulIdrPicId;
785            pData->pictureOrderCount = pSrcData->lPicOrderCnt;
786            pData->lumaCrc = pSrcData->ulLumaCrc;
787            pData->chromaCrc = pSrcData->ulChromaCrc;
788            pData->isField = pSrcData->eSourcePolarity != BAVC_Polarity_eFrame;
789            if (++link->crc.wptr == NEXUS_VIDEO_INPUT_CRC_QUEUE_SIZE) {
790                link->crc.wptr = 0;
791            }
792            if (link->crc.wptr == link->crc.rptr) {
793                BDBG_WRN(("crc capture overflow"));
794            }
795        }
796#endif
797        break;
798
799    default:
800        /* For analog/hd-dvi sources, we need to capture the data passed into the callback. Calling BVDC_Source_GetInputStatus does
801        not return reliable information.
802        A change in bActive will always result in a sourceChanged callback. */
803        pStatus->videoPresent = pSrcData->bActive;
804        /* Based on current VDC impl, pSrcData->pFmtInfo will never be NULL for analog/hddvi. We are checking anyway for code safety.
805        The main flag for knowing when video comes and goes is a change in bActive. */
806        if (pSrcData->pFmtInfo) {
807            if (pDirty->bFmtInfo || pDirty->bFrameRate) { /* save a couple cpu clock cycles */
808                NEXUS_VideoFormat videoFormat;
809                pStatus->width = pSrcData->pFmtInfo->ulWidth;
810                pStatus->height = pSrcData->pFmtInfo->ulHeight;
811                videoFormat = NEXUS_P_VideoFormat_FromMagnum(pSrcData->pFmtInfo->eVideoFmt);
812                if (videoFormat == NEXUS_VideoFormat_eUnknown) {
813                    BDBG_ERR(("Unable to convert analog magnum BFMT_VideoFmt %d to NEXUS_VideoFormat", pSrcData->pFmtInfo->eVideoFmt));
814                    /* For nexus_vdb and analog inputs, the videoFormat enum is required. The Nexus and FMT enum lists must be
815                    kept in sync.
816                    Another option is to learn if the stream is progressive/interlaced, then use NEXUS_P_VideoFormat_FromInfo. */
817                }
818                if (pStatus->format != videoFormat) {
819                    pStatus->format = videoFormat;
820                    formatChanged = true;
821                }
822                pStatus->aspectRatio = NEXUS_P_AspectRatio_FromMagnum(pSrcData->pFmtInfo->eAspectRatio);
823                pStatus->frameRate = NEXUS_P_FrameRate_FromMagnum(pSrcData->eFrameRateCode);
824                pStatus->refreshRate = NEXUS_P_RefreshRate_FromFrameRate(pStatus->frameRate);
825            }
826        }
827        else {
828            pStatus->format = NEXUS_VideoFormat_eUnknown;
829        }
830    }
831
832    /* don't fire source pending callback when the field is not active (e.g. muted).
833    instead, queue it up until we get an active picture. */
834    srcPending = false;
835#ifndef B_HAS_LEGACY_VDC
836    if (pDirty->bSrcPending) {
837        if (pSrcData->bActive) {
838            srcPending = true;
839        }
840        else {
841            link->deferSourcePending = true;
842        }
843    }
844    if (pSrcData->bActive && link->deferSourcePending) {
845        link->deferSourcePending = false;
846        srcPending = true;
847    }
848#endif
849
850    NEXUS_VideoInput_P_TriggerSourceChanged_isr(link, srcPending);
851
852    switch (link->input->type) {
853#if NEXUS_NUM_ANALOG_VIDEO_DECODERS
854    case NEXUS_VideoInputType_eAnalogVideoDecoder:
855        /* Allow AnalogVideoDecoder to do ISR processing */
856        NEXUS_AnalogVideoDecoder_P_SourceChanged_isr(link->input);
857
858        /* Must reconfigure VBI if the format changes */
859        if (formatChanged) {
860            BKNI_SetEvent(link->sourceChangedEvent);
861        }
862        break;
863#endif
864#if NEXUS_NUM_HDMI_INPUTS
865    case NEXUS_VideoInputType_eHdmi:
866        /* Allow HdmiInput to do ISR processing */
867        NEXUS_VideoInput_P_HdmiSourceCallback_isr(link, pSrcData);
868
869        /* HdmiInput needs a task callback to call BVDC_Source_GetInputStatus and get the remaining status information.
870        VideoInput must do the work. */
871        BKNI_SetEvent(link->sourceChangedEvent);
872        break;
873#endif
874    default:
875        break;
876    }
877}
878
879static void NEXUS_VideoInput_P_SourceChanged(void *context)
880{
881    NEXUS_VideoInput input = context;
882    NEXUS_VideoInput_P_Link *link = input->destination; /* do not call NEXUS_VideoInput_P_Get here. if the input has been shutdown, we can't recreate it here */
883
884    if (!link) return;
885    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
886
887    switch (link->input->type) {
888#if NEXUS_NUM_HDMI_INPUTS
889    case NEXUS_VideoInputType_eHdmi:
890        NEXUS_VideoInput_P_SetHdmiInputStatus(link);
891        break;
892#endif
893#if NEXUS_NUM_ANALOG_VIDEO_DECODERS
894    case NEXUS_VideoInputType_eAnalogVideoDecoder:
895        /* VBI decoders may have to be reconfigured on source format change
896        pFmtInfo should always be non-NULL here, but the "if" is to be extra safety */
897        if (link->vdcSourceCallbackData.pFmtInfo) {
898            (void)NEXUS_AnalogVideoDecoder_P_SetVbi(input->source, &link->vbiSettings, link->vdcSourceCallbackData.pFmtInfo->eVideoFmt);
899        }
900        break;
901#endif
902    default:
903        break;
904    }
905}
906
907static void NEXUS_VideoInput_P_SourcePending(void *context)
908{
909    NEXUS_VideoInput input = context;
910    NEXUS_VideoInput_P_Link *link = input->destination; /* do not call NEXUS_VideoInput_P_Get here. if the input has been shutdown, we can't recreate it here */
911
912    if (!link) return;
913    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
914
915    if ( link->resumeMode == NEXUS_VideoInputResumeMode_eAuto )
916    {
917        NEXUS_Vdb_P_HandleSourcePending(input);
918    }
919}
920
921void
922NEXUS_VideoInput_P_LinkData_Init(NEXUS_VideoInput_P_LinkData *data, BAVC_SourceId sourceId)
923{
924    BDBG_ASSERT(data);
925    BKNI_Memset(data, 0, sizeof(*data));
926    data->sourceId = sourceId;
927    return;
928}
929
930NEXUS_VideoInput_P_Link *
931NEXUS_VideoInput_P_CreateLink(NEXUS_VideoInput source, const NEXUS_VideoInput_P_LinkData *data, const NEXUS_VideoInput_P_Iface *iface)
932{
933    NEXUS_VideoInput_P_Link *link = NULL;
934    NEXUS_Error rc;
935
936    link = NEXUS_VideoInput_P_CreateLink_Init(source, data, iface);
937    if (!link) return NULL;
938
939    rc = NEXUS_VideoInput_P_Create_VdcSource(source, link, data);
940    if (NEXUS_SUCCESS != rc) {
941        NEXUS_VideoInput_P_DestroyLink_Uninit(link);
942        return NULL;
943    }
944
945    return link;
946}
947
948static void NEXUS_VideoInput_P_GetDefaultSettings(NEXUS_VideoInputSettings *pSettings)
949{
950    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
951    pSettings->video3DSettings.overrideOrientation = false;
952    pSettings->video3DSettings.orientation = NEXUS_VideoOrientation_e2D;
953    return;
954}
955
956static NEXUS_VideoInput_P_Link *
957NEXUS_VideoInput_P_CreateLink_Init(NEXUS_VideoInput source, const NEXUS_VideoInput_P_LinkData *data, const NEXUS_VideoInput_P_Iface *iface)
958{
959    NEXUS_VideoInput_P_Link *link = NULL;
960    NEXUS_Error rc = NEXUS_SUCCESS;
961
962    BDBG_ASSERT(source && source->source);
963    BDBG_ASSERT(data);
964    BDBG_ASSERT(iface);
965
966    BDBG_MSG((">NEXUS_VideoInput_P_CreateLink_Init id %d, heap %p", data->sourceId, data->heap));
967
968    link = BKNI_Malloc(sizeof(*link));
969    if(!link) {
970        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
971        goto err_alloc;
972    }
973    BKNI_Memset(link, 0, sizeof(*link));
974    BDBG_OBJECT_SET(link, NEXUS_VideoInput_P_Link);
975    NEXUS_VideoInput_P_GetDefaultSettings(&link->cfg);
976    link->id = data->sourceId;
977    link->heap = data->heap;
978
979    link->input = source;
980    link->iface = *iface;
981    link->input_info.type = source->type;
982    link->input_info.source = source->source;
983    link->sourcePendingCallback = NEXUS_IsrCallback_Create(source, NULL);
984    link->sourceChangedCallback = NEXUS_IsrCallback_Create(source, NULL);
985    BKNI_CreateEvent(&link->sourceChangedEvent);
986    link->sourceChangedEventHandler = NEXUS_RegisterEvent(link->sourceChangedEvent, NEXUS_VideoInput_P_SourceChanged, source);
987    link->resumeMode = NEXUS_VideoInputResumeMode_eAuto;
988
989    /* Only create this if we're doing dynamic RTS */
990    if ( g_NEXUS_DisplayModule_State.moduleSettings.handleDynamicRts )
991    {
992        BKNI_CreateEvent(&link->sourcePendingEvent);
993        link->sourcePendingEventHandler = NEXUS_RegisterEvent(link->sourcePendingEvent, NEXUS_VideoInput_P_SourcePending, source);
994        BKNI_CreateEvent(&link->checkFormatChangedEvent);
995        link->checkFormatChangedEventHandler = NEXUS_RegisterEvent(link->checkFormatChangedEvent, NEXUS_VideoInput_P_CheckFormatChanged, source);
996    }
997
998    /* Only default a CC buffer. All others require app to set buffer size. */
999    link->vbiSettings.closedCaptionBufferSize = 30;
1000    /* VBI decode defaults copied from bvbi.c */
1001    link->vbiSettings.gemStar.baseLineTop = 10;
1002    link->vbiSettings.gemStar.lineMaskTop = 0x1f;
1003    link->vbiSettings.gemStar.baseLineBottom = 273;
1004    link->vbiSettings.gemStar.lineMaskBottom = 0x1f;
1005    link->vbiSettings.wss.vline576i = 23;
1006    link->vbiSettings.cc.ccLineTop      = 21;
1007    link->vbiSettings.cc.ccLineBottom   = 284;
1008    /* no default buffer for teletext */
1009    link->vbi.wss.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1010    link->vbi.wss.data = 0xffff; /* no data */
1011    link->vbi.cgms.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1012    link->vbi.vps.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1013    link->vbi.cc.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1014    link->vbi.tt.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1015    link->vbi.gs.isrCallback = NEXUS_IsrCallback_Create(source, NULL);
1016
1017    source->ref_cnt++;
1018    BLST_S_DICT_ADD(&pVideo->inputs, link, NEXUS_VideoInput_P_Link, input, link, err_duplicate);
1019    BDBG_MSG(("<NEXUS_VideoInput_P_CreateLink_Init %p", link));
1020
1021    return link;
1022
1023err_duplicate:
1024    NEXUS_VideoInput_P_DestroyLink_Uninit(link);
1025err_alloc:
1026    return NULL;
1027}
1028
1029static NEXUS_Error
1030NEXUS_VideoInput_P_Create_VdcSource(NEXUS_VideoInput source, NEXUS_VideoInput_P_Link *link, const NEXUS_VideoInput_P_LinkData *data)
1031{
1032    NEXUS_Error rc = NEXUS_SUCCESS;
1033#ifndef B_HAS_LEGACY_VDC
1034    BVDC_Source_Settings sourceCfg;
1035#endif
1036
1037    BDBG_ASSERT(source && source->source);
1038    BDBG_ASSERT(link);
1039    BDBG_ASSERT(data);
1040
1041    BDBG_MSG((">NEXUS_VideoInput_P_Create_VdcSource input %p, link %p, heap %p", source, link, data->heap));
1042    if (data->sourceVdc) {
1043        link->sourceVdc = data->sourceVdc;
1044        link->copiedSourceVdc = true;
1045    }
1046    else {
1047#ifndef B_HAS_LEGACY_VDC
1048        rc = BVDC_Source_GetDefaultSettings(data->sourceId, &sourceCfg);
1049        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_source;}
1050
1051        if (data->heap && data->heap != pVideo->heap) {
1052            sourceCfg.hHeap = NEXUS_Display_P_CreateHeap(data->heap);
1053            if (!sourceCfg.hHeap) { rc = BERR_TRACE(rc); goto err_source;}
1054
1055            link->vdcHeap = sourceCfg.hHeap;
1056        }
1057
1058        rc = BVDC_Source_Create(pVideo->vdc, &link->sourceVdc, data->sourceId, &sourceCfg);
1059        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_source;}
1060#else
1061        rc = BVDC_Source_Create(pVideo->vdc, &link->sourceVdc, data->sourceId);
1062        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_source;}
1063#endif
1064
1065        if(pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto) {rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1066        rc = BVDC_ApplyChanges(pVideo->vdc);
1067        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_apply_changes;}
1068
1069        rc = BVDC_Source_InstallCallback(link->sourceVdc, NEXUS_VideoInput_P_SourceCallback_isr, link, 0);
1070        if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_apply_changes;}
1071       
1072    }
1073
1074    rc  = NEXUS_VideoInput_SetResumeMode(source, link->resumeMode);
1075    if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_apply_changes;}
1076   
1077    BDBG_MSG(("<NEXUS_VideoInput_P_Create_VdcSource %s %p:%d", link->copiedSourceVdc?"copied":"created", link->sourceVdc, data->sourceId));
1078
1079    return NEXUS_SUCCESS;
1080
1081err_apply_changes:
1082    if (!link->copiedSourceVdc) {
1083        rc = BVDC_AbortChanges(pVideo->vdc);
1084        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1085        rc = BVDC_Source_Destroy(link->sourceVdc);
1086        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1087    }
1088err_source:
1089    return rc;
1090}
1091
1092void
1093NEXUS_VideoInput_P_DestroyLink(NEXUS_VideoInput_P_Link *link)
1094{
1095    NEXUS_VideoInput_P_Destroy_VdcSource(link);
1096
1097    BKNI_Memset(&link->vbiSettings, 0, sizeof(link->vbiSettings));
1098    NEXUS_VideoInput_P_SetVbiState(link->input);
1099
1100    NEXUS_VideoInput_P_DestroyLink_Uninit(link);
1101
1102    return;
1103}
1104
1105static void
1106NEXUS_VideoInput_P_DestroyLink_Uninit(NEXUS_VideoInput_P_Link *link)
1107{
1108    BDBG_MSG((">NEXUS_VideoInput_P_DestroyLink_Uninit %p", link));
1109    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1110
1111    NEXUS_IsrCallback_Destroy(link->vbi.gs.isrCallback);
1112    NEXUS_IsrCallback_Destroy(link->vbi.tt.isrCallback);
1113    NEXUS_IsrCallback_Destroy(link->vbi.cc.isrCallback);
1114    NEXUS_IsrCallback_Destroy(link->vbi.wss.isrCallback);
1115    NEXUS_IsrCallback_Destroy(link->vbi.cgms.isrCallback);
1116    NEXUS_IsrCallback_Destroy(link->vbi.vps.isrCallback);
1117    if(link->vbi.cc.data) {
1118        BKNI_Free(link->vbi.cc.data);
1119    }
1120    if(link->vbi.tt.data) {
1121        BKNI_Free(link->vbi.tt.data);
1122    }
1123
1124    NEXUS_IsrCallback_Destroy(link->sourcePendingCallback);
1125    NEXUS_IsrCallback_Destroy(link->sourceChangedCallback);
1126    NEXUS_UnregisterEvent(link->sourceChangedEventHandler);
1127    BKNI_DestroyEvent(link->sourceChangedEvent);
1128    if ( link->checkFormatChangedEventHandler )
1129    {
1130        NEXUS_UnregisterEvent(link->checkFormatChangedEventHandler);
1131        BKNI_DestroyEvent(link->checkFormatChangedEvent);
1132    }
1133    if ( link->sourcePendingEventHandler )
1134    {
1135        NEXUS_UnregisterEvent(link->sourcePendingEventHandler);
1136        BKNI_DestroyEvent(link->sourcePendingEvent);
1137    }
1138
1139    link->input->ref_cnt--;
1140    BLST_S_DICT_REMOVE(&pVideo->inputs, link, link->input, NEXUS_VideoInput_P_Link, input, link);
1141
1142    BDBG_OBJECT_DESTROY(link, NEXUS_VideoInput_P_Link);
1143    BKNI_Free(link);
1144
1145    BDBG_MSG(("<NEXUS_VideoInput_P_DestroyLink_Uninit"));
1146
1147    return;
1148}
1149
1150static void
1151NEXUS_VideoInput_P_Destroy_VdcSource(NEXUS_VideoInput_P_Link *link)
1152{
1153    BERR_Code rc;
1154
1155    BDBG_MSG((">NEXUS_VideoInput_P_Destroy_VdcSource input %p, link %p", link->input, link));
1156    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1157
1158    if (!link->copiedSourceVdc && link->sourceVdc)
1159    {
1160        (void)BVDC_Source_InstallCallback(link->sourceVdc, NULL, NULL, 0);
1161
1162        rc = BVDC_Source_Destroy(link->sourceVdc);
1163        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1164
1165        if(pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto) {rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1166
1167        rc = BVDC_ApplyChanges(pVideo->vdc);
1168        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1169
1170        link->sourceVdc = NULL;
1171
1172#ifndef B_HAS_LEGACY_VDC
1173        if (link->vdcHeap) {
1174            NEXUS_Display_P_DestroyHeap(link->vdcHeap);
1175        }
1176#endif
1177   }
1178
1179    BDBG_MSG(("<NEXUS_VideoInput_P_Destroy_VdcSource"));
1180
1181    return;
1182}
1183
1184void
1185NEXUS_VideoInput_GetSettings(NEXUS_VideoInput input, NEXUS_VideoInputSettings *pSettings)
1186{
1187    NEXUS_VideoInput_P_Link *link;
1188
1189    BDBG_ASSERT(pSettings);
1190    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1191    link = NEXUS_VideoInput_P_Get(input);
1192    if(!link) {
1193        NEXUS_VideoInput_P_GetDefaultSettings(pSettings);
1194        goto done;
1195    }
1196    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1197    *pSettings  = link->cfg;
1198done:
1199    return;
1200}
1201
1202/*
1203Summary:
1204Returns bits 'e'..'b' from word 'w',
1205
1206Example:
1207    B_GET_BITS(0xDE,7,4)==0x0D
1208    B_GET_BITS(0xDE,3,0)=0x0E
1209*/
1210#define B_GET_BITS(w,e,b)  (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
1211
1212
1213NEXUS_Error
1214NEXUS_VideoInput_SetSettings( NEXUS_VideoInput input, const NEXUS_VideoInputSettings *pSettings)
1215{
1216    BERR_Code rc = NEXUS_SUCCESS;
1217    NEXUS_VideoInput_P_Link *link;
1218
1219    BDBG_ASSERT(pSettings);
1220    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1221    link = NEXUS_VideoInput_P_Get(input);
1222    if(!link) { rc=BERR_TRACE(BERR_NOT_SUPPORTED); goto err_link;}
1223    if (!link->sourceVdc) {link->isDeferCfg = true; link->cfg = *pSettings; return NEXUS_SUCCESS;}
1224
1225    if(pSettings->muteColor != link->cfg.muteColor) {
1226        rc = BVDC_Source_SetVideoMuteColor(link->sourceVdc, B_GET_BITS(pSettings->muteColor, 23, 16),
1227                                           B_GET_BITS(pSettings->muteColor, 15, 8), B_GET_BITS(pSettings->muteColor, 7, 0));
1228        if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_settings;}
1229    }
1230    if(pSettings->mute != link->cfg.mute || pSettings->repeat != link->cfg.repeat) {
1231        rc = BVDC_Source_SetMuteMode(link->sourceVdc,
1232            pSettings->mute ? BVDC_MuteMode_eConst :
1233            pSettings->repeat ? BVDC_MuteMode_eRepeat :
1234            BVDC_MuteMode_eDisable);
1235        if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_settings;}
1236    }
1237    if (pSettings->video3DSettings.overrideOrientation != link->cfg.video3DSettings.overrideOrientation || 
1238        pSettings->video3DSettings.orientation != link->cfg.video3DSettings.orientation) 
1239    {
1240        rc = BVDC_Source_SetOrientation(link->sourceVdc, pSettings->video3DSettings.overrideOrientation, NEXUS_P_VideoOrientation_ToMagnum(pSettings->video3DSettings.orientation));
1241        if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_settings;}
1242    }
1243
1244    rc = NEXUS_Display_P_ApplyChanges();
1245    if (rc) return BERR_TRACE(rc);
1246
1247    NEXUS_IsrCallback_Set(link->sourceChangedCallback, &pSettings->sourceChanged);
1248    NEXUS_IsrCallback_Set(link->sourcePendingCallback, &pSettings->sourcePending);
1249
1250    link->cfg = *pSettings;
1251    return rc;
1252
1253err_settings:
1254    {
1255        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc);
1256        if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1257    }
1258err_link:
1259    return rc;
1260}
1261
1262NEXUS_Error
1263NEXUS_VideoInput_GetStatus(NEXUS_VideoInput input,NEXUS_VideoInputStatus *pStatus)
1264{
1265    NEXUS_VideoInput_P_Link *link;
1266
1267    BDBG_ASSERT(pStatus);
1268    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1269    link = NEXUS_VideoInput_P_Get(input);
1270
1271    BKNI_Memset(pStatus, 0, sizeof(*pStatus));
1272
1273    if(!link) { goto done;}
1274
1275    switch(link->id) {
1276    case BAVC_SourceId_eMpeg0:
1277    case BAVC_SourceId_eMpeg1:
1278        if (link->info_valid) {
1279            BAVC_FrameRateCode frameRate;
1280            BFMT_AspectRatio aspectRatio;
1281            bool bStreamProgressive;
1282
1283            /* the assignment of the BAVC_MFD_Picture structure is not atomic. therefore, protect. */
1284            BKNI_EnterCriticalSection();
1285            frameRate = link->info.mfd.eFrameRateCode;
1286            aspectRatio = link->info.mfd.eAspectRatio;
1287            bStreamProgressive = link->info.mfd.bStreamProgressive;
1288            pStatus->width = link->info.mfd.ulSourceHorizontalSize;
1289            pStatus->height = link->info.mfd.ulSourceVerticalSize;
1290            pStatus->videoPresent = !link->info.mfd.bMute;
1291            BKNI_LeaveCriticalSection();
1292
1293            pStatus->frameRate = NEXUS_P_FrameRate_FromMagnum(frameRate);
1294            pStatus->format = NEXUS_P_VideoFormat_FromInfo(pStatus->height, pStatus->frameRate, !bStreamProgressive);
1295            pStatus->aspectRatio = NEXUS_P_AspectRatio_FromMagnum(aspectRatio);
1296            pStatus->refreshRate = NEXUS_P_RefreshRate_FromFrameRate(pStatus->frameRate);
1297        }
1298        break;
1299
1300    default:
1301        /* this status was already captured in NEXUS_VideoInput_P_SourceCallback_isr */
1302        *pStatus = link->status;
1303        break;
1304    }
1305
1306done:
1307    return 0;
1308}
1309
1310#if NEXUS_NUM_VIDEO_DECODERS
1311static void
1312NEXUS_VideoInput_P_DecoderDataReady_isr(void *input_, const BAVC_MFD_Picture *pPicture)
1313{
1314    NEXUS_VideoInput_P_Link *link = input_;
1315    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1316    BDBG_ASSERT(pPicture);
1317    link->info.mfd = *pPicture;
1318    link->info_valid = true;
1319
1320#if NEXUS_NUM_MOSAIC_DECODES
1321    if (link->mosaic.backendMosaic) {
1322        unsigned i;
1323        for (i=0;i<NEXUS_NUM_DISPLAYS;i++) {
1324            NEXUS_VideoWindowHandle window = link->mosaic.parentWindow[i];
1325        if (window) {
1326            /* this takes a single picture and cuts it up into a linked list of mosaic pictures */
1327            pPicture = NEXUS_VideoWindow_P_CutBackendMosaic_isr(window, pPicture);
1328                BDBG_ASSERT(pPicture); /* if it can't cut, NEXUS_VideoWindow_P_CutBackendMosaic_isr should have returned the original pPicture */
1329
1330                /* the first window gets to cut it. the other has to follow. */
1331                break;
1332            }
1333        }
1334    }
1335#endif
1336
1337    BVDC_Source_MpegDataReady_isr(link->sourceVdc, 0 /* unused */, (void *)pPicture);
1338    return;
1339}
1340
1341#if NEXUS_HAS_VIDEO_ENCODER
1342static void
1343NEXUS_VideoInput_P_UserDataCallback_isr(void *input_, const BAVC_USERDATA_info *userDataInfo)
1344{
1345    NEXUS_VideoInput_P_Link *link = input_;
1346   
1347    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1348
1349    if( link->hXud )
1350    {
1351        BXUDlib_UserDataHandler_isr(link->hXud, userDataInfo);
1352    }
1353}
1354#endif
1355
1356static BERR_Code
1357NEXUS_VideoInput_P_ConnectVideoDecoder(NEXUS_VideoInput_P_Link *link)
1358{
1359    BERR_Code rc;
1360    NEXUS_VideoDecoderDisplayConnection decoderConnect;
1361
1362    BDBG_ASSERT(link->input && link->input->source);
1363
1364    if (!pVideo->modules.videoDecoder) {
1365        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1366    }
1367
1368#if NEXUS_NUM_MOSAIC_DECODES
1369    if (link->mosaic.backendMosaic) {
1370        /* the parent has already connected to the decoder */
1371        return 0;
1372    }
1373#endif
1374
1375    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1376    NEXUS_VideoDecoder_GetDisplayConnection_priv(link->input->source, &decoderConnect);
1377    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1378
1379#if NEXUS_NUM_MOSAIC_DECODES
1380    link->mosaic.index = decoderConnect.mosaicIndex;
1381#endif
1382    rc = BVDC_Source_SetPsfMode(link->sourceVdc, decoderConnect.psfMode);
1383    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_setpsf;}
1384
1385    rc = BVDC_Source_GetInterruptName(link->sourceVdc, BAVC_Polarity_eTopField, &decoderConnect.top.intId);
1386    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1387    rc = BVDC_Source_GetInterruptName(link->sourceVdc, BAVC_Polarity_eBotField, &decoderConnect.bottom.intId);
1388    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1389    rc = BVDC_Source_GetInterruptName(link->sourceVdc, BAVC_Polarity_eFrame, &decoderConnect.frame.intId);
1390    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_intr_name;}
1391    decoderConnect.callbackContext = link;
1392    decoderConnect.dataReadyCallback_isr = NEXUS_VideoInput_P_DecoderDataReady_isr;
1393   
1394    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1395    rc = NEXUS_VideoDecoder_SetDisplayConnection_priv(link->input->source, &decoderConnect);
1396    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1397    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_connect;}
1398
1399    return rc;
1400
1401err_connect:
1402err_intr_name:
1403err_setpsf:
1404    return rc;
1405}
1406
1407static void
1408NEXUS_VideoInput_P_DisconnectVideoDecoder(NEXUS_VideoInput_P_Link *link)
1409{
1410    NEXUS_Error rc;
1411    NEXUS_VideoDecoderDisplayConnection decoderConnect;
1412
1413    if (!pVideo->modules.videoDecoder) {
1414        BERR_TRACE(NEXUS_NOT_SUPPORTED);
1415        return;
1416    }
1417
1418#if NEXUS_NUM_MOSAIC_DECODES
1419    if (link->mosaic.backendMosaic) {
1420        /* the parent is the only one connected to the decoder */
1421        return;
1422    }
1423#endif
1424
1425    BDBG_ASSERT(link->input && link->input->source);
1426    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1427    NEXUS_VideoDecoder_GetDisplayConnection_priv(link->input->source, &decoderConnect);
1428    decoderConnect.dataReadyCallback_isr = NULL;
1429    decoderConnect.userDataCallback_isr = NULL;
1430    rc = NEXUS_VideoDecoder_SetDisplayConnection_priv(link->input->source, &decoderConnect);
1431    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1432    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); }
1433    return;
1434}
1435
1436NEXUS_VideoInput_P_Link *
1437NEXUS_VideoInput_P_OpenDecoder(NEXUS_VideoInput input, NEXUS_VideoInput_P_Link *mosaicParent)
1438{
1439    BAVC_SourceId sourceId;
1440    NEXUS_VideoInput_P_Iface iface;
1441    NEXUS_VideoInput_P_LinkData data;
1442    NEXUS_HeapHandle videoDecoderHeap;
1443    NEXUS_VideoInput_P_Link *link;
1444
1445    if (!pVideo->modules.videoDecoder) {
1446        BERR_TRACE(NEXUS_NOT_SUPPORTED);
1447        return NULL;
1448    }
1449
1450    BDBG_ASSERT(input->source);
1451    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1452    NEXUS_VideoDecoder_GetSourceId_priv(input->source, &sourceId);
1453    NEXUS_VideoDecoder_GetHeap_priv(input->source, &videoDecoderHeap);
1454    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1455
1456    iface.connect = NEXUS_VideoInput_P_ConnectVideoDecoder;
1457    iface.disconnect = NEXUS_VideoInput_P_DisconnectVideoDecoder;
1458    NEXUS_VideoInput_P_LinkData_Init(&data, sourceId);
1459    data.heap = videoDecoderHeap;
1460#if NEXUS_NUM_MOSAIC_DECODES
1461    if (mosaicParent) {
1462        data.sourceVdc = mosaicParent->sourceVdc;
1463    }
1464#else
1465    BSTD_UNUSED(mosaicParent);
1466#endif
1467
1468    link = NEXUS_VideoInput_P_CreateLink(input, &data, &iface);
1469
1470#if NEXUS_NUM_MOSAIC_DECODES
1471    if (link && mosaicParent) {
1472        link->mosaic.backendMosaic = mosaicParent->mosaic.backendMosaic;
1473    }
1474#endif
1475
1476    return link;
1477}
1478#endif
1479
1480BERR_Code
1481NEXUS_VideoInput_P_Connect(NEXUS_VideoInput input, NEXUS_VideoWindowHandle window)
1482{
1483    BERR_Code rc;
1484    NEXUS_VideoInput_P_Link *link;
1485   
1486    /* this function is called on the first connection back to the VideoInput source */
1487
1488    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1489    BSTD_UNUSED(window); /* TODO: window should be removed from this function. a VideoInputLink could conceivably
1490        connect back to its source without a window. */
1491   
1492    /* this function is called on the first connection back to the VideoInput source */
1493
1494    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1495    BSTD_UNUSED(window); /* TODO: window should be removed from this function. a VideoInputLink could conceivably
1496        connect back to its source without a window. */
1497   
1498    link = NEXUS_VideoInput_P_Get(input);
1499    if(!link) {rc=BERR_TRACE(BERR_NOT_SUPPORTED); goto err_connect;}
1500
1501    link->info_valid = false;
1502    input->destination = link;
1503
1504    rc = link->iface.connect(link);
1505    if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc); goto err_connect;}
1506
1507    return rc;
1508
1509err_connect:
1510    /* NEXUS_VideoInput_Shutdown will still be required, but input->destination must be cleared because
1511    there is no connection to a window */
1512    input->destination = NULL;
1513    return rc;
1514}
1515
1516void
1517NEXUS_VideoInput_P_Disconnect(NEXUS_VideoInput input) {
1518    NEXUS_VideoInput_P_Link *link;
1519    BERR_Code rc;
1520#ifndef B_HAS_LEGACY_VDC
1521    BVDC_Dnr_Settings dnrSettings;
1522#endif
1523
1524    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1525    link = NEXUS_VideoInput_P_Get(input);
1526    if(!link) {rc=BERR_TRACE(BERR_NOT_SUPPORTED); goto done;}
1527    link->iface.disconnect(link);
1528
1529#ifndef B_HAS_LEGACY_VDC
1530    /* DNR is window-based in Nexus, source-based in VDC. So, we disable DNR when the VideoInput is disconnected from its last window. */
1531    rc = BVDC_Source_GetDnrConfiguration(link->sourceVdc, &dnrSettings);
1532    if (!rc) {
1533        dnrSettings.eBnrMode = BVDC_FilterMode_eDisable;
1534        dnrSettings.eDcrMode = BVDC_FilterMode_eDisable;
1535        dnrSettings.eMnrMode = BVDC_FilterMode_eDisable;
1536        rc = BVDC_Source_SetDnrConfiguration(link->sourceVdc, &dnrSettings);
1537        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); }
1538    }
1539#endif
1540
1541    link->info_valid = false;
1542#if NEXUS_HAS_VIDEO_ENCODER
1543    link->hXud = NULL;
1544#endif
1545    input->destination = NULL;
1546
1547done:
1548    return;
1549}
1550
1551NEXUS_VideoInput_P_Link *
1552NEXUS_VideoInput_P_Get(NEXUS_VideoInput input)
1553{
1554    NEXUS_Error rc;
1555    NEXUS_VideoInput_P_Link *inputLink;
1556
1557    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1558
1559    inputLink = input->destination;
1560    if(!inputLink) {
1561        BLST_S_DICT_FIND(&pVideo->inputs, inputLink, input, input, link);
1562        /* If we find one, this is a disconnected VideoInput. We will allow SetSettings to succeed,
1563        but settings will not be applied until connected. */
1564    }
1565
1566    if(!inputLink) {
1567        BDBG_ASSERT(input->destination==NULL);
1568        switch(input->type) {
1569#if NEXUS_HAS_VIDEO_DECODER
1570        case NEXUS_VideoInputType_eDecoder:
1571            inputLink = NEXUS_VideoInput_P_OpenDecoder(input, NULL);
1572            break;
1573#endif
1574        case NEXUS_VideoInputType_eImage:
1575            inputLink = NEXUS_VideoImageInput_P_OpenInput(input);
1576            break;
1577#if NEXUS_NUM_ANALOG_VIDEO_DECODERS
1578        case NEXUS_VideoInputType_eAnalogVideoDecoder:
1579            inputLink = NEXUS_VideoInput_P_OpenAnalogVideoDecoder(input);
1580            break;
1581#endif
1582#if NEXUS_NUM_HDMI_INPUTS
1583        case NEXUS_VideoInputType_eHdmi:
1584            inputLink = NEXUS_VideoInput_P_OpenHdmi(input);
1585            break;
1586#endif
1587#if NEXUS_NUM_656_INPUTS
1588        case NEXUS_VideoInputType_eCcir656:
1589            inputLink = NEXUS_VideoInput_P_OpenCcir656(input);
1590            break;
1591#endif
1592#if NEXUS_NUM_HDDVI_INPUTS
1593        case NEXUS_VideoInputType_eHdDvi:
1594            inputLink = NEXUS_VideoInput_P_OpenHdDviInput(input);
1595            break;
1596#endif
1597
1598        case NEXUS_VideoInputType_ePc:
1599        case NEXUS_VideoInputType_eComposite:
1600        case NEXUS_VideoInputType_eSvideo:
1601        case NEXUS_VideoInputType_eComponent:
1602        case NEXUS_VideoInputType_eIfd:
1603            /* These input types are used to connect to AnalogVideoDecoder only. This failure will
1604            occur with NEXUS_VideoInput_Get/SetSettings, NEXUS_VideoInput_GetStatus or NEXUS_VideoWindow_Add/RemoveInput. */
1605            BDBG_WRN(("This NEXUS_VideoInput type (%d) does not support this operation", input->type));
1606            rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);
1607            inputLink = NULL;
1608            break;
1609        default:
1610            BDBG_WRN(("unknown VideoInput type: %d", input->type));
1611            rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);
1612            inputLink = NULL;
1613            break;
1614        }
1615    }
1616
1617    if(inputLink) {
1618        BDBG_OBJECT_ASSERT(inputLink, NEXUS_VideoInput_P_Link);
1619        BDBG_ASSERT(inputLink->input == input);
1620        BDBG_ASSERT(input->destination == NULL || input->destination == inputLink);
1621        BDBG_ASSERT(input->type == inputLink->input_info.type && input->source == inputLink->input_info.source);
1622    }
1623    return inputLink;
1624}
1625
1626void
1627NEXUS_VideoInput_Shutdown(NEXUS_VideoInput input)
1628{
1629    NEXUS_VideoInput_P_Link *inputLink;
1630    NEXUS_Error rc;
1631    unsigned int i;
1632
1633    BSTD_UNUSED(rc);
1634    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1635
1636    if (input->destination) {
1637        /* check if this input is connected to a window and auto-remove. */
1638        while (1) {
1639            NEXUS_VideoWindowHandle window;
1640            unsigned num;
1641            rc = NEXUS_Display_P_GetWindows_priv(input, &window, 1, &num);
1642            if (rc) {rc = BERR_TRACE(rc); goto err_connected;}
1643
1644            if (!num) break;
1645
1646            rc = NEXUS_VideoWindow_RemoveInput(window, input);
1647            if (rc) {rc = BERR_TRACE(rc); goto err_connected;}
1648        }
1649
1650        /* if we're still connected, then this video input must be connected to another module. */
1651        if (input->destination) {
1652            BDBG_ERR(("Fatal application error. NEXUS_VideoInput_Shutdown %p called on connected input. You must call NEXUS_VideoWindow_RemoveInput before shutting down, otherwise system is likely to be in a corrupted state and will crash.", input));
1653            rc = BERR_TRACE(NEXUS_INVALID_PARAMETER); /* input is still connected */
1654#if 0
1655            /* Uncomment this BKNI_Fail to get a stack trace into your application. This is a serious app bug and should be corrected. */
1656            BKNI_Fail();
1657#endif
1658            goto err_connected;
1659        }
1660    }
1661
1662    for (i=0;i<NEXUS_NUM_DISPLAYS;i++) {
1663        if (pVideo->displays[i]) {
1664            NEXUS_DisplayVbiSettings dispvbiSettings;
1665            NEXUS_Display_GetVbiSettings(pVideo->displays[i], &dispvbiSettings);
1666            if (dispvbiSettings.vbiSource == input) {
1667                dispvbiSettings.vbiSource = NULL;
1668                NEXUS_Display_SetVbiSettings(pVideo->displays[i], &dispvbiSettings);
1669            }
1670        }
1671    }
1672
1673    /* this is like calling NEXUS_VideoInput_P_Get, but without the possible CreateLink */
1674    inputLink = input->destination;
1675    if (!inputLink) {
1676        BLST_S_DICT_FIND(&pVideo->inputs, inputLink, input, input, link);
1677    }
1678
1679    if (inputLink) {
1680        BDBG_OBJECT_ASSERT(inputLink, NEXUS_VideoInput_P_Link);
1681        BDBG_ASSERT(inputLink->input == input);
1682        BDBG_ASSERT(input->type == inputLink->input_info.type && input->source == inputLink->input_info.source);
1683        BDBG_ASSERT(input->ref_cnt > 0);
1684
1685        /* this is the inverse of the OpenXxx calls in NEXUS_VideoInput_P_Get */
1686        switch (inputLink->input->type) {
1687#if NEXUS_NUM_ANALOG_VIDEO_DECODERS
1688        case NEXUS_VideoInputType_eAnalogVideoDecoder:
1689            /* CloseAnalogVideoDecoder must call NEXUS_VideoInput_P_DestroyLink */
1690            NEXUS_VideoInput_P_CloseAnalogVideoDecoder(inputLink);
1691            break;
1692#endif
1693        default:
1694            NEXUS_VideoInput_P_DestroyLink(inputLink);
1695            break;
1696        }
1697    }
1698err_connected:
1699    return;
1700}
1701
1702void NEXUS_VideoInput_GetColorMatrix(NEXUS_VideoInput input, NEXUS_ColorMatrix *pColorMatrix)
1703{
1704#ifndef B_HAS_LEGACY_VDC
1705    NEXUS_VideoInput_P_Link *link;
1706
1707    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1708    link = NEXUS_VideoInput_P_Get(input);
1709    if (link && link->sourceVdc) {
1710        if (link->bColorMatrixSet) {
1711            /* avoid VDC race conditions and return whatever was last set by the user. */
1712            *pColorMatrix = link->colorMatrix;
1713            return;
1714        }
1715        else {
1716            bool bOverride;
1717            NEXUS_Error rc;
1718
1719            /* for video inputs, the BVDC_Source exists right away, so we can ask VDC for its default. */
1720            rc = BVDC_Source_GetColorMatrix(link->sourceVdc, &bOverride, pColorMatrix->coeffMatrix, &pColorMatrix->shift);
1721            if (!rc) return;
1722            /* else fall through */
1723        }
1724    }
1725#else
1726    BSTD_UNUSED(input);
1727#endif
1728
1729    BKNI_Memset(pColorMatrix, 0, sizeof(*pColorMatrix));
1730
1731    return;
1732}
1733
1734NEXUS_Error NEXUS_VideoInput_SetColorMatrix(NEXUS_VideoInput input, const NEXUS_ColorMatrix *pColorMatrix)
1735{
1736#ifndef B_HAS_LEGACY_VDC
1737    NEXUS_VideoInput_P_Link *link;
1738    BERR_Code rc;
1739
1740    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1741    link = NEXUS_VideoInput_P_Get(input);
1742    if (!link) return BERR_TRACE(NEXUS_UNKNOWN);
1743    if (!link->sourceVdc) {link->isDeferColorMatrix = true; link->colorMatrix = *pColorMatrix; return NEXUS_SUCCESS;}
1744
1745    if (pColorMatrix) {
1746        link->colorMatrix = *pColorMatrix;
1747    }
1748    link->bColorMatrixSet = pColorMatrix != NULL;
1749
1750    rc = BVDC_Source_SetColorMatrix(link->sourceVdc, link->bColorMatrixSet, link->colorMatrix.coeffMatrix, link->colorMatrix.shift);
1751    if (rc) return BERR_TRACE(rc);
1752
1753    rc = NEXUS_Display_P_ApplyChanges();
1754    if (rc) return BERR_TRACE(rc);
1755#else
1756    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1757    BSTD_UNUSED(pColorMatrix);
1758#endif
1759
1760    return 0;
1761}
1762
1763void NEXUS_VideoInput_GetSyncSettings_priv(NEXUS_VideoInput videoInput, NEXUS_VideoInputSyncSettings *pSyncSettings)
1764{
1765    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1766    NEXUS_ASSERT_MODULE();
1767
1768    switch (videoInput->type) {
1769#if NEXUS_HAS_VIDEO_DECODER
1770    case NEXUS_VideoInputType_eDecoder:
1771        if (!pVideo->modules.videoDecoder) {
1772            BERR_TRACE(NEXUS_NOT_SUPPORTED);
1773            return;
1774        }
1775        NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1776        NEXUS_VideoDecoder_GetSyncSettings_priv((NEXUS_VideoDecoderHandle)videoInput->source, pSyncSettings);
1777        NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1778        break;
1779#else
1780        BSTD_UNUSED(pSyncSettings);
1781#endif
1782    default:
1783        BDBG_WRN(("SyncChannel not supported for this video input"));
1784        break;
1785    }
1786}
1787
1788NEXUS_Error NEXUS_VideoInput_SetSyncSettings_priv(NEXUS_VideoInput videoInput, const NEXUS_VideoInputSyncSettings *pSyncSettings)
1789{
1790    NEXUS_Error rc = 0;
1791
1792    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1793    NEXUS_ASSERT_MODULE();
1794
1795    switch (videoInput->type) {
1796#if NEXUS_HAS_VIDEO_DECODER
1797    case NEXUS_VideoInputType_eDecoder:
1798        if (!pVideo->modules.videoDecoder) {
1799            return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1800        }
1801        NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1802        rc = NEXUS_VideoDecoder_SetSyncSettings_priv((NEXUS_VideoDecoderHandle)videoInput->source, pSyncSettings);
1803        NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1804        break;
1805#else
1806        BSTD_UNUSED(pSyncSettings);
1807#endif
1808    default:
1809        BDBG_WRN(("SyncChannel not supported for this video input"));
1810        break;
1811    }
1812    return rc;
1813}
1814
1815NEXUS_Error NEXUS_VideoInput_GetSyncStatus_isr(NEXUS_VideoInput videoInput, NEXUS_VideoInputSyncStatus *pSyncStatus)
1816{
1817    NEXUS_Error rc = 0;
1818
1819    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1820
1821    switch (videoInput->type) {
1822#if NEXUS_HAS_VIDEO_DECODER
1823    case NEXUS_VideoInputType_eDecoder:
1824        rc = NEXUS_VideoDecoder_GetSyncStatus_isr((NEXUS_VideoDecoderHandle)videoInput->source, pSyncStatus);
1825        break;
1826#else
1827        BSTD_UNUSED(pSyncStatus);
1828#endif
1829    default:
1830        BDBG_WRN(("SyncChannel not supported for this video input"));
1831        break;
1832    }
1833    return rc;
1834}
1835
1836NEXUS_Error NEXUS_Display_P_GetWindows_priv(NEXUS_VideoInput videoInput, NEXUS_VideoWindowHandle *pWindowArray, unsigned arraySize, unsigned *numFilled)
1837{
1838    unsigned i,j;
1839
1840    NEXUS_ASSERT_MODULE();
1841    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1842
1843    *numFilled = 0;
1844    for (i=0;i<NEXUS_NUM_DISPLAYS;i++) {
1845        for (j=0;j<NEXUS_NUM_VIDEO_WINDOWS;j++) {
1846            if (*numFilled == arraySize) return 0;
1847            if (pVideo->displays[i] && pVideo->displays[i]->windows[j].input == videoInput) {
1848                pWindowArray[(*numFilled)++] = &pVideo->displays[i]->windows[j];
1849            }
1850        }
1851    }
1852    return 0;
1853}
1854
1855void
1856NEXUS_Display_P_VideoInputDisplayUpdate(NEXUS_VideoInput videoInput, NEXUS_VideoWindowHandle window, const NEXUS_DisplaySettings *pSettings)
1857{
1858#if NEXUS_NUM_VIDEO_DECODERS
1859    NEXUS_VideoDecoder_DisplayInformation displayInformation;
1860#endif
1861#if !B_HAS_LEGACY_VDC && BCHP_CHIP != 7403
1862    BVDC_Window_Status vdcWindowStatus;
1863#endif
1864#if NEXUS_NUM_MOSAIC_DECODES
1865    NEXUS_VideoWindowHandle mosaicChild;
1866#endif
1867
1868    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1869    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1870    BDBG_ASSERT(pSettings);
1871
1872#if NEXUS_NUM_MOSAIC_DECODES
1873    /* pass along to each mosaic child */
1874    for (mosaicChild = BLST_S_FIRST(&window->mosaic.children); mosaicChild; mosaicChild = BLST_S_NEXT(mosaicChild, mosaic.link)) {
1875        if (mosaicChild->input) {
1876            NEXUS_Display_P_VideoInputDisplayUpdate(mosaicChild->input, mosaicChild, pSettings);
1877        }
1878    }
1879#endif
1880
1881    switch (videoInput->type) {
1882#if NEXUS_HAS_VIDEO_DECODER
1883    case NEXUS_VideoInputType_eDecoder:
1884        if (!pVideo->modules.videoDecoder) {
1885            BERR_TRACE(NEXUS_NOT_SUPPORTED);
1886            return;
1887        }
1888
1889    #if NEXUS_NUM_MOSAIC_DECODES       
1890        if (window->mosaic.parent) {
1891            /* mosaic windows have no VDC window and sync-locked is handled with BVDC_Window_SetMosaicTrack, so always pass the info along. */
1892        }
1893        /* if the window is not sync-locked, don't feed the display info back to the video decoder input */
1894        else
1895    #endif
1896        if (!window->vdcState.window
1897    #if !B_HAS_LEGACY_VDC && BCHP_CHIP != 7403
1898        || BVDC_Window_GetStatus(window->vdcState.window, &vdcWindowStatus) || !vdcWindowStatus.bSyncLock
1899    #endif
1900        ) {
1901            return;
1902        }
1903       
1904        displayInformation.refreshRate = window->display->status.refreshRate / 10;
1905        displayInformation.stgIndex = 0;
1906        if(pSettings->timingGenerator == NEXUS_DisplayTimingGenerator_eEncoder) {
1907            displayInformation.stgIndex = window->display->stgIndex;
1908            BDBG_MSG(("display stg%d vfreq=%d", displayInformation.stgIndex, displayInformation.refreshRate));
1909        }
1910        NEXUS_Module_Lock(pVideo->modules.videoDecoder);
1911        NEXUS_VideoDecoder_UpdateDisplayInformation_priv((NEXUS_VideoDecoderHandle)videoInput->source, &displayInformation);
1912#if NEXUS_HAS_VIDEO_ENCODER
1913        {
1914            NEXUS_VideoInput_P_Link *link;
1915            NEXUS_VideoDecoderDisplayConnection decoderConnect;
1916
1917            link = NEXUS_VideoInput_P_Get(videoInput);
1918            link->hXud = window->display->encodeUserData?window->display->hXud:NULL;
1919
1920            NEXUS_VideoDecoder_GetDisplayConnection_priv(link->input->source, &decoderConnect);
1921            decoderConnect.userDataCallback_isr = window->display->encodeUserData?NEXUS_VideoInput_P_UserDataCallback_isr:NULL;
1922            NEXUS_VideoDecoder_SetDisplayConnection_priv(link->input->source, &decoderConnect);
1923        }
1924#endif
1925        NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
1926        break;
1927#endif
1928    case NEXUS_VideoInputType_eImage:
1929        NEXUS_VideoImageInput_P_UpdateDisplayInformation((NEXUS_VideoImageInputHandle)videoInput->source, pSettings);
1930        break;
1931    default:
1932        break;
1933    }
1934    return;
1935}
1936
1937NEXUS_Error NEXUS_VideoInput_GetCrcData( NEXUS_VideoInput input, NEXUS_VideoInputCrcData *pData, unsigned numEntries, unsigned *numEntriesReturned )
1938{
1939#if NEXUS_CRC_CAPTURE
1940    NEXUS_VideoInput_P_Link *link = NEXUS_VideoInput_P_Get(input);
1941
1942    *numEntriesReturned = 0;
1943
1944    if (!link) return 0;
1945
1946    while (*numEntriesReturned < numEntries && link->crc.rptr != link->crc.wptr) {
1947        pData[*numEntriesReturned] = link->crc.data[link->crc.rptr];
1948        if (++link->crc.rptr == NEXUS_VIDEO_INPUT_CRC_QUEUE_SIZE) {
1949            link->crc.rptr = 0;
1950        }
1951        (*numEntriesReturned)++;
1952    }
1953    return 0;
1954#else
1955    BSTD_UNUSED(input);
1956    BSTD_UNUSED(pData);
1957    BSTD_UNUSED(numEntries);
1958    BSTD_UNUSED(numEntriesReturned);
1959    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1960#endif
1961}
1962
1963NEXUS_Error NEXUS_VideoInput_SetResumeMode( NEXUS_VideoInput videoInput, NEXUS_VideoInputResumeMode resumeMode )
1964{
1965#ifndef B_HAS_LEGACY_VDC
1966    NEXUS_VideoInput_P_Link *link;
1967    BERR_Code rc;
1968    BVDC_ResumeMode vdcMode;
1969
1970    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
1971    link = NEXUS_VideoInput_P_Get(videoInput);
1972    if ( !link ) return BERR_TRACE(NEXUS_UNKNOWN);
1973    if ( !link->sourceVdc ) { link->resumeMode = resumeMode; return NEXUS_SUCCESS; }
1974
1975    if ( resumeMode == NEXUS_VideoInputResumeMode_eFreezeRts )
1976    {
1977        if ( !g_NEXUS_DisplayModule_State.moduleSettings.handleDynamicRts )
1978        {
1979            BDBG_ERR(("Bandwidth can only be frozen while dynamic RTS management is active"));
1980            return BERR_TRACE(BERR_NOT_SUPPORTED);
1981        }
1982    }
1983
1984    if ( resumeMode == NEXUS_VideoInputResumeMode_eNow ||
1985         resumeMode == NEXUS_VideoInputResumeMode_eFreezeRts )
1986    {
1987        if ( g_NEXUS_DisplayModule_State.moduleSettings.handleDynamicRts &&
1988             link->resumeMode == NEXUS_VideoInputResumeMode_eManual )
1989        {
1990            /* Temporarily set to eNow so that VDB is processed. Otherwise eManual causes VDB-recalc to be bypassed. */
1991            link->resumeMode = NEXUS_VideoInputResumeMode_eNow;
1992            rc = NEXUS_Vdb_P_HandleSourcePending(videoInput);
1993            link->resumeMode = NEXUS_VideoInputResumeMode_eManual;
1994            if ( rc ) return BERR_TRACE(rc);
1995        }
1996
1997        rc = BVDC_Source_Resume(link->sourceVdc);
1998        if ( rc ) return BERR_TRACE(rc);
1999
2000        /* We must always apply changes when resuming */
2001        if ( pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto )
2002        {
2003            rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);
2004        }
2005
2006        if ( link->resumeMode == NEXUS_VideoInputResumeMode_eFreezeRts ||
2007             resumeMode == NEXUS_VideoInputResumeMode_eFreezeRts )
2008        {
2009            /* Allow the source to free-run at this point.  The app must exit this mode to change bandwidth later on. */
2010            (void)BVDC_Source_SetResumeMode(link->sourceVdc, NEXUS_VideoInputResumeMode_eAuto);
2011            link->resumeMode = NEXUS_VideoInputResumeMode_eFreezeRts;
2012        }
2013
2014        rc = BVDC_ApplyChanges(pVideo->vdc);
2015        if ( rc ) return BERR_TRACE(rc);
2016
2017        link->status.sourcePending = false;
2018        return NEXUS_SUCCESS;   /* Nothing more to do, return here to avoid a double apply changes */
2019    }
2020
2021    /* If we have a dynamic RTS configuration, use that instead of VDC's auto resume mode. */
2022    if ( g_NEXUS_DisplayModule_State.moduleSettings.handleDynamicRts )
2023    {
2024        vdcMode = BVDC_ResumeMode_eManual;
2025    }
2026    else
2027    {
2028        vdcMode = (resumeMode == NEXUS_VideoInputResumeMode_eAuto) ? BVDC_ResumeMode_eAuto : BVDC_ResumeMode_eManual;
2029    }
2030
2031    rc = BVDC_Source_SetResumeMode(link->sourceVdc, vdcMode);
2032    if ( rc ) return BERR_TRACE(rc);
2033
2034    if ( pVideo->updateMode != NEXUS_DisplayUpdateMode_eAuto )
2035    {
2036        rc=BERR_TRACE(NEXUS_NOT_SUPPORTED);
2037    }
2038    rc = BVDC_ApplyChanges(pVideo->vdc);
2039    if ( rc ) return BERR_TRACE(rc);
2040
2041    link->resumeMode = resumeMode;
2042#else
2043    BSTD_UNUSED(videoInput);
2044    BSTD_UNUSED(resumeMode);
2045#endif
2046    return 0;
2047}
2048
2049NEXUS_Error NEXUS_VideoInput_ForcePending(
2050    NEXUS_VideoInput videoInput
2051    )
2052{
2053    NEXUS_VideoInput_P_Link *link;
2054    BERR_Code rc;
2055
2056    BDBG_OBJECT_ASSERT(videoInput, NEXUS_VideoInput);
2057    link = NEXUS_VideoInput_P_Get(videoInput);
2058    if (!link) {return BERR_TRACE(NEXUS_UNKNOWN);}
2059    if (!link->sourceVdc) {link->isDeferForcePending = true; return NEXUS_SUCCESS;}
2060
2061    if ( link->resumeMode != NEXUS_VideoInputResumeMode_eManual )
2062    {
2063        return BERR_TRACE(BERR_NOT_SUPPORTED);
2064    }
2065#if !B_HAS_LEGACY_VDC && BCHP_CHIP != 7403
2066    rc = BVDC_Source_ForcePending(link->sourceVdc);
2067    if ( rc ) {return BERR_TRACE(rc);}
2068#endif
2069    link->status.sourcePending = true;
2070    rc = NEXUS_Display_P_ApplyChanges();
2071    if (rc) {return BERR_TRACE(rc);}
2072
2073    return NEXUS_SUCCESS;
2074}
2075
2076void NEXUS_VideoInput_P_CheckFormatChange_isr(void *pParam)
2077{
2078    NEXUS_VideoInput_P_Link *pLink = pParam;
2079
2080    BDBG_ASSERT(NULL != pLink);
2081
2082    if ( pLink->checkFormatChangedEvent )
2083    {
2084        BKNI_SetEvent_isr(pLink->checkFormatChangedEvent);
2085    }
2086}
2087
2088static void NEXUS_VideoInput_P_CheckFormatChanged(void *pParam)
2089{
2090    NEXUS_VideoInput source = pParam;
2091    NEXUS_Vdb_P_SourceModeChanged(source);
2092}
2093
Note: See TracBrowser for help on using the repository browser.