source: titan/titan/player.h @ 30600

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

[tithek] mipsel add 10mb gst prefillbuffer without infos

File size: 53.9 KB
Line 
1#ifndef PLAYER_H
2#define PLAYER_H
3
4// playercan bits:
5// 0 policy
6// 1 auditraklist
7// 2 subtitle
8// 3 videomode
9// 4 powerofftimer
10// 5 videosettings
11// 6 stop
12// 7 ff
13// 8 fr
14// 9 pause
15// 10 play
16// 11 jump/seek reverse
17// 12 jump/seek forward
18// 13 changecodec
19// 14 infobar
20// 15 slowmotion
21
22#ifdef EPLAYER3
23Context_t * player = NULL;
24extern OutputHandler_t OutputHandler;
25extern PlaybackHandler_t PlaybackHandler;
26extern ContainerHandler_t ContainerHandler;
27extern ManagerHandler_t ManagerHandler;
28#endif
29
30#ifdef EPLAYER4
31GstElement *pipeline = NULL;
32unsigned long long m_gst_startpts = 0;
33#endif
34
35//titan player
36
37//flag 0: from play
38//flag 1: from timeshift
39//flag 2: from playrcjumpr
40int playerstartts(char* file, int flag)
41{
42        int fd = -1, ret = 0, tssize = 188;
43        int16_t pmtpid = 0;
44        int serviceid = 0;
45        int supermagic = -1;
46        int lastpos = 0;
47        struct channel* chnode = NULL;
48        struct service* snode = NULL;
49        struct dvbdev* fenode = NULL;
50        struct dvbdev* dvrnode = NULL;
51
52        //supermagic = getsupermagic(file);
53
54        if(supermagic == NFS_SUPER_MAGIC || supermagic == SMB_SUPER_MAGIC)
55        {
56                debug(150, "use O_DIRECT to open file %s", file);
57                fd = open(file, O_RDONLY | O_LARGEFILE | O_NONBLOCK | O_DIRECT);
58        }
59        else
60                fd = open(file, O_RDONLY | O_LARGEFILE | O_NONBLOCK);
61
62        if(fd < 0)
63        {
64                perr("open player file");
65                return 1;
66        }
67
68        fenode = fegetdummy();
69        dvrnode = dvropen(fenode);
70        if(dvrnode == NULL)
71        {
72                err("find dvr dev");
73                close(fd);
74                return 1;
75        }
76
77        if(flag == 0 || flag == 2)
78        {
79                //TODO: funktion to get tssize from file content
80                if(cmpfilenameext(file, ".mts") == 0) tssize = 192;
81                if(cmpfilenameext(file, ".m2ts") == 0) tssize = 192;
82               
83                ret = dvbfindpmtpid(fd, &pmtpid, &serviceid, tssize);
84                if(ret == 1)
85                {
86                        err("find sid/pmt pid");
87                        close(fd);
88                        dvrclose(dvrnode, -1);
89                        return 1;
90                }
91               
92                lastpos = 0;
93                if(flag == 0 && getconfigint("showlastpos", NULL) == 1)
94                {
95                        char* fileseek = changefilenameext(file, ".se");
96                        FILE* fbseek = fopen(fileseek, "r");
97                        if(fbseek != NULL)
98                        {
99                                ret = textbox(_("Message"), _("Start at last position ?"), _("OK"), getrcconfigint("rcok", NULL), _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, 600, 200, 10, 0);
100                                if(ret == 0 || ret == 1)
101                                {
102                                        char* skip1 = calloc(1, 20);
103                                        if(skip1 != NULL)
104                                        {
105                                                fscanf(fbseek, "%s", skip1);
106                                                off64_t seekpos = atoll(skip1);
107                                                seekpos = seekpos - (seekpos % tssize);
108                                                lseek64(fd, atoll(skip1), SEEK_SET);
109                                                lastpos = 1;
110                                        }
111                                        free(skip1); skip1 = NULL;
112                                }
113                                fclose(fbseek);
114                        }
115                        free(fileseek); fileseek = NULL;
116                }       
117               
118                status.autoseek = 0;
119               
120                if(flag == 0)
121                {
122                        delmarkernode(-1);
123                        char* filemarker = changefilenameext(file, ".ma");
124                        getmarker(filemarker);
125                        free(filemarker); filemarker=NULL;
126                }
127               
128                if(status.playmarker != NULL)
129                {
130                        char* testfile = changefilenameext(file, ".as");
131                        FILE* testseek = fopen(testfile, "r");
132                        if(testseek != NULL)
133                        {
134                                if(lastpos == 0)
135                                        lseek64(fd, status.playmarker->pos, SEEK_SET);
136                                status.autoseek = 2;
137                                addtimer(&markerautoseek_thread, START, 10000, 1, NULL, NULL, NULL);
138                                fclose(testseek);
139                        }
140                        free(testfile); testfile = NULL;
141                }
142                               
143                delchannel(serviceid, 0, 1);
144                chnode = createchannel("player", 0, 0, serviceid, 99, 0, -1, -1, -1, -1, 0, -1);
145                if(chnode != NULL) chnode->pmtpid = pmtpid;
146        }
147        else
148                chnode = status.aktservice->channel;
149
150        if(chnode == NULL)
151        {
152                err("create channel");
153                close(fd);
154                dvrclose(dvrnode, -1);
155                return 1;
156        }
157
158        if(flag == 1)
159        {
160                ret = servicestart(chnode, NULL, NULL, 2);
161                if(ret != 0)
162                {
163                        err("start play");
164                        close(fd);
165                        dvrclose(dvrnode, -1);
166                        return 1;
167                }
168               
169                //on permanent timeshift seek to end, and a little back (eof problem)
170                if(status.timeshifttype == 1)
171                {
172                        if(status.timeshiftpos > 0)
173                                lseek64(fd, status.timeshiftpos, SEEK_SET);
174                        else
175                        {
176                                unsigned long long pos = lseek64(fd, 0, SEEK_END);
177                                pos -= 10000000;
178                                pos = pos - (pos & tssize);
179                                lseek64(fd, -pos, SEEK_END);
180                        }
181                }
182        }
183
184        ret = recordstartreal(NULL, fd, dvrnode->fd, RECPLAY, 0, NULL, tssize);
185        if(ret != 0)
186        {
187                err("start play thread");
188                close(fd);
189                dvrclose(dvrnode, -1);
190                return 1;
191        }
192
193        snode = getservice(RECORDPLAY, 0);
194        if(snode != NULL)
195        {
196                int dupfd = -1;
197                snode->recname = ostrcat(file, NULL, 0, 0);
198
199                dupfd = open(snode->recname, O_RDONLY | O_LARGEFILE);
200                if(dupfd > -1)
201                        gettsinfo(dupfd, &snode->lenpts, &snode->startpts, &snode->endpts, &snode->bitrate, snode->tssize);
202
203                if(flag == 1)
204                {
205                        snode->lenpts = 0;
206                        snode->endpts = 0;
207                }
208                else
209                {
210                        if(getservicebyrecname(file, 1, 0) != NULL) //playfile is recording, so len can change
211                        {
212                                snode->lenpts = 0;
213                                snode->endpts = 0;
214                        }
215                        else if(dupfd > -1)
216                                snode->endoffile = lseek64(dupfd , 0, SEEK_END);
217                }
218                close(dupfd);
219        }
220
221        if(flag == 0 || flag == 2)
222        {
223                ret = servicestart(chnode, NULL, NULL, 1);
224                if(ret != 0)
225                {
226                        err("start play");
227                        if(snode != NULL) snode->recendtime = 1;
228                        close(fd);
229                        dvrclose(dvrnode, -1);
230                        return 1;
231                }
232                //status.playercan = 0x7EFF;
233                status.playercan = 0xFFFF;     
234        }
235
236        return 0;
237}
238
239//flag 0: from play
240//flag 1: from timeshift
241//flag 2: from playrcjumpr/playerafterendts
242//flag1 0: stop from rcstop
243//flag1 1: stop from servicestop
244void playerstopts(int flag, int flag1)
245{
246        int ret = 0;
247        struct service* snode = NULL;
248        struct channel* node = NULL;
249
250        snode = getservice(RECORDPLAY, flag1);
251
252        if(snode != NULL && snode->recsrcfd >= 0 && flag == 0 && flag1 == 0)
253        {
254                char* fileseek = changefilenameext(snode->recname, ".se");
255                FILE* fbseek = fopen(fileseek, "w");
256                if(fbseek != NULL)
257                {
258                        off64_t pos = getcurrentpos(snode);
259                        if(pos <= 0)
260                                pos = lseek64(snode->recsrcfd, 0, SEEK_CUR);
261                        fprintf(fbseek,"%lld", pos);
262                        fclose(fbseek);
263                }
264                free(fileseek); fileseek=NULL;
265                char* filemarker = changefilenameext(snode->recname, ".ma");
266                ret = putmarker(filemarker);
267                free(filemarker); filemarker=NULL;
268                delmarkernode(-1);
269        }
270       
271        if(snode != NULL) snode->recendtime = 1;
272       
273        if(flag == 0 || flag == 2)
274        {
275                playerslowts(0);
276                playerffts(0);
277
278                ret = servicestop(status.aktservice, 1, 1);
279                if(ret == 1)
280                {
281                        debug(150, "can't stop ts playback service");   
282                }
283                else
284                        status.aktservice->channel = NULL;
285
286                               
287                node = gettmpchannel();
288                if(node != NULL && ostrcmp(node->name, "player") == 0)
289                        delchannel(node->serviceid, node->transponderid, 1);
290        }
291}
292
293void playerresetts()
294{
295        audiostop(status.aktservice->audiodev);
296        videostop(status.aktservice->videodev, 0);
297#ifdef MIPSEL
298        videoclearbuffer(status.aktservice->videodev);
299        audioclearbuffer(status.aktservice->audiodev);
300#endif
301        videoplay(status.aktservice->videodev);
302        audioplay(status.aktservice->audiodev);
303}
304
305void playercontinuets()
306{
307        videocontinue(status.aktservice->videodev);
308        audioplay(status.aktservice->audiodev);
309}
310
311void playerpausets()
312{
313        videofreeze(status.aktservice->videodev);
314        audiopause(status.aktservice->audiodev);
315}
316
317//flag 0: with lock
318//flag 1: without lock
319int playerseekts(struct service* servicenode, int sekunden, int flag)
320{
321        off64_t offset = 0;
322        off64_t endoffile = 0;
323        off64_t currentpos = 0;
324        //off64_t fdptspos = 0;
325        //int ret = 0;
326        unsigned long long lenpts = 0;
327        unsigned long long startpts = 0;
328        unsigned long long endpts = 0;
329        unsigned long long bitrate = 0;
330        //unsigned long long aktpts = 0;
331        //unsigned long long fdpts = 0;
332        //int aktsekunden = 0;
333        int sekundenoff = 0;
334       
335        if(servicenode == NULL) return 1;
336
337        if(servicenode->recsrcfd < 0)
338        {
339                err("source fd not ok");
340                return 1;
341        }
342       
343        if(flag == 0) m_lock(&status.tsseekmutex, 15);
344
345/*
346        ret = videogetpts(status.aktservice->videodev, &aktpts);
347        if(ret == 0)
348        {
349                aktsekunden = aktpts / 90000;
350        }
351        else
352                aktsekunden = 0;
353        ret = getpts(servicenode->recsrcfd, 0, 0, 256 * 1024, &fdpts, &fdptspos, -1, servicenode->tssize);
354        if(ret == 0 && aktsekunden != 0)
355        {
356                sekundenoff = fdpts / 90000 - aktsekunden ;
357                //currentpos = lseek64(servicenode->recsrcfd, fdptspos, SEEK_SET);
358        }
359        else
360                sekundenoff = 0;
361*/
362       
363        currentpos = lseek64(servicenode->recsrcfd, 0, SEEK_CUR);
364
365        lenpts = servicenode->lenpts;
366        startpts = servicenode->startpts;
367        endpts = servicenode->endpts;
368        bitrate = servicenode->bitrate;
369        if(gettsinfo(servicenode->recsrcfd, &lenpts, &startpts, &endpts, &bitrate, servicenode->tssize) != 0)
370        {
371                err("can't read ts info");
372                lseek64(servicenode->recsrcfd, currentpos, SEEK_SET);
373                if(flag == 0) m_unlock(&status.tsseekmutex, 15);
374                return 1;
375        }
376        if(servicenode->endoffile > 0)
377                endoffile = servicenode->endoffile - (servicenode->tssize * 2);
378        else
379                endoffile = lseek64(servicenode->recsrcfd , -servicenode->tssize * 2, SEEK_END);
380
381/*
382        ret = videoclearbuffer(status.aktservice->videodev);
383        ret = audioclearbuffer(status.aktservice->audiodev);
384        ret = videodiscontinuityskip(status.aktservice->videodev, 0);
385*/
386
387        if(sekunden >= 0)
388        {
389                if(sekundenoff != 0)
390                        offset = (bitrate / 8) * (sekunden - sekundenoff);
391                else
392                        offset = (bitrate / 8) * sekunden - 5000000;
393                offset = offset - (offset % servicenode->tssize);
394                if(currentpos + offset > endoffile)
395                {
396                        offset = endoffile - currentpos;
397                        offset = offset - (offset % servicenode->tssize);
398                }
399        }
400        else
401        {
402                sekunden = sekunden * -1;
403                if(sekundenoff != 0)
404                        offset = (bitrate / 8) * (sekunden + sekundenoff);
405                else
406                        offset = (bitrate / 8) * sekunden;
407                if(offset > 0) offset += 5000000;
408                offset = offset - (offset % servicenode->tssize);
409                if(currentpos - offset < 0)
410                        offset = currentpos;
411                offset = offset * -1;
412        }
413        offset += currentpos;
414        currentpos = lseek64(servicenode->recsrcfd, offset, SEEK_SET);
415
416        playerresetts();
417
418        if(flag == 0) m_unlock(&status.tsseekmutex, 15);
419        return 0;
420}
421
422void playerffts(int speed)
423{
424#ifdef MIPSEL
425        audiostop(status.aktservice->audiodev);
426        videoslowmotion(status.aktservice->videodev, 0);
427        videofastforward(status.aktservice->videodev, speed);
428        videocontinue(status.aktservice->videodev);
429#else   
430        videofastforward(status.aktservice->videodev, speed);
431#endif
432}
433
434void playerslowts(int speed)
435{
436#ifdef MIPSEL
437        audiostop(status.aktservice->audiodev);
438        videoslowmotion(status.aktservice->videodev, speed);
439        videofastforward(status.aktservice->videodev, 0);
440        videocontinue(status.aktservice->videodev);
441#else           
442        videoslowmotion(status.aktservice->videodev, speed);
443#endif
444}
445
446//flag = 0 --> recordplay
447//flag = 1 --> timeshift
448void playerfrts(int speed, int flag)
449{
450        if(flag == 1)
451                videocontinue(status.aktservice->videodev);
452        if(speed == -2)
453        {
454                videoclearbuffer(status.aktservice->videodev);
455                audioclearbuffer(status.aktservice->audiodev);
456        }
457        speed *= -1;
458#ifdef MIPSEL
459        audiostop(status.aktservice->audiodev);
460        videoslowmotion(status.aktservice->videodev, 0);
461        videofastforward(status.aktservice->videodev, speed);
462        videocontinue(status.aktservice->videodev);
463#else   
464        videofastforward(status.aktservice->videodev, speed);
465#endif
466}
467       
468
469//flag = 0 --> play ts
470//flag = 1 --> timeshift
471//flag = 2 --> timeshift, not in play mode (only recording)
472int playergetinfots(unsigned long long* lenpts, unsigned long long* startpts, unsigned long long* endpts, unsigned long long* aktpts, unsigned long long* bitrate, int flag)
473{
474        int ret = 0, dupfd = -1;
475        double ratio = 0;
476        struct service* snode = NULL;
477        unsigned long long lenpts1 = 0;
478        unsigned long long startpts1 = 0;
479        unsigned long long endpts1 = 0;
480        unsigned long long bitrate1 = 0;
481        unsigned long long endoffile1 = 0;
482        unsigned long long aktpos = 0;
483       
484        if(flag == 2)
485                snode = getservice(RECORDTIMESHIFT, 0);
486        else
487                snode = getservice(RECORDPLAY, 0);
488               
489        if(snode == NULL) return 1;
490
491        if(snode->lenpts > 0 && snode->startpts > 0 && snode->endpts > 0 && snode->bitrate > 0 && snode->endoffile > 0)
492        {
493                if(lenpts != NULL) *lenpts = snode->lenpts;
494                if(startpts != NULL) *startpts = snode->startpts;
495                if(endpts != NULL) *endpts = snode->endpts;
496                if(bitrate != NULL) *bitrate = snode->bitrate;
497
498                //ret = videogetpts(status.aktservice->videodev, aktpts);
499                if(aktpts != NULL)
500                {
501                        m_lock(&status.tsseekmutex, 15);
502                        if(flag == 2)
503                                aktpos = lseek64(snode->recdstfd , 0, SEEK_CUR);
504                        else
505                                aktpos = lseek64(snode->recsrcfd , 0, SEEK_CUR);
506                        m_unlock(&status.tsseekmutex, 15);
507
508                        ratio = (double)snode->endoffile / (double)(snode->endpts - snode->startpts);
509                        if(ratio == 0) ratio = 1;
510                        *aktpts = ((double)aktpos / ratio);
511                        *aktpts += snode->startpts;
512                }
513
514                return ret;
515        }
516       
517        dupfd = open(snode->recname, O_RDONLY | O_LARGEFILE);
518        if(dupfd < 0)
519        {
520                err("copy source fd not ok");
521                return 1;
522        }
523
524        lenpts1 = snode->lenpts;
525        startpts1 = snode->startpts;
526        endpts1 = snode->endpts;
527        bitrate1 = snode->bitrate;
528        if(gettsinfo(dupfd, &lenpts1, &startpts1, &endpts1, &bitrate1, snode->tssize) != 0)
529        {
530                err("can't read ts info");
531                return 1;
532        }
533
534        if(lenpts != NULL) *lenpts = lenpts1;
535        if(startpts != NULL) *startpts = startpts1;
536        if(endpts != NULL) *endpts = endpts1;
537        if(bitrate != NULL) *bitrate = bitrate1;
538
539        //ret = videogetpts(status.aktservice->videodev, aktpts);
540        if(aktpts != NULL)
541        {
542                m_lock(&status.tsseekmutex, 15);
543                if(flag == 2)
544                        aktpos = lseek64(snode->recdstfd, 0, SEEK_CUR);
545                else
546                        aktpos = lseek64(snode->recsrcfd, 0, SEEK_CUR);
547                m_unlock(&status.tsseekmutex, 15);
548
549                if(snode->endoffile <= 0)
550                        endoffile1 = lseek64(dupfd, 0, SEEK_END);
551                else
552                        endoffile1 = snode->endoffile;
553
554                if(endpts1 == 0)
555                        ratio = 1;
556                else
557                        ratio = (double)endoffile1 / (double)(endpts1 - startpts1);
558
559                if(ratio == 0) ratio = 1;
560                *aktpts = ((double)aktpos / ratio);
561                *aktpts += startpts1;
562        }
563
564        close(dupfd);
565        return ret;
566}
567
568void playerchangeaudiotrackts()
569{
570        screenaudiotrack();
571}
572
573void playerchangesubtitletrackts()
574{
575        screensubtitle();
576}
577
578int playerisplayingts()
579{
580        struct service* snode = getservice(RECORDPLAY, 0);
581
582        if(snode == NULL)
583                return 0;
584        return 1;
585}
586
587void playerafterendts()
588{
589        playerstopts(2, 0);
590}
591
592typedef struct _CustomData {
593  gboolean is_live;
594  GstElement *pipeline;
595  GMainLoop *loop;
596} CustomData;
597
598CustomData data;
599
600//extern player
601int playerstart(char* file)
602{
603        char * tmpfile = NULL;
604       
605        if(file != NULL)
606        {
607#ifdef EPLAYER3
608                //use eplayer
609
610                if(player != NULL)
611                {
612                        debug(150, "eplayer allready running");
613                        playerstop();
614                }
615
616                player = calloc(1, sizeof(Context_t));
617
618                if(player == NULL)
619                {
620                        err("no mem");
621                        return 1;
622                }
623
624                if(ostrstr(file, "://") == NULL)
625                        tmpfile = ostrcat("file://", file, 0, 0);
626                else
627                        tmpfile = ostrcat(file, NULL, 0, 0);
628
629                if(tmpfile == NULL)
630                {
631                        err("no mem");
632                        free(player); player = NULL;
633                        return 1;
634                }
635// move to mc
636//              set_player_sound(0);
637
638                if(ostrstr(tmpfile, "file://") == NULL)
639                        status.playercan = 0x4650;
640                else
641                        status.playercan = 0xFFFF;
642               
643                player->playback = &PlaybackHandler;
644                player->output = &OutputHandler;
645                player->container = &ContainerHandler;
646                player->manager = &ManagerHandler;
647               
648                //add container befor open, so we can set buffer size
649                char* ext = getfilenameext(tmpfile);
650                if(ext != NULL)
651                {
652                        player->container->Command(player, CONTAINER_ADD, ext);
653                        free(ext); ext = NULL;
654                }
655
656                //select container_ffmpeg, if we does not found a container with extensions
657                if(player->container->selectedContainer == NULL)
658                        player->container->Command(player, CONTAINER_ADD, "mp3");
659
660                if(player && player->container && player->container->selectedContainer)
661                {
662                        int size = getconfigint("playerbuffersize", NULL);
663                        int seektime = getconfigint("playerbufferseektime", NULL);
664                        player->container->selectedContainer->Command(player, CONTAINER_SET_BUFFER_SIZE, (void*)&size);
665                        player->container->selectedContainer->Command(player, CONTAINER_SET_BUFFER_SEEK_TIME, (void*)&seektime);
666                }
667               
668                debug(150, "eplayername = %s", player->output->Name);
669
670                //Registrating output devices
671                player->output->Command(player, OUTPUT_ADD, "audio");
672                player->output->Command(player, OUTPUT_ADD, "video");
673                player->output->Command(player, OUTPUT_ADD, "subtitle");
674               
675                //for subtitle
676                SubtitleOutputDef_t subout;
677
678                subout.screen_width = skinfb->width;
679                subout.screen_height = skinfb->height;
680                subout.framebufferFD = skinfb->fd;
681                subout.destination = (uint32_t *)skinfb->fb;
682                subout.destStride = skinfb->pitch;
683                subout.shareFramebuffer = 1;
684                subout.framebufferBlit = blitfb1;
685
686                player->output->subtitle->Command(player, (OutputCmd_t)OUTPUT_SET_SUBTITLE_OUTPUT, (void*)&subout);
687               
688                if(player->playback->Command(player, PLAYBACK_OPEN, tmpfile) < 0)
689                {
690                        free(player); player = NULL;
691                        free(tmpfile);
692                        return 1;
693                }
694
695                player->output->Command(player, OUTPUT_OPEN, NULL);
696                player->playback->Command(player, PLAYBACK_PLAY, NULL);
697
698                free(tmpfile);
699
700                return 0;
701#endif
702
703#ifdef EPLAYER4
704                int flags = 0x47; //(GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT);
705               
706                if(pipeline != NULL)
707                {
708                        debug(150, "eplayer allready running");
709                        playerstop();
710                }
711               
712                if(ostrstr(file, "://") == NULL)
713                        tmpfile = ostrcat("file://", file, 0, 0);
714                else
715                        tmpfile = ostrcat(file, NULL, 0, 0);
716
717                if(tmpfile == NULL)
718                {
719                        err("no mem");
720                        free(pipeline); pipeline = NULL;
721                        return 1;
722                }
723
724                if(ostrstr(tmpfile, "file://") == NULL)
725                        status.playercan = 0x7E7F;
726                else
727                        status.playercan = 0x7E7F;
728       
729                pipeline = gst_element_factory_make("playbin2", "playbin");
730
731// enable buffersize start
732                int size = getconfigint("playerbuffersize", NULL);
733                printf("size: %d\n",size);
734               
735                if(size > 0)
736                        status.prefillbuffer = 1;
737
738                g_object_set(G_OBJECT(pipeline), "buffer-duration", size * GST_SECOND, NULL);
739                g_object_set(G_OBJECT(pipeline), "buffer-size", size, NULL);
740// enable buffersizeend
741
742                g_object_set(G_OBJECT(pipeline), "uri", tmpfile, NULL);
743                g_object_set(G_OBJECT(pipeline), "flags", flags, NULL);
744                free(tmpfile); tmpfile = NULL;
745
746///////////////////
747// srt subs start
748                const char *filename = file;
749                const char *ext = strrchr(filename, '.');
750                if (!ext)
751                        ext = filename + strlen(filename);
752
753                GstElement *subsink = gst_element_factory_make("subsink", "subtitle_sink");
754                if (!subsink)
755                        printf("sorry, can't play: missing gst-plugin-subsink\n");
756                else
757                {
758//                      m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this);
759                        g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-raw; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs"), NULL);
760                        g_object_set (G_OBJECT (pipeline), "text-sink", subsink, NULL);
761                        g_object_set (G_OBJECT (pipeline), "current-text", -1, NULL);
762                }
763
764                GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
765#if GST_VERSION_MAJOR < 1
766//              gst_bus_set_sync_handler(bus, gstBusSyncHandler, this);
767                gst_bus_set_sync_handler(bus, NULL, NULL);
768#else
769//              gst_bus_set_sync_handler(bus, gstBusSyncHandler, this, NULL);
770                gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
771#endif
772
773                gst_object_unref(bus);
774                char srt_filename[ext - filename + 5];
775                strncpy(srt_filename,filename, ext - filename);
776                srt_filename[ext - filename] = '\0';
777                strcat(srt_filename, ".srt");
778
779                if(access(srt_filename, R_OK) >= 0)
780                {
781                        printf("found srt1: %s\n",srt_filename);
782                        printf("found srt2: %s\n",g_filename_to_uri(srt_filename, NULL, NULL));
783                        g_object_set(G_OBJECT (pipeline), "suburi", g_filename_to_uri(srt_filename, NULL, NULL), NULL);         
784                }
785// srt end     
786
787///////////////////
788//              CustomData data;
789                memset (&data, 0, sizeof (data));
790                data.pipeline = pipeline;
791//              GstBus *bus;
792//              bus = gst_element_get_bus (pipeline);
793               
794                // Start playing //
795                GstStateChangeReturn ret;
796                ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
797                if(ret == GST_STATE_CHANGE_FAILURE)
798                {
799                        g_printerr ("Unable to set the pipeline to the playing state.\n");
800                        gst_object_unref (pipeline);
801                        return -1;
802                }
803                else if(ret == GST_STATE_CHANGE_NO_PREROLL)
804                {
805                        data.is_live = TRUE;
806                }
807
808                data.loop = g_main_loop_new (NULL, FALSE);
809                data.pipeline = pipeline;
810                gst_bus_add_signal_watch (bus);
811//              g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data);
812//              status.prefillbuffer = 1;
813
814                int count = 0;
815                m_gst_startpts = 0;
816                while(m_gst_startpts == 0 && count < 5)
817                {
818                        count++;
819                        sleep(1);
820                        m_gst_startpts = playergetpts();
821                }
822
823                return 0;
824#endif
825        }
826       
827        return 1;
828}
829
830
831#ifdef EPLAYER4
832int setBufferSize(int size)
833{
834        int m_buffer_size = size;
835        g_object_set (G_OBJECT (pipeline), "buffer-size", m_buffer_size, NULL);
836        return 0;
837}
838#endif
839
840void playerinit(int argc, char* argv[])
841{
842#ifdef EPLAYER4
843        gst_init(&argc, &argv);
844#endif
845}
846
847#ifdef EPLAYER4
848int gstbuscall(GstBus *bus, GstMessage *msg, CustomData *data)
849{
850
851        int ret = 1;
852        if(!pipeline) return 0;
853        if(!msg) return ret;
854
855        gchar *sourceName = NULL;
856        GstObject *source = GST_MESSAGE_SRC(msg);
857
858        if(!GST_IS_OBJECT(source)) return ret;
859        sourceName = gst_object_get_name(source);
860
861        switch(GST_MESSAGE_TYPE(msg))
862        {
863                case GST_MESSAGE_EOS:
864                        debug(150, "gst player eof");
865                        ret = 0;
866                        break;
867                case GST_MESSAGE_STATE_CHANGED:
868                        if(GST_MESSAGE_SRC(msg) != GST_OBJECT(pipeline))
869                                break;
870
871                        GstState old_state, new_state;
872                        gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
873               
874                        if(old_state == new_state) break;
875       
876                        debug(150, "gst state change %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
877       
878                        GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state);
879       
880                        switch(transition)
881                        {
882                                case GST_STATE_CHANGE_NULL_TO_READY:
883                                        break;
884                                case GST_STATE_CHANGE_READY_TO_PAUSED:
885/*
886                                        GstElement *appsink = gst_bin_get_by_name(GST_BIN(pipeline), "subtitle_sink");
887                                        if(appsink)
888                                        {
889                                                g_object_set(G_OBJECT(appsink), "max-buffers", 2, NULL);
890                                                g_object_set(G_OBJECT(appsink), "sync", FALSE, NULL);
891                                                g_object_set(G_OBJECT(appsink), "emit-signals", TRUE, NULL);
892                                                gst_object_unref(appsink);
893                                        }
894*/
895                                        break;
896                                case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
897                                        //if(m_sourceinfo.is_streaming && m_streamingsrc_timeout )
898                                                //m_streamingsrc_timeout->stop();
899                                        break;
900                                case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
901                                        break;
902                                case GST_STATE_CHANGE_PAUSED_TO_READY:
903                                        break;
904                                case GST_STATE_CHANGE_READY_TO_NULL:
905                                        ret = 0;
906                                        break;
907                        }
908                        break;
909                case GST_MESSAGE_ERROR:
910                        debug(150, "gst player error");
911
912                        gchar *gdebug1;
913                        GError *err;
914
915                        gst_message_parse_error(msg, &err, &gdebug1);
916                        g_free(gdebug1);
917
918                        debug(150, "gst error: %s (%i) from %s", err->message, err->code, sourceName);
919                        if(err->domain == GST_STREAM_ERROR)
920                        {
921                                if(err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND )
922                                {
923                                        //if(g_strrstr(sourceName, "videosink"))
924                                        //      m_event((iPlayableService*)this, evUser+11);
925                                        //else if ( g_strrstr(sourceName, "audiosink") )
926                                        //      m_event((iPlayableService*)this, evUser+10);
927                                }
928                        }
929                        g_error_free(err);
930                        break;
931                case GST_MESSAGE_INFO:
932                        debug(150, "gst player info");
933
934/*
935                        gchar *gdebug2;
936                        GError *inf;
937       
938                        gst_message_parse_info(msg, &inf, &gdebug2);
939                        g_free(gdebug2);
940                        if(inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE )
941                        {
942                                //if(g_strrstr(sourceName, "videosink"))
943                                //      m_event((iPlayableService*)this, evUser+14);
944                        }
945                        g_error_free(inf);
946*/
947                        break;
948                case GST_MESSAGE_TAG:
949                        debug(150, "gst player tag");
950                        break;
951                //case GST_MESSAGE_ASYNC_DONE:
952                //      debug(150, "gst player async done");
953                //      break;
954                case GST_MESSAGE_ELEMENT:
955                        debug(150, "gst player element");
956                        break;
957                case GST_MESSAGE_BUFFERING:
958                        debug(150, "gst player buffering");
959
960/*
961                        GstBufferingMode mode;
962                        gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
963                        gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
964                        //m_event((iPlayableService*)this, evBuffering);
965*/
966
967//debug(10, "gst player buffering");
968                        if(status.prefillbuffer == 1)
969                        {
970
971                                gint percent = 0;
972                                if (data->is_live) break;
973                                gst_message_parse_buffering (msg, &percent);
974                                g_print ("Buffering (%3d%%)\r", percent);
975                                if (percent < 100)
976                                {
977                                        gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
978                                }
979                                else
980                                {
981                                        gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
982                                        status.prefillbuffer = 0;
983                                }
984                        }
985                        break;
986
987/*
988                        GstBufferingMode mode;
989                        gst_message_parse_buffering(msg, &(status.bufferpercent));
990                        gst_message_parse_buffering_stats(msg, &mode, &(status.avgInRate), &(status.avgOutRate), &(status.bufferingLeft));
991
992//                      printf("#########################################################\n");
993//                      printf("Buffering %u percent done\n", status.bufferpercent);
994//                      printf("avgInRate %d\n", status.avgInRate);
995//                      printf("avgOutRate %d\n", status.avgOutRate);
996//                      printf("bufferingLeft %lld\n", status.bufferingLeft);
997                                       
998                        if(status.prefillbuffer == 1)
999                        {
1000                                printf("status.prefillbuffer Buffering %u percent done\n", status.bufferpercent);
1001
1002                                if (status.bufferpercent == 100)
1003                                {
1004                                        GstState state;
1005                                        gst_element_get_state(pipeline, &state, NULL, 0LL);
1006                                        if (state != GST_STATE_PLAYING)
1007                                        {
1008                                                // eDebug("start playing");
1009                                                gst_element_set_state (pipeline, GST_STATE_PLAYING);
1010                                        }
1011//                                      m_ignore_buffering_messages = 5;
1012                                        status.prefillbuffer = 0;
1013                                }
1014                                else if (status.bufferpercent == 0)
1015                                {
1016                                        // eDebug("start pause");
1017                                        gst_element_set_state (pipeline, GST_STATE_PAUSED);
1018//                                      m_ignore_buffering_messages = 0;
1019                                }
1020                        }
1021*/
1022/*
1023                                GstBufferingMode mode;
1024                                printf("GST_STATE_PAUSED\n");
1025                                gst_element_set_state (pipeline, GST_STATE_PAUSED);
1026
1027
1028                                gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
1029                                // eDebug("Buffering %u percent done", m_bufferInfo.bufferPercent);
1030                                gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
1031                                m_event((iPlayableService*)this, evBuffering);
1032                                if (m_use_prefillbuffer && !m_is_live && --m_ignore_buffering_messages <= 0)
1033                                {
1034                                        if (m_bufferInfo.bufferPercent == 100)
1035                                        {
1036                                                GstState state;
1037                                                gst_element_get_state(pipeline, &state, NULL, 0LL);
1038                                                if (state != GST_STATE_PLAYING)
1039                                                {
1040                                                        // eDebug("start playing");
1041                                                        gst_element_set_state (pipeline, GST_STATE_PLAYING);
1042                                                }
1043                                                m_ignore_buffering_messages = 5;
1044                                        }
1045                                        else if (m_bufferInfo.bufferPercent == 0)
1046                                        {
1047                                                // eDebug("start pause");
1048                                                gst_element_set_state (pipeline, GST_STATE_PAUSED);
1049                                                m_ignore_buffering_messages = 0;
1050                                        }
1051                                        else
1052                                        {
1053                                                m_ignore_buffering_messages = 0;
1054                                        }
1055                                }
1056
1057*/
1058                        break;
1059                case GST_MESSAGE_STREAM_STATUS:
1060                        debug(150, "gst player stream status");
1061
1062/*
1063                        GstStreamStatusType type;
1064                        GstElement *owner;
1065
1066                        gst_message_parse_stream_status(msg, &type, &owner);
1067                        if(type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming)
1068                        {
1069                                if(GST_IS_PAD(source))
1070                                        owner = gst_pad_get_parent_element(GST_PAD(source));
1071                                else if(GST_IS_ELEMENT(source))
1072                                        owner = GST_ELEMENT(source);
1073                                else
1074                                        owner = NULL;
1075                                if(owner)
1076                                {
1077                                        GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner));
1078                                        const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
1079                                        if (!strcmp(name, "souphttpsrc"))
1080                                        {
1081                                                //m_streamingsrc_timeout->start(10 * 1000, true);
1082                                                g_object_set(G_OBJECT(owner), "timeout", 10, NULL);
1083                                        }
1084                                       
1085                                }
1086                                if(GST_IS_PAD(source))
1087                                        gst_object_unref(owner);
1088                        }
1089*/
1090                        break;
1091                default:
1092                        debug(150, "gst player unknown message");
1093                        break;
1094        }
1095        g_free(sourceName);
1096        return ret;
1097}
1098#endif
1099
1100int playergetbuffersize()
1101{
1102        int ret = 0;
1103
1104#ifdef EPLAYER3
1105        if(player && player->container && player->container->selectedContainer)
1106                player->container->selectedContainer->Command(player, CONTAINER_GET_BUFFER_SIZE, (void*)&ret);
1107#endif
1108
1109        return ret;
1110}
1111
1112int playergetbufferstatus()
1113{
1114        int ret = 0;
1115
1116#ifdef EPLAYER3
1117        if(player && player->container && player->container->selectedContainer)
1118                player->container->selectedContainer->Command(player, CONTAINER_GET_BUFFER_STATUS, (void*)&ret);
1119#endif
1120
1121        return ret;
1122}
1123
1124int playerstopbuffer()
1125{
1126        int ret = 0;
1127
1128#ifdef EPLAYER3
1129        if(player && player->container && player->container->selectedContainer)
1130                player->container->selectedContainer->Command(player, CONTAINER_STOP_BUFFER, NULL);
1131#endif
1132
1133        return ret;
1134}
1135
1136int playerisplaying()
1137{
1138#ifdef SIMULATE
1139        return 1;
1140#endif
1141
1142#ifdef EPLAYER3
1143        if(player != NULL && player->playback != NULL && player->playback->isPlaying)
1144                return 1;
1145#endif
1146
1147#ifdef EPLAYER4
1148        int ret = 1;
1149
1150        if(pipeline)
1151        {
1152                GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
1153                GstMessage *message = NULL;
1154//use global variale, with static var crash
1155//              CustomData *data = NULL;
1156                while((message = gst_bus_pop(bus)))
1157                {
1158                        ret = gstbuscall(bus, message, &data);
1159                        gst_message_unref(message);
1160                }
1161        }
1162        else
1163                ret = 0;
1164
1165        return ret;
1166#endif
1167        return 0;
1168}
1169
1170void playerplay()
1171{
1172#ifdef EPLAYER3
1173        if(player && player->playback)
1174                player->playback->Command(player, PLAYBACK_PLAY, NULL);
1175#endif
1176
1177#ifdef EPLAYER4
1178        if(pipeline)
1179                gst_element_set_state(pipeline, GST_STATE_PLAYING);
1180#endif
1181}
1182
1183int playerstop()
1184{
1185#ifdef EPLAYER3
1186        if(player && player->playback)
1187                player->playback->Command(player, PLAYBACK_STOP, NULL);
1188        if(player && player->container && player->container->selectedContainer)
1189                player->container->selectedContainer->Command(player, CONTAINER_STOP, NULL);
1190        if(player && player->output)
1191        {
1192                player->output->Command(player, OUTPUT_CLOSE, NULL);
1193                player->output->Command(player, OUTPUT_DEL, (void*)"audio");
1194                player->output->Command(player, OUTPUT_DEL, (void*)"video");
1195                player->output->Command(player, OUTPUT_DEL, (void*)"subtitle");
1196        }
1197        if(player && player->playback)
1198                player->playback->Command(player, PLAYBACK_CLOSE, NULL);
1199
1200        free(player);
1201        player = NULL;
1202// move to mc
1203//      set_player_sound(1);
1204#endif
1205
1206#ifdef EPLAYER4
1207        if(pipeline)
1208        {
1209                gst_element_set_state(pipeline, GST_STATE_NULL);
1210                gst_object_unref(GST_OBJECT(pipeline));
1211                pipeline = NULL;
1212        }
1213#endif
1214
1215        writesysint("/proc/sys/vm/drop_caches", 3, 0);
1216        return 0;
1217}
1218
1219void playerafterend()
1220{
1221#ifdef EPLAYER3
1222        if(player != NULL && player->playback != NULL)
1223                playerstop();
1224#endif
1225
1226#ifdef EPLAYER4
1227        if(pipeline)
1228                playerstop();
1229#endif
1230}
1231
1232void playerpause()
1233{
1234#ifdef EPLAYER3
1235        if(player && player->playback)
1236                player->playback->Command(player, PLAYBACK_PAUSE, NULL);
1237#endif
1238
1239#ifdef EPLAYER4
1240        if(pipeline)
1241                gst_element_set_state(pipeline, GST_STATE_PAUSED);
1242#endif
1243}
1244
1245void playercontinue()
1246{
1247#ifdef EPLAYER3
1248        if(player && player->playback)
1249                player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
1250#endif
1251
1252#ifdef EPLAYER4
1253        if(pipeline)
1254                gst_element_set_state(pipeline, GST_STATE_PLAYING);
1255#endif
1256}
1257
1258void playerff(int speed)
1259{
1260#ifdef EPLAYER3
1261        int speedmap = 0;
1262
1263        if (speed < 1) speed = 1;
1264        if (speed > 7) speed = 7;
1265
1266        switch(speed)
1267        {
1268                case 1: speedmap = 1; break;
1269                case 2: speedmap = 3; break;
1270                case 3: speedmap = 7; break;
1271                case 4: speedmap = 15; break;
1272                case 5: speedmap = 31; break;
1273                case 6: speedmap = 63; break;
1274                case 7: speedmap = 127; break;
1275        }
1276
1277        if(player && player->playback)
1278                player->playback->Command(player, PLAYBACK_FASTFORWARD, &speedmap);
1279#endif
1280}
1281
1282void playerslow(int speed)
1283{
1284#ifdef EPLAYER3
1285        int speedmap = 0;
1286
1287        if (speed < 1) speed = 1;
1288        if (speed > 7) speed = 7;
1289
1290        switch(speed)
1291        {
1292                case 1: speedmap = 1; break;
1293                case 2: speedmap = 3; break;
1294                case 3: speedmap = 7; break;
1295                case 4: speedmap = 15; break;
1296                case 5: speedmap = 31; break;
1297                case 6: speedmap = 63; break;
1298                case 7: speedmap = 127; break;
1299        }
1300
1301        if(player && player->playback)
1302                player->playback->Command(player, PLAYBACK_SLOWMOTION, &speedmap);
1303#endif
1304}
1305
1306void playerfr(int speed)
1307{
1308#ifdef EPLAYER3
1309        int speedmap = 0;
1310
1311        if (speed > -1) speed = -1;
1312        if (speed < -7) speed = -7;
1313
1314        switch(speed)
1315        {
1316                case -1: speedmap = -5; break;
1317                case -2: speedmap = -10; break;
1318                case -3: speedmap = -20; break;
1319                case -4: speedmap = -40; break;
1320                case -5: speedmap = -80; break;
1321                case -6: speedmap = -160; break;
1322                case -7: speedmap = -320; break;
1323        }
1324
1325        if(player && player->playback)
1326                player->playback->Command(player, PLAYBACK_FASTBACKWARD, &speedmap);
1327#endif
1328}
1329
1330void playerseek(float sec)
1331{
1332#ifdef EPLAYER3
1333        if(player && player->playback)
1334                player->playback->Command(player, PLAYBACK_SEEK, (void*)&sec);
1335#endif
1336
1337#ifdef EPLAYER4
1338        gint64 nanos_pts = 0, nanos_len = 0;
1339        gint64 pts = 0, len = 0;
1340        //GstFormat fmt = GST_FORMAT_TIME;
1341               
1342        if(pipeline)
1343        {
1344                len = playergetlength();
1345                nanos_len = len * 1000000000;
1346                if(nanos_len < 0) nanos_len = 0;
1347
1348                pts = playergetpts();
1349                nanos_pts = pts * 11111;
1350                nanos_pts = nanos_pts + (sec * 1000000000);
1351                if(nanos_pts < 0) nanos_pts = 0;
1352
1353                if(nanos_pts >= nanos_len)
1354                        playerstop();
1355                else
1356                        gst_element_seek(pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, nanos_pts, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1357        }
1358#endif
1359}
1360
1361typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC, atWMA } audiotype_t;
1362
1363audiotype_t gstCheckAudioPad(GstStructure* structure)
1364{
1365        if (!structure)
1366                return atUnknown;
1367
1368        if ( gst_structure_has_name (structure, "audio/mpeg"))
1369        {
1370                gint mpegversion, layer = -1;
1371                if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
1372                        return atUnknown;
1373
1374                switch (mpegversion) {
1375                        case 1:
1376                                {
1377                                        gst_structure_get_int (structure, "layer", &layer);
1378                                        if ( layer == 3 )
1379                                                return atMP3;
1380                                        else
1381                                                return atMPEG;
1382                                        break;
1383                                }
1384                        case 2:
1385                                return atAAC;
1386                        case 4:
1387                                return atAAC;
1388                        default:
1389                                return atUnknown;
1390                }
1391        }
1392
1393        else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") )
1394                return atAC3;
1395        else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") )
1396                return atDTS;
1397#if GST_VERSION_MAJOR < 1
1398        else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
1399#else
1400        else if ( gst_structure_has_name (structure, "audio/x-raw") )
1401#endif
1402                return atPCM;
1403
1404        return atUnknown;
1405}
1406
1407void playerfreetracklist(char** TrackList)
1408{
1409        int i = 0;
1410
1411        if(TrackList != NULL)
1412        {
1413                while(TrackList[i] != NULL)
1414                {
1415                        free(TrackList[i]);
1416                        free(TrackList[i + 1]);
1417                        i += 2;
1418                }
1419        }
1420}
1421
1422char** playergettracklist(int type)
1423{
1424        char ** TrackList = NULL;
1425#ifdef EPLAYER3
1426        if(player && player->manager)
1427        {
1428                switch(type)
1429                {
1430                        case 1:
1431                                if(player->manager->audio)
1432                                {
1433                                        player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
1434                                        debug(150, "Audio Track List");
1435                                }
1436                                break;
1437                        case 2:
1438                                if(player->manager->subtitle)
1439                                {
1440                                        player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList);
1441                                        debug(150, "Subtitle Track List");
1442                                }
1443                                break;
1444                        default:
1445                                if(player->manager->video)
1446                                {
1447                                        player->manager->video->Command(player, MANAGER_LIST, &TrackList);
1448                                        debug(150, "Video Track List");
1449                                }
1450                }
1451               
1452                int i = 0;
1453                if(TrackList != NULL)
1454                {
1455                        while(TrackList[i] != NULL)
1456                        {
1457                                string_newline(TrackList[i]);
1458                                i += 2;
1459                        }
1460                       
1461                        debug(150, "Track List");
1462                        i = 0;
1463                        while(TrackList[i] != NULL)
1464                        {
1465                                debug(150, "%s - %s", TrackList[i], TrackList[i + 1]);
1466                                i += 2;
1467                        }
1468                }
1469        }
1470#endif
1471
1472//////////////////////////////NEUER CODE //////////////////////////////
1473#ifdef EPLAYER4
1474        //char ** tmpTrackList[2][100];
1475        TrackList = calloc(1, sizeof(char *) * ((100 * 2) + 1));
1476        //TrackList = tmpTrackList;
1477       
1478        if(pipeline != NULL)
1479        {
1480                gint i, n_video = 0, n_audio = 0, n_text = 0;
1481               
1482                g_object_get(pipeline, "n-video", &n_video, NULL);
1483                g_object_get(pipeline, "n-audio", &n_audio, NULL);
1484                g_object_get(pipeline, "n-text", &n_text, NULL);
1485               
1486                switch(type)
1487                {
1488                        case 1:
1489                                for(i = 0; i < n_audio; i++)
1490                                {
1491                                        GstTagList *tags = NULL;
1492                                        gchar *g_codec = NULL, *g_lang = NULL;
1493                                        char* tmpstr = NULL;
1494                                        GstPad* pad = 0;
1495                                       
1496                                        g_signal_emit_by_name (pipeline, "get-audio-pad", i, &pad);
1497#if GST_VERSION_MAJOR < 1
1498                                        GstCaps* caps = gst_pad_get_negotiated_caps(pad);
1499#else
1500                                        GstCaps* caps = gst_pad_get_current_caps(pad);
1501#endif
1502                                        if(!caps)
1503                                                continue;
1504                                       
1505                                        GstStructure* str = gst_caps_get_structure(caps, 0);
1506                                        const gchar *g_type = gst_structure_get_name(str);
1507
1508                                        g_signal_emit_by_name(pipeline, "get-audio-tags", i, &tags);
1509
1510#if GST_VERSION_MAJOR < 1
1511                                        if(tags && gst_is_tag_list(tags))
1512#else
1513                                        if(tags && GST_IS_TAG_LIST(tags))
1514#endif
1515                                        {
1516                                                if(gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec))
1517                                                {
1518                                                        printf("Audio Codec: %s\n", g_codec);
1519
1520                                                        tmpstr = ostrcat(g_codec, NULL, 0, 0);
1521                                                        if(tmpstr != NULL)
1522                                                                tmpstr = ostrcat(tmpstr, " (", 1, 0);
1523                                                        tmpstr = ostrcat(tmpstr, (gchar*)g_type, 1, 0);
1524                                                        if(g_codec != NULL)
1525                                                                tmpstr = ostrcat(tmpstr, ")", 1, 0);
1526
1527                                                        TrackList[i * 2] = ostrcat(tmpstr, NULL, 0, 0);
1528                                                        g_free(tmpstr); tmpstr = NULL;
1529                                                        g_free(g_codec); g_codec = NULL;
1530                                                }
1531                                                if(gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
1532                                                {
1533                                                        printf("Audio Lang: %s\n", g_lang);
1534                                                        TrackList[(i * 2) + 1] = ostrcat(g_lang, NULL, 0, 0);
1535                                                        g_free(g_lang); g_lang = NULL;
1536                                                }
1537                                                gst_tag_list_free(tags);
1538                                        }
1539                                        else
1540                                        {
1541                                                printf("Audio Codec: %s\n", g_codec);
1542                                               
1543                                                tmpstr = ostrcat(g_codec, NULL, 0, 0);
1544                                                if(tmpstr != NULL)
1545                                                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
1546                                                tmpstr = ostrcat(tmpstr, (gchar*)g_type, 1, 0);
1547                                                if(g_codec != NULL)
1548                                                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
1549                                                               
1550                                                TrackList[i * 2] = ostrcat(tmpstr, NULL, 0, 0);
1551
1552                                                g_free(tmpstr); tmpstr = NULL;
1553                                                g_free(g_codec); g_codec = NULL;
1554                                        }
1555                                }
1556                                break;
1557                        case 2:
1558                                for(i = 0; i < n_text; i++)
1559                                {
1560                                        GstTagList *tags = NULL;
1561                                        gchar *g_codec = NULL, *g_lang = NULL;
1562//                                      GstPad* pad = 0;
1563                               
1564                                        g_signal_emit_by_name(pipeline, "get-text-tags", i, &tags);
1565                                       
1566#if GST_VERSION_MAJOR < 1
1567                                        if (tags && gst_is_tag_list(tags))
1568#else
1569                                        if (tags && GST_IS_TAG_LIST(tags))
1570#endif
1571                                        {
1572                                                if(gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec));
1573                                                {
1574                                                        printf("SubTitle Codec: %s\n", g_codec);
1575                                                        TrackList[i * 2] = ostrcat(g_codec, NULL, 0, 0);
1576                                                        g_free(g_codec); g_codec = NULL;
1577                                                }
1578                                                if(gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
1579                                                {
1580                                                        printf("SubTitle Lang: %s\n", g_lang);
1581                                                        TrackList[(i * 2) + 1] = ostrcat(g_lang, NULL, 0, 0);
1582                                                        g_free(g_lang); g_lang = NULL;
1583                                                }
1584                                                gst_tag_list_free(tags);
1585                                        }
1586/*
1587                                        g_signal_emit_by_name(pipeline, "get-text-pad", i, &pad);
1588                                        if(pad)
1589                                                g_signal_connect(G_OBJECT(pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this);
1590
1591                                        printf("getSubtitleType: %d\n", getSubtitleType(pad, g_codec));
1592*/
1593                                }
1594                                break;
1595                        default:
1596                                for(i = 0; i < n_video; i++)
1597                                {
1598                                        GstTagList *tags = NULL;
1599                                        gchar *g_codec = NULL, *g_lang = NULL;
1600                                       
1601                                        g_signal_emit_by_name(pipeline, "get-video-tags", i, &tags);
1602                                       
1603#if GST_VERSION_MAJOR < 1
1604                                        if (tags && gst_is_tag_list(tags))
1605#else
1606                                        if (tags && GST_IS_TAG_LIST(tags))
1607#endif
1608                                        {
1609                                                if(gst_tag_list_get_string(tags, GST_TAG_VIDEO_CODEC, &g_codec));
1610                                                {
1611                                                        printf("Video Codec: %s\n", g_codec);
1612                                                        TrackList[i * 2] = ostrcat(g_codec, NULL, 0, 0);
1613                                                        g_free(g_codec); g_codec = NULL;
1614                                                }
1615                                                if(gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
1616                                                {
1617                                                        printf("Video Lang: %s\n", g_lang);
1618                                                        TrackList[(i * 2) + 1] = ostrcat(g_lang, NULL, 0, 0);
1619                                                        g_free(g_lang); g_lang = NULL;
1620                                                }
1621                                                gst_tag_list_free(tags);
1622                                        }
1623                                }
1624                }
1625        }
1626#endif
1627//////////////////////////////NEUER CODE //////////////////////////////
1628
1629        return TrackList;
1630}
1631
1632//*CurTrackEncoding and *CurTrackName be freed
1633void playergetcurtrac(int type, int *CurTrackId, char** CurTrackEncoding, char** CurTrackName)
1634{
1635#ifdef EPLAYER3
1636        if(player && player->manager)
1637        {
1638                switch(type)
1639                {
1640                        case 1:
1641                                if(player->manager->audio)
1642                                {
1643                                        player->manager->audio->Command(player, MANAGER_GET, CurTrackId);
1644                                        player->manager->audio->Command(player, MANAGER_GETENCODING, CurTrackEncoding);
1645                                        player->manager->audio->Command(player, MANAGER_GETNAME, CurTrackName);
1646                                }
1647                                break;
1648                        case 2:
1649                                if(player->manager->subtitle)
1650                                {
1651                                        player->manager->subtitle->Command(player, MANAGER_GET, CurTrackId);
1652                                        player->manager->subtitle->Command(player, MANAGER_GETENCODING, CurTrackEncoding);
1653                                        player->manager->subtitle->Command(player, MANAGER_GETNAME, CurTrackName);
1654                                }
1655                                break;
1656                        default:
1657                                if(player->manager->video)
1658                                {
1659                                        player->manager->video->Command(player, MANAGER_GET, CurTrackId);
1660                                        player->manager->video->Command(player, MANAGER_GETENCODING, CurTrackEncoding);
1661                                        player->manager->video->Command(player, MANAGER_GETNAME, CurTrackName);
1662                                }
1663                }
1664
1665                if(CurTrackId != NULL)
1666                        debug(150, "Current Track ID: %d", *CurTrackId);
1667                if(*CurTrackEncoding != NULL)
1668                        debug(150, "Current Track Enc: %s", *CurTrackEncoding);
1669                if(*CurTrackName != NULL)
1670                        debug(150, "Current Track Name: %s", *CurTrackName);
1671        }
1672#endif
1673
1674#ifdef EPLAYER4
1675        if(pipeline != NULL)
1676        {
1677                switch(type)
1678                {
1679                        case 1:
1680                                g_object_get(G_OBJECT(pipeline), "current-audio", CurTrackId, NULL);
1681                                break;
1682                }
1683               
1684                if(CurTrackId != NULL)
1685                        debug(150, "Current Track ID: %d", *CurTrackId);
1686        }
1687#endif
1688}
1689
1690unsigned long long playergetpts()
1691{
1692        unsigned long long pts = 0;
1693        unsigned long long sec = 0;
1694
1695#ifdef EPLAYER3
1696        if(player && player->playback)
1697        {
1698                player->playback->Command(player, PLAYBACK_PTS, &pts);
1699                sec = pts / 90000;
1700                debug(150, "Pts = %02d:%02d:%02d (%llu.0000 sec)", (int)((sec / 60) / 60) % 60, (int)(sec / 60) % 60, (int)sec % 60, sec);
1701        }
1702#endif
1703
1704#ifdef EPLAYER4
1705        GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
1706       
1707/*
1708        if(pipeline)
1709        {
1710                gst_element_query_position(pipeline, &fmt, (gint64*)&pts);
1711                sec = pts / 1000000000;
1712                pts = sec * 90000;
1713                debug(150, "Pts = %02d:%02d:%02d (%llu.0000 sec)", (int)((sec / 60) / 60) % 60, (int)(sec / 60) % 60, (int)sec % 60, sec);
1714        }
1715*/
1716
1717        if(pipeline)
1718        {
1719                gint64 pos;
1720                GstElement *sink;
1721                pts = 0;
1722
1723                g_object_get(G_OBJECT (pipeline), "audio-sink", &sink, NULL);
1724
1725                if(!sink) g_object_get (G_OBJECT (pipeline), "video-sink", &sink, NULL);
1726                if(!sink) return 0;
1727
1728                gchar *name = gst_element_get_name(sink);
1729                gboolean use_get_decoder_time = ostrstr(name, "dvbaudiosink") || ostrstr(name, "dvbvideosink");
1730                g_free(name);
1731
1732                if(use_get_decoder_time) g_signal_emit_by_name(sink, "get-decoder-time", &pos);
1733
1734                gst_object_unref(sink);
1735
1736                if(!use_get_decoder_time && !gst_element_query_position(pipeline, &fmt, &pos))
1737                        return 0;
1738
1739                /* pos is in nanoseconds. we have 90 000 pts per second. */
1740                pts = pos / 11111;
1741                pts = pts - m_gst_startpts;
1742                sec = pts / 90000;
1743                debug(150, "StartPTS = %llu Pts = %02d:%02d:%02d (%llu.0000 sec)", m_gst_startpts, (int)((sec / 60) / 60) % 60, (int)(sec / 60) % 60, (int)sec % 60, sec);
1744        }
1745#endif
1746
1747        if(pts < 0) pts = 0;
1748        return pts;
1749}
1750
1751double playergetlength()
1752{
1753        double length = 0;
1754
1755#ifdef EPLAYER3
1756        if(player && player->playback)
1757        {
1758                player->playback->Command(player, PLAYBACK_LENGTH, &length);
1759                if(length < 0) length = 0;
1760                debug(150, "Length = %02d:%02d:%02d (%.4f sec)", (int)((length / 60) / 60) % 60, (int)(length / 60) % 60, (int)length % 60, length);
1761        }
1762#endif
1763
1764#ifdef EPLAYER4
1765        GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
1766        gint64 len;
1767
1768        if(pipeline)
1769        {
1770                gst_element_query_duration(pipeline, &fmt, &len);
1771                length = len / 1000000000;
1772                if(length < 0) length = 0;
1773                debug(150, "Length = %02d:%02d:%02d (%.4f sec)", (int)((length / 60) / 60) % 60, (int)(length / 60) % 60, (int)length % 60, length);
1774        }
1775#endif
1776
1777        return length;
1778}
1779
1780char* playergetinfo(char* tag)
1781{
1782        char* ret = NULL;
1783
1784#ifdef EPLAYER3
1785        char *tags[] = {"Title", "Artist", "Album", "Year", "Genre", "Comment", "Track", "Copyright", "TestLibEplayer", NULL};
1786        int i = 0;
1787
1788        if(player && player->playback)
1789        {
1790                while(tags[i] != NULL)
1791                {
1792                        ret = tags[i];
1793                        if(ostrcmp(tag, ret) == 0)
1794                        {
1795                                player->playback->Command(player, PLAYBACK_INFO, &ret);
1796                                break;
1797                        }
1798
1799                        i++;
1800                }
1801        }
1802#endif
1803        return ret;
1804}
1805
1806void playerchangeaudiotrack(int num)
1807{
1808#ifdef EPLAYER3
1809        if(player && player->playback)
1810                player->playback->Command(player, PLAYBACK_SWITCH_AUDIO, (void*)&num);
1811#endif
1812
1813#ifdef EPLAYER4
1814        if(pipeline != NULL)
1815                g_object_set(G_OBJECT(pipeline), "current-audio", num, NULL);   
1816#endif
1817}
1818
1819void playerchangesubtitletrack(int num)
1820{
1821#ifdef EPLAYER3
1822        if(player && player->playback)
1823                player->playback->Command(player, PLAYBACK_SWITCH_SUBTITLE, (void*)&num);
1824#endif
1825}
1826
1827void playerstopsubtitletrack()
1828{
1829#ifdef EPLAYER3
1830        if(player && player->output && player->output->subtitle)
1831                player->output->subtitle->Command(player, (OutputCmd_t)OUTPUT_STOP, NULL);
1832        if(player && player->container && player->container->assContainer)
1833        {
1834                player->container->assContainer->Command(player, CONTAINER_STOP, NULL);
1835                player->container->assContainer->Command(player, CONTAINER_INIT, NULL);
1836        }
1837        if(player && player->manager && player->manager->subtitle)
1838        {
1839                int onlycurrent = 1;
1840                player->manager->subtitle->Command(player, MANAGER_DEL, (void*)&onlycurrent);
1841        }
1842#endif
1843}
1844
1845int playerjumpts(struct service* servicenode, int sekunden, int *startpts, off64_t *poslastpts, off64_t *bitrate, int vpid, int tssize)
1846{
1847        int adaptation = 0;
1848        int payload = 0;
1849        int pes = 0;
1850        int tspid = 0;
1851       
1852        off64_t pts  = 0;
1853        uint64_t aktpts = 0;
1854        long long unsigned int lenpts = 0;
1855        long long unsigned int startpts1 = 0;
1856        long long unsigned int endpts = 0;
1857        long long unsigned int aktbitrate = 0;
1858        off64_t ziehlpts = 0;
1859
1860        off64_t curpos = 0;
1861        off64_t newpos = 0;
1862        off64_t jump = 0;
1863
1864        int kleiner = 0;
1865        int groesser = 0;
1866        int gleich = 0;
1867        int len = 0;
1868        int i = 0;
1869        int ret = 0;
1870
1871        if(servicenode == NULL) return -1;
1872
1873        int buflen = tssize * 15000;
1874        char *buf = malloc(buflen);
1875        if(buf == NULL)
1876                return -1;
1877       
1878        curpos = lseek64(servicenode->recsrcfd, 0, SEEK_CUR);   
1879        int dupfd = open(servicenode->recname, O_RDONLY | O_LARGEFILE);
1880        newpos = lseek64(dupfd, curpos, SEEK_SET);
1881       
1882        if (*startpts == 0)
1883        {
1884                if(videogetpts(status.aktservice->videodev, &aktpts) == 0)
1885                {
1886                                ziehlpts = (aktpts / 90000) + sekunden;
1887                }
1888                else
1889                        return 1;
1890        }
1891        else
1892        {
1893                ziehlpts = *startpts + sekunden;
1894        }
1895        *startpts = ziehlpts;
1896
1897        if(*bitrate == 0)
1898        {
1899                lenpts = servicenode->lenpts;
1900                startpts1 = servicenode->startpts;
1901                endpts = servicenode->endpts;
1902                aktbitrate = servicenode->bitrate;
1903                ret = gettsinfo(dupfd, &lenpts, &startpts1, &endpts, &aktbitrate, servicenode->tssize);
1904                if(ret != 0)
1905                {
1906                        err("can't read ts info");
1907                }
1908                else
1909                        *bitrate = aktbitrate;
1910                newpos = lseek64(dupfd, curpos, SEEK_SET);
1911        }
1912        else
1913                aktbitrate = *bitrate;
1914               
1915        if(*poslastpts == 0)
1916                *poslastpts = curpos;
1917       
1918        if(sekunden > 0)
1919        {
1920                err("not implemented");
1921                return 1;
1922        }       
1923        else if(sekunden < 0)
1924        {
1925                sekunden = sekunden * -1;
1926                if(aktbitrate != 0)
1927                {
1928                        jump = (aktbitrate / 8) * sekunden;
1929                        jump = jump + (curpos - *poslastpts);
1930                        jump = jump + (jump % servicenode->tssize);
1931                        newpos = lseek64(dupfd, -jump, SEEK_CUR);
1932                }
1933                else
1934                        newpos = lseek64(dupfd, - buflen, SEEK_CUR);
1935                if(newpos < 0)
1936                        newpos = lseek64(dupfd, tssize, SEEK_SET);
1937        }
1938        len = read(dupfd, buf, buflen);
1939        for(i = 0; i < len; i = i + 1)
1940        {
1941                if (buf[i] == 0x47 && buf[i+tssize] == 0x47)
1942                {
1943                        newpos = lseek64(dupfd, newpos + i, SEEK_SET);
1944                        break;
1945                }
1946        }
1947        if(i >= len)
1948        {
1949                newpos = lseek64(dupfd, curpos, SEEK_SET);     
1950                return 1;
1951        }
1952        while(1)
1953        {
1954        len = read(dupfd, buf, buflen);
1955
1956                if(len > 0)
1957                {
1958                        for(i = 0; i <= len-tssize; i = i + tssize)
1959                        {
1960                                payload = 0;
1961
1962                                tspid = (buf[i+1] & 0x1F) << 8;
1963                                tspid = tspid + (buf[i+2] & 0xFF);
1964                                pes = buf[i+1] & 0x40;
1965
1966                                if(tspid == vpid)
1967                                {       
1968                                        adaptation = buf[i+3] & 0x30;
1969                                        if(adaptation == 16)
1970                                        {
1971                                                payload = 4;
1972                                        }
1973                                        if(adaptation == 32)
1974                                        {
1975                                                //printf("adaptation field only\n");
1976                                        }
1977                                        if(adaptation == 48)
1978                                        {
1979                                                payload = buf[i+4] & 0xFF;
1980                                                payload = payload + 5;
1981                                        }
1982                                        if(payload != 0)
1983                                        {
1984                                                if(pes == 64)
1985                                                {
1986                                                        if(buf[i+payload+7] & 0x80) //PTS
1987                                                        {
1988                                                                pts = ((unsigned long long)(buf[i+payload+9] & 0xE)) << 29;
1989                                                                pts |= ((unsigned long long)(buf[i+payload+10] & 0xFF)) << 22;
1990                                                                pts |= ((unsigned long long)(buf[i+payload+11] & 0xFE)) << 14;
1991                                                                pts |= ((unsigned long long)(buf[i+payload+12] & 0xFF)) << 7;
1992                                                                pts |= ((unsigned long long)(buf[i+payload+13] & 0xFE)) >> 1;
1993                                                               
1994                                                                if(pts / 90000 == ziehlpts)
1995                                                                {
1996                                                                        gleich = newpos + i;
1997                                                                        break;
1998                                                                }
1999                                                                else if(pts / 90000 > ziehlpts)
2000                                                                {                                                                       
2001                                                                        groesser = newpos + i;
2002                                                                        break;
2003                                                                }
2004                                                                else
2005                                                                {
2006                                                                        kleiner = newpos + i;
2007                                                                }
2008                                                        }
2009                                                }
2010                                        }
2011                                }
2012                        }
2013                        if(gleich != 0)
2014                        {
2015                                close(dupfd);
2016                                free(buf);buf = NULL;
2017                                *poslastpts = lseek64(servicenode->recsrcfd, gleich, SEEK_SET);
2018                                return 0;
2019                        }
2020                        else if(groesser != 0 && kleiner != 0)
2021                        {
2022                                close(dupfd);
2023                                free(buf);buf = NULL;
2024                                *poslastpts = lseek64(servicenode->recsrcfd, kleiner, SEEK_SET);
2025                                return 0;
2026                        }
2027                        else if(groesser != 0)
2028                        {
2029                                if((newpos - buflen)  < 0)
2030                                {
2031                                        close(dupfd);
2032                                        free(buf);buf = NULL;
2033                                        *poslastpts = 0;
2034                                        return -1       ;
2035                                }
2036                                else
2037                                {
2038                                        newpos = lseek64(dupfd, -(buflen * 2), SEEK_CUR);
2039                                }
2040                        }
2041                }
2042                else
2043                {
2044                        if(kleiner == 0)
2045                        {
2046                                close(dupfd);
2047                                free(buf);buf = NULL;
2048                                newpos = lseek64(servicenode->recsrcfd, curpos, SEEK_SET);
2049                                *poslastpts = 0;
2050                                return -1;
2051                        }
2052                        else
2053                        {
2054                                close(dupfd);
2055                                free(buf);buf = NULL;
2056                                *poslastpts = lseek64(servicenode->recsrcfd, kleiner, SEEK_SET);
2057                                return 0;
2058                        }
2059                }
2060        }
2061}
2062
2063//praez = 1 .... sekunden
2064//                      =       2 .... zehntel
2065//                      = 3 .... hundertstel
2066//                      = 4 .... volle Uebereinstimmung
2067//
2068//type  = 0 .... alle
2069//                      = 1 .... nur PCR
2070//                      = 2 .... nur Video
2071//                      = 3 .... nur Audio
2072//
2073//flag = 0 --> play ts
2074//flag = 1 --> timeshift
2075//flag = 2 --> timeshift, not in play mode (only recording)
2076//flag = 9 --> dataset mode
2077//
2078off64_t playergetptspos(unsigned long long fpts, off64_t pos, int dir, int praez, int type, int flag, char* dsn)
2079{
2080        unsigned long long pts;
2081        int ret = 0, dupfd = -1, left = 0, tssize = 0, recbsize = 0;
2082        unsigned char* buf = NULL;
2083        unsigned char *payload;
2084        int pid = 0, pusi = 0;
2085        unsigned char* packet;
2086        struct service* snode;
2087       
2088        if(type > 3)
2089        {
2090                printf("type %i nicht unterstützt\n", type);
2091                return -1;
2092        }
2093       
2094        if(flag == 2)
2095                snode = getservice(RECORDTIMESHIFT, 0);
2096        else if(flag != 9)
2097                snode = getservice(RECORDPLAY, 0);
2098               
2099        if(flag == 9)
2100        {
2101                tssize = 188;
2102                recbsize = tssize * 1024 * 10;
2103                dupfd = open(dsn, O_RDONLY | O_LARGEFILE );
2104        }
2105        else
2106        {
2107                tssize = snode->tssize;
2108                recbsize = snode->tssize * 1024 * 10;
2109                dupfd = open(snode->recname, O_RDONLY | O_LARGEFILE);
2110        }
2111
2112        if(dupfd < 0)
2113        {
2114                err("copy source fd not ok");
2115                return -1;
2116        }
2117
2118        buf = malloc(recbsize);
2119        if(buf == NULL)
2120        {
2121                err("no mem");
2122                return -1;
2123        }
2124        packet = buf;
2125        if(dir > 0) 
2126                pos = lseek64(dupfd, pos, SEEK_SET);
2127        else
2128                pos = lseek64(dupfd, pos - recbsize, SEEK_SET);
2129       
2130        ret = read(dupfd,  buf, recbsize);
2131        close(dupfd);
2132        left = 0;
2133       
2134        if(buf[0] != 0x47)
2135        {
2136                while(left < tssize)
2137                {
2138                        if(buf[left] == 0x47) break;
2139                        left++;
2140                }
2141                if(left >= tssize)
2142                {
2143                        free(buf);
2144                        return -1;
2145                }       
2146        }
2147        pts = 0;
2148        while(left <= recbsize - tssize)
2149        {
2150                if(pts != 0)
2151                {
2152                        switch( praez )
2153          {
2154        case 1 :        if(fpts / 90000 != pts / 90000)
2155                                                        pts = 0;
2156                                                break;
2157        case 2 :        if(fpts / 9000 != pts / 9000)
2158                                                        pts = 0;
2159                                                break;
2160        case 3 :        if(fpts / 900 != pts / 900)
2161                                                        pts = 0;
2162                                                break;         
2163        case 4 :        if(fpts != pts )
2164                                                        pts = 0;
2165                                                break;
2166                                default :       free(buf); return -1; break;
2167                        }
2168                        if(pts != 0)
2169                        {       
2170                                pos = pos + left - tssize;
2171                                free(buf);
2172                                return pos;
2173                        }
2174                }
2175                packet = buf + left;
2176                left = left + tssize;
2177                                               
2178                pid = ((packet[1] << 8) | packet[2]) & 0x1FFF;
2179                pusi = !!(packet[1] & 0x40);
2180                //check for adaption field
2181                if(packet[3] & 0x20)
2182                {
2183                        if(type > 1)continue;
2184                        if(packet[4] >= 183) continue;
2185                        if(packet[4])
2186                        {
2187                                if(packet[5] & 0x10) //PCR present
2188                                {
2189                                        pts = ((unsigned long long)(packet[6] & 0xFF)) << 25;
2190                                        pts |= ((unsigned long long)(packet[7] & 0xFF)) << 17;
2191                                        pts |= ((unsigned long long)(packet[8] & 0xFE)) << 9;
2192                                        pts |= ((unsigned long long)(packet[9] & 0xFF)) << 1;
2193                                        pts |= ((unsigned long long)(packet[10] & 0x80)) >> 7;
2194                                        continue;
2195                                }
2196                        }
2197                        payload = packet + packet[4] + 4 + 1;
2198                } else
2199                        payload = packet + 4;
2200               
2201                if(type == 1) continue;
2202                if(!pusi) continue;
2203               
2204                if (payload[0] || payload[1] || (payload[2] != 1))
2205                        continue;
2206               
2207                        //stream use extension mechanism def in ISO 13818-1 Amendment 2
2208                if(payload[3] == 0xFD)
2209                {
2210                        if(payload[7] & 1) //PES extension flag
2211                        {
2212                                int offs = 0;
2213                                if(payload[7] & 0x80) offs += 5; //pts avail
2214                                if(payload[7] & 0x40) offs += 5; //dts avail
2215                                if(payload[7] & 0x20) offs += 6; //escr avail
2216                                if(payload[7] & 0x10) offs += 3; //es rate
2217                                if(payload[7] & 0x8) offs += 1; //dsm trickmode
2218                                if(payload[7] & 0x4) offs += 1; //additional copy info
2219                                if(payload[7] & 0x2) offs += 2; //crc
2220                                if(payload[8] < offs) continue;
2221
2222                                uint8_t pef = payload[9 + offs++]; //pes extension field
2223                                if(pef & 1) //pes extension flag 2
2224                                {
2225                                        if(pef & 0x80) offs += 16; //private data flag
2226                                        if(pef & 0x40) offs += 1; //pack header field flag
2227                                        if(pef & 0x20) offs += 2; //program packet sequence counter flag
2228                                        if(pef & 0x10) offs += 2; //P-STD buffer flag
2229                                        if(payload[8] < offs) continue;
2230
2231                                        uint8_t stream_id_extension_len = payload[9 + offs++] & 0x7F;
2232                                        if(stream_id_extension_len >= 1)
2233                                        {
2234                                                if(payload[8] < (offs + stream_id_extension_len)) continue;
2235                                                //stream_id_extension_bit (should not set)
2236                                                if(payload[9 + offs] & 0x80) continue;
2237                                                switch(payload[9 + offs])
2238                                                {
2239                                                        case 0x55 ... 0x5f: break; //VC-1
2240                                                        case 0x71: break; //AC3 / DTS
2241                                                        case 0x72: break; //DTS - HD
2242                                                        default:
2243                                                                printf("skip unknwn stream_id_extension %02x\n", payload[9 + offs]);
2244                                                                continue;
2245                                                }
2246                                        }
2247                                        else
2248                                                continue;
2249                                }
2250                                else
2251                                        continue;
2252                        }
2253                        else
2254                                continue;
2255                }
2256                //drop non-audio, non-video packets because other streams
2257                //can be non-compliant.
2258                //0xC0 = audio, 0xE0 = video
2259                else if(((payload[3] & 0xE0) != 0xC0) && ((payload[3] & 0xF0) != 0xE0))
2260                        continue;
2261
2262                if((payload[7] & 0x80) && ((payload[3] & 0xF0) != 0xE0) && (type == 0 || type == 2)) //PTS video
2263                {
2264                        pts = ((unsigned long long)(payload[9] & 0xE)) << 29;
2265                        pts |= ((unsigned long long)(payload[10] & 0xFF)) << 22;
2266                        pts |= ((unsigned long long)(payload[11] & 0xFE)) << 14;
2267                        pts |= ((unsigned long long)(payload[12] & 0xFF)) << 7;
2268                        pts |= ((unsigned long long)(payload[13] & 0xFE)) >> 1;
2269                        continue;
2270                }
2271                if((payload[7] & 0x80) && ((payload[3] & 0xE0) != 0xC0) && (type == 0 || type == 3)) //PTS audio
2272                {
2273                        pts = ((unsigned long long)(payload[9] & 0xE)) << 29;
2274                        pts |= ((unsigned long long)(payload[10] & 0xFF)) << 22;
2275                        pts |= ((unsigned long long)(payload[11] & 0xFE)) << 14;
2276                        pts |= ((unsigned long long)(payload[12] & 0xFF)) << 7;
2277                        pts |= ((unsigned long long)(payload[13] & 0xFE)) >> 1;
2278                        continue;
2279                }
2280        }
2281        free(buf);
2282        return recbsize * -1;
2283}
2284
2285#endif
Note: See TracBrowser for help on using the repository browser.