Statistics
| Branch: | Revision:

chunker-player / chunker_player / chunker_player.c @ 47943338

History | View | Annotate | Download (19.1 KB)

1 01f952d0 GiuseppeTropea
/*
2
 *  Copyright (c) 2009-2011 Carmelo Daniele, Dario Marchese, Diego Reforgiato, Giuseppe Tropea
3
 *  developed for the Napa-Wine EU project. See www.napa-wine.eu
4
 *
5
 *  This is free software; see lgpl-2.1.txt
6
 */
7
8 10c75ef7 GiuseppeTropea
#include <stdio.h>
9
#include <unistd.h>
10
#include <SDL.h>
11
#include <SDL_mutex.h>
12
#include "player_defines.h"
13
#include <confuse.h>
14
#include "http_default_urls.h"
15
#include "player_defines.h"
16
#include "chunker_player.h"
17
#include "player_gui.h"
18 e11386c0 CsabaKiraly
#include <time.h>
19
#include <getopt.h>
20 b0e46569 GiuseppeTropea
21
#ifdef PSNR_PUBLICATION
22 af11718f CarmeloDaniele
#include <event2/event.h>
23 0cd6b05d CarmeloDaniele
#include <napa_log.h>
24 b0e46569 GiuseppeTropea
#endif
25 e11386c0 CsabaKiraly
26 c35a59c4 CsabaKiraly
#ifdef _WIN32
27 e11386c0 CsabaKiraly
#include <windows.h>
28
#endif
29
30 74564eb3 CarmeloDaniele
int ReadALine(FILE* fp, char* Output, int MaxOutputSize)
31
{
32
    int i=0;
33
    int c;
34
    do
35
    {
36
        c=getc(fp);
37
        if(c=='\r' || c=='\n' || c==EOF)
38
        {
39
            Output[i]=0;
40
            return i;
41
        }
42
        Output[i++]=c;
43
    }
44
    while(c!=EOF);
45
    
46
    return -1;
47
}
48
49 59e008ed GiuseppeTropea
int CheckForRepoAddress(char* Param)
50 0cd6b05d CarmeloDaniele
{
51 59e008ed GiuseppeTropea
        int result = 0;
52 af11718f CarmeloDaniele
    int i, Found=0;
53
54 0cd6b05d CarmeloDaniele
    if(strncasecmp(Param,"repo_address=",13)==0)
55
    {
56 af11718f CarmeloDaniele
        result=1;
57
        //find ',' in Param (if exist)
58
        int len=strlen(Param);
59
        char* tmp=(char*)calloc(1,len);
60
        if(tmp)
61
        {
62
            for(i=13;i<len;i++)
63
            {
64
                if(Param[i]==',')
65
                {
66
                    Found=1;
67
                    break;
68
                }
69
                tmp[i-13]=Param[i];
70
            }
71
72
            if(i==len || Found) strncpy(RepoAddress,tmp,2048);
73
            free(tmp);
74
        }
75 0cd6b05d CarmeloDaniele
    }
76 59e008ed GiuseppeTropea
77
        return result;
78 0cd6b05d CarmeloDaniele
}
79
80 e11386c0 CsabaKiraly
void sigproc()
81
{
82
        printf("you have pressed ctrl-c, terminating...\n");
83
        quit = 1;
84
}
85
86
static void print_usage(int argc, char *argv[])
87
{
88
  fprintf (stderr,
89
    "\nUsage:%s [options]\n"
90
    "\n"
91
    "\t[-c ChannelName]: channel name (from channels.conf)\n"
92 12948c73 Csaba Kiraly
    "\t[-p port]: player http port\n"
93 5fd002d4 Csaba Kiraly
    "\t[-q q_thresh]: playout queue size\n"
94 2f5ae7bb Csaba Kiraly
    "\t[-A audiocodec]\n"
95
    "\t[-V videocodec]\n"
96 e11386c0 CsabaKiraly
    "\t[-t]: log traces (WARNING: old traces will be deleted).\n"
97 ccf75e3a GiuseppeTropea
    "\t[-s mode]: silent mode (no GUI) (mode=1 audio ON, mode=2 audio OFF, mode=3 audio OFF; P2P OFF).\n\n"
98 e11386c0 CsabaKiraly
    "=======================================================\n", argv[0]
99
    );
100
}
101 1e69ae95 GiuseppeTropea
102 10c75ef7 GiuseppeTropea
int main(int argc, char *argv[])
103
{
104 e11386c0 CsabaKiraly
        srand ( time(NULL) );
105 10c75ef7 GiuseppeTropea
        // some initializations
106
        SilentMode = 0;
107 5fd002d4 Csaba Kiraly
        queue_filling_threshold = 50;
108 10c75ef7 GiuseppeTropea
        quit = 0;
109
        QueueFillingMode=1;
110 e11386c0 CsabaKiraly
        LogTraces = 0;
111 b0e46569 GiuseppeTropea
112
#ifdef PSNR_PUBLICATION
113 0cd6b05d CarmeloDaniele
        repoclient=NULL;
114
        LastTimeRepoPublish.tv_sec=0;
115
        LastTimeRepoPublish.tv_usec=0;
116 59e008ed GiuseppeTropea
        eventbase = event_base_new();
117 0cd6b05d CarmeloDaniele
        napaInitLog(LOG_DEBUG, NULL, NULL);
118 b0e46569 GiuseppeTropea
        repInit("");
119
#endif
120 0cd6b05d CarmeloDaniele
        
121 e11386c0 CsabaKiraly
#ifndef __WIN32__
122
        static pid_t fork_pid = -1;
123
        P2PProcessHandle=&fork_pid;
124
#else
125
        static PROCESS_INFORMATION ProcessInfo;
126
        ZeroMemory( &ProcessInfo, sizeof(ProcessInfo) );
127
        P2PProcessHandle=&ProcessInfo;
128
#endif
129
130 10c75ef7 GiuseppeTropea
        NChannels = 0;
131
        SelectedChannel = -1;
132 19b05fc0 GiuseppeTropea
        char firstChannelName[255];
133
        int firstChannelIndex;
134 78068e21 GiuseppeTropea
        
135 12948c73 Csaba Kiraly
        firstChannelName[0] = 0;
136 10c75ef7 GiuseppeTropea
        memset((void*)Channels, 0, (MAX_CHANNELS_NUM*sizeof(SChannel)));
137 1e69ae95 GiuseppeTropea
138 b79102a2 CsabaKiraly
        Port = 6100;
139 157c26b4 Csaba Kiraly
140 3a240a99 GiuseppeTropea
        struct MHD_Daemon *daemon = NULL;
141 1e69ae95 GiuseppeTropea
        SDL_Event event;
142 10c75ef7 GiuseppeTropea
        OverlayMutex = SDL_CreateMutex();
143 20de09cd GiuseppeTropea
        
144 e11386c0 CsabaKiraly
        char c;
145 71fa7249 Csaba Kiraly
        while ((c = getopt (argc, argv, "q:c:p:s:t")) != -1)
146 aba1367c GiuseppeTropea
        {
147 e11386c0 CsabaKiraly
                switch (c) {
148
                        case 0: //for long options
149
                                break;
150
                        case 'q':
151
                                sscanf(optarg, "%d", &queue_filling_threshold);
152
                                break;
153
                        case 'c':
154
                                sprintf(firstChannelName, "%s", optarg);
155
                                break;
156
                        case 'p':
157 327da69f Csaba Kiraly
                                sscanf(optarg, "%d", &Port);
158 e11386c0 CsabaKiraly
                                break;
159
                        case 's':
160
                                sscanf(optarg, "%d", &SilentMode);
161
                                break;
162
                        case 't':
163
                                DELETE_DIR("traces");
164
                                CREATE_DIR("traces");
165
                                LogTraces = 1;
166
                                break;
167
                        default:
168
                                print_usage(argc, argv);
169
                                return -1;
170 aba1367c GiuseppeTropea
                }
171
        }
172 e11386c0 CsabaKiraly
173
#ifdef EMULATE_CHUNK_LOSS
174
        ScheduledChunkLosses = NULL;
175
        cfg_opt_t scheduled_chunk_loss_opts[] =
176 31e4e8ba GiuseppeTropea
        {
177 e11386c0 CsabaKiraly
                CFG_INT("Time", 0, CFGF_NONE),
178
                CFG_INT("Value", 0, CFGF_NONE),
179
                CFG_INT("MinValue", 0, CFGF_NONE),
180
                CFG_INT("MaxValue", 0, CFGF_NONE),
181
                CFG_INT("Burstiness", 0, CFGF_NONE),
182
                CFG_END()
183
        };
184
        cfg_opt_t opts[] =
185
        {
186
                CFG_SEC("ScheduledChunkLoss", scheduled_chunk_loss_opts, CFGF_MULTI),
187
                CFG_END()
188
        };
189
        cfg_t *cfg, *cfg_sched;
190
        cfg = cfg_init(opts, CFGF_NONE);
191
        if(!cfg_parse(cfg, "_chunklossrate.conf") == CFG_PARSE_ERROR)
192
        {
193
                NScheduledChunkLosses = cfg_size(cfg, "ScheduledChunkLoss");
194
                if(NScheduledChunkLosses > 0)
195
                        ScheduledChunkLosses = (SChunkLoss*)malloc((NScheduledChunkLosses)*sizeof(SChunkLoss));
196
                
197
                int j;
198
                for(j = 0; j < cfg_size(cfg, "ScheduledChunkLoss"); j++)
199
                {
200
                        cfg_sched = cfg_getnsec(cfg, "ScheduledChunkLoss", j);
201
                        ScheduledChunkLosses[j].Time = cfg_getint(cfg_sched, "Time");
202
                        ScheduledChunkLosses[j].Value = cfg_getint(cfg_sched, "Value");
203
                        ScheduledChunkLosses[j].Burstiness = cfg_getint(cfg_sched, "Burstiness");
204
                        
205
                        // -1 means random value between min and max
206
                        if(ScheduledChunkLosses[j].Value == -1)
207
                        {
208
                                ScheduledChunkLosses[j].MinValue = cfg_getint(cfg_sched, "MinValue");
209
                                ScheduledChunkLosses[j].MaxValue = cfg_getint(cfg_sched, "MaxValue");
210
                        }
211
                }
212
                cfg_free(cfg);
213
                CurrChunkLossIndex = -1;
214
                
215
                for(j=0; j < NScheduledChunkLosses; j++)
216
                {
217
                        printf("ScheduledChunkLosses[%d].Time = %ld\n", j, ScheduledChunkLosses[j].Time);
218
                        printf("ScheduledChunkLosses[%d].Value = %d\n", j, ScheduledChunkLosses[j].Value);
219
                        printf("ScheduledChunkLosses[%d].Burstiness = %d\n", j, ScheduledChunkLosses[j].Burstiness);
220
                }
221 31e4e8ba GiuseppeTropea
        }
222 e11386c0 CsabaKiraly
#endif
223 dae4a53f GiuseppeTropea
224 e11386c0 CsabaKiraly
#ifdef HTTPIO
225 dae4a53f GiuseppeTropea
        //this thread fetches chunks from the network by listening to the following path, port
226 327da69f Csaba Kiraly
        daemon = (struct MHD_Daemon*)initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, Port);
227 dae4a53f GiuseppeTropea
        if(daemon == NULL)
228
        {
229
                printf("CANNOT START MICROHTTPD SERVICE, EXITING...\n");
230
                exit(2);
231
        }
232 e11386c0 CsabaKiraly
#endif
233
#ifdef TCPIO
234 327da69f Csaba Kiraly
        int fd = initChunkPuller(Port);
235 e11386c0 CsabaKiraly
        if(! (fd > 0))
236
        {
237
                printf("CANNOT START TCP PULLER...\n");
238
                exit(2);
239
        }
240
#endif
241 dae4a53f GiuseppeTropea
242 ccf75e3a GiuseppeTropea
        if(SilentMode == 0)
243 19b05fc0 GiuseppeTropea
        {
244
                if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
245 ccf75e3a GiuseppeTropea
                        fprintf(stderr, "Could not initialize SDL audio/video or timer - %s\n", SDL_GetError());
246
                        return -1;
247
                }
248
        }
249
        else if(SilentMode == 1)
250
        {
251
                if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
252
                        fprintf(stderr, "Could not initialize SDL audio or timer - %s\n", SDL_GetError());
253 19b05fc0 GiuseppeTropea
                        return -1;
254
                }
255
        }
256
        else
257
        {
258
                if(SDL_Init(SDL_INIT_TIMER)) {
259 ccf75e3a GiuseppeTropea
                        fprintf(stderr, "Could not initialize SDL timer - %s\n", SDL_GetError());
260 19b05fc0 GiuseppeTropea
                        return -1;
261
                }
262 1e69ae95 GiuseppeTropea
        }
263 3a240a99 GiuseppeTropea
        
264 10c75ef7 GiuseppeTropea
        if(ParseConf())
265 3a240a99 GiuseppeTropea
        {
266 10c75ef7 GiuseppeTropea
                printf("ERROR: Cannot parse configuration file, exit...\n");
267 3a240a99 GiuseppeTropea
                exit(1);
268 1e69ae95 GiuseppeTropea
        }
269 3a240a99 GiuseppeTropea
        
270 19b05fc0 GiuseppeTropea
        firstChannelIndex = -1;
271
        int it;
272
        for(it = 0; it < NChannels; it++)
273
        {
274 12948c73 Csaba Kiraly
                if(firstChannelName[0] == 0) {
275
                        firstChannelIndex = 0;
276
                        break;
277
                } else if (!strcmp(Channels[it].Title, firstChannelName))
278 19b05fc0 GiuseppeTropea
                {
279
                        firstChannelIndex = it;
280
                        break;
281
                }
282
        }
283
        
284
        if(firstChannelIndex < 0)
285
        {
286 12948c73 Csaba Kiraly
                printf("Cannot find the specified channel (%s) in the configuration file (channels.conf), exiting\n", firstChannelName);
287 19b05fc0 GiuseppeTropea
                exit(0);
288
        }
289
        
290 10c75ef7 GiuseppeTropea
        if(ChunkerPlayerGUI_Init())
291 aba1367c GiuseppeTropea
        {
292 10c75ef7 GiuseppeTropea
                printf("ERROR: Cannot init player gui, exit...\n");
293
                exit(1);
294 aba1367c GiuseppeTropea
        }
295 10c75ef7 GiuseppeTropea
        
296 19b05fc0 GiuseppeTropea
        SelectedChannel = firstChannelIndex;
297 dae4a53f GiuseppeTropea
298 10c75ef7 GiuseppeTropea
        SwitchChannel(&(Channels[SelectedChannel]));
299 1e69ae95 GiuseppeTropea
300
        // Wait for user input
301 f126ff44 GiuseppeTropea
        while(!quit) {
302 34149271 GiuseppeTropea
                if(QueueFillingMode) {
303 1e69ae95 GiuseppeTropea
                        SDL_WM_SetCaption("Filling buffer...", NULL);
304 34149271 GiuseppeTropea
305 31e4e8ba GiuseppeTropea
                        if(ChunkerPlayerCore_AudioEnded())
306 10c75ef7 GiuseppeTropea
                                ChunkerPlayerCore_ResetAVQueues();
307 34149271 GiuseppeTropea
308
#ifdef DEBUG_QUEUE
309 f126ff44 GiuseppeTropea
                        //printf("QUEUE: MAIN audio:%d video:%d audiolastframe:%d videolastframe:%d\n", audioq.nb_packets, videoq.nb_packets, audioq.last_frame_extracted, videoq.last_frame_extracted);
310 34149271 GiuseppeTropea
#endif
311
                }
312 1e69ae95 GiuseppeTropea
                else
313
                        SDL_WM_SetCaption("NAPA-Wine Player", NULL);
314 af11718f CarmeloDaniele
                
315
#ifdef PSNR_PUBLICATION
316
                event_base_loop(eventbase, EVLOOP_ONCE);
317
#endif
318 34149271 GiuseppeTropea
319 f126ff44 GiuseppeTropea
                //listen for key and mouse
320
                while(SDL_PollEvent(&event)) {
321 aba1367c GiuseppeTropea
                        switch(event.type) {
322
                                case SDL_QUIT:
323
                                        quit=1;
324
                                break;
325
                                case SDL_VIDEORESIZE:
326 31e4e8ba GiuseppeTropea
                                        if(SilentMode)
327
                                                break;
328 10c75ef7 GiuseppeTropea
                                        // printf("\tSDL_VIDEORESIZE event received!! \n");
329
                                        if(!FullscreenMode)
330
                                                ChunkerPlayerGUI_HandleResize(event.resize.w, event.resize.h);
331
                                        else
332
                                                ChunkerPlayerGUI_HandleResize(FullscreenWidth, FullscreenHeight);
333 aba1367c GiuseppeTropea
                                break;
334
                                case SDL_ACTIVEEVENT:
335 31e4e8ba GiuseppeTropea
                                        if(SilentMode)
336
                                                break;
337
                                                
338 aba1367c GiuseppeTropea
                                        // if the window was iconified or restored
339 3a240a99 GiuseppeTropea
                                        if(event.active.state & SDL_APPACTIVE)
340 aba1367c GiuseppeTropea
                                        {
341
                                                //If the application is being reactivated
342
                                                if( event.active.gain != 0 )
343
                                                {
344 10c75ef7 GiuseppeTropea
                                                        ChunkerPlayerGUI_HandleGetFocus();
345 aba1367c GiuseppeTropea
                                                }
346
                                        }
347 a8be2526 GiuseppeTropea
348 aba1367c GiuseppeTropea
                                        //If something happened to the keyboard focus
349
                                        else if( event.active.state & SDL_APPINPUTFOCUS )
350
                                        {
351
                                                //If the application gained keyboard focus
352
                                                if( event.active.gain != 0 )
353
                                                {
354 10c75ef7 GiuseppeTropea
                                                        ChunkerPlayerGUI_HandleGetFocus();
355 aba1367c GiuseppeTropea
                                                }
356
                                        }
357
                                        //If something happened to the mouse focus
358
                                        else if( event.active.state & SDL_APPMOUSEFOCUS )
359
                                        {
360
                                                //If the application gained mouse focus
361
                                                if( event.active.gain != 0 )
362
                                                {
363 10c75ef7 GiuseppeTropea
                                                        ChunkerPlayerGUI_HandleGetFocus();
364 aba1367c GiuseppeTropea
                                                }
365 3a240a99 GiuseppeTropea
                                        }
366 f126ff44 GiuseppeTropea
                                        break;
367 aba1367c GiuseppeTropea
                                case SDL_MOUSEMOTION:
368 31e4e8ba GiuseppeTropea
                                        if(SilentMode)
369
                                                break;
370
                                                
371 10c75ef7 GiuseppeTropea
                                        ChunkerPlayerGUI_HandleMouseMotion(event.motion.x, event.motion.y);
372 aba1367c GiuseppeTropea
                                break;
373
                                case SDL_MOUSEBUTTONUP:
374 31e4e8ba GiuseppeTropea
                                        if(SilentMode)
375
                                                break;
376
                                                
377 aba1367c GiuseppeTropea
                                        if( event.button.button != SDL_BUTTON_LEFT )
378 78068e21 GiuseppeTropea
                                                break;
379 10c75ef7 GiuseppeTropea
380
                                        ChunkerPlayerGUI_HandleLButton(event.motion.x, event.motion.y);
381 aba1367c GiuseppeTropea
                                break;
382 b3283200 Csaba Kiraly
                                case SDL_KEYDOWN:  /* Handle a KEYDOWN event */
383
                                        switch( event.key.keysym.sym ){
384
                                                case SDLK_ESCAPE:
385
                                                        if(FullscreenMode) {
386
                                                                ChunkerPlayerGUI_ToggleFullscreen();
387
                                                        }
388
                                                break;
389 edd61080 Csaba Kiraly
                                                case SDLK_r:
390
                                                        ChunkerPlayerGUI_ChangeRatio();
391
                                                break;
392
                                                default:
393
                                                break;
394 b3283200 Csaba Kiraly
                                        }
395
                                break;
396 aba1367c GiuseppeTropea
                        }
397 10c75ef7 GiuseppeTropea
                        ChunkerPlayerGUI_HandleKey();
398 1e69ae95 GiuseppeTropea
                }
399 34149271 GiuseppeTropea
                usleep(120000);
400 1e69ae95 GiuseppeTropea
        }
401 e11386c0 CsabaKiraly
402
        KILL_PROCESS(P2PProcessHandle);
403 f9cf0a8d GiuseppeTropea
404 f126ff44 GiuseppeTropea
        //TERMINATE
405 10c75ef7 GiuseppeTropea
        ChunkerPlayerCore_Stop();
406
        if(YUVOverlay != NULL)
407
                SDL_FreeYUVOverlay(YUVOverlay);
408
        
409
        ChunkerPlayerGUI_Close();
410
        SDL_DestroyMutex(OverlayMutex);
411 26379a77 GiuseppeTropea
        SDL_Quit();
412 e11386c0 CsabaKiraly
        
413
#ifdef HTTPIO
414 e810bf7b GiuseppeTropea
        finalizeChunkPuller(daemon);
415 e11386c0 CsabaKiraly
#endif
416
#ifdef TCPIO
417
        finalizeChunkPuller();
418
#endif
419
        
420
#ifdef EMULATE_CHUNK_LOSS
421
        if(ScheduledChunkLosses)
422
                free(ScheduledChunkLosses);
423
#endif
424 59e008ed GiuseppeTropea
425
#ifdef PSNR_PUBLICATION
426 af11718f CarmeloDaniele
        if(repoclient) repClose(repoclient);
427 59e008ed GiuseppeTropea
        event_base_free(eventbase);
428
#endif
429 1e69ae95 GiuseppeTropea
        return 0;
430
}
431
432 e11386c0 CsabaKiraly
int cb_validate_conffile(cfg_t *cfg)
433
{
434
        char LaunchString[255];
435
        cfg_t *cfg_greet;
436
        
437
        if(cfg_size(cfg, "Channel") == 0)
438
        {
439
                cfg_error(cfg, "no \"Channel\" section found");
440
                return -1;
441
        }
442
        
443
        printf("\t%d Channel setions found\n", cfg_size(cfg, "Channel"));
444
        
445
        int j;
446
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
447
        {
448
                cfg_greet = cfg_getnsec(cfg, "Channel", j);
449
                sprintf(LaunchString, "%s", cfg_getstr(cfg_greet, "LaunchString"));
450
                if(!(strlen(LaunchString) > 0))
451
                {
452
                        cfg_error(cfg, "invalid LaunchString for Channel[%d]", j);
453
                        return -1;
454
                }
455
                printf("\tChannel[%d].LaunchString = %s\n", j, LaunchString);
456
                printf("\tChannel[%d].AudioChannels = %ld\n", j, cfg_getint(cfg_greet, "AudioChannels"));
457
                printf("\tChannel[%d].SampleRate = %ld\n", j, cfg_getint(cfg_greet, "SampleRate"));
458
                printf("\tChannel[%d].Width = %ld\n", j, cfg_getint(cfg_greet, "Width"));
459
                printf("\tChannel[%d].Height = %ld\n", j, cfg_getint(cfg_greet, "Height"));
460
                printf("\tChannel[%d].Bitrate = %ld\n", j, cfg_getint(cfg_greet, "Bitrate"));
461
                printf("\tChannel[%d].Ratio = %s\n", j, cfg_getstr(cfg_greet, "Ratio"));
462
        }
463
    return 0;
464
}
465
466 10c75ef7 GiuseppeTropea
int ParseConf()
467 78068e21 GiuseppeTropea
{
468
        int j;
469
        
470
        // PARSING CONF FILE
471
        cfg_opt_t channel_opts[] =
472
        {
473
                CFG_STR("Title", "", CFGF_NONE),
474
                CFG_STR("LaunchString", "", CFGF_NONE),
475 3a240a99 GiuseppeTropea
                CFG_INT("AudioChannels", 2, CFGF_NONE),
476
                CFG_INT("SampleRate", 48000, CFGF_NONE),
477
                CFG_INT("Width", 176, CFGF_NONE),
478
                CFG_INT("Height", 144, CFGF_NONE),
479 e11386c0 CsabaKiraly
                CFG_INT("Bitrate", 0, CFGF_NONE),
480 71fa7249 Csaba Kiraly
                CFG_STR("VideoCodec", "mpeg4", CFGF_NONE),
481
                CFG_STR("AudioCodec", "mp3", CFGF_NONE),
482 e11386c0 CsabaKiraly
                
483
                // for some reason libconfuse parsing for floating point does not work in windows
484
                //~ CFG_FLOAT("Ratio", 1.22, CFGF_NONE),
485
                CFG_STR("Ratio", "1.22", CFGF_NONE),
486 78068e21 GiuseppeTropea
                CFG_END()
487
        };
488
        cfg_opt_t opts[] =
489
        {
490
                CFG_SEC("Channel", channel_opts, CFGF_TITLE | CFGF_MULTI),
491
                CFG_END()
492
        };
493
        cfg_t *cfg, *cfg_channel;
494
        cfg = cfg_init(opts, CFGF_NONE);
495
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_PARSE_ERROR)
496
        {
497 fc014e26 GiuseppeTropea
                printf("Error while parsing configuration file, exiting...\n");
498 e11386c0 CsabaKiraly
                cb_validate_conffile(cfg);
499 fc014e26 GiuseppeTropea
                return 1;
500
        }
501
        
502
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_FILE_ERROR)
503
        {
504
                printf("Error trying parsing configuration file. '%s' file couldn't be opened for reading\n", DEFAULT_CONF_FILENAME);
505 78068e21 GiuseppeTropea
                return 1;
506
        }
507 fc014e26 GiuseppeTropea
        
508 569b286f GiuseppeTropea
        FILE * tmp_file;
509 e11386c0 CsabaKiraly
        if(tmp_file = fopen(DEFAULT_PEEREXECNAME_FILENAME, "r")) {
510
                if(fscanf(tmp_file, "%s", StreamerFilename) != 1) {
511
                        printf("Wrong format of conf file %s containing peer application exec name. Assuming default: %s.\n\n", DEFAULT_PEEREXECNAME_FILENAME, DEFAULT_PEER_EXEC_NAME);
512
                }
513
                fclose(tmp_file);
514
        }
515
        else {
516
                printf("Could not find conf file %s containing peer application exec name. Exiting.\n\n", DEFAULT_PEEREXECNAME_FILENAME);
517
                exit(1);
518
        }
519
        if(tmp_file = fopen(StreamerFilename, "r"))
520 569b286f GiuseppeTropea
    {
521
        fclose(tmp_file);
522
    }
523
    else
524
        {
525 e11386c0 CsabaKiraly
                printf("Could not find peer application (named '%s') into the current folder, please copy or link it into the player folder, then retry\n\n", StreamerFilename);
526 569b286f GiuseppeTropea
                exit(1);
527
        }
528
        
529 78068e21 GiuseppeTropea
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
530
        {
531
                cfg_channel = cfg_getnsec(cfg, "Channel", j);
532
                sprintf(Channels[j].Title, "%s", cfg_title(cfg_channel));
533 cf26d11f GiuseppeTropea
                strcpy(Channels[j].LaunchString, cfg_getstr(cfg_channel, "LaunchString"));
534 71fa7249 Csaba Kiraly
                strcpy(Channels[j].VideoCodec, cfg_getstr(cfg_channel, "VideoCodec"));
535
                strcpy(Channels[j].AudioCodec, cfg_getstr(cfg_channel, "AudioCodec"));
536 3a240a99 GiuseppeTropea
                Channels[j].Width = cfg_getint(cfg_channel, "Width");
537
                Channels[j].Height = cfg_getint(cfg_channel, "Height");
538
                Channels[j].AudioChannels = cfg_getint(cfg_channel, "AudioChannels");
539
                Channels[j].SampleRate = cfg_getint(cfg_channel, "SampleRate");
540 e11386c0 CsabaKiraly
                Channels[j].Ratio = strtof(cfg_getstr(cfg_channel, "Ratio"), 0);
541
                Channels[j].Bitrate = cfg_getint(cfg_channel, "Bitrate");
542
                
543 10c75ef7 GiuseppeTropea
                Channels[j].Index = j+1;
544 78068e21 GiuseppeTropea
                NChannels++;
545
        }
546
        cfg_free(cfg);
547
548 10c75ef7 GiuseppeTropea
        return 0;
549 78068e21 GiuseppeTropea
}
550
551 e11386c0 CsabaKiraly
int ReTune(SChannel* channel)
552
{        
553
        if(ChunkerPlayerCore_IsRunning())
554
                ChunkerPlayerCore_Pause();
555
        
556
        //reset quality info
557
        channel->startTime = time(NULL);
558
        
559
        ChunkerPlayerCore_Play();
560
        
561
        return 0;
562
}
563
564 10c75ef7 GiuseppeTropea
int SwitchChannel(SChannel* channel)
565 78068e21 GiuseppeTropea
{
566 dae4a53f GiuseppeTropea
        int i=0;
567 10c75ef7 GiuseppeTropea
#ifdef RESTORE_SCREEN_ON_ZAPPING
568
        int was_fullscreen = FullscreenMode;
569
        int old_width = window_width, old_height = window_height;
570
#endif
571
        
572
        if(ChunkerPlayerCore_IsRunning())
573
                ChunkerPlayerCore_Stop();
574 3a240a99 GiuseppeTropea
575 74564eb3 CarmeloDaniele
    KILL_PROCESS(P2PProcessHandle);
576 57b6471f Csaba Kiraly
#ifdef PSNR_PUBLICATION
577 74564eb3 CarmeloDaniele
        remove("NetworkID");
578 57b6471f Csaba Kiraly
#endif
579 10c75ef7 GiuseppeTropea
        
580 edd61080 Csaba Kiraly
        ChunkerPlayerGUI_SetChannelRatio(channel->Ratio);
581 10c75ef7 GiuseppeTropea
        ChunkerPlayerGUI_SetChannelTitle(channel->Title);
582
        ChunkerPlayerGUI_ForceResize(channel->Width, channel->Height);
583
        
584 e11386c0 CsabaKiraly
        int w=0, h=0;
585
        ChunkerPlayerGUI_AspectRatioResize((float)channel->Ratio, channel->Width, channel->Height, &w, &h);
586
        ChunkerPlayerCore_SetupOverlay(w, h);
587 e8699fac GiuseppeTropea
        //ChunkerPlayerGUI_SetupOverlayRect(channel);
588 10c75ef7 GiuseppeTropea
        
589 71fa7249 Csaba Kiraly
        if(ChunkerPlayerCore_InitCodecs(channel->VideoCodec, channel->Width, channel->Height, channel->AudioCodec, channel->SampleRate, channel->AudioChannels) < 0)
590 78068e21 GiuseppeTropea
        {
591 e11386c0 CsabaKiraly
                printf("ERROR, COULD NOT INITIALIZE CODECS\n");
592
                exit(2);
593 78068e21 GiuseppeTropea
        }
594 e11386c0 CsabaKiraly
        
595 b9e6f879 CsabaKiraly
        //reset quality info
596
        channel->startTime = time(NULL);
597
        channel->instant_score = 0.0;
598
        channel->average_score = 0.0;
599
        channel->history_index = 0;
600
        for(i=0; i<CHANNEL_SCORE_HISTORY_SIZE; i++)
601
                channel->score_history[i] = -1;
602
        sprintf(channel->quality, "EVALUATING...");
603 e11386c0 CsabaKiraly
        
604 b0e46569 GiuseppeTropea
        char argv0[255], parameters_string[511];
605
        sprintf(argv0, "%s", StreamerFilename);
606 b9e6f879 CsabaKiraly
607 e11386c0 CsabaKiraly
#ifdef HTTPIO
608 327da69f Csaba Kiraly
        sprintf(parameters_string, "%s %s %s %d %s %s %d", "-C", channel->Title, "-P", (Port+channel->Index), channel->LaunchString, "-F", Port);
609 e11386c0 CsabaKiraly
#endif
610 b9e6f879 CsabaKiraly
611 e11386c0 CsabaKiraly
#ifdef TCPIO
612 b43b48ff Csaba Kiraly
        sprintf(parameters_string, "%s %s %s %d %s %s tcp://127.0.0.1:%d", "-C", channel->Title, "-P", (Port+channel->Index), channel->LaunchString, "-F", Port);
613 e11386c0 CsabaKiraly
#endif
614 78068e21 GiuseppeTropea
615 b0e46569 GiuseppeTropea
        printf("OFFERSTREAMER LAUNCH STRING: %s %s\n", argv0, parameters_string);
616 78068e21 GiuseppeTropea
617 b0e46569 GiuseppeTropea
        if(SilentMode != 3) //mode 3 is without P2P peer process
618
        {
619 0cd6b05d CarmeloDaniele
620 18855fca Csaba Kiraly
                char* parameters_vector[255];
621
                parameters_vector[0] = argv0;
622
623
                RepoAddress[0]='\0';
624
625
                // split parameters and count them
626
                int par_count=1;
627
                char* pch = strtok (parameters_string, " ");
628
                while (pch != NULL)
629
                {
630
                        if(par_count > 255) break;
631
                        // printf ("\tpch=%s\n",pch);
632
                        parameters_vector[par_count] = (char*) malloc(sizeof(char)*(strlen(pch)+1));
633
                        strcpy(parameters_vector[par_count], pch);
634
                        // Find repo_address
635
                        CheckForRepoAddress(parameters_vector[par_count]);
636
                        pch = strtok (NULL, " ");
637
                        par_count++;
638
                }
639
                parameters_vector[par_count] = NULL;
640
641 47943338 GiuseppeTropea
#ifndef __WIN32__
642 e11386c0 CsabaKiraly
                int d;
643
                int stdoutS, stderrS;
644
                FILE* stream;
645
                stream = fopen("/dev/null", "a+");
646
                d = fileno(stream);
647
648
                // create backup descriptors for the current stdout and stderr devices
649
                stdoutS = dup(STDOUT_FILENO);
650
                stderrS = dup(STDERR_FILENO);
651 10c75ef7 GiuseppeTropea
                
652 e11386c0 CsabaKiraly
                // redirect child output to /dev/null
653
                dup2(d, STDOUT_FILENO);
654 bdf6152e Csaba Kiraly
                //dup2(d, STDERR_FILENO);
655 e11386c0 CsabaKiraly
656
                int pid = fork();
657
                if(pid == 0)
658
                {
659
                        execv(argv0, parameters_vector);
660
                        printf("ERROR, COULD NOT LAUNCH OFFERSTREAMER\n");
661
                        exit(2);
662
                }
663
                else
664
                        *((pid_t*)P2PProcessHandle) = pid;
665
                
666
                // restore backup descriptors in the parent process
667
                dup2(stdoutS, STDOUT_FILENO);
668
                dup2(stderrS, STDERR_FILENO);
669 10c75ef7 GiuseppeTropea
670 b0e46569 GiuseppeTropea
                fclose(stream);
671 e11386c0 CsabaKiraly
#else
672
                STARTUPINFO sti;
673
                SECURITY_ATTRIBUTES sats = { 0 };
674
                DWORD writ, excode, read, available;
675
                int ret = 0;
676
677
                //set SECURITY_ATTRIBUTES struct fields
678
                sats.nLength = sizeof(sats);
679
                sats.bInheritHandle = TRUE;
680
                sats.lpSecurityDescriptor = NULL;
681
682
                ZeroMemory( &sti, sizeof(sti) );
683
                sti.cb = sizeof(sti);
684
                ZeroMemory( P2PProcessHandle, sizeof(PROCESS_INFORMATION) );
685
686
                char buffer[512];
687
                sprintf(buffer, "%s %s", argv0, parameters_string);
688
689
                if(!CreateProcess(NULL,
690
                  buffer,
691
                  &sats,
692
                  &sats,
693
                  TRUE,
694
                  0,
695
                  NULL,
696
                  NULL,
697
                  &sti,
698
                  P2PProcessHandle))
699
                {
700
                        printf("Unable to generate process \n");
701
                        return -1;
702
                }
703 add73b22 CarmeloDaniele
#endif
704
705 47943338 GiuseppeTropea
                for(i=1; i<par_count; i++)
706
                        free(parameters_vector[i]);
707 e11386c0 CsabaKiraly
        }
708 b0e46569 GiuseppeTropea
709
#ifdef RESTORE_SCREEN_ON_ZAPPING
710
        if(SilentMode == 0) {
711
                if(was_fullscreen)
712
                        ChunkerPlayerGUI_ToggleFullscreen();
713
                else
714
                {
715
                        ChunkerPlayerGUI_HandleResize(old_width, old_height);
716
                }
717
        }
718
#endif
719
720
#ifdef PSNR_PUBLICATION
721 18855fca Csaba Kiraly
        if(RepoAddress[0]!='\0')        // TODO: search for RepoAddress currently disabled on linux
722 af11718f CarmeloDaniele
        {
723
            // Open Repository
724
            if(repoclient)
725
                    repClose(repoclient);
726
            repoclient=NULL;
727
728
            repoclient = repOpen(RepoAddress,0);
729
            if (repoclient == NULL)
730
                    printf("Unable to initialize PSNR publication in repoclient %s\n", RepoAddress);
731
    }
732
    else {
733
            printf("Repository address not present in streames launch string. Publication disabled\n");
734
    }
735 b0e46569 GiuseppeTropea
#endif
736
737 59e008ed GiuseppeTropea
738 57b6471f Csaba Kiraly
#ifdef PSNR_PUBLICATION
739 74564eb3 CarmeloDaniele
        // Read the Network ID
740
        int Error=true;
741
        char Line1[255], Line2[255];
742
        while(Error)
743
        {
744
            FILE* fp=fopen("NetworkID","r");
745
            if(fp)
746
            {
747
                if(ReadALine(fp,Line1,255)!=-1)
748
                    if(ReadALine(fp,Line2,255)!=-1)
749
                    {
750
                        if(strcmp(Line2,"IDEnd")==0)
751
                        {
752
                            strcpy(NetworkID,Line1);
753
                            Error=false;
754
                        }
755
                    }
756
                fclose(fp);
757
            }
758
            if(Error) usleep(100000);
759
        }
760
        
761
        printf("NetworkID = %s\n",NetworkID);
762 57b6471f Csaba Kiraly
#endif
763 74564eb3 CarmeloDaniele
        
764 e11386c0 CsabaKiraly
        ChunkerPlayerCore_Play();
765
        ChunkerPlayerGUI_ChannelSwitched();
766
        return 0;
767 78068e21 GiuseppeTropea
}
768
769 10c75ef7 GiuseppeTropea
void ZapDown()
770 fc014e26 GiuseppeTropea
{
771 10c75ef7 GiuseppeTropea
        SelectedChannel = ((SelectedChannel+1) %NChannels);
772
        SwitchChannel(&(Channels[SelectedChannel]));
773 fc014e26 GiuseppeTropea
}
774
775 10c75ef7 GiuseppeTropea
void ZapUp()
776 3a240a99 GiuseppeTropea
{
777 10c75ef7 GiuseppeTropea
        SelectedChannel--;
778
        if(SelectedChannel < 0)
779
                SelectedChannel = NChannels-1;
780 3a240a99 GiuseppeTropea
781 10c75ef7 GiuseppeTropea
        SwitchChannel(&(Channels[SelectedChannel]));
782 3a240a99 GiuseppeTropea
}
783
784 10c75ef7 GiuseppeTropea
int enqueueBlock(const uint8_t *block, const int block_size)
785 3a240a99 GiuseppeTropea
{
786 10c75ef7 GiuseppeTropea
        return ChunkerPlayerCore_EnqueueBlocks(block, block_size);
787 3a240a99 GiuseppeTropea
}