4 #include "ts_section_parser.h"
5 #include "ts_section_parser_error_code.h"
7 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
18 TS_SECTION_ELEM
*head
;
19 TS_SECTION_ELEM
*tail
;
27 TS_SECTION_ELEM
*work
;
28 TS_SECTION_ELEM
*last
;
33 TS_SECTION_PARSER_STAT stat
;
35 } TS_SECTION_PARSER_PRIVATE_DATA
;
37 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
40 #define MAX_RAW_SECTION_SIZE 4100
42 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
43 function prottypes (interface method)
44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
45 static void release_ts_section_parser(void *parser
);
46 static int reset_ts_section_parser(void *parser
);
47 static int put_ts_section_parser(void *parser
, TS_HEADER
*hdr
, uint8_t *data
, int size
);
48 static int get_ts_section_parser(void *parser
, TS_SECTION
*sect
);
49 static int ret_ts_section_parser(void *parser
, TS_SECTION
*sect
);
50 static int get_count_ts_section_parser(void *parser
);
51 static int get_stat_ts_section_parser(void *parser
, TS_SECTION_PARSER_STAT
*stat
);
53 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
54 global function implementation (factory method)
55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
56 TS_SECTION_PARSER
*create_ts_section_parser()
59 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
63 n
= sizeof(TS_SECTION_PARSER_PRIVATE_DATA
);
64 n
+= sizeof(TS_SECTION_PARSER
);
66 prv
= (TS_SECTION_PARSER_PRIVATE_DATA
*)calloc(1, n
);
68 /* failed on malloc() - no enough memory */
74 r
= (TS_SECTION_PARSER
*)(prv
+1);
75 r
->private_data
= prv
;
77 r
->release
= release_ts_section_parser
;
78 r
->reset
= reset_ts_section_parser
;
80 r
->put
= put_ts_section_parser
;
81 r
->get
= get_ts_section_parser
;
82 r
->ret
= ret_ts_section_parser
;
84 r
->get_count
= get_count_ts_section_parser
;
86 r
->get_stat
= get_stat_ts_section_parser
;
91 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
92 function prottypes (private method)
93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
94 static TS_SECTION_PARSER_PRIVATE_DATA
*private_data(void *parser
);
95 static void teardown(TS_SECTION_PARSER_PRIVATE_DATA
*prv
);
97 static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, uint8_t *data
, int size
);
98 static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, uint8_t *data
, int size
);
100 static void reset_section(TS_SECTION
*sect
);
101 static void append_section_data(TS_SECTION
*sect
, uint8_t *data
, int size
);
102 static int check_section_complete(TS_SECTION
*sect
);
104 static int compare_elem_section(TS_SECTION_ELEM
*a
, TS_SECTION_ELEM
*b
);
106 static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
);
107 static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
);
108 static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
);
109 static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
);
111 static TS_SECTION_ELEM
*query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA
*prv
);
113 static void extract_ts_section_header(TS_SECTION
*sect
);
115 static TS_SECTION_ELEM
*create_ts_section_elem();
116 static TS_SECTION_ELEM
*get_ts_section_list_head(TS_SECTION_LIST
*list
);
117 static void put_ts_section_list_tail(TS_SECTION_LIST
*list
, TS_SECTION_ELEM
*elem
);
118 static void unlink_ts_section_list(TS_SECTION_LIST
*list
, TS_SECTION_ELEM
*elem
);
119 static void clear_ts_section_list(TS_SECTION_LIST
*list
);
121 static uint32_t crc32(uint8_t *head
, uint8_t *tail
);
123 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
124 function implementation (interface method)
125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
126 static void release_ts_section_parser(void *parser
)
128 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
130 prv
= private_data(parser
);
137 memset(parser
, 0, sizeof(TS_SECTION_PARSER
));
141 static int reset_ts_section_parser(void *parser
)
143 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
145 prv
= private_data(parser
);
147 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
155 static int put_ts_section_parser(void *parser
, TS_HEADER
*hdr
, uint8_t *data
, int size
)
157 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
159 prv
= private_data(parser
);
160 if( (prv
== NULL
) || (hdr
== NULL
) || (data
== NULL
) || (size
< 1) ){
161 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
164 if( (prv
->pid
>= 0) && (prv
->pid
!= hdr
->pid
) ){
165 return TS_SECTION_PARSER_ERROR_INVALID_TS_PID
;
170 if(hdr
->payload_unit_start_indicator
== 0){
171 /* exclude section start */
172 return put_exclude_section_start(prv
, data
, size
);
174 /* include section start */
175 return put_include_section_start(prv
, data
, size
);
179 static int get_ts_section_parser(void *parser
, TS_SECTION
*sect
)
181 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
184 prv
= private_data(parser
);
185 if( (prv
== NULL
) || (sect
== NULL
) ){
186 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
189 w
= get_ts_section_list_head(&(prv
->buff
));
191 memset(sect
, 0, sizeof(TS_SECTION
));
192 return TS_SECTION_PARSER_ERROR_NO_SECTION_DATA
;
195 memcpy(sect
, &(w
->sect
), sizeof(TS_SECTION
));
196 put_ts_section_list_tail(&(prv
->pool
), w
);
201 static int ret_ts_section_parser(void *parser
, TS_SECTION
*sect
)
203 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
206 prv
= private_data(parser
);
207 if( (prv
== NULL
) || (sect
== NULL
) ){
208 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
213 if(w
->sect
.data
== sect
->data
){
216 w
= (TS_SECTION_ELEM
*)(w
->prev
);
219 if( (w
!= NULL
) && (w
->ref
> 0) ){
226 static int get_count_ts_section_parser(void *parser
)
228 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
230 prv
= private_data(parser
);
232 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
235 return prv
->buff
.count
;
238 static int get_stat_ts_section_parser(void *parser
, TS_SECTION_PARSER_STAT
*stat
)
240 TS_SECTION_PARSER_PRIVATE_DATA
*prv
;
242 prv
= private_data(parser
);
243 if( (prv
== NULL
) || (stat
== NULL
) ){
244 return TS_SECTION_PARSER_ERROR_INVALID_PARAM
;
247 memcpy(stat
, &(prv
->stat
), sizeof(TS_SECTION_PARSER_STAT
));
252 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
253 function implementation (private method)
254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
255 static TS_SECTION_PARSER_PRIVATE_DATA
*private_data(void *parser
)
257 TS_SECTION_PARSER_PRIVATE_DATA
*r
;
258 TS_SECTION_PARSER
*p
;
260 p
= (TS_SECTION_PARSER
*)parser
;
265 r
= (TS_SECTION_PARSER_PRIVATE_DATA
*)(p
->private_data
);
266 if( ((void *)(r
+1)) != parser
){
273 static void teardown(TS_SECTION_PARSER_PRIVATE_DATA
*prv
)
277 if(prv
->work
!= NULL
){
284 clear_ts_section_list(&(prv
->pool
));
285 clear_ts_section_list(&(prv
->buff
));
287 memset(&(prv
->stat
), 0, sizeof(TS_SECTION_PARSER_STAT
));
290 static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, uint8_t *data
, int size
)
295 if( (w
== NULL
) || (w
->sect
.raw
== w
->sect
.tail
) ){
296 /* no previous data */
300 append_section_data(&(w
->sect
), data
, size
);
301 if(check_section_complete(&(w
->sect
)) == 0){
308 if( (w
->sect
.hdr
.section_syntax_indicator
!= 0) &&
309 (crc32(w
->sect
.raw
, w
->sect
.tail
) != 0) ){
310 cancel_elem_error(prv
, w
);
311 return TS_SECTION_PARSER_WARN_CRC_MISSMATCH
;
314 if(compare_elem_section(w
, prv
->last
) == 0){
315 /* same section data */
316 cancel_elem_same(prv
, w
);
320 commit_elem_updated(prv
, w
);
324 static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, uint8_t *data
, int size
)
341 pointer_field
= p
[0];
344 if( (p
+pointer_field
) >= tail
){
345 /* input data is probably broken */
349 if(w
->sect
.raw
!= w
->sect
.tail
){
350 cancel_elem_error(prv
, w
);
351 return TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH
;
353 cancel_elem_empty(prv
, w
);
358 if(pointer_field
> 0){
359 r
= put_exclude_section_start(prv
, p
, pointer_field
);
370 if(w
->sect
.raw
!= w
->sect
.tail
){
371 cancel_elem_error(prv
, w
);
372 r
= TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH
;
374 cancel_elem_empty(prv
, w
);
381 w
= query_work_elem(prv
);
383 return TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY
;
386 append_section_data(&(w
->sect
), p
, tail
-p
);
387 if(check_section_complete(&(w
->sect
)) == 0){
392 length
= (w
->sect
.tail
- w
->sect
.raw
);
394 if( (w
->sect
.hdr
.section_syntax_indicator
!= 0) &&
395 (crc32(w
->sect
.raw
, w
->sect
.tail
) != 0) ){
396 cancel_elem_error(prv
, w
);
397 r
= TS_SECTION_PARSER_WARN_CRC_MISSMATCH
;
398 }else if(compare_elem_section(w
, prv
->last
) == 0){
399 cancel_elem_same(prv
, w
);
401 commit_elem_updated(prv
, w
);
406 } while ( (p
< tail
) && (p
[0] != 0xff) );
411 static void reset_section(TS_SECTION
*sect
)
413 memset(&(sect
->hdr
), 0, sizeof(TS_SECTION_HEADER
));
414 sect
->tail
= sect
->raw
;
418 static void append_section_data(TS_SECTION
*sect
, uint8_t *data
, int size
)
422 m
= sect
->tail
- sect
->raw
;
423 n
= MAX_RAW_SECTION_SIZE
- m
;
428 memcpy(sect
->tail
, data
, n
);
432 if(sect
->data
== NULL
){
433 extract_ts_section_header(sect
);
436 if(sect
->data
== NULL
){
441 n
= sect
->hdr
.section_length
+ 3;
443 sect
->tail
= sect
->raw
+ n
;
449 static int check_section_complete(TS_SECTION
*sect
)
453 if(sect
->data
== NULL
){
457 m
= sect
->tail
- sect
->raw
;
458 n
= sect
->hdr
.section_length
+ 3;
467 static int compare_elem_section(TS_SECTION_ELEM
*a
, TS_SECTION_ELEM
*b
)
471 if( (a
== NULL
) || (b
== NULL
) ){
475 m
= a
->sect
.tail
- a
->sect
.raw
;
476 n
= b
->sect
.tail
- b
->sect
.raw
;
481 if(memcmp(a
->sect
.raw
, b
->sect
.raw
, m
) != 0){
488 static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
)
490 reset_section(&(elem
->sect
));
492 put_ts_section_list_tail(&(prv
->pool
), elem
);
495 static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
)
497 reset_section(&(elem
->sect
));
499 put_ts_section_list_tail(&(prv
->pool
), elem
);
500 prv
->stat
.total
+= 1;
501 prv
->stat
.error
+= 1;
504 static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
)
506 reset_section(&(elem
->sect
));
508 put_ts_section_list_tail(&(prv
->pool
), elem
);
512 static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA
*prv
, TS_SECTION_ELEM
*elem
)
514 if( (prv
->last
!= NULL
) && (prv
->last
->ref
> 0) ){
520 put_ts_section_list_tail(&(prv
->buff
), elem
);
521 prv
->stat
.total
+= 1;
522 prv
->stat
.unique
+= 1;
525 static TS_SECTION_ELEM
*query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA
*prv
)
534 r
= (TS_SECTION_ELEM
*)(r
->next
);
538 unlink_ts_section_list(&(prv
->pool
), r
);
539 reset_section(&(r
->sect
));
544 return create_ts_section_elem();
547 static void extract_ts_section_header(TS_SECTION
*sect
)
554 size
= sect
->tail
- sect
->raw
;
562 sect
->hdr
.table_id
= p
[0];
563 sect
->hdr
.section_syntax_indicator
= (p
[1] >> 7) & 0x01;
564 sect
->hdr
.private_indicator
= (p
[1] >> 6) & 0x01;
565 sect
->hdr
.section_length
=((p
[1] << 8) | p
[2]) & 0x0fff;
567 if(sect
->hdr
.section_syntax_indicator
== 0){
568 /* short format section header */
573 /* long format section header */
580 sect
->hdr
.table_id_extension
=((p
[3] << 8) | p
[4]);
581 sect
->hdr
.version_number
= (p
[5] >> 1) & 0x1f;
582 sect
->hdr
.current_next_indicator
= p
[5] & 0x01;
583 sect
->hdr
.section_number
= p
[6];
584 sect
->hdr
.last_section_number
= p
[7];
591 static TS_SECTION_ELEM
*create_ts_section_elem()
596 n
= sizeof(TS_SECTION_ELEM
) + MAX_RAW_SECTION_SIZE
;
597 r
= (TS_SECTION_ELEM
*)calloc(1, n
);
599 /* failed on malloc() */
603 r
->sect
.raw
= (uint8_t *)(r
+1);
604 r
->sect
.tail
= r
->sect
.raw
;
609 static TS_SECTION_ELEM
*get_ts_section_list_head(TS_SECTION_LIST
*list
)
613 if(list
== NULL
){/* invalid param */
622 list
->head
= (TS_SECTION_ELEM
*)(r
->next
);
623 if(list
->head
!= NULL
){
624 list
->head
->prev
= NULL
;
636 static void put_ts_section_list_tail(TS_SECTION_LIST
*list
, TS_SECTION_ELEM
*elem
)
638 if( (list
== NULL
) || (elem
== NULL
) ){
643 if(list
->tail
!= NULL
){
644 elem
->prev
= list
->tail
;
646 list
->tail
->next
= elem
;
658 static void unlink_ts_section_list(TS_SECTION_LIST
*list
, TS_SECTION_ELEM
*elem
)
660 TS_SECTION_ELEM
*prev
;
661 TS_SECTION_ELEM
*next
;
663 if( (list
== NULL
) || (elem
== NULL
) ){
668 prev
= (TS_SECTION_ELEM
*)(elem
->prev
);
669 next
= (TS_SECTION_ELEM
*)(elem
->next
);
684 static void clear_ts_section_list(TS_SECTION_LIST
*list
)
689 if(list
== NULL
){ /* invalid param */
695 n
= (TS_SECTION_ELEM
*)(e
->next
);
705 static uint32_t crc32(uint8_t *head
, uint8_t *tail
)
710 static const uint32_t table
[256] = {
711 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
712 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
713 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
714 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
716 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
717 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
718 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
719 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
721 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
722 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
723 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
724 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
726 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
727 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
728 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
729 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
731 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
732 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
733 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
734 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
736 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
737 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
738 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
739 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
741 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
742 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
743 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
744 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
746 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
747 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
748 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
749 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
751 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
752 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
753 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
754 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
756 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
757 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
758 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
759 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
761 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
762 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
763 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
764 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
766 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
767 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
768 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
769 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
771 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
772 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
773 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
774 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
776 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
777 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
778 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
779 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
781 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
782 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
783 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
784 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
786 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
787 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
788 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
789 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4,
796 crc
= (crc
<< 8) ^ table
[ ((crc
>> 24) ^ p
[0]) & 0xff ];