source: titan/titan/player.h @ 30653

Last change on this file since 30653 was 30653, checked in by nit, 9 years ago

fix

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