source: titan/libeplayer3/main/exteplayer.c @ 41219

Last change on this file since 41219 was 41219, checked in by obi, 5 years ago

update libeplayer3 v36

File size: 31.3 KB
Line 
1/*
2 * eplayer3: command line playback using libeplayer3
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <sched.h>
25#include <signal.h>
26
27#include <sys/ioctl.h>
28#include <sys/prctl.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <sys/resource.h>
33#include <sys/mman.h>
34#include <sys/socket.h>
35#include <sys/un.h>
36#include <errno.h>
37
38#include <pthread.h>
39
40#include "common.h"
41#include "misc.h"
42
43#define DUMP_BOOL(x) 0 == x ? "false"  : "true"
44#define IPTV_MAX_FILE_PATH 1024
45
46extern int ffmpeg_av_dict_set(const char *key, const char *value, int flags);
47extern void       aac_software_decoder_set(const int32_t val);
48extern void  aac_latm_software_decoder_set(const int32_t val);
49extern void       dts_software_decoder_set(const int32_t val);
50extern void       wma_software_decoder_set(const int32_t val);
51extern void       ac3_software_decoder_set(const int32_t val);
52extern void      eac3_software_decoder_set(const int32_t val);
53extern void       mp3_software_decoder_set(const int32_t val);
54extern void            rtmp_proto_impl_set(const int32_t val);
55extern void        flv2mpeg4_converter_set(const int32_t val);
56extern void        sel_program_id_set(const int32_t val);
57
58extern void pcm_resampling_set(int32_t val);
59extern void stereo_software_decoder_set(int32_t val);
60extern void insert_pcm_as_lpcm_set(int32_t val);
61extern void progressive_playback_set(int32_t val);
62
63extern OutputHandler_t         OutputHandler;
64extern PlaybackHandler_t       PlaybackHandler;
65extern ContainerHandler_t      ContainerHandler;
66extern ManagerHandler_t        ManagerHandler;
67
68static Context_t *g_player = NULL;
69
70static void TerminateAllSockets(void)
71{
72    int i;
73    for(i=0; i<1024; ++i)
74    {
75        if( 0 == shutdown(i, SHUT_RDWR) )
76        {
77            /* yes, I know that this is not good practice and I know what this could cause
78             * but in this use case it can be accepted.
79             * We must close socket because without closing it recv will return 0 (after shutdown)
80             * 0 is not correctly handled by external libraries
81             */
82            close(i);
83        }
84    }
85}
86
87static int g_pfd[2] = {-1, -1}; /* Used to wake terminate thread */
88static int isPlaybackStarted = 0;
89static pthread_mutex_t playbackStartMtx;
90
91static void *TermThreadFun(void *arg)
92{
93    const char *socket_path = "/tmp/iptvplayer_extplayer_term_fd";
94    struct sockaddr_un addr;
95    int fd = -1;
96    int cl = -1;
97    int nfds = 1;
98    fd_set readfds;
99   
100    unlink(socket_path);
101    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
102    {
103        perror("TermThreadFun socket error");
104        goto finish;
105    }
106
107    memset(&addr, 0, sizeof(addr));
108    addr.sun_family = AF_UNIX;
109    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
110
111    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
112    {
113        perror("TermThreadFun bind error");
114        goto finish;
115    }
116
117    if (listen(fd, 1) == -1)
118    {
119        perror("TermThreadFun listen error");
120        goto finish;
121    }
122
123    FD_ZERO(&readfds);
124    FD_SET(g_pfd[0], &readfds);
125    FD_SET(fd, &readfds);
126   
127    nfds = fd > g_pfd[0] ? fd + 1 : g_pfd[0] + 1;
128   
129    while (select(nfds, &readfds, NULL, NULL, NULL) == -1
130           && errno == EINTR)
131    {
132        /* Restart if interrupted by signal */
133        continue;
134    }
135   
136    if (FD_ISSET(fd, &readfds))
137    {
138        /*
139        if ( (cl = accept(fd, NULL, NULL)) == -1)
140        {
141            perror("TermThreadFun accept error");
142            goto finish;
143        }
144        */
145       
146        pthread_mutex_lock(&playbackStartMtx);
147        PlaybackDieNow(1);
148        if (isPlaybackStarted)
149            TerminateAllSockets();
150        else
151            kill(getpid(), SIGINT);
152        pthread_mutex_unlock(&playbackStartMtx);
153    }
154
155finish:
156    close(cl);
157    close(fd);
158    pthread_exit(NULL);
159   
160}
161
162static void map_inter_file_path(char *filename)
163{
164    if (0 == strncmp(filename, "iptv://", 7))
165    {
166        FILE *f = fopen(filename + 7, "r");
167        if (NULL != f)
168        {
169            size_t num = fread(filename, 1, IPTV_MAX_FILE_PATH-1, f);
170            fclose(f);
171            if (num > 0 && filename[num-1] == '\n')
172            {
173                filename[num-1] = '\0';
174            }
175            else
176            {
177                filename[num] = '\0';
178            }
179        }
180    }
181}
182
183static int kbhit(void)
184{
185    struct timeval tv;
186    fd_set read_fd;
187
188    tv.tv_sec=1;
189    tv.tv_usec=0;
190
191    FD_ZERO(&read_fd);
192    FD_SET(0,&read_fd);
193
194    if(-1 == select(1, &read_fd, NULL, NULL, &tv))
195    {
196        return 0;
197    }
198
199    if(FD_ISSET(0,&read_fd))
200    {
201        return 1;
202    }
203
204    return 0;
205}
206
207static void SetBuffering()
208{
209    static char buff[2048];
210    memset( buff, '\0', sizeof(buff));
211    if( setvbuf(stderr, buff, _IOLBF, sizeof(buff)) )
212    {
213        printf("SetBuffering: failed to change the buffer of stderr\n");
214    }
215   
216    // make fgets not blocking
217    int flags = fcntl(stdin->_fileno, F_GETFL, 0);
218    fcntl(stdin->_fileno, F_SETFL, flags | O_NONBLOCK);
219}
220
221static void SetNice(int prio)
222{
223#if 0
224    setpriority(PRIO_PROCESS, 0, -8);
225   
226    int prio = sched_get_priority_max(SCHED_RR) / 2;
227    struct sched_param param = {
228        .sched_priority = prio
229    };
230    sched_setscheduler(0, SCHED_RR, &param);
231#else
232    int prevPrio = getpriority(PRIO_PROCESS, 0);
233    if (-1 == setpriority(PRIO_PROCESS, 0, prio))
234    {
235        printf("setpriority - failed\n");
236    }
237#endif
238}
239
240static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbackSwitchCmd, const char *argvBuff)
241{
242    int commandRetVal = 0;
243   
244    if (NULL == ptrManager || NULL == argvBuff || 2 != strnlen(argvBuff, 2))
245    {
246        return -1;
247    }
248   
249    switch (argvBuff[1])
250    {
251        case 'l':
252        {
253            TrackDescription_t *TrackList = NULL;
254            ptrManager->Command(g_player, MANAGER_LIST, &TrackList);
255            if( NULL != TrackList)
256            {
257                int i = 0;
258                fprintf(stderr, "{\"%c_%c\": [", argvBuff[0], argvBuff[1]);
259                for (i = 0; TrackList[i].Id >= 0; ++i)
260                {
261                    if(0 < i)
262                    {
263                        fprintf(stderr, ", ");
264                    }
265                    fprintf(stderr, "{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}", TrackList[i].Id , TrackList[i].Encoding, TrackList[i].Name);
266                    free(TrackList[i].Encoding);
267                    free(TrackList[i].Name);
268                }
269                fprintf(stderr, "]}\n");
270                free(TrackList);
271            }
272            else
273            {
274                // not tracks
275                fprintf(stderr, "{\"%c_%c\": []}\n", argvBuff[0], argvBuff[1]);
276            }
277            break;
278        }
279        case 'c':
280        {
281           
282            TrackDescription_t *track = NULL;
283            ptrManager->Command(g_player, MANAGER_GET_TRACK_DESC, &track);
284            if (NULL != track)
285            {
286                if ('a' == argvBuff[0] || 's' == argvBuff[0])
287                {
288                    fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}}\n", argvBuff[0], argvBuff[1], track->Id , track->Encoding, track->Name);
289                }
290                else // video
291                {
292                    fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\",\"w\":%d,\"h\":%d,\"f\":%u,\"p\":%d,\"an\":%d,\"ad\":%d}}\n", \
293                    argvBuff[0], argvBuff[1], track->Id , track->Encoding, track->Name, track->width, track->height, track->frame_rate, track->progressive, track->aspect_ratio_num, track->aspect_ratio_den);
294                }
295                free(track->Encoding);
296                free(track->Name);
297                free(track);
298            }
299            else
300            {
301                // no tracks
302                if ('a' == argvBuff[0] || 's' == argvBuff[0])
303                {
304                    fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}}\n", argvBuff[0], argvBuff[1], -1, "", "");
305                }
306                else // video
307                {
308                    fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\",\"w\":%d,\"h\":%d,\"f\":%u,\"p\":%d}}\n", argvBuff[0], argvBuff[1], -1, "", "", -1, -1, 0, -1);
309                }
310            }
311            break;
312        }
313        default:
314        {
315            /* switch command available only for audio and subtitle tracks */
316            if ('a' == argvBuff[0] || 's' == argvBuff[0])
317            {
318                int ok = 0;
319                int id = -1;
320                if ('i' == argvBuff[1])
321                {
322                    int idx = -1;
323                    ok = sscanf(argvBuff+2, "%d", &idx);
324                    if (idx >= 0)
325                    {
326                        TrackDescription_t *TrackList = NULL;
327                        ptrManager->Command(g_player, MANAGER_LIST, &TrackList);
328                        if( NULL != TrackList)
329                        {
330                            int i = 0;
331                            for (i = 0; TrackList[i].Id >= 0; ++i)
332                            {
333                                if (idx == i)
334                                {
335                                    id = TrackList[i].Id;
336                                }
337                                free(TrackList[i].Encoding);
338                                free(TrackList[i].Name);
339                            }
340                            free(TrackList);
341                        }
342                    }
343                    else
344                    {
345                        id = idx;
346                    }
347                }
348                else
349                {
350                    ok = sscanf(argvBuff+1, "%d", &id);
351                }
352               
353                if(id >= 0 || (1 == ok && id == -1))
354                {
355                    commandRetVal = g_player->playback->Command(g_player, playbackSwitchCmd, (void*)&id);
356                    fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"sts\":%d}}\n", argvBuff[0], 's', id, commandRetVal);
357                }
358            }
359            break;
360        }
361    }
362   
363    return commandRetVal;
364}
365
366static void UpdateVideoTrack()
367{
368    HandleTracks(g_player->manager->video, (PlaybackCmd_t)-1, "vc");
369}
370
371static int ParseParams(int argc,char* argv[], char *file, char *audioFile, int *pAudioTrackIdx, int *subtitleTrackIdx)
372{   
373    int ret = 0;
374    int c;
375    int digit_optind = 0;
376    int aopt = 0, bopt = 0;
377    char *copt = 0, *dopt = 0;
378    while ( (c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:")) != -1)
379    {
380        switch (c)
381        {
382        case 'a':
383        {
384            int flag = atoi(optarg);
385            printf("Software decoder will be used for AAC codec\n");
386            aac_software_decoder_set(flag & 0x01);
387            aac_latm_software_decoder_set(flag & 0x02);
388            break;
389        }
390        case 'e':
391            printf("Software decoder will be used for EAC3 codec\n");
392            eac3_software_decoder_set(1);
393            break;
394        case '3':
395            printf("Software decoder will be used for AC3 codec\n");
396            ac3_software_decoder_set(1);
397            break;
398        case 'd':
399            printf("Software decoder will be used for DTS codec\n");
400            dts_software_decoder_set(1);
401            break;
402        case 'm':
403            printf("Software decoder will be used for MP3 codec\n");
404            mp3_software_decoder_set(1);
405            break;
406        case 'w':
407            printf("Software decoder will be used for WMA codec\n");
408            wma_software_decoder_set(1);
409            break;
410        case 'l':
411            printf("Audio software decoding as LPCM\n");
412            insert_pcm_as_lpcm_set(1);
413            break;
414        case 's':
415            printf("Software decoder will decode to stereo\n");
416            stereo_software_decoder_set(1);
417            break;
418        case 'r':
419            printf("Software decoder do not use PCM resampling\n");
420            pcm_resampling_set(0);
421            break;
422        case 'o':
423            printf("Set progressive download to %d\n", atoi(optarg));
424            progressive_playback_set(atoi(optarg));
425            break;
426        case 'p':
427            SetNice(atoi(optarg));
428            break;
429        case 'P':
430            sel_program_id_set(atoi(optarg));
431            break;
432        case 't':
433            *pAudioTrackIdx = atoi(optarg);
434            break;
435        case '9':
436            *subtitleTrackIdx = atoi(optarg);
437            break;
438        case 'x':
439            strncpy(audioFile, optarg, IPTV_MAX_FILE_PATH-1);
440            map_inter_file_path(audioFile);
441            break;
442        case 'h':
443            ffmpeg_av_dict_set("headers", optarg, 0);
444            break;
445        case 'u':
446            ffmpeg_av_dict_set("user-agent", optarg, 0);
447            break;
448        case 'c':
449            printf("For now cookies should be set via headers option!\n");
450            ffmpeg_av_dict_set("cookies", optarg, 0);
451            break;
452        case 'i':
453            printf("Play in (infinity) loop.\n");
454            PlaybackHandler.isLoopMode = 1;
455            break;
456        case 'v':
457            printf("Use live TS stream mode.\n");
458            PlaybackHandler.isTSLiveMode = 1;
459            break;
460        case 'n':
461            printf("Force rtmp protocol implementation\n");
462            rtmp_proto_impl_set(atoi(optarg));
463            break;
464        case '0':
465            ffmpeg_av_dict_set("video_rep_index", optarg, 0);
466            break;
467        case '1':
468            ffmpeg_av_dict_set("audio_rep_index", optarg, 0);
469            break;
470        case '4':
471#ifdef HAVE_FLV2MPEG4_CONVERTER
472            flv2mpeg4_converter_set(atoi(optarg));
473#endif
474            break;
475        case 'f':
476        {
477            char *ffopt = strdup(optarg);
478            char *ffval = strchr(ffopt, '=');
479            if (ffval)
480            {
481                *ffval = '\0';
482                ffval += 1;
483                ffmpeg_av_dict_set(ffopt, ffval, 0);
484            }
485            free(ffopt);
486            break;
487        }
488        default:
489            printf ("?? getopt returned character code 0%o ??\n", c);
490            ret = -1;
491        }
492    }
493   
494    if (0 == ret && optind < argc)
495    {
496        ret = 0;
497       
498        if(NULL == strstr(argv[optind], "://"))
499        {
500            strcpy(file, "file://");
501        }
502        strcat(file, argv[optind]);
503        map_inter_file_path(file);
504        printf("file: [%s]\n", file);
505        ++optind;
506    }
507    else
508    {
509        ret = -1;
510    }
511    return ret;
512}
513
514int main(int argc, char* argv[])
515{
516    pthread_t termThread;
517    int isTermThreadStarted = 0;
518    char file[IPTV_MAX_FILE_PATH];
519    memset(file, '\0', sizeof(file));
520   
521    char audioFile[IPTV_MAX_FILE_PATH];
522    memset(audioFile, '\0', sizeof(audioFile));
523   
524    int audioTrackIdx = -1;
525    int subtitleTrackIdx = -1;
526   
527    char argvBuff[256];
528    memset(argvBuff, '\0', sizeof(argvBuff));
529    int commandRetVal = -1;
530    /* inform client that we can handle additional commands */
531    fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 36);
532
533    if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx))
534    {
535        printf("Usage: exteplayer3 filePath [-u user-agent] [-c cookies] [-h headers] [-p prio] [-a] [-d] [-w] [-l] [-s] [-i] [-t audioTrackId] [-9 subtitleTrackId] [-x separateAudioUri] plabackUri\n");
536        printf("[-a 0|1|2|3] AAC software decoding - 1 bit - AAC ADTS, 2 - bit AAC LATM\n");
537        printf("[-e] EAC3 software decoding\n");
538        printf("[-3] AC3 software decoding\n");
539        printf("[-d] DTS software decoding\n");
540        printf("[-m] MP3 software decoding\n");
541        printf("[-w] WMA1, WMA2, WMA/PRO software decoding\n");
542        printf("[-l] software decoder use LPCM for injection (otherwise wav PCM will be used)\n");
543        printf("[-s] software decoding as stereo [downmix]\n");
544#ifdef HAVE_FLV2MPEG4_CONVERTER
545        printf("[-4 0|1] - disable/enable flv2mpeg4 converter\n");
546#endif
547        printf("[-i] play in infinity loop\n");
548        printf("[-v] switch to live TS stream mode\n");
549        printf("[-n 0|1|2] rtmp force protocol implementation auto(0) native/ffmpeg(1) or librtmp(2)\n");       
550        printf("[-o 0|1] set progressive download\n");
551        printf("[-p value] nice value\n");
552        printf("[-P value] select Program ID from multi-service stream\n");
553        printf("[-t id] audio track ID switched on at start\n");
554        printf("[-9 id] subtitle track ID switched on at start\n");
555        printf("[-h headers] set custom HTTP headers \"Name: value\\r\\nName: value\\r\\n\"\n");
556        printf("[-u user-agent] set custom http User-Agent header\n");
557        printf("[-c cookies] set cookies - not working at now, please use -h instead\n");
558        printf("[-x separateAudioUri]\n");
559        printf("[-0 idx] video MPEG-DASH representation index\n");
560        printf("[-1 idx] audio MPEG-DASH representation index\n");
561        printf("[-f ffopt=ffval] any other ffmpeg option\n");
562       
563        exit(1);
564    }
565   
566    g_player = malloc(sizeof(Context_t));
567    if(NULL == g_player)
568    {
569        printf("g_player allocate error\n");
570        exit(1);
571    }
572   
573    pthread_mutex_init(&playbackStartMtx, NULL);
574    do
575    {
576        int flags = 0;
577       
578        if (pipe(g_pfd) == -1)
579            break;
580       
581        /* Make read and write ends of pipe nonblocking */
582        if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1)
583            break;
584       
585        /* Make read end nonblocking */
586        flags |= O_NONBLOCK;
587        if (fcntl(g_pfd[0], F_SETFL, flags) == -1)
588            break;
589       
590        if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1)
591            break;
592       
593        /* Make write end nonblocking */
594        flags |= O_NONBLOCK;
595        if (fcntl(g_pfd[1], F_SETFL, flags) == -1)
596            break;
597       
598        if(0 == pthread_create(&termThread, NULL, TermThreadFun, NULL))
599            isTermThreadStarted = 1;
600    } while(0);
601
602    g_player->playback    = &PlaybackHandler;
603    g_player->output      = &OutputHandler;
604    g_player->container   = &ContainerHandler;
605    g_player->manager     = &ManagerHandler;
606
607    // make sure to kill myself when parent dies
608    prctl(PR_SET_PDEATHSIG, SIGKILL);
609
610    SetBuffering();
611   
612    //Registrating output devices
613    g_player->output->Command(g_player, OUTPUT_ADD, "audio");
614    g_player->output->Command(g_player, OUTPUT_ADD, "video");
615    g_player->output->Command(g_player, OUTPUT_ADD, "subtitle");
616
617    g_player->manager->video->Command(g_player, MANAGER_REGISTER_UPDATED_TRACK_INFO, UpdateVideoTrack);
618    if (strncmp(file, "rtmp", 4) && strncmp(file, "ffrtmp", 4))
619    {
620        g_player->playback->noprobe = 1;
621    }
622
623    PlayFiles_t playbackFiles = {file, NULL};
624    if('\0' != audioFile[0])
625    {
626        playbackFiles.szSecondFile = audioFile;
627    }
628   
629    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_OPEN, &playbackFiles);
630    fprintf(stderr, "{\"PLAYBACK_OPEN\":{\"OutputName\":\"%s\", \"file\":\"%s\", \"sts\":%d}}\n", g_player->output->Name, file, commandRetVal);
631    if(commandRetVal < 0)
632    {
633        if(NULL != g_player)
634        {
635            free(g_player);
636        }
637        return 10;
638    }
639   
640    {
641        pthread_mutex_lock(&playbackStartMtx);
642        isPlaybackStarted = 1;
643        pthread_mutex_unlock(&playbackStartMtx);
644       
645        commandRetVal = g_player->output->Command(g_player, OUTPUT_OPEN, NULL);
646        fprintf(stderr, "{\"OUTPUT_OPEN\":{\"sts\":%d}}\n", commandRetVal);
647        commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PLAY, NULL);
648        fprintf(stderr, "{\"PLAYBACK_PLAY\":{\"sts\":%d}}\n", commandRetVal);
649       
650        if (g_player->playback->isPlaying)
651        {
652            HandleTracks(g_player->manager->video, (PlaybackCmd_t)-1, "vc");
653            HandleTracks(g_player->manager->audio, (PlaybackCmd_t)-1, "al");
654            if (audioTrackIdx >= 0)
655            {
656                static char cmd[128] = ""; // static to not allocate on stack
657                sprintf(cmd, "ai%d\n", audioTrackIdx);
658                commandRetVal = HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, cmd);
659            }
660            HandleTracks(g_player->manager->audio, (PlaybackCmd_t)-1, "ac");
661           
662            HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t)-1, "sl");
663            if (subtitleTrackIdx >= 0)
664            {
665                static char cmd[128] = ""; // static to not allocate on stack
666                sprintf(cmd, "si%d\n", subtitleTrackIdx);
667                commandRetVal = HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, cmd);
668            }
669            HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t)-1, "sc");
670        }
671
672        while(g_player->playback->isPlaying)
673        {
674            /* we made fgets non blocking */
675            if( NULL == fgets(argvBuff, sizeof(argvBuff)-1 , stdin) )
676            {
677                /* wait for data - max 1s */
678                kbhit();
679                continue;
680            }
681
682            if(0 == argvBuff[0])
683            {
684                continue;
685            }
686           
687            switch(argvBuff[0])
688            {
689            case 'v':
690            {
691                HandleTracks(g_player->manager->video, (PlaybackCmd_t)-1, argvBuff);
692            break;
693            }
694            case 'a':
695            {
696                HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, argvBuff);
697            break;
698            }
699            case 's':
700            {
701                HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, argvBuff);
702            break;
703            }
704            case 'q':
705            {
706                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_STOP, NULL);
707                fprintf(stderr, "{\"PLAYBACK_STOP\":{\"sts\":%d}}\n", commandRetVal);
708                break;
709            }
710            case 'c':
711            {
712                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_CONTINUE, NULL);
713                fprintf(stderr, "{\"PLAYBACK_CONTINUE\":{\"sts\":%d}}\n", commandRetVal);
714                break;
715            }
716            case 'p':
717            {
718                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PAUSE, NULL);
719                fprintf(stderr, "{\"PLAYBACK_PAUSE\":{\"sts\":%d}}\n", commandRetVal);
720                break;
721            }
722            case 'm':
723            {
724                int speed = 0;
725                sscanf(argvBuff+1, "%d", &speed);
726
727                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SLOWMOTION, &speed);
728                fprintf(stderr, "{\"PLAYBACK_SLOWMOTION\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
729                break;
730            }
731            case 'o':
732            {
733                int flags = 0;
734                if( 1 == sscanf(argvBuff+1, "%d", &flags) )
735                {
736                    progressive_playback_set(flags);
737                    fprintf(stderr, "{\"PROGRESSIVE_DOWNLOAD\":{\"flags\":%d, \"sts\":0}}\n", flags);
738                }
739                break;
740            }
741            case 'f':
742            {
743                int speed = 0;
744                sscanf(argvBuff+1, "%d", &speed);
745
746                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTFORWARD, &speed);
747                fprintf(stderr, "{\"PLAYBACK_FASTFORWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
748                break;
749            }
750            case 'b':
751            {
752                int speed = 0;
753                sscanf(argvBuff+1, "%d", &speed);
754
755                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTBACKWARD, &speed);
756                fprintf(stderr, "{\"PLAYBACK_FASTBACKWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
757                break;
758            }
759            case 'g':
760            {
761                int32_t gotoPos = 0;
762                int64_t length = 0;
763                int32_t lengthInt = 0;
764                int64_t sec = 0;
765                int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check
766               
767                sscanf(argvBuff+2, "%d", &gotoPos);
768                if(0 <= gotoPos || force)
769                {
770                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
771                    fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal);
772
773                    lengthInt = (int32_t)length;
774                    if(10 <= lengthInt || force)
775                    {
776                        sec = gotoPos;
777                        if(!force && gotoPos >= lengthInt)
778                        {
779                            sec = lengthInt - 10;
780                        }
781                       
782                        commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK_ABS, (void*)&sec);
783                        fprintf(stderr, "{\"PLAYBACK_SEEK_ABS\":{\"sec\":%lld, \"sts\":%d}}\n", sec, commandRetVal);
784                    }
785                }
786                break;
787            }
788            case 'k':
789            {
790                int32_t seek = 0;
791                int64_t length = 0;
792                int32_t lengthInt = 0;
793                int64_t sec = 0;
794                int64_t pts = 0;
795                int32_t CurrentSec = 0;
796                int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check
797               
798                sscanf(argvBuff+2, "%d", &seek);
799               
800                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts);
801                CurrentSec = (int32_t)(pts / 90000);
802                if (0 == commandRetVal)
803                {
804                    fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90, commandRetVal);
805                }
806                if(0 == commandRetVal || force)
807                {                   
808                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
809                    fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal);
810                   
811                    lengthInt = (int32_t)length;
812                    if(10 <= lengthInt || force )
813                    {
814                        int32_t ergSec = CurrentSec + seek;
815                        if(!force && 0 > ergSec)
816                        {
817                            sec = CurrentSec * -1; // jump to start position
818                        }
819                        else if(!force && ergSec >= lengthInt)
820                        {
821                            sec = (lengthInt - CurrentSec) - 5;
822                            if(0 < sec)
823                            {
824                                sec = 0; // no jump we are at the end
825                            }
826                        }
827                        else
828                        {
829                            sec = seek;
830                        }
831                    }
832                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK, (void*)&sec);
833                    fprintf(stderr, "{\"PLAYBACK_SEEK\":{\"sec\":%lld, \"sts\":%d}}\n", sec, commandRetVal);
834                }
835                break;
836            }
837            case 'l':
838            {
839                int64_t length = 0;
840                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
841                fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal);
842                break;
843            }
844            case 'j':
845            {
846                int64_t pts = 0;
847                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts);
848                if (0 == commandRetVal)
849                {
850                    fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90, commandRetVal);
851                }
852                break;
853            }
854            case 'i':
855            {
856                PlaybackHandler_t *ptrP = g_player->playback;
857                if(ptrP)
858                {
859                    fprintf(stderr, "{\"PLAYBACK_INFO\":{ \"isPlaying\":%s, \"isPaused\":%s, \"isForwarding\":%s, \"isSeeking\":%s, \"isCreationPhase\":%s,", \
860                    DUMP_BOOL(ptrP->isPlaying), DUMP_BOOL(ptrP->isPaused), DUMP_BOOL(ptrP->isForwarding), DUMP_BOOL(ptrP->isSeeking), DUMP_BOOL(ptrP->isCreationPhase) );
861                    fprintf(stderr, "\"BackWard\":%d, \"SlowMotion\":%d, \"Speed\":%d, \"AVSync\":%d,", ptrP->BackWard, ptrP->SlowMotion, ptrP->Speed, ptrP->AVSync);
862                    fprintf(stderr, " \"isVideo\":%s, \"isAudio\":%s, \"isSubtitle\":%s, \"isDvbSubtitle\":%s, \"isTeletext\":%s, \"mayWriteToFramebuffer\":%s, \"abortRequested\":%s }}\n", \
863                    DUMP_BOOL(ptrP->isVideo), DUMP_BOOL(ptrP->isAudio), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(ptrP->abortRequested) );
864                }
865               
866                break;
867            }
868            case 'n':
869            {
870                uint8_t loop = 0;
871                if( '1' == argvBuff[1] || '0' == argvBuff[1] )
872                {
873                    PlaybackHandler_t *ptrP = g_player->playback;
874                    if(ptrP)
875                    {
876                        ptrP->isLoopMode = '1' == argvBuff[1] ? 1 : 0;
877                        fprintf(stderr, "{\"N\":{ \"isLoop\":%s }}\n", DUMP_BOOL(ptrP->isLoopMode));
878                    }
879                }
880                break;
881            }
882           
883            default:
884            {
885                break;
886            }
887            }
888        }
889
890        g_player->output->Command(g_player, OUTPUT_CLOSE, NULL);
891    }
892   
893    if(NULL != g_player)
894    {
895        free(g_player);
896    }
897   
898    if (isTermThreadStarted && 1 == write(g_pfd[1], "x", 1))
899    {
900        pthread_join(termThread, NULL);
901    }
902   
903    pthread_mutex_destroy(&playbackStartMtx);
904   
905    close(g_pfd[0]);
906    close(g_pfd[1]);
907
908    //printOutputCapabilities();
909
910    exit(0);
911}
Note: See TracBrowser for help on using the repository browser.