source: svn/trunk/newcon3bcm2_21bu/dta/src/dvb/dvb_subtitle.c @ 28

Last change on this file since 28 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 39.6 KB
Line 
1
2#include "bapp.h"
3#include "dvb_subtitle.h"
4#include "bos.h"
5#include "bos_task_priorities.h"
6#include "bgfx.h"
7#include "bsettop_decode.h"
8#include "genericlist.h"
9
10BDBG_MODULE(dsub);
11
12
13#define MAX_DSUB_EVENT          10
14#define DSUB_PARSER_STACK_SIZE  1024
15#define DSUB_DRAW_STACK_SIZE    1024
16#define DSUB_PES_HDR_LEN            6
17
18#define DSUB_WIDTH              720
19#define DSUB_HEIGHT             576
20#define DSUB_NUM_WNDS                   20
21#define DSUB_MAX_WIN_HEIGHT             50
22
23typedef struct surf_node_t {
24        LINKS_T links;
25        bgfx_surf_t surf;
26} surf_node_t;
27
28/* page composition segment */
29struct dsub_page_region
30{
31        uint8_t  region_id;  /* region_id */
32        uint16_t horizontal; /* region_horizontal_address */
33        uint16_t vertical;   /* region_vertical_address */
34//      struct dsub_page_region *next;
35};
36
37struct dsub_region_object
38{
39        uint16_t obj_id;            /* object_id */
40        uint8_t  obj_type;          /* object_type */
41        uint8_t  obj_provider_flag; /* object_provider_flag */ 
42        uint16_t obj_h_pos;         /* object_horizontal_position */
43        uint16_t obj_v_pos;         /* object_vertical_position */
44        uint8_t fore_pixel;         /* foreground_pixel_code */
45        uint8_t back_pixel;         /* background_pixel_code */
46        struct dsub_region_object *next;
47};
48
49/* region composition segment */
50struct dsub_region
51{
52        uint8_t region_id;       /* region_id */
53        uint8_t region_version;  /* region_version_number */
54        uint16_t region_width;   /* region_width */
55        uint16_t region_height;  /* region_height */
56        uint8_t *region_buffer;
57        surf_node_t *region_surf;       
58
59        uint8_t clut_id;         /* CLUT_id */
60        struct dsub_region_object *region_objects;
61        struct dsub_region *next;
62};
63
64
65#define MAX_DSUB_CLUT_ENTRY             16
66/* CLUT definition segment */
67struct dsub_clut
68{
69        uint8_t clut_id;      /* CLUT_id */
70        uint8_t clut_size;    /* entry size */
71        uint8_t clut_version; /* CLUT_version_number */
72        uint8_t clut_flag;    /* bit 2: 2bit, bit 3: 4bit, bit 4: 8bit */
73        uint32_t entry[MAX_DSUB_CLUT_ENTRY];
74        struct dsub_clut *next;
75};
76               
77#define MAX_ACTIVE_REGIONS              10
78struct dsub_page
79{
80        uint8_t page_id;
81        uint8_t timeout;
82        uint8_t page_version;
83        uint8_t page_size;
84        uint8_t state;
85        uint8_t region_cnt;
86
87        struct dsub_page_region active_regions[MAX_ACTIVE_REGIONS];
88        struct dsub_region *regions;
89        struct dsub_clut *cluts;
90        struct dsub_page *next;
91};
92
93enum {
94        DSUB_EVT_PARSE,  /* start parse */
95        DSUB_EVT_FREE,   /* free allocated memory */
96        DSUB_EVT_CLEAR   /* clear screen */
97};
98
99typedef struct dsub_evt_t {
100        unsigned int cmd;
101        unsigned int data[4];
102} dsub_evt_t;
103
104struct bapp_dsub
105{
106        bapp_t          *p_app;
107
108        b_task_t        p_thread;                       /* parser thread */
109        b_task_t        d_thread;
110        uint32_t        *p_thread_stack;        /* parser thread stack */
111        uint32_t        *d_thread_stack;
112
113        bool            enabled;                        /* application will enable/disable depending on application's state */
114
115        bool            pes_started;            /* indicate PUSI message is delivered */
116        uint16_t        pes_len;                        /* length of complete pes */
117        uint16_t        pes_received;           /* length of accumulated pes packet */
118
119        uint32_t        start_ptr;                      /* current packet's start position in buffer */ 
120        uint32_t        write_ptr;                      /* current write position in buffer */
121
122        b_mutex_t       mutex;
123        b_mutex_t   p_mutex;
124        b_queue_t       packet_queue;
125        b_event_t       p_event[MAX_DSUB_EVENT];
126
127        LIST_T          free_surf_list;
128        dsub_evt_t      packet_event;
129       
130        bgfx_surf_t     *p_osd_surf;            /* OSD frame buffer which is from application */
131        bgfx_surf_t     surf;                           /* 720x576 subtitle surface */
132
133        uint16_t        page_no;                        /* page number to be selected by application */
134        uint32_t        timeout_tick;
135
136        struct dsub_page        *pages;                         /* list of pages */
137} bapp_dsub;
138
139
140bapp_dsub_t     s_p_subtitle = NULL;
141
142static void dsub_p_parser_thread(void *data);
143static void dsub_p_draw_thread(void *data);
144static bool dsub_p_find_pes_start_code(uint8_t *buf);
145static void dsub_p_copy_pes(uint8_t *pes_hdr, int len);
146static void dsub_p_post_complete_event(void);
147
148/*
149 * Open DVB subtitle object
150 */
151bapp_dsub_t bapp_dsub_open(void *v_app)
152{
153        bapp_t *p_app = (bapp_t *)v_app;
154        b_task_params params;
155        surf_node_t *surf_node; 
156        int i;
157
158        BDBG_ASSERT(p_app);
159
160//      BDBG_SetModuleLevel("dsub",BDBG_eMsg);
161        s_p_subtitle = (bapp_dsub_t)BKNI_Malloc(sizeof(struct bapp_dsub));
162        if (!s_p_subtitle) {
163                BDBG_ERR(("fail to create dvb subtitle object"));
164                goto done;
165        }
166
167        BKNI_Memset(s_p_subtitle, 0, sizeof(struct bapp_dsub));
168        s_p_subtitle->p_app = p_app;
169
170        s_p_subtitle->p_thread_stack = BKNI_Malloc(DSUB_PARSER_STACK_SIZE*sizeof(unsigned int));
171        if (!s_p_subtitle->p_thread_stack) {
172                BDBG_ERR(("fail to create parser thread stack"));
173                goto err;
174        }
175        s_p_subtitle->d_thread_stack = BKNI_Malloc(DSUB_DRAW_STACK_SIZE*sizeof(unsigned int));
176       
177        s_p_subtitle->page_no = 0xFFFF;
178    s_p_subtitle->p_osd_surf = &p_app->surf;
179
180        /* create subtitle surface, which is 720x576 PAL size, AYCbCr32 format */
181        if (bgfx_create(&s_p_subtitle->surf,DSUB_WIDTH,DSUB_HEIGHT,NULL,0,NULL,BGFX_SURF_BPP(32)|BGFX_SURF_GRC)!=0)
182        {
183                BDBG_ERR(("bgfx_create failed"));
184                goto err;
185        }
186        /* clear the subtitle suface buffer */
187        bgfx_fill_rect(&s_p_subtitle->surf, 0, 0, DSUB_WIDTH, DSUB_HEIGHT, 0);
188
189        if (bos_create_mutex(&s_p_subtitle->mutex)!=b_ok) goto err;
190        if (bos_create_mutex(&s_p_subtitle->p_mutex)!= b_ok) {
191                bos_delete_mutex(&s_p_subtitle->mutex) ;
192                goto err;
193        }
194        if (bos_create_queue(&s_p_subtitle->packet_queue, s_p_subtitle->p_event, MAX_DSUB_EVENT)!=b_ok) {
195                bos_delete_mutex(&s_p_subtitle->mutex);
196                bos_delete_mutex(&s_p_subtitle->p_mutex) ;
197                goto gerr;
198        }
199       
200        s_p_subtitle->timeout_tick = 0xFFFFFFFF;
201
202        /* create dvb subtitle parser thread */ 
203        params.name = "dsub_parser";
204        params.priority = DSUB_PARSER_PRIORITY;
205        params.stack_size = DSUB_PARSER_STACK_SIZE;
206        params.stack = s_p_subtitle->p_thread_stack;
207        bos_start_task(&s_p_subtitle->p_thread, &params, dsub_p_parser_thread, s_p_subtitle);
208
209        params.name = "dsub_draw";
210        params.priority = DSUB_DRAW_PRIORITY;
211        params.stack_size = DSUB_DRAW_STACK_SIZE;
212        params.stack = s_p_subtitle->d_thread_stack;
213        bos_start_task(&s_p_subtitle->d_thread, &params, dsub_p_draw_thread, s_p_subtitle);     
214
215        /* create surface list */
216        initl(&s_p_subtitle->free_surf_list);
217        for (i=0; i<DSUB_NUM_WNDS; i++) {
218                surf_node = (surf_node_t *)BKNI_Malloc(sizeof(surf_node_t));
219                BKNI_Memset(surf_node, 0, sizeof(surf_node_t));
220                if (bgfx_create(&surf_node->surf, DSUB_WIDTH, DSUB_MAX_WIN_HEIGHT,NULL,0,NULL,BGFX_SURF_BPP(32)|BGFX_SURF_GRC)!=0) {
221                        BDBG_WRN(("fail to creaet surface"));
222                        continue;
223                }
224                inslt(&(s_p_subtitle->free_surf_list), surf_node);
225        }
226        goto done;     
227
228gerr:
229        bgfx_destroy(&s_p_subtitle->surf);
230err:
231        if (s_p_subtitle->p_thread_stack) BKNI_Free(s_p_subtitle->p_thread_stack);
232
233        BKNI_Free(s_p_subtitle);
234        s_p_subtitle = NULL;
235done:
236        return s_p_subtitle;
237}
238
239/*
240 * enable/disable dvb subtitle
241 */
242void bapp_dsub_enable(bapp_dsub_t p_dsub, bool enable, uint16_t page_no)
243{
244        dsub_evt_t *p_event;
245
246        BDBG_ASSERT(p_dsub);
247        BDBG_ASSERT(s_p_subtitle);
248        BDBG_ASSERT(p_dsub==s_p_subtitle);
249
250        BDBG_WRN(("%s: enable = %s (%d)", __FUNCTION__, enable?"true":"false", page_no));
251       
252        if (p_dsub->enabled == enable) {
253                return;
254        }       
255
256        p_dsub->enabled = enable;
257        if (!enable) {
258                p_dsub->pes_received = 0;
259                p_dsub->pes_len = 0;
260                p_dsub->pes_started = false;
261                p_dsub->timeout_tick = 0xFFFFFFFF;
262
263                /* let parser thread clear previously allocated page entries */
264                p_event = (dsub_evt_t *)BKNI_Malloc(sizeof(dsub_evt_t));
265                p_event->cmd = DSUB_EVT_FREE;
266                bos_post_event(s_p_subtitle->packet_queue, (b_event_t *)p_event);
267        }
268        else {
269                p_dsub->page_no = page_no;
270        }
271}
272
273
274/*
275 * it's called when message callback is invoked.
276 * parser thread will start parsing when whole section is delived
277 */
278void bapp_dsub_process(uint8_t *buf, size_t size)
279{
280        uint8_t *pes_hdr;
281        uint8_t adaptation, adaptation_len = 0, pusi = 0;
282        int len;
283
284        /* sync byte */
285        if (buf[0] != 0x47) {
286                BDBG_WRN(("%s: invalid packet. discard", __FUNCTION__));       
287                return;
288        }
289
290        pusi = (buf[1]&0x40)?1:0;
291        adaptation = (buf[3]>>4)&0x3;
292        if (adaptation == 0x3) {
293                adaptation_len = buf[4]+1;
294        }
295        else if (adaptation == 2) 
296                return;
297        pes_hdr = (uint8_t *)(buf+4+adaptation_len);
298       
299        len = size - (pes_hdr-buf);
300
301        if (pusi) {
302                /* find start code */
303                if (!dsub_p_find_pes_start_code(pes_hdr)) {
304                        s_p_subtitle->pes_started = false;
305                        BDBG_WRN(("invalid start code : %x %x %x %x, %d", *pes_hdr, *(pes_hdr+1), *(pes_hdr+2), *(pes_hdr+3), adaptation_len));
306                        return;
307                }
308
309                s_p_subtitle->pes_started = true;
310                /* put the packet into parser buffer */
311                if (bos_acquire_mutex(&(s_p_subtitle->mutex), 50) != b_ok) {
312                        BDBG_WRN(("%s:%d failed to acquire mutex", __FUNCTION__, __LINE__));
313                        return;
314                }
315
316                /* complete pes length */
317                s_p_subtitle->pes_len = ((pes_hdr[4]<<8)|(pes_hdr[5]&0xFF)) + DSUB_PES_HDR_LEN; /* 3 start code, 1 stream id 2 len */
318                s_p_subtitle->pes_received = len;
319
320                s_p_subtitle->start_ptr = s_p_subtitle->write_ptr;
321                dsub_p_copy_pes(pes_hdr, len);
322
323                if (s_p_subtitle->pes_len <= s_p_subtitle->pes_received)
324                {
325                        dsub_p_post_complete_event();
326                }
327                bos_release_mutex(&(s_p_subtitle->mutex));
328        }
329        else if (s_p_subtitle->pes_started) {
330                /* put it into list */
331                if (bos_acquire_mutex(&(s_p_subtitle->mutex), 50) != b_ok) {
332                        BDBG_WRN(("%s:%d failed to acquire mutex", __FUNCTION__, __LINE__));
333                        return;
334                }
335
336                s_p_subtitle->pes_received += len;
337                dsub_p_copy_pes(pes_hdr,len);
338
339                if (s_p_subtitle->pes_received >= s_p_subtitle->pes_len) {
340                        /* complete the data */
341                        dsub_p_post_complete_event();
342                }
343                bos_release_mutex(&(s_p_subtitle->mutex));
344        }
345        else {
346                //BDBG_MSG(("discard : %x %x %x %x %x %x %x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]));
347        }
348}
349
350/* ---------------------------------------------------------------- */
351#define DSUB_BUF_SIZE                   (0xFFFF*2)
352#define PRIVATE_STREAM_1                0xBD
353
354#define DSUB_PCKT_LEN_MSB_POS       4
355#define DSUB_PCKT_LEN_LSB_POS       5
356#define DSUB_PCKT_HEADER_LENGTH     45
357#define DSUB_PCKT_LINENUM_MASK      0x1F    /* line number mask */
358#define DSUB_PCKT_ODD_FIELD_FLAG    0x20    /* on line number byte */
359#define DSUB_PCKT_EBU_DATA          0x03    /* EBU subtitle data */
360#define DSUB_PCKT_FRAMING_CODE      0xe4    /* framing code */
361#define DSUB_DATA_IDENTIFIER        0x20
362#define DSUB_STREAM_ID                          0x00
363#define DSUB_SYNC_BYTE                          0x0F
364#define DSUB_END_MARKER                         0xFF
365
366#define DSUB_SEGMENT_PAGE           0x10
367#define DSUB_SEGMENT_REGION         0x11
368#define DSUB_SEGMENT_CLUT           0x12
369#define DSUB_SEGMENT_OBJECT         0x13
370#define DSUB_ENDOF_DISPLAY          0x80
371
372typedef enum dsub_page_state {
373    PAGE_ST_NORMAL,
374    PAGE_ST_ACQUISITION,
375    PAGE_ST_MODE_CHANGE,
376    PAGE_ST_MAX
377} dsub_page_state;
378
379static uint8_t dsub_msg_buff[DSUB_BUF_SIZE];
380
381/* find the  start code */
382static bool dsub_p_find_pes_start_code(uint8_t *buf)
383{
384        if ((buf[0]==0x00) && (buf[1]==0x00) && (buf[2]==0x01) && (buf[3]==PRIVATE_STREAM_1)) 
385                return true;
386        return false;
387}
388
389/* whole messages are received, start parsing */
390static void dsub_p_post_complete_event(void)
391{
392       
393        dsub_evt_t *p_event = (dsub_evt_t *)BKNI_Malloc(sizeof(dsub_evt_t));
394        s_p_subtitle->pes_started = false;
395        p_event->cmd = DSUB_EVT_PARSE;
396        p_event->data[0] = s_p_subtitle->start_ptr;
397        p_event->data[1] = s_p_subtitle->pes_len;
398        bos_post_event(s_p_subtitle->packet_queue, (b_event_t *)p_event);
399}
400
401static void dsub_p_copy_pes(uint8_t *pes_hdr, int len)
402{
403        int remain = s_p_subtitle->write_ptr + len - DSUB_BUF_SIZE;
404       
405        if (!len) return;
406       
407        if (remain>0) {
408                BKNI_Memcpy(&dsub_msg_buff[s_p_subtitle->write_ptr], pes_hdr, len-remain);
409                BKNI_Memcpy(&dsub_msg_buff[0], pes_hdr+(len-remain), remain);
410                s_p_subtitle->write_ptr = remain;
411        }
412        else {
413                BKNI_Memcpy(&dsub_msg_buff[s_p_subtitle->write_ptr], pes_hdr, len);
414                s_p_subtitle->write_ptr += len;
415        }
416
417        if (s_p_subtitle->write_ptr == DSUB_BUF_SIZE) {
418                s_p_subtitle->write_ptr = 0;
419        } else if (s_p_subtitle->write_ptr > DSUB_BUF_SIZE) {
420                BDBG_WRN(("!!! error in handling write_ptr"));
421        }
422}
423
424/* ---------------------------------------
425 * Parser/Draw
426 * ---------------------------------------*/
427static void dsub_p_process_pes(bapp_dsub_t p_dsub, uint8_t *ptr, int len);
428static void dsub_p_free_pages(bapp_dsub_t p_dsub);
429static void dsub_p_clear_active_regions(struct dsub_page *page);
430static void dsub_p_free_regions(struct dsub_page *page);
431static void dsub_p_free_cluts(struct dsub_page *page);
432static void dsub_p_clear_screen(bapp_dsub_t p_dsub);
433
434
435static void dsub_p_parser_thread(void *data)
436{
437        dsub_evt_t *p_event;
438        dsub_evt_t *discard_event;
439        bapp_dsub_t     p_dsub = (bapp_dsub_t)data;
440        uint8_t *ptr;
441        int start, len, remain;
442        bool alloced = false;
443
444        while (1)
445        {
446                p_event = (dsub_evt_t *)bos_pend_event(p_dsub->packet_queue, -1);       
447                alloced = false;
448
449                if (p_event) 
450                {
451                        switch (p_event->cmd) {
452                                case DSUB_EVT_PARSE:
453                                        if (!p_dsub->enabled) break;
454
455                                        start = p_event->data[0];
456                                        len = p_event->data[1];
457                                        if (start+len>DSUB_BUF_SIZE) {
458                                                remain = start+len-DSUB_BUF_SIZE;
459                                                ptr = (uint8_t *)BKNI_Malloc(len);
460                                                BKNI_Memcpy(ptr, &dsub_msg_buff[start], len-remain);
461                                                BKNI_Memcpy(ptr+(len-remain), &dsub_msg_buff[0], remain);
462                                                alloced = true;
463                                        }
464                                        else {
465                                                ptr = &dsub_msg_buff[start];
466                                        }
467
468                                        if (!dsub_p_find_pes_start_code(ptr)) {
469                                                BDBG_WRN(("invalid packet is received in parser thread..."));
470                                                break; 
471                                        }
472                                        else {
473                                                dsub_p_process_pes(p_dsub, ptr, len);
474                                        }
475                                        break;
476                                case DSUB_EVT_FREE:
477                                {
478                                        BDBG_WRN(("clear cached dsub page and clear event queue"));
479                                        dsub_p_free_pages(p_dsub);
480                                        while (1) {     
481                                                /* discard the current messages */
482                                                discard_event = (dsub_evt_t *)bos_pend_event(p_dsub->packet_queue,0);
483                                                if(discard_event) {
484                                                        BKNI_Free(discard_event);
485                                                        continue;
486                                                }
487                                                break;
488                                        }
489                                        break;
490                                }
491                                case DSUB_EVT_CLEAR:
492                                {
493                                        BDBG_WRN(("page timeout expired.. clear the screen..."));
494                                        /* reset timeout_tick */
495                                        p_dsub->timeout_tick = 0xFFFFFFFF;     
496                                        if (p_dsub->enabled) {
497                                                dsub_p_clear_screen(p_dsub);
498                                        }
499                                }
500                                default:
501                                        break;
502                        }
503                }
504                else {
505                        BKNI_Sleep(5);
506                }
507
508                if (p_event) {
509                        BKNI_Free(p_event);
510                }
511
512                if (alloced) {
513                        BKNI_Free(ptr);
514                }
515        }
516}
517
518/* draw pages */
519static int redraw_page(bapp_dsub_t p_dsub, struct dsub_page *page)
520{
521        struct dsub_region *region;
522        int i, obj_cnt;
523
524        if (page->page_id != p_dsub->page_no) {
525                BDBG_WRN(("not drawing this page (%d %d)", page->page_id, p_dsub->page_no));
526                return 0;
527        }
528
529        obj_cnt = 0;
530        for (i=0; i<page->region_cnt; i++)
531        {
532                region = page->regions;
533
534                /* find the region for this active region */
535                while (region) {
536                        if (page->active_regions[i].region_id == region->region_id) 
537                                break;
538                        region = region->next;
539                }
540
541                if (region) {
542                        if (region->region_objects) {
543                                obj_cnt++;
544                        }
545                        bgfx_blit_rect(&region->region_surf->surf, &s_p_subtitle->surf, 0, 0,   
546                                page->active_regions[i].horizontal, page->active_regions[i].vertical, 
547                                region->region_width, region->region_height);
548                } 
549        }       
550        return obj_cnt;
551}
552
553/* ETSI EN300 743 v1.2.1, 10.4/5/6 */
554static int table_2_to_4_bit[4] = {0x00, 0x07, 0x08, 0x0F};
555static int table_2_to_8_bit[4] = {0x00, 0x77, 0x88, 0xFF};
556static int table_4_to_8_bit[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
557
558static uint32_t get_color(struct dsub_clut *clut, int col)
559{
560    return clut->entry[col]; 
561}
562
563/* process pixel-data sub-block */
564static int dsub_p_process_pixel_object(
565        struct dsub_region *region,     /* region of this pixel data */
566        struct dsub_region_object *obj, /* object for this pixel data */
567        struct dsub_clut *clut,         /* clut which is assigned to region */
568        uint16_t object_id,             /* object id */
569        int *y, int *x,                 /* [in,out] x/y offset in this object */
570        uint8_t *ptr,                   /* pixel buffer */
571        int tot_len,                    /* maximum length which is allocated for this pixel object */
572        bool copy                                               /* copy top field data into bottom field if btm_field_data_block_length is zero*/
573)
574{
575        struct bit_state_t bs;
576        uint8_t type;
577        uint8_t code;
578
579        int i, len, color, height = 1;
580
581//      static uint32_t line[DSUB_WIDTH];
582       
583        bs.data = (unsigned char *)ptr;
584        bs.bindex = 0;
585
586        type = get_bits(8, &bs);
587
588        if (copy) {
589                height = 2;     
590        }
591        switch (type)
592        {
593                case 0x10: /* 2-bit pixel coding string */
594                        while (s_p_subtitle->enabled && (bs.bindex/8<tot_len))
595                        { /* process end of 2-bit_pixel_code_string: */
596                len = 0;
597                                color = 0;
598
599                                code = get_bits(2, &bs);
600                                if (code) {
601                                        len = 1;
602                                        color = code;
603                                }
604                                else {
605                                        code = get_bits(2, &bs);
606                                        if (!code) { /* switch_1:0, switch_2:0 */
607                                                code = get_bits(2, &bs);
608                                                if (code == 1) { /* two pixels entry zero */
609                                                        color = 0;
610                                                        len = 2;
611                                                }
612                                                else if (code == 2) { /* run_length_12-27 */
613                                                        len = get_bits(4, &bs);
614                                                        len += 12;
615                                                        color = get_bits(2, &bs);
616                                                }
617                                                else if (code == 3) { /* run_length_29-284 */
618                                                        len = get_bits(8, &bs);
619                                                        len += 29;
620                                                        color = get_bits(2, &bs);
621                                                }
622                                                else { /* end of 2-bit/pixel_code_string */
623                                                        break;
624                                                }
625                                        }
626                                        else if (code == 1) { /* switch_1:0, switch_2:1 */
627                                                color = 0; /* one pixel entry zero */
628                                                len = 1;
629                                        }
630                                        else if (code & 2) { /* switch_1:1 */
631                                                len = 3 + get_bits(3, &bs); /* run_length_3-10*/
632                                                color = get_bits(2, &bs);
633                                        }
634                                }
635
636                                /* convert to 4 bit color table */
637                                color = table_2_to_4_bit[color];
638                                bgfx_fill_rect(&region->region_surf->surf, obj->obj_h_pos+*x, obj->obj_v_pos+*y, len, height, get_color(clut, color));
639                                *x += len;
640               
641                                if ((len == 0) || ((obj->obj_h_pos+(*x)) > DSUB_WIDTH)) {
642                                        break;
643                                }
644                        }
645
646                        /* bytealigned */
647                        if (bs.bindex%8) {
648                                get_bits(8-bs.bindex%8, &bs);
649                        }
650                        break;
651                case 0x11: /* 4-bit pixel coding string */
652                        while (s_p_subtitle->enabled && ((bs.bindex/8)<tot_len))
653                        {
654                                len = 0;
655                                color = 0;
656
657                                code = get_bits(4, &bs);
658                                if (code) {
659                                        len = 1;
660                                        color = code;
661                                }
662                                else {
663                                        code = get_bits(4, &bs);
664                                        if (!code) { /* switch_1:0, switch_2:0, switch_3:00, end_of_string_signal */
665                                                break;
666                                        }
667                                        else if (code == 0xc) { /* switch_1:1, switch_2:1, switch_3:00 */
668                                                color = 0; /* one pixel pseudo entry */
669                                                len = 1;
670                                        }
671                                        else if (code == 0xd) { /* switch_1:1, switch_2:1, switch_3:01 */
672                                                color = 0; /* two pixels pseudo entry */
673                                                len = 2;
674                                        }
675                                        else if (code<8) { /* switch_1:0 run-length_3-9 */
676                                                color = 0;
677                                                len = (code&7)+2;
678                                        }
679                                        else if ((code&0xc) == 0x8) { /* switch_1:1, switch_2:0 */
680                                                color = get_bits(4, &bs);
681                                                len = (code&3) + 4;
682                                        }
683                                        else if (code == 0xE) { /* switch_1:1, switch_2:1, switch_3:10 */
684                                                len = get_bits(4, &bs) + 9;
685                                                color = get_bits(4, &bs);
686                                        }
687                                        else if (code == 0xF) { /* switch_1:1, switch_2:1, switch_3:11 */
688                                                len = get_bits(8, &bs) + 25;
689                                                color = get_bits(4, &bs);
690                                        }
691                                }
692                                bgfx_fill_rect(&region->region_surf->surf, obj->obj_h_pos+(*x), obj->obj_v_pos+(*y), len, height, get_color(clut, color));
693                                *x += len;
694                                if ((len == 0) || ((obj->obj_h_pos+(*x)) > DSUB_WIDTH)) {
695                                        break;
696                                }
697                        }
698                        /* byte aligned */
699                        if (bs.bindex%8) {
700                                get_bits(8-bs.bindex%8, &bs);
701                        }
702                        break;
703        case 0x12: /* 8bit pixel coding string */
704                        while (s_p_subtitle->enabled && (bs.bindex/8<tot_len))
705                        {
706                len = 0;
707                                color = 0;
708
709                code = get_bits(8, &bs);
710                if (code) {
711                    len = 1;
712                    color = code;
713                }
714                else {
715                    code = get_bits(8, &bs);
716                    if (!code) {
717                        break; /* end of signal */
718                    }
719                    else if ((code&0x80) == 0x80) {
720                        len = code&0x7F;
721                        color = get_bits(8, &bs);
722                    }
723                    else { /* run_length_1-127 */
724                        len = code&0x7F;
725                        color = 0;
726                    }
727                }
728                color = color>>4; /* 8->4 bit reduction */
729                                bgfx_fill_rect(&region->region_surf->surf, obj->obj_h_pos+(*x), obj->obj_v_pos+(*y), len, height, get_color(clut, color));
730                                *x += len;
731
732                                if ((len == 0) || ((obj->obj_h_pos+(*x)) > DSUB_WIDTH)) {
733                                        break;
734                                }
735            }
736            break;
737        case 0x20: /* 2 to 4 bit map_table data */
738            BDBG_MSG(("2 to 4 bit map_table data"));
739            for (i=0; i<4; i++) { /* 4 entry numbers of 4-bits each */
740                table_2_to_4_bit[i] = get_bits(4, &bs);
741            }
742            break;
743        case 0x21: /* 2 to 8 bit map_table data */
744            BDBG_MSG(("2 to 8 bit map_table data"));
745            for (i=0; i<4; i++) {
746                table_2_to_8_bit[i] = get_bits(8, &bs);
747            }
748            break;
749        case 0x22: /* 4 to 8 bit map_table data */
750            BDBG_MSG(("4 to 8 bit map_table data"));
751            for (i=0; i<16; i++) {
752                table_4_to_8_bit[i] = get_bits(8, &bs);
753            }
754            break;
755        case 0xf0: /* end of object line code */
756                        /* object is assumed to be interlaced, with a top field and bottom field EN 300 743, 7.2.4 */
757            (*y) += 2; 
758            *x = 0;
759            return bs.bindex/8;
760        default:
761            BDBG_WRN(("%s: unhandled code %x", __FUNCTION__, code));
762                        return -1;
763            break;
764    }
765    return bs.bindex/8;
766}
767
768/* process string object */
769static void dsub_p_process_string_object(struct dsub_page *page, uint8_t object_id, uint8_t *ptr)
770{       
771        uint8_t num_codes = *ptr;
772        int i;
773       
774        ptr++; 
775
776        /* character_code */
777        for (i=0; i<num_codes; i++) 
778        {
779               
780        }
781       
782}
783
784/* handle segment block */
785static void dsub_p_process_segment(
786        uint8_t segment_type,      /* segment type */
787        uint16_t segment_length,   /* length of this segment */
788        uint8_t *ptr,              /* buffer to be processed which is pointing buf after segment_length field */
789        struct dsub_page *page     /* [out] */
790)
791{
792        struct bit_state_t bs;
793        static bool discont = true;
794
795        BDBG_ASSERT(page);
796
797        bs.data = (unsigned char *)ptr;
798        bs.bindex = 0;
799
800        switch (segment_type)
801        {
802                /* page composition segment */
803                case DSUB_SEGMENT_PAGE:
804                {
805                        uint8_t timeout, version, state;
806
807                        timeout = get_bits(8, &bs);
808                        version = get_bits(4, &bs);
809
810                        if (page->page_version == version) {
811                                /* same version.. */
812                                BDBG_MSG(("same page delivered.."));   
813                                break;
814                        }
815
816                        BDBG_MSG(("PAGE [%d] 0x%x -> 0x%x [timeout:%d]", page->page_id, page->page_version, version, timeout));
817                        if ((page->page_version == 0xF && version == 0) || ((version-page->page_version) == 1)) 
818                                discont = false;       
819                        else {
820                                discont = true;
821                        }       
822                        page->timeout = timeout; /* timeout should start when it's displayed */
823                        page->page_version = version;
824
825                        state = get_bits(2, &bs);
826                        get_bits(2, &bs); /* skip reserved */
827                        page->state = state;
828
829                        /* acquisition point: page refresh, mode change: new page */
830                        if ((state == PAGE_ST_ACQUISITION) || (state == PAGE_ST_MODE_CHANGE)) {
831                                BDBG_MSG(("     st_acquisition/mode_change(%d) : delete all page region", state));
832                                /* delete all page regions */
833                                dsub_p_free_regions(page);
834                                dsub_p_free_cluts(page);
835                                discont = false;
836                        }
837
838                        /* page is new or updated -> clear active regions */           
839                        dsub_p_clear_active_regions(page);     
840
841                        while ((bs.bindex/8)<segment_length) 
842                        {
843                                page->active_regions[page->region_cnt].region_id = get_bits(8, &bs);
844                                get_bits(8, &bs); /* skip reserved field */
845                                page->active_regions[page->region_cnt].horizontal = get_bits(16, &bs);
846                                page->active_regions[page->region_cnt].vertical = get_bits(16, &bs);
847                                BDBG_MSG(("     region:%x, hor:%d ver:%d", 
848                                        page->active_regions[page->region_cnt].region_id,
849                                        page->active_regions[page->region_cnt].horizontal, page->active_regions[page->region_cnt].vertical));
850                                page->region_cnt++;
851
852                                /* TODO: should we increase the active region size?? */
853                                if (page->region_cnt >= MAX_ACTIVE_REGIONS) {
854                                        BDBG_WRN(("active region is full"));
855                                        break;
856                                }
857                        }
858                        break;
859                }
860                /* region composition segment */
861                case DSUB_SEGMENT_REGION:
862                {
863                        uint8_t region_id, region_version, region_flag;
864                        struct dsub_region *region, **pregion;
865                        struct dsub_region_object *objects, **pobject, *cur_object;
866                        uint8_t region_level_of_compatibility, region_depth;
867                        uint8_t pixel_code_8, pixel_code_4, pixel_code_2;
868                        bool new = false;
869
870                        if (page->page_version == 0xFF) {
871                                BDBG_WRN(("[REGION] page composition segment is not delivered yet"));
872                                break;
873                        }
874
875                        region_id = get_bits(8, &bs);
876                        region_version = get_bits(4, &bs);
877                        region_flag = get_bits(1, &bs);
878                        get_bits(3, &bs); /* skip reserved field */
879
880                        region = page->regions;
881                        pregion = &page->regions;
882
883                        while (region) {
884                                if (region->region_id == region_id)
885                                        break;
886       
887                                pregion = &region->next;
888                                region = region->next;
889                        }
890
891                        if (!region) {
892                                new = true;
893                                *pregion = region = (struct dsub_region *)BKNI_Malloc(sizeof(struct dsub_region));
894                                if (!region) {
895                                        BDBG_WRN(("fail to allocate memory for region"));
896                                        break;
897                                }
898                                BKNI_Memset(region, 0, sizeof(struct dsub_region));
899                                region->region_version = 0xFF;
900                        }
901
902                        if (region->region_version == region_version) {
903                                BDBG_MSG(("same object version.. "));
904                                break;
905                        }
906
907                        /* delete all region objects */
908                        objects = region->region_objects;
909                        while (objects) {
910                                struct dsub_region_object *n = objects->next;
911                               
912                                BKNI_Free(objects);     
913                                objects = n ;
914                        }
915                        region->region_objects = NULL;
916
917                        region->region_id = region_id;
918                        region->region_version = region_version;
919                        region->region_width = get_bits(16, &bs);
920                        region->region_height = get_bits(16, &bs);
921                        if (new == true) 
922                        {
923                                if (region->region_height>DSUB_MAX_WIN_HEIGHT) {
924                                        BDBG_MSG((" ** create surface : %d", region->region_id));
925                                        region->region_surf = (surf_node_t *)BKNI_Malloc(sizeof(surf_node_t));
926                                        if (!region->region_surf && bgfx_create(&region->region_surf->surf,region->region_width,region->region_height,NULL,0,NULL,
927                                                BGFX_SURF_BPP(32)|BGFX_SURF_GRC) != 0) {
928
929                                                BDBG_WRN(("Fail to create surface for region"));
930                                                break;
931                                        }
932                                }
933                                else { 
934                                        region->region_surf = remlh(&(s_p_subtitle->free_surf_list));
935                                }
936                                if (!region->region_surf) {
937                                        BDBG_WRN(("no surface available for the region (%d)", region_id));
938                                        break;
939                                }
940                                /* clear the region surface, only when it's delivered first time */
941                                bgfx_fill_rect(&region->region_surf->surf,0,0,region->region_width,region->region_height,0);
942                        }
943                        else if (discont == true) {
944                                /* TODO:: how to handle discontinuous page */
945//                              BDBG_MSG(("clear region's frame buffer for discontinuous page"));
946//                              bgfx_fill_rect(&region->region_surf->surf,0,0,region->region_width,region->region_height,0);
947                        }
948
949                        region_level_of_compatibility = get_bits(3, &bs);
950                        region_depth = get_bits(3, &bs);
951                        get_bits(2, &bs); /* skip reserved field */
952
953                        region->clut_id = get_bits(8, &bs);
954                        BDBG_MSG(("REGION [%d] width:%d, height:%d clut_id:%d",
955                                region->region_id, region->region_width, region->region_height, region->clut_id));
956
957                        pixel_code_8 = get_bits(8, &bs);
958                        pixel_code_4 = get_bits(4, &bs);
959                        pixel_code_2 = get_bits(2, &bs);
960                        get_bits(2, &bs); /* skip reserved field */
961
962                        if (region_flag) {
963#if 0
964                                if (region_depth == 1)
965                                        BKNI_Memset(region->region_buffer, pixel_code_2, region->region_width*region->region_height);
966                                else if (region_depth == 2)
967                                        BKNI_Memset(region->region_buffer, pixel_code_4, region->region_width*region->region_height);
968                                else if (region_depth == 3)
969                                        BKNI_Memset(region->region_buffer, pixel_code_8, region->region_width*region->region_height);
970                                else
971                                        BDBG_WRN(("region depth is not valid: %d", region_depth));
972#endif
973            }
974
975                        pobject = &region->region_objects;
976                       
977                        while (bs.bindex/8<segment_length)
978                        {
979                                cur_object = (struct dsub_region_object *)BKNI_Malloc(sizeof(struct dsub_region_object));
980                                *pobject = cur_object;
981                                BKNI_Memset(cur_object, 0, sizeof(struct dsub_region_object));
982                                pobject = &cur_object->next;
983
984                                cur_object->obj_id = get_bits(16, &bs);
985                                cur_object->obj_type = get_bits(2, &bs);
986                                cur_object->obj_provider_flag = get_bits(2, &bs);
987                                cur_object->obj_h_pos = get_bits(12, &bs);
988                                get_bits(4, &bs);
989                                cur_object->obj_v_pos = get_bits(12, &bs);
990
991                                /* character / composite_object(string of characters */
992                                if (cur_object->obj_type == 1 || cur_object->obj_type == 2) 
993                                {
994                                        cur_object->fore_pixel = get_bits(8, &bs); /* character's foreground color */
995                                        cur_object->back_pixel = get_bits(8, &bs); /* character's background color */
996                                }
997                                BDBG_MSG(("   object (%d), type(%d), h_pos(%d), v_pos(%d)", cur_object->obj_id, cur_object->obj_type,
998                                        cur_object->obj_h_pos, cur_object->obj_v_pos));
999                        }
1000                        break;
1001                }
1002                case DSUB_SEGMENT_CLUT:
1003                {
1004                        uint8_t clut_id, clut_version;
1005                        struct dsub_clut *clut, **pclut;
1006
1007                        if (page->page_version == 0xFF) {
1008                                BDBG_WRN(("[CLUT] page composition segment is not delivered yet"));
1009                                break;
1010                        }
1011
1012                        clut_id = get_bits(8, &bs);
1013                        clut_version = get_bits(4, &bs);
1014                        get_bits(4, &bs);
1015
1016                        clut = page->cluts;
1017                        pclut = &page->cluts;
1018
1019                        while (clut) {
1020                                if (clut->clut_id == clut_id)
1021                                        break;
1022                                pclut = &clut->next;
1023                                clut = clut->next;
1024                        }
1025
1026                        if (!clut) {
1027                                *pclut = clut = (struct dsub_clut *)BKNI_Malloc(sizeof(struct dsub_clut));
1028                                BKNI_Memset(clut, 0, sizeof(struct dsub_clut));
1029                                clut->clut_version = 0xFF;
1030                        }
1031                        else if (clut->clut_version == clut_version) {
1032                                BDBG_MSG(("same clut is received"));
1033                                break;
1034                        }
1035
1036                        clut->clut_id = clut_id;
1037                        BDBG_MSG(("CLUT[%d] %d->%d (%d)", clut->clut_id, clut->clut_version, clut_version, segment_length));
1038                        clut->clut_version = clut_version;
1039
1040                        while (bs.bindex/8 < segment_length)
1041                        {
1042                                uint8_t clut_entry_id, clut_flag, full_range_flag;
1043                                uint8_t y, cb, cr, t;
1044
1045                                clut_entry_id = get_bits(8, &bs);
1046                                clut_flag = get_bits(3, &bs); /* 2bit, 4bit, 8bit */
1047       
1048                                get_bits(4, &bs);
1049                                full_range_flag = get_bits(1, &bs);
1050
1051                                if (full_range_flag) {
1052                                        y = get_bits(8, &bs);
1053                                        cr = get_bits(8, &bs);
1054                                        cb = get_bits(8, &bs);
1055                                        t = get_bits(8, &bs);
1056                                }
1057                                else {
1058                                        y = get_bits(6, &bs);
1059                                        cr = get_bits(4, &bs);
1060                                        cb = get_bits(4, &bs);
1061                                        t = get_bits(2, &bs);
1062                                }
1063
1064                                if (!(clut_flag & 0x6)) {
1065                    BDBG_WRN(("8bit clut... !!!!!! need increase clut_entry..."));
1066                                        return;
1067                                }
1068
1069                                if (y == 0) { /* full transparency */
1070                                        clut->entry[clut_entry_id] = 0x00108080;
1071                                } 
1072                                else {
1073                                        clut->entry[clut_entry_id] = ((0xFF-t)<<24)|(y<<16)|(cb<<8)|(cr);
1074                                }
1075            }
1076            break;
1077                }
1078                case DSUB_SEGMENT_OBJECT:
1079                {
1080                        uint16_t object_id;
1081                        uint8_t object_version, object_coding, non_modifying_color_flag ;
1082
1083                        struct dsub_region *region;
1084                        struct dsub_clut *clut;
1085                        struct dsub_region_object *robj;
1086
1087                        if (!page) break;
1088
1089                        object_id = get_bits(16, &bs);
1090                        object_version = get_bits(4, &bs);
1091                        object_coding = get_bits(2, &bs);
1092
1093                        /* TODO:: how to handle if non_modifying_color_flag is set */
1094                        non_modifying_color_flag = get_bits(1, &bs);
1095                        if (non_modifying_color_flag) {
1096                                BDBG_MSG(("non_modifying_color_flag is set"));
1097                        }
1098                        get_bits(1, &bs);
1099
1100                        /* find the region which is for this object */
1101                        region = page->regions;
1102                        while (region) {
1103                                robj = region->region_objects;
1104                                while (robj) {
1105                                        if (robj->obj_id == object_id)
1106                                                break;
1107                                        robj = robj->next;
1108                                }
1109                                if (robj)
1110                                        break;
1111                                region = region->next;
1112                        }
1113
1114                        if (region && robj) {
1115                                clut = page->cluts;
1116                                while (clut)
1117                                {
1118                                        if (clut->clut_id == region->clut_id)
1119                                                break;
1120                                        clut = clut->next;
1121                                }
1122                        }
1123                        else {
1124                                BDBG_WRN(("region entri is not delivered yet. discard the object"));
1125                                break;
1126                        }
1127
1128                        if (!clut) {
1129                                BDBG_WRN(("clut entry is not delivered yet.. discard the object entry"));
1130                                break;
1131                        }
1132
1133                        if (object_coding == 0) {
1134                                uint16_t top_field_length, btm_field_length;
1135                                int x, y, len, pos;
1136                                uint8_t *line_buf;
1137       
1138                                top_field_length = get_bits(16, &bs);
1139                                btm_field_length = get_bits(16, &bs);
1140
1141                                BDBG_MSG(("OBJ[%d] top_len:%d btm_len:%d", object_id, top_field_length, btm_field_length));
1142
1143                                pos = 0;
1144                                line_buf = &ptr[bs.bindex/8];
1145
1146                                /* first pixel of the first line of the top field is the top left pixel of the object */
1147                                x = y = 0; 
1148
1149                                /* if btm_field_data_block_length is 0, pixel-data_sub-block shall apply for the bottom field also
1150                                   EN 300 743, 7.2.4 */
1151                                while ( s_p_subtitle->enabled && (pos< top_field_length)) {
1152                                        len = dsub_p_process_pixel_object(region, robj, clut, object_id, &y, &x, line_buf, (top_field_length-pos),
1153                                                btm_field_length?false:true);
1154                                        if (len < 0) {
1155                                                break;
1156                                        }
1157                                        line_buf += len;
1158                                        pos += len;
1159                                }
1160                                bs.bindex += top_field_length*8;
1161
1162                                /* first pixel of the first line of the bottom field is the most left pixel on the second line of the object */
1163                                y = 1;
1164                                x = 0;
1165                                pos = 0;
1166                                line_buf = &ptr[bs.bindex/8];
1167                                while (s_p_subtitle->enabled && (pos<btm_field_length)) {
1168                                        len = dsub_p_process_pixel_object(region, robj, clut, object_id, &y, &x, line_buf, (btm_field_length-pos),false);
1169                                        if (len<0) break;
1170                                        line_buf+=len;
1171                                        pos += len;
1172                                }
1173                                bs.bindex += btm_field_length*8;
1174
1175                                if ((top_field_length + btm_field_length) &1)
1176                                        get_bits(8, &bs); /* 8 stuff bits */
1177                        }
1178                        else if (object_coding == 1) { /* string code */
1179                                BDBG_WRN(("string code..."));
1180                                dsub_p_process_string_object(page, object_id, &ptr[bs.bindex/8]);
1181                        }
1182                        break;
1183        }
1184        case DSUB_ENDOF_DISPLAY:
1185                        BDBG_MSG(("ENDOF_DISPLAY (%d)", s_p_subtitle->enabled));
1186            if (s_p_subtitle->enabled) {
1187                        struct dsub_page *page;
1188                                int flush = 0;
1189                                uint32_t timeout ;
1190
1191                        page = s_p_subtitle->pages;
1192
1193                        bgfx_fill_rect(&s_p_subtitle->surf, 0, 0, s_p_subtitle->surf.surface.width, s_p_subtitle->surf.surface.height, 0);
1194                        while (page)
1195                        {
1196                                        if (page->page_id == s_p_subtitle->page_no) {
1197                                flush += redraw_page(s_p_subtitle, page);
1198                                                timeout = page->timeout;
1199                                        }
1200                        page = page->next;
1201                        }
1202                                bgfx_blit(&s_p_subtitle->surf, s_p_subtitle->p_osd_surf, 0, 0);
1203                        if (flush>0) {
1204                                        s_p_subtitle->timeout_tick = bos_getticks() + MS_TO_TICKS(timeout*1000);
1205                                        /* setup timeout */
1206                                        bapp_flush_screen(s_p_subtitle->p_app);
1207                                }
1208            }
1209            break;
1210        default:
1211                        BDBG_WRN(("undefined segment type"));
1212            break;
1213    }
1214}
1215
1216static void dsub_p_clear_screen(bapp_dsub_t p_dsub)
1217{
1218        bgfx_fill_rect(p_dsub->p_osd_surf, 0, 0, p_dsub->p_osd_surf->surface.width, p_dsub->p_osd_surf->surface.height, 0);
1219        bapp_flush_screen(p_dsub->p_app);
1220}
1221
1222static void dsub_p_process_pes(bapp_dsub_t p_dsub, uint8_t *ptr, int len)
1223{
1224        int cur_len;
1225        int pes_hdr_len;
1226        bool pts_present = false;       
1227        uint8_t *p = ptr;
1228        uint8_t data_identifier, stream_id, sync_byte, segment_type;
1229        uint16_t page_id, segment_length, processed;
1230        struct dsub_page *page, **ppage;
1231
1232        struct bit_state_t bs;
1233        uint32_t pts;
1234
1235        BDBG_MSG((">> %s: start", __FUNCTION__));       
1236        cur_len = p[4]<<8 | p[5];
1237        if ((cur_len + DSUB_PES_HDR_LEN) != len) {
1238                BDBG_WRN(("incomplete packet.. discard.. %d %d", cur_len, len));
1239                return;
1240        }
1241
1242        /* check presentation time */
1243        p += DSUB_PES_HDR_LEN;
1244
1245        bs.bindex = 0;
1246        bs.data = p;
1247        get_bits(8, &bs); 
1248        if (get_bits(1, &bs)) {
1249                /* retrieve PTS info */
1250                pts_present = true;
1251        }
1252        get_bits(7, &bs);
1253        pes_hdr_len = get_bits(8, &bs);
1254
1255        if (pts_present) {
1256                uint8_t flag;
1257
1258                flag = get_bits(4, &bs); /* skip: b0010 or b0011*/
1259                if ((flag != 0x2) && (flag != 0x3)) {
1260                        BDBG_WRN(("pts field is not correct"));
1261                        pts_present = false;
1262                }
1263                /* use 32 bit MSB out of 33 bits */
1264                pts = get_bits(3, &bs)<<29;
1265                if (get_bits(1, &bs) != 1) {
1266                        BDBG_WRN(("invalid pts field "));
1267                        pts_present = false;
1268                }
1269                pts += get_bits(15, &bs)<<14;
1270                if (get_bits(1, &bs) != 1) {
1271                        BDBG_WRN(("invalid pts field "));
1272                        pts_present = false;
1273                }       
1274                pts += get_bits(15, &bs)>>1;
1275                if (get_bits(1, &bs) != 1) {
1276                        BDBG_WRN(("invalid pts field "));
1277                        pts_present = false;
1278                }       
1279        }
1280
1281        p += 2/*extension*/+1/*header length field*/+pes_hdr_len;
1282
1283        if (pts_present) {
1284                bdecode_status    status;       
1285                int32_t diff;
1286                bdecode_get_status(s_p_subtitle->p_app->decode, &status);
1287                diff = (pts-status.video_stc)/90; /* convert to ms, 90khz resolution */
1288                if ((diff > 500) && (diff<10000)) {
1289                        BDBG_MSG(("*** PTS:%x, STC:%x, diff:%d", pts, status.video_stc, diff));
1290                        BKNI_Sleep(diff);
1291                }
1292        }
1293        /*
1294         * PES_data_field() {
1295         *      data_identifier:8 - should be 0x20
1296         *      subtitle_stream_id - subtitle stream in this PES packet, it should be 0
1297         *      while (nextbits() == '0000 1111') {
1298         *              subtitling_segment
1299         *      }
1300         *      end_of_PES_data_field_marker : '1111 1111'
1301         */
1302        bs.bindex = 0;
1303        bs.data = p;
1304
1305        data_identifier = get_bits(8, &bs);
1306        if (data_identifier != DSUB_DATA_IDENTIFIER) {
1307                BDBG_WRN(("invalid data identifier (0x%x)", data_identifier));
1308                return;
1309        }
1310
1311        stream_id = get_bits(8, &bs);
1312        if (stream_id != DSUB_STREAM_ID) {
1313                BDBG_WRN(("invalid stream id (0x%x)", stream_id));
1314                return;
1315        }
1316        processed = len - DSUB_PES_HDR_LEN - 3 - pes_hdr_len;
1317        while (s_p_subtitle->enabled) {
1318                if (bs.bindex/8>processed) break;
1319                sync_byte = get_bits(8, &bs);
1320                if (sync_byte != DSUB_SYNC_BYTE) 
1321                        break;
1322
1323                /* here's subtitling_segment */
1324                segment_type = get_bits(8, &bs);
1325                page_id = get_bits(16, &bs);
1326                segment_length = get_bits(16, &bs);
1327
1328                /* TODO::check page_id with p_dsub->page_id ... */
1329
1330                page = p_dsub->pages;
1331                ppage = &(p_dsub->pages);               
1332               
1333                while (page) {
1334                        if (page->page_id == page_id) 
1335                                break;
1336                        ppage = &page->next;
1337                        page = page->next;
1338                }
1339
1340                if (!page) {
1341                        page = BKNI_Malloc(sizeof(struct dsub_page));
1342                        if (!page) {
1343                                BDBG_WRN(("fail to alloc for page"));
1344                                return;
1345                        }
1346                        BDBG_WRN(("page is allocated : 0x%x", page));
1347                        BKNI_Memset(page, 0, sizeof(struct dsub_page));
1348                        page->page_id = page_id;
1349                        page->page_version = 0xFF;
1350                        *ppage = page;
1351                }
1352                dsub_p_process_segment(segment_type, segment_length, &p[bs.bindex/8], page);
1353                bs.bindex += segment_length*8;
1354
1355        }
1356
1357        if (sync_byte != DSUB_END_MARKER) {
1358                BDBG_WRN(("end_of_PES_data_field_marker is invalid : 0x%x", sync_byte));
1359                return;
1360        }
1361        BDBG_MSG(("<< %s: done", __FUNCTION__));       
1362}
1363
1364static void dsub_p_clear_active_regions(struct dsub_page *page)
1365{
1366        int i;
1367
1368        for (i=0; i<MAX_ACTIVE_REGIONS; i++) {
1369                BKNI_Memset(&page->active_regions[i], 0, sizeof(struct dsub_page_region));
1370        }
1371        page->region_cnt = 0;
1372}
1373
1374static void dsub_p_free_regions(struct dsub_page *page)
1375{
1376        struct dsub_region *p_reg;
1377        struct dsub_region_object *p_robj;
1378        surf_node_t *p_surf;
1379
1380        while (page->regions)
1381        {
1382                p_reg = page->regions->next;
1383                while (page->regions->region_objects) {
1384                        p_robj = page->regions->region_objects->next;
1385                        BKNI_Free(page->regions->region_objects);
1386                        page->regions->region_objects = p_robj;
1387                }
1388
1389                if (page->regions->region_height>DSUB_MAX_WIN_HEIGHT) {
1390                        BDBG_MSG(("destroy surface (%d) height:%d", page->regions->region_id, page->regions->region_height));
1391                        bgfx_destroy(&page->regions->region_surf->surf);
1392                        BKNI_Free(page->regions->region_surf);
1393                }
1394                else {
1395                        p_surf = page->regions->region_surf;
1396                        /* clear the surface first */
1397                        bgfx_fill_rect(&p_surf->surf, 0, 0, p_surf->surf.surface.width, p_surf->surf.surface.height, 0);
1398                        inslt(&(s_p_subtitle->free_surf_list), p_surf);
1399                }
1400                BKNI_Free(page->regions);
1401                page->regions = p_reg;
1402        }
1403}
1404
1405static void dsub_p_free_cluts(struct dsub_page *page)
1406{
1407        struct dsub_clut *p_clut;
1408
1409        while (page->cluts)
1410        {
1411                p_clut = page->cluts->next;
1412                BKNI_Free(page->cluts);
1413                page->cluts = p_clut;
1414        }
1415}
1416       
1417static void dsub_p_free_pages(bapp_dsub_t p_dsub)
1418{
1419        struct dsub_page *page;
1420       
1421        /* free the page */
1422        page = p_dsub->pages;
1423        while (page) {
1424                struct dsub_page *p = page->next;
1425
1426                dsub_p_clear_active_regions(page);
1427                dsub_p_free_regions(page);
1428                dsub_p_free_cluts(page);
1429                BKNI_Free(page);
1430                page = p;
1431        }
1432
1433        p_dsub->pages = NULL;
1434}
1435
1436static void dsub_p_draw_thread(void *data)
1437{
1438        bapp_dsub_t     p_dsub = (bapp_dsub_t)data;
1439        uint32_t current_tick;
1440        dsub_evt_t *p_event;
1441
1442        while (1) {
1443                current_tick = bos_getticks();
1444                if (current_tick > p_dsub->timeout_tick) {
1445                        /* erase screen */
1446                        p_event = (dsub_evt_t *)BKNI_Malloc(sizeof(dsub_evt_t));
1447                        p_event->cmd = DSUB_EVT_CLEAR;
1448                        bos_post_event(s_p_subtitle->packet_queue, (b_event_t *)p_event);
1449                }
1450
1451                /* reaction accuracy of -0/+5 s is accurate enough */
1452                BKNI_Sleep(500);
1453        }
1454}
Note: See TracBrowser for help on using the repository browser.