source: titan/titan/dvb.h @ 42137

Last change on this file since 42137 was 42137, checked in by gost, 5 years ago

[tiatn] workaround DTSHD

File size: 31.9 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(200, "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(200, "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, 1);
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, 1);
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, isddp = 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; isddp = 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 0x7A: 
566                                        isddp = 1;
567                                break;
568                                case 0x56: //teletext
569                                        for (y = 0; y < descriptorlength / 5; y++)
570                                        {
571                                                langdesc[0] = toupper(tmpbuf[pos + 5 * y + 2]);
572                                                langdesc[1] = toupper(tmpbuf[pos + 5 * y + 3]);
573                                                langdesc[2] = toupper(tmpbuf[pos + 5 * y + 4]);
574                                                langdesc[3] = '\0';
575                                                unsigned char txttype = tmpbuf[pos + 5 * y + 5] >> 3;
576                                                unsigned short txtmagazinenr = tmpbuf[pos + 5 * y + 5] & 7;
577                                                unsigned short txtpagenr = tmpbuf[pos + 5 * y + 6];
578                                                if(txttype == 0x02 || txttype == 0x05)
579                                                        addsubtitle(chnode, 1, langdesc , pid, txttype, txtmagazinenr, txtpagenr, NULL);
580
581                                        }
582                                        chnode->txtpid = pid;
583                                        debug(200, "add txtpid %d", pid);
584                                        break;
585                                case 0x59: //subtitle
586                                        if(streamtype == 0x06)
587                                        {
588                                                for (y = 0; y < descriptorlength / 8; y++)
589                                                {
590                                                        langdesc[0] = toupper(tmpbuf[pos + 8 * y + 2]);
591                                                        langdesc[1] = toupper(tmpbuf[pos + 8 * y + 3]);
592                                                        langdesc[2] = toupper(tmpbuf[pos + 8 * y + 4]);
593                                                        langdesc[3] = '\0';
594                                                        unsigned char subtype = tmpbuf[pos + 8 * y + 5];
595                                                        unsigned short subpageid = (tmpbuf[(pos + 8 * y + 6) + 1] << 8) | tmpbuf[pos + 8 * y + 6];
596                                                        endianswapshort(&subpageid);
597                                                        unsigned short subancillarypageid = (tmpbuf[(pos + 8 * y + 8) + 1] << 8) | tmpbuf[pos + 8 * y + 8];
598                                                        endianswapshort(&subancillarypageid);
599                                                        addsubtitle(chnode, 2, langdesc , pid, subtype, subpageid, subancillarypageid, NULL);
600                                                }
601                                                debug(200, "add subtile pid %d", pid);
602                                        }
603                                        break;
604                                //case 0x53: //ca identifier
605                        }
606                }
607
608                switch (streamtype)
609                {
610                        case 0x01: // Mpeg1 Video (6)
611                        case 0x02: // Mpeg2 Video (0)
612                        case 0x10: // Mpeg4 Part2 Video (4)
613                        case 0x1b: // H264 (1)
614                        case 0x24: //   H265_HEVC
615                        case 0xea: // vc1 (10)
616                                if(streamtype == 0x1b)
617                                        videocodec = H264;
618                                else if(streamtype == 0x24)
619                                        videocodec = H265;
620                                else if(streamtype == 0x10)
621                                        videocodec = MPEG4V;
622                                else if(streamtype == 0xea)
623                                        videocodec = VC1;
624                                else
625                                        videocodec = MPEGV;
626
627                                if(chnode->videopid != pid || chnode->videocodec != videocodec)
628                                {
629                                        chnode->videopid = pid;
630                                        chnode->videocodec = videocodec;
631                                        status.writechannel = 1;
632                                        ret = 1;
633
634                                        debug(200, "set videopid to %d", pid);
635                                        debug(200, "set videocode to %d (pid=%d)", videocodec, pid);
636                                }
637                                break;
638                        case 0x03: // Mpeg1 Audio (1)
639                        case 0x04: // Mpeg2 Audio (1)
640                        case 0x0f: // Mpeg2 AAC (8)
641                        case 0x11: // Mpeg4 AACHE (9)
642                        case 0x80: // LPCM (6)
643                        case 0xA0: // LPCM (6)
644                        case 0x81: // AC3 (0)
645                        case 0xA1: // AC3 (0)
646                        case 0x82: // DTS (2)
647                        case 0xA2: // DTS (2)
648                        case 0x85: // DTS-HD HRA
649                        case 0x86: // DTS-HD MA
650                        case 0xA6: // DTS-HD
651                        case 0x06:
652                                if(descriptorcount == 0 && streamtype == 0x06 && prevaudio != NULL)
653                                {
654                                        prevaudio->rdspid = pid;
655                                        debug(200, "set rdspid to %d", pid);
656                                }
657                                prevaudio = NULL;
658                                //if(streamtype == 0x81) esInfo->stream_type = 0x6;
659                                if(streamtype == 0x06 && !isac3 && !isdts && !isaac && !isddp)
660                                        continue;
661
662                                if(streamtype == 0x06)
663                                {
664                                        if(isac3)
665                                                audiocodec = AC3;
666                                        else if(isdts)
667                                                audiocodec = DTS;
668                                        else if(isaac)
669                                                audiocodec = AAC;
670                                        else if(isddp)
671                                                audiocodec = DDP;
672                                }
673                                else if(streamtype == 0x0F)
674                                        audiocodec = AAC;
675                                else if(streamtype == 0x11)
676                                        audiocodec = AACHE;
677                                else if(streamtype == 0x80 || streamtype == 0xA0)
678                                        audiocodec = LPCM;
679                                else if(streamtype == 0x81 || streamtype == 0xA1)
680                                        audiocodec = AC3;
681                                else if(streamtype == 0x82 || streamtype == 0xA2)
682                                        audiocodec = DTS;
683                                else if(streamtype == 0x85 || streamtype == 0x86 || streamtype == 0xA6)
684                                        audiocodec = DTSHD;
685                                else
686                                        audiocodec = MPEGA;
687                                       
688                                //workaround DTSHD
689                                if(audiocodec == DTSHD)
690                                {
691                                        audiocodec = 0;
692                                        continue;
693                                }
694
695                                if(firstaudiopid == -1 || firstaudiocodec == -1)
696                                {
697                                        firstaudiopid = pid;
698                                        firstaudiocodec = audiocodec;
699                                }
700
701                                if(getconfigint("av_ac3default", NULL) == YES && audiocodec == AC3 && chnode->audiocodec != AC3)
702                                {
703                                        chnode->audiopid = pid;
704                                        chnode->audiocodec = audiocodec;
705                                        status.writechannel = 1;
706                                        debug(200, "ac3default -> set audiopid to %d", pid);
707                                        debug(200, "ac3default -> set audiocode to %d (pid=%d)", chnode->audiocodec, pid);
708                                }
709                               
710                                if(chnode->audiopid == pid && chnode->audiocodec == audiocodec)
711                                        audiochange = 0;
712
713                                prevaudio = addaudiotrack(chnode, langdesc, pid, audiocodec, NULL);
714                                break;
715                }
716        }
717       
718        if(audiochange == 1 && firstaudiopid != -1 && firstaudiocodec != -1)
719        {
720                chnode->audiopid = firstaudiopid;
721                chnode->audiocodec = firstaudiocodec;
722                status.writechannel = 1;
723                ret = 1;
724
725                debug(200, "set audiopid to %d", firstaudiopid);
726                debug(200, "set audiocode to %d (pid=%d)", firstaudiocodec, firstaudiopid);
727        }
728       
729        if(chnode->crypt != 0) debug(200, "stream is crypted");
730        return ret;
731}
732
733//check dynamic change of pmt
734void dvbgetpmtthread()
735{
736        int len = 0, change = 0;
737        unsigned char* pmtbuf = NULL;
738
739        //play activ?
740        if(status.play != 0 || status.playspeed != 0) return;
741       
742        if(status.aktservice->type != CHANNEL || status.aktservice->channel == NULL) return;
743       
744        debug(200, "dvbgetpmtthread started");
745       
746        int serviceid = status.aktservice->channel->serviceid;
747        uint64_t transponderid = status.aktservice->channel->transponderid;
748        int16_t pmtpid = status.aktservice->channel->pmtpid;
749        int16_t audiopid = status.aktservice->channel->audiopid;
750        int16_t videopid = status.aktservice->channel->videopid;
751        uint8_t crypt = status.aktservice->channel->crypt;
752        int oldpmtlen = status.aktservice->pmtlen;
753       
754        if(pmtpid < 1) return;
755
756        //outside of lock, can block a little
757        pmtbuf = dvbgetpmt(status.aktservice->fedev, NULL, serviceid, &pmtpid, &len, -1, 1);
758        if(pmtbuf == NULL) return;
759
760        m_lock(&status.servicemutex, 2);
761
762        //check if threre was a change from start funktion to lock
763        if(status.aktservice->type != CHANNEL || status.aktservice->channel == NULL || status.aktservice->channel->serviceid != serviceid || status.aktservice->channel->transponderid != transponderid)
764        {
765                debug(200, "change from start");
766                m_unlock(&status.servicemutex, 2);
767                free(pmtbuf);
768                return;
769        }
770
771        if(len != status.aktservice->pmtlen || memcmp(status.aktservice->pmtbuf, pmtbuf, len) != 0)
772        {
773                serviceresetchannelinfo(status.aktservice->channel);
774                status.aktservice->channel->audiopid = -1;
775                status.aktservice->channel->audiocodec = -1;
776                status.aktservice->channel->videopid = -1;
777                status.aktservice->channel->videocodec = -1;
778                status.aktservice->channel->pmtpid = pmtpid;
779                status.aktservice->channel->crypt = 0;
780                dvbgetinfo(pmtbuf, status.aktservice->channel);
781
782                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);
783
784                if(status.aktservice->channel->audiopid != audiopid || status.aktservice->channel->videopid != videopid || oldpmtlen == -1 || status.aktservice->channel->crypt != crypt)
785                        change = 1;
786        }
787
788        m_unlock(&status.servicemutex, 2);
789        free(pmtbuf);
790
791        if(change == 1)
792                servicestart(status.aktservice->channel, NULL, NULL, 3);
793               
794        debug(200, "dvbgetpmtthread ended... change=%i", change);
795}
796
797time_t dvbconvertdate(unsigned char *buf, int flag)
798{
799        int i = 0;
800        long mjd;
801        struct tm *time = NULL;
802        time_t gmttime = 0;
803
804        time = (struct tm*)malloc(sizeof(struct tm));
805        if(time == NULL)
806        {
807                err("no mem");
808                return 0;
809        }
810
811        memset(time, 0, sizeof(struct tm));
812
813        mjd = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
814        time->tm_hour = bcdtoint(buf[2] & 0xff);
815        time->tm_min = bcdtoint(buf[3] & 0xff);
816        time->tm_sec = bcdtoint(buf[4] & 0xff);
817
818        time->tm_year = (int) ((mjd - 15078.2) / 365.25);
819        time->tm_mon = (int) ((mjd - 14956.1 - (int) (time->tm_year * 365.25)) / 30.6001);
820        time->tm_mday = (int) mjd - 14956 - (int) (time->tm_year * 365.25) - (int) (time->tm_mon * 30.6001);
821        if(time->tm_mon == 14 || time->tm_mon == 15) i = 1;
822        time->tm_year += i;
823        time->tm_mon = time->tm_mon - 2 - i * 12;
824
825        time->tm_isdst = 0;
826        time->tm_gmtoff = 0;
827
828        if(flag == 0)
829                gmttime = timegm(time);
830        else
831                gmttime = mktime(time);
832
833        free(time);
834        return gmttime;
835}
836
837int dvbgetdate(time_t* time, int timeout)
838{
839        int length = -1, sectionlength;
840        struct dvbdev* dmxnode = NULL;
841        unsigned char *buf = NULL;
842
843        buf = malloc(MINMALLOC);
844        if(buf == NULL)
845        {
846                err("no memory");
847                return 1;
848        }
849
850        if(status.aktservice->fedev == NULL)
851        {
852                err("no frontend dev in aktservice");
853                free(buf);
854                return 1;
855        }
856
857        dmxnode = dmxopen(status.aktservice->fedev, 1);
858        if(dmxnode == NULL)
859        {
860                err("open demux dev");
861                free(buf);
862                return 1;
863        }
864
865        dmxsetsource(dmxnode, status.aktservice->fedev->fedmxsource);
866        dmxsetfilter(dmxnode, 0x14, 0, 3);
867
868        if((length = dvbread(dmxnode, buf, 0, MINMALLOC, timeout)) < 0)
869        if(length < 3)
870        {
871                dmxclose(dmxnode, -1);
872                free(buf);
873                err("read dvb date");
874                return 1;
875        }
876
877        sectionlength = ((buf[1] & 0x0f) << 8) | (buf[2] & 0xff);
878        if(length == sectionlength + 3)
879                *time = dvbconvertdate(&(buf[3]), 0);
880        else
881        {
882                dmxclose(dmxnode, -1);
883                free(buf);
884                err("read dvb date");
885                return 1;
886        }
887
888        setrtctime(*time);
889
890        dmxclose(dmxnode, -1);
891        free(buf);
892        return 0;
893}
894
895// getPTS extracts a pts value from any PID at a given offset.
896int getpts(int fd, off64_t offset, int spid, int left, unsigned long long *pts, off64_t *findpos, int dir, int tssize)
897{
898        int first = 1;
899       
900        offset -= offset % tssize;
901        if(dir < 0 && offset < tssize) offset = tssize * 2;
902        if(dir < 0) offset *= -1;
903        while(left >= tssize)
904        {
905                unsigned char packet[tssize];
906
907                if(dir > -1)
908                        *findpos = lseek64(fd, offset, SEEK_SET);
909                else
910                {
911                        if(dir == -2)
912                        {
913                                if(first == 1)
914                                {
915                                        first = 0;
916                                        offset *= -1;
917                                        *findpos = lseek64(fd, offset, SEEK_SET);
918                                        offset = -tssize;
919                                }
920                                else
921                                {
922                                        if(offset % tssize != 0)
923                                        {
924                                                *findpos = lseek64(fd, (offset % tssize) - tssize, SEEK_CUR);
925                                                offset = -tssize;
926                                        }
927                                        else
928                                                *findpos = lseek64(fd, -tssize * 2, SEEK_CUR);
929                                }
930                        }
931                        else
932                                *findpos = lseek64(fd, offset, SEEK_END);
933                }
934
935                int ret = dvbreadfd(fd, packet, 0, tssize, -1, 0);
936                if(ret != tssize && ret != 188)
937                {
938                        err("read error");
939                        break;
940                }
941
942                if(packet[0] != 0x47)
943                {
944                        debug(200, "resync");
945                        int i = 0;
946                        while(i < tssize)
947                        {
948                                if(packet[i] == 0x47) break;
949                                i++;
950                                offset++;
951                        }
952                        continue;
953                }
954
955                left -= tssize;
956                if(dir > -1)
957                        offset += tssize;
958                else
959                        offset -= tssize;
960               
961                int pid = ((packet[1] << 8) | packet[2]) & 0x1FFF;
962                int pusi = !!(packet[1] & 0x40);
963               
964//              printf("PID %04x, PUSI %d\n", pid, pusi);
965
966                unsigned char *payload;
967               
968                //check for adaption field
969                if(packet[3] & 0x20)
970                {
971                        if(packet[4] >= 183) continue;
972                        if(packet[4])
973                        {
974                                if(packet[5] & 0x10) //PCR present
975                                {
976                                        *pts = ((unsigned long long)(packet[6] & 0xFF)) << 25;
977                                        *pts |= ((unsigned long long)(packet[7] & 0xFF)) << 17;
978                                        *pts |= ((unsigned long long)(packet[8] & 0xFE)) << 9;
979                                        *pts |= ((unsigned long long)(packet[9] & 0xFF)) << 1;
980                                        *pts |= ((unsigned long long)(packet[10] & 0x80)) >> 7;
981                                        if(dir > -1)
982                                        {
983                                                offset -= tssize;
984                                                *findpos -= tssize;
985                                        }
986                                        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]);
987                                        return 0;
988                                }
989                        }
990                        payload = packet + packet[4] + 4 + 1;
991                } else
992                        payload = packet + 4;
993
994                //if(spid >= 0 && pid != spid) continue;
995                if(!pusi) continue;
996
997                //somehow not a startcode. (this is invalid, since pusi was set.) ignore it.
998                if (payload[0] || payload[1] || (payload[2] != 1))
999                        continue;
1000
1001                //stream use extension mechanism def in ISO 13818-1 Amendment 2
1002                if(payload[3] == 0xFD)
1003                {
1004                        if(payload[7] & 1) //PES extension flag
1005                        {
1006                                int offs = 0;
1007                                if(payload[7] & 0x80) offs += 5; //pts avail
1008                                if(payload[7] & 0x40) offs += 5; //dts avail
1009                                if(payload[7] & 0x20) offs += 6; //escr avail
1010                                if(payload[7] & 0x10) offs += 3; //es rate
1011                                if(payload[7] & 0x8) offs += 1; //dsm trickmode
1012                                if(payload[7] & 0x4) offs += 1; //additional copy info
1013                                if(payload[7] & 0x2) offs += 2; //crc
1014                                if(payload[8] < offs) continue;
1015
1016                                uint8_t pef = payload[9 + offs++]; //pes extension field
1017                                if(pef & 1) //pes extension flag 2
1018                                {
1019                                        if(pef & 0x80) offs += 16; //private data flag
1020                                        if(pef & 0x40) offs += 1; //pack header field flag
1021                                        if(pef & 0x20) offs += 2; //program packet sequence counter flag
1022                                        if(pef & 0x10) offs += 2; //P-STD buffer flag
1023                                        if(payload[8] < offs) continue;
1024
1025                                        uint8_t stream_id_extension_len = payload[9 + offs++] & 0x7F;
1026                                        if(stream_id_extension_len >= 1)
1027                                        {
1028                                                if(payload[8] < (offs + stream_id_extension_len)) continue;
1029                                                //stream_id_extension_bit (should not set)
1030                                                if(payload[9 + offs] & 0x80) continue;
1031                                                switch(payload[9 + offs])
1032                                                {
1033                                                        case 0x55 ... 0x5f: break; //VC-1
1034                                                        case 0x71: break; //AC3 / DTS
1035                                                        case 0x72: break; //DTS - HD
1036                                                        default:
1037                                                                debug(200, "skip unknwn stream_id_extension %02x\n", payload[9 + offs]);
1038                                                                continue;
1039                                                }
1040                                        }
1041                                        else
1042                                                continue;
1043                                }
1044                                else
1045                                        continue;
1046                        }
1047                        else
1048                                continue;
1049                }
1050                //drop non-audio, non-video packets because other streams
1051                //can be non-compliant.
1052                //0xC0 = audio, 0xE0 = video
1053                else if(((payload[3] & 0xE0) != 0xC0) && ((payload[3] & 0xF0) != 0xE0))
1054                        continue;
1055
1056                if(payload[7] & 0x80) //PTS
1057                {
1058                        *pts = ((unsigned long long)(payload[9] & 0xE)) << 29;
1059                        *pts |= ((unsigned long long)(payload[10] & 0xFF)) << 22;
1060                        *pts |= ((unsigned long long)(payload[11] & 0xFE)) << 14;
1061                        *pts |= ((unsigned long long)(payload[12] & 0xFF)) << 7;
1062                        *pts |= ((unsigned long long)(payload[13] & 0xFE)) >> 1;
1063
1064                        if(dir > -1)
1065                        {
1066                                offset -= tssize;
1067                                *findpos -= tssize;
1068                        }
1069                        debug(200, "PTS %16llx found at %lld pid %02x stream: %02x", *pts, offset, pid, payload[3]);
1070
1071                        return 0;
1072                }
1073        }
1074       
1075        return 1;
1076}
1077
1078unsigned long long fixuppts(unsigned long long start, unsigned long long end)
1079{
1080                //pts can wrap to 0 in the middle
1081                if(end < start)
1082                        end = end + 0x200000000LL;
1083                return end;
1084}
1085
1086unsigned long long gettsbitrate(unsigned long long start, unsigned long long end, off64_t startfindpos, off64_t endfindpos)
1087{
1088        unsigned long long bitrate = 0;
1089        unsigned long long diff = 0;
1090
1091        diff = end - start;
1092        if(diff <= 0) return 0;
1093
1094        bitrate = (endfindpos - startfindpos) * 90000 * 8 / diff;
1095        if(bitrate < 10000 || bitrate > 100000000)
1096                return 0;
1097        else
1098                return bitrate;
1099}
1100
1101int gettsinfo(int fd, unsigned long long* lenpts, unsigned long long* startpts, unsigned long long* endpts, unsigned long long* bitrate, int tssize)
1102{
1103        int ret = 0;
1104        unsigned long long start = 0, end = 0;
1105        off64_t startfindpos = 0, endfindpos = 0;
1106
1107        if(startpts != NULL && *startpts > 0) start = *startpts;
1108        if(endpts != NULL && *endpts > 0) end = *endpts;
1109
1110        if(start == 0 || (bitrate != NULL && bitrate == 0))
1111                ret = getpts(fd, 0, 0, 256 * 1024, &start, &startfindpos, 1, tssize);
1112
1113        if((ret == 0 && end == 0) || (bitrate != NULL && bitrate == 0))
1114                ret = getpts(fd, 0, 0, 256 * 1024, &end, &endfindpos, -1, tssize);
1115
1116        if(ret == 0)
1117        {
1118                end = fixuppts(start, end);
1119                if(lenpts != NULL) *lenpts = end - start;
1120                if(startpts != NULL) *startpts = start;
1121                if(endpts != NULL) *endpts = end;
1122                if(bitrate != NULL && *bitrate == 0) *bitrate = gettsbitrate(start, end, startfindpos, endfindpos);
1123        }
1124
1125        if(lenpts != NULL && *lenpts < 0) *lenpts = 0;
1126        if(startpts != NULL && *startpts < 0) *startpts = 0;
1127        if(endpts != NULL && *endpts < 0) *endpts = 0;
1128        return ret;
1129}
1130
1131int getptspos(int fd, off64_t startfind, unsigned long long* pts, off64_t* findpos, int dir, int tssize)
1132{
1133        int ret = 0;
1134        unsigned long long pts1 = 0;
1135        off64_t findpos1 = 0;
1136       
1137        ret = getpts(fd, startfind, 0, 256 * 1024, &pts1, &findpos1, dir, tssize);
1138        if(pts != NULL) *pts = pts1;
1139        if(findpos != NULL) *findpos = findpos1;
1140       
1141        return ret;             
1142}
1143
1144
1145//rc = 1 --> mpeg
1146//rc = 2 --> h.264
1147int findcodec(unsigned char* buf, int len, int tssize)
1148{
1149        int i,i1;
1150        int rc = 2;
1151       
1152        for(i = 0; i < len-tssize; i = i + tssize)
1153        {
1154                if((buf[i+1]&0x40)>>6 == 0x01)
1155                {
1156                        for(i1 = i+4; i1 < i + tssize-4; i1 = i1 + 1)
1157                        {
1158                                if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01 && buf[i1+3] == 0xB3)
1159                                {
1160                                        return 1;
1161                                }
1162                        }
1163                }
1164        }
1165        return rc;
1166}
1167
1168//flag=0 -> future use
1169//flag=1 -> I-Slice
1170//flag=2 -> ende Frame
1171int findframeHD(unsigned char* buf, int len, int start, int tssize, int flag)
1172{
1173        int position = -1;
1174        int i = 0;
1175        int i1 = 0;
1176
1177        len = start + len;
1178       
1179        while(1)
1180        {
1181                for(i = start; i < len-3; i = i + 1)
1182                {
1183                        //Picture header ?
1184                        if (buf[i] == 0x00 && buf[i+1] == 0x00 && buf[i+2] == 0x01)
1185                        {
1186                                //SPS (Sequence Parameter Set)?
1187                                if(buf[i+3] == 0x67 && flag == 1)
1188                                {
1189                                        //PPS (Picture Parameter Set) ?
1190                                        for(i1 = i + 4; i1 < (i % tssize) + i; i1 = i1 + 1)
1191                                        {
1192                                                if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01 && buf[i1+3] == 0x68)
1193                                                {
1194                                                        position = i1;
1195                                                        break;
1196                                                }
1197                                        }
1198                                        if(position != -1)
1199                                        {
1200                                                for(i1 = position + 4; i1 < (position % tssize) + position; i1 = i1 + 1)
1201                                                {
1202                                                        if (buf[i1] == 0x00 && buf[i1+1] == 0x00 && buf[i1+2] == 0x01)
1203                                                        {
1204                                                                if(buf[i1+3] == 0x01 || buf[i1+3] == 0x21 || buf[i1+3] == 0x41 || buf[i1+3] == 0x61)
1205                                                                {
1206                                                                        i = i1+4;
1207                                                                        position = -1;
1208                                                                        break;
1209                                                                }
1210                                                        }
1211                                                }
1212                                        }
1213                                        if(position != -1)
1214                                                break;                                 
1215                                }
1216                                //I-P-Slice oder I-P-B-Slice oder oder .....?
1217                                else if((buf[i+3] == 0x01 || buf[i+3] == 0x21 || buf[i+3] == 0x41 || buf[i+3] == 0x61) && flag == 2 )
1218                                {
1219                                  position = i;
1220                                        break;
1221                                }
1222                }
1223        }
1224        return position;
1225        }
1226}
1227
1228
1229//flag=0 -> Sequence header
1230//flag=1 -> I-Fame
1231//flag=2 -> ende Frame
1232int findframe(unsigned char* buf, int len, int start, int tssize, int flag)
1233{       
1234        //#define       SEQ_START_CODE          0x000001b3
1235        //#define GOP_START_CODE          0x000001b8
1236        //#define PICTURE_START_CODE      0x00000100
1237        //#define SLICE_START_CODE        0x00000101
1238        //#define PACK_START_CODE         0x000001ba
1239        //#define VIDEO_ID                0x000001e0
1240        //#define AUDIO_ID                0x000001c0
1241
1242       
1243        int position = -1;
1244        int i = 0;
1245
1246        len = start + len;
1247
1248        while(1) {
1249
1250                for(i = start; i < len-3; i = i + 1)
1251                {
1252
1253                        //Picture header ?
1254                        if (buf[i] == 0x00 && buf[i+1] == 0x00 && buf[i+2] == 0x01)
1255                        {
1256       
1257                                //Sequence header
1258                                if(buf[i+3] == 0xB3 && flag == 0)
1259                                {
1260                                        position = i;
1261                                        break;
1262                                }       
1263
1264                                //Picture-Frame ?
1265                                else if(buf[i+3] == 0x00)
1266                                {
1267
1268                                        //I-Frame ?
1269                                        if((buf[i+5] & 0x38)>>3 == 0x01 && flag == 1)
1270                                        {
1271                                          position = i;
1272                                                break;
1273                                        }
1274
1275                                        //other Frame ?
1276                                        else if((buf[i+5] & 0x38)>>3 != 0x00 && flag == 2)
1277                                        {
1278                                          position = i;
1279                                                break;
1280                                        }       
1281                                }
1282                }
1283        }
1284        return position;
1285        }
1286}
1287
1288int findandposrew(int fd, int tssize, int skip)
1289{
1290        int i;
1291        int ret = 0;
1292        int framelen = -1;
1293        off64_t endframe = -1;
1294        off64_t startframe = -1;
1295        int readret = 0;
1296        int codec = 0;
1297        int buflen = tssize * 15000;
1298        unsigned char* buf = malloc(buflen);
1299        off64_t currentpos;
1300        off64_t skippos;
1301       
1302        //ret = videostop(status.aktservice->videodev,0);
1303        //ret = videoclearbuffer(status.aktservice->videodev);
1304        //ret = audioclearbuffer(status.aktservice->audiodev);
1305        //ret = audiosetavsync(status.aktservice->audiodev, 0);
1306        //ret = audiosetmute(status.aktservice->audiodev, 1);
1307       
1308        currentpos = lseek64(fd, 0, SEEK_CUR);
1309        skippos = currentpos;
1310       
1311        while(1)
1312        {
1313                skippos = skippos - buflen;
1314                if(skippos < 0)
1315                {
1316                        currentpos = lseek64(fd, currentpos, SEEK_SET);
1317                        free(buf);
1318                        return -1;
1319                }
1320                skippos = lseek64(fd, skippos, SEEK_SET);
1321                readret = dvbreadfd(fd, buf, 0, buflen, 5000000, 1);
1322                if(readret > 0)
1323                {
1324                        codec = findcodec(buf, buflen, tssize);
1325                        for(i = readret - tssize; i >= 0; i = i - tssize)
1326                        {
1327                                if(codec == 1)
1328                                        ret = findframe(buf, tssize, i, tssize, 0);
1329                                else
1330                                        ret = findframeHD(buf, tssize, i, tssize, 1);
1331                                if(ret > -1)
1332                                {
1333                                        if(endframe == -1)
1334                                        {
1335                                                if(skip != 0)
1336                                                        skip = skip - 1;
1337                                                else
1338                                                        endframe = skippos + i;
1339                                        }
1340                                        else
1341                                        {
1342                                                startframe = skippos + i;
1343                                                framelen = endframe - startframe;
1344                                                currentpos = lseek64(fd, startframe, SEEK_SET);
1345                                                //readret = dvbreadfd(servicenode->recsrcfd, buf, 0, buflen, 5000000, 1);
1346                                                free(buf);
1347                                                return framelen;
1348                                        }
1349                                }
1350                        }
1351                }
1352                else
1353                {
1354                        currentpos = lseek64(fd, currentpos, SEEK_SET);
1355                        free(buf);
1356                        return -1;
1357                }
1358        }
1359}
1360
1361#endif
Note: See TracBrowser for help on using the repository browser.