source: svn/newcon3bcm2_21bu/nexus/lib/playback_ip/apps/ip_psi.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: 29.5 KB
Line 
1/******************************************************************************
2 *    (c)2008-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: ip_psi.c $
39 * $brcm_Revision: 21 $
40 * $brcm_Date: 12/21/11 3:48p $
41 *
42 * Module Description:
43 *  ip psi test file
44 *
45 * Revision History:
46 *
47 * $brcm_Log: /nexus/lib/playback_ip/apps/ip_psi.c $
48 *
49 * 21   12/21/11 3:48p ssood
50 * SW7231-516: fixed the sharing of same xcode session w/ multiple clients
51 *  + modified the qam frontend logic to use fast lock Status function
52 *
53 * 20   10/14/11 10:18a ssood
54 * SW7425-889: initial check-in for enabling audio in the live xcoded
55 *  streams
56 *
57 * 19   7/14/11 12:01p ssood
58 * SW7346-309: Add support for Streaming from Satellite Source
59 *
60 * 18   6/18/11 11:52a ssood
61 * SW7425-718: 3128 related changes: use different frontend resources for
62 *  each streaming session even though it is same channel
63 *
64 * 17   8/12/10 11:24a ssood
65 * SW7420-883: added support for streaming same transcoding session to
66 *  multiple clients
67 *
68 * 16   7/30/10 2:11p garetht
69 * SW7420-919: Add CableCARD support to Ip_streamer
70 *
71 * 15   3/4/10 12:17p ssood
72 * SW7420-561: merge from branch to mainline
73 *
74 * SW7420-561/2   2/16/10 10:42p ssood
75 * SW7420-561: Changes to support basic RTSP w/o trickmodes
76 *
77 * SW7420-561/1   2/16/10 10:11a ssood
78 * SW7420-561: initial cut of new APIs to meet Media Browser, DMR, &
79 *  Philips RTSP requirements
80 *
81 * 14   1/27/10 10:18a ssood
82 * SW7420-454: conditionally compile Live Streaming Code using
83 *  LIVE_STREAMING_SUPPORT
84 *
85 * 13   1/19/10 4:55p ssood
86 * SW7420-454: convert verbose output to be available via msg modules
87 *  flags
88 *
89 * 12   1/14/10 6:41p ssood
90 * SW7408-47: Add support to compile IP Streamer App on platforms w/ no
91 *  frontend support
92 *
93 * 11   12/4/09 8:09p ssood
94 * SW7420-454: added support to parse programs w/ either audio or video
95 *  streams only
96 *
97 * 10   11/24/09 6:05p ssood
98 * SW7420-454: reset psi structure before each psi acquisition
99 *
100 * 9   10/20/09 6:33p ssood
101 * SW7420-340: remove nexus playback, audio, video decoder dependencies
102 *  for SMS compilation
103 *
104 * 8   10/9/09 12:29p ssood
105 * SW7420-340: add support to play live streams on non-Broadcom clients
106 *
107 * 7   10/8/09 1:14p ssood
108 * SW7420-340: convert PSI data ready event from global to per thread
109 *  specific + enabled debug prints
110 *
111 * 6   10/2/09 11:35a ssood
112 * SW7420-340: wait for qam lock before acquiring PSI info
113 *
114 * 5   9/30/09 9:49a ssood
115 * SW7420-340: wait for signal lock before starting PSI acquisition
116 *
117 * 4   9/25/09 5:15p ssood
118 * SW7420-340: Add support for VSB frontend
119 *
120 * 3   9/17/09 2:58p ssood
121 * SW7420-340: compiling for SMS
122 *
123 * 2   9/16/09 12:07p ssood
124 * SW7420-340: header changes to include file history
125 *
126 ******************************************************************************/
127#include "nexus_platform.h"
128#if B_HAS_LIVE_STREAMING
129#include "nexus_frontend.h"
130#endif
131#include "nexus_parser_band.h"
132
133#include "nexus_pid_channel.h"
134#include "nexus_playpump.h"
135#include "nexus_message.h"
136#include "nexus_recpump.h"
137#include "nexus_record.h"
138#include "ip_psi.h"
139#include "b_playback_ip_lib.h"
140#include "b_os_lib.h"
141#include "b_os_lib.h"
142
143#include "b_psip_lib.h"
144#include "nexus_core_utils.h"
145
146#ifdef STREAMER_CABLECARD_SUPPORT
147#include "ip_strm_cablecard.h"
148#else
149#include <tspsimgr.h>
150#endif
151
152BDBG_MODULE(ip_psi);
153
154#undef MIN
155#define MIN(a,b)    ((a) < (b) ? (a) : (b))
156
157/* struct used to keep track of the si callback we must use, to notify
158   the si applib that it's previously requested data is now available */
159typedef struct siRequest_t
160{
161    B_PSIP_DataReadyCallback   callback;
162    void                   * callbackParam;
163} siRequest_t;
164
165/* we only have one filterHandle (i.e. msg), so we only have to keep track
166   of the current request from si (specifically, the si "data ready"
167   callback and associated param) */
168static siRequest_t g_siRequest;
169
170/* nexus message "data ready" callback - forward notification to si lib */
171static void DataReady(void * context, int param)
172{
173    BSTD_UNUSED(context);
174    BSTD_UNUSED(param);
175
176    if (NULL != g_siRequest.callback) {
177        /* printf("in DataReady callback - forward notification to psip lib\n");*/
178        g_siRequest.callback(g_siRequest.callbackParam);
179    }
180}
181
182/* message "data ready" callback which is called by si when our requested data
183   has been processed and is ready for retrieval */
184static void SiDataReady(B_Error status, void * context)
185{
186    /* printf("in APP DataReady callback - psip lib has finished processing data\n");*/
187    if (B_ERROR_SUCCESS == status) {
188        BKNI_SetEvent((BKNI_EventHandle)context);
189    } else {
190        BDBG_WRN(("problem receiving data from api call - error code:%d\n", status));
191        /* set event so our test app can continue... */
192        BKNI_SetEvent((BKNI_EventHandle)context);
193    }
194}
195
196/* utility function to convert si applib message filter to nexus message filter
197   assumes pNexusFilter has already been properly initialized with default values */
198static void cpyFilter(NEXUS_MessageFilter * pNexusFilter, B_PSIP_Filter * pSiFilter)
199{
200    int i = 0;
201
202    for (i = 0; i < MIN(B_PSIP_FILTER_SIZE, NEXUS_MESSAGE_FILTER_SIZE); i++)
203    {
204        if (i == 2) {
205            /* WARNING: will not filter message byte 2! */
206            continue;
207        } else
208            if (i >= 2) {
209                /* adjust nexus index see NEXUS_MessageFilter in nexus_message.h */
210                pNexusFilter->mask[i-1]        = pSiFilter->mask[i];
211                pNexusFilter->coefficient[i-1] = pSiFilter->coef[i];
212                pNexusFilter->exclusion[i-1]   = pSiFilter->excl[i];
213            } else {
214                pNexusFilter->mask[i]        = pSiFilter->mask[i];
215                pNexusFilter->coefficient[i] = pSiFilter->coef[i];
216                pNexusFilter->exclusion[i]   = pSiFilter->excl[i];
217            }
218    }
219}
220
221/* gets a pidchannel - nexus handles pid channel reuse automatically */
222NEXUS_PidChannelHandle OpenPidChannel(psiCollectionDataType * pCollectionData, uint16_t pid)
223{
224    int    i = 0;
225    NEXUS_PidChannelSettings pidChannelSettings;
226    NEXUS_PlaypumpOpenPidChannelSettings playpumpPidChannelSettings;
227
228    NEXUS_Playpump_GetDefaultOpenPidChannelSettings(&playpumpPidChannelSettings);
229
230    playpumpPidChannelSettings.pidSettings.requireMessageBuffer = true;
231    pidChannelSettings.requireMessageBuffer = true;
232    NEXUS_PidChannel_GetDefaultSettings(&pidChannelSettings);
233
234    for (i = 0; i < NUM_PID_CHANNELS; i++)
235    {
236        if (NULL == pCollectionData->pid[i].channel) {
237            BDBG_MSG(("open pidChannel for pid:0x%04x\n", pid));
238            pCollectionData->pid[i].num = pid; 
239            if (pCollectionData->srcType == IpStreamerSrc_eIp) {
240                pCollectionData->pid[i].channel = 
241                    NEXUS_Playpump_OpenPidChannel(pCollectionData->playpump, pid, &playpumpPidChannelSettings);
242            }
243            else {
244                pCollectionData->pid[i].channel = 
245                    NEXUS_PidChannel_Open(pCollectionData->parserBand, pid, &pidChannelSettings);
246            }
247            return pCollectionData->pid[i].channel;
248        }
249    }
250
251    if (i == NUM_PID_CHANNELS) {
252        BDBG_WRN(("failed to open pid channel:0x%04x - not enough storage space in pCollectionData!\n", pid));
253    }
254
255    return NULL;
256}
257
258/* closes a previously opened pid channel */
259void ClosePidChannel(psiCollectionDataType * pCollectionData, uint16_t pid)
260{
261    int i = 0;
262    bool found=false;
263
264    for (i = 0; i < NUM_PID_CHANNELS; i++)
265    {
266        /* find pid to close */
267        if (( pCollectionData->pid[i].num == pid) &&
268            ( pCollectionData->pid[i].channel != NULL)) {
269            BDBG_MSG(("close pidChannel for pid:0x%04x\n", pid));
270            if (pCollectionData->srcType == IpStreamerSrc_eIp)
271                NEXUS_Playpump_ClosePidChannel(pCollectionData->playpump, pCollectionData->pid[i].channel);
272            else 
273                NEXUS_PidChannel_Close(pCollectionData->pid[i].channel);
274            pCollectionData->pid[i].channel = NULL;
275            pCollectionData->pid[i].num = 0;
276            found = true;
277            break;
278        }
279    }
280    if (!found)
281        BDBG_WRN(("failure closing pid channel:0x%04x - not found in list\n", pid));
282}
283
284void StartMessageFilter(psiCollectionDataType * pCollectionData, B_PSIP_CollectionRequest * pRequest, NEXUS_PidChannelHandle pidChannel)
285{
286    NEXUS_MessageHandle          msg;
287    NEXUS_MessageStartSettings   msgStartSettings;
288
289    BSTD_UNUSED(pCollectionData);
290    msg = (NEXUS_MessageHandle)pRequest->filterHandle;
291    /* printf("StartMessageFilter\n");*/
292
293    NEXUS_Message_GetDefaultStartSettings(msg, &msgStartSettings);
294    msgStartSettings.bufferMode = NEXUS_MessageBufferMode_eOneMessage;
295    msgStartSettings.pidChannel = pidChannel;
296    cpyFilter(&msgStartSettings.filter, &pRequest->filter);
297
298    NEXUS_Message_Start(msg, &msgStartSettings);
299    NEXUS_StartCallbacks(msg);
300}
301
302void StopMessageFilter(psiCollectionDataType * pCollectionData, B_PSIP_CollectionRequest * pRequest)
303{
304    NEXUS_MessageHandle          msg;
305    BSTD_UNUSED(pCollectionData);
306
307    /* printf("StopMessageFilter\n"); */
308    msg = (NEXUS_MessageHandle)pRequest->filterHandle;
309    NEXUS_StopCallbacks(msg);
310    NEXUS_Message_Stop(msg);
311}
312
313/* callback function called by si applib to collect si data */
314static B_Error CollectionFunc(B_PSIP_CollectionRequest * pRequest, void * context)
315{
316
317    NEXUS_PidChannelHandle pidChannel = NULL;
318    pPsiCollectionDataType  pCollectionData = (pPsiCollectionDataType)context;
319    NEXUS_MessageHandle          msg;
320
321    BDBG_ASSERT(NULL != pRequest);
322    BDBG_ASSERT(NULL != context);
323    msg = (NEXUS_MessageHandle)pRequest->filterHandle;
324    if (NULL == msg) {
325        BDBG_WRN(("invalid filterHandle received from SI applib!\n"));
326        return B_ERROR_INVALID_PARAMETER;
327    }
328
329    switch (pRequest->cmd)
330    {
331        const uint8_t  * buffer;
332        size_t             size;
333
334    case B_PSIP_eCollectStart:
335        BDBG_MSG(("-=-=- B_PSIP_eCollectStart -=-=-\n"));
336
337        /*
338         * Save off pRequest->callback and pRequest->callbackParam.
339         * these need to be called when DataReady() is called.  this will
340         * notify the si lib that it can begin processing the received data.
341         * Si applib only allows us to call one API at a time (per filterHandle),
342         * so we only have to keep track of the latest siRequest.callback
343         * and siRequest.callbackParam (for our one and only filterHandle).
344         */
345        g_siRequest.callback      = pRequest->callback;
346        g_siRequest.callbackParam = pRequest->callbackParam;
347
348        pidChannel = OpenPidChannel(pCollectionData, pRequest->pid);
349        StartMessageFilter(pCollectionData, pRequest, pidChannel);
350        break;
351
352    case B_PSIP_eCollectStop:
353        BDBG_MSG(("-=-=- B_PSIP_eCollectStop -=-=-\n"));
354        StopMessageFilter(pCollectionData, pRequest);
355        ClosePidChannel(pCollectionData, pRequest->pid);
356        break;
357
358    case B_PSIP_eCollectGetBuffer:
359        BDBG_MSG(("-=-=- B_PSIP_eCollectGetBuffer -=-=-\n"));
360        /* fall through for now... */
361
362    case B_PSIP_eCollectCopyBuffer:
363        /*printf("-=-=- B_PSIP_eCollectCopyBuffer -=-=-\n");*/
364        if (NEXUS_SUCCESS == NEXUS_Message_GetBuffer(msg, (const void **)&buffer, &size)) {
365            if (0 < size) {
366                BDBG_MSG(("NEXUS_Message_GetBuffer() succeeded! size:%d\n",size));
367                memcpy(pRequest->pBuffer, buffer, *(pRequest->pBufferLength)); /* copy valid data to request buffer */
368                *(pRequest->pBufferLength) = MIN(*(pRequest->pBufferLength), size);
369                NEXUS_Message_ReadComplete(msg, size);
370            } else {
371                /* NEXUS_Message_GetBuffer can return size==0 (this is normal
372                 * operation).  We will simply wait for the next data ready
373                 * notification by returning a B_ERROR_RETRY to the PSIP applib
374                 */
375                NEXUS_Message_ReadComplete(msg, size);
376                return B_ERROR_PSIP_RETRY;
377            }
378        }
379        else {
380            BDBG_WRN(("NEXUS_Message_GetBuffer() failed\n"));
381
382            return B_ERROR_UNKNOWN;
383        }
384        break;
385
386    default:
387        BDBG_WRN(("-=-=- invalid Command received:%d -=-=-\n", pRequest->cmd));
388        return B_ERROR_INVALID_PARAMETER;
389        break;
390    }
391
392    return B_ERROR_SUCCESS;
393}
394
395/* convertStreamToPsi                            */
396/* Fills in B_PlaybackIpPsiInfo based on PMT info */
397static void convertStreamToPsi( TS_PMT_stream *stream, B_PlaybackIpPsiInfo *psi)
398{
399    psi->mpegType = NEXUS_TransportType_eTs;
400    switch (stream->stream_type) {
401        case TS_PSI_ST_13818_2_Video:
402        case TS_PSI_ST_ATSC_Video:
403            psi->videoCodec = NEXUS_VideoCodec_eMpeg2;
404            psi->videoPid = stream->elementary_PID; 
405            psi->psiValid = true;
406            break;
407        case TS_PSI_ST_11172_2_Video:
408            psi->videoCodec = NEXUS_VideoCodec_eMpeg1;
409            psi->videoPid = stream->elementary_PID; 
410            psi->psiValid = true;
411            break;
412        case TS_PSI_ST_14496_10_Video:
413            psi->videoCodec = NEXUS_VideoCodec_eH264;
414            psi->videoPid = stream->elementary_PID; 
415            psi->psiValid = true;
416            break;
417        case TS_PSI_ST_11172_3_Audio:
418        case TS_PSI_ST_13818_3_Audio:
419            psi->audioCodec = NEXUS_AudioCodec_eMpeg;
420            psi->audioPid = stream->elementary_PID; 
421            psi->psiValid = true;
422            break;
423        case TS_PSI_ST_ATSC_AC3:
424            psi->audioCodec = NEXUS_AudioCodec_eAc3;
425            psi->audioPid = stream->elementary_PID; 
426            psi->psiValid = true;
427            break;
428        case TS_PSI_ST_ATSC_EAC3:
429            psi->audioCodec = NEXUS_AudioCodec_eAc3Plus;
430            psi->audioPid = stream->elementary_PID; 
431            psi->psiValid = true;
432            break;
433        case TS_PSI_ST_13818_7_AAC:
434            psi->audioCodec = NEXUS_AudioCodec_eAac;
435            psi->audioPid = stream->elementary_PID; 
436            psi->psiValid = true;
437            break;
438        case TS_PSI_ST_14496_3_Audio:
439            psi->audioCodec = NEXUS_AudioCodec_eAacPlus;
440            psi->audioPid = stream->elementary_PID; 
441            psi->psiValid = true;
442            break;
443        default:
444            BDBG_WRN(("###### TODO: Unknown stream type: %x #####", stream->stream_type));
445    }
446}
447
448#ifndef STREAMER_CABLECARD_SUPPORT
449static void 
450tsPsi_procProgDescriptors( const uint8_t *p_bfr, unsigned bfrSize, PROGRAM_INFO_T *progInfo )
451{
452    int i;
453    TS_PSI_descriptor descriptor;
454
455    for( i = 0, descriptor = TS_PMT_getDescriptor( p_bfr, bfrSize, i );
456        descriptor != NULL;
457        i++, descriptor = TS_PMT_getDescriptor( p_bfr, bfrSize, i ) )
458    {
459        switch (descriptor[0])
460        {
461        case TS_PSI_DT_CA:
462            progInfo->ca_pid = ((descriptor[4] & 0x1F) << 8) + descriptor[5];
463            break;
464
465        default:
466            break;
467        }
468    }
469}
470
471static void 
472tsPsi_procStreamDescriptors( const uint8_t *p_bfr, unsigned bfrSize, int streamNum, EPID *ePidData )
473{
474    int i;
475    TS_PSI_descriptor descriptor;
476
477    for( i = 0, descriptor = TS_PMT_getStreamDescriptor( p_bfr, bfrSize, streamNum, i );
478        descriptor != NULL;
479        i++, descriptor = TS_PMT_getStreamDescriptor( p_bfr, bfrSize, streamNum, i ) )
480    {
481        switch (descriptor[0])
482        {
483        case TS_PSI_DT_CA:
484            ePidData->ca_pid = ((descriptor[4] & 0x1F) << 8) + descriptor[5];
485            break;
486
487        default:
488            break;
489        }
490    }
491}
492#endif
493
494#if B_HAS_LIVE_STREAMING
495#define UNLOCK_TIMEOUT 300
496#define SCAN_TIMEOUT 3000
497static bool
498checkNexusQamLockStatus(NEXUS_FrontendHandle frontendHandle, BKNI_EventHandle signalLockedEvent)
499{
500    NEXUS_FrontendFastStatus fastStatus;
501    NEXUS_FrontendQamScanStatus scanStatus;
502
503    /* wait for the first unlock callback */
504    if (BKNI_WaitForEvent(signalLockedEvent, UNLOCK_TIMEOUT)) {
505        BDBG_WRN(("%s: failed to get the unlock callback...", __FUNCTION__));
506        return false;
507    }
508    BDBG_MSG(("%s: got first unlock callback", __FUNCTION__));
509
510    /* now wait for scan to complete */
511    if (BKNI_WaitForEvent(signalLockedEvent, SCAN_TIMEOUT)) {
512        BDBG_WRN(("%s: failed to lock the signal for scan completion...", __FUNCTION__));
513        return false;
514    }
515    BDBG_MSG(("%s: scan is complete", __FUNCTION__));
516
517    if (NEXUS_Frontend_GetFastStatus(frontendHandle, &fastStatus) != NEXUS_SUCCESS) {
518        BDBG_ERR(("%s: unrecognized NEXUS_Frontend_GetFastStatus", __FUNCTION__));
519        return false;
520    }
521    if (fastStatus.lockStatus == NEXUS_FrontendLockStatus_eLocked) {
522        NEXUS_Frontend_GetQamScanStatus(frontendHandle, &scanStatus);
523        BDBG_MSG(("%s: QAM frontent locked: Scan Status: SymbolRate %d, Acquisition Status %d",  __FUNCTION__, scanStatus.symbolRate, scanStatus.acquisitionStatus));
524        return true;
525    }
526    else if (fastStatus.lockStatus == NEXUS_FrontendLockStatus_eUnlocked) {
527        BDBG_ERR(("%s: can't get the lock", __FUNCTION__));
528        return false;
529    }
530    else if (fastStatus.lockStatus == NEXUS_FrontendLockStatus_eNoSignal) {
531        BDBG_ERR(("%s: no signal at this freq", __FUNCTION__));
532        return false;
533    }
534    else {
535        BDBG_ERR(("%s: unrecognized NEXUS_Frontend_GetFastStatus", __FUNCTION__));
536        return false;
537    }
538    return false;
539}
540#endif
541
542/*                                                         */
543/* This function returns first stream (video and/or audio) */ 
544/* To return multiple streams, remove stream found and     */
545/* pass a ptr to array of psi structures.                  */
546/*                                                         */
547void acquirePsiInfo(pPsiCollectionDataType pCollectionData, B_PlaybackIpPsiInfo *psi, int *numProgramsFound)
548{
549
550    B_Error                    errCode;
551    NEXUS_MessageSettings      settings;
552    NEXUS_MessageHandle        msg = NULL;
553    B_PSIP_Handle si = NULL;
554    B_PSIP_Settings si_settings;
555    B_PSIP_ApiSettings settingsApi;
556    TS_PMT_stream stream;
557    TS_PAT_program program;
558    uint8_t  i,j; 
559    uint8_t  buf[4096];
560    uint32_t bufLength = 4096;
561    uint8_t  bufPMT[4096];
562    uint32_t bufPMTLength = 4096;
563    NEXUS_Error rc;
564    B_PlaybackIpSessionStartSettings ipStartSettings;
565    B_PlaybackIpSessionStartStatus ipStartStatus;
566    BKNI_EventHandle dataReadyEvent = NULL;
567#ifndef STREAMER_CABLECARD_SUPPORT
568    PROGRAM_INFO_T programInfo;
569    BKNI_Memset(&programInfo, 0, sizeof(programInfo));
570    EPID epid;
571#endif
572
573    /* ----------------------------------------------------------------------------------------------------------------*/
574    /* Start stream  */
575    *numProgramsFound = 0;
576    if (pCollectionData->srcType == IpStreamerSrc_eIp) {
577        /* start playpump */
578        rc = NEXUS_Playpump_Start(pCollectionData->playpump);
579        if (rc) {BDBG_ERR(("PSI - NEXUS Error (%d) at %d \n", rc, __LINE__)); return;}
580        /* let IP Applib go ... */
581        memset(&ipStartSettings, 0, sizeof(ipStartSettings));
582        /* Since PAT/PMT based PSI discovery is only done for Live UDP/RTP/RTSP sessions, so we only need to set the playpump handle */
583        ipStartSettings.nexusHandles.playpump = pCollectionData->playpump;
584        ipStartSettings.nexusHandlesValid = true;
585        ipStartSettings.u.rtsp.mediaTransportProtocol = B_PlaybackIpProtocol_eRtp;  /* protocol used to carry actual media */
586        rc = B_PlaybackIp_SessionStart(pCollectionData->playbackIp, &ipStartSettings, &ipStartStatus);
587        while (rc == B_ERROR_IN_PROGRESS) {
588            /* app can do some useful work while SessionSetup is in progress and resume when callback sends the completion event */
589            BDBG_WRN(("Session Start call in progress, sleeping for now..."));
590            BKNI_Sleep(100);
591            rc = B_PlaybackIp_SessionStart(pCollectionData->playbackIp, &ipStartSettings, &ipStartStatus);
592        }
593        if (rc) {BDBG_ERR(("PSI - NEXUS Error (%d) at %d\n", rc, __LINE__)); return;}
594    }
595#if B_HAS_LIVE_STREAMING
596    else if (pCollectionData->srcType == IpStreamerSrc_eQam) {
597        BKNI_ResetEvent(pCollectionData->signalLockedEvent);
598        rc = NEXUS_Frontend_TuneQam(pCollectionData->frontend, pCollectionData->qamSettings);
599        if (rc) {
600            BDBG_ERR(("PSI - NEXUS Error (%d) at %d\n", rc, __LINE__));
601            return;
602        }
603        if (checkNexusQamLockStatus(pCollectionData->frontend, pCollectionData->signalLockedEvent) == false) {
604            BDBG_WRN(("QAM Src failed to lock the signal during PSI acquisition...\n"));
605            return;
606        }
607        BDBG_MSG(("%s: QAM Src locked the signal during PSI acquisition...", __FUNCTION__));
608        /* continue below */
609    }
610    else if (pCollectionData->srcType == IpStreamerSrc_eSat) {
611        BDBG_MSG(("%s: Sat Freq %d, symbolRate %d, mode %d", __FUNCTION__, 
612                    pCollectionData->satSettings->frequency, pCollectionData->satSettings->symbolRate, pCollectionData->satSettings->mode));
613        rc = NEXUS_Frontend_TuneSatellite(pCollectionData->frontend, pCollectionData->satSettings);
614        if (rc) {BDBG_ERR(("PSI - NEXUS Error (%d) at %d\n", rc, __LINE__)); return;}
615        BDBG_MSG(("%s: Sat Src locked the signal during PSI acquisition...", __FUNCTION__));
616        if (BKNI_WaitForEvent(pCollectionData->signalLockedEvent, 10000)) {
617            BDBG_WRN(("Sat Src failed to lock the signal during PSI acquisition...\n"));
618            return;
619        }
620    }
621    else if (pCollectionData->srcType == IpStreamerSrc_eVsb) {
622        rc = NEXUS_Frontend_TuneVsb(pCollectionData->frontend, pCollectionData->vsbSettings);
623        if (rc) {BDBG_ERR(("PSI - NEXUS Error (%d) at %d\n", rc, __LINE__)); return;}
624        if (BKNI_WaitForEvent(pCollectionData->signalLockedEvent, 5000)) {
625            BDBG_WRN(("failed to lock the signal during PSI acquisition...\n"));
626            return;
627        }
628    }
629#endif
630    else {
631        BDBG_WRN(("%s: doesn't support PSI discovery for this %d src type", __FUNCTION__, pCollectionData->srcType));
632        return;
633    }
634
635    if (BKNI_CreateEvent(&dataReadyEvent) != BERR_SUCCESS) { BDBG_ERR(("Failed to create PSI dataReadyEvent \n")); goto error; }
636
637    NEXUS_Message_GetDefaultSettings(&settings);
638    settings.dataReady.callback = DataReady; 
639    settings.dataReady.context = NULL;
640    msg = NEXUS_Message_Open(&settings);
641    if (!msg) { BDBG_ERR(("PSI - NEXUS_Message_Open failed\n")); goto error; }
642
643    B_PSIP_GetDefaultSettings(&si_settings);
644    si_settings.PatTimeout = 500;
645    si_settings.PmtTimeout = 500;
646    si = B_PSIP_Open(&si_settings, CollectionFunc, pCollectionData);
647    if (!si) { BDBG_ERR(("PSI - Unable to open SI applib\n")); goto error; }
648
649    BDBG_MSG(("starting PSI gathering\n"));
650    errCode = B_PSIP_Start(si);
651    if ( errCode ) { BDBG_ERR(("PSI - Unable to start SI data collection, err %d\n", errCode)); goto error; }
652
653
654    B_PSIP_GetDefaultApiSettings(&settingsApi);
655    settingsApi.siHandle                 = si;
656    settingsApi.filterHandle             = msg;
657    settingsApi.dataReadyCallback        = SiDataReady;
658    settingsApi.dataReadyCallbackParam   = dataReadyEvent;
659    settingsApi.timeout                  = 65000; 
660
661    memset(buf, 0, sizeof(buf));
662    BKNI_ResetEvent((BKNI_EventHandle)settingsApi.dataReadyCallbackParam);
663    if (B_ERROR_SUCCESS != B_PSIP_GetPAT(&settingsApi, buf, &bufLength)) {
664        BDBG_ERR(("B_PSIP_GetPAT() failed\n"));
665        goto error;
666    }
667
668    /* wait for async response from si - wait on dataReadyEvent */
669    BKNI_WaitForEvent((BKNI_EventHandle)settingsApi.dataReadyCallbackParam, BKNI_INFINITE);
670    BDBG_MSG(("received response from SI, len = %d!\n", bufLength));
671#if 0
672    printf("\n"); for (i=0;i<bufLength;i++) printf("%02x ",buf[i]); printf("\n");
673#endif
674
675    if (0 < bufLength) {
676        BDBG_MSG(("PAT Programs found = %d\n", TS_PAT_getNumPrograms(buf)));
677        for (i = 0; i<MAX_PROGRAMS_PER_FREQUENCY && (TS_PAT_getProgram(buf, bufLength, i, &program)==BERR_SUCCESS); i++) 
678        {
679            memset(psi, 0, sizeof(*psi));
680            BDBG_MSG(("program_number: %d, i %d, PID: 0x%04X, psi %p, sizeof psi %d\n", program.program_number, i, program.PID, psi, sizeof(*psi))); 
681            psi->pmtPid = program.PID;
682
683            BKNI_ResetEvent((BKNI_EventHandle)settingsApi.dataReadyCallbackParam);
684            memset(bufPMT, 0, sizeof(bufPMT));
685            if (B_ERROR_SUCCESS != B_PSIP_GetPMT(&settingsApi, program.PID, bufPMT, &bufPMTLength)) {
686                BDBG_ERR(("B_PSIP_GetPMT() failed\n"));
687                continue;
688            }
689            /* wait for async response from si - wait on dataReadyEvent */
690            BKNI_WaitForEvent((BKNI_EventHandle)settingsApi.dataReadyCallbackParam, BKNI_INFINITE);
691            BDBG_MSG(("received PMT: size:%d, # of streams in this program %d\n", bufPMTLength, TS_PMT_getNumStreams(bufPMT, bufPMTLength)));
692#ifndef STREAMER_CABLECARD_SUPPORT
693            /* find and process Program descriptors */
694            tsPsi_procProgDescriptors(bufPMT, bufPMTLength, &programInfo);
695            if (programInfo.ca_pid) {
696                BDBG_WRN(("Program # %d, pid 0x%x is encrypted, ca_pid 0x%x, ignore it", program.program_number, program.PID, programInfo.ca_pid));
697                continue;
698            }
699#endif
700            if (0 < bufPMTLength) {
701                for (j = 0; j < TS_PMT_getNumStreams(bufPMT, bufPMTLength); j++)
702                {
703                    memset(&stream, 0, sizeof(stream));
704                    TS_PMT_getStream(bufPMT, bufPMTLength, j, &stream);
705                    BDBG_MSG(("j %d, stream_type:0x%02X, PID:0x%04X\n", j, stream.stream_type, stream.elementary_PID));
706                    convertStreamToPsi( &stream, psi);
707#ifdef STREAMER_CABLECARD_SUPPORT
708                    memcpy(psi->pmtBuffer, bufPMT, bufPMTLength);
709                    psi->pmtBufferSize = bufPMTLength;
710#else
711                    memset(&epid, 0, sizeof(epid));
712                    tsPsi_procStreamDescriptors(bufPMT, bufPMTLength, j, &epid);
713                    if (epid.ca_pid) {
714                        BDBG_WRN(("program 0x%x has ca pid 0x%x, ignore it", program.PID, epid.ca_pid));
715                        break;
716                    }
717#endif
718                    psi->pcrPid = TS_PMT_getPcrPid(bufPMT, bufPMTLength);
719                    if ((psi->videoPid ) && (psi->audioPid )) {
720                        (*numProgramsFound)++;
721                        BDBG_WRN(("Found %d program, vpid %d, vcodec %d, apid %d, acodec %d", *numProgramsFound, psi->videoPid, psi->videoCodec, psi->audioPid, psi->audioCodec));
722                        psi += 1;
723                        break;
724                    }
725                    else if (j == (TS_PMT_getNumStreams(bufPMT, bufPMTLength)-1)) {
726                        /* last stream in the program */
727                        if ((psi->videoPid ) || (psi->audioPid )) {
728                            (*numProgramsFound)++;
729                            BDBG_WRN(("Found %d program, vpid %d or apid %d", *numProgramsFound, psi->videoPid, psi->audioPid));
730                            psi += 1;
731                            break;
732                        }
733                    }
734                }
735            }
736        }
737    }
738    BDBG_MSG(("stopping PSI gathering\n"));
739
740    if (pCollectionData->srcType == IpStreamerSrc_eIp) {
741        B_PlaybackIp_SessionStop(pCollectionData->playbackIp);
742        NEXUS_Playpump_Stop(pCollectionData->playpump);
743    }
744
745    /* cleanup */
746    B_PSIP_Stop(si);
747error:
748    if (si)
749        B_PSIP_Close(si);
750    if (msg)
751        NEXUS_Message_Close(msg);
752    if (dataReadyEvent)
753        BKNI_DestroyEvent(dataReadyEvent);
754}
Note: See TracBrowser for help on using the repository browser.