source: titan/titan/dvb.h @ 34375

Last change on this file since 34375 was 31259, checked in by obi, 9 years ago

revert to gost fix

File size: 31.5 KB
Line 
1#ifndef DVB_H
2#define DVB_H
3
4int dvbwrite(int fd, unsigned char* buf, int count, int tout)
5{
6        struct timeval timeout;
7        int ret = 0, usec = 0, sec = 0, tmpcount = count;
8        unsigned char* buffer = NULL;
9
10        if(fd < 0) return -1;
11
12        if(tout == -1) tout = 5000 * 1000;
13        usec = tout % 1000000;
14        sec = (tout - usec) / 1000000;
15
16        fd_set wfds;
17
18        while (tmpcount > 0)
19        {
20                buffer = buf + (count - tmpcount);
21                ret = write(fd, buffer, tmpcount);
22                if(ret < 0)
23                {
24                        if(errno == EINTR || errno == EAGAIN)
25                        {
26                                FD_ZERO(&wfds);
27                                FD_SET(fd, &wfds);
28                       
29                                timeout.tv_sec = sec;
30                                timeout.tv_usec = usec;
31                       
32                                ret = TEMP_FAILURE_RETRY(select(fd + 1, NULL, &wfds, NULL, &timeout));
33                        }
34                       
35                        if(ret == 0)
36                        {
37                                perr("dvbwrite timed out fd=%d", fd);
38                                return -1;
39                        }
40                        if(ret < 0)
41                        {
42                                perr("can't write fd=%d", fd);
43                                return errno * -1;
44                        }
45                }
46                else
47                        tmpcount -= ret;
48        }
49
50        return count;
51}
52
53//flag 0: eof with timeout
54//flag 1: eof without timeout
55int dvbreadfd(int fd, unsigned char *buf, int pos, int count, int tout, int flag)
56{
57        struct timeval timeout;
58        int ret = 0, usec = 0, sec = 0;
59        fd_set rfds;
60       
61        if(fd < 0) return -1;
62
63        if(tout == -1) tout = 5000 * 1000;
64        usec = tout % 1000000;
65        sec = (tout - usec) / 1000000;
66
67        timeout.tv_sec = sec;
68        timeout.tv_usec = usec;
69        FD_ZERO(&rfds);
70        FD_SET(fd, &rfds);
71
72        ret = TEMP_FAILURE_RETRY(select(fd + 1, &rfds , NULL, NULL, &timeout));
73
74        if(ret == 1)
75        {
76retry:
77                ret = TEMP_FAILURE_RETRY(read(fd, buf + pos, count));
78                if(ret > 0)
79                        return ret;
80                else if(ret == 0)
81                {
82#ifdef SIMULATE
83                        tout = tout - 100000;
84                        usleep(100000);
85#else
86                        tout = tout - 1000;
87                        usleep(1000);
88#endif
89                        if(flag == 0 && tout > 0) goto retry;
90                        debug(250, "dvb read timeout fd=%d", fd);
91                }
92                else if(ret < 0)
93                {
94                        if((errno == EAGAIN || errno == EOVERFLOW) && tout > 0)
95                        {
96                                if(errno != EAGAIN) perr("dvb read data fd=%d -> retry", fd);
97#ifdef SIMULATE
98                                tout = tout - 100000;
99                                usleep(100000);
100#else
101                                tout = tout - 1000;
102                                usleep(1000);
103#endif
104                                goto retry;
105                        }
106                        perr("dvb read data fd=%d", fd);
107                }
108        }
109        else if(ret == 0)
110        {
111                debug(250, "dvb select timeout fd=%d, tout=%d", fd, tout);
112        }
113        else
114        {
115                perr("dvb select fd=%d", fd);
116        }
117
118        return -1;
119}
120
121int dvbread(struct dvbdev* node, unsigned char *buf, int pos, int count, int tout)
122{
123        if(node == NULL) return -2;
124        return dvbreadfd(node->fd, buf, pos, count, tout, 0);
125}
126
127int dvbfindpmtpid(int fd, int16_t *pmtpid, int *serviceid, int tssize)
128{
129        off_t pos = 0;
130        int left = 5 * 1024 * 1024;
131
132        if(fd < 0) return 1;
133
134        while(left >= tssize)
135        {
136                unsigned char packet[tssize];
137
138                lseek64(fd, pos, SEEK_SET);
139                int ret = dvbreadfd(fd, packet, 0, tssize, -1, 0);
140                if(ret != tssize)
141                {
142                        err("read error");
143                        break;
144                }
145                left -= tssize;
146                pos += tssize;
147
148                if(packet[0] != 0x47)
149                {
150                        int i = 0;
151                        while(i < tssize)
152                        {
153                                if(packet[i] == 0x47) break;
154                                --pos;
155                                ++i;
156                        }
157                        continue;
158                }
159
160                int pid = ((packet[1] << 8) | packet[2]) & 0x1FFF;
161
162                int pusi = !!(packet[1] & 0x40);
163                if(!pusi) continue;
164               
165                // ok, now we have a PES header or section header
166                unsigned char *sec;
167               
168                // check for adaption field
169                if(packet[3] & 0x20)
170                {
171                        if(packet[4] >= 183) continue;
172                        sec = packet + packet[4] + 4 + 1;
173                }
174                else
175                        sec = packet + 4;
176               
177                // table pointer, assumed to be 0
178                if(sec[0]) continue;
179
180                // program map section
181                if(sec[1] == 0x02)
182                {
183                        *pmtpid = pid;
184                        *serviceid = (sec[4] << 8) | sec[5];
185                        lseek64(fd, 0, SEEK_SET);
186                        return 0;
187                }
188        }
189       
190        lseek64(fd, 0, SEEK_SET);
191        return 1;
192}
193
194int dvbgetpmtpid(unsigned char *buf, int serviceid)
195{
196        if(buf == NULL) return 1;
197
198        int i=0;
199        int length = (buf[1] & 0x0F) << 8 | ((buf[2] + 3) & 0xff);
200        if(length > MINMALLOC) length = MINMALLOC;
201
202        debug(200, "PAT length: %d", length);
203        for (i = 8; i < length; i += 4)
204        {
205                if((((buf[i] & 0xff) << 8) | (buf[i + 1] & 0xff)) > 0)
206                {
207                        if (serviceid == (((buf[i] & 0xff) << 8) | (buf[i + 1] & 0xff)))
208                        {
209                                int pmtpid = (((buf[i + 2] & 0x1f) << 8) | (buf[i + 3] & 0xff));
210                                debug(200, "PMT pid: 0x%X (%d)", pmtpid, pmtpid);
211                                return pmtpid;
212                        }
213                }
214        }
215        return 0;
216}
217
218char* dvbgethbbtvurl(unsigned char* buf)
219{
220        //int seclen = 0;
221        int pos = 0;
222        int pos2 = 0;
223        int commondesclen = 0;
224        int applooplen = 0;
225        int appdesclen = 0;
226        int desclen = 0;
227        char* url = NULL;
228
229        if(buf == NULL) return NULL;
230
231        //seclen = ((buf[1] & 0x0F) << 8) + buf[2];
232        commondesclen = ((buf[8] & 0x0F) << 8) + buf[9];
233        pos = 10 + commondesclen;
234
235        applooplen = ((buf[pos] & 0x0F) << 8) + buf[pos + 1];
236        pos += 2;
237
238        for(; pos < applooplen; pos += appdesclen + 9)
239        {
240                //long orgid = (buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3];
241                //int appid = (buf[pos + 4] << 8) + buf[pos + 5];
242                int appcode = buf[pos + 6];
243                appdesclen = ((buf[pos + 7] & 0x0F) << 8) + buf[pos + 8];
244
245                if(appcode != 1) continue;
246
247                desclen = 0;
248                for(pos2 = pos + 9; pos2 < appdesclen + pos + 9; pos2 += desclen + 2)
249                {
250                        int desctag = buf[pos2];
251                        desclen = buf[pos2 + 1];
252
253                        switch(desctag)
254                        {
255                                case 0x00: //application desc
256                                        break;
257                                case 0x01: //application name desc
258                                        break;
259                                case 0x02: //transport protocol desc
260                                {
261                                        int protocolid = buf[pos2 + 2] +  buf[pos2 + 3];
262                                        switch(protocolid)
263                                        {
264                                                case 1: //object carousel
265                                                        break;
266                                                case 2: //ip
267                                                        break;
268                                                case 3: //interaction
269                                                {
270                                                        free(url); url = NULL;
271                                                        url = malloc(desclen - 4);
272                                                        if(url != NULL)
273                                                        {
274                                                                strncpy(url, (char*)&buf[pos2 + 6], desclen - 5);
275                                                                url[desclen - 5]='\0';
276                                                        }
277                                                        break;
278                                                }
279                                        }
280                                        break;
281                                }
282                                case 0x14: //graphics constraints desc
283                                        break;
284                                case 0x15: //simple application location desc
285                                {
286                                        if(url != NULL)
287                                        {
288                                                char* tmpurl = NULL;
289                                                tmpurl = malloc(desclen + 1);
290                                                strncpy(tmpurl, (char*)&buf[pos2 + 2], desclen);
291                                                tmpurl[desclen]='\0';
292                                                url = ostrcat(url, tmpurl, 1, 1);
293                                        }
294                                        break;
295                                }
296                                case 0x16: //application usage desc
297                                        break;
298                                case 0x17: //simple application boundary desc
299                                        break;
300                        }
301                }
302        }
303
304        return url;
305}
306
307unsigned char* dvbget(struct dvbdev* fenode, int pid, int type, int secnr, int timeout)
308{
309        int length = -1;
310        struct dvbdev* dmxnode = NULL;
311        unsigned char* buf = NULL;
312
313        buf = malloc(MINMALLOC);
314        if(buf == NULL)
315        {
316                err("no memory");
317                return NULL;
318        }
319
320        if(fenode == NULL)
321        {
322                err("no frontend dev");
323                free(buf);
324                return NULL;
325        }
326
327        dmxnode = dmxopen(fenode);
328        if(dmxnode == NULL)
329        {
330                err("open demux dev");
331                free(buf);
332                return NULL;
333        }
334
335        dmxsetsource(dmxnode, fenode->fedmxsource);
336        dmxsetfilter(dmxnode, pid, secnr, type);
337
338        length = dvbread(dmxnode, buf, 0, MINMALLOC, timeout);
339        if(length < 0)
340        {
341                dmxclose(dmxnode, -1);
342                free(buf);
343                err("read");
344                return NULL;
345        }
346
347        dmxclose(dmxnode, -1);
348        return buf;
349}
350
351unsigned char* dvbgetait(struct dvbdev* fenode, int pid, int secnr, int timeout)
352{
353        return dvbget(fenode, pid, 14, secnr, timeout);
354}
355
356unsigned char* dvbgetsdt(struct dvbdev* fenode, int secnr, int timeout)
357{
358        return dvbget(fenode, 0x11, 11, secnr, timeout);
359}
360
361unsigned char* dvbgetpat(struct dvbdev* fenode, int timeout)
362{
363        return dvbget(fenode, 0, 1, 0, timeout);
364}
365
366unsigned char* dvbgetnit(struct dvbdev* fenode, int secnr, int timeout)
367{
368        return dvbget(fenode, 0x10, 4, secnr, timeout);
369}
370
371//flag 0: with pat
372//flag 1: don't use patbuf
373unsigned char* dvbgetpmt(struct dvbdev* fenode, unsigned char* patbuf, int serviceid, int16_t* pmtpid, int* pmtlen, int timeout, int flag)
374{
375        int length = -1, i;
376        struct dvbdev* dmxnode = NULL;
377        unsigned char* buf = NULL;
378
379#ifdef SIMULATE
380        FILE* fd = NULL;
381       
382        buf = malloc(MINMALLOC);
383
384        fd = fopen("simulate/pmt.tmp", "rb");
385        if(fd == NULL)
386        {
387                err("open simulate/pmt.tmp");
388        }
389        else
390                fread(buf, sizeof(unsigned char), MINMALLOC, fd);
391
392        if(fd != NULL) fclose(fd);
393        if(buf != NULL) return buf;
394#endif
395
396        if(flag == 0)
397        {
398                if(patbuf == NULL) return NULL;
399                *pmtpid = dvbgetpmtpid(patbuf, serviceid);
400        }
401
402        if(*pmtpid < 1)
403        {
404                err("pmt pid not found sid=%d, pmtpid=%d", serviceid, *pmtpid);
405                return NULL;
406        }
407
408        buf = malloc(MINMALLOC);
409        if(buf == NULL)
410        {
411                err("no memory");
412                return NULL;
413        }
414
415        if(fenode == NULL)
416        {
417                err("no frontend dev");
418                return NULL;
419        }
420
421        dmxnode = dmxopen(fenode);
422        if(dmxnode == NULL)
423        {
424                err("open demux dev");
425                free(buf);
426                return NULL;
427        }
428        // error
429//      if(checkbox("ATEMIO-NEMESIS") != 1)
430                dmxsetsource(dmxnode, fenode->fedmxsource);
431
432        dmxsetfilter(dmxnode, *pmtpid, 0, 2);
433
434        for (i = 0; i < 64; i++)
435        {
436                if((length = dvbread(dmxnode, buf, 0, MINMALLOC, timeout)) < 0)
437                {
438                        err("read pmt pid=%d", *pmtpid);
439                        break;
440                }
441                if(serviceid == (((buf[3] & 0xff) << 8) + (buf[4] & 0xff)))
442                {
443                        debug(200, "sid: %d = buf", serviceid);
444                        dmxclose(dmxnode, -1);
445                        if(pmtlen != NULL)
446                        {
447                                *pmtlen =((buf[1] & 0xf) << 8) + ((buf[2] + 3) & 0xff);
448                                debug(200, "pmtlen=%d", *pmtlen);
449                                buf = realloc(buf, *pmtlen);
450                        }
451                        return buf;
452                }
453        }
454
455        err("find pmt");
456        dmxclose(dmxnode, -1);
457        free(buf);
458        if(flag == 0) *pmtpid = 0;
459        return NULL;
460}
461
462int dvbgetinfo(unsigned char* pmtbuf, struct channel* chnode)
463{
464        int i, sectionlength, programinfolength, esinfolength, ret = 0;
465        unsigned short pos, descriptortag, descriptorlength;
466        int isac3 = 0, isdts = 0, isaac = 0;
467        int audiocodec = 0, videocodec = 0;
468        int firstaudiopid = -1, firstaudiocodec = -1, audiochange = 1;
469        int streamtype, pid, tsid, onid, pcrpid;
470        unsigned char *tmpbuf = NULL;
471        struct audiotrack* prevaudio = NULL;
472
473        if(pmtbuf == NULL || chnode == NULL)
474        {
475                err("NULL detect");
476                return -1;
477        }
478
479        sectionlength = ((pmtbuf[1] & 0x0F) << 8) + (pmtbuf[2] & 0xff);
480        if(sectionlength > MINMALLOC) sectionlength = MINMALLOC;
481        programinfolength = ((pmtbuf[10] & 0x0F) << 8) | (pmtbuf[11] & 0xff);
482        if(programinfolength > MINMALLOC) programinfolength = MINMALLOC;
483       
484        pcrpid = chnode->pcrpid;
485        chnode->pcrpid = ((pmtbuf[8] & 0x1F) << 8) + pmtbuf[9];
486        debug(200, "add pcrpid %d", chnode->pcrpid);
487        if(chnode->pcrpid != pcrpid) status.writechannel = 1;
488
489        // pmt
490        int programnumber = (pmtbuf[3] << 8) + pmtbuf[4];
491        int versionnumber = (pmtbuf[5] >> 1) & 0x1F;
492        int currentnextindicator = pmtbuf[5] & 0x01;
493        addpmt(chnode, programnumber, versionnumber, currentnextindicator);
494
495        if(programinfolength)
496        {
497                for(i = 12; i < 12 + programinfolength; i += pmtbuf[i + 1] + 2)
498                {
499                        switch (pmtbuf[i])
500                        {
501                                case 0x09:
502                                        chnode->crypt = 1;
503                                        addcadesc(chnode, 0, &pmtbuf[i], NULL);
504                                        break;
505                        }
506                }
507        }
508
509        for(i = 12 + programinfolength; i < sectionlength - 1; i += esinfolength + 5)
510        {
511                tmpbuf = pmtbuf + i;
512                if(tmpbuf > pmtbuf + MINMALLOC) break;
513                streamtype = (tmpbuf[0] & 0xff);
514                pid = ((tmpbuf[1] & 0x1F) << 8) | (tmpbuf[2] & 0xff);
515                esinfolength = ((tmpbuf[3] & 0x0F) << 8) | (tmpbuf[4] & 0xff);
516                isac3 = 0; isdts = 0; isaac = 0, audiocodec = 0, videocodec = 0;
517                char langdesc[4] = "---";
518                int y = 0, descriptorcount = 0;
519
520                addesinfo(chnode, streamtype, pid, NULL);
521
522                for(pos = 5; pos < esinfolength + 5; pos += descriptorlength + 2)
523                {
524                        descriptorcount++;
525                        descriptortag = tmpbuf[pos];
526                        descriptorlength = tmpbuf[pos + 1];
527                        switch (descriptortag)
528                        {
529        case 0x6f: //get aitpid for hbbtv
530                                        if(streamtype == 0x05)
531          {
532            chnode->aitpid = pid;
533            debug(200, "add aitpid %d", pid);
534          }
535          break;
536                                case 0x05:
537                                        if(descriptorlength >= 3)
538                                                if(!ostrncmp((char*)&tmpbuf[pos + 2], "DTS", 3))
539                                                        isdts = 1;
540                                        break;
541                                case 0x81:
542                                        // private descr: dvb namespace
543                                        tsid = tmpbuf[pos + 6] << 8 | tmpbuf[pos + 7];
544                                        onid = (tmpbuf[pos + 8]) << 8 | tmpbuf[pos + 9];
545                                        break;
546                                case 0x09:
547                                        chnode->crypt = 1;
548                                        addcadesc(chnode, pid, &tmpbuf[pos], NULL);
549                                        break;
550                                case 0x0A:
551                                        langdesc[0] = toupper(tmpbuf[pos + 2]);
552                                        langdesc[1] = toupper(tmpbuf[pos + 3]);
553                                        langdesc[2] = toupper(tmpbuf[pos + 4]);
554                                        langdesc[3] = '\0';
555                                        break;
556                                case 0x6A:
557                                        isac3 = 1;
558                                        break;
559                                case 0x7C:
560                                        isaac = 1;
561                                        break;
562                                case 0x7B:
563                                        isdts = 1;
564                                        break;
565                                case 0x56: //teletext
566                                        for (y = 0; y < descriptorlength / 5; y++)
567                                        {
568                                                langdesc[0] = toupper(tmpbuf[pos + 5 * y + 2]);
569                                                langdesc[1] = toupper(tmpbuf[pos + 5 * y + 3]);
570                                                langdesc[2] = toupper(tmpbuf[pos + 5 * y + 4]);
571                                                langdesc[3] = '\0';
572                                                unsigned char txttype = tmpbuf[pos + 5 * y + 5] >> 3;
573                                                unsigned short txtmagazinenr = tmpbuf[pos + 5 * y + 5] & 7;
574                                                unsigned short txtpagenr = tmpbuf[pos + 5 * y + 6];
575                                                if(txttype == 0x02 || txttype == 0x05)
576                                                        addsubtitle(chnode, 1, langdesc , pid, txttype, txtmagazinenr, txtpagenr, NULL);
577
578                                        }
579                                        chnode->txtpid = pid;
580                                        debug(200, "add txtpid %d", pid);
581                                        break;
582                                case 0x59: //subtitle
583                                        if(streamtype == 0x06)
584                                        {
585                                                for (y = 0; y < descriptorlength / 8; y++)
586                                                {
587                                                        langdesc[0] = toupper(tmpbuf[pos + 8 * y + 2]);
588                                                        langdesc[1] = toupper(tmpbuf[pos + 8 * y + 3]);
589                                                        langdesc[2] = toupper(tmpbuf[pos + 8 * y + 4]);
590                                                        langdesc[3] = '\0';
591                                                        unsigned char subtype = tmpbuf[pos + 8 * y + 5];
592                                                        unsigned short subpageid = (tmpbuf[(pos + 8 * y + 6) + 1] << 8) | tmpbuf[pos + 8 * y + 6];
593                                                        endianswapshort(&subpageid);
594                                                        unsigned short subancillarypageid = (tmpbuf[(pos + 8 * y + 8) + 1] << 8) | tmpbuf[pos + 8 * y + 8];
595                                                        endianswapshort(&subancillarypageid);
596                                                        addsubtitle(chnode, 2, langdesc , pid, subtype, subpageid, subancillarypageid, NULL);
597                                                }
598                                                debug(200, "add subtile pid %d", pid);
599                                        }
600                                        break;
601                                //case 0x53: //ca identifier
602                        }
603                }
604
605                switch (streamtype)
606                {
607                        case 0x01: // Mpeg1 Video (6)
608                        case 0x02: // Mpeg2 Video (0)
609                        case 0x10: // Mpeg4 Part2 Video (4)
610                        case 0x1b: // H264 (1)
611                        case 0xea: // vc1 (10)
612                                if(streamtype == 0x1b)
613                                        videocodec = H264;
614                                else if(streamtype == 0x10)
615                                        videocodec = MPEG4V;
616                                else if(streamtype == 0xea)
617                                        videocodec = VC1;
618                                else
619                                        videocodec = MPEGV;
620
621                                if(chnode->videopid != pid || chnode->videocodec != videocodec)
622                                {
623                                        chnode->videopid = pid;
624                                        chnode->videocodec = videocodec;
625                                        status.writechannel = 1;
626                                        ret = 1;
627
628                                        debug(200, "set videopid to %d", pid);
629                                        debug(200, "set videocode to %d (pid=%d)", videocodec, pid);
630                                }
631                                break;
632                        case 0x03: // Mpeg1 Audio (1)
633                        case 0x04: // Mpeg2 Audio (1)
634                        case 0x0f: // Mpeg2 AAC (8)
635                        case 0x11: // Mpeg4 AACHE (9)
636                        case 0x80: // LPCM (6)
637                        case 0xA0: // LPCM (6)
638                        case 0x81: // AC3 (0)
639                        case 0xA1: // AC3 (0)
640                        case 0x82: // DTS (2)
641                        case 0xA2: // DTS (2)
642                        //case 0x86: // DTS-HD
643                        //case 0xA6: // DTS-HD
644                        case 0x06:
645                                if(descriptorcount == 0 && streamtype == 0x06 && prevaudio != NULL)
646                                {
647                                        prevaudio->rdspid = pid;
648                                        debug(200, "set rdspid to %d", pid);
649                                }
650                                prevaudio = NULL;
651                                //if(streamtype == 0x81) esInfo->stream_type = 0x6;
652                                if(streamtype == 0x06 && !isac3 && !isdts && !isaac)
653                                        continue;
654
655                                if(streamtype == 0x06)
656                                {
657                                        if(isac3)
658                                                audiocodec = AC3;
659                                        else if(isdts)
660                                                audiocodec = DTS;
661                                        else if(isaac)
662                                                audiocodec = AAC;
663                                }
664                                else if(streamtype == 0x0F)
665                                        audiocodec = AAC;
666                                else if(streamtype == 0x11)
667                                        audiocodec = AACHE;
668                                else if(streamtype == 0x80 || streamtype == 0xA0)
669                                        audiocodec = LPCM;
670                                else if(streamtype == 0x81 || streamtype == 0xA1)
671                                        audiocodec = AC3;
672                                else if(streamtype == 0x82 || streamtype == 0xA2)
673                                        audiocodec = DTS;
674                                else
675                                        audiocodec = MPEGA;
676
677                                if(firstaudiopid == -1 || firstaudiocodec == -1)
678                                {
679                                        firstaudiopid = pid;
680                                        firstaudiocodec = audiocodec;
681                                }
682
683                                if(getconfigint("av_ac3default", NULL) == YES && audiocodec == AC3 && chnode->audiocodec != AC3)
684                                {
685                                        chnode->audiopid = pid;
686                                        chnode->audiocodec = audiocodec;
687                                        status.writechannel = 1;
688                                        debug(200, "ac3default -> set audiopid to %d", pid);
689                                        debug(200, "ac3default -> set audiocode to %d (pid=%d)", chnode->audiocodec, pid);
690                                }
691                               
692                                if(chnode->audiopid == pid && chnode->audiocodec == audiocodec)
693                                        audiochange = 0;
694
695                                prevaudio = addaudiotrack(chnode, langdesc, pid, audiocodec, NULL);
696                                break;
697                }
698        }
699       
700        if(audiochange == 1 && firstaudiopid != -1 && firstaudiocodec != -1)
701        {
702                chnode->audiopid = firstaudiopid;
703                chnode->audiocodec = firstaudiocodec;
704                status.writechannel = 1;
705                ret = 1;
706
707                debug(200, "set audiopid to %d", firstaudiopid);
708                debug(200, "set audiocode to %d (pid=%d)", firstaudiocodec, firstaudiopid);
709        }
710       
711        if(chnode->crypt != 0) debug(200, "stream is crypted");
712        return ret;
713}
714
715//check dynamic change of pmt
716void dvbgetpmtthread()
717{
718        int len = 0, change = 0;
719        unsigned char* pmtbuf = NULL;
720
721        //play activ?
722        if(status.play != 0 || status.playspeed != 0) return;
723       
724        if(status.aktservice->type != CHANNEL || status.aktservice->channel == NULL) return;
725       
726        debug(200, "dvbgetpmtthread started");
727       
728        int serviceid = status.aktservice->channel->serviceid;
729        uint64_t transponderid = status.aktservice->channel->transponderid;
730        int16_t pmtpid = status.aktservice->channel->pmtpid;
731        int16_t audiopid = status.aktservice->channel->audiopid;
732        int16_t videopid = status.aktservice->channel->videopid;
733        uint8_t crypt = status.aktservice->channel->crypt;
734        int oldpmtlen = status.aktservice->pmtlen;
735       
736        if(pmtpid < 1) return;
737
738        //outside of lock, can block a little
739        pmtbuf = dvbgetpmt(status.aktservice->fedev, NULL, serviceid, &pmtpid, &len, -1, 1);
740        if(pmtbuf == NULL) return;
741
742        m_lock(&status.servicemutex, 2);
743
744        //check if threre was a change from start funktion to lock
745        if(status.aktservice->type != CHANNEL || status.aktservice->channel == NULL || status.aktservice->channel->serviceid != serviceid || status.aktservice->channel->transponderid != transponderid)
746        {
747                debug(200, "change from start");
748                m_unlock(&status.servicemutex, 2);
749                free(pmtbuf);
750                return;
751        }
752
753        if(len != status.aktservice->pmtlen || memcmp(status.aktservice->pmtbuf, pmtbuf, len) != 0)
754        {
755                serviceresetchannelinfo(status.aktservice->channel);
756                status.aktservice->channel->audiopid = -1;
757                status.aktservice->channel->audiocodec = -1;
758                status.aktservice->channel->videopid = -1;
759                status.aktservice->channel->videocodec = -1;
760                status.aktservice->channel->pmtpid = pmtpid;
761                status.aktservice->channel->crypt = 0;
762                dvbgetinfo(pmtbuf, status.aktservice->channel);
763
764                debug(200, "pmt dynamic change oldapid=%d apid=%d oldvpid=%d vpid=%d oldcrypt=%d crypt=%d oldpmtlen=%d\n", audiopid, status.aktservice->channel->audiopid, videopid, status.aktservice->channel->videopid, status.aktservice->channel->crypt, crypt, oldpmtlen);
765
766                if(status.aktservice->channel->audiopid != audiopid || status.aktservice->channel->videopid != videopid || oldpmtlen == -1 || status.aktservice->channel->crypt != crypt)
767                        change = 1;
768        }
769
770        m_unlock(&status.servicemutex, 2);
771        free(pmtbuf);
772
773        if(change == 1)
774                servicestart(status.aktservice->channel, NULL, NULL, 3);
775               
776        debug(200, "dvbgetpmtthread ended... change=%i", change);
777}
778
779time_t dvbconvertdate(unsigned char *buf, int flag)
780{
781        int i = 0;
782        long mjd;
783        struct tm *time = NULL;
784        time_t gmttime = 0;
785
786        time = (struct tm*)malloc(sizeof(struct tm));
787        if(time == NULL)
788        {
789                err("no mem");
790                return 0;
791        }
792
793        memset(time, 0, sizeof(struct tm));
794
795        mjd = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
796        time->tm_hour = bcdtoint(buf[2] & 0xff);
797        time->tm_min = bcdtoint(buf[3] & 0xff);
798        time->tm_sec = bcdtoint(buf[4] & 0xff);
799
800        time->tm_year = (int) ((mjd - 15078.2) / 365.25);
801        time->tm_mon = (int) ((mjd - 14956.1 - (int) (time->tm_year * 365.25)) / 30.6001);
802        time->tm_mday = (int) mjd - 14956 - (int) (time->tm_year * 365.25) - (int) (time->tm_mon * 30.6001);
803        if(time->tm_mon == 14 || time->tm_mon == 15) i = 1;
804        time->tm_year += i;
805        time->tm_mon = time->tm_mon - 2 - i * 12;
806
807        time->tm_isdst = 0;
808        time->tm_gmtoff = 0;
809
810        if(flag == 0)
811                gmttime = timegm(time);
812        else
813                gmttime = mktime(time);
814
815        free(time);
816        return gmttime;
817}
818
819int dvbgetdate(time_t* time, int timeout)
820{
821        int length = -1, sectionlength;
822        struct dvbdev* dmxnode = NULL;
823        unsigned char *buf = NULL;
824
825        buf = malloc(MINMALLOC);
826        if(buf == NULL)
827        {
828                err("no memory");
829                return 1;
830        }
831
832        if(status.aktservice->fedev == NULL)
833        {
834                err("no frontend dev in aktservice");
835                free(buf);
836                return 1;
837        }
838
839        dmxnode = dmxopen(status.aktservice->fedev);
840        if(dmxnode == NULL)
841        {
842                err("open demux dev");
843                free(buf);
844                return 1;
845        }
846
847        dmxsetsource(dmxnode, status.aktservice->fedev->fedmxsource);
848        dmxsetfilter(dmxnode, 0x14, 0, 3);
849
850        if((length = dvbread(dmxnode, buf, 0, MINMALLOC, timeout)) < 0)
851        if(length < 3)
852        {
853                dmxclose(dmxnode, -1);
854                free(buf);
855                err("read dvb date");
856                return 1;
857        }
858
859        sectionlength = ((buf[1] & 0x0f) << 8) | (buf[2] & 0xff);
860        if(length == sectionlength + 3)
861                *time = dvbconvertdate(&(buf[3]), 0);
862        else
863        {
864                dmxclose(dmxnode, -1);
865                free(buf);
866                err("read dvb date");
867                return 1;
868        }
869
870        setrtctime(*time);
871
872        dmxclose(dmxnode, -1);
873        free(buf);
874        return 0;
875}
876
877// getPTS extracts a pts value from any PID at a given offset.
878int getpts(int fd, off64_t offset, int spid, int left, unsigned long long *pts, off64_t *findpos, int dir, int tssize)
879{
880        int first = 1;
881       
882        offset -= offset % tssize;
883        if(dir < 0 && offset < tssize) offset = tssize * 2;
884        if(dir < 0) offset *= -1;
885        while(left >= tssize)
886        {
887                unsigned char packet[tssize];
888
889                if(dir > -1)
890                        *findpos = lseek64(fd, offset, SEEK_SET);
891                else
892                {
893                        if(dir == -2)
894                        {
895                                if(first == 1)
896                                {
897                                        first = 0;
898                                        offset *= -1;
899                                        *findpos = lseek64(fd, offset, SEEK_SET);
900                                        offset = -tssize;
901                                }
902                                else
903                                {
904                                        if(offset % tssize != 0)
905                                        {
906                                                *findpos = lseek64(fd, (offset % tssize) - tssize, SEEK_CUR);
907                                                offset = -tssize;
908                                        }
909                                        else
910                                                *findpos = lseek64(fd, -tssize * 2, SEEK_CUR);
911                                }
912                        }
913                        else
914                                *findpos = lseek64(fd, offset, SEEK_END);
915                }
916
917                int ret = dvbreadfd(fd, packet, 0, tssize, -1, 0);
918                if(ret != tssize && ret != 188)
919                {
920                        err("read error");
921                        break;
922                }
923
924                if(packet[0] != 0x47)
925                {
926                        debug(200, "resync");
927                        int i = 0;
928                        while(i < tssize)
929                        {
930                                if(packet[i] == 0x47) break;
931                                i++;
932                                offset++;
933                        }
934                        continue;
935                }
936
937                left -= tssize;
938                if(dir > -1)
939                        offset += tssize;
940                else
941                        offset -= tssize;
942               
943                int pid = ((packet[1] << 8) | packet[2]) & 0x1FFF;
944                int pusi = !!(packet[1] & 0x40);
945               
946//              printf("PID %04x, PUSI %d\n", pid, pusi);
947
948                unsigned char *payload;
949               
950                //check for adaption field
951                if(packet[3] & 0x20)
952                {
953                        if(packet[4] >= 183) continue;
954                        if(packet[4])
955                        {
956                                if(packet[5] & 0x10) //PCR present
957                                {
958                                        *pts = ((unsigned long long)(packet[6] & 0xFF)) << 25;
959                                        *pts |= ((unsigned long long)(packet[7] & 0xFF)) << 17;
960                                        *pts |= ((unsigned long long)(packet[8] & 0xFE)) << 9;
961                                        *pts |= ((unsigned long long)(packet[9] & 0xFF)) << 1;
962                                        *pts |= ((unsigned long long)(packet[10] & 0x80)) >> 7;
963                                        if(dir > -1)
964                                        {
965                                                offset -= tssize;
966                                                *findpos -= tssize;
967                                        }
968                                        debug(200, "PCR %16llx found at %lld pid %02x (%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)", *pts, offset, pid, packet[0], packet[1], packet[2], packet[3], packet[4], packet[5], packet[10], packet[9], packet[8], packet[7], packet[6]);
969                                        return 0;
970                                }
971                        }
972                        payload = packet + packet[4] + 4 + 1;
973                } else
974                        payload = packet + 4;
975
976                //if(spid >= 0 && pid != spid) continue;
977                if(!pusi) continue;
978
979                //somehow not a startcode. (this is invalid, since pusi was set.) ignore it.
980                if (payload[0] || payload[1] || (payload[2] != 1))
981                        continue;
982
983                //stream use extension mechanism def in ISO 13818-1 Amendment 2
984                if(payload[3] == 0xFD)
985                {
986                        if(payload[7] & 1) //PES extension flag
987                        {
988                                int offs = 0;
989                                if(payload[7] & 0x80) offs += 5; //pts avail
990                                if(payload[7] & 0x40) offs += 5; //dts avail
991                                if(payload[7] & 0x20) offs += 6; //escr avail
992                                if(payload[7] & 0x10) offs += 3; //es rate
993                                if(payload[7] & 0x8) offs += 1; //dsm trickmode
994                                if(payload[7] & 0x4) offs += 1; //additional copy info
995                                if(payload[7] & 0x2) offs += 2; //crc
996                                if(payload[8] < offs) continue;
997
998                                uint8_t pef = payload[9 + offs++]; //pes extension field
999                                if(pef & 1) //pes extension flag 2
1000                                {
1001                                        if(pef & 0x80) offs += 16; //private data flag
1002                                        if(pef & 0x40) offs += 1; //pack header field flag
1003                                        if(pef & 0x20) offs += 2; //program packet sequence counter flag
1004                                        if(pef & 0x10) offs += 2; //P-STD buffer flag
1005                                        if(payload[8] < offs) continue;
1006
1007                                        uint8_t stream_id_extension_len = payload[9 + offs++] & 0x7F;
1008                                        if(stream_id_extension_len >= 1)
1009                                        {
1010                                                if(payload[8] < (offs + stream_id_extension_len)) continue;
1011                                                //stream_id_extension_bit (should not set)
1012                                                if(payload[9 + offs] & 0x80) continue;
1013                                                switch(payload[9 + offs])
1014                                                {
1015                                                        case 0x55 ... 0x5f: break; //VC-1
1016                                                        case 0x71: break; //AC3 / DTS
1017                                                        case 0x72: break; //DTS - HD
1018                                                        default:
1019                                                                debug(200, "skip unknwn stream_id_extension %02x\n", payload[9 + offs]);
1020                                                                continue;
1021                                                }
1022                                        }
1023                                        else
1024                                                continue;
1025                                }
1026                                else
1027                                        continue;
1028                        }
1029                        else
1030                                continue;
1031                }
1032                //drop non-audio, non-video packets because other streams
1033                //can be non-compliant.
1034                //0xC0 = audio, 0xE0 = video
1035                else if(((payload[3] & 0xE0) != 0xC0) && ((payload[3] & 0xF0) != 0xE0))
1036                        continue;
1037
1038                if(payload[7] & 0x80) //PTS
1039                {
1040                        *pts = ((unsigned long long)(payload[9] & 0xE)) << 29;
1041                        *pts |= ((unsigned long long)(payload[10] & 0xFF)) << 22;
1042                        *pts |= ((unsigned long long)(payload[11] & 0xFE)) << 14;
1043                        *pts |= ((unsigned long long)(payload[12] & 0xFF)) << 7;
1044                        *pts |= ((unsigned long long)(payload[13] & 0xFE)) >> 1;
1045
1046                        if(dir > -1)
1047                        {
1048                                offset -= tssize;
1049                                *findpos -= tssize;
1050                        }
1051                        debug(200, "PTS %16llx found at %lld pid %02x stream: %02x", *pts, offset, pid, payload[3]);
1052
1053                        return 0;
1054                }
1055        }
1056       
1057        return 1;
1058}
1059
1060unsigned long long fixuppts(unsigned long long start, unsigned long long end)
1061{
1062                //pts can wrap to 0 in the middle
1063                if(end < start)
1064                        end = end + 0x200000000LL;
1065                return end;
1066}
1067
1068unsigned long long gettsbitrate(unsigned long long start, unsigned long long end, off64_t startfindpos, off64_t endfindpos)
1069{
1070        unsigned long long bitrate = 0;
1071        unsigned long long diff = 0;
1072
1073        diff = end - start;
1074        if(diff <= 0) return 0;
1075
1076        bitrate = (endfindpos - startfindpos) * 90000 * 8 / diff;
1077        if(bitrate < 10000 || bitrate > 100000000)
1078                return 0;
1079        else
1080                return bitrate;
1081}
1082
1083int gettsinfo(int fd, unsigned long long* lenpts, unsigned long long* startpts, unsigned long long* endpts, unsigned long long* bitrate, int tssize)
1084{
1085        int ret = 0;
1086        unsigned long long start = 0, end = 0;
1087        off64_t startfindpos = 0, endfindpos = 0;
1088
1089        if(startpts != NULL && *startpts > 0) start = *startpts;
1090        if(endpts != NULL && *endpts > 0) end = *endpts;
1091
1092        if(start == 0 || (bitrate != NULL && bitrate == 0))
1093                ret = getpts(fd, 0, 0, 256 * 1024, &start, &startfindpos, 1, tssize);
1094
1095        if((ret == 0 && end == 0) || (bitrate != NULL && bitrate == 0))
1096                ret = getpts(fd, 0, 0, 256 * 1024, &end, &endfindpos, -1, tssize);
1097
1098        if(ret == 0)
1099        {
1100                end = fixuppts(start, end);
1101                if(lenpts != NULL) *lenpts = end - start;
1102                if(startpts != NULL) *startpts = start;
1103                if(endpts != NULL) *endpts = end;
1104                if(bitrate != NULL && *bitrate == 0) *bitrate = gettsbitrate(start, end, startfindpos, endfindpos);
1105        }
1106
1107        if(lenpts != NULL && *lenpts < 0) *lenpts = 0;
1108        if(startpts != NULL && *startpts < 0) *startpts = 0;
1109        if(endpts != NULL && *endpts < 0) *endpts = 0;
1110        return ret;
1111}
1112
1113int getptspos(int fd, off64_t startfind, unsigned long long* pts, off64_t* findpos, int dir, int tssize)
1114{
1115        int ret = 0;
1116        unsigned long long pts1 = 0;
1117        off64_t findpos1 = 0;
1118       
1119        ret = getpts(fd, startfind, 0, 256 * 1024, &pts1, &findpos1, dir, tssize);
1120        if(pts != NULL) *pts = pts1;
1121        if(findpos != NULL) *findpos = findpos1;
1122       
1123        return ret;             
1124}
1125
1126
1127//rc = 1 --> mpeg
1128//rc = 2 --> h.264
1129int findcodec(unsigned char* buf, int len, int tssize)
1130{
1131        int i,i1;
1132        int rc = 2;
1133       
1134        for(i = 0; i < len-tssize; i = i + tssize)
1135        {
1136                if((buf[i+1]&0x40)>>6 == 0x01)
1137                {
1138                        for(i1 = i+4; i1 < i + tssize-4; i1 = i1 + 1)
1139                        {
1140                                if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01 && buf[i1+3] == 0xB3)
1141                                {
1142                                        return 1;
1143                                }
1144                        }
1145                }
1146        }
1147        return rc;
1148}
1149
1150//flag=0 -> future use
1151//flag=1 -> I-Slice
1152//flag=2 -> ende Frame
1153int findframeHD(unsigned char* buf, int len, int start, int tssize, int flag)
1154{
1155        int position = -1;
1156        int i = 0;
1157        int i1 = 0;
1158
1159        len = start + len;
1160       
1161        while(1)
1162        {
1163                for(i = start; i < len-3; i = i + 1)
1164                {
1165                        //Picture header ?
1166                        if (buf[i] == 0x00 && buf[i+1] == 0x00 && buf[i+2] == 0x01)
1167                        {
1168                                //SPS (Sequence Parameter Set)?
1169                                if(buf[i+3] == 0x67 && flag == 1)
1170                                {
1171                                        //PPS (Picture Parameter Set) ?
1172                                        for(i1 = i + 4; i1 < (i % tssize) + i; i1 = i1 + 1)
1173                                        {
1174                                                if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01 && buf[i1+3] == 0x68)
1175                                                {
1176                                                        position = i1;
1177                                                        break;
1178                                                }
1179                                        }
1180                                        if(position != -1)
1181                                        {
1182                                                for(i1 = position + 4; i1 < (position % tssize) + position; i1 = i1 + 1)
1183                                                {
1184                                                        if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01)
1185                                                        {
1186                                                                if(buf[i1+3] == 0x01 || buf[i1+3] == 0x21 || buf[i1+3] == 0x41 || buf[i1+3] == 0x61)
1187                                                                {
1188                                                                        i = i1+4;
1189                                                                        position = -1;
1190                                                                        break;
1191                                                                }
1192                                                        }
1193                                                }
1194                                        }
1195                                        if(position != -1)
1196                                                break;                                 
1197                                }
1198                                //I-P-Slice oder I-P-B-Slice oder oder .....?
1199                                else if((buf[i+3] == 0x01 || buf[i+3] == 0x21 || buf[i+3] == 0x41 || buf[i+3] == 0x61) && flag == 2 )
1200                                {
1201                                  position = i;
1202                                        break;
1203                                }
1204                }
1205        }
1206        return position;
1207        }
1208}
1209
1210
1211//flag=0 -> Sequence header
1212//flag=1 -> I-Fame
1213//flag=2 -> ende Frame
1214int findframe(unsigned char* buf, int len, int start, int tssize, int flag)
1215{       
1216        //#define       SEQ_START_CODE          0x000001b3
1217        //#define GOP_START_CODE          0x000001b8
1218        //#define PICTURE_START_CODE      0x00000100
1219        //#define SLICE_START_CODE        0x00000101
1220        //#define PACK_START_CODE         0x000001ba
1221        //#define VIDEO_ID                0x000001e0
1222        //#define AUDIO_ID                0x000001c0
1223
1224       
1225        int position = -1;
1226        int i = 0;
1227
1228        len = start + len;
1229
1230        while(1) {
1231
1232                for(i = start; i < len-3; i = i + 1)
1233                {
1234
1235                        //Picture header ?
1236                        if (buf[i] == 0x00 && buf[i+1] == 0x00 && buf[i+2] == 0x01)
1237                        {
1238       
1239                                //Sequence header
1240                                if(buf[i+3] == 0xB3 && flag == 0)
1241                                {
1242                                        position = i;
1243                                        break;
1244                                }       
1245
1246                                //Picture-Frame ?
1247                                else if(buf[i+3] == 0x00)
1248                                {
1249
1250                                        //I-Frame ?
1251                                        if((buf[i+5] & 0x38)>>3 == 0x01 && flag == 1)
1252                                        {
1253                                          position = i;
1254                                                break;
1255                                        }
1256
1257                                        //other Frame ?
1258                                        else if((buf[i+5] & 0x38)>>3 != 0x00 && flag == 2)
1259                                        {
1260                                          position = i;
1261                                                break;
1262                                        }       
1263                                }
1264                }
1265        }
1266        return position;
1267        }
1268}
1269
1270int findandposrew(int fd, int tssize, int skip)
1271{
1272        int i;
1273        int ret = 0;
1274        int framelen = -1;
1275        off64_t endframe = -1;
1276        off64_t startframe = -1;
1277        int readret = 0;
1278        int codec = 0;
1279        int buflen = tssize * 15000;
1280        unsigned char* buf = malloc(buflen);
1281        off64_t currentpos;
1282        off64_t skippos;
1283       
1284        //ret = videostop(status.aktservice->videodev,0);
1285        //ret = videoclearbuffer(status.aktservice->videodev);
1286        //ret = audioclearbuffer(status.aktservice->audiodev);
1287        //ret = audiosetavsync(status.aktservice->audiodev, 0);
1288        //ret = audiosetmute(status.aktservice->audiodev, 1);
1289       
1290        currentpos = lseek64(fd, 0, SEEK_CUR);
1291        skippos = currentpos;
1292       
1293        while(1)
1294        {
1295                skippos = skippos - buflen;
1296                if(skippos < 0)
1297                {
1298                        currentpos = lseek64(fd, currentpos, SEEK_SET);
1299                        free(buf);
1300                        return -1;
1301                }
1302                skippos = lseek64(fd, skippos, SEEK_SET);
1303                readret = dvbreadfd(fd, buf, 0, buflen, 5000000, 1);
1304                if(readret > 0)
1305                {
1306                        codec = findcodec(buf, buflen, tssize);
1307                        for(i = readret - tssize; i >= 0; i = i - tssize)
1308                        {
1309                                if(codec == 1)
1310                                        ret = findframe(buf, tssize, i, tssize, 0);
1311                                else
1312                                        ret = findframeHD(buf, tssize, i, tssize, 1);
1313                                if(ret > -1)
1314                                {
1315                                        if(endframe == -1)
1316                                        {
1317                                                if(skip != 0)
1318                                                        skip = skip - 1;
1319                                                else
1320                                                        endframe = skippos + i;
1321                                        }
1322                                        else
1323                                        {
1324                                                startframe = skippos + i;
1325                                                framelen = endframe - startframe;
1326                                                currentpos = lseek64(fd, startframe, SEEK_SET);
1327                                                //readret = dvbreadfd(servicenode->recsrcfd, buf, 0, buflen, 5000000, 1);
1328                                                free(buf);
1329                                                return framelen;
1330                                        }
1331                                }
1332                        }
1333                }
1334                else
1335                {
1336                        currentpos = lseek64(fd, currentpos, SEEK_SET);
1337                        free(buf);
1338                        return -1;
1339                }
1340        }
1341}
1342
1343#endif
Note: See TracBrowser for help on using the repository browser.