0
|
1 #include <stdlib.h>
|
|
2 #include <string.h>
|
|
3
|
|
4 #include "ts_section_parser.h"
|
|
5 #include "ts_section_parser_error_code.h"
|
|
6
|
|
7 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
8 inner structures
|
|
9 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
10 typedef struct {
|
|
11 void *prev;
|
|
12 void *next;
|
|
13 TS_SECTION sect;
|
|
14 int32_t ref;
|
|
15 } TS_SECTION_ELEM;
|
|
16
|
|
17 typedef struct {
|
|
18 TS_SECTION_ELEM *head;
|
|
19 TS_SECTION_ELEM *tail;
|
|
20 int32_t count;
|
|
21 } TS_SECTION_LIST;
|
|
22
|
|
23 typedef struct {
|
|
24
|
|
25 int32_t pid;
|
|
26
|
|
27 TS_SECTION_ELEM *work;
|
|
28 TS_SECTION_ELEM *last;
|
|
29
|
|
30 TS_SECTION_LIST pool;
|
|
31 TS_SECTION_LIST buff;
|
|
32
|
|
33 TS_SECTION_PARSER_STAT stat;
|
|
34
|
|
35 } TS_SECTION_PARSER_PRIVATE_DATA;
|
|
36
|
|
37 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
38 constant values
|
|
39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
40 #define MAX_RAW_SECTION_SIZE 4100
|
|
41
|
|
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);
|
|
52
|
|
53 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
54 global function implementation (factory method)
|
|
55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
56 TS_SECTION_PARSER *create_ts_section_parser()
|
|
57 {
|
|
58 TS_SECTION_PARSER *r;
|
|
59 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
60
|
|
61 int n;
|
|
62
|
|
63 n = sizeof(TS_SECTION_PARSER_PRIVATE_DATA);
|
|
64 n += sizeof(TS_SECTION_PARSER);
|
|
65
|
|
66 prv = (TS_SECTION_PARSER_PRIVATE_DATA *)calloc(1, n);
|
|
67 if(prv == NULL){
|
|
68 /* failed on malloc() - no enough memory */
|
|
69 return NULL;
|
|
70 }
|
|
71
|
|
72 prv->pid = -1;
|
|
73
|
|
74 r = (TS_SECTION_PARSER *)(prv+1);
|
|
75 r->private_data = prv;
|
|
76
|
|
77 r->release = release_ts_section_parser;
|
|
78 r->reset = reset_ts_section_parser;
|
|
79
|
|
80 r->put = put_ts_section_parser;
|
|
81 r->get = get_ts_section_parser;
|
|
82 r->ret = ret_ts_section_parser;
|
|
83
|
|
84 r->get_count = get_count_ts_section_parser;
|
|
85
|
|
86 r->get_stat = get_stat_ts_section_parser;
|
|
87
|
|
88 return r;
|
|
89 }
|
|
90
|
|
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);
|
|
96
|
|
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);
|
|
99
|
|
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);
|
|
103
|
|
104 static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b);
|
|
105
|
|
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);
|
|
110
|
|
111 static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv);
|
|
112
|
|
113 static void extract_ts_section_header(TS_SECTION *sect);
|
|
114
|
|
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);
|
|
120
|
|
121 static uint32_t crc32(uint8_t *head, uint8_t *tail);
|
|
122
|
|
123 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
124 function implementation (interface method)
|
|
125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
126 static void release_ts_section_parser(void *parser)
|
|
127 {
|
|
128 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
129
|
|
130 prv = private_data(parser);
|
|
131 if(prv == NULL){
|
|
132 return;
|
|
133 }
|
|
134
|
|
135 teardown(prv);
|
|
136
|
|
137 memset(parser, 0, sizeof(TS_SECTION_PARSER));
|
|
138 free(prv);
|
|
139 }
|
|
140
|
|
141 static int reset_ts_section_parser(void *parser)
|
|
142 {
|
|
143 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
144
|
|
145 prv = private_data(parser);
|
|
146 if(prv == NULL){
|
|
147 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
148 }
|
|
149
|
|
150 teardown(prv);
|
|
151
|
|
152 return 0;
|
|
153 }
|
|
154
|
|
155 static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size)
|
|
156 {
|
|
157 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
158
|
|
159 prv = private_data(parser);
|
|
160 if( (prv == NULL) || (hdr == NULL) || (data == NULL) || (size < 1) ){
|
|
161 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
162 }
|
|
163
|
|
164 if( (prv->pid >= 0) && (prv->pid != hdr->pid) ){
|
|
165 return TS_SECTION_PARSER_ERROR_INVALID_TS_PID;
|
|
166 }
|
|
167
|
|
168 prv->pid = hdr->pid;
|
|
169
|
|
170 if(hdr->payload_unit_start_indicator == 0){
|
|
171 /* exclude section start */
|
|
172 return put_exclude_section_start(prv, data, size);
|
|
173 }else{
|
|
174 /* include section start */
|
|
175 return put_include_section_start(prv, data, size);
|
|
176 }
|
|
177 }
|
|
178
|
|
179 static int get_ts_section_parser(void *parser, TS_SECTION *sect)
|
|
180 {
|
|
181 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
182 TS_SECTION_ELEM *w;
|
|
183
|
|
184 prv = private_data(parser);
|
|
185 if( (prv == NULL) || (sect == NULL) ){
|
|
186 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
187 }
|
|
188
|
|
189 w = get_ts_section_list_head(&(prv->buff));
|
|
190 if(w == NULL){
|
|
191 memset(sect, 0, sizeof(TS_SECTION));
|
|
192 return TS_SECTION_PARSER_ERROR_NO_SECTION_DATA;
|
|
193 }
|
|
194
|
|
195 memcpy(sect, &(w->sect), sizeof(TS_SECTION));
|
|
196 put_ts_section_list_tail(&(prv->pool), w);
|
|
197
|
|
198 return 0;
|
|
199 }
|
|
200
|
|
201 static int ret_ts_section_parser(void *parser, TS_SECTION *sect)
|
|
202 {
|
|
203 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
204 TS_SECTION_ELEM *w;
|
|
205
|
|
206 prv = private_data(parser);
|
|
207 if( (prv == NULL) || (sect == NULL) ){
|
|
208 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
209 }
|
|
210
|
|
211 w = prv->pool.tail;
|
|
212 while(w != NULL){
|
|
213 if(w->sect.data == sect->data){
|
|
214 break;
|
|
215 }
|
|
216 w = (TS_SECTION_ELEM *)(w->prev);
|
|
217 }
|
|
218
|
|
219 if( (w != NULL) && (w->ref > 0) ){
|
|
220 w->ref -= 1;
|
|
221 }
|
|
222
|
|
223 return 0;
|
|
224 }
|
|
225
|
|
226 static int get_count_ts_section_parser(void *parser)
|
|
227 {
|
|
228 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
229
|
|
230 prv = private_data(parser);
|
|
231 if(prv == NULL){
|
|
232 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
233 }
|
|
234
|
|
235 return prv->buff.count;
|
|
236 }
|
|
237
|
|
238 static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat)
|
|
239 {
|
|
240 TS_SECTION_PARSER_PRIVATE_DATA *prv;
|
|
241
|
|
242 prv = private_data(parser);
|
|
243 if( (prv == NULL) || (stat == NULL) ){
|
|
244 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
|
|
245 }
|
|
246
|
|
247 memcpy(stat, &(prv->stat), sizeof(TS_SECTION_PARSER_STAT));
|
|
248
|
|
249 return 0;
|
|
250 }
|
|
251
|
|
252 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
253 function implementation (private method)
|
|
254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
255 static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser)
|
|
256 {
|
|
257 TS_SECTION_PARSER_PRIVATE_DATA *r;
|
|
258 TS_SECTION_PARSER *p;
|
|
259
|
|
260 p = (TS_SECTION_PARSER *)parser;
|
|
261 if(p == NULL){
|
|
262 return NULL;
|
|
263 }
|
|
264
|
|
265 r = (TS_SECTION_PARSER_PRIVATE_DATA *)(p->private_data);
|
|
266 if( ((void *)(r+1)) != parser ){
|
|
267 return NULL;
|
|
268 }
|
|
269
|
|
270 return r;
|
|
271 }
|
|
272
|
|
273 static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv)
|
|
274 {
|
|
275 prv->pid = -1;
|
|
276
|
|
277 if(prv->work != NULL){
|
|
278 free(prv->work);
|
|
279 prv->work = NULL;
|
|
280 }
|
|
281
|
|
282 prv->last = NULL;
|
|
283
|
|
284 clear_ts_section_list(&(prv->pool));
|
|
285 clear_ts_section_list(&(prv->buff));
|
|
286
|
|
287 memset(&(prv->stat), 0, sizeof(TS_SECTION_PARSER_STAT));
|
|
288 }
|
|
289
|
|
290 static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size)
|
|
291 {
|
|
292 TS_SECTION_ELEM *w;
|
|
293
|
|
294 w = prv->work;
|
|
295 if( (w == NULL) || (w->sect.raw == w->sect.tail) ){
|
|
296 /* no previous data */
|
|
297 return 0;
|
|
298 }
|
|
299
|
|
300 append_section_data(&(w->sect), data, size);
|
|
301 if(check_section_complete(&(w->sect)) == 0){
|
|
302 /* need more data */
|
|
303 return 0;
|
|
304 }
|
|
305
|
|
306 prv->work = NULL;
|
|
307
|
|
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;
|
|
312 }
|
|
313
|
|
314 if(compare_elem_section(w, prv->last) == 0){
|
|
315 /* same section data */
|
|
316 cancel_elem_same(prv, w);
|
|
317 return 0;
|
|
318 }
|
|
319
|
|
320 commit_elem_updated(prv, w);
|
|
321 return 0;
|
|
322 }
|
|
323
|
|
324 static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size)
|
|
325 {
|
|
326 TS_SECTION_ELEM *w;
|
|
327
|
|
328 int pointer_field;
|
|
329
|
|
330 uint8_t *p;
|
|
331 uint8_t *tail;
|
|
332
|
|
333 int r;
|
|
334 int length;
|
|
335
|
|
336 p = data;
|
|
337 tail = p + size;
|
|
338
|
|
339 r = 0;
|
|
340
|
|
341 pointer_field = p[0];
|
|
342 p += 1;
|
|
343
|
|
344 if( (p+pointer_field) >= tail ){
|
|
345 /* input data is probably broken */
|
|
346 w = prv->work;
|
|
347 prv->work = NULL;
|
|
348 if(w != NULL) {
|
|
349 if(w->sect.raw != w->sect.tail){
|
|
350 cancel_elem_error(prv, w);
|
|
351 return TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH;
|
|
352 }
|
|
353 cancel_elem_empty(prv, w);
|
|
354 }
|
|
355 return 0;
|
|
356 }
|
|
357
|
|
358 if(pointer_field > 0){
|
|
359 r = put_exclude_section_start(prv, p, pointer_field);
|
|
360 if(r < 0){
|
|
361 return r;
|
|
362 }
|
|
363 p += pointer_field;
|
|
364 }
|
|
365
|
|
366 w = prv->work;
|
|
367 prv->work = NULL;
|
|
368
|
|
369 if(w != NULL){
|
|
370 if(w->sect.raw != w->sect.tail){
|
|
371 cancel_elem_error(prv, w);
|
|
372 r = TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH;
|
|
373 }else{
|
|
374 cancel_elem_empty(prv, w);
|
|
375 }
|
|
376 w = NULL;
|
|
377 }
|
|
378
|
|
379 do {
|
|
380
|
|
381 w = query_work_elem(prv);
|
|
382 if(w == NULL){
|
|
383 return TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY;
|
|
384 }
|
|
385
|
|
386 append_section_data(&(w->sect), p, tail-p);
|
|
387 if(check_section_complete(&(w->sect)) == 0){
|
|
388 /* need more data */
|
|
389 prv->work = w;
|
|
390 return 0;
|
|
391 }
|
|
392 length = (w->sect.tail - w->sect.raw);
|
|
393
|
|
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);
|
|
400 }else{
|
|
401 commit_elem_updated(prv, w);
|
|
402 }
|
|
403
|
|
404 p += length;
|
|
405
|
|
406 } while ( (p < tail) && (p[0] != 0xff) );
|
|
407
|
|
408 return r;
|
|
409 }
|
|
410
|
|
411 static void reset_section(TS_SECTION *sect)
|
|
412 {
|
|
413 memset(&(sect->hdr), 0, sizeof(TS_SECTION_HEADER));
|
|
414 sect->tail = sect->raw;
|
|
415 sect->data = NULL;
|
|
416 }
|
|
417
|
|
418 static void append_section_data(TS_SECTION *sect, uint8_t *data, int size)
|
|
419 {
|
|
420 int m,n;
|
|
421
|
|
422 m = sect->tail - sect->raw;
|
|
423 n = MAX_RAW_SECTION_SIZE - m;
|
|
424
|
|
425 if(size < n){
|
|
426 n = size;
|
|
427 }
|
|
428 memcpy(sect->tail, data, n);
|
|
429 sect->tail += n;
|
|
430 m += n;
|
|
431
|
|
432 if(sect->data == NULL){
|
|
433 extract_ts_section_header(sect);
|
|
434 }
|
|
435
|
|
436 if(sect->data == NULL){
|
|
437 /* need more data */
|
|
438 return;
|
|
439 }
|
|
440
|
|
441 n = sect->hdr.section_length + 3;
|
|
442 if(m > n){
|
|
443 sect->tail = sect->raw + n;
|
|
444 }
|
|
445
|
|
446 return;
|
|
447 }
|
|
448
|
|
449 static int check_section_complete(TS_SECTION *sect)
|
|
450 {
|
|
451 int m,n;
|
|
452
|
|
453 if(sect->data == NULL){
|
|
454 return 0;
|
|
455 }
|
|
456
|
|
457 m = sect->tail - sect->raw;
|
|
458 n = sect->hdr.section_length + 3;
|
|
459
|
|
460 if(n > m){
|
|
461 return 0;
|
|
462 }
|
|
463
|
|
464 return 1;
|
|
465 }
|
|
466
|
|
467 static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b)
|
|
468 {
|
|
469 int m,n;
|
|
470
|
|
471 if( (a == NULL) || (b == NULL) ){
|
|
472 return 1;
|
|
473 }
|
|
474
|
|
475 m = a->sect.tail - a->sect.raw;
|
|
476 n = b->sect.tail - b->sect.raw;
|
|
477 if( m != n ){
|
|
478 return 1;
|
|
479 }
|
|
480
|
|
481 if(memcmp(a->sect.raw, b->sect.raw, m) != 0){
|
|
482 return 1;
|
|
483 }
|
|
484
|
|
485 return 0;
|
|
486 }
|
|
487
|
|
488 static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
|
|
489 {
|
|
490 reset_section(&(elem->sect));
|
|
491 elem->ref = 0;
|
|
492 put_ts_section_list_tail(&(prv->pool), elem);
|
|
493 }
|
|
494
|
|
495 static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
|
|
496 {
|
|
497 reset_section(&(elem->sect));
|
|
498 elem->ref = 0;
|
|
499 put_ts_section_list_tail(&(prv->pool), elem);
|
|
500 prv->stat.total += 1;
|
|
501 prv->stat.error += 1;
|
|
502 }
|
|
503
|
|
504 static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
|
|
505 {
|
|
506 reset_section(&(elem->sect));
|
|
507 elem->ref = 0;
|
|
508 put_ts_section_list_tail(&(prv->pool), elem);
|
|
509 prv->stat.total +=1;
|
|
510 }
|
|
511
|
|
512 static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
|
|
513 {
|
|
514 if( (prv->last != NULL) && (prv->last->ref > 0) ){
|
|
515 prv->last->ref -= 1;
|
|
516 }
|
|
517
|
|
518 elem->ref = 2;
|
|
519 prv->last = elem;
|
|
520 put_ts_section_list_tail(&(prv->buff), elem);
|
|
521 prv->stat.total += 1;
|
|
522 prv->stat.unique += 1;
|
|
523 }
|
|
524
|
|
525 static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv)
|
|
526 {
|
|
527 TS_SECTION_ELEM *r;
|
|
528
|
|
529 r = prv->pool.head;
|
|
530 while(r != NULL){
|
|
531 if(r->ref < 1){
|
|
532 break;
|
|
533 }
|
|
534 r = (TS_SECTION_ELEM *)(r->next);
|
|
535 }
|
|
536
|
|
537 if(r != NULL){
|
|
538 unlink_ts_section_list(&(prv->pool), r);
|
|
539 reset_section(&(r->sect));
|
|
540 r->ref = 0;
|
|
541 return r;
|
|
542 }
|
|
543
|
|
544 return create_ts_section_elem();
|
|
545 }
|
|
546
|
|
547 static void extract_ts_section_header(TS_SECTION *sect)
|
|
548 {
|
|
549 int size;
|
|
550 uint8_t *p;
|
|
551
|
|
552 sect->data = NULL;
|
|
553
|
|
554 size = sect->tail - sect->raw;
|
|
555 if(size < 3){
|
|
556 /* need more data */
|
|
557 return;
|
|
558 }
|
|
559
|
|
560 p = sect->raw;
|
|
561
|
|
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;
|
|
566
|
|
567 if(sect->hdr.section_syntax_indicator == 0){
|
|
568 /* short format section header */
|
|
569 sect->data = p+3;
|
|
570 return;
|
|
571 }
|
|
572
|
|
573 /* long format section header */
|
|
574
|
|
575 if(size < 8){
|
|
576 /* need more data */
|
|
577 return;
|
|
578 }
|
|
579
|
|
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];
|
|
585
|
|
586 sect->data = p+8;
|
|
587
|
|
588 return;
|
|
589 }
|
|
590
|
|
591 static TS_SECTION_ELEM *create_ts_section_elem()
|
|
592 {
|
|
593 TS_SECTION_ELEM *r;
|
|
594 int n;
|
|
595
|
|
596 n = sizeof(TS_SECTION_ELEM) + MAX_RAW_SECTION_SIZE;
|
|
597 r = (TS_SECTION_ELEM *)calloc(1, n);
|
|
598 if(r == NULL){
|
|
599 /* failed on malloc() */
|
|
600 return NULL;
|
|
601 }
|
|
602
|
|
603 r->sect.raw = (uint8_t *)(r+1);
|
|
604 r->sect.tail = r->sect.raw;
|
|
605
|
|
606 return r;
|
|
607 }
|
|
608
|
|
609 static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list)
|
|
610 {
|
|
611 TS_SECTION_ELEM *r;
|
|
612
|
|
613 if(list == NULL){/* invalid param */
|
|
614 return NULL;
|
|
615 }
|
|
616
|
|
617 r = list->head;
|
|
618 if(r == NULL){
|
|
619 return NULL;
|
|
620 }
|
|
621
|
|
622 list->head = (TS_SECTION_ELEM *)(r->next);
|
|
623 if(list->head != NULL){
|
|
624 list->head->prev = NULL;
|
|
625 list->count -= 1;
|
|
626 }else{
|
|
627 list->tail = NULL;
|
|
628 list->count = 0;
|
|
629 }
|
|
630
|
|
631 r->next = NULL;
|
|
632
|
|
633 return r;
|
|
634 }
|
|
635
|
|
636 static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem)
|
|
637 {
|
|
638 if( (list == NULL) || (elem == NULL) ){
|
|
639 /* invalid param */
|
|
640 return;
|
|
641 }
|
|
642
|
|
643 if(list->tail != NULL){
|
|
644 elem->prev = list->tail;
|
|
645 elem->next = NULL;
|
|
646 list->tail->next = elem;
|
|
647 list->tail = elem;
|
|
648 list->count += 1;
|
|
649 }else{
|
|
650 elem->prev = NULL;
|
|
651 elem->next = NULL;
|
|
652 list->head = elem;
|
|
653 list->tail = elem;
|
|
654 list->count = 1;
|
|
655 }
|
|
656 }
|
|
657
|
|
658 static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem)
|
|
659 {
|
|
660 TS_SECTION_ELEM *prev;
|
|
661 TS_SECTION_ELEM *next;
|
|
662
|
|
663 if( (list == NULL) || (elem == NULL) ){
|
|
664 /* invalid param */
|
|
665 return;
|
|
666 }
|
|
667
|
|
668 prev = (TS_SECTION_ELEM *)(elem->prev);
|
|
669 next = (TS_SECTION_ELEM *)(elem->next);
|
|
670
|
|
671 if(prev != NULL){
|
|
672 prev->next = next;
|
|
673 }else{
|
|
674 list->head = next;
|
|
675 }
|
|
676 if(next != NULL){
|
|
677 next->prev = prev;
|
|
678 }else{
|
|
679 list->tail = prev;
|
|
680 }
|
|
681 list->count -= 1;
|
|
682 }
|
|
683
|
|
684 static void clear_ts_section_list(TS_SECTION_LIST *list)
|
|
685 {
|
|
686 TS_SECTION_ELEM *e;
|
|
687 TS_SECTION_ELEM *n;
|
|
688
|
|
689 if(list == NULL){ /* invalid param */
|
|
690 return;
|
|
691 }
|
|
692
|
|
693 e = list->head;
|
|
694 while(e != NULL){
|
|
695 n = (TS_SECTION_ELEM *)(e->next);
|
|
696 free(e);
|
|
697 e = n;
|
|
698 }
|
|
699
|
|
700 list->head = NULL;
|
|
701 list->tail = NULL;
|
|
702 list->count = 0;
|
|
703 }
|
|
704
|
|
705 static uint32_t crc32(uint8_t *head, uint8_t *tail)
|
|
706 {
|
|
707 uint32_t crc;
|
|
708 uint8_t *p;
|
|
709
|
|
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,
|
|
715
|
|
716 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
|
|
717 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
|
|
718 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
|
|
719 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
|
|
720
|
|
721 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
|
|
722 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
|
|
723 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
|
|
724 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
|
|
725
|
|
726 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
|
|
727 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
|
|
728 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
|
|
729 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
|
|
730
|
|
731 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
|
|
732 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
|
|
733 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
|
|
734 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
|
|
735
|
|
736 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
|
|
737 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
|
|
738 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
|
|
739 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
|
|
740
|
|
741 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
|
|
742 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
|
|
743 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
|
|
744 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
|
|
745
|
|
746 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
|
|
747 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
|
|
748 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
|
|
749 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
|
|
750
|
|
751 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
|
|
752 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
|
|
753 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
|
|
754 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
|
|
755
|
|
756 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
|
|
757 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
|
|
758 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
|
|
759 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
|
|
760
|
|
761 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
|
|
762 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
|
|
763 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
|
|
764 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
|
|
765
|
|
766 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
|
|
767 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
|
|
768 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
|
|
769 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
|
|
770
|
|
771 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
|
|
772 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
|
|
773 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
|
|
774 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
|
|
775
|
|
776 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
|
|
777 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
|
|
778 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
|
|
779 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
|
|
780
|
|
781 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
|
|
782 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
|
|
783 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
|
|
784 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
|
|
785
|
|
786 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
|
|
787 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
|
|
788 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
|
|
789 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4,
|
|
790 };
|
|
791
|
|
792 crc = 0xffffffff;
|
|
793
|
|
794 p = head;
|
|
795 while(p < tail){
|
|
796 crc = (crc << 8) ^ table[ ((crc >> 24) ^ p[0]) & 0xff ];
|
|
797 p += 1;
|
|
798 }
|
|
799
|
|
800 return crc;
|
|
801 }
|
|
802
|