Statistics
| Branch: | Revision:

chunker-player / chunker_player / chunker_player.c @ 78068e21

History | View | Annotate | Download (50.9 KB)

1
// player.c
2
// Author 
3
// Diego Reforgiato, Dario Marchese, Carmelo Daniele, Giuseppe Tropea
4
//
5
// Use the file compile to compile the program to build (assuming libavformat and libavcodec are 
6
// correctly installed your system).
7
//
8
// Run using
9
//
10
// player <width> <height>
11

    
12
#include <libavcodec/avcodec.h>
13
#include <libavformat/avformat.h>
14
#include <libswscale/swscale.h>
15

    
16
#include <stdio.h>
17
#include <dirent.h>
18
#include <string.h>
19
#include <stdlib.h>
20
#include <sys/time.h>
21
#include <unistd.h>
22
#include <signal.h>
23
#include <SDL.h>
24
#include <SDL_thread.h>
25
#include <SDL_mutex.h>
26
#include <SDL_image.h>
27
#include <math.h>
28
#include <confuse.h>
29

    
30
#ifdef __MINGW32__
31
#undef main /* Prevents SDL from overriding main() */
32
#endif
33

    
34
#include "http_default_urls.h"
35
#include "chunker_player.h"
36
#include "codec_definitions.h"
37

    
38
#ifdef __WIN32__
39
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "taskkill /pid %d /F", pid); system(command_name);}
40
#endif
41
#ifdef __LINUX__
42
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "kill %d", pid); system(command_name);}
43
#endif
44
#ifdef __MACOS__
45
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "kill %d", pid); system(command_name);}
46
#endif
47

    
48
void packet_queue_init(PacketQueue *q, short int Type) {
49
#ifdef DEBUG_QUEUE
50
        printf("QUEUE: INIT BEGIN: NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
51
#endif
52
        memset(q,0,sizeof(PacketQueue));
53
        q->mutex = SDL_CreateMutex();
54
        QueueFillingMode=1;
55
        q->queueType=Type;
56
        q->last_frame_extracted = -1;
57
        q->total_lost_frames = 0;
58
        q->first_pkt= NULL;
59
        //q->last_pkt = NULL;
60
        q->nb_packets = 0;
61
        q->size = 0;
62
        q->density= 0.0;
63
        FirstTime = 1;
64
        FirstTimeAudio = 1;
65
#ifdef DEBUG_QUEUE
66
        printf("QUEUE: INIT END: NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
67
#endif
68
}
69

    
70
void packet_queue_reset(PacketQueue *q, short int Type) {
71
        AVPacketList *tmp,*tmp1;
72
#ifdef DEBUG_QUEUE
73
        printf("QUEUE: RESET BEGIN: NPackets=%d Type=%d LastExtr=%d\n", q->nb_packets, q->queueType, q->last_frame_extracted);
74
#endif
75
        SDL_LockMutex(q->mutex);
76

    
77
        tmp = q->first_pkt;
78
        while(tmp) {
79
                tmp1 = tmp;
80
                tmp = tmp->next;
81
                av_free_packet(&(tmp1->pkt));
82
                av_free(tmp1);
83
#ifdef DEBUG_QUEUE
84
                printf("F ");
85
#endif
86
        }
87
#ifdef DEBUG_QUEUE
88
        printf("\n");
89
#endif
90

    
91
        QueueFillingMode=1;
92
        q->last_frame_extracted = -1;
93
        q->total_lost_frames = 0;
94
        q->first_pkt= NULL;
95
        //q->last_pkt = NULL;
96
        q->nb_packets = 0;
97
        q->size = 0;
98
        q->density= 0.0;
99
        FirstTime = 1;
100
        FirstTimeAudio = 1;
101
#ifdef DEBUG_QUEUE
102
        printf("QUEUE: RESET END: NPackets=%d Type=%d LastExtr=%d\n", q->nb_packets, q->queueType, q->last_frame_extracted);
103
#endif
104
        SDL_UnlockMutex(q->mutex);
105
}
106

    
107
int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
108
        short int skip = 0;
109
        AVPacketList *pkt1, *tmp, *prevtmp;
110
/*
111
        if(q->nb_packets > QUEUE_MAX_SIZE) {
112
#ifdef DEBUG_QUEUE
113
                printf("QUEUE: PUT i have TOO MANY packets %d Type=%d\n", q->nb_packets, q->queueType);
114
#endif    
115
                return -1;
116
  }
117
*/
118
        //make a copy of the incoming packet
119
        if(av_dup_packet(pkt) < 0) {
120
#ifdef DEBUG_QUEUE
121
                printf("QUEUE: PUT in Queue cannot duplicate in packet        : NPackets=%d Type=%d\n",q->nb_packets, q->queueType);
122
#endif
123
                return -1;
124
        }
125
        pkt1 = av_malloc(sizeof(AVPacketList));
126

    
127
        if(!pkt1) {
128
                av_free_packet(pkt);
129
                return -1;
130
        }
131
        pkt1->pkt = *pkt;
132
        pkt1->next = NULL;
133

    
134
        SDL_LockMutex(q->mutex);
135

    
136
        // INSERTION SORT ALGORITHM
137
        // before inserting pkt, check if pkt.stream_index is <= current_extracted_frame.
138
//        if(pkt->stream_index > q->last_frame_extracted) {
139
                // either checking starting from the first_pkt or needed other struct like AVPacketList with next and prev....
140
                //if (!q->last_pkt)
141
                if(!q->first_pkt) {
142
                        q->first_pkt = pkt1;
143
                        q->last_pkt = pkt1;
144
                }
145
                else if(pkt->stream_index < q->first_pkt->pkt.stream_index) {
146
                        //the packet that has arrived is earlier than the first we got some time ago!
147
                        //we need to put it at the head of the queue
148
                        pkt1->next = q->first_pkt;
149
                        q->first_pkt = pkt1;
150
                }
151
                else {
152
                        tmp = q->first_pkt;
153
                        while(tmp->pkt.stream_index < pkt->stream_index) {
154
                                prevtmp = tmp;
155
                                tmp = tmp->next;
156

    
157
                                if(!tmp) {
158
                                        break;
159
                                }
160
                        }
161
                        if(tmp && tmp->pkt.stream_index == pkt->stream_index) {
162
                                //we already have a frame with that index
163
                                skip = 1;
164
#ifdef DEBUG_QUEUE
165
                                printf("QUEUE: PUT: we already have frame with index %d, skipping\n", pkt->stream_index);
166
#endif
167
                        }
168
                        else {
169
                                prevtmp->next = pkt1;
170
                                pkt1->next = tmp;
171
                                if(pkt1->next == NULL)
172
                                        q->last_pkt = pkt1;
173
                        }
174
                        //q->last_pkt->next = pkt1; // It was uncommented when not insertion sort
175
                }
176
                if(skip == 0) {
177
                        //q->last_pkt = pkt1;
178
                        q->nb_packets++;
179
                        q->size += pkt1->pkt.size;
180
                        if(q->nb_packets>=queue_filling_threshold && QueueFillingMode) // && q->queueType==AUDIO)
181
                        {
182
                                QueueFillingMode=0;
183
#ifdef DEBUG_QUEUE
184
                                printf("QUEUE: PUT: FillingMode set to zero\n");
185
#endif
186
                        }
187
                }
188
//        }
189
/*
190
        else {
191
                av_free_packet(&pkt1->pkt);
192
                av_free(pkt1);
193
#ifdef DEBUG_QUEUE
194
                                printf("QUEUE: PUT: NOT inserting because index %d > last extracted %d\n", pkt->stream_index, q->last_frame_extracted);
195
#endif
196
        }
197
*/
198
        if(q->last_pkt->pkt.stream_index > q->first_pkt->pkt.stream_index)
199
                q->density = (double)q->nb_packets / (double)(q->last_pkt->pkt.stream_index - q->first_pkt->pkt.stream_index) * 100.0;
200

    
201
#ifdef DEBUG_STATS
202
        if(q->queueType == AUDIO)
203
                printf("STATS: AUDIO QUEUE DENSITY percentage %f\n", q->density);
204
        if(q->queueType == VIDEO)
205
                printf("STATS: VIDEO QUEUE DENSITY percentage %f\n", q->density);
206
#endif
207

    
208
        SDL_UnlockMutex(q->mutex);
209
        return 0;
210
}
211

    
212

    
213
int decode_enqueued_audio_packet(AVPacket *pkt, PacketQueue *q) {
214
        uint16_t *audio_bufQ = NULL;
215
        int16_t *dataQ = NULL;
216
        int data_sizeQ = AVCODEC_MAX_AUDIO_FRAME_SIZE;
217
        int lenQ;
218
        int ret = 0;
219

    
220
        //set the flag to decoded anyway        
221
        pkt->convergence_duration = -1;
222

    
223
        audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
224
        if(audio_bufQ) {
225
#ifdef DEBUG_AUDIO_BUFFER
226
                printf("AUDIO_BUFFER: about to decode packet %d, size %d, data %d\n", pkt->stream_index, pkt->size, pkt->data);
227
#endif
228
                //decode the packet data
229
                lenQ = avcodec_decode_audio3(aCodecCtx, (int16_t *)audio_bufQ, &data_sizeQ, pkt);
230
                if(lenQ > 0) {
231
                        dataQ = (int16_t *)av_malloc(data_sizeQ); //this will be free later at the time of playback
232
                        if(dataQ) {
233
                                memcpy(dataQ, audio_bufQ, data_sizeQ);
234
                                //discard the old encoded bytes
235
                                av_free(pkt->data);
236
                                //subtract them from queue size
237
                                q->size -= pkt->size;
238
                                pkt->data = (int8_t *)dataQ;
239
                                pkt->size = data_sizeQ;
240
                                //add new size to queue size
241
                                q->size += pkt->size;
242
                                ret = 1;
243
                        }
244
                        else {
245
#ifdef DEBUG_AUDIO_BUFFER
246
                                printf("AUDIO_BUFFER: cannot alloc space for decoded packet %d\n", pkt->stream_index);
247
#endif
248
                        }
249
                }
250
                else {
251
#ifdef DEBUG_AUDIO_BUFFER
252
                        printf("AUDIO_BUFFER: cannot decode packet %d\n", pkt->stream_index);
253
#endif
254
                }
255
                av_free(audio_bufQ);
256
        }
257
        else {
258
#ifdef DEBUG_AUDIO_BUFFER
259
                printf("AUDIO_BUFFER: cannot alloc decode buffer for packet %d\n", pkt->stream_index);
260
#endif
261
        }
262
        return ret; //problems occurred
263
}
264

    
265
//removes a packet from the list and returns the next
266
AVPacketList *remove_from_queue(PacketQueue *q, AVPacketList *p) {
267
        AVPacketList *retpk = p->next;
268
        q->nb_packets--;
269
        //adjust size here and not in the various cases of the dequeue
270
        q->size -= p->pkt.size;
271
        if(&p->pkt)
272
                av_free_packet(&p->pkt);
273
        if(p)
274
                av_free(p);
275
        return retpk;
276
}
277

    
278
AVPacketList *seek_and_decode_packet_starting_from(AVPacketList *p, PacketQueue *q) {
279
        while(p) {
280
                        //check if audio packet has been already decoded
281
                        if(p->pkt.convergence_duration == 0) {
282
                                //not decoded yet, try to decode it
283
                                if( !decode_enqueued_audio_packet(&(p->pkt), q) ) {
284
                                        //it was not possible to decode this packet, return next one
285
                                        p = remove_from_queue(q, p);
286
                                }
287
                                else
288
                                        return p;
289
                        }
290
                        else
291
                                return p;
292
        }
293
        return NULL;
294
}
295

    
296
void update_queue_stats(PacketQueue *q, int packet_index) {
297
        double percentage = 0.0;        
298
        //compute lost frame statistics
299
        if(q->last_frame_extracted > 0 && packet_index > q->last_frame_extracted) {
300
                q->total_lost_frames = q->total_lost_frames + packet_index - q->last_frame_extracted - 1;
301
                percentage = (double)q->total_lost_frames / (double)q->last_frame_extracted * 100.0;
302
#ifdef DEBUG_STATS
303
                if(q->queueType == AUDIO)
304
                        printf("STATS: AUDIO FRAMES LOST: total %d percentage %f\n", q->total_lost_frames, percentage);
305
                else if(q->queueType == VIDEO)
306
                        printf("STATS: VIDEO FRAMES LOST: total %d percentage %f\n", q->total_lost_frames, percentage);
307
#endif
308
        }
309
}
310

    
311
int packet_queue_get(PacketQueue *q, AVPacket *pkt, short int av) {
312
        //AVPacket tmp;
313
        AVPacketList *pkt1 = NULL;
314
        int ret=-1;
315
        int SizeToCopy=0;
316

    
317
        SDL_LockMutex(q->mutex);
318

    
319
#ifdef DEBUG_QUEUE
320
        printf("QUEUE: Get NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
321
#endif
322

    
323
        if((q->queueType==AUDIO && QueueFillingMode) || QueueStopped)
324
        {
325
                SDL_UnlockMutex(q->mutex);
326
                return -1;
327
        }
328

    
329
        if(av==1) { //somebody requested an audio packet, q is the audio queue
330
                //try to dequeue the first packet of the audio queue
331
                pkt1 = seek_and_decode_packet_starting_from(q->first_pkt, q);
332
                if(pkt1) { //yes we have them!
333
                        if(pkt1->pkt.size-AudioQueueOffset > dimAudioQ) {
334
                                //one packet if enough to give us the requested number of bytes by the audio_callback
335
#ifdef DEBUG_QUEUE
336
                                printf("  AV=1 and Extract from the same packet\n");
337
#endif
338
                                pkt->size = dimAudioQ;
339
                                memcpy(pkt->data,pkt1->pkt.data+AudioQueueOffset,dimAudioQ);
340
                                pkt->dts = pkt1->pkt.dts;
341
                                pkt->pts = pkt1->pkt.pts;
342
                                pkt->stream_index = pkt1->pkt.stream_index;//1;
343
                                pkt->flags = 1;
344
                                pkt->pos = -1;
345
                                pkt->convergence_duration = -1;
346
#ifdef DEBUG_QUEUE
347
                                printf("   Adjust timestamps Old = %lld New = %lld\n", pkt1->pkt.dts, (int64_t)(pkt1->pkt.dts + deltaAudioQ + deltaAudioQError));
348
#endif
349
                                int64_t Olddts=pkt1->pkt.dts;
350
                                pkt1->pkt.dts += deltaAudioQ + deltaAudioQError;
351
                                pkt1->pkt.pts += deltaAudioQ + deltaAudioQError;
352
                                deltaAudioQError=(float)Olddts + deltaAudioQ + deltaAudioQError - (float)pkt1->pkt.dts;
353
                                AudioQueueOffset += dimAudioQ;
354
#ifdef DEBUG_QUEUE
355
                                printf("   deltaAudioQError = %f\n",deltaAudioQError);
356
#endif
357
                                //update overall state of queue
358
                                //size is diminished because we played some audio samples
359
                                //but packet is not removed since a portion has still to be played
360
                                //HINT ERRATA we had a size mismatch since size grows with the
361
                                //number of compressed bytes, and diminishes here with the number
362
                                //of raw uncompressed bytes, hence we update size during the
363
                                //real removes and not here anymore
364
                                //q->size -= dimAudioQ;
365
                                update_queue_stats(q, pkt->stream_index);
366
                                //update index of last frame extracted
367
                                q->last_frame_extracted = pkt->stream_index;
368
#ifdef DEBUG_AUDIO_BUFFER
369
                                printf("1: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
370
#endif
371
                                ret = 1; //OK
372
                        }
373
                        else {
374
                                //we need bytes from two consecutive packets to satisfy the audio_callback
375
#ifdef DEBUG_QUEUE
376
                                printf("  AV = 1 and Extract from 2 packets\n");
377
#endif
378
                                //check for a valid next packet since we will finish the current packet
379
                                //and also take some bytes from the next one
380
                                pkt1->next = seek_and_decode_packet_starting_from(pkt1->next, q);
381
                                if(pkt1->next) {
382
#ifdef DEBUG_QUEUE
383
                                        printf("   we have a next...\n");
384
#endif
385
                                        pkt->size = dimAudioQ;
386
                                        pkt->dts = pkt1->pkt.dts;
387
                                        pkt->pts = pkt1->pkt.pts;
388
                                        pkt->stream_index = pkt1->pkt.stream_index;//1;
389
                                        pkt->flags = 1;
390
                                        pkt->pos = -1;
391
                                        pkt->convergence_duration = -1;
392
                                        {
393
                                                SizeToCopy=pkt1->pkt.size-AudioQueueOffset;
394
#ifdef DEBUG_QUEUE
395
                                                printf("      SizeToCopy=%d\n",SizeToCopy);
396
#endif
397
                                                memcpy(pkt->data, pkt1->pkt.data+AudioQueueOffset, SizeToCopy);
398
                                                memcpy(pkt->data+SizeToCopy, pkt1->next->pkt.data, (dimAudioQ-SizeToCopy)*sizeof(uint8_t));
399
                                        }
400
#ifdef DEBUG_AUDIO_BUFFER
401
                                        printf("2: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
402
#endif
403
                                }
404
#ifdef DEBUG_AUDIO_BUFFER
405
                                else {
406
                                        printf("2: NONEXT\n");
407
                                }
408
#endif
409
                                //HINT SEE before q->size -= SizeToCopy;
410
                                q->first_pkt = remove_from_queue(q, pkt1);
411

    
412
                                // Adjust timestamps
413
                                pkt1 = q->first_pkt;
414
                                if(pkt1) {
415
                                        int Offset=(dimAudioQ-SizeToCopy)*1000/(spec.freq*2*spec.channels);
416
                                        int64_t LastDts=pkt1->pkt.dts;
417
                                        pkt1->pkt.dts += Offset + deltaAudioQError;
418
                                        pkt1->pkt.pts += Offset + deltaAudioQError;
419
                                        deltaAudioQError = (float)LastDts + (float)Offset + deltaAudioQError - (float)pkt1->pkt.dts;
420
#ifdef DEBUG_QUEUE
421
                                        printf("   Adjust timestamps Old = %lld New = %lld\n", LastDts, pkt1->pkt.dts);
422
#endif
423
                                        AudioQueueOffset = dimAudioQ - SizeToCopy;
424
                                        //SEE BEFORE HINT q->size -= AudioQueueOffset;
425
                                        ret = 1;
426
                                }
427
                                else {
428
                                        AudioQueueOffset=0;
429
#ifdef DEBUG_AUDIO_BUFFER
430
                                        printf("0: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
431
#endif
432
                                }
433
#ifdef DEBUG_QUEUE
434
                                printf("   deltaAudioQError = %f\n",deltaAudioQError);
435
#endif
436
                                update_queue_stats(q, pkt->stream_index);
437
                                //update index of last frame extracted
438
                                q->last_frame_extracted = pkt->stream_index;
439
                        }
440
                }
441
        }
442
        else { //somebody requested a video packet, q is the video queue
443
                pkt1 = q->first_pkt;
444
                if(pkt1) {
445
#ifdef DEBUG_QUEUE
446
                        printf("  AV not 1\n");
447
#endif
448
                        pkt->size = pkt1->pkt.size;
449
                        pkt->dts = pkt1->pkt.dts;
450
                        pkt->pts = pkt1->pkt.pts;
451
                        pkt->stream_index = pkt1->pkt.stream_index;
452
                        pkt->flags = pkt1->pkt.flags;
453
                        pkt->pos = pkt1->pkt.pos;
454
                        pkt->convergence_duration = pkt1->pkt.convergence_duration;
455
                        //*pkt = pkt1->pkt;
456
                        memcpy(pkt->data, pkt1->pkt.data, pkt1->pkt.size);
457

    
458
                        //HINT SEE BEFORE q->size -= pkt1->pkt.size;
459
                        q->first_pkt = remove_from_queue(q, pkt1);
460

    
461
                        ret = 1;
462
                        update_queue_stats(q, pkt->stream_index);
463
                        //update index of last frame extracted
464
                        q->last_frame_extracted = pkt->stream_index;
465
                }
466
#ifdef DEBUG_QUEUE
467
                else {
468
                        printf("  VIDEO pk1 NULL!!!!\n");
469
                }
470
#endif
471
        }
472

    
473
        if(q->nb_packets==0 && q->queueType==AUDIO) {
474
                QueueFillingMode=1;
475
#ifdef DEBUG_QUEUE
476
                printf("QUEUE: Get FillingMode ON\n");
477
#endif
478
        }
479
#ifdef DEBUG_QUEUE
480
        printf("QUEUE: Get LastFrameExtracted = %d\n",q->last_frame_extracted);
481
        printf("QUEUE: Get Tot lost frames = %d\n",q->total_lost_frames);
482
#endif
483

    
484
        SDL_UnlockMutex(q->mutex);
485
        return ret;
486
}
487

    
488

    
489
int audio_decode_frame(uint8_t *audio_buf, int buf_size) {
490
        //struct timeval now;
491
        int audio_pkt_size = 0;
492
        long long Now;
493
        short int DecodeAudio=0, SkipAudio=0;
494
        //int len1, data_size;
495

    
496
        //gettimeofday(&now,NULL);
497
        //Now = (now.tv_sec)*1000+now.tv_usec/1000;
498
        Now=(long long)SDL_GetTicks();
499

    
500
        if(QueueFillingMode || QueueStopped)
501
        {
502
                //SDL_LockMutex(timing_mutex);
503
                FirstTimeAudio=1;
504
                FirstTime = 1;
505
                //SDL_UnlockMutex(timing_mutex);
506
                return -1;
507
        }
508

    
509
        if((FirstTime==1 || FirstTimeAudio==1) && audioq.size>0) {
510
                if(audioq.first_pkt->pkt.pts>0)
511
                {
512
                        //SDL_LockMutex(timing_mutex);
513
                        DeltaTime=Now-(long long)(audioq.first_pkt->pkt.pts);
514
                        FirstTimeAudio = 0;
515
                        FirstTime = 0;
516
                        //SDL_UnlockMutex(timing_mutex);
517
#ifdef DEBUG_AUDIO 
518
                         printf("AUDIO: audio_decode_frame - DeltaTimeAudio=%lld\n",DeltaTime);
519
#endif
520
                }
521
        }
522

    
523
#ifdef DEBUG_AUDIO 
524
        if(audioq.first_pkt)
525
        {
526
                printf("AUDIO: audio_decode_frame - Syncro params: Delta:%lld Now:%lld pts=%lld pts+Delta=%lld ",(long long)DeltaTime,Now,(long long)audioq.first_pkt->pkt.pts,(long long)audioq.first_pkt->pkt.pts+DeltaTime);
527
                printf("AUDIO: QueueLen=%d ",(int)audioq.nb_packets);
528
                printf("AUDIO: QueueSize=%d\n",(int)audioq.size);
529
        }
530
        else
531
                printf("AUDIO: audio_decode_frame - Empty queue\n");
532
#endif
533

    
534

    
535
        if(audioq.nb_packets>0) {
536
                if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
537
                        SkipAudio = 1;
538
                        DecodeAudio = 0;
539
                }
540
                else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
541
                        (long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
542
                                SkipAudio = 0;
543
                                DecodeAudio = 1;
544
                }
545
        }
546
                
547
        while(SkipAudio==1 && audioq.size>0) {
548
                SkipAudio = 0;
549
#ifdef DEBUG_AUDIO
550
                 printf("AUDIO: skipaudio: queue size=%d\n",audioq.size);
551
#endif
552
                if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
553
                        return -1;
554
                }
555
                if(audioq.first_pkt)
556
                {
557
                        if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
558
                                SkipAudio = 1;
559
                                DecodeAudio = 0;
560
                        }
561
                        else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
562
                                (long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
563
                                        SkipAudio = 0;
564
                                        DecodeAudio = 1;
565
                        }
566
                }
567
        }
568
        if(DecodeAudio==1) {
569
                if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
570
                        return -1;
571
                }
572
                memcpy(audio_buf,AudioPkt.data,AudioPkt.size);
573
                audio_pkt_size = AudioPkt.size;
574
#ifdef DEBUG_AUDIO
575
                 printf("AUDIO: Decode audio\n");
576
#endif
577
        }
578

    
579
        return audio_pkt_size;
580
}
581

    
582

    
583
int video_callback(void *valthread) {
584
        //AVPacket pktvideo;
585
        AVCodecContext  *pCodecCtx;
586
        AVCodec         *pCodec;
587
        AVFrame         *pFrame;
588
        AVPacket        packet;
589
        int frameFinished;
590
        int countexit;
591
        AVPicture pict;
592
        //FILE *frecon;
593
        SDL_Event event;
594
        long long Now;
595
        short int SkipVideo, DecodeVideo;
596

    
597
        //double frame_rate = 0.0,time_between_frames=0.0;
598
        //struct timeval now;
599

    
600
        //int wait_for_sync = 1;
601
        ThreadVal *tval;
602
        tval = (ThreadVal *)valthread;
603

    
604
        //frame_rate = tval->framerate;
605
        //time_between_frames = 1.e6 / frame_rate;
606
        //gettimeofday(&time_now,0);
607

    
608
        //frecon = fopen("recondechunk.mpg","wb");
609

    
610
        pCodecCtx=avcodec_alloc_context();
611
        pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
612
#ifdef H264_VIDEO_ENCODER
613
        pCodecCtx->codec_id  = CODEC_ID_H264;
614
        pCodecCtx->me_range = 16;
615
        pCodecCtx->max_qdiff = 4;
616
        pCodecCtx->qmin = 10;
617
        pCodecCtx->qmax = 51;
618
        pCodecCtx->qcompress = 0.6;
619
#else
620
        pCodecCtx->codec_id  = CODEC_ID_MPEG4;
621
#endif
622
        //pCodecCtx->bit_rate = 400000;
623
        // resolution must be a multiple of two
624
        pCodecCtx->width = tval->width;//176;//352;
625
        pCodecCtx->height = tval->height;//144;//288;
626
        // frames per second
627
        //pCodecCtx->time_base = (AVRational){1,25};
628
        //pCodecCtx->gop_size = 10; // emit one intra frame every ten frames
629
        //pCodecCtx->max_b_frames=1;
630
        pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
631
        pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
632

    
633
        if(pCodec==NULL) {
634
                fprintf(stderr, "Unsupported codec!\n");
635
                return -1; // Codec not found
636
        }
637
        if(avcodec_open(pCodecCtx, pCodec) < 0) {
638
                fprintf(stderr, "could not open codec\n");
639
                return -1; // Could not open codec
640
        }
641
        pFrame=avcodec_alloc_frame();
642
        if(pFrame==NULL) {
643
                printf("Memory error!!!\n");
644
                return -1;
645
        }
646

    
647
        while(!quit) {
648
                if(QueueFillingMode || QueueStopped)
649
                {
650
                        //SDL_LockMutex(timing_mutex);
651
                        FirstTime = 1;
652
                        //SDL_UnlockMutex(timing_mutex);
653
                        usleep(5000);
654
                        continue;
655
                }
656

    
657
                DecodeVideo = 0;
658
                SkipVideo = 0;
659
                Now=(long long)SDL_GetTicks();
660
                if(FirstTime==1 && videoq.size>0) {
661
                        if(videoq.first_pkt->pkt.pts>0)
662
                        {
663
                                //SDL_LockMutex(timing_mutex);
664
                                DeltaTime=Now-(long long)videoq.first_pkt->pkt.pts;
665
                                FirstTime = 0;
666
                                //SDL_UnlockMutex(timing_mutex);
667
                        }
668
#ifdef DEBUG_VIDEO 
669
                         printf("VIDEO: VideoCallback - DeltaTimeAudio=%lld\n",DeltaTime);
670
#endif
671
                }
672

    
673
#ifdef DEBUG_VIDEO 
674
                if(videoq.first_pkt)
675
                {
676
                        printf("VIDEO: VideoCallback - Syncro params: Delta:%lld Now:%lld pts=%lld pts+Delta=%lld ",(long long)DeltaTime,Now,(long long)videoq.first_pkt->pkt.pts,(long long)videoq.first_pkt->pkt.pts+DeltaTime);
677
                        printf("VIDEO: Index=%d ", (int)videoq.first_pkt->pkt.stream_index);
678
                        printf("VIDEO: QueueLen=%d ", (int)videoq.nb_packets);
679
                        printf("VIDEO: QueueSize=%d\n", (int)videoq.size);
680
                }
681
                else
682
                        printf("VIDEO: VideoCallback - Empty queue\n");
683
#endif
684

    
685
                if(videoq.nb_packets>0) {
686
                        if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)<Now-(long long)MAX_TOLLERANCE) {
687
                                SkipVideo = 1;
688
                                DecodeVideo = 0;
689
                        }
690
                        else 
691
                                if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)>=Now-(long long)MAX_TOLLERANCE &&
692
                                   ((long long)videoq.first_pkt->pkt.pts+DeltaTime)<=Now+(long long)MAX_TOLLERANCE) {
693
                                        SkipVideo = 0;
694
                                        DecodeVideo = 1;
695
                                }
696
                }
697
#ifdef DEBUG_VIDEO
698
                printf("VIDEO: skipvideo:%d decodevideo:%d\n",SkipVideo,DecodeVideo);
699
#endif
700

    
701
                while(SkipVideo==1 && videoq.size>0) {
702
                        SkipVideo = 0;
703
#ifdef DEBUG_VIDEO 
704
                         printf("VIDEO: Skip Video\n");
705
#endif
706
                        if(packet_queue_get(&videoq,&VideoPkt,0) < 0) {
707
                                break;
708
                        }
709
                        avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
710
                        if(videoq.first_pkt)
711
                        {
712
                                if((long long)videoq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
713
                                        SkipVideo = 1;
714
                                        DecodeVideo = 0;
715
                                }
716
                                else if((long long)videoq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
717
                                                                (long long)videoq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
718
                                        SkipVideo = 0;
719
                                        DecodeVideo = 1;
720
                                }
721
                        }
722
                }
723
                
724
                if(DecodeVideo==1) {
725
                        if(packet_queue_get(&videoq,&VideoPkt,0) > 0) {
726

    
727
#ifdef DEBUG_VIDEO
728
                                printf("VIDEO: Decode video FrameTime=%lld Now=%lld\n",(long long)VideoPkt.pts+DeltaTime,Now);
729
#endif
730

    
731
                                avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
732

    
733
                                if(frameFinished) { // it must be true all the time else error
734
#ifdef DEBUG_VIDEO
735
                                        printf("VIDEO: FrameFinished\n");
736
#endif
737
                                        if(SaveYUV)
738
                                                SaveFrame(pFrame, pCodecCtx->width, pCodecCtx->height);
739
                                        //fwrite(pktvideo.data, 1, pktvideo.size, frecon);
740

    
741
                                        if(silentMode)
742
                                                continue;
743

    
744
                                        // Lock SDL_yuv_overlay
745
                                        if(SDL_MUSTLOCK(screen)) {
746
                                                if(SDL_LockSurface(screen) < 0) {
747
                                                        continue;
748
                                                }
749
                                        }
750

    
751
                                        if(SDL_LockYUVOverlay(yuv_overlay) < 0) {
752
                                                if(SDL_MUSTLOCK(screen)) {
753
                                                        SDL_UnlockSurface(screen);
754
                                                }
755
                                                continue;
756
                                        }
757
                                        
758
                                        pict.data[0] = yuv_overlay->pixels[0];
759
                                        pict.data[1] = yuv_overlay->pixels[2];
760
                                        pict.data[2] = yuv_overlay->pixels[1];
761

    
762
                                        pict.linesize[0] = yuv_overlay->pitches[0];
763
                                        pict.linesize[1] = yuv_overlay->pitches[2];
764
                                        pict.linesize[2] = yuv_overlay->pitches[1];
765

    
766
                                        if(img_convert_ctx == NULL) {
767
                                                img_convert_ctx = sws_getContext(tval->width, tval->height, PIX_FMT_YUV420P, initRect->w, initRect->h, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
768
                                                if(img_convert_ctx == NULL) {
769
                                                        fprintf(stderr, "Cannot initialize the conversion context!\n");
770
                                                        exit(1);
771
                                                }
772
                                        }
773
                                        // let's draw the data (*yuv[3]) on a SDL screen (*screen)
774
                                        sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, tval->height, pict.data, pict.linesize);
775
                                        SDL_UnlockYUVOverlay(yuv_overlay);
776
                                        // Show, baby, show!
777
                                        SDL_LockMutex(RedrawMutex);
778
                                        SDL_DisplayYUVOverlay(yuv_overlay, &rect);
779
                                        SDL_UnlockMutex(RedrawMutex);
780

    
781
                                        //redisplay logo
782
                                        /**SDL_BlitSurface(image, NULL, screen, &dest);*/
783
                                        /* Update the screen area just changed */
784
                                        /**SDL_UpdateRects(screen, 1, &dest);*/
785

    
786
                                        if(SDL_MUSTLOCK(screen)) {
787
                                                SDL_UnlockSurface(screen);
788
                                        }
789
                                } //if FrameFinished
790
                        } // if packet_queue_get
791
                } //if DecodeVideo=1
792

    
793
                usleep(5000);
794
        }
795
        av_free(pCodecCtx);
796
        //fclose(frecon);
797
#ifdef DEBUG_VIDEO
798
         printf("VIDEO: video callback end\n");
799
#endif
800
        return 1;
801
}
802

    
803

    
804
void aspect_ratio_rect(float aspect_ratio, int width, int height)
805
{
806
        int h = 0, w = 0, x, y;
807
        aspect_ratio_resize(aspect_ratio, width, height, &w, &h);
808
        x = (width - w) / 2;
809
        y = (height - h) / 2;
810
        rect.x = x;//x;
811
        rect.y = y;//y;
812
        rect.w = w;
813
        rect.h = h;
814

    
815
//         printf("setting video mode %dx%d\n", rect.w, rect.h);
816
}
817

    
818

    
819
void audio_callback(void *userdata, Uint8 *stream, int len) {
820

    
821
        //AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
822
        int audio_size;
823

    
824
        static uint8_t audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
825

    
826
        audio_size = audio_decode_frame(audio_buf, sizeof(audio_buf));
827
        if(audio_size != len) {
828
                memset(stream, 0, len);
829
        } else {
830
                memcpy(stream, (uint8_t *)audio_buf, len);
831
        }
832
}
833

    
834
void SetupGUI()
835
{
836
        // init SDL_image
837
        int flags=IMG_INIT_JPG|IMG_INIT_PNG;
838
        int initted=IMG_Init(flags);
839
        if(initted&flags != flags) {
840
                printf("IMG_Init: Failed to init required jpg and png support!\n");
841
                printf("IMG_Init: %s\n", IMG_GetError());
842
                exit(1);
843
        }
844

    
845
        SDL_Surface *temp;
846
        int screen_w = 0, screen_h = 0;
847

    
848
        if(rect.w > BUTTONS_CONTAINER_WIDTH)
849
                screen_w = rect.w;
850
        else
851
                screen_w = BUTTONS_CONTAINER_WIDTH;
852

    
853
                screen_h = rect.h + BUTTONS_CONTAINER_HEIGHT + BUTTONS_LAYER_OFFSET;
854

    
855
        SDL_WM_SetCaption("Filling buffer...", NULL);
856
        // Make a screen to put our video
857
#ifndef __DARWIN__
858
        screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
859
#else
860
        screen = SDL_SetVideoMode(screen_w, screen_h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
861
#endif
862
        if(!screen) {
863
                fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
864
                exit(1);
865
        }
866
        
867
        window_width = screen_w;
868
        window_height = screen_h;
869
        
870
        /** Setting up cursors */
871
        defaultCursor = SDL_GetCursor();
872
        handCursor = init_system_cursor(handXPM);
873
        
874
        /** Init Buttons */
875
        int i;
876
        for(i=0; i<NBUTTONS; i++)
877
        {
878
                SButton* tmp = &(Buttons[i]);
879
                tmp->Hover = 0;
880
                tmp->ToggledButton = NULL;
881
                tmp->Visible = 1;
882
                tmp->HoverCallback = NULL;
883
                tmp->LButtonUpCallback = NULL;
884
        }
885
        
886
        /** Loading icons */
887
        
888
        // fullscreen
889
        temp = IMG_Load(FULLSCREEN_ICON_FILE);
890
        if (temp == NULL) {
891
                fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_ICON_FILE, SDL_GetError());
892
                exit(1);
893
        }
894
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
895
        SDL_FreeSurface(temp);
896
        
897
        // fullscreen hover
898
        temp = IMG_Load(FULLSCREEN_HOVER_ICON_FILE);
899
        if (temp == NULL) {
900
                fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
901
                exit(1);
902
        }
903
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
904
        SDL_FreeSurface(temp);
905

    
906
        // no fullscreen
907
        temp = IMG_Load(NOFULLSCREEN_ICON_FILE);
908
        if (temp == NULL) {
909
                fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_ICON_FILE, SDL_GetError());
910
                exit(1);
911
        }
912
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
913
        SDL_FreeSurface(temp);
914

    
915
        // no fullscreen hover
916
        temp = IMG_Load(NOFULLSCREEN_HOVER_ICON_FILE);
917
        if (temp == NULL) {
918
                fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
919
                exit(1);
920
        }
921
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
922
        SDL_FreeSurface(temp);
923
        
924
        // channel up
925
        temp = IMG_Load(CHANNEL_UP_ICON_FILE);
926
        if (temp == NULL) {
927
                fprintf(stderr, "Error loading %s: %s\n", CHANNEL_UP_ICON_FILE, SDL_GetError());
928
                exit(1);
929
        }
930
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
931
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
932
        SDL_FreeSurface(temp);
933
        
934
        // channel down
935
        temp = IMG_Load(CHANNEL_DOWN_ICON_FILE);
936
        if (temp == NULL) {
937
                fprintf(stderr, "Error loading %s: %s\n", CHANNEL_DOWN_ICON_FILE, SDL_GetError());
938
                exit(1);
939
        }
940
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
941
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
942
        SDL_FreeSurface(temp);
943

    
944
        /** Setting up icon boxes */
945
        Buttons[FULLSCREEN_BUTTON_INDEX].XOffset = Buttons[NO_FULLSCREEN_BUTTON_INDEX].XOffset = 20;
946
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.x = 20;
947
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.w = Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon->w;
948
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h = Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon->h;
949
        Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
950
        
951
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.x = 20;
952
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.w = Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon->w;
953
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h = Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon->h;
954
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
955
        
956
        Buttons[CHANNEL_UP_BUTTON_INDEX].XOffset = -50;
957
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.w = Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon->w;
958
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.h = Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon->h;
959
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.x = (screen_w - 50);
960
        Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
961
        
962
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].XOffset = -25;
963
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.w = Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon->w;
964
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.h = Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon->h;
965
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.x = (screen_w - 25);
966
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
967
        
968
        /** Setting up buttons events */
969
        Buttons[FULLSCREEN_BUTTON_INDEX].ToggledButton = &(Buttons[NO_FULLSCREEN_BUTTON_INDEX]);
970
        Buttons[FULLSCREEN_BUTTON_INDEX].LButtonUpCallback = &toggle_fullscreen;
971
        Buttons[NO_FULLSCREEN_BUTTON_INDEX].LButtonUpCallback = &toggle_fullscreen;
972
        Buttons[CHANNEL_UP_BUTTON_INDEX].LButtonUpCallback = &zap_up;
973
        Buttons[CHANNEL_DOWN_BUTTON_INDEX].LButtonUpCallback = &zap_down;
974

    
975
        //create video overlay for display of video frames
976
        yuv_overlay = SDL_CreateYUVOverlay(rect.w, rect.h, SDL_YV12_OVERLAY, screen);
977

    
978
        if ( yuv_overlay == NULL ) {
979
                fprintf(stderr,"SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError());
980
                exit(1);
981
        }
982

    
983
        if ( yuv_overlay->hw_overlay )
984
                fprintf(stderr,"SDL: Using hardware overlay.");
985
        rect.x = (screen_w - rect.w) / 2;
986
        SDL_DisplayYUVOverlay(yuv_overlay, &rect);
987

    
988
        redraw_buttons();
989
}
990

    
991
void SaveFrame(AVFrame *pFrame, int width, int height) {
992
        FILE *pFile;
993
        int  y;
994
  
995
         // Open file
996
        pFile=fopen(YUVFileName, "ab");
997
        if(pFile==NULL)
998
                return;
999
  
1000
        // Write header
1001
        //fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1002
  
1003
        // Write Y data
1004
        for(y=0; y<height; y++)
1005
                  fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile);
1006
        // Write U data
1007
        for(y=0; y<height/2; y++)
1008
                  fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile);
1009
        // Write V data
1010
        for(y=0; y<height/2; y++)
1011
                  fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile);
1012
  
1013
        // Close file
1014
        fclose(pFile);
1015
}
1016

    
1017
void sigint_handler (int signal) {
1018
        printf("Caught SIGINT, exiting...");
1019
        got_sigint = 1;
1020
}
1021

    
1022
void ProcessKeys() {
1023
        static Uint32 LastTime=0;
1024
        static int LastKey=-1;
1025

    
1026
        Uint32 Now=SDL_GetTicks();
1027
        Uint8* keystate=SDL_GetKeyState(NULL);
1028
        /*if(keystate[SDLK_SPACE] &&
1029
          (LastKey!=SDLK_SPACE || (LastKey==SDLK_SPACE && (Now-LastTime>1000))))
1030
        {
1031
                LastKey=SDLK_SPACE;
1032
                LastTime=Now;
1033
                QueueStopped=!QueueStopped;
1034
                if(QueueStopped) CurrStatus = PAUSED;
1035
                else CurrStatus = RUNNING;
1036
                // refresh_fullscreen_button(0);
1037
        }*/
1038
        if(keystate[SDLK_ESCAPE] &&
1039
          (LastKey!=SDLK_ESCAPE || (LastKey==SDLK_ESCAPE && (Now-LastTime>1000))))
1040
        {
1041
                LastKey=SDLK_ESCAPE;
1042
                LastTime=Now;
1043
                quit=1;
1044
        }
1045
        /*if(keystate[SDLK_f] &&
1046
          (LastKey!=SDLK_f || (LastKey==SDLK_f && (Now-LastTime>1000))))
1047
        {
1048
                LastKey=SDLK_f;
1049
                LastTime=Now;
1050
                SDL_WM_ToggleFullScreen(NULL);
1051
        }*/
1052
}
1053

    
1054
int main(int argc, char *argv[]) {
1055
        int i, j, videoStream, outbuf_size, out_size, out_size_audio, seq_current_chunk = 0, audioStream;
1056
        int len1, data_size, stime, cont=0;
1057
        int frameFinished, len_audio;
1058
        int numBytes, outbuf_audio_size, audio_size;
1059
        
1060
        memset((void*)Channels, 0, (255*sizeof(SChannel)));
1061

    
1062
        int y;
1063
        
1064
        uint8_t *outbuf,*outbuf_audio;
1065
        uint8_t *outbuf_audi_audio;
1066
        int httpPort = -1;
1067
        
1068
        AVFormatContext *pFormatCtx;
1069

    
1070
        AVCodec         *pCodec,*aCodec;
1071
        AVFrame         *pFrame; 
1072

    
1073
        AVPicture pict;
1074
        SDL_Thread *video_thread;//exit_thread,*exit_thread2;
1075
        SDL_Event event;
1076
        SDL_AudioSpec wanted_spec;
1077
        
1078
        struct MHD_Daemon *daemon = NULL;        
1079

    
1080
        char buf[1024],outfile[1024], basereadfile[1024],readfile[1024];
1081
        FILE *fp;        
1082
        int width,height,asample_rate,achannels;
1083

    
1084
        ThreadVal *tval;
1085
        tval = (ThreadVal *)malloc(sizeof(ThreadVal));
1086
                
1087
        if(argc<9) {
1088
                printf("chunker_player width height aspect_ratio audio_sample_rate audio_channels queue_thresh httpd_port silentMode <YUVFilename>\n");
1089
                exit(1);
1090
        }
1091
        sscanf(argv[1],"%d",&width);
1092
        sscanf(argv[2],"%d",&height);
1093
        sscanf(argv[3],"%f",&ratio);
1094
        sscanf(argv[4],"%d",&asample_rate);
1095
        sscanf(argv[5],"%d",&achannels);
1096
        sscanf(argv[6],"%d",&queue_filling_threshold);
1097
        sscanf(argv[7],"%d",&httpPort);
1098
        sscanf(argv[8],"%d",&silentMode);
1099
        
1100
        if(argc==10)
1101
        {
1102
                sscanf(argv[9],"%s",YUVFileName);
1103
                printf("YUVFile: %s\n",YUVFileName);
1104
                FILE* fp=fopen(YUVFileName, "wb");
1105
                if(fp)
1106
                {
1107
                        SaveYUV=1;
1108
                        fclose(fp);
1109
                }
1110
                else
1111
                        printf("ERROR: Unable to create YUVFile\n");
1112
        }
1113
        
1114
        if(parse_conf())
1115
        {
1116
                printf("Error while parsing configuration file, exiting...\n");
1117
                exit(1);
1118
        }
1119
        SelectedChannel = 0;
1120
        
1121
        switch_channel(&(Channels[SelectedChannel]));
1122

    
1123
        tval->width = width;
1124
        tval->height = height;
1125
        tval->aspect_ratio = ratio;
1126

    
1127
        // Register all formats and codecs
1128
        av_register_all();
1129
        if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
1130
                fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
1131
                return -1;
1132
        }
1133

    
1134
        aCodecCtx = avcodec_alloc_context();
1135
        //aCodecCtx->bit_rate = 64000;
1136
        aCodecCtx->sample_rate = asample_rate;
1137
        aCodecCtx->channels = achannels;
1138
#ifdef MP3_AUDIO_ENCODER
1139
        aCodec = avcodec_find_decoder(CODEC_ID_MP3); // codec audio
1140
#else
1141
        aCodec = avcodec_find_decoder(CODEC_ID_MP2);
1142
#endif
1143
        printf("MP2 codec id %d MP3 codec id %d\n",CODEC_ID_MP2,CODEC_ID_MP3);
1144
        if(!aCodec) {
1145
                printf("Codec not found!\n");
1146
                return -1;
1147
        }
1148
        if(avcodec_open(aCodecCtx, aCodec)<0) {
1149
                fprintf(stderr, "could not open codec\n");
1150
                return -1; // Could not open codec
1151
        }
1152
        printf("using audio Codecid: %d ",aCodecCtx->codec_id);
1153
        printf("samplerate: %d ",aCodecCtx->sample_rate);
1154
        printf("channels: %d\n",aCodecCtx->channels);
1155
        wanted_spec.freq = aCodecCtx->sample_rate;
1156
        wanted_spec.format = AUDIO_S16SYS;
1157
        wanted_spec.channels = aCodecCtx->channels;
1158
        wanted_spec.silence = 0;
1159
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1160
        wanted_spec.callback = audio_callback;
1161
        wanted_spec.userdata = aCodecCtx;
1162
        if(!silentMode)
1163
                if(SDL_OpenAudio(&wanted_spec,&spec)<0) {
1164
                        fprintf(stderr,"SDL_OpenAudio: %s\n",SDL_GetError());
1165
                        return -1;
1166
                }
1167
        dimAudioQ = spec.size;
1168
        deltaAudioQ = (float)((float)spec.samples)*1000/spec.freq;
1169

    
1170
#ifdef DEBUG_AUDIO
1171
        printf("freq:%d\n",spec.freq);
1172
        printf("format:%d\n",spec.format);
1173
        printf("channels:%d\n",spec.channels);
1174
        printf("silence:%d\n",spec.silence);
1175
        printf("samples:%d\n",spec.samples);
1176
        printf("size:%d\n",spec.size);
1177
        printf("deltaAudioQ: %f\n",deltaAudioQ);
1178
#endif
1179

    
1180
        pFrame=avcodec_alloc_frame();
1181
        if(pFrame==NULL) {
1182
                printf("Memory error!!!\n");
1183
                return -1;
1184
        }
1185
        outbuf_audio = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1186

    
1187
        //initialize the audio and the video queues
1188
        packet_queue_init(&audioq, AUDIO);
1189
        packet_queue_init(&videoq, VIDEO);
1190

    
1191
        //calculate aspect ratio and put updated values in rect
1192
        aspect_ratio_rect(ratio, width, height);
1193

    
1194
        initRect = (SDL_Rect*) malloc(sizeof(SDL_Rect));
1195
        if(!initRect)
1196
        {
1197
                printf("Memory error!!!\n");
1198
                return -1;
1199
        }
1200
        initRect->x = rect.x;
1201
        initRect->y = rect.y;
1202
        initRect->w = rect.w;
1203
        initRect->h = rect.h;
1204
        
1205
        RedrawMutex = SDL_CreateMutex();
1206
        if(!silentMode)
1207
                SetupGUI();
1208
        
1209
        // Init audio and video buffers
1210
        av_init_packet(&AudioPkt);
1211
        av_init_packet(&VideoPkt);
1212
        AudioPkt.data=(uint8_t *)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1213
        if(!AudioPkt.data) return 0;
1214
        VideoPkt.data=(uint8_t *)malloc(width*height*3/2);
1215
        if(!VideoPkt.data) return 0;
1216
        
1217
        SDL_PauseAudio(0);
1218
        video_thread = SDL_CreateThread(video_callback,tval);
1219
        
1220
        //this thread fetches chunks from the network by listening to the following path, port
1221
        daemon = initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, httpPort);
1222
        CurrStatus = RUNNING;
1223

    
1224
        // Wait for user input
1225
        while(!quit) {
1226
                if(QueueFillingMode) {
1227
                        SDL_WM_SetCaption("Filling buffer...", NULL);
1228

    
1229
                        if(audioq.nb_packets==0 && audioq.last_frame_extracted>0) {        // video ended therefore init queues
1230
#ifdef DEBUG_QUEUE
1231
                                printf("QUEUE: MAIN SHOULD RESET\n");
1232
#endif
1233
                                packet_queue_reset(&audioq, AUDIO);
1234
                                packet_queue_reset(&videoq, VIDEO);
1235
                        }
1236

    
1237
#ifdef DEBUG_QUEUE
1238
                        //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);
1239
#endif
1240
                }
1241
                else
1242
                        SDL_WM_SetCaption("NAPA-Wine Player", NULL);
1243

    
1244
                int x = 0, y = 0;
1245
                int resize_w, resize_h;
1246
                int tmp_switch = 0;
1247
                int i;
1248
                //listen for key and mouse
1249
                while(SDL_PollEvent(&event)) {
1250
                        switch(event.type) {
1251
                                case SDL_QUIT:
1252
                                        //exit(0);
1253
                                        quit=1;
1254
                                        if(child_pid > 0)
1255
                                                KILL_PROCESS(child_pid);
1256
                                break;
1257
                                case SDL_VIDEORESIZE:
1258
                                        SDL_LockMutex(RedrawMutex);
1259
#ifndef __DARWIN__
1260
                                        screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
1261
#else
1262
                                        screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
1263
#endif
1264
                                        if(!screen) {
1265
                                                fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
1266
                                                exit(1);
1267
                                        }
1268
                                        
1269
                                        SDL_UnlockMutex(RedrawMutex);
1270
                                        
1271
                                        window_width = event.resize.w;
1272
                                        window_height = event.resize.h;
1273
                                        
1274
                                        // update the overlay surface size, mantaining the aspect ratio
1275
                                        aspect_ratio_rect(ratio, event.resize.w, event.resize.h - BUTTONS_LAYER_OFFSET - BUTTONS_CONTAINER_HEIGHT);
1276
                                        
1277
                                        // update each button coordinates
1278
                                        for(i=0; i<NBUTTONS; i++)
1279
                                        {
1280
                                                if(Buttons[i].XOffset > 0)
1281
                                                        Buttons[i].ButtonIconBox.x = Buttons[i].XOffset;
1282
                                                else
1283
                                                        Buttons[i].ButtonIconBox.x = (event.resize.w + Buttons[i].XOffset);
1284
                                                        
1285
                                                Buttons[i].ButtonIconBox.y = event.resize.h - Buttons[i].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1286
                                        }
1287
                                        
1288
                                        SDL_LockMutex(RedrawMutex);
1289
                                        redraw_buttons();
1290
                                        SDL_UnlockMutex(RedrawMutex);
1291
                                        
1292
                                break;
1293
                                case SDL_ACTIVEEVENT:
1294
                                        //printf("\tSDL_ACTIVEEVENT\n");
1295
                                        // if the window was iconified or restored
1296
                                        /*if(event.active.state & SDL_APPACTIVE)
1297
                                        {
1298
                                                //If the application is being reactivated
1299
                                                if( event.active.gain != 0 )
1300
                                                {
1301
                                                        //SDL_WM_SetCaption( "Window Event Test restored", NULL );
1302
                                                }
1303
                                        }
1304

1305
                                        //If something happened to the keyboard focus
1306
                                        else if( event.active.state & SDL_APPINPUTFOCUS )
1307
                                        {
1308
                                                //If the application gained keyboard focus
1309
                                                if( event.active.gain != 0 )
1310
                                                {
1311
                                                }
1312
                                        }
1313
                                        //If something happened to the mouse focus
1314
                                        else if( event.active.state & SDL_APPMOUSEFOCUS )
1315
                                        {
1316
                                                //If the application gained mouse focus
1317
                                                if( event.active.gain != 0 )
1318
                                                {
1319
                                                }
1320
                                        }*/
1321
                                        break;
1322
                                case SDL_MOUSEMOTION:
1323
                                        //printf("\tSDL_MOUSEMOTION\n");
1324
                                        x = event.motion.x;
1325
                                        y = event.motion.y;
1326
                                        
1327
                                        for(i=0; i<NBUTTONS; i++)
1328
                                        {
1329
                                                //If the mouse is over the button
1330
                                                if(
1331
                                                        ( x > Buttons[i].ButtonIconBox.x ) && ( x < Buttons[i].ButtonIconBox.x + Buttons[i].ButtonIcon->w )
1332
                                                        && ( y > Buttons[i].ButtonIconBox.y ) && ( y < Buttons[i].ButtonIconBox.y + Buttons[i].ButtonIcon->h )
1333
                                                )
1334
                                                {
1335
                                                        Buttons[i].Hover = 1;
1336
                                                        SDL_SetCursor(handCursor);
1337
                                                        break;
1338
                                                }
1339
                                                
1340
                                                else
1341
                                                {
1342
                                                        Buttons[i].Hover = 0;
1343
                                                        SDL_SetCursor(defaultCursor);
1344
                                                }
1345
                                        }
1346
                                break;
1347
                                case SDL_MOUSEBUTTONUP:
1348
                                        //printf("\tSDL_MOUSEBUTTONUP\n");
1349
                                        if( event.button.button != SDL_BUTTON_LEFT )
1350
                                                break;
1351
                                        
1352
                                        x = event.motion.x;
1353
                                        y = event.motion.y;
1354
                                        
1355
                                        for(i=0; i<NBUTTONS; i++)
1356
                                        {
1357
                                                //If the mouse is over the button
1358
                                                if(
1359
                                                        ( x > Buttons[i].ButtonIconBox.x ) && ( x < Buttons[i].ButtonIconBox.x + Buttons[i].ButtonIcon->w )
1360
                                                        && ( y > Buttons[i].ButtonIconBox.y ) && ( y < Buttons[i].ButtonIconBox.y + Buttons[i].ButtonIcon->h )
1361
                                                )
1362
                                                {
1363
                                                        Buttons[i].LButtonUpCallback();
1364
                                                        break;
1365
                                                }
1366
                                        }
1367
                                break;
1368
                        }
1369
                        ProcessKeys();
1370
                }
1371
                usleep(120000);
1372
        }
1373

    
1374
        //TERMINATE
1375
        IMG_Quit();
1376

    
1377
        // Stop audio&video playback
1378
        SDL_WaitThread(video_thread,NULL);
1379
        SDL_PauseAudio(1);
1380
        SDL_CloseAudio();
1381
        //SDL_DestroyMutex(timing_mutex);
1382
        SDL_Quit();
1383
        
1384
        if(child_pid > 0)
1385
                KILL_PROCESS(child_pid);
1386
        
1387
        av_free(aCodecCtx);
1388
        free(AudioPkt.data);
1389
        free(VideoPkt.data);
1390
        free(outbuf_audio);
1391
        finalizeChunkPuller(daemon);
1392
        free(tval);
1393
        free(initRect);
1394
        return 0;
1395
}
1396

    
1397
int enqueueBlock(const uint8_t *block, const int block_size) {
1398
        Chunk *gchunk = NULL;
1399
        ExternalChunk *echunk = NULL;
1400
        int decoded_size = -1;
1401
        uint8_t *tempdata, *buffer;
1402
        int i, j;
1403
        Frame *frame = NULL;
1404
        AVPacket packet, packetaudio;
1405

    
1406
        uint16_t *audio_bufQ = NULL;
1407
        int16_t *dataQ = NULL;
1408
        int data_sizeQ;
1409
        int lenQ;
1410

    
1411
        //the frame.h gets encoded into 5 slots of 32bits (3 ints plus 2 more for the timeval struct
1412
        static int sizeFrameHeader = 5*sizeof(int32_t);
1413
        static int ExternalChunk_header_size = 5*CHUNK_TRANSCODING_INT_SIZE + 2*CHUNK_TRANSCODING_INT_SIZE + 2*CHUNK_TRANSCODING_INT_SIZE + 1*CHUNK_TRANSCODING_INT_SIZE*2;
1414

    
1415
        audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1416
        if(!audio_bufQ) {
1417
                printf("Memory error in audio_bufQ!\n");
1418
                return PLAYER_FAIL_RETURN;
1419
        }
1420

    
1421
        gchunk = (Chunk *)malloc(sizeof(Chunk));
1422
        if(!gchunk) {
1423
                printf("Memory error in gchunk!\n");
1424
                av_free(audio_bufQ);
1425
                return PLAYER_FAIL_RETURN;
1426
        }
1427

    
1428
        decoded_size = decodeChunk(gchunk, block, block_size);
1429
#ifdef DEBUG_CHUNKER
1430
        printf("CHUNKER: enqueueBlock: decoded_size %d target size %d\n", decoded_size, GRAPES_ENCODED_CHUNK_HEADER_SIZE + ExternalChunk_header_size + gchunk->size);
1431
#endif
1432
  if(decoded_size < 0 || decoded_size != GRAPES_ENCODED_CHUNK_HEADER_SIZE + ExternalChunk_header_size + gchunk->size) {
1433
                //HINT here i should differentiate between various return values of the decode
1434
                //in order to free what has been allocated there
1435
                printf("chunk probably corrupted!\n");
1436
                av_free(audio_bufQ);
1437
                free(gchunk);
1438
                return PLAYER_FAIL_RETURN;
1439
        }
1440

    
1441
        echunk = grapesChunkToExternalChunk(gchunk);
1442
        if(echunk == NULL) {
1443
                printf("Memory error in echunk!\n");
1444
                free(gchunk->attributes);
1445
                free(gchunk->data);
1446
                free(gchunk);
1447
                return PLAYER_FAIL_RETURN;
1448
        }
1449
        free(gchunk->attributes);
1450
        free(gchunk);
1451

    
1452
        frame = (Frame *)malloc(sizeof(Frame));
1453
        if(!frame) {
1454
                printf("Memory error in Frame!\n");
1455
                if(gchunk->attributes)
1456
                        free(gchunk->attributes);
1457
                if(echunk->data)
1458
                        free(echunk->data);
1459
                if(echunk)
1460
                        free(echunk);
1461
                av_free(audio_bufQ);
1462
                return PLAYER_FAIL_RETURN;
1463
        }
1464

    
1465
        tempdata = echunk->data; //let it point to first frame of payload
1466
        j=echunk->payload_len;
1467
        while(j>0 && !quit) {
1468
                frame->number = bit32_encoded_pull(tempdata);
1469
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1470
                frame->timestamp.tv_sec = bit32_encoded_pull(tempdata);
1471
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1472
                frame->timestamp.tv_usec = bit32_encoded_pull(tempdata);
1473
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1474
                frame->size = bit32_encoded_pull(tempdata);
1475
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1476
                frame->type = bit32_encoded_pull(tempdata);
1477
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1478

    
1479
                buffer = tempdata; // here coded frame information
1480
                tempdata += frame->size; //let it point to the next frame
1481

    
1482
                if(frame->type < 5) { // video frame
1483
                        av_init_packet(&packet);
1484
                        packet.data = buffer;//video_bufQ;
1485
                        packet.size = frame->size;
1486
                        packet.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1487
                        packet.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1488
                        packet.stream_index = frame->number; // use of stream_index for number frame
1489
                        //packet.duration = frame->timestamp.tv_sec;
1490
                        if(packet.size > 0)
1491
                                packet_queue_put(&videoq, &packet); //the _put makes a copy of the packet
1492

    
1493
#ifdef DEBUG_SOURCE
1494
                        printf("SOURCE: Insert video in queue pts=%lld %d %d sindex:%d\n",packet.pts,(int)frame->timestamp.tv_sec,(int)frame->timestamp.tv_usec,packet.stream_index);
1495
#endif
1496
                }
1497
                else if(frame->type == 5) { // audio frame
1498
                        av_init_packet(&packetaudio);
1499
                        packetaudio.data = buffer;
1500
                        packetaudio.size = frame->size;
1501
                        packetaudio.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1502
                        packetaudio.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1503
                        //packetaudio.duration = frame->timestamp.tv_sec;
1504
                        packetaudio.stream_index = frame->number; // use of stream_index for number frame
1505
                        packetaudio.flags = 1;
1506
                        packetaudio.pos = -1;
1507

    
1508
                        //instead of -1, in order to signal it is not decoded yet
1509
                        packetaudio.convergence_duration = 0;
1510

    
1511
                        // insert the audio frame into the queue
1512
                        if(packetaudio.size > 0)
1513
                                packet_queue_put(&audioq, &packetaudio);//makes a copy of the packet so i can free here
1514

    
1515
#ifdef DEBUG_SOURCE
1516
                        printf("SOURCE: Insert audio in queue pts=%lld sindex:%d\n", packetaudio.pts, packetaudio.stream_index);
1517
#endif
1518
                }
1519
                else {
1520
                        printf("SOURCE: Unknown frame type %d. Size %d\n", frame->type, frame->size);
1521
                }
1522
                if(frame->size > 0)
1523
                        j = j - sizeFrameHeader - frame->size;
1524
                else {
1525
                        printf("SOURCE: Corrupt frames (size %d) in chunk. Skipping it...\n", frame->size);
1526
                        j = -1;
1527
                }
1528
        }
1529
        //chunk ingestion terminated!
1530
        if(echunk->data)
1531
                free(echunk->data);
1532
        if(echunk)
1533
                free(echunk);
1534
        if(frame)
1535
                free(frame);
1536
        if(audio_bufQ)
1537
                av_free(audio_bufQ);
1538
}
1539

    
1540
/* From SDL documentation. */
1541
SDL_Cursor *init_system_cursor(const char *image[])
1542
{
1543
        int i, row, col;
1544
        Uint8 data[4*32];
1545
        Uint8 mask[4*32];
1546
        int hot_x, hot_y;
1547

    
1548
        i = -1;
1549
        for ( row=0; row<32; ++row ) {
1550
                for ( col=0; col<32; ++col ) {
1551
                        if ( col % 8 ) {
1552
                                data[i] <<= 1;
1553
                                mask[i] <<= 1;
1554
                        } else {
1555
                                ++i;
1556
                                data[i] = mask[i] = 0;
1557
                        }
1558
                        
1559
                        switch (image[4+row][col]) {
1560
                                case ' ':
1561
                                        data[i] |= 0x01;
1562
                                        mask[i] |= 0x01;
1563
                                        break;
1564
                                case '.':
1565
                                        mask[i] |= 0x01;
1566
                                        break;
1567
                                case 'X':
1568
                                        break;
1569
                        }
1570
                }
1571
        }
1572
        
1573
        sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
1574
        return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
1575
}
1576

    
1577
void aspect_ratio_resize(float aspect_ratio, int width, int height, int* out_width, int* out_height)
1578
{
1579
        int h,w,x,y;
1580
        h = (int)((float)width/aspect_ratio);
1581
        if(h<=height)
1582
        {
1583
                w = width;
1584
        }
1585
        else
1586
        {
1587
                w = (int)((float)height*aspect_ratio);
1588
                h = height;
1589
        }
1590
        *out_width = w;
1591
        *out_height = h;
1592
}
1593

    
1594
void toggle_fullscreen()
1595
{
1596
        SDL_LockMutex(RedrawMutex);
1597
        
1598
        int i;
1599
        
1600
        //If the screen is windowed
1601
        if( !fullscreen )
1602
        {
1603
                //Set the screen to fullscreen
1604
#ifndef __DARWIN__
1605
                screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 0, SDL_SWSURFACE | SDL_NOFRAME | SDL_FULLSCREEN);
1606
#else
1607
                screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 24, SDL_SWSURFACE | SDL_NOFRAME | SDL_FULLSCREEN);
1608
#endif
1609

    
1610
                //If there's an error
1611
                if( screen == NULL )
1612
                {
1613
                        fprintf(stderr, "SDL_SetVideoMode returned null: could not toggle fullscreen mode - exiting\n");
1614
                        exit(1);
1615
                }
1616
                
1617
                // update the overlay surface size, mantaining the aspect ratio
1618
                aspect_ratio_rect(ratio, FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT - BUTTONS_LAYER_OFFSET - BUTTONS_CONTAINER_HEIGHT);
1619
                
1620
                // update each button coordinates
1621
                for(i=0; i<NBUTTONS; i++)
1622
                {
1623
                        if(Buttons[i].XOffset > 0)
1624
                                Buttons[i].ButtonIconBox.x = Buttons[i].XOffset;
1625
                        else
1626
                                Buttons[i].ButtonIconBox.x = (FULLSCREEN_WIDTH + Buttons[i].XOffset);
1627
                                
1628
                        Buttons[i].ButtonIconBox.y = FULLSCREEN_HEIGHT - Buttons[i].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1629
                }
1630

    
1631
                //Set the window state flag
1632
                fullscreen = 1;
1633
                
1634
                Buttons[FULLSCREEN_BUTTON_INDEX].Visible = 0;
1635
                Buttons[NO_FULLSCREEN_BUTTON_INDEX].Visible = 1;
1636
        }
1637
        
1638
        //If the screen is fullscreen
1639
        else
1640
        {
1641
                //Window the screen
1642
#ifndef __DARWIN__
1643
                screen = SDL_SetVideoMode(window_width, window_height, 0, SDL_SWSURFACE | SDL_RESIZABLE);
1644
#else
1645
                screen = SDL_SetVideoMode(window_width, window_height, 24, SDL_SWSURFACE | SDL_RESIZABLE);
1646
#endif
1647
                
1648
                //If there's an error
1649
                if( screen == NULL )
1650
                {
1651
                        fprintf(stderr, "SDL_SetVideoMode returned null: could not toggle fullscreen mode - exiting\n");
1652
                        exit(1);
1653
                }
1654
                
1655
                // update the overlay surface size, mantaining the aspect ratio
1656
                aspect_ratio_rect(ratio, window_width, window_height - BUTTONS_LAYER_OFFSET - BUTTONS_CONTAINER_HEIGHT);
1657
                
1658
                // update each button coordinates
1659
                for(i=0; i<NBUTTONS; i++)
1660
                {
1661
                        if(Buttons[i].XOffset > 0)
1662
                                Buttons[i].ButtonIconBox.x = Buttons[i].XOffset;
1663
                        else
1664
                                Buttons[i].ButtonIconBox.x = (window_width + Buttons[i].XOffset);
1665
                                
1666
                        Buttons[i].ButtonIconBox.y = window_height - Buttons[i].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1667
                }
1668
                
1669
                //Set the window state flag
1670
                fullscreen = 0;
1671
                
1672
                Buttons[FULLSCREEN_BUTTON_INDEX].Visible = 1;
1673
                Buttons[NO_FULLSCREEN_BUTTON_INDEX].Visible = 0;
1674
        }
1675
        
1676
        redraw_buttons();
1677
        
1678
        SDL_UnlockMutex(RedrawMutex);
1679
}
1680

    
1681
int parse_conf()
1682
{
1683
        int j;
1684
        
1685
        // PARSING CONF FILE
1686
        cfg_opt_t channel_opts[] =
1687
        {
1688
                CFG_STR("Title", "", CFGF_NONE),
1689
                CFG_STR("LaunchString", "", CFGF_NONE),
1690
                CFG_END()
1691
        };
1692
        cfg_opt_t opts[] =
1693
        {
1694
                CFG_STR("ExecPath", DEFAULT_CHANNEL_EXEC_PATH, CFGF_NONE),
1695
                CFG_STR("ExecName", DEFAULT_CHANNEL_EXEC_NAME, CFGF_NONE),
1696
                CFG_SEC("Channel", channel_opts, CFGF_TITLE | CFGF_MULTI),
1697
                CFG_END()
1698
        };
1699
        cfg_t *cfg, *cfg_channel;
1700
        cfg = cfg_init(opts, CFGF_NONE);
1701
        if(cfg_parse(cfg, DEFAULT_CONF_FILENAME) == CFG_PARSE_ERROR)
1702
        {
1703
                return 1;
1704
        }
1705
        sprintf(OfferStreamerPath, "%s", cfg_getstr(cfg, "ExecPath"));
1706
        sprintf(OfferStreamerFilename, "%s", cfg_getstr(cfg, "ExecName"));
1707
        for(j = 0; j < cfg_size(cfg, "Channel"); j++)
1708
        {
1709
                cfg_channel = cfg_getnsec(cfg, "Channel", j);
1710
                sprintf(Channels[j].Title, "%s", cfg_title(cfg_channel));
1711
                // printf("parsing channel %s...", Channels[j].Title);
1712
                // printf(", %s\n", cfg_getstr(cfg_channel, "LaunchString"));
1713
                sprintf(Channels[j].LaunchString, "%s", cfg_getstr(cfg_channel, "LaunchString"));
1714
                NChannels++;
1715
        }
1716
        cfg_free(cfg);
1717
        
1718
        return 0;
1719
}
1720

    
1721
void zap_down()
1722
{
1723
        SelectedChannel = ((SelectedChannel+1) %NChannels);
1724
        packet_queue_reset(&audioq, AUDIO);
1725
        packet_queue_reset(&videoq, VIDEO);
1726
        switch_channel(&(Channels[SelectedChannel]));
1727
}
1728

    
1729
void zap_up()
1730
{
1731
        SelectedChannel--;
1732
        if(SelectedChannel < 0)
1733
                SelectedChannel = NChannels-1;
1734
                
1735
        packet_queue_reset(&audioq, AUDIO);
1736
        packet_queue_reset(&videoq, VIDEO);
1737
        switch_channel(&(Channels[SelectedChannel]));
1738
}
1739

    
1740
int switch_channel(SChannel* channel)
1741
{
1742
        if(child_pid > 0)
1743
                KILL_PROCESS(child_pid);
1744
                
1745
        char* parameters_vector[255];
1746
        char argv0[255], parameters_string[255];
1747
        sprintf(argv0, "%s%s", OfferStreamerPath, OfferStreamerFilename);
1748
        
1749
        sprintf(parameters_string, "%s %s", argv0, channel->LaunchString);
1750
        
1751
        int par_count=0;
1752
        
1753
        // split parameters and count them
1754
        char* pch = strtok (parameters_string, " ");
1755
        
1756
        while (pch != NULL)
1757
        {
1758
                if(par_count > 255) break;
1759
                // printf ("%s\n",pch);
1760
                parameters_vector[par_count] = (char*) malloc(sizeof(char)*strlen(pch));
1761
                strcpy(parameters_vector[par_count], pch);
1762
                pch = strtok (NULL, " ");
1763
                par_count++;
1764
        }
1765
        parameters_vector[par_count] = NULL;
1766

    
1767
#ifdef __LINUX__
1768

    
1769
        int d;
1770
        int stdoutS, stderrS;
1771
        FILE* stream;
1772
        stream = fopen("/dev/null", "a+");
1773
        d = fileno(stream);
1774

    
1775
        // create backup descriptors for the current stdout and stderr devices
1776
        stdoutS = dup(STDOUT_FILENO);
1777
        stderrS = dup(STDERR_FILENO);
1778
        
1779
        // redirect child output to /dev/null
1780
        dup2(d, STDOUT_FILENO);
1781
        dup2(d, STDERR_FILENO);
1782

    
1783
        int pid = fork();
1784
        if(pid == 0)
1785
                execv(argv0, parameters_vector);
1786
        else
1787
                child_pid = pid;
1788
        
1789
        // restore backup descriptors in the parent process
1790
        dup2(stdoutS, STDOUT_FILENO);
1791
        dup2(stderrS, STDERR_FILENO);
1792
        
1793
        int i;
1794
        for(i=0; i<par_count; i++)
1795
                free(parameters_vector[i]);
1796
                
1797
        return 0;
1798
#endif
1799

    
1800
        return 1;
1801
}
1802

    
1803
void redraw_buttons()
1804
{
1805
        int i;
1806
        for(i=0; i<NBUTTONS; i++)
1807
        {
1808
                if(Buttons[i].Visible)
1809
                {
1810
                        if(!Buttons[i].Hover)
1811
                        {
1812
                                SDL_BlitSurface(Buttons[i].ButtonIcon, NULL, screen, &Buttons[i].ButtonIconBox);
1813
                                SDL_UpdateRects(screen, 1, &Buttons[i].ButtonIconBox);
1814
                        }
1815
                        else
1816
                        {
1817
                                SDL_BlitSurface(Buttons[i].ButtonHoverIcon, NULL, screen, &(Buttons[i].ButtonIconBox));
1818
                                SDL_UpdateRects(screen, 1, &(Buttons[i].ButtonIconBox));
1819
                        }
1820
                }
1821
        }
1822
}