source: titan/titan/dvb.h @ 39757

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

[titan] add H265_HEVC codec

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