/*************************************************************************** * Copyright (c) 2002, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: bcmDccTransport.c $ * $brcm_Revision: \main\SanJose_MSTV_Devel\1 $ * $brcm_Date: 3/12/02 4:45p $ * * Module Description: * * Revision History: * * $brcm_Log: $ * * \main\SanJose_MSTV_Devel\1 3/12/02 4:45p erikg * Merge from SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38 * * \main\SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38\5 3/12/02 3:59p erikg * fleshed out _QueryDetectedFormats * * \main\SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38\4 3/12/02 2:57p erikg * debugged using base platform * * \main\SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38\3 3/7/02 4:21p erikg * more fleshing out * * \main\SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38\2 3/6/02 2:21p erikg * fleshed out some of the functions * * \main\SanJose_MSTV_Devel_erikg_mpegccxport2_2002_03_06_1118_38\1 3/6/02 11:29a erikg * new source files * ***************************************************************************/ /***************************************************************************/ /* E X A M P L E S O U R C E C O D E */ /* B E G I N */ #if 0 EDeviceErrCode eDevError ; unsigned long ulMainSize ; unsigned long ulMainErrorFlag ; unsigned long ulMainPicInfo ; unsigned char * pCCMainBuffer ; DCC_OUTBUF_INFO CC608BufInfo ; unsigned char * pCCPair ; unsigned int NumCCPairs ; unsigned int pair ; do { /* * Get a pointer into the ring buffer for the next * user data. The pointer is valid until we call * bcmMPIUpdateClosedCaptionStatus(). */ eDevError = bcmMPIReadClosedCaptionStatus( pDevice, /* MPEG device */ &m_MpegCCaptionHandle, /* CC handle */ &pCCMainBuffer, /* ptr returned here */ &ulMainSize, /* size returned here */ &ulMainErrorFlag, /* error returned here */ &ulMainPicInfo) ; /* info returned here */ if ( eDevError != eDeviceSuccess ) { /* handle error condition */ } if ( ulMainErrorFlag ) { /* handle error condition */ } /* * Did we get anything? If so, parse it and * queue up the Closed Captioning for encode. */ if ( ulMainSize ) { /* * Parse the Picture User Data area(s) returned * the the bcmMPIReadClosedCaptionStatus() call. */ dccerr = DccTransport_Process( pTransObj, /* transport object */ pCCMainBuffer, /* pInputBuf */ ulMainSize, /* InputBufSize */ //ulMainPicInfo, /* picture info */ &CC608BufInfo, /* 608 output buf descriptor */ NULL) ; /* DTVCC output buf descriptor */ if ( dccerr != dccSuccess ) { /* handle error condition */ } /* * Queue up the 608 data for encoding later by the ISR. * DccTransport_Process gives us data in groups of 3 * bytes. The first is an indicator of which field. * The next two bytes are the CC data pair. */ NumCCPairs = CC608BufInfo.OutputBytesProduced / 3 ; for ( pair=0 ; pair < NumCCPairs ; pair++) { if ( CC608BufInfo.pOutputBuf[pair*3] == DCC_608_FIELD_TOP ) ulField = CC_QUEUE_FLAG_TOP : else ulField = CC_QUEUE_FLAG_BOTTOM : pCCPair = &CC608BufInfo.pOutputBuf[pair*3+1] ; ok = bCCEQueueAdd( eCCE_VEC1, /* which VEC */ ulField, /* which field */ pCCPair) ; /* 2 CC bytes */ } /* * Relinquish access to the buffer. */ bcmMPIUpdateClosedCaptionStatus( pDevice, /* MPEG device */ &m_MpegCCaptionHandle, /* CC handle */ pCCMainBuffer) ; /* buffer ptr */ } /* end if ( ulMainSize ) */ } while ( ulMainSize ) ; #endif /* E N D */ /* E X A M P L E S O U R C E C O D E */ /***************************************************************************/ #include "bcmDccTransport.h" #include "bcmDccPriv.h" #include "bcmDccTransportParse.h" /************************************************************************** * * Function: DccTransport_Init * * Inputs: * pObj - object to init * OutputType - defines which 608 CC type to output * * Outputs: * pObj - object state is modified * * Returns: dccSuccess or a standard DCCERR error code * * Description: * * This function initializes an MPEG CC transport session. * **************************************************************************/ DCCERR DccTransport_Init( DCC_TRANSPORT_OBJECT * pObj, DCC_CC608_TYPE OutputType) { /* * Validate */ if ( NULL == pObj ) { DccPrintf(("DccTransport_Init: null pointer as argument\n")) ; return(dccErrNullPointer) ; } /* * Set the 608 output type. */ switch ( OutputType ) { case CC608_A53 : case CC608_DVS157 : case CC608_A53Preferred : pObj->CC608Type = OutputType ; break ; default : DccPrintf(("DccTransport_Init: bad OutputType 0x%08x\n", OutputType)) ; return(dccErrBadOutputType) ; break ; } /* * Initialize the MUX state. This essentially * zeroes out all of the type counters. */ CC608Mux_Init(&pObj->CC608MuxState) ; /* * all done */ return(dccSuccess) ; } /* DccTransport_Init */ /************************************************************************** * * Function: DccTransport_Fini * * Inputs: * pObj - object, previously init'ed * * Outputs: * * * Returns: dccSuccess or a standard DCCERR error code * * Description: * * This function undoes the initialization done by DccTransport_Init. * **************************************************************************/ DCCERR DccTransport_Fini(DCC_TRANSPORT_OBJECT * pObj) { /* nothing to do */ return(dccSuccess) ; } /* DccTransport_Fini */ /************************************************************************** * * Function: DccTransport_Process * * Inputs: * pObj - object, previously init'ed * pInputBuf - input buffer, holds 1/more User Data * InputBufSize - size in bytes of input buffer * ulPicInfo - picture info from bcmMPIReadCCStatus * * Outputs: * p608BufInfo - describes output buf for 608, or NULL * pDTVCCBufInfo - describes output buf for DTVCC, or NULL * * Returns: dccSuccess or a standard DCCERR error code * * Description: * * Reads the input buffer and copies CC data to the output buffer(s). This * function parses the looking for DTVCC Closed Captioning data or the type * of 608 CC data specified in the DccTransport_Init function. This function * scans up to InputBufSize bytes of the pInputBuf buffer. The parsing logic * looks for Picture User Data start_codes, namely, the byte sequence 00 00 01 B2. * * If multiple Picture User Data areas are found, each will be processed in order, * and the CC bytes extracted from each will be copied to the output buffer(s). If * DTVCC Closed Captioning data is found and if pDTVCCBufInfo is not NULL, then * DTVCC data is parsed and copied to pDTVCCBufInfo. * * If p608BufInfo is not NULL, then this function will copy 608 Closed Captioning * data according to the OutputType argument in the DccTransport_Init( ) call: * * CC608_A53: Only valid CC bytes from ATSC A/53 will be output. * CC608_DVS157: Only valid CC Bytes from DVS157 will be output. * CC608_A53Preferred: This function will track the presence of both A53 * and DVS157 formats. If only one format is detected, * it will be output. If both formats are detected, A53 * will be output. This algorithm uses a sliding window * approach. * **************************************************************************/ DCCERR DccTransport_Process( DCC_TRANSPORT_OBJECT * pObj, unsigned char * pInputBuf, unsigned int InputBufSize, //unsigned long ulPicInfo, DCC_OUTBUF_INFO * p608BufInfo, DCC_OUTBUF_INFO * pDTVCCBufInfo) { DCCERR dccerr = dccSuccess ; unsigned int StartCodeIndex ; unsigned char * pInputCur = pInputBuf ; unsigned int InputCurSize = InputBufSize ; /* * Validate Arguments */ if ( pObj == NULL || pInputBuf == NULL ) { DccPrintf(("DccTransport_Process: null pointer as argument\n")) ; return(dccErrNullPointer) ; } /* * Prep output buffers. */ if ( p608BufInfo ) { p608BufInfo->OutputBytesProduced = 0 ; p608BufInfo->DccError = dccSuccess ; } if ( pDTVCCBufInfo ) { pDTVCCBufInfo->OutputBytesProduced = 0 ; pDTVCCBufInfo->DccError = dccSuccess ; } /* * Subtract from each type counter. */ CC608Mux_LeakAll(&pObj->CC608MuxState) ; /* * Loop thru for each user data area. Note that each * is delineated by a 4-byte start code. */ while ( NextStartCode(pInputCur, InputCurSize, &StartCodeIndex) ) { /* move to the start code, and just beyond it */ pInputCur += (StartCodeIndex + 4) ; InputCurSize -= (StartCodeIndex + 4) ; /* * Call ParsePicUserDataForCC to do the * real work. If it returns an error (dccerr) * it's such that we can't continue, so break out. */ dccerr = ParseOnePicUserDataForCC( pObj, /* transport session object */ pInputCur, /* input buffer, remaining */ InputCurSize, /* input buffer size, remaining */ // ulPicInfo, /* picture info from MPEG UD extraction call */ p608BufInfo, /* output buffer info for 608 type */ pDTVCCBufInfo) ; /* output buffer info for DTVCC type */ if ( dccerr ) { DccPrintf(("DccTransport_Process: parsing error 0x%08x\n", dccerr)) ; break ; } } /* end while ( find_next_start_code ) */ return(dccerr) ; } /* DccTransport_Process */ /************************************************************************** * * Function: DccTransport_QueryDetectedFormats * * Inputs: * pObj - object, previously init'ed * * Outputs: * pDetectedFormats - bitmask, each bit reps one format * DCC_TYPE_DVS157 * DCC_TYPE_A53_608 * DCC_TYPE_A53_DTVCC * DCC_TYPE_UNKNOWN * * Returns: dccSuccess or a standard DCCERR error code * * Description: * * This function retrieves a bitmask representing which formats have been * detected in the stream. This is useful because on any call to * DccTransport_Process, the caller cannot merely look at the number of bytes * output for each output buffer to determine the detected formats. * **************************************************************************/ DCCERR DccTransport_QueryDetectedFormats( DCC_TRANSPORT_OBJECT * pObj, unsigned int * pDetectedFormats) { /* * validate */ if ( NULL == pObj || NULL == pDetectedFormats ) { DccPrintf(("DccTransport_QueryDetectedFormats: null pointer as argument\n")) ; return(dccErrNullPointer) ; } /* * clear the bitmask */ *pDetectedFormats = 0 ; /* * set each bit as appropriate */ if ( CC608Mux_IsDetected(&pObj->CC608MuxState, cctDVS157) ) *pDetectedFormats |= DCC_TYPE_DVS157 ; if ( CC608Mux_IsDetected(&pObj->CC608MuxState, cctA053_608) ) *pDetectedFormats |= DCC_TYPE_A53_608 ; if ( CC608Mux_IsDetected(&pObj->CC608MuxState, cctA053_DTVCC) ) *pDetectedFormats |= DCC_TYPE_A53_DTVCC ; if ( CC608Mux_IsDetected(&pObj->CC608MuxState, cctUnknown) ) *pDetectedFormats |= DCC_TYPE_UNKNOWN ; return(dccSuccess) ; } /* DccTransport_QueryDetectedFormats */