source: svn/trunk/newcon3bcm2_21bu/magnum/commonutils/udp/budp_scteparse.c

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 30.9 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_scteparse.c $
11 * $brcm_Revision: Hydra_Software_Devel/3 $
12 * $brcm_Date: 10/28/10 3:59p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/commonutils/udp/budp_scteparse.c $
19 *
20 * Hydra_Software_Devel/3   10/28/10 3:59p darnstein
21 * SW3548-2364: trivial implementation of _isr functions for parsing.
22 *
23 * Hydra_Software_Devel/2   7/27/10 7:13p darnstein
24 * SW3548-3022: Some data structures involving SCTE-20 and SCTE-21 are
25 * moved from BVBI portiing interface to BUDP commonutils module.
26 *
27 * Hydra_Software_Devel/1   7/27/10 5:07p darnstein
28 * SW3548-3022: userdata parsing software.
29 *
30 ***************************************************************************/
31
32/* For debugging */
33/* #define BUDP_P_GETUD_DUMP 1 */
34#ifdef BUDP_P_GETUD_DUMP
35static const char* BUDP_P_Getud_Filename = "userdata.getud";
36#include <stdio.h>
37#endif
38
39#include "bstd.h"
40#include "bavc.h"
41#include "bkni.h"
42#include "bdbg.h"
43#include "budp.h"
44#include "budp_bitread.h"
45#include "budp_scteparse.h"
46
47BDBG_MODULE(BUDP);
48
49
50/***************************************************************************
51* Private data types
52***************************************************************************/
53
54typedef struct {
55        BUDP_SCTEparse_Format type;
56        BERR_Code (*parser) (
57                BUDP_Bitread_Context* pReader, 
58                size_t                                   length,
59                size_t*                  pBytesParsed,
60                uint8_t*                 pscte_count,
61                BUDP_SCTEparse_sctedata* pScteData
62        );
63} DigitalParser;
64
65
66/***************************************************************************
67* Forward declarations of static (private) functions
68***************************************************************************/
69
70#ifndef MAX
71        #define MAX(a,b) \
72                (((a) >= (b)) ? (a) : (b))
73#endif
74
75static size_t FindMpegUserdataStart (
76        BUDP_Bitread_Context* pReader, size_t length);
77static BERR_Code ParseSCTE20Data (
78        BUDP_Bitread_Context* pReader, 
79        size_t                                   length,
80        size_t*                  pBytesParsed,
81        uint8_t*                 pscte_count,
82        BUDP_SCTEparse_sctedata* pScteData);
83static BERR_Code ParseSCTE21CCData (
84        BUDP_Bitread_Context* pReader, 
85        size_t                                   length,
86        size_t*                  pBytesParsed,
87        uint8_t*                 pscte_count,
88        BUDP_SCTEparse_sctedata* pScteData);
89static BERR_Code ParseSCTE21ACCData (
90        BUDP_Bitread_Context* pReader, 
91        size_t                                   length,
92        size_t*                  pBytesParsed,
93        uint8_t*                 pscte_count,
94        BUDP_SCTEparse_sctedata* pScteData);
95static BERR_Code ParseSCTE21PAMData (
96        BUDP_Bitread_Context* pReader, 
97        size_t                                   length,
98        size_t*                  pBytesParsed,
99        uint8_t*                 pscte_count,
100        BUDP_SCTEparse_sctedata* pScteData);
101
102static void P_ArrayInit_SCTE (
103        BUDP_SCTEparse_sctedata* pSCTEdata,
104        const BAVC_USERDATA_info* pUserdata_info);
105
106static int swap_bits (int src);
107static void P_EndSwap (uint8_t* byteData, size_t byteLength);
108
109#ifdef BUDP_P_GETUD_DUMP
110static void dump_getud (
111        const BAVC_USERDATA_info* pUserdata_info, size_t offset);
112#endif
113
114
115/***************************************************************************
116* Static data (tables, etc.)
117***************************************************************************/
118
119/* The arrays of digital CC data parsers. 
120 */
121static const DigitalParser scte20Parsers[] = {
122        {BUDP_SCTEparse_Format_SCTE20,         ParseSCTE20Data},
123};
124#define NUM_20_PARSERS (sizeof(scte20Parsers) / sizeof(scte20Parsers[0]))
125static const DigitalParser scte21Parsers[] = {
126        {BUDP_SCTEparse_Format_SCTE21CC,       ParseSCTE21CCData},
127        {BUDP_SCTEparse_Format_SCTE21ACC,      ParseSCTE21ACCData},
128        {BUDP_SCTEparse_Format_SCTE21PAM,      ParseSCTE21PAMData}
129};
130#define NUM_21_PARSERS (sizeof(scte21Parsers) / sizeof(scte21Parsers[0]))
131
132static const bool bByteswap = (BSTD_CPU_ENDIAN == BSTD_ENDIAN_LITTLE);
133
134
135/***************************************************************************
136* Implementation of "BUDP_SCTEparse_" API functions
137***************************************************************************/
138
139
140/***************************************************************************
141 *
142 */
143BERR_Code BUDP_SCTE20parse_isr ( 
144        const BAVC_USERDATA_info*      pUserdata_info, 
145        size_t                   offset, 
146        size_t*                  pBytesParsed,
147        uint8_t*                 pscte_count,
148        BUDP_SCTEparse_sctedata* pScteData
149)
150{
151        size_t bytesParsedSub;
152        size_t length;
153        uint8_t* userdata;
154        unsigned int iparser;
155        BERR_Code eErr;
156        BUDP_Bitread_Context reader; 
157        BUDP_Bitread_Context savedReader; 
158
159        BDBG_ENTER(BUDP_SCTE20parse_isr);
160
161        /* Check for obvious errors from user */
162        if ((pUserdata_info   == 0x0) ||
163            (pBytesParsed     == 0x0) ||
164            (pscte_count      == 0x0) ||
165            (pScteData        == 0x0)   )
166        {
167                return BERR_INVALID_PARAMETER;
168        }
169
170        /* Programming note:  all function parameters are now validated */
171
172#ifdef BUDP_P_GETUD_DUMP
173        dump_getud (pUserdata_info, offset);
174#endif
175
176        /* Take care of a special case */
177        userdata = (uint8_t*)(pUserdata_info->pUserDataBuffer) + offset;
178        length   = pUserdata_info->ui32UserDataBufSize - offset;
179        if (length < 4)
180        {
181                *pBytesParsed = length;
182                return BERR_BUDP_NO_DATA;
183        }
184
185        /* Prepare to play with bits */
186        BUDP_Bitread_Init (&reader, bByteswap, userdata);
187
188        /* jump past the first MPEG userdata start code */
189        bytesParsedSub = FindMpegUserdataStart (&reader, length);
190        *pBytesParsed = bytesParsedSub;
191        length -= bytesParsedSub;
192        savedReader = reader;
193
194        /* If we did not find a start code, bail out now */
195        if (length == 0)
196        {
197                return BERR_BUDP_NO_DATA;
198        }
199
200        /* Initialize output array */
201        P_ArrayInit_SCTE (pScteData, pUserdata_info);
202        *pscte_count = 0;
203
204        /*********************************************************************\
205        * Programming note:  each of the parsers will give up and return
206        * BERR_BUDP_NO_DATA if it finds the wrong identifier byte. 
207        \*********************************************************************/
208
209        /* Try all the available parsers */
210        for (iparser = 0 ; iparser < NUM_20_PARSERS ; ++iparser)
211        {
212                reader = savedReader;
213                eErr = (*scte20Parsers[iparser].parser) (
214                        &reader, length, &bytesParsedSub, pscte_count, pScteData);
215                switch (eErr)
216                {
217                case BERR_SUCCESS:
218                case BERR_BUDP_PARSE_ERROR:
219                        *pBytesParsed += bytesParsedSub;
220                        BDBG_LEAVE(BUDP_SCTE20parse_isr);
221                        return eErr;
222                        break;
223                case BERR_BUDP_NO_DATA:
224                        break;
225                default:
226                        /* Programming error */
227                        BDBG_ASSERT (false);
228                        break;
229                }
230        }
231
232        /* Programming note:
233         * None of the parsers liked this bit of userdata.
234         * It would be more elegant to skip to the next start code
235         * before returning.  But it is more efficient to simply
236         * stop parsing. */
237
238        /* No userdata was found */
239        BDBG_LEAVE(BUDP_SCTE20parse_isr);
240        return BERR_BUDP_NO_DATA;
241}
242
243
244/***************************************************************************
245 *
246 */
247BERR_Code BUDP_SCTE21parse_isr ( 
248        const BAVC_USERDATA_info*      pUserdata_info, 
249        size_t                   offset, 
250        size_t*                  pBytesParsed,
251        uint8_t*                 pscte_count,
252        BUDP_SCTEparse_sctedata* pScteData
253)
254{
255        size_t bytesParsedSub;
256        size_t length;
257        uint8_t* userdata;
258        unsigned int iparser;
259        BERR_Code eErr;
260        BUDP_Bitread_Context reader; 
261        BUDP_Bitread_Context savedReader; 
262
263        BDBG_ENTER(BUDP_SCTE21parse_isr);
264
265        /* Check for obvious errors from user */
266        if ((pUserdata_info   == 0x0) ||
267            (pBytesParsed     == 0x0) ||
268            (pscte_count      == 0x0) ||
269            (pScteData        == 0x0)   )
270        {
271                return BERR_INVALID_PARAMETER;
272        }
273
274        /* Programming note:  all function parameters are now validated */
275
276#ifdef BUDP_P_GETUD_DUMP
277        dump_getud (pUserdata_info, offset);
278#endif
279
280        /* Take care of a special case */
281        userdata = (uint8_t*)(pUserdata_info->pUserDataBuffer) + offset;
282        length   = pUserdata_info->ui32UserDataBufSize - offset;
283        if (length < 4)
284        {
285                *pBytesParsed = length;
286                return BERR_BUDP_NO_DATA;
287        }
288
289        /* Prepare to play with bits */
290        BUDP_Bitread_Init (&reader, bByteswap, userdata);
291
292        /* jump past the first MPEG userdata start code */
293        bytesParsedSub = FindMpegUserdataStart (&reader, length);
294        *pBytesParsed = bytesParsedSub;
295        length -= bytesParsedSub;
296        savedReader = reader;
297
298        /* If we did not find a start code, bail out now */
299        if (length == 0)
300        {
301                return BERR_BUDP_NO_DATA;
302        }
303
304        /* Initialize output array */
305        P_ArrayInit_SCTE (pScteData, pUserdata_info);
306        *pscte_count = 0;
307
308        /*********************************************************************\
309        * Programming note:  each of the parsers will give up and return
310        * BERR_BUDP_NO_DATA if it finds the wrong identifier byte. 
311        \*********************************************************************/
312
313        /* Try all the available parsers */
314        for (iparser = 0 ; iparser < NUM_21_PARSERS ; ++iparser)
315        {
316                reader = savedReader;
317                eErr = (*scte21Parsers[iparser].parser) (
318                        &reader, length, &bytesParsedSub, pscte_count, pScteData);
319                switch (eErr)
320                {
321                case BERR_SUCCESS:
322                case BERR_BUDP_PARSE_ERROR:
323                        *pBytesParsed += bytesParsedSub;
324                        BDBG_LEAVE(BUDP_SCTE21parse_isr);
325                        return eErr;
326                        break;
327                case BERR_BUDP_NO_DATA:
328                        break;
329                default:
330                        /* Programming error */
331                        BDBG_ASSERT (false);
332                        break;
333                }
334        }
335
336        /* Programming note:
337         * None of the parsers liked this bit of userdata.
338         * It would be more elegant to skip to the next start code
339         * before returning.  But it is more efficient to simply
340         * stop parsing. */
341
342        /* No userdata was found */
343        BDBG_LEAVE(BUDP_SCTE21parse_isr);
344        return BERR_BUDP_NO_DATA;
345}
346
347
348/***************************************************************************
349* Implementation of private (static) functions
350***************************************************************************/
351
352/***************************************************************************
353 * This function finds the next userdata startcode 0x000001B2.  It
354 * indicates the byte following this startcode by its return value.
355 * If no startcode was found, it simply returns the length of the
356 * input data.
357 */
358static size_t FindMpegUserdataStart (
359        BUDP_Bitread_Context* pReader, size_t length)
360{
361    size_t count = 0;
362        uint8_t saved[4];
363
364        /* Special case (failure) */
365        if (length < 4)
366                return length;
367
368        /* Initialize */
369        saved[1] = BUDP_Bitread_Byte (pReader);
370        saved[2] = BUDP_Bitread_Byte (pReader);
371        saved[3] = BUDP_Bitread_Byte (pReader);
372
373        while (length >= 4)
374        { 
375                /* Read in another byte */
376                saved[0] = saved[1];
377                saved[1] = saved[2];
378                saved[2] = saved[3];
379                saved[3] = BUDP_Bitread_Byte (pReader);
380
381                if ((saved[0] == 0x00) &&
382                    (saved[1] == 0x00) &&
383                        (saved[2] == 0x01) &&
384                        (saved[3] == 0xB2)    ) 
385                {
386                        /* Found it! */
387                        break;
388                }
389
390                /* proceed to the next byte */
391                --length;
392                ++count;
393        }
394
395        if (length >= 4)
396        {
397                /* found the pattern before the end of stream */   
398                return count + 4;
399        }
400        else
401        {
402                /* Didn't find any start code */
403                return count + 3;
404        }
405}
406
407/***************************************************************************
408 * This function parses SCTE20 data.  It assumes that the userdata
409 * startcode 0x000001B2 has just been read.
410 */
411static BERR_Code ParseSCTE20Data (
412        BUDP_Bitread_Context* pReader,
413        size_t                                   length,
414        size_t*                  pBytesParsed,
415        uint8_t*                 pscte_count,
416        BUDP_SCTEparse_sctedata* pScteData
417)
418{
419        size_t bitsParsed;
420        int index;
421        int icount;
422        int ifield;
423        int cc_count;
424        int nrtv_count;
425        int field_number;
426        BAVC_Polarity targetPolarity;
427        BUDP_SCTE_CC_Data ccData;
428        BUDP_SCTE_NRTV_Data nrtvData = 
429        {
430                false, 0, 0, 0, 0, 
431                {
432                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
433                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
434                },
435                {
436                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
437                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
438                }
439        };
440
441        /* Special case */
442        if (length == 0)
443        {   
444                return BERR_BUDP_PARSE_ERROR;
445        }
446
447        /* user_data_type_code(8) */
448        if (BUDP_Bitread_Byte (pReader) != 0x03) 
449        {
450                /* not SCTE20 data */
451                *pBytesParsed = 1;
452                return BERR_BUDP_NO_DATA;
453        }
454
455        /* Start things off by recognizing that we have parsed one byte.
456           If an error occurs now, don't bother updating the count of
457           parsed bytes.
458        */
459        --length;
460        *pBytesParsed = 1;
461
462        if (length == 0)
463        {   
464                /* Packet is too short */
465                return BERR_BUDP_PARSE_ERROR;
466        }
467
468        /* Skip '1000 000' bits (7) */
469        /* vbi_data_flag(1) */
470        if (!(BUDP_Bitread_Byte (pReader) & 0x01))
471        {
472                /* No data for us.  Prevent other parsers from trying though. */
473                return BERR_SUCCESS;
474        }
475
476        --length;
477        *pBytesParsed += 1;
478        if (length == 0)
479        {   
480                /* Packet is too short */
481                return BERR_BUDP_PARSE_ERROR;
482        }
483
484        /* Debug code
485        printf ("SCTE 20 parsing under way\n");
486        */
487
488        /*
489         * Closed caption (like) data
490         */
491
492        /* Start the bit level parsing */
493        cc_count = BUDP_Bitread_Read (pReader, 5);
494        bitsParsed = 5;
495
496        for (icount = 0 ; icount < cc_count ; ++icount)
497        {
498                /* Each sub-packet of data is 26 bits */
499                if (length < 4)
500                {
501                        /* Minimum packet length */
502                        return BERR_BUDP_PARSE_ERROR;
503                }
504
505                /* Not part of SCTE 20 standard! */
506                ccData.valid = 1;
507
508                ccData.priority = BUDP_Bitread_Read (pReader, 2);
509
510                field_number = BUDP_Bitread_Read (pReader, 2);
511                if (field_number < 1)
512                {
513                        /* Violates spec */
514                        return BERR_BUDP_PARSE_ERROR;
515                }
516                ifield = field_number - 1;
517
518                ccData.line_number = BUDP_Bitread_Read (pReader, 5) + 10;
519
520                ccData.cc_data_1 = swap_bits(BUDP_Bitread_Byte (pReader));
521                ccData.cc_data_2 = swap_bits(BUDP_Bitread_Byte (pReader));
522                /* marker bit(1) */ 
523                (void)BUDP_Bitread_Read (pReader, 1);
524
525                /* Adjust length again */
526                /* bitsParsed += 26; */
527                if (bitsParsed < 6)
528                {
529                        length -= 3;
530                        *pBytesParsed += 3;
531                        bitsParsed += 2;
532                }
533                else
534                {
535                        length -= 4;
536                        *pBytesParsed += 4;
537                        bitsParsed -= 6;
538                }
539
540                /* Copy data obtained above into user's space */
541                /* TODO: fix this test. Should be using _size attribute. */
542                if (pScteData[ifield].data.cc_data)
543                {
544                        *pscte_count = MAX (*pscte_count, ifield + 1);
545                        pScteData[ifield].format = BUDP_SCTEparse_Format_SCTE20;
546                        pScteData[ifield].data.field_number = field_number;
547                        index = pScteData[ifield].data.cc_count;
548                        if (index < BUDP_SCTE_MAX_ITEMS)
549                        {
550                                pScteData[ifield].data.cc_data[index] = ccData;
551                                pScteData[ifield].data.cc_count = ++index;
552                        }
553                        /* TODO: complain if index is too large. */
554                }
555        }
556
557        /*
558         * Near Real Time Video
559         */
560
561        /* Resume bit level parsing */
562        nrtv_count =  BUDP_Bitread_Read (pReader, 4);
563        bitsParsed += 4;
564
565        for (icount = 0 ; icount < nrtv_count ; ++icount)
566        {
567                /* Account for the first half of the sub-packet */
568                if (length < 1)
569                {
570                        /* Minimum packet length */
571                        return BERR_BUDP_PARSE_ERROR;
572                }
573
574                /* Not part of SCTE 20 spec */
575                nrtvData.valid = 1;
576
577                nrtvData.priority = BUDP_Bitread_Read (pReader, 2);
578                nrtvData.sequence_number = BUDP_Bitread_Read (pReader, 2);
579                field_number = BUDP_Bitread_Read (pReader, 1);
580                nrtvData.line_number = BUDP_Bitread_Read (pReader, 5) + 10;
581
582                /* bitsParsed += 10 */
583                if (bitsParsed < 6)
584                {
585                        length -= 1;
586                        *pBytesParsed += 1;
587                        bitsParsed += 2;
588                }
589                else
590                {
591                        length -= 2;
592                        *pBytesParsed -= 2;
593                        bitsParsed -= 6;
594                }
595
596                /* This field is optional, so it makes for more work here. */
597                if (nrtvData.sequence_number != 0)
598                {
599                        /* Account for the second half of the sub-packet */
600                        if (length < 64)
601                        {
602                                /* Minimum packet length */
603                                return BERR_BUDP_PARSE_ERROR;
604                        }
605
606                        nrtvData.segment_number =  BUDP_Bitread_Read (pReader, 5);
607                        for (index = 0 ; index < 32 ; ++index)
608                        {
609                                nrtvData.y_data[index]      = 
610                                        BUDP_Bitread_Read (pReader, 8);
611                        }
612                        for (index = 0 ; index < 16 ; ++index)
613                        {
614                                nrtvData.cbcr_data[2*index] = 
615                                        BUDP_Bitread_Read (pReader, 8);
616                                nrtvData.cbcr_data[2*index+1] = 
617                                        BUDP_Bitread_Read (pReader, 8);
618                        }
619
620                        /* Adjust length again */
621                        /* bitsParsed += 517 */
622                        if (bitsParsed < 3)
623                        {
624                                length -= 64;
625                                *pBytesParsed += 64;
626                                bitsParsed += 5;
627                        }
628                        else
629                        {
630                                length -= 65;
631                                *pBytesParsed += 65;
632                                bitsParsed -= 3;
633                        }
634                }
635                else
636                {
637                        nrtvData.segment_number = 0;
638                }
639               
640                /* NRTV data can go top or bottom field */
641                targetPolarity = 
642                        field_number ? BAVC_Polarity_eTopField : BAVC_Polarity_eBotField;
643                if      (pScteData[0].polarity == targetPolarity)
644                        ifield = 0;
645                else if (pScteData[1].polarity == targetPolarity)
646                        ifield = 1;
647                else
648                        return BERR_BUDP_PARSE_ERROR;
649
650                /* NRTV data can go on third field if first field is occupied */
651                if (pScteData[ifield].data.nrtv_count)
652                {
653                        if (ifield == 0)
654                        {
655                                ifield = 2;
656                                if (pScteData[ifield].polarity != targetPolarity)
657                                        return BERR_BUDP_PARSE_ERROR;
658                                if (pScteData[ifield].data.nrtv_count)
659                                        return BERR_BUDP_PARSE_ERROR;
660
661                        }
662                        else
663                        {
664                                return BERR_BUDP_PARSE_ERROR;
665                        }
666                }
667
668                /* Copy data obtained above into user's space */
669                /* TODO: fix this test. Should be using _size attribute. */
670                if (pScteData[ifield].data.nrtv_data)
671                {
672                        *pscte_count = MAX (*pscte_count, ifield + 1);
673                        index = pScteData[ifield].data.nrtv_count;
674                        if (index < BUDP_SCTE_MAX_ITEMS)
675                        {
676                                pScteData[ifield].format                = 
677                                        BUDP_SCTEparse_Format_SCTE20;
678                                pScteData[ifield].data.field_number     = field_number;
679                                pScteData[ifield].data.nrtv_data[index] = nrtvData;
680                                pScteData[ifield].data.nrtv_count = ++index;
681                        }
682                        /* TODO: complain if index is too large. */
683                }
684        }
685
686        /* What a journey it was */
687        return BERR_SUCCESS;
688}
689
690/***************************************************************************
691 * This function parses SCTE 21 CC data.  It assumes that the userdata
692 * startcode 0x000001B2 has just been read.
693 */
694static BERR_Code ParseSCTE21CCData (
695        BUDP_Bitread_Context* pReader, 
696        size_t                                   length,
697        size_t*                  pBytesParsed,
698        uint8_t*                 pscte_count,
699        BUDP_SCTEparse_sctedata* pScteData)
700{
701        unsigned int index;
702        unsigned int icount;
703        unsigned int ifield;
704        unsigned int cc_count;
705        unsigned int cc_valid;
706        unsigned int cc_type;
707        unsigned int field_number;
708        BAVC_Polarity targetPolarity;
709        BUDP_SCTE_CC_Data ccData;
710
711        /* Start counting */
712        *pscte_count = 0;
713
714        /* Start travelling pointer into data */
715        if (length < 4)
716        {   
717                return BERR_BUDP_PARSE_ERROR;
718        }
719
720        /* ATSC identifier (32) */
721        if ((BUDP_Bitread_Byte (pReader) != 0x47) ||
722            (BUDP_Bitread_Byte (pReader) != 0x41) ||
723            (BUDP_Bitread_Byte (pReader) != 0x39) ||
724            (BUDP_Bitread_Byte (pReader) != 0x34)   )
725        {
726                /* not SCTE 21 data */
727                *pBytesParsed = 4;
728                return BERR_BUDP_NO_DATA;
729        }
730
731        /* Start things off by recognizing that we have parsed four bytes.
732           If an error occurs now, don't bother updating the count of
733           parsed bytes.
734        */
735        length -= 4;
736        *pBytesParsed = 4;
737
738        if (length == 0)
739        {   
740                /* Empty! */
741                return BERR_BUDP_PARSE_ERROR;
742        }
743
744        /* user_data_type_code(8) */
745        if (BUDP_Bitread_Byte (pReader) != 0x03)
746        {
747                /* not SCTE 21 CC data */
748                *pBytesParsed = 5;
749                return BERR_BUDP_NO_DATA;
750        }
751
752        --length;
753        *pBytesParsed = 5;
754        if (length == 0)
755        {   
756                /* Packet too short */
757                return BERR_BUDP_PARSE_ERROR;
758        }
759
760        /* Skip process_em_data_flag(1) */
761        (void)BUDP_Bitread_Read (pReader, 1);
762       
763        /* Dig out process_cc_data_flag(1) */
764        if (!BUDP_Bitread_Read (pReader, 1))
765        {
766                /* No closed caption data to process */
767                *pBytesParsed = 6;
768                return BERR_BUDP_NO_DATA;
769        }
770
771        /* Debug code
772        printf ("SCTE 21 CC parsing under way\n");
773        */
774
775        /* Skip additional_data_flag(1) */
776        (void)BUDP_Bitread_Read (pReader, 1);
777
778        /* Dig out the count of cc data pairs */
779        cc_count = BUDP_Bitread_Read (pReader, 5);
780
781        --length;
782        *pBytesParsed = 6;
783        if (length == 0)
784        {   
785                /* Packet too short */
786                return BERR_BUDP_PARSE_ERROR;
787        }
788
789        /* Skip em_data(8) */
790        (void)BUDP_Bitread_Byte (pReader);
791
792        /* This will be the last length check */
793        --length;
794        *pBytesParsed = 7;
795        if (length < (3 * cc_count))
796        {   
797                /* Packet too short */
798                return BERR_BUDP_PARSE_ERROR;
799        }
800        *pBytesParsed += (3 * cc_count);
801
802        /* Dig out the closed caption data pairs */
803        for (icount = 0 ; icount < cc_count ; ++icount)
804        {
805                /* Skip marker bits(5) */
806                (void)BUDP_Bitread_Read (pReader, 5);
807
808                /* cc_valid(1) */
809                cc_valid = BUDP_Bitread_Read (pReader, 1);
810                ccData.valid = cc_valid;
811
812                /* Debug code
813                if (cc_valid != 1)
814                        printf ("cc_valid =%d\n", cc_valid);
815                */
816       
817                /* cc_type(2) */
818                cc_type = BUDP_Bitread_Read (pReader, 2);
819                /* Bogus */
820                field_number = cc_type;
821
822                /* Kludge */
823                ccData.line_number = 21;
824
825                /* cc_data_1(8) */
826                ccData.cc_data_1 = BUDP_Bitread_Byte (pReader);
827
828                /* cc_data_2(8) */
829                ccData.cc_data_2 = BUDP_Bitread_Byte (pReader);
830
831                /* Skip data that is not analog */
832                if ((!cc_valid) || (cc_type > 1))
833                        continue;
834               
835                /* CC data can go top or bottom field */
836                targetPolarity = 
837                        cc_type ? BAVC_Polarity_eTopField : BAVC_Polarity_eBotField;
838                if      (pScteData[0].polarity == targetPolarity)
839                        ifield = 0;
840                else if (pScteData[1].polarity == targetPolarity)
841                        ifield = 1;
842                else
843                        return BERR_BUDP_PARSE_ERROR;
844
845                /* CC data can go in a third field, if first field is occupied. */
846                if (pScteData[ifield].data.cc_count)
847                {
848                        if (ifield == 0) 
849                        {
850                                ifield = 2;
851                                if (pScteData[ifield].polarity != targetPolarity)
852                                        return BERR_BUDP_PARSE_ERROR;
853                        }
854                        else
855                        {
856                                return BERR_BUDP_PARSE_ERROR;
857                        }
858                }
859
860                /* Copy data obtained above into user's space */
861                /* TODO: fix this test. Should be using _size attribute. */
862                if (pScteData[ifield].data.cc_data)
863                {
864                        *pscte_count = MAX (*pscte_count, ifield + 1);
865                        index = pScteData[ifield].data.cc_count;
866                        if (index < BUDP_SCTE_MAX_ITEMS)
867                        {
868                                /* Not part of SCTE-21 standard */
869                                ccData.priority = 0;
870
871                                pScteData[ifield].format              = 
872                                        BUDP_SCTEparse_Format_SCTE21CC;
873                                pScteData[ifield].data.field_number   = field_number;
874                                pScteData[ifield].data.cc_data[index] = ccData;
875                                pScteData[ifield].data.cc_count = ++index;
876                        }
877                        /* TODO: complain if index is too large. */
878                }
879        }
880        return BERR_SUCCESS;
881}
882
883/***************************************************************************
884 * This function parses SCTE21 "additional CC" data.  It assumes that the
885 * userdata startcode 0x000001B2 has just been read.
886 */
887static BERR_Code ParseSCTE21ACCData (
888        BUDP_Bitread_Context* pReader, 
889        size_t                                   length,
890        size_t*                  pBytesParsed,
891        uint8_t*                 pscte_count,
892        BUDP_SCTEparse_sctedata* pScteData)
893{
894        unsigned int index;
895        unsigned int icount;
896        unsigned int ifield;
897        unsigned int cc_count;
898        unsigned int field_number;
899        BUDP_SCTE_CC_Data ccData;
900
901        /* Start counting */
902        *pscte_count = 0;
903
904        /* Special case */
905        if (length < 4)
906        {   
907                return BERR_BUDP_PARSE_ERROR;
908        }
909
910        /* ATSC identifier (4) */
911        if ((BUDP_Bitread_Byte (pReader) != 0x47) ||
912            (BUDP_Bitread_Byte (pReader) != 0x41) ||
913            (BUDP_Bitread_Byte (pReader) != 0x39) ||
914            (BUDP_Bitread_Byte (pReader) != 0x34)   )
915        {
916                /* not SCTE21ACC data */
917                *pBytesParsed = 4;
918                return BERR_BUDP_NO_DATA;
919        }
920
921        /* Start things off by recognizing that we have parsed four bytes.
922           If an error occurs now, don't bother updating the count of
923           parsed bytes.
924        */
925        length -= 4;
926        *pBytesParsed = 4;
927
928        if (length == 0)
929        {   
930                /* Empty! */
931                return BERR_BUDP_PARSE_ERROR;
932        }
933
934        /* user_data_type_code(8) */
935        if (BUDP_Bitread_Byte (pReader) != 0x04)
936        {
937                /* not SCTE21ACC data */
938                *pBytesParsed = 5;
939                return BERR_BUDP_NO_DATA;
940        }
941
942        --length;
943        *pBytesParsed += 1;
944        if (length == 0)
945        {   
946                /* Packet too short */
947                return BERR_BUDP_PARSE_ERROR;
948        }
949
950        /* Debug code
951        printf ("SCTE 21 A-CC parsing under way\n");
952        */
953
954        /*
955         * Begin processing additional EIA-608 closed caption data
956         */
957
958        /* Skip marker bits(3) and dig out the count of cc data pairs(5) */
959        cc_count = BUDP_Bitread_Byte (pReader) & 0x1F;
960
961        /* This will be the last length check for standard CC data */
962        --length;
963        *pBytesParsed += 1;
964        if (length < (3 * cc_count))
965        {   
966                /* Packet too short */
967                return BERR_BUDP_PARSE_ERROR;
968        }
969        *pBytesParsed += (3 * cc_count);
970
971        /* Dig out the closed caption data pairs */
972        for (icount = 0 ; icount < cc_count ; ++icount)
973        {
974                /* additional_cc_valid(1) */
975                ccData.valid = BUDP_Bitread_Read (pReader, 1);
976       
977                /* additional_cc_line_offset(5) */
978                ccData.line_number = BUDP_Bitread_Read (pReader, 5) + 9;
979
980                /* additional_cc_field_number(2) */
981                field_number = BUDP_Bitread_Read (pReader, 2);
982                if (field_number < 1)
983                {
984                        /* Violates spec */
985                        return BERR_BUDP_PARSE_ERROR;
986                }
987                ifield = field_number - 1;
988
989                /* additional_cc_data_1(8) */
990                ccData.cc_data_1 = BUDP_Bitread_Byte (pReader);
991
992                /* additional_cc_data_2(8) */
993                ccData.cc_data_2 = BUDP_Bitread_Byte (pReader);
994
995                /* Skip data that is not analog */
996                if (!ccData.valid)
997                        continue;
998
999                /* Copy data obtained above into user's space */
1000                /* TODO: fix this test. Should be using _size attribute. */
1001                if (pScteData[ifield].data.cc_data)
1002                {
1003                        *pscte_count = MAX (*pscte_count, ifield + 1);
1004                        index = pScteData[ifield].data.cc_count; 
1005                        if (index < BUDP_SCTE_MAX_ITEMS)
1006                        {
1007                                /* Not part of SCTE-21 standard */
1008                                ccData.priority = 0;
1009
1010                                pScteData[ifield].format              = 
1011                                        BUDP_SCTEparse_Format_SCTE21ACC;
1012                                pScteData[ifield].data.field_number   = field_number;
1013                                pScteData[ifield].data.cc_data[index] = ccData;
1014                                pScteData[ifield].data.cc_count = ++index;
1015                        }
1016                        /* TODO: complain if index is too large. */
1017                }
1018        }
1019
1020        /* Another happy landing */
1021        return BERR_SUCCESS;
1022}
1023
1024/***************************************************************************
1025 * This function parses SCTE21 luma PAM data.  It assumes that the
1026 * userdata startcode 0x000001B2 has just been read.
1027 */
1028static BERR_Code ParseSCTE21PAMData (
1029        BUDP_Bitread_Context* pReader, 
1030        size_t                                   length,
1031        size_t*                  pBytesParsed,
1032        uint8_t*                 pscte_count,
1033        BUDP_SCTEparse_sctedata* pScteData)
1034{
1035        unsigned int ifield;
1036        size_t bytesParsedSub;
1037        uint8_t* pam_data;
1038
1039        /* Start counting */
1040        *pscte_count = 0;
1041
1042        /* Special case */
1043        if (length < 4)
1044        {   
1045                return BERR_BUDP_PARSE_ERROR;
1046        }
1047
1048        /* ATSC identifier (4) */
1049        if ((BUDP_Bitread_Byte (pReader) != 0x47) ||
1050            (BUDP_Bitread_Byte (pReader) != 0x41) ||
1051            (BUDP_Bitread_Byte (pReader) != 0x39) ||
1052            (BUDP_Bitread_Byte (pReader) != 0x34)   )
1053        {
1054                /* not SCTE21PAM data */
1055                *pBytesParsed = 4;
1056                return BERR_BUDP_NO_DATA;
1057        }
1058
1059        /* Start things off by recognizing that we have parsed four bytes.
1060           If an error occurs now, don't bother updating the count of
1061           parsed bytes.
1062        */
1063        length -= 4;
1064        *pBytesParsed = 4;
1065
1066        if (length == 0)
1067        {   
1068                /* Empty! */
1069                return BERR_BUDP_PARSE_ERROR;
1070        }
1071
1072        /* user_data_type_code(8) */
1073        if (BUDP_Bitread_Byte (pReader) != 0x05)
1074        {
1075                /* not SCTE21PAM data */
1076                *pBytesParsed = 5;
1077                return BERR_BUDP_NO_DATA;
1078        }
1079
1080        --length;
1081        *pBytesParsed += 1;
1082        if (length == 0)
1083        {   
1084                /* Packet too short */
1085                return BERR_BUDP_PARSE_ERROR;
1086        }
1087
1088        /* Debug code
1089        printf ("SCTE 21 PAM parsing under way\n");
1090        */
1091
1092        /* Record the luma data start */
1093        pam_data = (uint8_t*)(pReader->userdata_start);
1094
1095        /* Skip past data, and then record data size. */
1096        (void)BUDP_Bitread_next_start_code (pReader, length, &bytesParsedSub);
1097        length -=  bytesParsedSub;
1098        *pBytesParsed +=  bytesParsedSub;
1099
1100        /* Loop over fields indicated in luma_PAM_data() structure */
1101        for (ifield = 0 ; ifield < 3 ; ++ifield)
1102        {
1103                if (pScteData[ifield].polarity == BAVC_Polarity_eFrame)
1104                        continue;
1105
1106                /* Copy data obtained above into user's space */
1107                /* TODO: fix this test. Should be using _size attribute. */
1108                if (pScteData[ifield].data.luma_PAM_data)
1109                {
1110                        *pscte_count = MAX (*pscte_count, ifield + 1);
1111                        pScteData[ifield].data.pam_size = bytesParsedSub;
1112                        pScteData[ifield].format = BUDP_SCTEparse_Format_SCTE21PAM;
1113                        BKNI_Memcpy (
1114                                pScteData[ifield].data.luma_PAM_data, pam_data, bytesParsedSub);
1115
1116                        /* It is a shame that this is necessary */
1117                        if (bByteswap)
1118                        {
1119                                P_EndSwap (
1120                                        pScteData[ifield].data.luma_PAM_data, bytesParsedSub);
1121                        }
1122                }
1123        }
1124
1125        /* Another happy landing */
1126        return BERR_SUCCESS;
1127}
1128
1129/***************************************************************************
1130 * This function initializes an array of BUDP_SCTEparse_sctedata according
1131 * to one piece of SCTE 20 userdata or SCTE 21 userdata.
1132 */
1133static void P_ArrayInit_SCTE (
1134        BUDP_SCTEparse_sctedata* pSCTEdata,
1135        const BAVC_USERDATA_info*   pUserdata_info)
1136{
1137        int entry;
1138        bool top_field_first           = pUserdata_info->bTopFieldFirst;
1139        bool repeat_first_field        = pUserdata_info->bRepeatFirstField;
1140        BAVC_Polarity pictureStructure = pUserdata_info->eSourcePolarity;
1141
1142        /* Dumb initialization */
1143        for (entry = 0 ; entry < 3 ; ++entry)
1144        {
1145                BUDP_SCTEparse_sctedata* sldata = &pSCTEdata[entry];
1146                BUDP_SCTE_Data* pidata = &(sldata->data);
1147                sldata->polarity = BAVC_Polarity_eFrame;
1148                sldata->format = BUDP_SCTEparse_Format_Unknown;
1149                pidata->cc_count = 0;
1150                pidata->nrtv_count = 0;
1151                pidata->pam_count = 0;
1152        }
1153
1154        /* According to the MPEG userdata... */
1155        if ((pictureStructure == BAVC_Polarity_eTopField) ||
1156            (pictureStructure == BAVC_Polarity_eTopField)   )
1157        {
1158                /* Field picture */
1159                pSCTEdata[0].polarity = pictureStructure;
1160        }
1161        else
1162        {
1163                /* Frame picture */
1164                if (top_field_first)
1165                {
1166                        pSCTEdata[0].polarity = BAVC_Polarity_eTopField;
1167                        pSCTEdata[1].polarity = BAVC_Polarity_eBotField;
1168                        if (repeat_first_field)
1169                        {
1170                                pSCTEdata[2].polarity = BAVC_Polarity_eTopField;
1171                        }
1172                }
1173                else /* Bottom field first */
1174                {
1175                        pSCTEdata[0].polarity = BAVC_Polarity_eBotField;
1176                        pSCTEdata[1].polarity = BAVC_Polarity_eTopField;
1177                        if (repeat_first_field)
1178                        {
1179                                pSCTEdata[2].polarity = BAVC_Polarity_eBotField;
1180                        }
1181                }
1182        }
1183}
1184
1185/***************************************************************************
1186 * This function reverses the order of bits in a byte.
1187*/
1188static int swap_bits(int src)
1189{
1190        int result;
1191        int i;
1192
1193        for (result = 0, i = 0; i < 8; i++) 
1194        {
1195                result = (result << 1) | (src & 1);
1196                src >>= 1;
1197        }
1198        return result;
1199}
1200
1201/***************************************************************************
1202 * This function performs a big-endian / little-endian swap
1203*/
1204static void P_EndSwap (uint8_t* byteData, size_t byteLength)
1205{
1206        size_t qLength = byteLength / 4;
1207
1208        while (qLength-- > 0)
1209        {
1210                uint8_t entry;
1211                entry       = byteData[0];
1212                byteData[0] = byteData[3];
1213                byteData[3] = entry;
1214                entry       = byteData[1];
1215                byteData[1] = byteData[2];
1216                byteData[2] = entry;
1217                byteData += 4;
1218        }
1219}
1220
1221#ifdef BUDP_P_GETUD_DUMP
1222static void dump_getud (
1223        const BAVC_USERDATA_info* pUserdata_info, size_t offset)
1224{
1225        unsigned int iByte;
1226        static FILE* fd = NULL;
1227        static unsigned int nPicture;
1228        uint8_t* userdata = (uint8_t*)(pUserdata_info->pUserDataBuffer) + offset;
1229        size_t   length   = pUserdata_info->ui32UserDataBufSize - offset;
1230
1231        /* Initialization */
1232        if (fd == NULL)
1233        {
1234                if ((fd = fopen (BUDP_P_Getud_Filename, "w")) == 0)
1235                {
1236                        fprintf (stderr, "ERROR: could not open %s for debug output\n",
1237                                BUDP_P_Getud_Filename);
1238                        return;
1239                }
1240                fprintf (fd, "getud output format version 1\n");
1241                nPicture = 0;
1242        }
1243
1244        fprintf (fd, "\nPic %u LOC %06lx TR %u\n", ++nPicture, 0UL, 0U);
1245        fprintf (fd, "PS %d TFF %d RFF %d\n",
1246                pUserdata_info->eSourcePolarity,
1247                pUserdata_info->bTopFieldFirst,
1248                pUserdata_info->bRepeatFirstField);
1249        fprintf (fd, "UDBYTES %u\n", length);
1250    for (iByte = 0 ; iByte < length ; ++iByte)
1251    {
1252        fprintf (fd, "%02x", userdata[iByte]);
1253        if ((iByte % 16) == 15)
1254            putc ('\n', fd);
1255        else
1256            putc (' ', fd);
1257    }
1258    if ((iByte % 16) != 15)
1259        putc ('\n', fd);
1260}
1261#endif
Note: See TracBrowser for help on using the repository browser.