source: svn/newcon3bcm2_21bu/BSEAV/lib/scte_127/scte_127.c @ 46

Last change on this file since 46 was 46, checked in by megakiss, 11 years ago

459Mhz로 OTC 주파수 변경

  • Property svn:executable set to *
File size: 26.7 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2008, 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:  $
11 * $brcm_Revision:  $
12 * $brcm_Date: $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log:  $
19 *
20 ***************************************************************************/
21#include "scte_127.h"
22#include "pes_scte_127.h"
23#include "bapp_amol.h"
24#include "bapp_gs.h"
25#include "bstd.h"
26#include "bkni.h"
27#include "ministd.h"
28#include "gist.h"
29
30#include "bvbi_chip_priv.h"
31#if (BVBI_P_NUM_GSE >= 1)
32#include "bchp_gse_0.h"  /* RDB info for primary Gemstar encoder core */
33#endif
34#if (BVBI_P_NUM_GSE >= 2)
35#include "bchp_gse_1.h"   /* RDB info for secondary Gemstar encoder core */
36#endif
37#if (BVBI_P_NUM_GSE >= 3)
38#include "bchp_gse_2.h"  /* RDB info for tertiary Gemstar encoder core */
39#endif
40#if (BVBI_P_NUM_GSE_656 >= 1)
41#include "bchp_gse_ancil_0.h"   /* RDB info for bypass Gemstar encoder core */
42#endif
43
44#ifndef USE_LEGACY_AMOL_GS
45/* to use VBI lib functions instead */
46#include "bsettop_display.h"
47/*#include "bvbi.h"*/
48#endif
49
50BDBG_MODULE(scte_127);
51
52#ifndef SCTE_ASSERT
53#define SCTE_ASSERT(expr) {                                         \
54    if (!expr)                                                      \
55        printf("%s failed at %s:%d\n",#expr, __FILE__, __LINE__);   \
56    }
57#endif
58
59#define SCTE_127_MUTEX_TIMEOUT                  (g_ticks_per_second * 2)
60
61#ifdef  USE_LEGACY_AMOL_GS
62static bapp_amol_t      g_p_amol = NULL;        /* pointer to amol encoder object */
63static bapp_gs_t        g_p_gs = NULL;          /* pointer to Gemstar (TVG2X) encoder object */
64#endif
65
66static pscte_127_handle s_pscte_127 = NULL;
67
68/*
69 * This function is used to return scte 127 handle
70 *
71 * Parameters:
72 *      NONE
73 *
74 * Returns:
75 *      pointer to scte_127_handle if success
76*/
77pscte_127_handle scte_127_get_handle(void)
78{
79        return s_pscte_127;
80}
81
82/*
83 * This function is used to initialize scte 127 object
84 *
85 * Parameters:
86 *      NONE
87 *
88 * Returns:
89 *      pointer to scte_127_handle if success
90 *      NULL otherwise
91*/
92pscte_127_handle scte_127_init(void)
93{
94        pscte_127_handle        pscte_127;
95        pscte_127_data          pdata;
96        int i;
97
98        BDBG_MSG(("%s: enter", __func__));
99
100        pscte_127 = (pscte_127_handle)malloc(sizeof(scte_127_handle));
101        if (NULL == pscte_127) {
102                BDBG_ERR(("%s: no memory", __func__));
103                return NULL;
104        }       
105        memset(pscte_127, 0, sizeof(scte_127_handle));
106
107        for (i = 0; i < SCTE_127_MAX_FIELD; i++) {
108                initl(&pscte_127->amol_list[i]);
109                initl(&pscte_127->gs_list[i]);
110        }
111        initl(&pscte_127->free_list);
112
113        /* put all buffer in free list */
114        for (i = 0; i < SCTE_127_NUM_DATA_BUF; i++)
115        {
116                pdata = &(pscte_127->data[i]);
117                inslt(&(pscte_127->free_list), pdata);
118        }
119
120#ifdef  USE_LEGACY_AMOL_GS
121/* no AMOL for PAL */
122#if (DISPLAY_NTSC == 1)
123        g_p_amol = bapp_amol_open(NULL);
124        if (!g_p_amol) {
125                scte_127_deinit(pscte_127);
126                BDBG_ERR(("%s: open AMOL module failed", __func__));
127                return NULL;
128        }
129#endif
130        g_p_gs = bapp_gs_open(NULL);
131        if (!g_p_gs) {
132                scte_127_deinit(pscte_127);
133                BDBG_ERR(("%s: open GemStar module failed", __func__));
134                return NULL;
135        }
136
137#if (DISPLAY_NTSC == 1)
138        bapp_amol_enable(g_p_amol, 1);  /* enable AMOL */
139#endif
140        bapp_gs_enable(g_p_gs, 1);      /* enable GemStar */
141#endif
142
143        BDBG_MSG(("%s: leave", __func__));
144
145        s_pscte_127 = pscte_127;
146
147        return pscte_127;
148}
149
150/*
151 * This function is used to de-initialize scte 127 object initialize before
152 *
153 * Parameters:
154 *      pointer to scte 127 handle
155 *
156 * Returns:
157 *      NONE
158*/
159void scte_127_deinit(pscte_127_handle pscte_127)
160{
161        BDBG_MSG(("%s: enter", __func__));
162
163        if (!pscte_127) {
164                BDBG_MSG(("%s: null pointer", __func__));
165                return;
166        }
167
168#ifdef  USE_LEGACY_AMOL_GS
169        if (g_p_amol) {
170                bapp_amol_enable(g_p_amol, 0);  /* diable AMOL */
171                bapp_amol_close(g_p_amol);
172                g_p_amol = NULL;
173        }
174
175        if (g_p_gs) {
176                bapp_gs_enable(g_p_gs, 0);      /* diable GemStar */
177                bapp_gs_close(g_p_gs);
178                g_p_gs = NULL;
179        }
180#endif
181
182        free(pscte_127);
183
184        BDBG_MSG(("%s: leave", __func__));
185}
186
187/* will use a new fast swap when necessary */
188void scte_bit_swap(unsigned char *pbuf, int size)
189{
190        unsigned char c, c1, i;
191
192        while (size) {
193                c1 = 0;
194                c = *pbuf;
195                for (i = 0; i < 7; i++) {
196                        c1 |= (c & 0x1);
197                        c = c >> 1;
198                        c1 = c1 << 1;
199                }
200                c1 |= (c & 0x1);
201                *pbuf++ = c1;
202                size--;
203        }
204}
205
206/*
207 * parsing pes data field of giving packet for a data unit block
208 *
209 * Parameters:
210 *      packet[in]      pointer to the data unit of PES packet
211 *      size[in]        length of data buffer
212 *      data[out]       pointer to scte_127_data structure for holding the data
213 *      unit_type[out]  pointer for holding date unit type if found
214 *
215 * Returns:
216 *      number of bytes consumed
217 *      0 if no data is found
218*/
219int scte_pes_data_field(unsigned char *packet, int size, scte_127_data *data, int *unit_type)
220{
221        int bytes = 0, data_unit_id, data_unit_length;
222        unsigned char *buf = packet;
223       
224        BDBG_MSG(("%s: enter", __func__));
225
226        if (!packet || size < (SCTE_127_DATA_UNIT_ID_CP_LEN + 2) || !data || !unit_type) {
227                BDBG_ERR(("%s: invalid parameter", __func__));
228                return 0;
229        }
230
231        data_unit_id = buf[0];
232        data_unit_length = buf[1];
233
234        switch (data_unit_id)
235        {
236                case SCTE_127_DATA_UNIT_ID_AMOL48:
237                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_AMOL48_LEN) {
238                                /* skip data field header */
239                                bytes += 2;
240                                /* data unit header */
241                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
242                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
243                                if (!(data->line_offset >= 10 && data->line_offset <= 22))
244                                        BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset));
245                                bytes++;
246                                data->u.amol48[0] = AMOL_SOM_48 | (buf[bytes] & 0x80); bytes++;
247                                data->u.amol48[1] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++;
248                                data->u.amol48[2] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++;
249                                data->u.amol48[3] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++;
250                                data->u.amol48[4] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++;
251                                data->u.amol48[5] = (buf[bytes - 1] & 0x7f) | (buf[bytes] & 0x80); bytes++;
252                                data->u.amol48[6] = 0;
253                                data->u.amol48[7] = 0;
254                                data->u.amol48[8] = 0;
255                                data->u.amol48[9] = 0;
256                                data->u.amol48[10] = 0;
257                                data->u.amol48[11] = 0;
258                                data->u.amol48[12] = 0;
259                                *unit_type = data_unit_id;
260                                return bytes;
261                        }
262                        break;
263       
264                case SCTE_127_DATA_UNIT_ID_AMOL96:
265                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_AMOL96_LEN) {
266                                /* skip data field header */
267                                bytes += 2;
268                                /* data unit header */
269                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
270                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
271                                if (!(data->line_offset >= 10 && data->line_offset <= 22))
272                                        BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset));
273                                bytes++;
274                                data->u.amol96[ 0] = AMOL_SOM_96;
275                                data->u.amol96[ 1] = buf[bytes]; bytes++;
276                                data->u.amol96[ 2] = buf[bytes]; bytes++;
277                                data->u.amol96[ 3] = buf[bytes]; bytes++;
278                                data->u.amol96[ 4] = buf[bytes]; bytes++;
279                                data->u.amol96[ 5] = buf[bytes]; bytes++;
280                                data->u.amol96[ 6] = buf[bytes]; bytes++;
281                                data->u.amol96[ 7] = buf[bytes]; bytes++;
282                                data->u.amol96[ 8] = buf[bytes]; bytes++;
283                                data->u.amol96[ 9] = buf[bytes]; bytes++;
284                                data->u.amol96[10] = buf[bytes]; bytes++;
285                                data->u.amol96[11] = buf[bytes]; bytes++;
286                                *unit_type = data_unit_id;
287                                return bytes;
288                        }
289                        break;
290
291#ifdef  SCTE_127_NABTS
292                case SCTE_127_DATA_UNIT_ID_NABTS:
293                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_NABTS_LEN) {
294                                unsigned char framing_code;
295
296                                /* skip data field header */
297                                bytes += 2;
298                                /* data unit header */
299                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
300                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
301                                if (!(data->line_offset >= 10 && data->line_offset <= 22))
302                                        BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset));
303                                bytes++;
304                                framing_code = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]); bytes++;
305                                //SCTE_ASSERT(SCTE_127_DATA_NABTS_FRAMING_CODE == framing_code);
306                                BKNI_Memcpy(data->u.nabts, &buf[bytes], SCTE_127_DATA_UNIT_ID_NABTS_LEN - 2);   
307                                bytes += SCTE_127_DATA_UNIT_ID_NABTS_LEN - 2;
308                                *unit_type = data_unit_id;
309                                return bytes;
310                        }
311                        break;
312#endif
313
314                case SCTE_127_DATA_UNIT_ID_TVG2X:
315                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_TVG2X_LEN) {
316                                /* skip data field header */
317                                bytes += 2;
318                                /* data unit header */
319                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
320                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
321                                if (!(data->line_offset >= 10 && data->line_offset <= 22))
322                                        BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset));
323                                bytes++;
324                                /* RLQ, to make sure the byte order to match byte_swap_video_sample setting */
325                                data->u.tvg2x = (uint32_t)((buf[bytes] << 24) + (buf[bytes + 1] << 16) + 
326                                        (buf[bytes + 2] << 8) + buf[bytes + 3]);
327                                //data->u.tvg2x = (uint32_t)(buf[bytes] + (buf[bytes + 1] << 8) +
328                                //      (buf[bytes + 2] << 16) + (buf[bytes + 3] << 24));
329                                bytes += SCTE_127_DATA_UNIT_ID_TVG2X_LEN - 1;
330                                *unit_type = data_unit_id;
331                                return bytes;
332                        }
333                        break;
334
335                case SCTE_127_DATA_UNIT_ID_VITC:
336                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_VITC_LEN) {
337                                /* skip data field header */
338                                bytes += 2;
339                                /* data unit header */
340                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
341                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
342                                if (!(data->line_offset >= 14 && data->line_offset <= 22))
343                                        BDBG_WRN(("%s: invalid line %d", __func__, data->line_offset));
344                                bytes++;
345                                BKNI_Memcpy(data->u.vitc, &buf[bytes], SCTE_127_DATA_UNIT_ID_VITC_LEN - 1);
346                                bytes += SCTE_127_DATA_UNIT_ID_VITC_LEN - 1;
347                                *unit_type = data_unit_id;
348                                return bytes;
349                        }
350                        break;
351
352                case SCTE_127_DATA_UNIT_ID_CP:
353                        if ((size - 2) >= SCTE_127_DATA_UNIT_ID_CP_LEN) {
354                                /* skip data field header */
355                                bytes += 2;
356                                /* data unit header */
357                                data->field_parity = SCTE_127_DATA_UNIT_FIELD_PARITY(buf[bytes]);
358                                data->line_offset = SCTE_127_DATA_UNIT_LINE_OFFSET(buf[bytes]);
359                                bytes++;
360                                data->u.cp[0] = buf[bytes]; bytes++;
361                                *unit_type = data_unit_id;
362                                return bytes;
363                        }
364                        break;
365
366                default:
367                        BDBG_WRN(("%s: unsupported data unit id (0x%02x)", __func__, data_unit_id));
368                        return 0;
369        }
370
371        BDBG_MSG(("%s: leave", __func__));
372
373        return 0;
374}
375
376/*
377 * go through pes data field block of giving packet for data units
378 *
379 * Parameters:
380 *      pscte_127[in]   pointer to scte_127 handle
381 *      packet[in]      pointer to the data unit id of PES packet
382 *      size[in]        length of data packet
383 *
384 * Returns:
385 *      1 if success
386 *      0 if no data is found or error
387*/
388int scte_127_pes_data_field_parser(pscte_127_handle pscte_127, unsigned char *pdata_id, int size)
389{
390        unsigned int flags;
391        scte_127_data *data;
392        int unit_type;
393        uint8_t *p;
394        int len = 0;
395        uint16_t term;
396
397        BDBG_MSG(("%s: enter", __func__));
398
399        SCTE_ASSERT(pscte_127 && pdata_id && size);
400       
401        if (SCTE_127_DATA_ID != *pdata_id) {
402                BDBG_ERR(("%s: invalid data id (0x%2x)", __func__, *pdata_id));
403                return 0;
404        }
405        p = (uint8_t *)pdata_id;
406        p++;    /* skip data unit id */
407        size--;
408
409        do {
410                switch ((int)*p)
411                {
412                        default:
413                                term = TS_READ_16(p) & 0xff00;
414                                if ((0xff00 == term) || (0xffff == term)) {
415                                        /* terminator, normal */
416                                        BDBG_MSG(("%s: terminated\n", __func__));
417                                        return 1;
418                                }
419                                return 0;
420
421                        case SCTE_127_DATA_UNIT_ID_AMOL48:
422                                len = (int)*(p + 1);
423                                if (len != SCTE_127_DATA_UNIT_ID_AMOL48_LEN) {
424                                        /* wrong data unit, quit */
425                                        BDBG_ERR(("%s: invalid AMOL48 data unit size (%d)\n", __func__, len));
426                                        return 0;
427                                }
428                                break;
429
430                        case SCTE_127_DATA_UNIT_ID_AMOL96:
431                                len = (int)*(p + 1);
432                                if (len != SCTE_127_DATA_UNIT_ID_AMOL96_LEN) {
433                                                /* wrong data unit, quit */
434                                                BDBG_ERR(("%s: invalid AMOL96 data unit size (%d)\n", __func__, len));
435                                                return 0;
436                                }
437                                break;
438
439                        case SCTE_127_DATA_UNIT_ID_TVG2X:
440                                len = (int)*(p + 1);
441                                if (len != SCTE_127_DATA_UNIT_ID_TVG2X_LEN) {
442                                                /* wrong data unit, quit */
443                                                BDBG_ERR(("%s: invalid TVG2X data unit size (%d)\n", __func__, len));
444                                                return 0;
445                                }
446                                break;
447                }       
448
449                /* get data buffer from free pool */
450                flags = bos_enter_critical();
451                data = (pscte_127_data)remlh(&(pscte_127->free_list));
452                bos_exit_critical(flags);
453                if (data) {
454                                if (scte_pes_data_field(p, size, data, &unit_type)) {
455                                                data->data_unit_type = unit_type;
456                                                /* specific to AMOL */
457                                                if (SCTE_127_DATA_UNIT_ID_AMOL48 == unit_type) 
458                                                                data->amol_type = AMOL_TYPE_I;
459                                                else if (SCTE_127_DATA_UNIT_ID_AMOL96 == unit_type)
460                                                                data->amol_type = AMOL_TYPE_II_1M;
461
462                                                if (!scte_127_queue_data(pscte_127, data)) {
463                                                                BDBG_WRN(("%s: scte_127_queue_data failed", __func__));
464                                                                /* put buffer back to free list */
465                                                                scte_127_queue_buffer(pscte_127, data);
466                                                                return 0;
467                                                }
468                                }
469                                else {
470                                                BDBG_ERR(("%s: invalid pes data field", __func__));
471                                                /* put buffer back to free list */
472                                                scte_127_queue_buffer(pscte_127, data);
473                                                return 0;
474                                }
475                }
476                else {
477                                BDBG_WRN(("%s: no free data buffer\n", __func__));
478                                /* reset buffer */
479                                scte_127_reset(pscte_127);
480                                return 0;
481                }
482                p += (len + 1) + 1;
483                size -= ((len + 1) + 1);
484        } while ((size - 2) > 0);
485
486        BDBG_MSG(("%s: leave", __func__));
487
488        return 1;
489}
490
491/*
492 * To queue given data to list. This function should be called from within SCTE 127
493 * data extraction thread.
494 *
495 * Parameters:
496 *      pscte_127       pointer to scte_127 handle
497 *      pdata           pointer to scte_127_data structure to queue
498 *
499 * Returns:
500 *      1 if success
501 *      0 otherwise
502 */
503int scte_127_queue_data(pscte_127_handle pscte_127, pscte_127_data pdata)
504{
505        unsigned int flags;
506
507        BDBG_MSG(("%s: enter", __func__));
508
509        if (!pscte_127 || !pdata) {
510                BDBG_ERR(("%s: NULL pointer", __func__));
511                return 0;
512        }
513
514        /* validation, and drop invalidated data early */
515        if (!(0 == pdata->field_parity || 1 == pdata->field_parity)) {
516                BDBG_ERR(("%s: invalid field parity %d", __func__, pdata->field_parity));
517                return 0;
518        }
519
520        switch (pdata->data_unit_type) {
521                /* currently we support following data type */
522                case SCTE_127_DATA_UNIT_ID_AMOL48:
523                case SCTE_127_DATA_UNIT_ID_AMOL96:
524                        /* validation, and drop invalidated data early */
525                        if (20 != pdata->line_offset && 22 != pdata->line_offset) {
526                                BDBG_WRN(("%s: invalid line offset, drop", __func__));
527                                return 0;
528                        }
529
530#if (DISPLAY_PAL == 1) || (DISPLAY_PAL_NC == 1)
531                        /* no AMOL for PAL, so drop it */
532                        return 1;
533#endif
534                        flags = bos_enter_critical();
535                        /* AMOL should be in pdata->u.amol48/96 */
536                        inslt(&(pscte_127->amol_list[pdata->field_parity]), pdata);
537                        pscte_127->amol_count[pdata->field_parity]++;
538                        bos_exit_critical(flags);
539                        break;
540
541                case SCTE_127_DATA_UNIT_ID_TVG2X:
542                        /* validation, and drop invalidated data early */
543                        if (pdata->line_offset < 10 || pdata->line_offset > 22) {
544                                BDBG_WRN(("%s: invalid line offset, drop", __func__));
545                                return 0;
546                        }
547                        flags = bos_enter_critical();
548                        /* GS should be in pdata->u.tvg2x */
549                        inslt(&(pscte_127->gs_list[pdata->field_parity]), pdata);
550                        pscte_127->gs_count[pdata->field_parity]++;
551                        bos_exit_critical(flags);
552                        break;
553
554                default:
555                        BDBG_ERR(("%s: not supported data type 0x%2x", __func__, pdata->data_unit_type));
556                        return 0;
557        }
558
559        BDBG_MSG(("%s: leave", __func__));
560
561        return 1;
562}
563
564/*
565 * to put buffer back to free list.
566 *
567 * Parameters:
568 *      pscte_127       pointer to scte_127 handle
569 *      pdata           pointer to scte_127_data structure to free list
570 *
571 * Returns:
572 *      1 if success
573 *      0 otherwise
574 */
575int scte_127_queue_buffer(pscte_127_handle pscte_127, pscte_127_data pdata)
576{
577        unsigned int flags;
578
579        BDBG_MSG(("%s: enter", __func__));
580
581#ifdef  DEBUG
582        if (!pscte_127 || !pdata) {
583                BDBG_ERR(("%s: NULL pointer", __func__));
584                return 0;
585        }
586#endif
587
588        flags = bos_enter_critical();
589        /* the real data from SCTE 127, e.g. AMOL should be in pdata->u.amol48/96 already */
590        inslt(&(pscte_127->free_list), pdata);
591        bos_exit_critical(flags);
592
593        BDBG_MSG(("%s: leave", __func__));
594
595        return 1;
596}
597
598/*
599 * This function is used to check if there are any scte 127 data in the lists
600 *
601 * Parameters:
602 *      pscte_127       pointer to scte_127 handle
603 *
604 * Returns:
605 *      count of data (AMOL + GS in both even and odd field lists)
606 *      0 otherwise
607 */
608int scte_127_has_data(pscte_127_handle pscte_127, int parity)
609{
610        if (parity < 0 || parity > 1)
611                return 0;
612
613        return (pscte_127->amol_count[parity] + pscte_127->gs_count[parity]);
614}
615
616/*
617 * This function is used to reset scte 127, clear list. e.g. Used after channel change.
618 *
619 * Parameters:
620 *      pscte_127       pointer to scte_127 handle
621 *
622 * Returns:
623 *      1 if success
624 *      0 otherwise
625 */
626int scte_127_reset(pscte_127_handle pscte_127)
627{
628        pscte_127_data  pdata;
629        unsigned int    flags;
630        int i;
631
632        BDBG_MSG(("%s: enter", __func__));
633
634        if (NULL == pscte_127) {
635                BDBG_WRN(("%s: null pointer", __func__));
636                return 0;
637        }       
638
639        /* if no data in the lists, simply return */
640        if ((0 == (scte_127_has_data(pscte_127, 0)) && (0 == scte_127_has_data(pscte_127, 1))))
641                return 1;
642
643        flags = bos_enter_critical();
644        initl(&pscte_127->amol_list[0]);
645        initl(&pscte_127->amol_list[1]);
646        initl(&pscte_127->gs_list[0]);
647        initl(&pscte_127->gs_list[1]);
648        initl(&pscte_127->free_list);
649        pscte_127->amol_count[0] = 0;
650        pscte_127->amol_count[1] = 0;
651        pscte_127->gs_count[0] = 0;
652        pscte_127->gs_count[1] = 0;
653
654        /* put all buffer in free list */
655        for (i = 0; i < SCTE_127_NUM_DATA_BUF; i++)
656        {
657                pdata = &(pscte_127->data[i]);
658                inslt(&(pscte_127->free_list), pdata);
659        }
660        bos_exit_critical(flags);
661
662        BDBG_MSG(("%s: leave", __func__));
663        return 1;
664}
665
666#ifdef  USE_LEGACY_AMOL_GS
667/*
668 * feed scte 127 data object to corresonding encoder, like AMOL. This function
669 * should be called from within VBI ISR to feed data to SCTE 127 module for
670 * encoding/transcoding.
671 *
672 * Parameters:
673 *      pscte_127       pointer to scte_127 handle
674 *      parity          parity to process
675 *
676 * Returns:
677 *      1 if success
678 *      0 otherwise
679 */
680int scte_127_feed_data_buf(pscte_127_handle pscte_127, int parity)
681{
682        pscte_127_data  pdata, pdata_list[SCTE_127_MAX_GS_DATA];
683        unsigned int flags, amol_pair = 0, gs_count = 0, gs_line = 0, i;
684
685        BDBG_MSG(("%s: enter", __func__));
686
687#if DEBUG
688        if (!pscte_127) {
689                BDBG_ERR(("%s: NULL pointer", __func__));
690                return 0;
691        }
692#endif
693
694        if (parity < 0 || parity > 1) {
695                BDBG_MSG(("%s: invalid parity", __func__));
696                return 0;
697        }
698
699        /* process AMOL data first */
700        if (pscte_127->amol_count[parity] < 1) {
701                BDBG_MSG(("%s: no AMOL data", __func__));
702                goto PROCESS_GS;
703        }
704
705PROCESS_AMOL:
706        flags = bos_enter_critical();
707        pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity]));
708        if (pdata) 
709                pscte_127->amol_count[parity]--;
710        bos_exit_critical(flags);
711        if (!pdata) {
712                /* something wrong? */
713                BDBG_WRN(("%s: Oops AMOL is wrong", __func__));
714                goto PROCESS_GS;
715        }
716
717        if (0 == amol_pair) {
718                /* try next if any */
719                if (pscte_127->amol_count[parity]) {
720                        pdata_list[0] = pdata;
721                        amol_pair++;
722                        goto PROCESS_AMOL;     
723                }
724                /* if only one in the list */
725                bapp_amol_set_scte_127(g_p_amol, pdata);
726                scte_127_queue_buffer(pscte_127, pdata);
727                amol_pair = 1;
728        }
729        else {
730                /* now check the line offset to make sure they are not same */
731                if (pdata_list[0]->line_offset >= pdata->line_offset) {
732                        /* put back to head of the queue */     
733                        flags = bos_enter_critical();
734                        inslh(&(pscte_127->amol_list[parity]), pdata);
735                        pscte_127->amol_count[parity]++;
736                        bos_exit_critical(flags);
737
738                        bapp_amol_set_scte_127(g_p_amol, pdata_list[0]);
739                        scte_127_queue_buffer(pscte_127, pdata_list[0]);
740                }
741                else {
742                        bapp_amol_set_scte_127_ex(g_p_amol, pdata_list[0], pdata);
743                        flags = bos_enter_critical();
744                        inslt(&(pscte_127->free_list), pdata_list[0]);
745                        inslt(&(pscte_127->free_list), pdata);
746                        bos_exit_critical(flags);
747                }
748        }
749
750PROCESS_GS:
751        /* process GS data */
752        if (pscte_127->gs_count[parity] < 1) {
753                BDBG_MSG(("%s: no GS data", __func__));
754                return amol_pair ? 1 : 0;
755        }
756
757        do {
758                flags = bos_enter_critical();
759                pdata = (pscte_127_data)remlh(&(pscte_127->gs_list[parity]));
760                if (pdata) 
761                        pscte_127->gs_count[parity]--;
762                bos_exit_critical(flags);
763                if (!pdata) {
764                        BDBG_WRN(("%s: Oops GS is wrong", __func__));
765                        /* something wrong? */
766                        break;
767                }
768
769                if (gs_count) {
770                        if (gs_line >= pdata->line_offset) {
771                                /* we are done for this field, put back to head of the queue */ 
772                                flags = bos_enter_critical();
773                                inslh(&(pscte_127->gs_list[parity]), pdata);
774                                pscte_127->gs_count[parity]++;
775                                bos_exit_critical(flags);
776                                break;
777                        }       
778                }
779                pdata_list[gs_count] = pdata;
780                /* remember current line */
781                gs_line = pdata->line_offset;
782        } while (gs_count++ < SCTE_127_MAX_GS_DATA && (pscte_127->gs_count[parity] > 0));
783
784        /* process buffer */
785        bapp_gs_set_scte_127_list(g_p_gs, gs_count, pdata_list);
786        /* release buffer */
787        flags = bos_enter_critical();
788        for (i = 0; i < gs_count; i++) {
789                inslt(&(pscte_127->free_list), pdata_list[i]);
790        }
791        bos_exit_critical(flags);
792
793        BDBG_MSG(("%s: leave", __func__));
794
795        return 1;
796}
797#else
798int scte_127_feed_data_buf(pscte_127_handle pscte_127, int parity)
799{
800        return 0;
801}
802#endif
803
804#ifdef HAS_VBI
805/*
806 * set GS active line and base for given parity
807 *
808 * Parameters:
809 *      pscte_127       pointer to scte_127 handle
810 *      parity                  parity to set
811 *      base                    base
812 *      line_mask               mask for given line
813 *
814 * Returns:
815 *      1 if success
816 *      0 otherwise
817 */
818int scte_127_set_gs_line_mask(pscte_127_handle pscte_127, int parity, unsigned int base, unsigned int line_mask)
819{
820        unsigned int regVal;
821
822#if (BVBI_P_NUM_GSE >= 1)
823    if (!pscte_127) {
824                BDBG_MSG(("%s: null pointer", __func__));
825                return 0;
826    }
827        /* currently use GSE 0 only */
828        if (parity) {
829        regVal = BREG_Read32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_BOT);
830        regVal &= ~(BCHP_MASK(GSE_0_ACTIVE_LINE_BOT, ACTIVE_LINE) | 
831                                        BCHP_MASK(GSE_0_ACTIVE_LINE_BOT, BASE));
832        regVal |= BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_BOT, ACTIVE_LINE, line_mask) | 
833                                        BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_BOT, BASE, base);
834                BREG_Write32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_BOT, regVal + 7); /* GES encoder will adjust by -7 */
835        }
836        else {
837        regVal = BREG_Read32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_TOP);
838        regVal &= ~(BCHP_MASK(GSE_0_ACTIVE_LINE_TOP, ACTIVE_LINE) |
839                    BCHP_MASK(GSE_0_ACTIVE_LINE_TOP, BASE));
840        regVal |= BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_TOP, ACTIVE_LINE, line_mask) |
841                    BCHP_FIELD_DATA(GSE_0_ACTIVE_LINE_TOP, BASE, base);
842                BREG_Write32(GetREG(), BCHP_GSE_0_ACTIVE_LINE_TOP, regVal);
843        }
844#endif
845
846        return 1;
847}
848
849/*
850 * to put buffer back to free list.
851 *
852 * Parameters:
853 *      pscte_127       pointer to scte_127 handle
854 *      pdata           pointer to scte_127_data structure to free list
855 *
856 * Returns:
857 *      1 if success
858 *      0 otherwise
859 */
860int scte_127_queue_buffer_isr(pscte_127_handle pscte_127, pscte_127_data pdata)
861{
862    /* the real data from SCTE 127, e.g. AMOL should be in pdata->u.amol48/96 already */
863        if (pdata) {
864        inslt(&(pscte_127->free_list), pdata);
865        return 1;
866        }
867        return 0;
868}
869
870pscte_127_data scte_127_get_amol_data_buf_isr(pscte_127_handle pscte_127, int parity)
871{
872    pscte_127_data  pdata = NULL;
873        unsigned int flags;
874
875    BDBG_MSG(("%s: enter", __func__));
876
877    if (parity < 0 || parity > 1) {
878        BDBG_WRN(("%s: invalid parity", __func__));
879        return NULL;
880    }
881
882    /* process AMOL data first */
883    if (pscte_127->amol_count[parity] < 1) {
884        return NULL;
885    }
886    flags = bos_enter_critical();
887    pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity]));
888    if (pdata)
889        pscte_127->amol_count[parity]--;
890    bos_exit_critical(flags);
891       
892        return pdata;
893}
894
895bool scte_127_get_amol_data_buf_isr_ex(pscte_127_handle pscte_127, int parity, int *type, unsigned char *amol_data)
896{
897        pscte_127_data  pdata = NULL, line_offset = 0;
898        unsigned int flags, amol_pair = 0;
899
900    BDBG_MSG(("%s: enter", __func__));
901
902        *type = AMOL_TYPE_NONE;
903    if (parity < 0 || parity > 1) {
904        BDBG_WRN(("%s: invalid parity", __func__));
905        return false;
906    }
907
908    /* process AMOL data first */
909    if (pscte_127->amol_count[parity] < 1) {
910        return false;
911    }
912
913PROCESS_AMOL:
914        flags = bos_enter_critical();
915    pdata = (pscte_127_data)remlh(&(pscte_127->amol_list[parity]));
916        if (pdata) 
917                pscte_127->amol_count[parity]--;
918        bos_exit_critical(flags);
919        if (!pdata) {
920                /* something wrong? */
921                BDBG_WRN(("%s: Oops AMOL is wrong", __func__));
922                return false;
923        }
924
925        if (0 == amol_pair) {
926                /* try next if any */
927                amol_pair++;
928                *type = pdata->amol_type;
929                memcpy(amol_data, pdata->u.amol96, sizeof(pdata->u.amol96));
930                line_offset = pdata->line_offset;
931                scte_127_queue_buffer(pscte_127, pdata);
932                if (pscte_127->amol_count[parity]) {
933                        goto PROCESS_AMOL;     
934                }
935        }
936        else {
937                /* now check the line offset to make sure they are not same */
938                if (line_offset >= pdata->line_offset) {
939                        /* put back to head of the queue */     
940                        flags = bos_enter_critical();
941                        inslh(&(pscte_127->amol_list[parity]), pdata);
942                        pscte_127->amol_count[parity]++;
943                        bos_exit_critical(flags);
944                }
945                else {
946                        /* force to set AMOL96 high bit rate */
947                        *type = AMOL_TYPE_II_2M;
948                        memcpy(&amol_data[12], pdata->u.amol96, sizeof(pdata->u.amol96));
949                        scte_127_queue_buffer(pscte_127, pdata);
950                }
951        }
952        /* we have AMOL data */
953        return true;
954}
955
956int scte_127_get_gs_data_buf_isr(pscte_127_handle pscte_127, int parity, int *line_offset, int *gs_count, uint32_t *gs_data)
957{
958        static pscte_127_data  pdata = NULL;
959        unsigned int count = 0, gs_line = 0;
960
961        /* function is called from within ISR routine, so don't need critical section  */
962        if (parity < 0 || parity > 1) {
963                BDBG_MSG(("%s: invalid parity", __func__));
964                return 0;
965        }
966
967        /* process GS data */
968        if (pscte_127->gs_count[parity] < 1) {
969                BDBG_MSG(("%s: no GS data", __func__));
970                return 0;
971        }
972
973        do {
974                pdata = (pscte_127_data)remlh(&(pscte_127->gs_list[parity]));
975                if (pdata)
976                        pscte_127->gs_count[parity]--;
977                if (!pdata) {
978                        BDBG_WRN(("%s: Oops GS is wrong", __func__));
979                        /* something wrong? */
980                        gs_count = 0;
981                        return 0;
982                }
983
984                if (count) {
985                        if (gs_line >= pdata->line_offset) {
986                                /* we are done for this field, put back to head of the queue */
987                                inslh(&(pscte_127->gs_list[parity]), pdata);
988                                pscte_127->gs_count[parity]++;
989                                break;
990                        }
991                }
992                else {
993                        /* start line for GS data */
994                        *line_offset = pdata->line_offset;
995                }
996                gs_data[count] = pdata->u.tvg2x;
997                /* remember current line */
998                gs_line = pdata->line_offset;
999                inslt(&(pscte_127->free_list), pdata);
1000        } while (count++ < SCTE_127_MAX_GS_DATA && (pscte_127->gs_count[parity] > 0));
1001
1002        *gs_count = count;
1003        BDBG_MSG(("%s: leave", __func__));
1004
1005        return 1;
1006}
1007#endif
1008
1009/*
1010 * enable/disable SCTE 127 (AMOL and GS)
1011 *
1012 * Parameters:
1013 *  pscte_127   pointer to scte_127 handle
1014 *  enable      enable/disable SCTE 127 module
1015 *
1016 * Returns:
1017 *      NONE
1018 */
1019void scte_127_enable(pscte_127_handle pscte_127, int enable)
1020{
1021#ifdef  USE_LEGACY_AMOL_GS
1022#if (DISPLAY_NTSC == 1)
1023        bapp_amol_enable(g_p_amol, enable); 
1024#endif
1025        bapp_gs_enable(g_p_gs, enable);
1026#endif
1027
1028#ifdef HAS_VBI
1029        scte_127_reset(pscte_127);
1030        bdisplay_vbi_enable_amol_gs(enable);
1031#endif
1032}
1033
Note: See TracBrowser for help on using the repository browser.