source: svn/newcon3bcm2_21bu/nexus/modules/display/7552/src/nexus_display_mosaic.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: 23.8 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_display_mosaic.c $
39 * $brcm_Revision: 16 $
40 * $brcm_Date: 6/27/11 4:59p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/display/7400/src/nexus_display_mosaic.c $
47 *
48 * 16   6/27/11 4:59p erickson
49 * SW7425-466: force zorder to zero for one-mosaic configuration. this
50 *  avoids potential conflicts with PIP (zorder=1).
51 *
52 * 15   6/2/10 12:36p erickson
53 * SW7400-2773: support all stripe widths
54 *
55 * 14   4/5/10 4:19p erickson
56 * SW7405-3965: explicitly unset parentVideoInput->source in
57 *  NEXUS_VideoWindow_P_RemoveMosaicInput
58 *
59 * 13   3/26/10 2:19p erickson
60 * SW7405-3965: refactor mosaic to support hd/sd simul mode
61 *
62 * 12   3/16/10 1:26p erickson
63 * SW7405-3625: insert mosaics in mosaicIndex order so that backendMosaic
64 *  is applied correctly
65 *
66 * 11   3/2/10 11:29a erickson
67 * SW7405-3625: add check to NEXUS_VideoWindow_P_RemoveMosaicInput
68 *
69 * 10   2/22/10 2:45p erickson
70 * SW7405-3625: fix non-mosaic build
71 *
72 * 9   2/22/10 12:50p erickson
73 * SW7405-3625: update backendMosaic impl
74 *
75 * 8   2/19/10 1:23p erickson
76 * SW7405-3625: add NEXUS_VideoWindowMosaicSettings for backendMosaic
77 *  support
78 *
79 * 7   2/12/10 3:23p mward
80 * SW7125-143: bClearRectByMaskColor must be set when setting up mosaic
81 *  mode.  Set mosaic background black.
82 *
83 * 6   1/6/10 4:18p erickson
84 * SW7405-3533: if there's only one mosaic window, convert to a normal
85 *  window. apply all settings, including MAD.
86 *
87 * 5   12/9/09 4:54p erickson
88 * SW7405-3394: fix non-mosaic build
89 *
90 * 4   12/9/09 3:10p erickson
91 * SW7405-3394: refactor mosaic mode API
92 *
93 * 3   7/10/09 3:58p erickson
94 * PR56558: add NEXUS_DisplayModule_SetVideoDecoderModule to allow faster
95 *  start up time
96 *
97 * 2   4/28/09 4:03p erickson
98 * PR54676: allow VideoDecoder to incrementally create/destroy channels
99 *
100 * 1   1/18/08 2:20p jgarrett
101 * PR 38808: Merging to main branch
102 *
103 * Nexus_Devel/2   11/8/07 10:56a erickson
104 * PR36802: added #if for no mosaic
105 *
106 * Nexus_Devel/1   11/8/07 9:16a erickson
107 * PR36802: added mosaic mode
108 *
109 ***************************************************************************/
110#include "nexus_display_module.h"
111
112BDBG_MODULE(nexus_display_mosaic);
113
114NEXUS_VideoWindowHandle NEXUS_VideoWindow_OpenMosaic( NEXUS_VideoWindowHandle parentWindow, unsigned mosaicIndex)
115{
116#if NEXUS_NUM_MOSAIC_DECODES
117    NEXUS_VideoWindowHandle window;
118
119    BDBG_OBJECT_ASSERT(parentWindow, NEXUS_VideoWindow);
120
121    if (parentWindow->mosaic.parent) {
122        BDBG_ERR(("Window %p is a mosaic child and so can't be a mosaic parent", parentWindow));
123        return NULL;
124    }
125    if (mosaicIndex >= NEXUS_NUM_MOSAIC_DECODES) {
126        BERR_TRACE(NEXUS_INVALID_PARAMETER);
127        return NULL;
128    }
129    for (window = BLST_S_FIRST(&parentWindow->mosaic.children); window; window = BLST_S_NEXT(window, mosaic.link)) {
130        if (window->mosaic.userIndex == mosaicIndex) {
131            BDBG_ERR(("Window %p mosaic %d already opened", parentWindow, mosaicIndex));
132            return NULL;
133        }
134    }
135
136    window = BKNI_Malloc(sizeof(*window));
137    if (!window) {
138        BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY);
139        return NULL;
140    }
141    NEXUS_VideoWindow_P_InitState(window, mosaicIndex, parentWindow->display);
142    window->open = true;
143    window->mosaic.parent = parentWindow;
144    window->mosaic.userIndex = mosaicIndex;
145
146    /* Insert in mosaicIndex order
147    This is convenient for NEXUS_VideoWindow_P_CutBackendMosaic_isr where there is no VideoDecoder order, only window order. */
148    {
149        NEXUS_VideoWindowHandle mosaicWindow, prev = NULL;
150        for (mosaicWindow = BLST_S_FIRST(&parentWindow->mosaic.children); mosaicWindow; mosaicWindow = BLST_S_NEXT(mosaicWindow, mosaic.link)) {
151            if (mosaicWindow->mosaic.userIndex > mosaicIndex) {
152                if (prev) {
153                    BLST_S_INSERT_AFTER(&parentWindow->mosaic.children, prev, window, mosaic.link);
154                }
155                else {
156                    BLST_S_INSERT_HEAD(&parentWindow->mosaic.children, window, mosaic.link);
157                }
158                break;
159            }
160            prev = mosaicWindow;
161        }
162        if (!mosaicWindow) {
163            if (prev) {
164                BLST_S_INSERT_AFTER(&parentWindow->mosaic.children, prev, window, mosaic.link);
165            }
166            else {
167                BLST_S_INSERT_HEAD(&parentWindow->mosaic.children, window, mosaic.link);
168            }
169        }
170    }
171
172    /* default to a tile layout based on mosaicIndex */
173    window->cfg.position.x = 50 + 130 * (mosaicIndex%4);
174    window->cfg.position.y = 50 + 130 * (mosaicIndex/4);
175    window->cfg.position.width = 100;
176    window->cfg.position.height = 100;
177
178    return window;
179#else
180    BSTD_UNUSED(parentWindow);
181    BSTD_UNUSED(mosaicIndex);
182    BERR_TRACE(NEXUS_NOT_SUPPORTED);
183    return NULL;
184#endif
185}
186
187#define pVideo (&g_NEXUS_DisplayModule_State)
188
189NEXUS_Error NEXUS_VideoWindow_P_ApplyMosaic(NEXUS_VideoWindowHandle window)
190{
191#if NEXUS_NUM_MOSAIC_DECODES
192    BERR_Code rc;
193    NEXUS_VideoWindowHandle mosaicWindow;
194    NEXUS_VideoWindowHandle singleWindow = NULL;
195    BVDC_Window_Handle windowVdc;
196    unsigned cnt = 0;
197    unsigned total = 0;
198    bool mosaic_visible[NEXUS_NUM_MOSAIC_DECODES];
199    BVDC_Rect mosaic_rects[NEXUS_NUM_MOSAIC_DECODES];
200    uint8_t mosaic_zorder[NEXUS_NUM_MOSAIC_DECODES];
201    unsigned mosaicTrackIndex = NEXUS_NUM_MOSAIC_DECODES;
202    NEXUS_VideoInput_P_Link *link;
203    BAVC_MFD_Picture *pPrevPicture = NULL;
204
205    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
206    BDBG_ASSERT(!window->mosaic.parent);
207
208    windowVdc = window->vdcState.window;
209    if (!windowVdc) return 0;
210
211    BKNI_Memset(mosaic_visible, 0, sizeof(mosaic_visible));
212
213    for (mosaicWindow = BLST_S_FIRST(&window->mosaic.children); mosaicWindow; mosaicWindow = BLST_S_NEXT(mosaicWindow, mosaic.link)) {
214        unsigned index;
215
216        if (!mosaicWindow->input) continue;
217
218        link = NEXUS_VideoInput_P_Get(mosaicWindow->input);
219        BDBG_ASSERT(link);
220
221        if (mosaicWindow->mosaic.mosaicSettings.backendMosaic.enabled) {
222            index = mosaicWindow->mosaic.userIndex;
223
224            /* build a linked list of BAVC_MFD_Picture structs for backend mosaic */
225            if (pPrevPicture) {
226                pPrevPicture->pNext = &mosaicWindow->mosaic.picture;
227            }
228            pPrevPicture = &mosaicWindow->mosaic.picture;
229            pPrevPicture->pNext = NULL;
230        }
231        else {
232            index = link->mosaic.index;
233        }
234
235        mosaic_visible[index] = mosaicWindow->cfg.visible;
236        mosaic_rects[index].lLeft = mosaicWindow->cfg.position.x;
237        mosaic_rects[index].lTop = mosaicWindow->cfg.position.y;
238        mosaic_rects[index].ulWidth = mosaicWindow->cfg.position.width;
239        mosaic_rects[index].ulHeight = mosaicWindow->cfg.position.height;
240        /* skip mosaic zorder=1 because of PIP */
241        mosaic_zorder[index] = mosaicWindow->cfg.zorder>0?mosaicWindow->cfg.zorder+1:mosaicWindow->cfg.zorder;
242        BDBG_MSG(("mosaic %d: v=%c z=%d position=%d,%d,%d,%d", index,
243            mosaicWindow->cfg.visible?'y':'n',
244            mosaicWindow->cfg.zorder,
245            mosaicWindow->cfg.position.x,mosaicWindow->cfg.position.y,mosaicWindow->cfg.position.width,mosaicWindow->cfg.position.height));
246
247        if (window->display->cfg.frameRateMaster) {
248            if (window->display->cfg.frameRateMaster == mosaicWindow->input) {
249                mosaicTrackIndex = index;
250            }
251        }
252        else if (mosaicWindow->cfg.autoMaster) {
253            mosaicTrackIndex = index;
254        }
255
256        if (index+1 > cnt) {
257            cnt = index+1;
258        }
259        total++;
260        singleWindow = mosaicWindow;
261    }
262
263    if (!total) {
264        BDBG_MSG(("no mosaics"));
265        rc = BVDC_Window_SetMosaicConfiguration(windowVdc, false, NULL);
266        if (rc) {return BERR_TRACE(rc);}
267    }
268    else if (total == 1) {
269        NEXUS_VideoInput_P_Link *link;
270        NEXUS_VideoWindowSettings cfg = singleWindow->cfg;
271
272        BDBG_MSG(("one mosaic: converting to regular window"));
273        /* if only one mosaic, dynamically convert to a normal window */
274        rc = BVDC_Window_SetMosaicConfiguration(windowVdc, false, NULL);
275        if (rc) {return BERR_TRACE(rc);}
276
277        link = NEXUS_VideoInput_P_Get(singleWindow->mosaic.parent->input);
278        BDBG_ASSERT(link);
279
280        cfg.zorder = 0; /* force one mosaic zorder to zero. */
281        rc = NEXUS_VideoWindow_P_SetVdcSettings(singleWindow->mosaic.parent, &cfg, true);
282        if (rc) {return BERR_TRACE(rc);}
283
284        singleWindow->mosaic.parent->adjContext = singleWindow->adjContext;
285        rc = NEXUS_VideoAdj_P_ApplySetSettings(singleWindow->mosaic.parent);
286        if (rc) {return BERR_TRACE(rc);}
287    }
288    else {
289        bool dummy;
290        BVDC_MosaicConfiguration mosaic_config;
291        unsigned i;
292        const NEXUS_Rect *pDisplayRect = &window->display->displayRect;
293
294        /* VDC does not ignore invisible windows, so we must ensure ok values */
295        for (i=0;i<cnt;i++) {
296            if (!mosaic_visible[i]) {
297                mosaic_rects[i].lLeft = mosaic_rects[i].lTop = 0;
298                mosaic_rects[i].ulWidth = mosaic_rects[i].ulHeight = 100;
299                mosaic_zorder[i] = 0;
300            }
301        }
302        BDBG_MSG(("%d mosaics, array size %d", total, cnt));
303
304        /* set parent properties that are required for mosaics */
305        rc = BVDC_Window_SetScalerOutput(windowVdc, 0, 0, pDisplayRect->width, pDisplayRect->height);
306        if (rc) {return BERR_TRACE(rc);}
307        rc = BVDC_Window_SetDstRect(windowVdc, 0, 0, pDisplayRect->width, pDisplayRect->height);
308        if (rc) {return BERR_TRACE(rc);}
309        rc = BVDC_Window_SetVisibility(windowVdc, true);
310        if (rc) {return BERR_TRACE(rc);}
311
312        BVDC_Window_GetMosaicConfiguration(windowVdc, &dummy, &mosaic_config);
313        mosaic_config.bVideoInMosaics = true;
314        mosaic_config.bClearRectByMaskColor = true;
315        mosaic_config.ulClearRectAlpha = 255;
316        mosaic_config.ulMaskColorBlue = 0;
317        mosaic_config.ulMaskColorGreen = 0;
318        mosaic_config.ulMaskColorRed = 0;
319        rc = BVDC_Window_SetMosaicConfiguration(windowVdc, true, &mosaic_config);
320        if (rc) {return BERR_TRACE(rc);}
321
322        rc = BVDC_Window_SetMosaicDstRects(windowVdc, cnt, mosaic_rects);
323        if (rc) {return BERR_TRACE(rc);}
324        rc = BVDC_Window_SetMosaicRectsVisibility(windowVdc, cnt, mosaic_visible);
325        if (rc) {return BERR_TRACE(rc);}
326        rc = BVDC_Window_SetMosaicRectsZOrder(windowVdc, cnt, mosaic_zorder);
327        if (rc) {return BERR_TRACE(rc);}
328        if (mosaicTrackIndex != NEXUS_NUM_MOSAIC_DECODES) {
329            rc = BVDC_Window_SetMosaicTrack(windowVdc, mosaicTrackIndex);
330            if (rc) {return BERR_TRACE(rc);}
331        }
332    }
333
334    rc = BVDC_ApplyChanges(pVideo->vdc);
335    if (rc) {return BERR_TRACE(rc);}
336
337    return 0;
338#else
339    BSTD_UNUSED(window);
340    return BERR_TRACE(BERR_NOT_SUPPORTED);
341#endif
342}
343
344void NEXUS_VideoWindow_GetMosaicSettings( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowMosaicSettings *pSettings )
345{
346    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
347#if NEXUS_NUM_MOSAIC_DECODES
348    *pSettings = window->mosaic.mosaicSettings;
349#else
350    BSTD_UNUSED(pSettings);
351    BERR_TRACE(NEXUS_NOT_SUPPORTED);
352#endif
353}
354
355NEXUS_Error NEXUS_VideoWindow_SetMosaicSettings( NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowMosaicSettings *pSettings )
356{
357    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
358#if NEXUS_NUM_MOSAIC_DECODES
359    window->mosaic.mosaicSettings = *pSettings;
360    return 0;
361#else
362    BSTD_UNUSED(pSettings);
363    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
364#endif
365}
366
367#if NEXUS_NUM_MOSAIC_DECODES
368const BAVC_MFD_Picture *NEXUS_VideoWindow_P_CutBackendMosaic_isr(NEXUS_VideoWindowHandle window, const BAVC_MFD_Picture *pPicture)
369{
370    unsigned ulStripeWidth;
371    NEXUS_VideoWindowHandle mosaicWindow;
372    const BAVC_MFD_Picture *pFirstPicture = NULL;
373    unsigned id = 0;
374
375    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
376
377    switch (pPicture->eStripeWidth) {
378    case BAVC_StripeWidth_e64Byte: ulStripeWidth = 64; break;
379    case BAVC_StripeWidth_e128Byte: ulStripeWidth = 128; break;
380    case BAVC_StripeWidth_e256Byte: ulStripeWidth = 256; break;
381    default:
382        BDBG_ERR(("unsupported stripe width %d", pPicture->eStripeWidth));
383        return NULL;
384    }
385
386    for (mosaicWindow = BLST_S_FIRST(&window->mosaic.children); mosaicWindow; mosaicWindow = BLST_S_NEXT(mosaicWindow, mosaic.link)) {
387        BAVC_MFD_Picture *pThis, *pNext;
388        unsigned ulStripeNum;
389        NEXUS_VideoWindowMosaicSettings *pMosaicSettings = &mosaicWindow->mosaic.mosaicSettings;
390        unsigned x, y;
391
392        if (!pMosaicSettings->backendMosaic.enabled) continue;
393
394        pThis = &mosaicWindow->mosaic.picture;
395        if (!pFirstPicture) {
396            pFirstPicture = pThis;
397        }
398
399        pNext = pThis->pNext;
400        *pThis = *pPicture; /* overwrite everything */
401        pThis->pNext = pNext; /* restore the pNext pointer */
402        pThis->ulChannelId = id++;
403
404        /* avoid div-by-zero math */
405        if (!pMosaicSettings->backendMosaic.clipBase.width || !pMosaicSettings->backendMosaic.clipBase.height) {
406            continue;
407        }
408
409        x = pMosaicSettings->backendMosaic.clipRect.x * pThis->ulSourceHorizontalSize / pMosaicSettings->backendMosaic.clipBase.width;
410        y = pMosaicSettings->backendMosaic.clipRect.y * pThis->ulSourceVerticalSize / pMosaicSettings->backendMosaic.clipBase.height;
411
412        pThis->ulSourceHorizontalSize = pThis->ulSourceHorizontalSize * pMosaicSettings->backendMosaic.clipRect.width / pMosaicSettings->backendMosaic.clipBase.width;
413        pThis->ulDisplayHorizontalSize = pThis->ulDisplayHorizontalSize * pMosaicSettings->backendMosaic.clipRect.width / pMosaicSettings->backendMosaic.clipBase.width;
414        pThis->ulSourceVerticalSize = pThis->ulSourceVerticalSize * pMosaicSettings->backendMosaic.clipRect.height / pMosaicSettings->backendMosaic.clipBase.height;
415        pThis->ulDisplayVerticalSize = pThis->ulDisplayVerticalSize * pMosaicSettings->backendMosaic.clipRect.height / pMosaicSettings->backendMosaic.clipBase.height;
416
417        ulStripeNum = x / ulStripeWidth;
418
419        pThis->pLuminanceFrameBufferAddress = (void*)
420            ((uint8_t*)pThis->pLuminanceFrameBufferAddress +
421             ulStripeNum * pThis->ulLuminanceNMBY * 16 * ulStripeWidth +
422             y * ulStripeWidth +
423             (x % ulStripeWidth));
424
425        pThis->pChrominanceFrameBufferAddress = (void*)
426            ((uint8_t*)pThis->pChrominanceFrameBufferAddress +
427
428            /* stripe offset */
429             ulStripeNum * pThis->ulChrominanceNMBY * 16 * ulStripeWidth +
430
431            /* vertical offset within a stripe (take care of 422 vs 420 chroma type) */
432             ((y * ulStripeWidth /2) << (pThis->eYCbCrType - BAVC_YCbCrType_e4_2_0)) +
433
434            /* horizontal offset within a stripe */
435             (x % ulStripeWidth));
436    }
437
438    return pFirstPicture ? pFirstPicture : pPicture;
439}
440
441/**
442Need to find parent mosaic NEXUS_VideoInput which matches the child mosaic mosaicInput.
443We must match by going back to the VideoDecoder mosaic parent.
444Be aware that a single parent mosaic NEXUS_VideoInput will serve multiple mosaic windows on multiple displays.
445**/
446static NEXUS_VideoInput NEXUS_VideoWindow_P_AssignMosaicInput(NEXUS_VideoInput mosaicInput)
447{
448    NEXUS_VideoInput input = NULL;
449    unsigned freeInput = NEXUS_NUM_MOSAIC_DECODE_SETS;
450    NEXUS_VideoDecoderDisplayConnection connection;
451    unsigned i;
452
453    if (!pVideo->modules.videoDecoder) {
454        BERR_TRACE(NEXUS_NOT_SUPPORTED);
455        return NULL;
456    }
457
458    NEXUS_Module_Lock(pVideo->modules.videoDecoder);
459    NEXUS_VideoDecoder_GetDisplayConnection_priv(mosaicInput->source, &connection);
460    NEXUS_Module_Unlock(pVideo->modules.videoDecoder);
461
462    for (i=0;i<NEXUS_NUM_MOSAIC_DECODE_SETS;i++) {
463        if (pVideo->mosaicInput[i].input.source) {
464            if (connection.parentIndex == pVideo->mosaicInput[i].parentIndex) {
465                input = &pVideo->mosaicInput[i].input;
466                break;
467            }
468        }
469        else if (freeInput == NEXUS_NUM_MOSAIC_DECODE_SETS) {
470            freeInput = i;
471        }
472    }
473
474    if (!input && freeInput < NEXUS_NUM_MOSAIC_DECODE_SETS) {
475        input = &pVideo->mosaicInput[freeInput].input;
476        input->source = mosaicInput->source; /* this is the link */
477        pVideo->mosaicInput[freeInput].parentIndex = connection.parentIndex; /* cache this value */
478    }
479
480    return input;
481}
482
483NEXUS_Error NEXUS_VideoWindow_P_AddMosaicInput(NEXUS_VideoWindowHandle window, NEXUS_VideoInput input)
484{
485    NEXUS_Error rc;
486    NEXUS_VideoInput parentVideoInput;
487    NEXUS_VideoInput_P_Link *parentLink;
488
489    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
490
491    /* Mosaic windows share a common parent VideoWindow and a common parent NEXUS_VideoInput_P_Link.
492       There is a single NEXUS_VideoInput_P_Link for each VideoDecoder set of mosaics. One NEXUS_VideoInput_P_Link could serve multiple displays (HD/SD simul).
493       The parent link is not connected back to VideoDecoder; it only holds the BVDC_Source for the Display module.
494       Each mosaic window has its own, separate NEXUS_VideoInput_P_Link as well, used to connect back to each mosaic decoder and to store its mosaicIndex. */
495
496    if (input->type != NEXUS_VideoInputType_eDecoder) {
497        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
498    }
499
500    parentVideoInput = NEXUS_VideoWindow_P_AssignMosaicInput(input);
501    if (!parentVideoInput) return BERR_TRACE(NEXUS_INVALID_PARAMETER);
502
503    if (!window->mosaic.parent->input) {
504        rc = NEXUS_VideoWindow_AddInput(window->mosaic.parent, parentVideoInput);
505        if (rc) {
506            parentVideoInput->source = NULL; /* reverse the effect of NEXUS_VideoWindow_P_AssignMosaicInput */
507            return BERR_TRACE(rc);
508        }
509
510        parentLink = parentVideoInput->destination;
511        BDBG_ASSERT(parentLink);
512
513        parentLink->mosaic.parentWindow[window->display->index] = window->mosaic.parent;
514
515        /* The decoder is not mosaic. so only the parentLink can connect. instead, the display module
516        will cut up the single stream into the desired number of mosaics in NEXUS_VideoInput_P_DecoderDataReady_isr.
517        This must be set after NEXUS_VideoWindow_AddInput. */
518        parentLink->mosaic.backendMosaic = window->mosaic.mosaicSettings.backendMosaic.enabled;
519    }
520    else {
521        if (window->mosaic.parent->input != parentVideoInput) {
522            BDBG_ERR(("mosaic mismatch parent window %p already has input %p, mosaic window maps to input %p",
523                window->mosaic.parent, window->mosaic.parent->input, window, parentVideoInput));
524            return BERR_TRACE(NEXUS_UNKNOWN);
525        }
526        parentLink = parentVideoInput->destination;
527    }
528
529    /* now create this input's link, but use the parentLink for the shared VDC source. */
530    if (input->destination == NULL) {
531        NEXUS_VideoInput_P_Link *link;
532        BLST_S_DICT_FIND(&pVideo->inputs, link, input, input, link);
533        if (!link) {
534            link = NEXUS_VideoInput_P_OpenDecoder(input, parentLink);
535            if (!link) {
536                return BERR_TRACE(NEXUS_UNKNOWN);
537            }
538        }
539    }
540
541    return 0;
542}
543
544void NEXUS_VideoWindow_P_RemoveMosaicInput(NEXUS_VideoWindowHandle window, NEXUS_VideoInput input)
545{
546    NEXUS_VideoInput parentVideoInput;
547    NEXUS_VideoInput_P_Link *parentLink;
548
549    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
550    BDBG_ASSERT(window->mosaic.parent);
551    BDBG_OBJECT_ASSERT(window->mosaic.parent, NEXUS_VideoWindow);
552
553    /* check if this source is used for the mosaic parent. if so, switch the mosaic parent to
554    another mosaic's source. if there are no more mosaics, destroy the parent link. */
555
556    parentVideoInput = window->mosaic.parent->input;
557    if (!parentVideoInput) return;
558    BDBG_OBJECT_ASSERT(parentVideoInput, NEXUS_VideoInput);
559
560    parentLink = parentVideoInput->destination;
561    if (!parentLink) return;
562    BDBG_OBJECT_ASSERT(parentLink, NEXUS_VideoInput_P_Link);
563
564    /* are we removing the mosaic video input which was used to connect the parent video input? if so, we must adjust the parent */
565    if (parentVideoInput->source == input->source) {
566        unsigned i;
567        NEXUS_VideoWindowHandle mosaicChild = NULL;
568
569        /* find another mosaic which is currently using this parentLink */
570        for (i=0;i<NEXUS_NUM_DISPLAYS;i++) {
571            NEXUS_VideoWindowHandle parentWindow = parentLink->mosaic.parentWindow[i];
572            if (!parentWindow) continue;
573
574            BDBG_OBJECT_ASSERT(parentWindow, NEXUS_VideoWindow);
575            for (mosaicChild = BLST_S_FIRST(&parentWindow->mosaic.children); mosaicChild; mosaicChild = BLST_S_NEXT(mosaicChild, mosaic.link)) {
576                if ((mosaicChild != window) && mosaicChild->input && mosaicChild->input->source) {
577                    i = NEXUS_NUM_DISPLAYS; /* break out of outer loop */
578                    break;
579                }
580            }
581        }
582
583        if (mosaicChild) {
584            BDBG_MSG(("moving internal mosaic parent input(%p) from %p to %p", parentVideoInput, window, mosaicChild));
585            parentVideoInput->source = mosaicChild->input->source;
586            parentLink->input_info.source = mosaicChild->input->source;
587        }
588        else {
589            /* parentVideoInput was not assigned to another mosaic child. it is unused. */
590            BDBG_MSG(("shutting down internal mosaic parent input(%p)", parentVideoInput));
591            parentLink->mosaic.backendMosaic = false; /* this will allow parent to disconnect if backendMosaic was true */
592            NEXUS_VideoInput_Shutdown(parentVideoInput);
593            parentVideoInput->source = NULL;
594        }
595    }
596}
597#endif
Note: See TracBrowser for help on using the repository browser.