source: titan/titan/dvb.h @ 39899

Last change on this file since 39899 was 39899, checked in by gost, 7 years ago

[titan] add new audio codec

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