source: svn/newcon3bcm2_21bu/magnum/commonutils/udp/budp_dccparse_dss.c @ 76

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

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

  • Property svn:executable set to *
File size: 15.3 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2010, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: budp_dccparse_dss.c $
11 * $brcm_Revision: Hydra_Software_Devel/2 $
12 * $brcm_Date: 10/28/10 3:59p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/commonutils/udp/budp_dccparse_dss.c $
19 *
20 * Hydra_Software_Devel/2   10/28/10 3:59p darnstein
21 * SW3548-2364: trivial implementation of _isr functions for parsing.
22 *
23 * Hydra_Software_Devel/1   10/21/10 4:09p darnstein
24 * SW7401-2571: DSS parser, converted from BVBIlib to BUDP.
25 *
26 ***************************************************************************/
27
28/* For debugging */
29/* #define BUDP_DSS_GETUD_DUMP 1 */
30#include "bstd.h"
31#include "bavc.h"
32#include "bdbg.h"
33#include "budp_bitread.h"
34#include "budp_dccparse.h"
35#include "budp_dccparse_dss.h"
36#include "bdbg.h"
37
38BDBG_MODULE(BUDP_dss);
39
40static const bool bByteswap = (BSTD_CPU_ENDIAN == BSTD_ENDIAN_LITTLE);
41
42static BERR_Code ParseDSSData (
43        BUDP_Bitread_Context* pReader,
44        size_t                                   length,
45        size_t*                  pBytesParsed,
46        uint8_t*                 pcc_count,
47        BUDP_DCCparse_dss_cc_subtitle* pCCdata,
48        uint8_t*                 psubtitle_count,
49        BUDP_DCCparse_dss_cc_subtitle* pSubtitledata);
50static size_t FindMpegUserdataStart (
51        BUDP_Bitread_Context* pREader, size_t length);
52
53#ifdef BUDP_DSS_GETUD_DUMP
54static void dss_dump_getud (
55        const BAVC_USERDATA_info* pUserdata_info, size_t offset);
56#endif
57
58#ifdef DIRECTV_SKY
59#define ATSC_CC_DATA_FLG                        0x40
60#define ATSC_CC_DATA_CNT                        0x1f
61#define ATSC_ADDITIONAL_DATA_FLG        0x20
62#define ATSC_CC_DATA_VALID              0x04
63#define ATSC_CC_DATA_TYPE               0x03
64#define ATSC_CC_FIELD_1                 0x00
65#define ATSC_CC_FIELD_2                 0x01
66#define ATSC_CC_A53_IDENTIFIER(buf)\
67        ((*(buf) == 0x47) && (*((buf)+1) == 0x41) && (*((buf)+2) == 0x39) && (*((buf)+3) == 0x34))
68
69#define ATSC_CC_A53_ADDITIONAL_CODE(buf)\
70        ((*(buf) == 0x0) && (*((buf)+1) == 0x0) && (*((buf)+2) == 0x01))
71       
72static BERR_Code ParseATSCA53Data (
73        uint8_t         *pUserData,
74        size_t          length,
75        size_t          *pBytesParsedSub,
76        uint8_t         *pcc_count,
77        BUDP_DCCparse_dss_cc_subtitle* pCCdata
78);
79#endif /* DIRECTV_SKY */
80
81/***************************************************************************
82 * This function parses DSS SD user data.  It assumes that the userdata
83 * startcode 0x000001B2 has just been read.
84 */
85static BERR_Code ParseDSSData (
86        BUDP_Bitread_Context* pReader,
87        size_t                                   length,
88        size_t*                  pBytesParsed,
89        uint8_t*                 pcc_count,
90        BUDP_DCCparse_dss_cc_subtitle* pCCdata,
91        uint8_t*                 psubtitle_count,
92        BUDP_DCCparse_dss_cc_subtitle* pSubtitledata
93)
94{
95        uint8_t userDataLength, userDataType, ccCount, i, subtitleCount;
96
97        /* Start counting */
98        *pcc_count = 0;
99        *pBytesParsed = 0;
100        ccCount = 0;
101        *psubtitle_count = 0;
102        subtitleCount = 0;
103
104        /* We must have at least one length byte and a type byte */
105        if (length < 2)
106        {   
107                return BERR_BUDP_NO_DATA;;
108        }
109
110        /* Read 8-bit length field */
111        userDataLength = BUDP_Bitread_Byte (pReader);
112        (*pBytesParsed)++;
113
114        if (userDataLength > length)
115        {
116                /* The userDataLength is somehow corrupted */
117                return BERR_BUDP_PARSE_ERROR;
118        }
119
120        BDBG_MSG((" userDataLength is %d \n", userDataLength));
121        while(userDataLength != 0)
122        {
123                /* Read 8-bit type field */
124                userDataType = BUDP_Bitread_Byte (pReader);
125                BDBG_MSG((" userDataType is %d \n", userDataType));
126
127                (*pBytesParsed)++;
128
129                /* Type can be 2 bytes if first byte is 0xFF */
130                if(userDataType == 0xFF)
131                {
132                        userDataType = BUDP_Bitread_Byte (pReader);
133                        (*pBytesParsed)++;
134                }       
135
136                if((userDataType == 9 || userDataType == 10))
137                { 
138                   if (userDataLength != 3)
139                   {
140                                /* The userDataLength is somehow corrupted */
141                                /* It is out of spec. Return error. */
142                                return BERR_BUDP_PARSE_ERROR;                   
143                        }
144
145                        ccCount = (userDataLength - 1) / 2;
146
147                        /* All DirecTV SD CC data is intended for top field display. In the
148                        * case of 3:2 pulldown, we may actually end up with 2 pairs of CC
149                        * data, which needs to get spread across 2 successive frames when
150                        * the fields are repeated.
151                        */
152                        for(i=0;i<ccCount;i++)
153                        {
154                                pCCdata[*pcc_count].eCCType = BUDP_DCCparse_CC_Dss_Type_ClosedCaption;
155                                pCCdata[*pcc_count].bIsAnalog = true;
156
157                                /* All DirecTV SD CC data is intended for top field display, */
158                                /* while EDS data is intended for bottom field display.      */
159                                if(userDataType == 9)
160                                {
161                                pCCdata[*pcc_count].polarity = BAVC_Polarity_eTopField;
162                                pCCdata[*pcc_count].language_type = 0;
163                                }
164                                else
165                                {
166                                        pCCdata[*pcc_count].polarity = BAVC_Polarity_eBotField;
167                                        pCCdata[*pcc_count].language_type = 1;
168                                }       
169
170                                /* cc_data_1(8) or eds_byte_1(8) */
171                                pCCdata[*pcc_count].cc_data_1 = 
172                                        BUDP_Bitread_Byte (pReader);
173                                (*pBytesParsed)++;
174
175                                /* cc_data_2(8) or eds_byte_1(8) */
176                                pCCdata[*pcc_count].cc_data_2 = 
177                                        BUDP_Bitread_Byte (pReader);
178                                (*pBytesParsed)++;
179
180                                BDBG_MSG((" ccdata1 is 0x%x, ccdata2 is 0x%x \n", pCCdata[*pcc_count].cc_data_1, pCCdata[*pcc_count].cc_data_2));
181                                (*pcc_count)++;
182                        }
183                }
184                else if(userDataType == 0x10)
185                {
186                        /*Subtitle for GLA Project "Subtitling specification for GLA Project V2.2.pdf" */
187                        int i;
188                        BDBG_MSG((" userDataLength is %d \n", userDataLength));
189
190                        if (userDataLength > 13)
191                        {
192                                /* The userDataLength is somehow corrupted */
193                                /* the maximum number of subtitle language is 4, so the maximum of userdata_length =  No of Sub_title_language_type*3+1=4*3+1=13*/
194                                return BERR_BUDP_PARSE_ERROR;                   
195                        }
196                       
197                        subtitleCount = (userDataLength - 1) / 3;
198                        for(i=0; i<subtitleCount;i++)
199                        {
200                                pSubtitledata[*psubtitle_count].eCCType = BUDP_DCCparse_CC_Dss_Type_Subtitle;
201                                pSubtitledata[*psubtitle_count].bIsAnalog = false;
202                                pSubtitledata[*psubtitle_count].language_type = BUDP_Bitread_Byte (pReader) & 0x7f; /*7 bits for this field language type*/
203                                (*pBytesParsed)++;
204                               
205                                /* subtitle_data_1(8) */
206                                pSubtitledata[*psubtitle_count].cc_data_1 = 
207                                        BUDP_Bitread_Byte (pReader);
208                                (*pBytesParsed)++;
209
210                                /* subtitle_data_2(8) */
211                                pSubtitledata[*psubtitle_count].cc_data_2 = 
212                                        BUDP_Bitread_Byte (pReader);
213                                (*pBytesParsed)++;
214
215                                BDBG_MSG((" subtitle_language_type is 0x%x \n", pSubtitledata[*psubtitle_count].language_type));
216                                BDBG_MSG((" subtitle_data_1 is 0x%x \n", pSubtitledata[*psubtitle_count].cc_data_1));
217                                BDBG_MSG((" subtitle_data_2 is 0x%x \n", pSubtitledata[*psubtitle_count].cc_data_2));
218
219                                (*psubtitle_count)++;
220                        }
221
222                }
223                else
224                {
225                        if (userDataLength > length)
226                        {
227                                /* The userDataLength is somehow corrupted */
228                                /* Return an error */
229                                return BERR_BUDP_PARSE_ERROR;
230                        }
231                        else
232                        {
233                        /* Skip over non-CC data */
234                        for(i=0;i<(userDataLength-1);i++)
235                                BUDP_Bitread_Byte (pReader);
236                        *pBytesParsed += (userDataLength-1);
237                      }
238                }
239
240                /* Read 8-bit length field of next chunk of user data */
241                if(*pBytesParsed < length)
242                {
243                        userDataLength = BUDP_Bitread_Byte (pReader);
244                        (*pBytesParsed)++;
245                }
246                else
247                    userDataLength = 0; 
248        }
249
250        return BERR_SUCCESS;
251}
252
253/***************************************************************************
254 *
255 */
256BERR_Code BUDP_DCCparse_DSS_isr ( 
257        const BAVC_USERDATA_info*      pUserdata_info, 
258        size_t                   offset, 
259        size_t*                  pBytesParsed,
260        uint8_t*    pcc_count, 
261        BUDP_DCCparse_dss_cc_subtitle*  pCCdata,
262        uint8_t*                 psubtitle_count, 
263        BUDP_DCCparse_dss_cc_subtitle* pSubtitledata
264)
265{
266        size_t bytesParsedSub;
267        size_t length;
268        uint8_t* userdata;
269        BERR_Code eErr;
270        BUDP_Bitread_Context reader; 
271        BUDP_Bitread_Context savedReader; 
272       
273        BDBG_ENTER(BUDP_DCCparse_DSS_isr);
274       
275        /* Check for obvious errors from user */
276        if ((pUserdata_info == 0x0) ||
277            (pBytesParsed   == 0x0) ||
278            (pcc_count      == 0x0) ||
279            (pCCdata        == 0x0)   )
280        {
281                return BERR_INVALID_PARAMETER;
282        }
283
284        /* Programming note:  all function parameters are now validated */
285#ifdef BUDP_DSS_GETUD_DUMP
286        dss_dump_getud (pUserdata_info, offset);
287#endif
288
289        /* Take care of a special case */
290        userdata = (uint8_t*)(pUserdata_info->pUserDataBuffer) + offset;
291        length   = pUserdata_info->ui32UserDataBufSize - offset;
292        if (length < 4)
293        {
294                *pBytesParsed = length;
295                return BERR_BUDP_NO_DATA;
296        }
297
298        /* Prepare to play with bits */
299        BUDP_Bitread_Init (&reader, bByteswap, userdata);
300
301        /* jump past the first MPEG userdata start code */
302        bytesParsedSub = FindMpegUserdataStart (&reader, length);
303        *pBytesParsed = bytesParsedSub;
304        length -= bytesParsedSub;
305        savedReader = reader;
306
307        /* If we did not find a start code, bail out now */
308        if (length == 0)
309        {
310                return BERR_BUDP_NO_DATA;
311        }
312
313        reader = savedReader;
314
315#ifdef DIRECTV_SKY
316        /* Process ATSC A/53 encoded user data? */
317        if ((length >= 4) && ATSC_CC_A53_IDENTIFIER(userdata+bytesParsedSub))
318        {
319                eErr = ParseATSCA53Data(userdata, length, &bytesParsedSub, pcc_count, pCCdata);
320        }
321        else
322#endif /* DIRECTV_SKY */
323
324        eErr = ParseDSSData (
325                &reader, length, &bytesParsedSub, pcc_count, pCCdata, psubtitle_count, pSubtitledata);
326        switch (eErr)
327        {
328                case BERR_SUCCESS:
329                case BERR_BUDP_PARSE_ERROR:
330                        *pBytesParsed += bytesParsedSub;
331                        BDBG_LEAVE(BUDP_DCCparse_isr);
332                        return eErr;
333                        break;
334                case BERR_BUDP_NO_DATA:
335                        break;
336                default:
337                        /* Programming error */
338                        BDBG_ASSERT (false);
339                        break;
340        }
341
342        BDBG_LEAVE(BUDP_DCCparse_DSS_isr);
343        return BERR_SUCCESS;
344}
345
346/***************************************************************************
347 * This function finds the next userdata startcode 0x000001B2.  It
348 * indicates the byte following this startcode by its return value.
349 * If no startcode was found, it simply returns the length of the
350 * input data.
351 */
352static size_t FindMpegUserdataStart (
353        BUDP_Bitread_Context* pReader, size_t length)
354{
355    size_t count = 0;
356        uint8_t saved[4];
357
358        /* Special case (failure) */
359        if (length < 4)
360                return length;
361
362        /* Initialize */
363        saved[1] = BUDP_Bitread_Byte (pReader);
364        saved[2] = BUDP_Bitread_Byte (pReader);
365        saved[3] = BUDP_Bitread_Byte (pReader);
366
367        while (length >= 4)
368        { 
369                /* Read in another byte */
370                saved[0] = saved[1];
371                saved[1] = saved[2];
372                saved[2] = saved[3];
373                saved[3] = BUDP_Bitread_Byte (pReader);
374
375                if ((saved[0] == 0x00) &&
376                    (saved[1] == 0x00) &&
377                        (saved[2] == 0x01) &&
378                        (saved[3] == 0xB2)    ) 
379                {
380                        /* Found it! */
381                        break;
382                }
383
384                /* proceed to the next byte */
385                --length;
386                ++count;
387        }
388
389        if (length >= 4)
390        {
391                /* found the pattern before the end of stream */   
392                return count + 4;
393        }
394        else
395        {
396                /* Didn't find any start code */
397                return count + 3;
398        }
399}
400
401#ifdef BUDP_DSS_GETUD_DUMP
402static void dss_dump_getud (
403        const BAVC_USERDATA_info* pUserdata_info, size_t offset)
404{
405        unsigned int iByte;
406        uint8_t* userdata = (uint8_t*)(pUserdata_info->pUserDataBuffer) + offset;
407        size_t   length   = pUserdata_info->ui32UserDataBufSize - offset;
408
409        BDBG_MSG(("PS %d TFF %d RFF %d\n",
410                pUserdata_info->eSourcePolarity,
411                pUserdata_info->bTopFieldFirst,
412                pUserdata_info->bRepeatFirstField));
413        BDBG_MSG( ("User Data BYTES %d\n", length));
414    for (iByte = 0 ; iByte < length ; ++iByte)
415    {
416        BDBG_MSG( ("%02x", (int)userdata[iByte]));
417        if ((iByte % 16) == 15)
418            BDBG_MSG( ("\n"));
419        else
420            BDBG_MSG( (" "));
421    }
422    if ((iByte % 16) != 15)
423        BDBG_MSG(("\n"));
424
425}
426#endif
427
428
429#ifdef DIRECTV_SKY
430
431/***************************************************************************
432 * This function parses ATSC SD user data.  It assumes that the userdata
433 * startcode 0x000001B2 has just been read before calling this function. The pBytesParseSub should
434 * contains the offset to the ATSC identifier.
435 */
436static BERR_Code ParseATSCA53Data (
437        uint8_t         *pUserData,
438        size_t          length,
439        size_t          *pBytesParsedSub,
440        uint8_t         *pcc_count,
441        BUDP_DCCparse_dss_cc_subtitle* pCCdata
442)
443{
444        uint8_t  *pCurBuffer;
445        uint8_t   u8SkyCCCnt=0;
446        uint8_t   u8CCIndx;
447        uint8_t   u8CurBufferOffset, u8CCInfo;
448        uint8_t   u8CCType;
449        uint8_t   u8AdditionalDataFlag;
450        BERR_Code status = BERR_BUDP_PARSE_ERROR;
451
452        /* Check for obvious errors from user */
453        if ((pUserData == NULL) ||
454            (pBytesParsedSub   == NULL) ||
455            (pcc_count      == NULL) ||
456            (pCCdata        == NULL)   )
457        {
458                return BERR_INVALID_PARAMETER;
459        }
460
461        /* Sanity check atleast length after the startcode >= 5 */
462        if (length < 5)
463        {
464                *pBytesParsedSub = length;
465                return BERR_BUDP_NO_DATA;
466        }
467
468        /* Skip the ATSC identifier */
469        *pBytesParsedSub += 4;
470        pCurBuffer = pUserData + (*pBytesParsedSub);
471
472        /* Skip user data type byte */
473        *pBytesParsedSub += 1;
474
475        /* Adjust length: ATSC identifier + user data type byte */
476        length -= 5;
477
478        /* Check for user data type code */
479        u8CurBufferOffset = 0;
480        if ((pCurBuffer[u8CurBufferOffset] == 0x03) && (length >= 2))
481        {
482                /* Read the cc info byte */
483                u8CCInfo = pCurBuffer[u8CurBufferOffset+1];
484
485                /* Skip EMM Data & CC info byte */
486                *pBytesParsedSub += 2;
487                u8CurBufferOffset += 3;
488                length -= 2;
489
490                /* Check if need to process CC data */
491                u8AdditionalDataFlag = u8CCInfo & ATSC_ADDITIONAL_DATA_FLG;
492                if (u8CCInfo & ATSC_CC_DATA_FLG)
493                {
494                        /* CC counts */
495                        u8SkyCCCnt = u8CCInfo & ATSC_CC_DATA_CNT;
496                               
497                        /* Reading CC data */
498                        for (u8CCIndx=0; (u8CCIndx<u8SkyCCCnt) && (length >= 3); u8CCIndx++)
499                        {
500                                /* CC valid ? */
501                                u8CCType = pCurBuffer[u8CurBufferOffset] & ATSC_CC_DATA_TYPE;
502                                if (pCurBuffer[u8CurBufferOffset] & ATSC_CC_DATA_VALID)
503                                {
504                                        pCCdata[*pcc_count].eCCType = BUDP_DCCparse_CC_Dss_Type_ClosedCaption;
505                                        pCCdata[*pcc_count].bIsAnalog = true;
506
507                                        /* All DirecTV SD CC data is intended for top field display, */
508                                        /* while EDS data is intended for bottom field display.      */
509                                        if (u8CCType == ATSC_CC_FIELD_1)
510                                        {
511                                                pCCdata[*pcc_count].polarity = BAVC_Polarity_eTopField;
512                                                pCCdata[*pcc_count].language_type = 0;
513                                        }
514                                        else if (u8CCType == ATSC_CC_FIELD_2)
515                                        {
516                                                pCCdata[*pcc_count].polarity = BAVC_Polarity_eBotField;
517                                                pCCdata[*pcc_count].language_type = 1;
518                                        }
519                                        else
520                                        {
521                                                BDBG_MSG(("[CC-DRV] BUDP_DCCparse_DSS: invalid Closed Caption type = 0x%x\n", u8CCType));
522                                                break;
523                                        }
524
525                                        /* cc_data_1(8) or eds_byte_1(8) */
526                                        pCCdata[*pcc_count].cc_data_1 = pCurBuffer[u8CurBufferOffset+1];
527
528                                        /* cc_data_2(8) or eds_byte_1(8) */
529                                        pCCdata[*pcc_count].cc_data_2 = pCurBuffer[u8CurBufferOffset+2];
530
531                                        (*pcc_count)++;
532                                }
533                                       
534                                /* Adjust byte parsed counter */
535                                *pBytesParsedSub += 3;
536                                length -= 3;
537                                u8CurBufferOffset += 3;
538                        }
539                }
540
541                /* Skip Marker Byte */
542                *pBytesParsedSub += 1;
543                length -= 1;
544                u8CurBufferOffset += 1;
545
546                /* Check for additional data flag */
547                if (u8AdditionalDataFlag)
548                {
549                        BDBG_MSG(("[CC-DRV] BUDP_DCCparse_DSS: ATSC Additional Data Flag is set...... TODO TODO HERE....\n"));
550                        pCurBuffer = pUserData + *pBytesParsedSub;
551                        while (length >= 3 && ATSC_CC_A53_ADDITIONAL_CODE(pCurBuffer))
552                        {
553                                /* TODO: Parser unsupported additional data */
554                                length -= 4;
555                                *pBytesParsedSub += 4;
556                        }
557                }
558
559                /* Adjust pBytesParsedSub not including the 5-bytes userdata start code */
560                if (*pBytesParsedSub >= 5) *pBytesParsedSub -= 5;
561               
562                status = BERR_SUCCESS;
563        }
564        else
565        {
566                BDBG_MSG(("[CC-DRV] BUDP_DCCparse_DSS: Invalid User Data Type Code for ATSC A53 = 0x%x length[%d]\n", pCurBuffer[u8CurBufferOffset], length));
567                *pBytesParsedSub += length;
568                status = BERR_BUDP_NO_DATA;
569        }
570
571        return status;
572       
573}
574#endif /* DIRECTV_SKY */
575
Note: See TracBrowser for help on using the repository browser.