1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
|
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <event.h>
#include <assert.h>
#include "getstream.h"
#include "stream.h"
#include "crc32.h"
#include "csa.h"
static char *pidstr[]={ "None", "PMT", "PCR", "Video", "Audio", "Private", "User", "Other", NULL };
/*
* TS Header
*
* Name Bits
*
* sync_byte 8 (0x47)
* transport_error_indicator 1
* payload_unit_start_indicator 1
* transport_priority 1
* PID 13
* transport_scrambling_control 2
* adaption_field_control 2
* continuity_counter 4
*
* if (adaption_field_control == '10' ||
* adaption_field_control == '11') {
*
* adaption_field();
* }
*
*/
/*
* DMX_PES_VIDEO
* DMX_PES_AUDIO
* DMX_PES_TELETEXT
* DMX_PES_OTHER
*
*/
int demux_set_pes_filter(int fd, int pid, int pestype) {
struct dmx_pes_filter_params pesFilterParams;
memset(&pesFilterParams, 0, sizeof(struct dmx_pes_filter_params));
logwrite(LOG_INFO,"demux: Setting filter for pid %d pestype %d", pid, pestype);
pesFilterParams.pid = pid;
pesFilterParams.input = DMX_IN_FRONTEND;
pesFilterParams.output = DMX_OUT_TS_TAP;
pesFilterParams.pes_type = pestype;
pesFilterParams.flags = DMX_IMMEDIATE_START;
if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
logwrite(LOG_ERROR,"demux: ioctl DMX_SET_PES_FILTER failed for pid %u pestype %d ",pid, pestype);
return 0;
}
return 1;
}
static inline char *dvrname(int adapter) {
static char dvrname[128];
sprintf(dvrname, "/dev/dvb/adapter%d/dvr0", adapter);
return dvrname;
}
static inline char *dmxname(int adapter) {
static char dmxname[128];
sprintf(dmxname, "/dev/dvb/adapter%d/demux0", adapter);
return dmxname;
}
void dmx_leave_pid(struct adapter_s *adapter, int pid) {
if (adapter->dmxfd[pid] >= 0)
close(adapter->dmxfd[pid]);
adapter->dmxfd[pid]=-1;
return;
}
int dmx_join_pid(struct adapter_s *adapter, int pid) {
if (adapter->budgetmode)
return 1;
adapter->dmxfd[pid]=open(dmxname(adapter->no), O_RDWR);
if (adapter->dmxfd[pid] < 0)
return 0;
return demux_set_pes_filter(adapter->dmxfd[pid], pid, DMX_PES_OTHER);
}
/*
* Apply section filter to opened demux interface.
*
*/
int demux_set_sct_filter(int fd, int pid,
struct dmx_filter *df, int flags, int timeout) {
struct dmx_sct_filter_params sctFilterParams;
memset(&sctFilterParams, 0, sizeof(struct dmx_sct_filter_params));
sctFilterParams.pid=pid;
sctFilterParams.timeout=timeout;
sctFilterParams.flags=flags;
memcpy(&sctFilterParams.filter, df, sizeof(struct dmx_filter));
if (ioctl(fd, DMX_SET_FILTER, &sctFilterParams) < 0) {
logwrite(LOG_ERROR, "demux: ioctl DMX_SET_PES_FILTER failed for pid %u",pid);
exit(-1);
}
return 0;
}
#define TS_SYNC_OFF 0
#define TS_SYNC 0x47
#define TS_PID_OFF1 1
#define TS_PID_OFF2 2
#define TS_PUSI_OFF 1
#define TS_PUSI_MASK 0x40
#define TS_AFC_OFF 3
#define TS_AFC_MASK 0x30
#define TS_AFC_SHIFT 4
#define TS_HEAD_MIN 4
#define TS_AFC_LEN 4
#define TS_CC_OFF 3
#define TS_CC_MASK 0xf
#define TS_AF_OFF 4
#define TS_PAYLOAD_OFF 4
/*
* PMT - Program Map Table
*
* Name No of Bits Offset
* table_id 8 0
* section_syntax_indicator 1 1
* '0' 1 1
* reserved 2 1
* section_length 12 1/2
* programm_number 16 3/4
* reserved 2 5
* version_number 5 5
* current_next_indicator 1 5
* section_number 8 6
* last_section_number 8 7
* reserved 3 8
* PCR_PID 13 8/9
* reserved 4 10
* programm_info_length 12 10/11
* 1 ... N (program_info_length)
* descriptor()
*
* 1 ... N1
* stream_type 8 0
* reserved 3 1
* elementary_PID 13 1/2
* reserved 4 3
* ES_info_length 12 3/4
* 1 ... N2
* descriptor()
*
* CRC32 32
*/
#define PMT_TABLE_OFF 0
#define PMT_TABLE_ID 0x02
#define PMT_SECLEN_OFF1 1
#define PMT_SECLEN_OFF2 2
#define PMT_SECLEN_MASK 0x0fff
#define PMT_SECNO_OFF 6
#define PMT_LASTSECNO_OFF 7
#define PMT_PNR_OFF1 3
#define PMT_PNR_OFF2 4
#define PMT_PILEN_OFF1 10
#define PMT_PILEN_OFF2 11
#define PMT_PILEN_MASK 0x03ff
#define PMT_PI_OFF 12
#define PMT_PCR_OFF1 8
#define PMT_PCR_MASK1 0x1f
#define PMT_PCR_OFF2 9
#define PMT_PCR_MASK2 0xff
#define PMT_ST_STYPE_OFF 0
#define PMT_ST_PID_OFF1 1
#define PMT_ST_PID_OFF2 2
#define PMT_ST_ESLEN_OFF1 3
#define PMT_ST_ESLEN_OFF2 4
#define PMT_ST_ESLEN_MASK 0x0fff
#define PMT_ST_ES_OFF 5
#define PMT_PID_MASK 0x1fff
#define PMT_D_TAG_OFF 0
#define PMT_D_LEN_OFF 1
#define PMT_SECTION_OFF 5
#define PMT_LAST_SECTION_OFF 5
#define PMT_CRC32_LEN 4
#define PMT_MIN_LEN (PMT_PI_OFF+PMT_CRC32_LEN)
static inline unsigned int ts_has_payload(uint8_t *tsp) {
int afc;
afc=(tsp[TS_AFC_OFF] & TS_AFC_MASK) >> TS_AFC_SHIFT;
return(afc & 0x1);
}
static inline unsigned int ts_afc(uint8_t *tsp) {
return ((tsp[TS_AFC_OFF] & TS_AFC_MASK) >> TS_AFC_SHIFT);
}
static inline unsigned int ts_has_af(uint8_t *tsp) {
return (ts_afc(tsp) & 0x2);
}
static inline unsigned int ts_af_len(uint8_t *tsp) {
return (ts_has_af(tsp) ? tsp[TS_AFC_LEN] : 0);
}
static inline unsigned int ts_payload_start(uint8_t *tsp) {
return ts_af_len(tsp)+TS_HEAD_MIN;
}
static inline unsigned int ts_pusi(uint8_t *tsp) {
return tsp[TS_PUSI_OFF] & TS_PUSI_MASK;
}
static inline unsigned int ts_pid(uint8_t *tsp) {
return (tsp[TS_PID_OFF1]<<8|tsp[TS_PID_OFF2])&PMT_PID_MASK;
}
static inline unsigned int ts_tei(uint8_t *tsp) {
return (tsp[TS_PID_OFF1] & 0x80);
}
static inline unsigned int ts_cc(uint8_t *tsp) {
return (tsp[TS_CC_OFF] & TS_CC_MASK);
}
#define PSI_SECLEN_ADD 3 /* Size starts after SECLEN */
#define PSI_SECLEN_OFF 1
#define PSI_SECLEN_MASK 0xfff
#define PSI_SECNO_OFF 6
#define PSI_LASTSECNO_OFF 7
static inline int psi_len(uint8_t *psi) {
int l=((psi[PSI_SECLEN_OFF]<<8|psi[PSI_SECLEN_OFF+1])&PSI_SECLEN_MASK);
if (l<=4 || l>PSI_MAX_PKT_SIZE) {
l=0;
logwrite(LOG_XTREME, "demux: psi_seclen got too large packet size");
dump_hex(LOG_XTREME, "demux:", psi, 256);
} else {
l+=PSI_SECLEN_ADD;
}
return l;
}
static inline unsigned int psi_secno(uint8_t *psi) {
return psi[PSI_SECNO_OFF];
}
static inline unsigned int psi_lastsecno(uint8_t *psi) {
return psi[PSI_LASTSECNO_OFF];
}
/* Reassemble a generic PSI (Program Specific Information) e.h. PMT PAT CA packet */
static int reassemble_psi(uint8_t *tsp, struct psipkt_s *psi) {
int pid; /* PID for debugging */
int ps; /* TS Packet Payload Start offset */
int psis; /* PSI packet start offset */
int psitpl; /* PSI this packet length */
int ptr; /* TS Packet Payload Pointer (PUSI==1) */
uint8_t *psip; /* PSI Part pointer */
int psilen; /* Total PSI length */
logwrite(LOG_XTREME, "demux: Reassemble PSI Packet:");
dump_hex(LOG_XTREME, "demux:", tsp, TS_PACKET_SIZE);
/*
* Check for Transport Error Indicator - We ignore packets
* with uncorrectable bit errors in it
*/
if (ts_tei(tsp))
return 0;
/*
* If the packet is Adaption Field only - ignore it
*/
if (!ts_has_payload(tsp))
return 0;
pid=ts_pid(tsp);
ps=ts_payload_start(tsp);
/* If we are starting with section */
if (ts_pusi(tsp)) {
/* Payload Unit Start Indicator says pointer is following */
ptr=tsp[ps];
/* The PSI Packet starts at TS packet payload + pointer */
psis=ps+ptr+1;
/* In case ptr is larger than packet */
if(psis > TS_PACKET_SIZE) {
logwrite(LOG_XTREME, "demux: PMT with broken ptr in section overflowing transport stream packet size");
return 0;
}
psip=&tsp[psis];
psilen=psi_len(psip);
/* PSI this packet length */
psitpl=MIN(psilen, TS_PACKET_SIZE-psis);
logwrite(LOG_XTREME, "demux: PSI reassemble initial part found, total %d this %d on pid %d",
psilen, psitpl, pid);
/* Copy section start to channel buffer */
memcpy(&psi->pkt, psip, psitpl);
psi->valid=psitpl;
psi->length=psilen;
psi->pid=pid;
} else {
/*
* FIXME - We should do some error checking. The second part should be
* on the same pid. The Continuity Counter should only increment by 1 etc.
* ISO 13818-1 is a little unspecific on how secondary parts can be validated
* and should be formatted or inserted into the stream. It might be that
* i am simply unable to find it in the 205 Pages document.
*
*/
psip=&tsp[ps];
psitpl=MIN(TS_PACKET_SIZE-TS_HEAD_MIN, psi->length-psi->valid);
logwrite(LOG_XTREME, "demux: PSI reassemble secondary part length %d found for pid %d",
psitpl, pid);
memcpy(&psi->pkt[psi->valid], psip, psitpl);
psi->valid+=psitpl;
}
if (psi->valid < psi->length)
return 0;
return 1;
}
static void pmt_join_pid(struct channel_s *channel, int pid, int pidtype) {
/* Do we already receive this pid ? */
if (channel->pidtable[pid].type == PID_NONE) {
if (!channel->adapter->pidtable[pid]) {
if (!dmx_join_pid(channel->adapter, pid))
return;
}
channel->adapter->pidtable[pid]=
g_list_append(channel->adapter->pidtable[pid], channel);
channel->pidtable[pid].type=pidtype;
channel->pidcount[pidtype]++;
logwrite(LOG_INFO, "demux: Setting PID %4d type to %s(%02x) for PNR %04x (%s)",
pid, pidstr[pidtype], pidtype, channel->id, channel->name);
}
channel->pidtable[pid].last=time(NULL);
}
static void pmt_parse(struct channel_s *channel, struct psipkt_s *psi) {
int espid, eslen, pilen,
pnr, sto, ste, pmtlen, pcr;
uint8_t *pmt, *psie;
uint32_t ccrc, pcrc;
logwrite(LOG_XTREME, "demux: parse_pmt dumping PMT");
dump_hex(LOG_XTREME, "demux:", psi->pkt, psi->length);
/* Length of PMT */
pmtlen=psi->length;
if (pmtlen < PMT_MIN_LEN) {
logwrite(LOG_DEBUG, "demux: PMT on pid %d received with broken length %d", psi->pid, pmtlen);
return;
}
/* Check CRC of PMT */
psie=&psi->pkt[psi->length-4];
pcrc=psie[0]<<24|psie[1]<<16|psie[2]<<8|psie[3];
ccrc=crc32_be(0xffffffff, psi->pkt, psi->length-4);
if (pcrc != ccrc) {
logwrite(LOG_DEBUG, "demux: Received PMT on pid %d with wrong crc32", psi->pid);
return;
}
/* ISO/IEC 1-13818 Page 88 says section_number and last_section_number
shall be zero - this seems to be a common issue so we warn only */
if (psi_secno(psi->pkt) != 0x0 || psi_lastsecno != 0x0) {
logwrite(LOG_XTREME, "demux: PMT on pid %d with non zero (last_)section_number received", psi->pid);
}
pmt=psi->pkt;
/* Get program number */
pnr=pmt[PMT_PNR_OFF1] << 8 | pmt[PMT_PNR_OFF2];
/* Get Program Clock Reference PID for this channel */
pcr=(pmt[PMT_PCR_OFF1]&PMT_PCR_MASK1) << 8 | pmt[PMT_PCR_OFF2];
if (pcr != MAX_PID)
pmt_join_pid(channel, pcr, PID_PCR);
/* Get program descriptor length */
pilen=(pmt[PMT_PILEN_OFF1] << 8 | pmt[PMT_PILEN_OFF2]) & PMT_PILEN_MASK;
if (pnr != channel->id) {
logwrite(LOG_DEBUG, "demux: Received PMT on pid %d wrong pnr - is %d should be %d",
psi->pid, pnr, channel->id);
return;
}
/* Start of Stream Table is header + programm_info descriptors */
sto=PMT_PI_OFF+pilen;
/* End of Stream Table */
ste=pmtlen-PMT_CRC32_LEN;
while(sto < ste) {
int streamtype=0;
uint8_t pmtstreamtype=pmt[sto];
espid=(pmt[sto+PMT_ST_PID_OFF1]<<8 | pmt[sto+PMT_ST_PID_OFF2]) & PMT_PID_MASK;
eslen=(pmt[sto+PMT_ST_ESLEN_OFF1]<<8 | pmt[sto+PMT_ST_ESLEN_OFF2]) & PMT_ST_ESLEN_MASK;
switch (pmtstreamtype) {
case 1: /* ISO/IEC 11172 Video */
case 2: /* ITU-T Rec. H.262 */
/* ISO/IEC 13818-2 Video */
/* ISO/IEC 11172-2 */
case 27: /* ITU-T Rec. H.264 */
/* ISO/IEC 14496-10 Video */
streamtype=PID_VIDEO;
break;
case 3: /* ISO/IEC 11172 Audio */
case 4: /* ISO/IEC 13818-3 Audio */
streamtype=PID_AUDIO;
break;
case 5: /* ISO/IEC 13818-1 Page 160 - Private Sections */
case 6: /* ITU-T Rec. H.222.0 ISO/IEC 13818-1 PES - Private Data */
/* Stephen Gardner sent dvbsnoop output showing AC3 Audio
* in here encapsulated in the private data. As we dont
* treat different pid types differently we don't care for
* now */
streamtype=PID_PRIVATE;
break;
case 7: /* ISO/IEC 13522 MHEG */
case 8: /* ITU-T Rec. H.220.0 / ISO/IEC 13818-1 Annex A DSM CC */
case 9: /* ITU-T Rec. H.220.1 */
case 10: /* ISO/IEC 13818-6 Type A */
case 11: /* ISO/IEC 13818-6 Type B */
case 12: /* ISO/IEC 13818-6 Type C */
case 13: /* ISO/IEC 13818-6 Type D */
case 14: /* ISO/IEC 13818-1 auxiliary */
streamtype=PID_OTHER;
break;
default:
if (pmtstreamtype & 0x80) {
streamtype=PID_USER;
break;
}
/* Make it possible to dump unknown PID types */
logwrite(LOG_DEBUG, "demux: PMT PID %d on channel %s has unknown type %d",
espid, channel->name, pmtstreamtype);
}
if (streamtype)
pmt_join_pid(channel, espid, streamtype);
/* Add Stream table descriptor entry size */
sto+=PMT_ST_ES_OFF+eslen;
}
}
static void pmt_process(struct channel_s *channel, uint8_t *tsp) {
if (!reassemble_psi(tsp, &channel->pmt))
return;
pmt_parse(channel, &channel->pmt);
}
static void dvr_read(int fd, short event, void *arg) {
int len, i, cc;
struct adapter_s *adapter=arg;
uint8_t *db=adapter->dvrbuf;
int pid;
GList *cl;
do {
len=read(fd, db, DVR_BUFFER_SIZE);
/* EOF aka no more TS Packets ? */
if (len == 0)
break;
/* Read returned error ? */
if (len < 0) {
if (errno != EAGAIN)
logwrite(LOG_ERROR, "demux: read in dvr_read returned with errno %d", errno);
break;
}
/* We should only get n*TS_PACKET_SIZE */
if (len % TS_PACKET_SIZE != 0) {
logwrite(LOG_ERROR, "demux: Oops - unaligned read of %d bytes dropping buffer", len);
continue;
}
for(i=0;i<len;i+=TS_PACKET_SIZE) {
/* TS (Transport Stream) packets start with 0x47 */
if (db[i] != 0x47) {
logwrite(LOG_XTREME, "demux: Non TS Stream packet (!0x47) received on dvr0");
dump_hex(LOG_XTREME, "demux:", &db[i], TS_PACKET_SIZE);
continue;
}
pid=ts_pid(&db[i]);
/* continuity counter check */
cc=ts_cc(&db[i]);
/* We ognore 8191 as i see loads of cc=0 -> cc=0 on that "virtual" pid */
if (adapter->pidcc[pid]) {
unsigned int occ=adapter->pidcc[pid]&0xf;
unsigned int afc=ts_afc(&db[i]);
/* ISO/IEC 13818 Page 51
*
* The continuity_counter shall not be incremented when the
* adaptation_field_control of the packet equals '00' or '10'.
*
*/
if (afc == 0x2 || afc == 0) {
if (cc != occ) {
logwrite(LOG_DEBUG, "demux: PID %d CC increased from %d to %d although AFC %d",
pid, occ, cc, afc);
}
} else {
/* Duplicate packet or increase */
if (cc != occ && cc != ((occ+1)&0xf)) {
logwrite(LOG_DEBUG, "demux: PID %d CC increased from %d to %d",
pid, occ, cc);
}
}
}
adapter->pidcc[pid]=cc|0x80;
/* Does somebody want this pid ? */
if (!adapter->pidtable[pid])
continue;
for(cl=g_list_first(adapter->pidtable[pid]);cl!=NULL;cl=g_list_next(cl)) {
struct channel_s *c=cl->data;
switch(c->pidtable[pid].type) {
case(PID_PMT):
pmt_process(c, &db[i]);
stream_send(c, &db[i]);
break;
default:
/*
* FIXME csa_Encrypt modifies the transport stream packet buffer
* thus we cant send it to multiple stream outputs. Need to copy
* it first ...
*/
if (c->csat)
csa_Encrypt(c->csat, &db[i], c->csalength, 1);
stream_send(c, &db[i]);
break;
}
}
}
} while (len > 0);
}
/*
* PAT Programm Association Table
*
* The PAT is multiplexed into the TS (Transport Stream)
* at PID 0x0. It contains the table of all PMT (Program Map Table)
* pids within the TS.
*
* Name Bits Offset
*
* table_id 8 0
* section_syntax_indicator 1 1
* pad (0) 1 1
* reserved 2 1
* section_length 12 1/2
* transport_stream_id 16 3/4
* reserved 2 5
* version_number 5 5
* current_next_indicator 1 5
* section_number 8 6
* last_section_number 8 7
*
* 1..N
* program_number 16
* reserved 3
* pid 13
* (if pnum==0 network_pid else program_map_pid)
*
* crc32 32
*
*/
#define PAT_TABLE_ID_OFF 0
#define PAT_TABLE_ID 0x0
#define PAT_LAST_SECTION_OFF 7
#define PAT_SECTION_OFF 6
#define PAT_SLEN_OFF1 1
#define PAT_SLEN_OFF2 2
#define PAT_SLEN_MASK 0x0fff
#define PAT_TID_OFF1 3
#define PAT_TID_OFF2 4
#define PAT_VER_OFF 5
#define PAT_PNR_OFF1 8 /* First PNR offset byte 1 */
#define PAT_PNR_OFF2 9 /* First PNR offset byte 2 */
#define PAT_PMTPID_OFF1 10 /* First PMTPID offset byte 1 */
#define PAT_PMTPID_OFF2 11 /* First PMTPID offset byte 2 */
#define PAT_PMTPID_MASK 0x1fff
#define PAT_CRC_OFF1 12 /* Offset of CRC32 in case of single program PAT */
#define PAT_CRC_OFF2 13
#define PAT_CRC_OFF3 14
#define PAT_CRC_OFF4 15
#define PAT_MIN_LEN 9
/*
* 0000 47 40 64 18 00 02 b0 83 6d ca f5 00 00 e0 65 f0 G.d.....m.....e.
* aa bc cc de
*
* a - TS_SYNC -> 0x47
* b - transport_error_indicator 0
* payload_unit_start_indicator 1
* transport_priority 0 -> 0x4
* c - PID -> 0x64
* d - transport_scrambling_control 00
* adaption_field_control 01 -> 0x1
* e - continuity_counter -> 0x8
*
*/
static void dmx_send_pat(uint8_t *rpat, struct adapter_s *adapter) {
uint8_t tsbuf[TS_PACKET_SIZE],
*pat;
GList *cl;
unsigned int sid;
__u32 crc;
/* Fill with 0xff */
memset(tsbuf, 0xff, TS_PACKET_SIZE);
cl=g_list_first(adapter->channel);
while(cl) {
struct channel_s *channel=cl->data;
channel->pid0cc=(channel->pid0cc+1)&TS_CC_MASK; /* Increment CC */
sid=channel->id;
/* Build PID 0 TS packet */
tsbuf[TS_SYNC_OFF]=TS_SYNC;
tsbuf[TS_PID_OFF1]=0x0; /* Clear PID */
tsbuf[TS_PID_OFF2]=0x0;
tsbuf[TS_PUSI_OFF]=TS_PUSI_MASK; /* PUSI == 0x40 */
tsbuf[TS_CC_OFF]=(channel->pid0cc&TS_CC_MASK);/* Store CC into TS */
tsbuf[TS_AFC_OFF]|=0x1<<TS_AFC_SHIFT; /* Payload only - no adaption field */
tsbuf[TS_PAYLOAD_OFF]=0x0; /* Clear PSI pointer */
pat=&tsbuf[TS_PAYLOAD_OFF+1];
pat[PAT_TABLE_ID_OFF]=PAT_TABLE_ID;
pat[PAT_SLEN_OFF1]=0x0 | 0x80; /* Set section_syntax_inidicator */
pat[PAT_SLEN_OFF2]=13; /* Single Programm PAT */
pat[PAT_TID_OFF1]=rpat[PAT_TID_OFF1];
pat[PAT_TID_OFF2]=rpat[PAT_TID_OFF2];
pat[PAT_VER_OFF]=rpat[PAT_VER_OFF];
pat[PAT_SECTION_OFF]=0x0;
pat[PAT_LAST_SECTION_OFF]=0x0;
pat[PAT_PNR_OFF1]=(sid >> 8) & 0xff;
pat[PAT_PNR_OFF2]=sid & 0xff;
pat[PAT_PMTPID_OFF1]=(channel->pmtpid >> 8) & 0xff;
pat[PAT_PMTPID_OFF2]=(channel->pmtpid) & 0xff;
pat[PAT_CRC_OFF1]=0x0;
pat[PAT_CRC_OFF2]=0x0;
pat[PAT_CRC_OFF3]=0x0;
pat[PAT_CRC_OFF4]=0x0;
/* CRC over complete pat without CRC */
crc=crc32_be(0xffffffff, pat, PAT_CRC_OFF1);
pat[PAT_CRC_OFF1]=crc >> 24 & 0xff;
pat[PAT_CRC_OFF2]=crc >> 16 & 0xff;
pat[PAT_CRC_OFF3]=crc >> 8 & 0xff;
pat[PAT_CRC_OFF4]=crc & 0xff;
stream_send(channel, tsbuf);
cl=g_list_next(cl);
}
/*
* TS Header
*
* Name Bits
*
* sync_byte 8 (0x47)
* transport_error_indicator 1
* payload_unit_start_indicator 1
* transport_priority 1
* PID 13
* transport_scrambling_control 2
* adaption_field_control 2
* continuity_counter 4
*
* if (adaption_field_control == '10' ||
* adaption_field_control == '11') {
*
* adaption_field();
* }
*
*/
}
/*
* Parse PAT (Programm Association Table) and set pid types
* in the pid demux table.
*/
static void dmx_parse_pat(uint8_t *buf, int len,
struct adapter_s *adapter) {
int ppid, pnr, patlen, patnoppid, i;
time_t now;
GList *cl;
now=time(NULL);
if (len < PAT_MIN_LEN)
return;
/*
* FIXME - We shoudl check for current_next bit
* to make shure we only parse and process
* current PATs
*
*/
/* Calculate this PATs length */
patlen=(buf[PAT_SLEN_OFF1] << 8 | buf[PAT_SLEN_OFF2])
& PAT_SLEN_MASK;
/* Calculate the number PMTpids in this PAT */
patnoppid=(patlen-9) / 4;
/* Loop on ppids */
for(i=0;i<patnoppid;i++) {
/* Get Programm Number */
pnr=buf[PAT_PNR_OFF1+i*4] << 8 | buf[PAT_PNR_OFF2+i*4];
ppid=(buf[PAT_PMTPID_OFF1+i*4] << 8 | buf[PAT_PMTPID_OFF2+i*4])
& PAT_PMTPID_MASK;
/*
* Try to check whether we want this program number
* We do a linear search here as there may only be up
* to 30-40 Programs per transponder and PATs are "rare"
*
*/
cl=g_list_first(adapter->channel);
while(cl) {
struct channel_s *channel=cl->data;
if (channel->id == pnr) {
/* Append to adapter pidtable */
if (channel->pidtable[ppid].type == PID_NONE) {
/* Join if not already joined */
if (adapter->pidtable[ppid] || dmx_join_pid(adapter, ppid)) {
adapter->pidtable[ppid]=g_list_append(adapter->pidtable[ppid], channel);
/* Update channel pid table */
channel->pidtable[ppid].type=PID_PMT;
/* FIXME Do we need this anywhere ? */
channel->pmtpid=ppid;
channel->pidcount[PID_PMT]++;
logwrite(LOG_INFO, "demux: Setting PID %4d type to PMT for PNR %04x (%s)",
ppid, channel->id, channel->name);
}
}
channel->pidtable[ppid].last=now;
break;
}
cl=g_list_next(cl);
}
}
}
/*
* This will be called for PAT (Programm Association Table)
* receive on PID 0. We should parse the PAT and fill the pid
* demux table with the PMT pids pointing to the PMT decoder.
*
*/
#define MAX_SEC_LEN 8192
static void dmx_read(int fd, short event, void *arg) {
struct adapter_s *adapter=arg;
static uint8_t secbuf[MAX_SEC_LEN];
int len;
len=read(fd, &secbuf, MAX_SEC_LEN);
if (len) {
dmx_parse_pat(secbuf, len, adapter);
dmx_send_pat(secbuf, adapter);
}
}
static int dmx_init(struct adapter_s *adapter) {
static struct event dmxevent;
struct dmx_filter df;
int dmxfd;
/* FIXME Check for open success */
dmxfd=open(dmxname(adapter->no), O_RDWR);
if (dmxfd < 0)
return 0;
event_set(&dmxevent, dmxfd, EV_READ|EV_PERSIST, dmx_read, adapter);
event_add(&dmxevent, NULL);
memset(&df, 0, sizeof(struct dmx_filter));
/* Prepare filter - give us section 0x0 aka PAT */
df.filter[0]=0x0;
df.mask[0]=0xff;
/* Set filter and immediatly start receiving packets */
demux_set_sct_filter(dmxfd, 0, &df, DMX_IMMEDIATE_START|DMX_CHECK_CRC, 0);
return 1;
}
static int dvr_init(struct adapter_s *adapter) {
static struct event pesevent;
int dmxfd, dvrfd;
/* FIXME - check for open success */
dmxfd=open(dmxname(adapter->no), O_RDWR);
dvrfd=open(dvrname(adapter->no), O_RDONLY|O_NONBLOCK);
if (dmxfd < 0 || dvrfd < 0) {
return 0;
}
event_set(&pesevent, dvrfd, EV_READ|EV_PERSIST, dvr_read, adapter);
event_add(&pesevent, NULL);
if (adapter->budgetmode) {
/* Budget Mode - Gimme all you have */
if (!demux_set_pes_filter(dmxfd, 0x2000, DMX_PES_OTHER)) {
logwrite(LOG_INFO, "demux: Setting budget filter failed - switching off budget mode");
adapter->budgetmode=0;
}
}
return 1;
}
static void pidexpire_init(struct adapter_s *adapter);
/*
* If the PAT or PMT didnt refresh a PID for 30 seconds
* we remove it from the pid table
*
*/
#define PID_TIMEOUT 60
static void pidexpire(int fd, short event, void *arg) {
time_t now=time(NULL);
int pid;
struct adapter_s *adapter=arg;
GList **pidtable=adapter->pidtable;
GList *cl, *clt;
/* Loop on pids on adapter */
for(pid=0;pid<MAX_PID;pid++) {
/* If noone on this adapter want this pid - continue */
if (!pidtable[pid])
continue;
/* Loop on channels on this pid whether they wanted this pid */
for(cl=g_list_first(pidtable[pid]);cl;cl=g_list_next(cl)) {
struct channel_s *c=cl->data;
if (c->pidtable[pid].last+PID_TIMEOUT < now) {
logwrite(LOG_INFO, "demux: expiring pid %d at age %lu for channel %s",
pid, now-c->pidtable[pid].last, c->name);
/* Housekeeping in PIDTYPE count table */
c->pidcount[c->pidtable[pid].type]--;
/* Mark as free in channels pid table */
c->pidtable[pid].type=PID_NONE;
c->pidtable[pid].last=0;
/*
* Remove from adapter pidtable channel list
*
* Save pointer - after removing cl from adapter channel list
* we dont want to dereference it anymore. It might be save today
* but probably not tomorrow.
*/
clt=g_list_next(cl);
pidtable[pid]=g_list_remove_link(pidtable[pid], cl);
cl=clt;
if (!pidtable[pid])
dmx_leave_pid(adapter, pid);
}
}
}
/* Reinit timer */
pidexpire_init(adapter);
}
static void pidexpire_init(struct adapter_s *adapter) {
static struct event peevent;
static struct timeval tv;
tv.tv_usec=0;
tv.tv_sec=5;
evtimer_set(&peevent, pidexpire, adapter);
evtimer_add(&peevent, &tv);
}
int demux_init(struct adapter_s *adapter) {
/* demux0 PAT receive */
if (!dmx_init(adapter))
return 0;
/* dvr0 stream reveive in budget mode*/
if (!dvr_init(adapter))
return 0;
pidexpire_init(adapter);
return 1;
}
|