Mercurial > pt1
comparison recpt1/tssplitter_lite.c @ 127:8e0f7191b92e
Imported PID re-acquisition code by Toshiyuki Kawashima
<tos@fa2.so-net.ne.jp>. The original patch can be obtained
from http://www.castanet.homeip.net/~tos/wiki/index.php
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 12 Mar 2012 22:22:27 +0900 |
parents | a910b49dfbee |
children | 9e9dbb17b70f |
comparison
equal
deleted
inserted
replaced
126:bb93a7c0ff5d | 127:8e0f7191b92e |
---|---|
31 /* prototypes */ | 31 /* prototypes */ |
32 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); | 32 static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); |
33 static int AnalyzePat(splitter *sp, unsigned char *buf); | 33 static int AnalyzePat(splitter *sp, unsigned char *buf); |
34 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); | 34 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); |
35 static char** AnalyzeSid(char *sid); | 35 static char** AnalyzeSid(char *sid); |
36 static int AnalyzePmt(splitter *sp, unsigned char *buf); | 36 static int AnalyzePmt(splitter *sp, unsigned char *buf, unsigned char mark); |
37 static int GetCrc32(unsigned char *data, int len); | 37 static int GetCrc32(unsigned char *data, int len); |
38 static int GetPid(unsigned char *data); | 38 static int GetPid(unsigned char *data); |
39 | 39 |
40 /** | 40 /** |
41 * サービスID解析 | 41 * サービスID解析 |
157 return NULL; | 157 return NULL; |
158 } | 158 } |
159 sp->pat_count = 0xFF; | 159 sp->pat_count = 0xFF; |
160 sp->pmt_retain = -1; | 160 sp->pmt_retain = -1; |
161 sp->pmt_counter = 0; | 161 sp->pmt_counter = 0; |
162 | |
163 memset(sp->section_remain, 0U, sizeof(sp->section_remain)); | |
164 memset(sp->packet_seq, 0U, sizeof(sp->packet_seq)); | |
162 | 165 |
163 return sp; | 166 return sp; |
164 } | 167 } |
165 | 168 |
166 /** | 169 /** |
218 | 221 |
219 int length = sbuf->size; | 222 int length = sbuf->size; |
220 int pid; | 223 int pid; |
221 int result = TSS_ERROR; | 224 int result = TSS_ERROR; |
222 int index; | 225 int index; |
226 int analyze_result = 0; | |
223 | 227 |
224 index = 0; | 228 index = 0; |
225 while(length - index - LENGTH_PACKET > 0) { | 229 while(length - index - LENGTH_PACKET > 0) { |
226 pid = GetPid(sbuf->data + index + 1); | 230 pid = GetPid(sbuf->data + index + 1); |
227 // PAT | 231 // PAT |
236 // PMT | 240 // PMT |
237 /* 残すpmt_pidである場合には、pmtに書かれている | 241 /* 残すpmt_pidである場合には、pmtに書かれている |
238 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ | 242 * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ |
239 if(sp->pmt_pids[pid] == 1) { | 243 if(sp->pmt_pids[pid] == 1) { |
240 /* この中にはPMT毎に一度しか入らないようにしておく */ | 244 /* この中にはPMT毎に一度しか入らないようにしておく */ |
241 result = AnalyzePmt(sp, sbuf->data + index); | 245 analyze_result = AnalyzePmt(sp, sbuf->data + index, 1); |
242 if(result != TSS_SUCCESS) { | 246 if(TSS_SUCCESS == analyze_result) { |
243 return result; | 247 sp->pmt_pids[pid]++; |
244 } | 248 sp->pmt_counter += 1; |
245 sp->pmt_pids[pid]++; | 249 *(sbuf->data + index + 1) = 0xff; |
246 sp->pmt_counter += 1; | 250 *(sbuf->data + index + 2) = 0xff; |
251 } | |
247 } | 252 } |
248 /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを | 253 /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを |
249 * 得る */ | 254 * 得る */ |
250 /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ | 255 /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ |
251 if(sp->pmt_counter == sp->pmt_retain) { | 256 if(sp->pmt_counter == sp->pmt_retain) { |
259 } | 264 } |
260 | 265 |
261 return(result); | 266 return(result); |
262 } | 267 } |
263 | 268 |
269 static int RescanPID(splitter *splitter, unsigned char *buf) | |
270 { | |
271 int result = TSS_NULL; | |
272 int i; | |
273 | |
274 // clear | |
275 if (splitter->pmt_counter == splitter->pmt_retain) { | |
276 memcpy(splitter->pids, splitter->pmt_pids, sizeof(splitter->pids)); | |
277 splitter->pmt_counter = 0; | |
278 memset(splitter->section_remain, 0U, sizeof(splitter->section_remain)); | |
279 memset(splitter->packet_seq, 0U, sizeof(splitter->packet_seq)); | |
280 | |
281 fprintf(stderr, "Rescan PID \n"); | |
282 } | |
283 | |
284 if (TSS_SUCCESS == AnalyzePmt(splitter, buf, 2)) { | |
285 splitter->pmt_counter += 1; | |
286 } | |
287 | |
288 if (splitter->pmt_retain == splitter->pmt_counter) { | |
289 result = TSS_SUCCESS; | |
290 for (i = 0; MAX_PID > i; i++) { | |
291 if (splitter->pids[i] > 0) { | |
292 splitter->pids[i] -= 1; | |
293 } | |
294 } | |
295 fprintf(stderr, "Rescan PID End\n"); | |
296 } | |
297 | |
298 return result; | |
299 } | |
264 /** | 300 /** |
265 * TS 分離処理 | 301 * TS 分離処理 |
266 */ | 302 */ |
267 int split_ts( | 303 int split_ts( |
268 splitter *splitter, // [in] splitterパラメータ | 304 splitter *splitter, // [in] splitterパラメータ |
272 { | 308 { |
273 int pid; | 309 int pid; |
274 unsigned char *sptr, *dptr; | 310 unsigned char *sptr, *dptr; |
275 int s_offset = 0; | 311 int s_offset = 0; |
276 int d_offset = 0; | 312 int d_offset = 0; |
313 int result = TSS_SUCCESS; | |
314 int pmts = 0; | |
315 int version = 0; | |
277 | 316 |
278 /* 初期化 */ | 317 /* 初期化 */ |
279 dbuf->size = 0; | 318 dbuf->size = 0; |
280 if (sbuf->size < 0) { | 319 if (sbuf->size < 0) { |
281 return TSS_ERROR; | 320 return TSS_ERROR; |
305 memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET); | 344 memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET); |
306 d_offset += LENGTH_PACKET; | 345 d_offset += LENGTH_PACKET; |
307 dbuf->size += LENGTH_PACKET; | 346 dbuf->size += LENGTH_PACKET; |
308 break; | 347 break; |
309 default: | 348 default: |
349 if(0 != splitter->pmt_pids[pid]) { | |
350 //PMT | |
351 if ((sptr + s_offset)[1] & 0x40) { // PES開始インジケータ | |
352 // バージョンチェック | |
353 for(pmts = 0; splitter->pmt_retain > pmts; pmts++) { | |
354 if (splitter->pmt_version[pmts].pid == pid) { | |
355 version = splitter->pmt_version[pmts].version; | |
356 break; | |
357 } | |
358 } | |
359 if((version != ((sptr + s_offset)[10] & 0x3e)) | |
360 ||(splitter->pmt_retain != splitter->pmt_counter)) { | |
361 // 再チェック | |
362 result = RescanPID(splitter, sptr + s_offset); | |
363 } | |
364 } | |
365 else { | |
366 if (splitter->pmt_retain != splitter->pmt_counter) { | |
367 // 再チェック | |
368 result = RescanPID(splitter, sptr + s_offset); | |
369 } | |
370 } | |
371 } | |
310 /* pids[pid] が 1 は残すパケットなので書き込む */ | 372 /* pids[pid] が 1 は残すパケットなので書き込む */ |
311 if(1 == splitter->pids[pid]) { | 373 if(0 != splitter->pids[pid]) { |
312 memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); | 374 memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); |
313 d_offset += LENGTH_PACKET; | 375 d_offset += LENGTH_PACKET; |
314 dbuf->size += LENGTH_PACKET; | 376 dbuf->size += LENGTH_PACKET; |
315 } | 377 } |
316 break; | 378 break; |
317 } /* switch */ | 379 } /* switch */ |
318 | 380 |
319 s_offset += LENGTH_PACKET; | 381 s_offset += LENGTH_PACKET; |
320 } | 382 } |
321 | 383 |
322 return(TSS_SUCCESS); | 384 return result; |
323 } | 385 } |
324 | 386 |
325 /** | 387 /** |
326 * PAT 解析処理 | 388 * PAT 解析処理 |
327 * | 389 * |
333 unsigned char** pat, // [out] PAT 情報(再構築後) | 395 unsigned char** pat, // [out] PAT 情報(再構築後) |
334 unsigned char* pids, // [out] 出力対象 PID 情報 | 396 unsigned char* pids, // [out] 出力対象 PID 情報 |
335 char** sid_list, // [in] 出力対象サービス ID のリスト | 397 char** sid_list, // [in] 出力対象サービス ID のリスト |
336 unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID | 398 unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID |
337 int* pmt_retain // [out] 残すPMTの数 | 399 int* pmt_retain // [out] 残すPMTの数 |
338 ) | 400 |
339 #endif | 401 #endif |
340 { | 402 { |
341 int pos[MAX_PID]; | 403 int pos[MAX_PID]; |
342 int service_id; | 404 int service_id; |
343 int i, j, k; | 405 int i, j, k; |
384 pid = GetPid(&buf[i + 2]); | 446 pid = GetPid(&buf[i + 2]); |
385 *(pmt_pids+pid) = 1; | 447 *(pmt_pids+pid) = 1; |
386 *(pids+pid) = 1; | 448 *(pids+pid) = 1; |
387 pos[pid] = i; | 449 pos[pid] = i; |
388 sid_found = TRUE; | 450 sid_found = TRUE; |
451 sp->pmt_version[sp->pmt_retain].pid = pid; | |
389 sp->pmt_retain += 1; | 452 sp->pmt_retain += 1; |
390 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 453 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
391 p++; | 454 p++; |
392 continue; | 455 continue; |
393 } | 456 } |
397 pid = GetPid(&buf[i + 2]); | 460 pid = GetPid(&buf[i + 2]); |
398 *(pmt_pids+pid) = 1; | 461 *(pmt_pids+pid) = 1; |
399 *(pids+pid) = 1; | 462 *(pids+pid) = 1; |
400 pos[pid] = i; | 463 pos[pid] = i; |
401 sid_found = TRUE; | 464 sid_found = TRUE; |
465 sp->pmt_version[sp->pmt_retain].pid = pid; | |
402 sp->pmt_retain += 1; | 466 sp->pmt_retain += 1; |
403 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 467 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
404 } | 468 } |
405 p++; | 469 p++; |
406 continue; | 470 continue; |
411 pid = GetPid(&buf[i + 2]); | 475 pid = GetPid(&buf[i + 2]); |
412 *(pmt_pids+pid) = 1; | 476 *(pmt_pids+pid) = 1; |
413 *(pids+pid) = 1; | 477 *(pids+pid) = 1; |
414 pos[pid] = i; | 478 pos[pid] = i; |
415 sid_found = TRUE; | 479 sid_found = TRUE; |
480 sp->pmt_version[sp->pmt_retain].pid = pid; | |
416 sp->pmt_retain += 1; | 481 sp->pmt_retain += 1; |
417 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 482 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
418 } | 483 } |
419 p++; | 484 p++; |
420 continue; | 485 continue; |
425 pid = GetPid(&buf[i + 2]); | 490 pid = GetPid(&buf[i + 2]); |
426 *(pmt_pids+pid) = 1; | 491 *(pmt_pids+pid) = 1; |
427 *(pids+pid) = 1; | 492 *(pids+pid) = 1; |
428 pos[pid] = i; | 493 pos[pid] = i; |
429 sid_found = TRUE; | 494 sid_found = TRUE; |
495 sp->pmt_version[sp->pmt_retain].pid = pid; | |
430 sp->pmt_retain += 1; | 496 sp->pmt_retain += 1; |
431 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 497 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
432 } | 498 } |
433 p++; | 499 p++; |
434 continue; | 500 continue; |
439 if(pid == 0x1FC8) { | 505 if(pid == 0x1FC8) { |
440 *(pmt_pids+pid) = 1; | 506 *(pmt_pids+pid) = 1; |
441 *(pids+pid) = 1; | 507 *(pids+pid) = 1; |
442 pos[pid] = i; | 508 pos[pid] = i; |
443 sid_found = TRUE; | 509 sid_found = TRUE; |
510 sp->pmt_version[sp->pmt_retain].pid = pid; | |
444 sp->pmt_retain += 1; | 511 sp->pmt_retain += 1; |
445 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 512 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
446 } | 513 } |
447 p++; | 514 p++; |
448 continue; | 515 continue; |
452 pid = GetPid(&buf[i + 2]); | 519 pid = GetPid(&buf[i + 2]); |
453 *(pmt_pids+pid) = 1; | 520 *(pmt_pids+pid) = 1; |
454 *(pids+pid) = 1; | 521 *(pids+pid) = 1; |
455 pos[pid] = i; | 522 pos[pid] = i; |
456 sid_found = TRUE; | 523 sid_found = TRUE; |
524 sp->pmt_version[sp->pmt_retain].pid = pid; | |
457 sp->pmt_retain += 1; | 525 sp->pmt_retain += 1; |
458 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 526 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
459 break; | 527 break; |
460 } | 528 } |
461 | 529 |
470 pid = GetPid(&buf[i + 2]); | 538 pid = GetPid(&buf[i + 2]); |
471 *(pmt_pids+pid) = 1; | 539 *(pmt_pids+pid) = 1; |
472 *(pids+pid) = 1; | 540 *(pids+pid) = 1; |
473 pos[pid] = i; | 541 pos[pid] = i; |
474 sid_found = TRUE; | 542 sid_found = TRUE; |
543 sp->pmt_version[sp->pmt_retain].pid = pid; | |
475 sp->pmt_retain += 1; | 544 sp->pmt_retain += 1; |
476 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); | 545 sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); |
477 } | 546 } |
478 } | 547 } |
479 | 548 |
486 | 555 |
487 #if 0 | 556 #if 0 |
488 /* print PMTs */ | 557 /* print PMTs */ |
489 fprintf(stderr, "Available PMT = "); | 558 fprintf(stderr, "Available PMT = "); |
490 for(k=0; k < sp->num_pmts; k++) | 559 for(k=0; k < sp->num_pmts; k++) |
491 fprintf(stderr, "%d ", sp->avail_pmts[k]); | 560 fprintf(stderr, "%d ", sp->avail_pmts[k].pid); |
492 fprintf(stderr, "\n"); | 561 fprintf(stderr, "\n"); |
493 #endif | 562 #endif |
494 | 563 |
495 // PAT 再構築 | 564 // PAT 再構築 |
496 result = RecreatePat(sp, buf, pos); | 565 result = RecreatePat(sp, buf, pos); |
512 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos) | 581 static int RecreatePat(splitter *sp, unsigned char *buf, int *pos) |
513 #if 0 | 582 #if 0 |
514 unsigned char* buf, // [in] 読み込んだバッファ | 583 unsigned char* buf, // [in] 読み込んだバッファ |
515 unsigned char** pat, // [out] PAT 情報(再構築後) | 584 unsigned char** pat, // [out] PAT 情報(再構築後) |
516 unsigned char* pids, // [out] 出力対象 PID 情報 | 585 unsigned char* pids, // [out] 出力対象 PID 情報 |
517 int *pos) // [in] 取得対象 PMT のバッファ中の位置 | 586 int *pos // [in] 取得対象 PMT のバッファ中の位置 |
518 #endif | 587 #endif |
519 { | 588 { |
520 unsigned char y[LENGTH_CRC_DATA]; | 589 unsigned char y[LENGTH_CRC_DATA]; |
521 int crc; | 590 int crc; |
522 int i; | 591 int i; |
578 /** | 647 /** |
579 * PMT 解析処理 | 648 * PMT 解析処理 |
580 * | 649 * |
581 * PMT を解析し、保存対象の PID を特定する | 650 * PMT を解析し、保存対象の PID を特定する |
582 */ | 651 */ |
583 static int AnalyzePmt(splitter *sp, unsigned char *buf) | 652 static int AnalyzePmt(splitter *sp, unsigned char *buf, unsigned char mark) |
584 #if 0 | 653 #if 0 |
585 unsigned char* buf, // [in] 読み込んだバッファ | 654 unsigned char* buf, // [in] 読み込んだバッファ |
586 unsigned char* pids) // [out] 出力対象 PID 情報 | 655 unsigned char* pids // [out] 出力対象 PID 情報 |
587 #endif | 656 #endif |
588 { | 657 { |
589 unsigned char Nall; | 658 unsigned char Nall; |
590 unsigned char N; | 659 unsigned char N; |
591 int pcr; | 660 int pcr; |
592 int epid; | 661 int epid; |
662 int pid; | |
593 int retry_count = 0; | 663 int retry_count = 0; |
594 | 664 int count; |
595 Nall = ((buf[6] & 0x0F) << 4) + buf[7]; | 665 int payload_offset; // offset to payload |
596 if(Nall > LENGTH_PACKET) | 666 |
597 Nall = LENGTH_PACKET - 8; /* xxx workaround --yaz */ | 667 pid = GetPid(&buf[1]); |
598 | 668 if (buf[1] & 0x40) { // PES開始インジケータ |
599 // PCR | 669 sp->section_remain[pid] = ((buf[6] & 0x0F) << 8) + buf[7] + 3; // セクションサイズ取得(ヘッダ込) |
600 pcr = GetPid(&buf[13]); | 670 payload_offset = 5; |
601 sp->pids[pcr] = 1; | 671 |
602 | 672 for (count = 0; sp->pmt_retain > count; count++) { |
603 N = ((buf[15] & 0x0F) << 4) + buf[16] + 16 + 1; | 673 if (sp->pmt_version[count].pid == pid) { |
604 | 674 sp->pmt_version[count].version = buf[10] & 0x3e; |
605 // ECM | 675 } |
606 int p = 17; | 676 } |
607 while(p < N) { | 677 // PCR, 番組情報が先頭からはみ出ることはないだろう |
608 uint32_t ca_pid; | 678 |
609 uint32_t tag; | 679 // PCR |
610 uint32_t len; | 680 pcr = GetPid(&buf[payload_offset + 8]); |
611 | 681 sp->pids[pcr] = mark; |
612 tag = buf[p]; | 682 |
613 len = buf[p+1]; | 683 // ECM |
614 p += 2; | 684 N = ((buf[payload_offset + 10] & 0x0F) << 8) + buf[payload_offset + 11] + payload_offset + 12; // ES情報開始点 |
615 | 685 int p = payload_offset + 12; |
616 if(tag == 0x09 && len >= 4 && p+len <= N) { | 686 |
617 ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; | 687 while(p < N) { |
618 sp->pids[ca_pid] = 1; | 688 uint32_t ca_pid; |
619 } | 689 uint32_t tag; |
620 p += len; | 690 uint32_t len; |
621 } | 691 |
692 tag = buf[p]; | |
693 len = buf[p+1]; | |
694 p += 2; | |
695 | |
696 if(tag == 0x09 && len >= 4 && p+len <= N) { | |
697 ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; | |
698 sp->pids[ca_pid] = mark; | |
699 } | |
700 p += len; | |
701 } | |
702 } | |
703 else { | |
704 if (sp->section_remain[pid] == 0) return TSS_ERROR; // セクション先頭が飛んでいる | |
705 if ((buf[3] & 0x0F) != ((sp->packet_seq[pid] + 1) & 0x0F)) return TSS_ERROR; // パケットカウンタが飛んだ | |
706 payload_offset = 4; | |
707 N = payload_offset; | |
708 } | |
709 sp->packet_seq[pid] = buf[3] & 0x0F; // 巡回カウンタ | |
710 | |
711 Nall = sp->section_remain[pid]; | |
712 if(Nall > LENGTH_PACKET - payload_offset) | |
713 Nall = LENGTH_PACKET - payload_offset; | |
622 | 714 |
623 // ES PID | 715 // ES PID |
624 while (N < Nall + 8 - 4) | 716 while (N <= Nall + payload_offset - 5) |
625 { | 717 { |
626 // ストリーム種別が 0x0D(type D)は出力対象外 | 718 // ストリーム種別が 0x0D(type D)は出力対象外 |
627 if (0x0D != buf[N]) | 719 if (0x0D != buf[N]) |
628 { | 720 { |
629 epid = GetPid(&buf[N + 1]); | 721 epid = GetPid(&buf[N + 1]); |
630 | 722 |
631 sp->pids[epid] = 1; | 723 sp->pids[epid] = mark; |
632 } | 724 } |
633 N += 4 + (((buf[N + 3]) & 0x0F) << 4) + buf[N + 4] + 1; | 725 N += 4 + (((buf[N + 3]) & 0x0F) << 8) + buf[N + 4] + 1; |
634 retry_count++; | 726 retry_count++; |
635 if(retry_count > Nall) { | 727 if(retry_count > Nall) { |
636 return TSS_ERROR; | 728 return TSS_ERROR; |
637 } | 729 } |
638 } | 730 } |
639 | 731 sp->section_remain[pid] -= Nall; |
640 return TSS_SUCCESS; | 732 |
733 if (sp->section_remain[pid] > 0) | |
734 return SECTION_CONTINUE; | |
735 else | |
736 return TSS_SUCCESS; | |
641 } | 737 } |
642 | 738 |
643 /** | 739 /** |
644 * CRC 計算 | 740 * CRC 計算 |
645 */ | 741 */ |