source: titan/titan/dvb.h @ 42144

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

[titan] mutant fix DTSHD

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