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 */