Statistics
| Branch: | Revision:

chunker-player / chunker_player / chunker_player.c @ 6e7ee06a

History | View | Annotate | Download (48.1 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

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

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

    
37
#define SDL_AUDIO_BUFFER_SIZE 1024
38

    
39
#define MAX_TOLLERANCE 40
40
#define AUDIO        1
41
#define VIDEO        2
42
#define QUEUE_MAX_SIZE 3000
43

    
44
#define FULLSCREEN_ICON_FILE "icons/fullscreen32.png"
45
#define NOFULLSCREEN_ICON_FILE "icons/nofullscreen32.png"
46
#define FULLSCREEN_HOVER_ICON_FILE "icons/fullscreen32.png"
47
#define NOFULLSCREEN_HOVER_ICON_FILE "icons/nofullscreen32.png"
48

    
49
#define BUTTONS_LAYER_OFFSET 10
50

    
51
typedef enum Status { STOPPED, RUNNING, PAUSED } Status;
52

    
53
//#define DEBUG_AUDIO
54
//#define DEBUG_VIDEO
55
#define DEBUG_QUEUE
56
#define DEBUG_SOURCE
57
//#define DEBUG_STATS
58
//#define DEBUG_AUDIO_BUFFER
59
//#define DEBUG_CHUNKER
60

    
61

    
62
short int QueueFillingMode=1;
63
short int QueueStopped=0;
64

    
65
typedef struct PacketQueue {
66
        AVPacketList *first_pkt;
67
        AVPacketList *last_pkt;
68
        int nb_packets;
69
        int size;
70
        SDL_mutex *mutex;
71
        short int queueType;
72
        int last_frame_extracted; //HINT THIS SHOULD BE MORE THAN 4 BYTES
73
        int total_lost_frames;
74
        double density;
75
} PacketQueue;
76

    
77
typedef struct threadVal {
78
        int width;
79
        int height;
80
        float aspect_ratio;
81
} ThreadVal;
82

    
83
int AudioQueueOffset=0;
84
PacketQueue audioq;
85
PacketQueue videoq;
86
AVPacket AudioPkt, VideoPkt;
87
int quit = 0;
88
int SaveYUV=0;
89
char YUVFileName[256];
90

    
91
int queue_filling_threshold = 0;
92

    
93
SDL_Surface *screen;
94
SDL_Overlay *yuv_overlay;
95
SDL_Rect    rect;
96
SDL_Rect *initRect = NULL;
97
SDL_AudioSpec spec;
98
Status CurrStatus = STOPPED;
99

    
100
struct SwsContext *img_convert_ctx = NULL;
101
float ratio;
102

    
103
//SDL_mutex *timing_mutex;
104

    
105
int got_sigint = 0;
106

    
107
long long DeltaTime;
108
short int FirstTimeAudio=1, FirstTime = 1;
109

    
110
int dimAudioQ;
111
float deltaAudioQ;
112
float deltaAudioQError=0;
113

    
114
void SaveFrame(AVFrame *pFrame, int width, int height);
115

    
116
// other GUI staff
117
SDL_Cursor *init_system_cursor(const char *image[]);
118
void refresh_fullscreen_button(int hover);
119
void toggle_fullscreen();
120
void aspect_ratio_resize(float aspect_ratio, int width, int height, int* out_width, int* out_height);
121
int fullscreen = 0; // fullscreen vs windowized flag
122
SDL_Rect    fullscreenIconBox;
123
SDL_Surface *fullscreenIcon;
124
SDL_Surface *fullscreenHoverIcon;
125
SDL_Surface *nofullscreenIcon;
126
SDL_Surface *nofullscreenHoverIcon;
127
SDL_Cursor *defaultCursor;
128
SDL_Cursor *handCursor;
129
int fullscreenButtonHover = 0;
130
int silentMode = 0;
131

    
132
/* XPM */
133
static char *handXPM[] = {
134
/* columns rows colors chars-per-pixel */
135
"32 32 3 1",
136
"  c black",
137
". c gray100",
138
"X c None",
139
/* pixels */
140
"XXXXX  XXXXXXXXXXXXXXXXXXXXXXXXX",
141
"XXXX .. XXXXXXXXXXXXXXXXXXXXXXXX",
142
"XXXX .. XXXXXXXXXXXXXXXXXXXXXXXX",
143
"XXXX .. XXXXXXXXXXXXXXXXXXXXXXXX",
144
"XXXX .. XXXXXXXXXXXXXXXXXXXXXXXX",
145
"XXXX ..   XXXXXXXXXXXXXXXXXXXXXX",
146
"XXXX .. ..   XXXXXXXXXXXXXXXXXXX",
147
"XXXX .. .. ..  XXXXXXXXXXXXXXXXX",
148
"XXXX .. .. .. . XXXXXXXXXXXXXXXX",
149
"   X .. .. .. .. XXXXXXXXXXXXXXX",
150
" ..  ........ .. XXXXXXXXXXXXXXX",
151
" ... ........... XXXXXXXXXXXXXXX",
152
"X .. ........... XXXXXXXXXXXXXXX",
153
"XX . ........... XXXXXXXXXXXXXXX",
154
"XX ............. XXXXXXXXXXXXXXX",
155
"XXX ............ XXXXXXXXXXXXXXX",
156
"XXX ........... XXXXXXXXXXXXXXXX",
157
"XXXX .......... XXXXXXXXXXXXXXXX",
158
"XXXX .......... XXXXXXXXXXXXXXXX",
159
"XXXXX ........ XXXXXXXXXXXXXXXXX",
160
"XXXXX ........ XXXXXXXXXXXXXXXXX",
161
"XXXXX          XXXXXXXXXXXXXXXXX",
162
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
163
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
164
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
165
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
166
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
167
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
168
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
169
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
170
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
171
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
172
"0,0"
173
};
174

    
175
void packet_queue_init(PacketQueue *q, short int Type) {
176
#ifdef DEBUG_QUEUE
177
        printf("QUEUE: INIT BEGIN: NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
178
#endif
179
        memset(q,0,sizeof(PacketQueue));
180
        q->mutex = SDL_CreateMutex();
181
        QueueFillingMode=1;
182
        q->queueType=Type;
183
        q->last_frame_extracted = -1;
184
        q->total_lost_frames = 0;
185
        q->first_pkt= NULL;
186
        //q->last_pkt = NULL;
187
        q->nb_packets = 0;
188
        q->size = 0;
189
        q->density= 0.0;
190
        FirstTime = 1;
191
        FirstTimeAudio = 1;
192
#ifdef DEBUG_QUEUE
193
        printf("QUEUE: INIT END: NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
194
#endif
195
}
196

    
197
void packet_queue_reset(PacketQueue *q, short int Type) {
198
        AVPacketList *tmp,*tmp1;
199
#ifdef DEBUG_QUEUE
200
        printf("QUEUE: RESET BEGIN: NPackets=%d Type=%d LastExtr=%d\n", q->nb_packets, q->queueType, q->last_frame_extracted);
201
#endif
202
        SDL_LockMutex(q->mutex);
203

    
204
        tmp = q->first_pkt;
205
        while(tmp) {
206
                tmp1 = tmp;
207
                tmp = tmp->next;
208
                av_free_packet(&(tmp1->pkt));
209
                av_free(tmp1);
210
#ifdef DEBUG_QUEUE
211
        printf("F ");
212
#endif
213
        }
214
#ifdef DEBUG_QUEUE
215
        printf("\n");
216
#endif
217

    
218
        QueueFillingMode=1;
219
        q->last_frame_extracted = -1;
220
        q->total_lost_frames = 0;
221
        q->first_pkt= NULL;
222
        //q->last_pkt = NULL;
223
        q->nb_packets = 0;
224
        q->size = 0;
225
        q->density= 0.0;
226
        FirstTime = 1;
227
        FirstTimeAudio = 1;
228
#ifdef DEBUG_QUEUE
229
        printf("QUEUE: RESET END: NPackets=%d Type=%d LastExtr=%d\n", q->nb_packets, q->queueType, q->last_frame_extracted);
230
#endif
231
        SDL_UnlockMutex(q->mutex);
232
}
233

    
234
int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
235
        short int skip = 0;
236
        AVPacketList *pkt1, *tmp, *prevtmp;
237
/*
238
        if(q->nb_packets > QUEUE_MAX_SIZE) {
239
#ifdef DEBUG_QUEUE
240
                printf("QUEUE: PUT i have TOO MANY packets %d Type=%d\n", q->nb_packets, q->queueType);
241
#endif    
242
                return -1;
243
  }
244
*/
245
        //make a copy of the incoming packet
246
        if(av_dup_packet(pkt) < 0) {
247
#ifdef DEBUG_QUEUE
248
                printf("QUEUE: PUT in Queue cannot duplicate in packet        : NPackets=%d Type=%d\n",q->nb_packets, q->queueType);
249
#endif
250
                return -1;
251
        }
252
        pkt1 = av_malloc(sizeof(AVPacketList));
253

    
254
        if(!pkt1) {
255
                av_free_packet(pkt);
256
                return -1;
257
        }
258
        pkt1->pkt = *pkt;
259
        pkt1->next = NULL;
260

    
261
        SDL_LockMutex(q->mutex);
262

    
263
        // INSERTION SORT ALGORITHM
264
        // before inserting pkt, check if pkt.stream_index is <= current_extracted_frame.
265
//        if(pkt->stream_index > q->last_frame_extracted) {
266
                // either checking starting from the first_pkt or needed other struct like AVPacketList with next and prev....
267
                //if (!q->last_pkt)
268
                if(!q->first_pkt) {
269
                        q->first_pkt = pkt1;
270
                        q->last_pkt = pkt1;
271
                }
272
                else if(pkt->stream_index < q->first_pkt->pkt.stream_index) {
273
                        //the packet that has arrived is earlier than the first we got some time ago!
274
                        //we need to put it at the head of the queue
275
                        pkt1->next = q->first_pkt;
276
                        q->first_pkt = pkt1;
277
                }
278
                else {
279
                        tmp = q->first_pkt;
280
                        while(tmp->pkt.stream_index < pkt->stream_index) {
281
                                prevtmp = tmp;
282
                                tmp = tmp->next;
283

    
284
                                if(!tmp) {
285
                                        break;
286
                                }
287
                        }
288
                        if(tmp && tmp->pkt.stream_index == pkt->stream_index) {
289
                                //we already have a frame with that index
290
                                skip = 1;
291
#ifdef DEBUG_QUEUE
292
                                printf("QUEUE: PUT: we already have frame with index %d, skipping\n", pkt->stream_index);
293
#endif
294
                        }
295
                        else {
296
                                prevtmp->next = pkt1;
297
                                pkt1->next = tmp;
298
                                if(pkt1->next == NULL)
299
                                        q->last_pkt = pkt1;
300
                        }
301
                        //q->last_pkt->next = pkt1; // It was uncommented when not insertion sort
302
                }
303
                if(skip == 0) {
304
                        //q->last_pkt = pkt1;
305
                        q->nb_packets++;
306
                        q->size += pkt1->pkt.size;
307
                        if(q->nb_packets>=queue_filling_threshold && QueueFillingMode) // && q->queueType==AUDIO)
308
                        {
309
                                QueueFillingMode=0;
310
#ifdef DEBUG_QUEUE
311
                                printf("QUEUE: PUT: FillingMode set to zero\n");
312
#endif
313
                        }
314
                }
315
//        }
316
/*
317
        else {
318
                av_free_packet(&pkt1->pkt);
319
                av_free(pkt1);
320
#ifdef DEBUG_QUEUE
321
                                printf("QUEUE: PUT: NOT inserting because index %d > last extracted %d\n", pkt->stream_index, q->last_frame_extracted);
322
#endif
323
        }
324
*/
325
        if(q->last_pkt->pkt.stream_index > q->first_pkt->pkt.stream_index)
326
                q->density = (double)q->nb_packets / (double)(q->last_pkt->pkt.stream_index - q->first_pkt->pkt.stream_index) * 100.0;
327

    
328
#ifdef DEBUG_STATS
329
        if(q->queueType == AUDIO)
330
                printf("STATS: AUDIO QUEUE DENSITY percentage %f\n", q->density);
331
        if(q->queueType == VIDEO)
332
                printf("STATS: VIDEO QUEUE DENSITY percentage %f\n", q->density);
333
#endif
334

    
335
        SDL_UnlockMutex(q->mutex);
336
        return 0;
337
}
338

    
339

    
340
int decode_enqueued_audio_packet(AVPacket *pkt, PacketQueue *q) {
341
        uint16_t *audio_bufQ = NULL;
342
        int16_t *dataQ = NULL;
343
        int data_sizeQ = AVCODEC_MAX_AUDIO_FRAME_SIZE;
344
        int lenQ;
345
        int ret = 0;
346

    
347
        //set the flag to decoded anyway        
348
        pkt->convergence_duration = -1;
349

    
350
        audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
351
        if(audio_bufQ) {
352
#ifdef DEBUG_AUDIO_BUFFER
353
                printf("AUDIO_BUFFER: about to decode packet %d, size %d, data %d\n", pkt->stream_index, pkt->size, pkt->data);
354
#endif
355
                //decode the packet data
356
                lenQ = avcodec_decode_audio3(aCodecCtx, (int16_t *)audio_bufQ, &data_sizeQ, pkt);
357
                if(lenQ > 0) {
358
                        dataQ = (int16_t *)av_malloc(data_sizeQ); //this will be free later at the time of playback
359
                        if(dataQ) {
360
                                memcpy(dataQ, audio_bufQ, data_sizeQ);
361
                                //discard the old encoded bytes
362
                                av_free(pkt->data);
363
                                //subtract them from queue size
364
                                q->size -= pkt->size;
365
                                pkt->data = (int8_t *)dataQ;
366
                                pkt->size = data_sizeQ;
367
                                //add new size to queue size
368
                                q->size += pkt->size;
369
                                ret = 1;
370
                        }
371
                        else {
372
#ifdef DEBUG_AUDIO_BUFFER
373
                                printf("AUDIO_BUFFER: cannot alloc space for decoded packet %d\n", pkt->stream_index);
374
#endif
375
                        }
376
                }
377
                else {
378
#ifdef DEBUG_AUDIO_BUFFER
379
                        printf("AUDIO_BUFFER: cannot decode packet %d\n", pkt->stream_index);
380
#endif
381
                }
382
                av_free(audio_bufQ);
383
        }
384
        else {
385
#ifdef DEBUG_AUDIO_BUFFER
386
                printf("AUDIO_BUFFER: cannot alloc decode buffer for packet %d\n", pkt->stream_index);
387
#endif
388
        }
389
        return ret; //problems occurred
390
}
391

    
392

    
393
//removes a packet from the list and returns the next
394
AVPacketList *remove_from_queue(PacketQueue *q, AVPacketList *p) {
395
        AVPacketList *retpk = p->next;
396
        q->nb_packets--;
397
        //adjust size here and not in the various cases of the dequeue
398
        q->size -= p->pkt.size;
399
        if(&p->pkt)
400
                av_free_packet(&p->pkt);
401
        if(p)
402
                av_free(p);
403
        return retpk;
404
}
405

    
406
AVPacketList *seek_and_decode_packet_starting_from(AVPacketList *p, PacketQueue *q) {
407
        while(p) {
408
                        //check if audio packet has been already decoded
409
                        if(p->pkt.convergence_duration == 0) {
410
                                //not decoded yet, try to decode it
411
                                if( !decode_enqueued_audio_packet(&(p->pkt), q) ) {
412
                                        //it was not possible to decode this packet, return next one
413
                                        p = remove_from_queue(q, p);
414
                                }
415
                                else
416
                                        return p;
417
                        }
418
                        else
419
                                return p;
420
        }
421
        return NULL;
422
}
423

    
424
void update_queue_stats(PacketQueue *q, int packet_index) {
425
        double percentage = 0.0;        
426
        //compute lost frame statistics
427
        if(q->last_frame_extracted > 0 && packet_index > q->last_frame_extracted) {
428
                q->total_lost_frames = q->total_lost_frames + packet_index - q->last_frame_extracted - 1;
429
                percentage = (double)q->total_lost_frames / (double)q->last_frame_extracted * 100.0;
430
#ifdef DEBUG_STATS
431
                if(q->queueType == AUDIO)
432
                        printf("STATS: AUDIO FRAMES LOST: total %d percentage %f\n", q->total_lost_frames, percentage);
433
                else if(q->queueType == VIDEO)
434
                        printf("STATS: VIDEO FRAMES LOST: total %d percentage %f\n", q->total_lost_frames, percentage);
435
#endif
436
        }
437
}
438

    
439
int packet_queue_get(PacketQueue *q, AVPacket *pkt, short int av) {
440
        //AVPacket tmp;
441
        AVPacketList *pkt1 = NULL;
442
        int ret=-1;
443
        int SizeToCopy=0;
444

    
445
        SDL_LockMutex(q->mutex);
446

    
447
#ifdef DEBUG_QUEUE
448
        printf("QUEUE: Get NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
449
#endif
450

    
451
        if((q->queueType==AUDIO && QueueFillingMode) || QueueStopped)
452
        {
453
                SDL_UnlockMutex(q->mutex);
454
                return -1;
455
        }
456

    
457
        if(av==1) { //somebody requested an audio packet, q is the audio queue
458
                //try to dequeue the first packet of the audio queue
459
                pkt1 = seek_and_decode_packet_starting_from(q->first_pkt, q);
460
                if(pkt1) { //yes we have them!
461
                        if(pkt1->pkt.size-AudioQueueOffset > dimAudioQ) {
462
                                //one packet if enough to give us the requested number of bytes by the audio_callback
463
#ifdef DEBUG_QUEUE
464
                                printf("  AV=1 and Extract from the same packet\n");
465
#endif
466
                                pkt->size = dimAudioQ;
467
                                memcpy(pkt->data,pkt1->pkt.data+AudioQueueOffset,dimAudioQ);
468
                                pkt->dts = pkt1->pkt.dts;
469
                                pkt->pts = pkt1->pkt.pts;
470
                                pkt->stream_index = pkt1->pkt.stream_index;//1;
471
                                pkt->flags = 1;
472
                                pkt->pos = -1;
473
                                pkt->convergence_duration = -1;
474
#ifdef DEBUG_QUEUE
475
                                printf("   Adjust timestamps Old = %lld New = %lld\n", pkt1->pkt.dts, (int64_t)(pkt1->pkt.dts + deltaAudioQ + deltaAudioQError));
476
#endif
477
                                int64_t Olddts=pkt1->pkt.dts;
478
                                pkt1->pkt.dts += deltaAudioQ + deltaAudioQError;
479
                                pkt1->pkt.pts += deltaAudioQ + deltaAudioQError;
480
                                deltaAudioQError=(float)Olddts + deltaAudioQ + deltaAudioQError - (float)pkt1->pkt.dts;
481
                                AudioQueueOffset += dimAudioQ;
482
#ifdef DEBUG_QUEUE
483
                                printf("   deltaAudioQError = %f\n",deltaAudioQError);
484
#endif
485
                                //update overall state of queue
486
                                //size is diminished because we played some audio samples
487
                                //but packet is not removed since a portion has still to be played
488
                                //HINT ERRATA we had a size mismatch since size grows with the
489
                                //number of compressed bytes, and diminishes here with the number
490
                                //of raw uncompressed bytes, hence we update size during the
491
                                //real removes and not here anymore
492
                                //q->size -= dimAudioQ;
493
                                update_queue_stats(q, pkt->stream_index);
494
                                //update index of last frame extracted
495
                                q->last_frame_extracted = pkt->stream_index;
496
#ifdef DEBUG_AUDIO_BUFFER
497
                                printf("1: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
498
#endif
499
                                ret = 1; //OK
500
                        }
501
                        else {
502
                                //we need bytes from two consecutive packets to satisfy the audio_callback
503
#ifdef DEBUG_QUEUE
504
                                printf("  AV = 1 and Extract from 2 packets\n");
505
#endif
506
                                //check for a valid next packet since we will finish the current packet
507
                                //and also take some bytes from the next one
508
                                pkt1->next = seek_and_decode_packet_starting_from(pkt1->next, q);
509
                                if(pkt1->next) {
510
#ifdef DEBUG_QUEUE
511
                                        printf("   we have a next...\n");
512
#endif
513
                                        pkt->size = dimAudioQ;
514
                                        pkt->dts = pkt1->pkt.dts;
515
                                        pkt->pts = pkt1->pkt.pts;
516
                                        pkt->stream_index = pkt1->pkt.stream_index;//1;
517
                                        pkt->flags = 1;
518
                                        pkt->pos = -1;
519
                                        pkt->convergence_duration = -1;
520
                                        {
521
                                                SizeToCopy=pkt1->pkt.size-AudioQueueOffset;
522
#ifdef DEBUG_QUEUE
523
                                                printf("      SizeToCopy=%d\n",SizeToCopy);
524
#endif
525
                                                memcpy(pkt->data, pkt1->pkt.data+AudioQueueOffset, SizeToCopy);
526
                                                memcpy(pkt->data+SizeToCopy, pkt1->next->pkt.data, (dimAudioQ-SizeToCopy)*sizeof(uint8_t));
527
                                        }
528
#ifdef DEBUG_AUDIO_BUFFER
529
                                        printf("2: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
530
#endif
531
                                }
532
#ifdef DEBUG_AUDIO_BUFFER
533
                                else {
534
                                        printf("2: NONEXT\n");
535
                                }
536
#endif
537
                                //HINT SEE before q->size -= SizeToCopy;
538
                                q->first_pkt = remove_from_queue(q, pkt1);
539

    
540
                                // Adjust timestamps
541
                                pkt1 = q->first_pkt;
542
                                if(pkt1) {
543
                                        int Offset=(dimAudioQ-SizeToCopy)*1000/(spec.freq*2*spec.channels);
544
                                        int64_t LastDts=pkt1->pkt.dts;
545
                                        pkt1->pkt.dts += Offset + deltaAudioQError;
546
                                        pkt1->pkt.pts += Offset + deltaAudioQError;
547
                                        deltaAudioQError = (float)LastDts + (float)Offset + deltaAudioQError - (float)pkt1->pkt.dts;
548
#ifdef DEBUG_QUEUE
549
                                        printf("   Adjust timestamps Old = %lld New = %lld\n", LastDts, pkt1->pkt.dts);
550
#endif
551
                                        AudioQueueOffset = dimAudioQ - SizeToCopy;
552
                                        //SEE BEFORE HINT q->size -= AudioQueueOffset;
553
                                        ret = 1;
554
                                }
555
                                else {
556
                                        AudioQueueOffset=0;
557
#ifdef DEBUG_AUDIO_BUFFER
558
                                        printf("0: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
559
#endif
560
                                }
561
#ifdef DEBUG_QUEUE
562
                                printf("   deltaAudioQError = %f\n",deltaAudioQError);
563
#endif
564
                                update_queue_stats(q, pkt->stream_index);
565
                                //update index of last frame extracted
566
                                q->last_frame_extracted = pkt->stream_index;
567
                        }
568
                }
569
        }
570
        else { //somebody requested a video packet, q is the video queue
571
                pkt1 = q->first_pkt;
572
                if(pkt1) {
573
#ifdef DEBUG_QUEUE
574
                        printf("  AV not 1\n");
575
#endif
576
                        pkt->size = pkt1->pkt.size;
577
                        pkt->dts = pkt1->pkt.dts;
578
                        pkt->pts = pkt1->pkt.pts;
579
                        pkt->stream_index = pkt1->pkt.stream_index;
580
                        pkt->flags = pkt1->pkt.flags;
581
                        pkt->pos = pkt1->pkt.pos;
582
                        pkt->convergence_duration = pkt1->pkt.convergence_duration;
583
                        //*pkt = pkt1->pkt;
584
                        memcpy(pkt->data, pkt1->pkt.data, pkt1->pkt.size);
585

    
586
                        //HINT SEE BEFORE q->size -= pkt1->pkt.size;
587
                        q->first_pkt = remove_from_queue(q, pkt1);
588

    
589
                        ret = 1;
590
                        update_queue_stats(q, pkt->stream_index);
591
                        //update index of last frame extracted
592
                        q->last_frame_extracted = pkt->stream_index;
593
                }
594
#ifdef DEBUG_QUEUE
595
                else {
596
                        printf("  VIDEO pk1 NULL!!!!\n");
597
                }
598
#endif
599
        }
600

    
601
        if(q->nb_packets==0 && q->queueType==AUDIO) {
602
                QueueFillingMode=1;
603
#ifdef DEBUG_QUEUE
604
                printf("QUEUE: Get FillingMode ON\n");
605
#endif
606
        }
607
#ifdef DEBUG_QUEUE
608
        printf("QUEUE: Get LastFrameExtracted = %d\n",q->last_frame_extracted);
609
        printf("QUEUE: Get Tot lost frames = %d\n",q->total_lost_frames);
610
#endif
611

    
612
        SDL_UnlockMutex(q->mutex);
613
        return ret;
614
}
615

    
616

    
617
int audio_decode_frame(uint8_t *audio_buf, int buf_size) {
618
        //struct timeval now;
619
        int audio_pkt_size = 0;
620
        long long Now;
621
        short int DecodeAudio=0, SkipAudio=0;
622
        //int len1, data_size;
623

    
624
        //gettimeofday(&now,NULL);
625
        //Now = (now.tv_sec)*1000+now.tv_usec/1000;
626
        Now=(long long)SDL_GetTicks();
627

    
628
        if(QueueFillingMode || QueueStopped)
629
        {
630
                //SDL_LockMutex(timing_mutex);
631
                FirstTimeAudio=1;
632
                FirstTime = 1;
633
                //SDL_UnlockMutex(timing_mutex);
634
                return -1;
635
        }
636

    
637
        if((FirstTime==1 || FirstTimeAudio==1) && audioq.size>0) {
638
                if(audioq.first_pkt->pkt.pts>0)
639
                {
640
                        //SDL_LockMutex(timing_mutex);
641
                        DeltaTime=Now-(long long)(audioq.first_pkt->pkt.pts);
642
                        FirstTimeAudio = 0;
643
                        FirstTime = 0;
644
                        //SDL_UnlockMutex(timing_mutex);
645
#ifdef DEBUG_AUDIO 
646
                         printf("AUDIO: audio_decode_frame - DeltaTimeAudio=%lld\n",DeltaTime);
647
#endif
648
                }
649
        }
650

    
651
#ifdef DEBUG_AUDIO 
652
        if(audioq.first_pkt)
653
        {
654
                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);
655
                printf("AUDIO: QueueLen=%d ",(int)audioq.nb_packets);
656
                printf("AUDIO: QueueSize=%d\n",(int)audioq.size);
657
        }
658
        else
659
                printf("AUDIO: audio_decode_frame - Empty queue\n");
660
#endif
661

    
662

    
663
        if(audioq.nb_packets>0) {
664
                if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
665
                        SkipAudio = 1;
666
                        DecodeAudio = 0;
667
                }
668
                else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
669
                        (long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
670
                                SkipAudio = 0;
671
                                DecodeAudio = 1;
672
                }
673
        }
674
                
675
        while(SkipAudio==1 && audioq.size>0) {
676
                SkipAudio = 0;
677
#ifdef DEBUG_AUDIO
678
                 printf("AUDIO: skipaudio: queue size=%d\n",audioq.size);
679
#endif
680
                if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
681
                        return -1;
682
                }
683
                if(audioq.first_pkt)
684
                {
685
                        if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
686
                                SkipAudio = 1;
687
                                DecodeAudio = 0;
688
                        }
689
                        else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
690
                                (long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
691
                                        SkipAudio = 0;
692
                                        DecodeAudio = 1;
693
                        }
694
                }
695
        }
696
        if(DecodeAudio==1) {
697
                if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
698
                        return -1;
699
                }
700
                memcpy(audio_buf,AudioPkt.data,AudioPkt.size);
701
                audio_pkt_size = AudioPkt.size;
702
#ifdef DEBUG_AUDIO
703
                 printf("AUDIO: Decode audio\n");
704
#endif
705
        }
706

    
707
        return audio_pkt_size;
708
}
709

    
710

    
711
int video_callback(void *valthread) {
712
        //AVPacket pktvideo;
713
        AVCodecContext  *pCodecCtx;
714
        AVCodec         *pCodec;
715
        AVFrame         *pFrame;
716
        AVPacket        packet;
717
        int frameFinished;
718
        int countexit;
719
        AVPicture pict;
720
        //FILE *frecon;
721
        SDL_Event event;
722
        long long Now;
723
        short int SkipVideo, DecodeVideo;
724

    
725
        //double frame_rate = 0.0,time_between_frames=0.0;
726
        //struct timeval now;
727

    
728
        //int wait_for_sync = 1;
729
        ThreadVal *tval;
730
        tval = (ThreadVal *)valthread;
731

    
732
        //frame_rate = tval->framerate;
733
        //time_between_frames = 1.e6 / frame_rate;
734
        //gettimeofday(&time_now,0);
735

    
736
        //frecon = fopen("recondechunk.mpg","wb");
737

    
738
        pCodecCtx=avcodec_alloc_context();
739
        pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
740
#ifdef H264_VIDEO_ENCODER
741
        pCodecCtx->codec_id  = CODEC_ID_H264;
742
        pCodecCtx->me_range = 16;
743
        pCodecCtx->max_qdiff = 4;
744
        pCodecCtx->qmin = 10;
745
        pCodecCtx->qmax = 51;
746
        pCodecCtx->qcompress = 0.6;
747
#else
748
        pCodecCtx->codec_id  = CODEC_ID_MPEG4;
749
#endif
750
        //pCodecCtx->bit_rate = 400000;
751
        // resolution must be a multiple of two
752
        pCodecCtx->width = tval->width;//176;//352;
753
        pCodecCtx->height = tval->height;//144;//288;
754
        // frames per second
755
        //pCodecCtx->time_base = (AVRational){1,25};
756
        //pCodecCtx->gop_size = 10; // emit one intra frame every ten frames
757
        //pCodecCtx->max_b_frames=1;
758
        pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
759
        pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
760

    
761
        if(pCodec==NULL) {
762
                fprintf(stderr, "Unsupported codec!\n");
763
                return -1; // Codec not found
764
        }
765
        if(avcodec_open(pCodecCtx, pCodec) < 0) {
766
                fprintf(stderr, "could not open codec\n");
767
                return -1; // Could not open codec
768
        }
769
        pFrame=avcodec_alloc_frame();
770
        if(pFrame==NULL) {
771
                printf("Memory error!!!\n");
772
                return -1;
773
        }
774

    
775
        while(!quit) {
776
                if(QueueFillingMode || QueueStopped)
777
                {
778
                        //SDL_LockMutex(timing_mutex);
779
                        FirstTime = 1;
780
                        //SDL_UnlockMutex(timing_mutex);
781
                        usleep(5000);
782
                        continue;
783
                }
784

    
785
                DecodeVideo = 0;
786
                SkipVideo = 0;
787
                Now=(long long)SDL_GetTicks();
788
                if(FirstTime==1 && videoq.size>0) {
789
                        if(videoq.first_pkt->pkt.pts>0)
790
                        {
791
                                //SDL_LockMutex(timing_mutex);
792
                                DeltaTime=Now-(long long)videoq.first_pkt->pkt.pts;
793
                                FirstTime = 0;
794
                                //SDL_UnlockMutex(timing_mutex);
795
                        }
796
#ifdef DEBUG_VIDEO 
797
                         printf("VIDEO: VideoCallback - DeltaTimeAudio=%lld\n",DeltaTime);
798
#endif
799
                }
800

    
801
#ifdef DEBUG_VIDEO 
802
                if(videoq.first_pkt)
803
                {
804
                        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);
805
                        printf("VIDEO: Index=%d ", (int)videoq.first_pkt->pkt.stream_index);
806
                        printf("VIDEO: QueueLen=%d ", (int)videoq.nb_packets);
807
                        printf("VIDEO: QueueSize=%d\n", (int)videoq.size);
808
                }
809
                else
810
                        printf("VIDEO: VideoCallback - Empty queue\n");
811
#endif
812

    
813
                if(videoq.nb_packets>0) {
814
                        if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)<Now-(long long)MAX_TOLLERANCE) {
815
                                SkipVideo = 1;
816
                                DecodeVideo = 0;
817
                        }
818
                        else 
819
                                if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)>=Now-(long long)MAX_TOLLERANCE &&
820
                                   ((long long)videoq.first_pkt->pkt.pts+DeltaTime)<=Now+(long long)MAX_TOLLERANCE) {
821
                                        SkipVideo = 0;
822
                                        DecodeVideo = 1;
823
                                }
824
                }
825
#ifdef DEBUG_VIDEO
826
                printf("VIDEO: skipvideo:%d decodevideo:%d\n",SkipVideo,DecodeVideo);
827
#endif
828

    
829
                while(SkipVideo==1 && videoq.size>0) {
830
                        SkipVideo = 0;
831
#ifdef DEBUG_VIDEO 
832
                         printf("VIDEO: Skip Video\n");
833
#endif
834
                        if(packet_queue_get(&videoq,&VideoPkt,0) < 0) {
835
                                break;
836
                        }
837
                        avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
838
                        if(videoq.first_pkt)
839
                        {
840
                                if((long long)videoq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
841
                                        SkipVideo = 1;
842
                                        DecodeVideo = 0;
843
                                }
844
                                else if((long long)videoq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
845
                                                                (long long)videoq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
846
                                        SkipVideo = 0;
847
                                        DecodeVideo = 1;
848
                                }
849
                        }
850
                }
851
                
852
                if(DecodeVideo==1) {
853
                        if(packet_queue_get(&videoq,&VideoPkt,0) > 0) {
854

    
855
#ifdef DEBUG_VIDEO
856
                                printf("VIDEO: Decode video FrameTime=%lld Now=%lld\n",(long long)VideoPkt.pts+DeltaTime,Now);
857
#endif
858

    
859
                                avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
860

    
861
                                if(frameFinished) { // it must be true all the time else error
862
#ifdef DEBUG_VIDEO
863
                                        printf("VIDEO: FrameFinished\n");
864
#endif
865
                                        if(SaveYUV)
866
                                                SaveFrame(pFrame, pCodecCtx->width, pCodecCtx->height);
867
                                        //fwrite(pktvideo.data, 1, pktvideo.size, frecon);
868

    
869
                                        if(silentMode)
870
                                                continue;
871

    
872
                                        // Lock SDL_yuv_overlay
873
                                        if(SDL_MUSTLOCK(screen)) {
874
                                                if(SDL_LockSurface(screen) < 0) {
875
                                                        continue;
876
                                                }
877
                                        }
878

    
879
                                        if(SDL_LockYUVOverlay(yuv_overlay) < 0) {
880
                                                if(SDL_MUSTLOCK(screen)) {
881
                                                        SDL_UnlockSurface(screen);
882
                                                }
883
                                                continue;
884
                                        }
885
                                        pict.data[0] = yuv_overlay->pixels[0];
886
                                        pict.data[1] = yuv_overlay->pixels[2];
887
                                        pict.data[2] = yuv_overlay->pixels[1];
888

    
889
                                        pict.linesize[0] = yuv_overlay->pitches[0];
890
                                        pict.linesize[1] = yuv_overlay->pitches[2];
891
                                        pict.linesize[2] = yuv_overlay->pitches[1];
892

    
893
                                        if(img_convert_ctx == NULL) {
894
                                                img_convert_ctx = sws_getContext(tval->width, tval->height, PIX_FMT_YUV420P, initRect->w, initRect->h, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
895
                                                if(img_convert_ctx == NULL) {
896
                                                        fprintf(stderr, "Cannot initialize the conversion context!\n");
897
                                                        exit(1);
898
                                                }
899
                                        }
900
                                        // let's draw the data (*yuv[3]) on a SDL screen (*screen)
901
                                        sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, tval->height, pict.data, pict.linesize);
902
                                        SDL_UnlockYUVOverlay(yuv_overlay);
903
                                        // Show, baby, show!
904
                                        SDL_DisplayYUVOverlay(yuv_overlay, &rect);
905

    
906
                                        //redisplay logo
907
                                        /**SDL_BlitSurface(image, NULL, screen, &dest);*/
908
                                        /* Update the screen area just changed */
909
                                        /**SDL_UpdateRects(screen, 1, &dest);*/
910
                                        
911
                                        refresh_fullscreen_button(fullscreenButtonHover);
912

    
913
                                        if(SDL_MUSTLOCK(screen)) {
914
                                                SDL_UnlockSurface(screen);
915
                                        }
916
                                } //if FrameFinished
917
                        } // if packet_queue_get
918
                } //if DecodeVideo=1
919

    
920
                usleep(5000);
921
        }
922
        av_free(pCodecCtx);
923
        //fclose(frecon);
924
#ifdef DEBUG_VIDEO
925
         printf("VIDEO: video callback end\n");
926
#endif
927
        return 1;
928
}
929

    
930

    
931
void aspect_ratio_rect(float aspect_ratio, int width, int height)
932
{
933
        int h = 0, w = 0, x, y;
934
        aspect_ratio_resize(aspect_ratio, width, height, &w, &h);
935
        x = (width - w) / 2;
936
        y = (height - h) / 2;
937
        rect.x = x;//x;
938
        rect.y = y;//y;
939
        rect.w = w;
940
        rect.h = h;
941

    
942
//         printf("setting video mode %dx%d\n", rect.w, rect.h);
943
}
944

    
945

    
946
void audio_callback(void *userdata, Uint8 *stream, int len) {
947

    
948
        //AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
949
        int audio_size;
950

    
951
        static uint8_t audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
952

    
953
        audio_size = audio_decode_frame(audio_buf, sizeof(audio_buf));
954
        if(audio_size != len) {
955
                memset(stream, 0, len);
956
        } else {
957
                memcpy(stream, (uint8_t *)audio_buf, len);
958
        }
959
}
960

    
961
void SetupGUI()
962
{
963
        // init SDL_image
964
        int flags=IMG_INIT_JPG|IMG_INIT_PNG;
965
        int initted=IMG_Init(flags);
966
        if(initted&flags != flags) {
967
                printf("IMG_Init: Failed to init required jpg and png support!\n");
968
                printf("IMG_Init: %s\n", IMG_GetError());
969
                exit(1);
970
        }
971

    
972
        SDL_Surface *temp;
973
        int screen_w = 0, screen_h = 0;
974

    
975
        /* Load a BMP file on a surface */
976
        temp = IMG_Load(FULLSCREEN_ICON_FILE);
977
        if (temp == NULL) {
978
                fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_ICON_FILE, SDL_GetError());
979
                exit(1);
980
        }
981

    
982
        if(rect.w > temp->w)
983
                screen_w = rect.w;
984
        else
985
                screen_w = temp->w;
986

    
987
                screen_h = rect.h + temp->h + BUTTONS_LAYER_OFFSET;
988

    
989
        SDL_WM_SetCaption("Filling buffer...", NULL);
990
        // Make a screen to put our video
991
#ifndef __DARWIN__
992
        screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
993
#else
994
        screen = SDL_SetVideoMode(screen_w, screen_h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
995
#endif
996
        if(!screen) {
997
                fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
998
                exit(1);
999
        }
1000
        
1001
        window_width = screen_w;
1002
        window_height = screen_h;
1003
        
1004
        fullscreenIcon = SDL_DisplayFormatAlpha(temp);
1005
        SDL_FreeSurface(temp);
1006

    
1007
        // load icon buttons
1008
        temp = IMG_Load(NOFULLSCREEN_ICON_FILE);
1009
        if (temp == NULL) {
1010
                fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_ICON_FILE, SDL_GetError());
1011
                exit(1);
1012
        }
1013
        nofullscreenIcon = SDL_DisplayFormatAlpha(temp);
1014
        SDL_FreeSurface(temp);
1015

    
1016
        temp = IMG_Load(NOFULLSCREEN_HOVER_ICON_FILE);
1017
        if (temp == NULL) {
1018
                fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
1019
                exit(1);
1020
        }
1021
        nofullscreenHoverIcon = SDL_DisplayFormatAlpha(temp);
1022
        SDL_FreeSurface(temp);
1023

    
1024
        temp = IMG_Load(FULLSCREEN_HOVER_ICON_FILE);
1025
        if (temp == NULL) {
1026
                fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
1027
                exit(1);
1028
        }
1029
        fullscreenHoverIcon = SDL_DisplayFormatAlpha(temp);
1030
        SDL_FreeSurface(temp);
1031

    
1032
        defaultCursor = SDL_GetCursor();
1033
        handCursor = init_system_cursor(handXPM);
1034

    
1035
        /* Copy on the screen surface 
1036
        surface should be blocked now.
1037
        */
1038
        fullscreenIconBox.x = (screen_w - fullscreenIcon->w) / 2;
1039
        fullscreenIconBox.y = rect.h + (BUTTONS_LAYER_OFFSET/2);
1040
        fullscreenIconBox.w = fullscreenIcon->w;
1041
        fullscreenIconBox.h = fullscreenIcon->h;
1042
        printf("x%d y%d w%d h%d\n", fullscreenIconBox.x, fullscreenIconBox.y, fullscreenIconBox.w, fullscreenIconBox.h);
1043

    
1044
        //create video overlay for display of video frames
1045
        yuv_overlay = SDL_CreateYUVOverlay(rect.w, rect.h, SDL_YV12_OVERLAY, screen);
1046

    
1047
        if ( yuv_overlay == NULL ) {
1048
                fprintf(stderr,"SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError());
1049
                exit(1);
1050
        }
1051

    
1052
        if ( yuv_overlay->hw_overlay )
1053
                fprintf(stderr,"SDL: Using hardware overlay.");
1054
        rect.x = (screen_w - rect.w) / 2;
1055
        SDL_DisplayYUVOverlay(yuv_overlay, &rect);
1056

    
1057
        /**SDL_BlitSurface(image, NULL, screen, &dest);*/
1058
        SDL_BlitSurface(fullscreenIcon, NULL, screen, &fullscreenIconBox);
1059
        /* Update the screen area just changed */
1060
        SDL_UpdateRects(screen, 1, &fullscreenIconBox);
1061
}
1062

    
1063
void SaveFrame(AVFrame *pFrame, int width, int height) {
1064
        FILE *pFile;
1065
        int  y;
1066
  
1067
         // Open file
1068
        pFile=fopen(YUVFileName, "ab");
1069
        if(pFile==NULL)
1070
                return;
1071
  
1072
        // Write header
1073
        //fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1074
  
1075
        // Write Y data
1076
        for(y=0; y<height; y++)
1077
                  fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile);
1078
        // Write U data
1079
        for(y=0; y<height/2; y++)
1080
                  fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile);
1081
        // Write V data
1082
        for(y=0; y<height/2; y++)
1083
                  fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile);
1084
  
1085
        // Close file
1086
        fclose(pFile);
1087
}
1088

    
1089
void sigint_handler (int signal) {
1090
        printf("Caught SIGINT, exiting...");
1091
        got_sigint = 1;
1092
}
1093

    
1094
void ProcessKeys() {
1095
        static Uint32 LastTime=0;
1096
        static int LastKey=-1;
1097

    
1098
        Uint32 Now=SDL_GetTicks();
1099
        Uint8* keystate=SDL_GetKeyState(NULL);
1100
        if(keystate[SDLK_SPACE] &&
1101
          (LastKey!=SDLK_SPACE || (LastKey==SDLK_SPACE && (Now-LastTime>1000))))
1102
        {
1103
                LastKey=SDLK_SPACE;
1104
                LastTime=Now;
1105
                QueueStopped=!QueueStopped;
1106
                if(QueueStopped) CurrStatus = PAUSED;
1107
                else CurrStatus = RUNNING;
1108
                refresh_fullscreen_button(0);
1109
        }
1110
        if(keystate[SDLK_ESCAPE] &&
1111
          (LastKey!=SDLK_ESCAPE || (LastKey==SDLK_ESCAPE && (Now-LastTime>1000))))
1112
        {
1113
                LastKey=SDLK_ESCAPE;
1114
                LastTime=Now;
1115
                quit=1;
1116
        }
1117
        /*if(keystate[SDLK_f] &&
1118
          (LastKey!=SDLK_f || (LastKey==SDLK_f && (Now-LastTime>1000))))
1119
        {
1120
                LastKey=SDLK_f;
1121
                LastTime=Now;
1122
                SDL_WM_ToggleFullScreen(NULL);
1123
        }*/
1124
}
1125

    
1126
int main(int argc, char *argv[]) {
1127
        int i, j, videoStream, outbuf_size, out_size, out_size_audio, seq_current_chunk = 0, audioStream;
1128
        int len1, data_size, stime, cont=0;
1129
        int frameFinished, len_audio;
1130
        int numBytes, outbuf_audio_size, audio_size;
1131

    
1132
        int y;
1133
        
1134
        uint8_t *outbuf,*outbuf_audio;
1135
        uint8_t *outbuf_audi_audio;
1136
        int httpPort = -1;
1137
        
1138
        AVFormatContext *pFormatCtx;
1139

    
1140
        AVCodec         *pCodec,*aCodec;
1141
        AVFrame         *pFrame; 
1142

    
1143
        AVPicture pict;
1144
        SDL_Thread *video_thread;//exit_thread,*exit_thread2;
1145
        SDL_Event event;
1146
        SDL_AudioSpec wanted_spec;
1147
        
1148
        struct MHD_Daemon *daemon = NULL;        
1149

    
1150
        char buf[1024],outfile[1024], basereadfile[1024],readfile[1024];
1151
        FILE *fp;        
1152
        int width,height,asample_rate,achannels;
1153

    
1154
        ThreadVal *tval;
1155
        tval = (ThreadVal *)malloc(sizeof(ThreadVal));
1156
                
1157
        if(argc<9) {
1158
                printf("chunker_player width height aspect_ratio audio_sample_rate audio_channels queue_thresh httpd_port silentMode <YUVFilename>\n");
1159
                exit(1);
1160
        }
1161
        sscanf(argv[1],"%d",&width);
1162
        sscanf(argv[2],"%d",&height);
1163
        sscanf(argv[3],"%f",&ratio);
1164
        sscanf(argv[4],"%d",&asample_rate);
1165
        sscanf(argv[5],"%d",&achannels);
1166
        sscanf(argv[6],"%d",&queue_filling_threshold);
1167
        sscanf(argv[7],"%d",&httpPort);
1168
        sscanf(argv[8],"%d",&silentMode);
1169
        
1170
        if(argc==10)
1171
        {
1172
                sscanf(argv[9],"%s",YUVFileName);
1173
                printf("YUVFile: %s\n",YUVFileName);
1174
                FILE* fp=fopen(YUVFileName, "wb");
1175
                if(fp)
1176
                {
1177
                        SaveYUV=1;
1178
                        fclose(fp);
1179
                }
1180
                else
1181
                        printf("ERROR: Unable to create YUVFile\n");
1182
        }
1183

    
1184
        tval->width = width;
1185
        tval->height = height;
1186
        tval->aspect_ratio = ratio;
1187

    
1188
        // Register all formats and codecs
1189
        av_register_all();
1190
        if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
1191
                fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
1192
                return -1;
1193
        }
1194

    
1195
        aCodecCtx = avcodec_alloc_context();
1196
        //aCodecCtx->bit_rate = 64000;
1197
        aCodecCtx->sample_rate = asample_rate;
1198
        aCodecCtx->channels = achannels;
1199
#ifdef MP3_AUDIO_ENCODER
1200
        aCodec = avcodec_find_decoder(CODEC_ID_MP3); // codec audio
1201
#else
1202
        aCodec = avcodec_find_decoder(CODEC_ID_MP2);
1203
#endif
1204
        printf("MP2 codec id %d MP3 codec id %d\n",CODEC_ID_MP2,CODEC_ID_MP3);
1205
        if(!aCodec) {
1206
                printf("Codec not found!\n");
1207
                return -1;
1208
        }
1209
        if(avcodec_open(aCodecCtx, aCodec)<0) {
1210
                fprintf(stderr, "could not open codec\n");
1211
                return -1; // Could not open codec
1212
        }
1213
        printf("using audio Codecid: %d ",aCodecCtx->codec_id);
1214
        printf("samplerate: %d ",aCodecCtx->sample_rate);
1215
        printf("channels: %d\n",aCodecCtx->channels);
1216
        wanted_spec.freq = aCodecCtx->sample_rate;
1217
        wanted_spec.format = AUDIO_S16SYS;
1218
        wanted_spec.channels = aCodecCtx->channels;
1219
        wanted_spec.silence = 0;
1220
        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
1221
        wanted_spec.callback = audio_callback;
1222
        wanted_spec.userdata = aCodecCtx;
1223
        if(!silentMode)
1224
                if(SDL_OpenAudio(&wanted_spec,&spec)<0) {
1225
                        fprintf(stderr,"SDL_OpenAudio: %s\n",SDL_GetError());
1226
                        return -1;
1227
                }
1228
        dimAudioQ = spec.size;
1229
        deltaAudioQ = (float)((float)spec.samples)*1000/spec.freq;
1230

    
1231
#ifdef DEBUG_AUDIO
1232
        printf("freq:%d\n",spec.freq);
1233
        printf("format:%d\n",spec.format);
1234
        printf("channels:%d\n",spec.channels);
1235
        printf("silence:%d\n",spec.silence);
1236
        printf("samples:%d\n",spec.samples);
1237
        printf("size:%d\n",spec.size);
1238
        printf("deltaAudioQ: %f\n",deltaAudioQ);
1239
#endif
1240

    
1241
        pFrame=avcodec_alloc_frame();
1242
        if(pFrame==NULL) {
1243
                printf("Memory error!!!\n");
1244
                return -1;
1245
        }
1246
        outbuf_audio = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1247

    
1248
        //initialize the audio and the video queues
1249
        packet_queue_init(&audioq, AUDIO);
1250
        packet_queue_init(&videoq, VIDEO);
1251

    
1252
        //calculate aspect ratio and put updated values in rect
1253
        aspect_ratio_rect(ratio, width, height);
1254

    
1255
        initRect = (SDL_Rect*) malloc(sizeof(SDL_Rect));
1256
        if(!initRect)
1257
        {
1258
                printf("Memory error!!!\n");
1259
                return -1;
1260
        }
1261
        initRect->x = rect.x;
1262
        initRect->y = rect.y;
1263
        initRect->w = rect.w;
1264
        initRect->h = rect.h;
1265

    
1266
        //SetupGUI("napalogo_small.bmp");
1267
        if(!silentMode)
1268
                SetupGUI();
1269
        
1270
        // Init audio and video buffers
1271
        av_init_packet(&AudioPkt);
1272
        av_init_packet(&VideoPkt);
1273
        AudioPkt.data=(uint8_t *)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1274
        if(!AudioPkt.data) return 0;
1275
        VideoPkt.data=(uint8_t *)malloc(width*height*3/2);
1276
        if(!VideoPkt.data) return 0;
1277
        
1278
        SDL_PauseAudio(0);
1279
        video_thread = SDL_CreateThread(video_callback,tval);
1280
        
1281
        //this thread fetches chunks from the network by listening to the following path, port
1282
        daemon = initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, httpPort);
1283
        CurrStatus = RUNNING;
1284

    
1285
        // Wait for user input
1286
        while(!quit) {
1287
                if(QueueFillingMode) {
1288
                        SDL_WM_SetCaption("Filling buffer...", NULL);
1289

    
1290
                        if(audioq.nb_packets==0 && audioq.last_frame_extracted>0) {        // video ended therefore init queues
1291
#ifdef DEBUG_QUEUE
1292
                                printf("QUEUE: MAIN SHOULD RESET\n");
1293
#endif
1294
                                packet_queue_reset(&audioq, AUDIO);
1295
                                packet_queue_reset(&videoq, VIDEO);
1296
                        }
1297

    
1298
#ifdef DEBUG_QUEUE
1299
                        //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);
1300
#endif
1301
                }
1302
                else
1303
                        SDL_WM_SetCaption("NAPA-Wine Player", NULL);
1304

    
1305
                int x = 0, y = 0;
1306
                int resize_w, resize_h;
1307
                int tmp_switch = 0;
1308
                //listen for key and mouse
1309
                while(SDL_PollEvent(&event)) {
1310
                        switch(event.type) {
1311
                                case SDL_QUIT:
1312
                                        //exit(0);
1313
                                        quit=1;
1314
                                break;
1315
                                case SDL_VIDEORESIZE:
1316
                                        //printf("\tSDL_VIDEORESIZE\n");
1317
                                        
1318
                                        // if running, pause until resize has done
1319
                                        if(CurrStatus == RUNNING)
1320
                                        {
1321
                                                QueueStopped = 1;
1322
                                                CurrStatus = PAUSED;
1323
                                                tmp_switch = 1;
1324
                                        }
1325
#ifndef __DARWIN__
1326
                                        screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
1327
#else
1328
                                        screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
1329
#endif
1330
                                        if(!screen) {
1331
                                                fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
1332
                                                exit(1);
1333
                                        }
1334
                                        
1335
                                        window_width = event.resize.w;
1336
                                        window_height = event.resize.h;
1337
                                        
1338
                                        aspect_ratio_rect(ratio, event.resize.w, event.resize.h - BUTTONS_LAYER_OFFSET - fullscreenIconBox.h);
1339
                                        
1340
                                        fullscreenIconBox.x = (event.resize.w - fullscreenIcon->w) / 2;
1341

    
1342
                                        // put the button just below the video overlay
1343
//                                         fullscreenIcon.y = rect.y+rect.h + (BUTTONS_LAYER_OFFSET/2);
1344

    
1345
                                        // put the button at the bottom edge of the screen
1346
                                        fullscreenIconBox.y = event.resize.h - fullscreenIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1347
                                        
1348
                                        // refresh_fullscreen_button(0);
1349
                                        
1350
                                        if(tmp_switch)
1351
                                        {
1352
                                                QueueStopped = 0;
1353
                                                CurrStatus= RUNNING;
1354
                                                tmp_switch = 0;
1355
                                        }
1356
                                break;
1357
                                case SDL_ACTIVEEVENT:
1358
                                        //printf("\tSDL_ACTIVEEVENT\n");
1359
                                        // if the window was iconified or restored
1360
                                        /*if(event.active.state & SDL_APPACTIVE)
1361
                                        {
1362
                                                //If the application is being reactivated
1363
                                                if( event.active.gain != 0 )
1364
                                                {
1365
                                                        //SDL_WM_SetCaption( "Window Event Test restored", NULL );
1366
                                                }
1367
                                        }
1368

1369
                                        //If something happened to the keyboard focus
1370
                                        else if( event.active.state & SDL_APPINPUTFOCUS )
1371
                                        {
1372
                                                //If the application gained keyboard focus
1373
                                                if( event.active.gain != 0 )
1374
                                                {
1375
                                                }
1376
                                        }
1377
                                        //If something happened to the mouse focus
1378
                                        else if( event.active.state & SDL_APPMOUSEFOCUS )
1379
                                        {
1380
                                                //If the application gained mouse focus
1381
                                                if( event.active.gain != 0 )
1382
                                                {
1383
                                                }
1384
                                        }*/
1385
                                        break;
1386
                                case SDL_MOUSEMOTION:
1387
                                        //printf("\tSDL_MOUSEMOTION\n");
1388
                                        x = event.motion.x;
1389
                                        y = event.motion.y;
1390
                                        //If the mouse is over the button
1391
                                        if(
1392
                                                ( x > fullscreenIconBox.x ) && ( x < fullscreenIconBox.x + fullscreenIcon->w )
1393
                                                && ( y > fullscreenIconBox.y ) && ( y < fullscreenIconBox.y + fullscreenIcon->h )
1394
                                        )
1395
                                        {
1396
                                                fullscreenButtonHover = 1;
1397
                                                SDL_SetCursor(handCursor);
1398
                                        }
1399
                                        //If not
1400
                                        else
1401
                                        {
1402
                                                fullscreenButtonHover = 0;
1403
                                                SDL_SetCursor(defaultCursor);
1404
                                        }
1405
                                break;
1406
                                case SDL_MOUSEBUTTONUP:
1407
                                        //printf("\tSDL_MOUSEBUTTONUP\n");
1408
                                        if( event.button.button != SDL_BUTTON_LEFT )
1409
                                                break;
1410
                                        
1411
                                        x = event.motion.x;
1412
                                        y = event.motion.y;
1413
                                        //If the mouse is over the button
1414
                                        if(
1415
                                                ( x > fullscreenIconBox.x ) && ( x < fullscreenIconBox.x + fullscreenIcon->w )
1416
                                                && ( y > fullscreenIconBox.y ) && ( y < fullscreenIconBox.y + fullscreenIcon->h )
1417
                                        )
1418
                                        {
1419
                                                
1420
                                                // if running, pause until resize has done
1421
                                                if(CurrStatus == RUNNING)
1422
                                                {
1423
                                                        QueueStopped = 1;
1424
                                                        CurrStatus = PAUSED;
1425
                                                        tmp_switch = 1;
1426
                                                }
1427
                                                
1428
                                                toggle_fullscreen();
1429
                                                
1430
                                                fullscreenButtonHover = 1;
1431
                                                
1432
                                                if(tmp_switch)
1433
                                                {
1434
                                                        QueueStopped = 0;
1435
                                                        CurrStatus= RUNNING;
1436
                                                        tmp_switch = 0;
1437
                                                }
1438
                                        }
1439
                                break;
1440
                        }
1441
                        ProcessKeys();
1442
                }
1443
                usleep(120000);
1444
        }
1445

    
1446
        //TERMINATE
1447
        IMG_Quit();
1448

    
1449
        // Stop audio&video playback
1450
        SDL_WaitThread(video_thread,NULL);
1451
        SDL_PauseAudio(1);
1452
        SDL_CloseAudio();
1453
        //SDL_DestroyMutex(timing_mutex);
1454
        SDL_Quit();
1455
        av_free(aCodecCtx);
1456
        free(AudioPkt.data);
1457
        free(VideoPkt.data);
1458
        free(outbuf_audio);
1459
        finalizeChunkPuller(daemon);
1460
        free(tval);
1461
        free(initRect);
1462
        return 0;
1463
}
1464

    
1465
int enqueueBlock(const uint8_t *block, const int block_size) {
1466
        Chunk *gchunk = NULL;
1467
        ExternalChunk *echunk = NULL;
1468
        int decoded_size = -1;
1469
        uint8_t *tempdata, *buffer;
1470
        int i, j;
1471
        Frame *frame = NULL;
1472
        AVPacket packet, packetaudio;
1473

    
1474
        uint16_t *audio_bufQ = NULL;
1475
        int16_t *dataQ = NULL;
1476
        int data_sizeQ;
1477
        int lenQ;
1478

    
1479
        //the frame.h gets encoded into 5 slots of 32bits (3 ints plus 2 more for the timeval struct
1480
        static int sizeFrameHeader = 5*sizeof(int32_t);
1481
        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;
1482

    
1483
        audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1484
        if(!audio_bufQ) {
1485
                printf("Memory error in audio_bufQ!\n");
1486
                return PLAYER_FAIL_RETURN;
1487
        }
1488

    
1489
        gchunk = (Chunk *)malloc(sizeof(Chunk));
1490
        if(!gchunk) {
1491
                printf("Memory error in gchunk!\n");
1492
                av_free(audio_bufQ);
1493
                return PLAYER_FAIL_RETURN;
1494
        }
1495

    
1496
        decoded_size = decodeChunk(gchunk, block, block_size);
1497
#ifdef DEBUG_CHUNKER
1498
        printf("CHUNKER: enqueueBlock: decoded_size %d target size %d\n", decoded_size, GRAPES_ENCODED_CHUNK_HEADER_SIZE + ExternalChunk_header_size + gchunk->size);
1499
#endif
1500
  if(decoded_size < 0 || decoded_size != GRAPES_ENCODED_CHUNK_HEADER_SIZE + ExternalChunk_header_size + gchunk->size) {
1501
                //HINT here i should differentiate between various return values of the decode
1502
                //in order to free what has been allocated there
1503
                printf("chunk probably corrupted!\n");
1504
                av_free(audio_bufQ);
1505
                free(gchunk);
1506
                return PLAYER_FAIL_RETURN;
1507
        }
1508

    
1509
        echunk = grapesChunkToExternalChunk(gchunk);
1510
        if(echunk == NULL) {
1511
                printf("Memory error in echunk!\n");
1512
                free(gchunk->attributes);
1513
                free(gchunk->data);
1514
                free(gchunk);
1515
                return PLAYER_FAIL_RETURN;
1516
        }
1517
        free(gchunk->attributes);
1518
        free(gchunk);
1519

    
1520
        frame = (Frame *)malloc(sizeof(Frame));
1521
        if(!frame) {
1522
                printf("Memory error in Frame!\n");
1523
                if(gchunk->attributes)
1524
                        free(gchunk->attributes);
1525
                if(echunk->data)
1526
                        free(echunk->data);
1527
                if(echunk)
1528
                        free(echunk);
1529
                av_free(audio_bufQ);
1530
                return PLAYER_FAIL_RETURN;
1531
        }
1532

    
1533
        tempdata = echunk->data; //let it point to first frame of payload
1534
        j=echunk->payload_len;
1535
        while(j>0 && !quit) {
1536
                frame->number = bit32_encoded_pull(tempdata);
1537
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1538
                frame->timestamp.tv_sec = bit32_encoded_pull(tempdata);
1539
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1540
                frame->timestamp.tv_usec = bit32_encoded_pull(tempdata);
1541
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1542
                frame->size = bit32_encoded_pull(tempdata);
1543
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1544
                frame->type = bit32_encoded_pull(tempdata);
1545
                tempdata += CHUNK_TRANSCODING_INT_SIZE;
1546

    
1547
                buffer = tempdata; // here coded frame information
1548
                tempdata += frame->size; //let it point to the next frame
1549

    
1550
                if(frame->type < 5) { // video frame
1551
                        av_init_packet(&packet);
1552
                        packet.data = buffer;//video_bufQ;
1553
                        packet.size = frame->size;
1554
                        packet.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1555
                        packet.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1556
                        packet.stream_index = frame->number; // use of stream_index for number frame
1557
                        //packet.duration = frame->timestamp.tv_sec;
1558
                        if(packet.size > 0)
1559
                                packet_queue_put(&videoq, &packet); //the _put makes a copy of the packet
1560

    
1561
#ifdef DEBUG_SOURCE
1562
                        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);
1563
#endif
1564
                }
1565
                else if(frame->type == 5) { // audio frame
1566
                        av_init_packet(&packetaudio);
1567
                        packetaudio.data = buffer;
1568
                        packetaudio.size = frame->size;
1569
                        packetaudio.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1570
                        packetaudio.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec;
1571
                        //packetaudio.duration = frame->timestamp.tv_sec;
1572
                        packetaudio.stream_index = frame->number; // use of stream_index for number frame
1573
                        packetaudio.flags = 1;
1574
                        packetaudio.pos = -1;
1575

    
1576
                        //instead of -1, in order to signal it is not decoded yet
1577
                        packetaudio.convergence_duration = 0;
1578

    
1579
                        // insert the audio frame into the queue
1580
                        if(packetaudio.size > 0)
1581
                                packet_queue_put(&audioq, &packetaudio);//makes a copy of the packet so i can free here
1582

    
1583
#ifdef DEBUG_SOURCE
1584
                        printf("SOURCE: Insert audio in queue pts=%lld sindex:%d\n", packetaudio.pts, packetaudio.stream_index);
1585
#endif
1586
                }
1587
                else {
1588
                        printf("SOURCE: Unknown frame type %d. Size %d\n", frame->type, frame->size);
1589
                }
1590
                if(frame->size > 0)
1591
                        j = j - sizeFrameHeader - frame->size;
1592
                else {
1593
                        printf("SOURCE: Corrupt frames (size %d) in chunk. Skipping it...\n", frame->size);
1594
                        j = -1;
1595
                }
1596
        }
1597
        //chunk ingestion terminated!
1598
        if(echunk->data)
1599
                free(echunk->data);
1600
        if(echunk)
1601
                free(echunk);
1602
        if(frame)
1603
                free(frame);
1604
        if(audio_bufQ)
1605
                av_free(audio_bufQ);
1606
}
1607

    
1608
/* From SDL documentation. */
1609
SDL_Cursor *init_system_cursor(const char *image[])
1610
{
1611
        int i, row, col;
1612
        Uint8 data[4*32];
1613
        Uint8 mask[4*32];
1614
        int hot_x, hot_y;
1615

    
1616
        i = -1;
1617
        for ( row=0; row<32; ++row ) {
1618
                for ( col=0; col<32; ++col ) {
1619
                        if ( col % 8 ) {
1620
                                data[i] <<= 1;
1621
                                mask[i] <<= 1;
1622
                        } else {
1623
                                ++i;
1624
                                data[i] = mask[i] = 0;
1625
                        }
1626
                        
1627
                        switch (image[4+row][col]) {
1628
                                case ' ':
1629
                                        data[i] |= 0x01;
1630
                                        mask[i] |= 0x01;
1631
                                        break;
1632
                                case '.':
1633
                                        mask[i] |= 0x01;
1634
                                        break;
1635
                                case 'X':
1636
                                        break;
1637
                        }
1638
                }
1639
        }
1640
        
1641
        sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
1642
        return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
1643
}
1644

    
1645
void refresh_fullscreen_button(int hover)
1646
{
1647
        if(!hover)
1648
        {
1649
                if(!fullscreen)
1650
                {
1651
                        SDL_BlitSurface(fullscreenIcon, NULL, screen, &fullscreenIconBox);
1652
                        SDL_UpdateRects(screen, 1, &fullscreenIconBox);
1653
                }
1654
                else
1655
                {
1656
                        SDL_BlitSurface(nofullscreenIcon, NULL, screen, &fullscreenIconBox);
1657
                        SDL_UpdateRects(screen, 1, &fullscreenIconBox);
1658
                }
1659
        }
1660
        else
1661
        {
1662
                if(!fullscreen)
1663
                {
1664
                        SDL_BlitSurface(fullscreenHoverIcon, NULL, screen, &fullscreenIconBox);
1665
                        SDL_UpdateRects(screen, 1, &fullscreenIconBox);
1666
                }
1667
                else
1668
                {
1669
                        SDL_BlitSurface(nofullscreenHoverIcon, NULL, screen, &fullscreenIconBox);
1670
                        SDL_UpdateRects(screen, 1, &fullscreenIconBox);
1671
                }
1672
        }
1673
}
1674

    
1675
void aspect_ratio_resize(float aspect_ratio, int width, int height, int* out_width, int* out_height)
1676
{
1677
        int h,w,x,y;
1678
        h = (int)((float)width/aspect_ratio);
1679
        if(h<=height)
1680
        {
1681
                w = width;
1682
        }
1683
        else
1684
        {
1685
                w = (int)((float)height*aspect_ratio);
1686
                h = height;
1687
        }
1688
        *out_width = w;
1689
        *out_height = h;
1690
}
1691

    
1692
void toggle_fullscreen()
1693
{
1694
        //If the screen is windowed
1695
        if( !fullscreen )
1696
        {
1697
                //Set the screen to fullscreen
1698
#ifndef __DARWIN__
1699
                // screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 0, SDL_SWSURFACE | SDL_RESIZABLE | SDL_FULLSCREEN);
1700
                screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 0, SDL_SWSURFACE | SDL_NOFRAME | SDL_FULLSCREEN);
1701
#else
1702
                // screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 24, SDL_SWSURFACE | SDL_RESIZABLE | SDL_FULLSCREEN);
1703
                screen = SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 24, SDL_SWSURFACE | SDL_NOFRAME | SDL_FULLSCREEN);
1704
#endif
1705

    
1706
                //If there's an error
1707
                if( screen == NULL )
1708
                {
1709
                        fprintf(stderr, "SDL_SetVideoMode returned null: could not toggle fullscreen mode - exiting\n");
1710
                        exit(1);
1711
                }
1712
                
1713
                aspect_ratio_rect(ratio, FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT - BUTTONS_LAYER_OFFSET - fullscreenIconBox.h);
1714
                fullscreenIconBox.x = (FULLSCREEN_WIDTH - fullscreenIcon->w) / 2;
1715
                // fullscreenIcon.y = rect.y+rect.h + (BUTTONS_LAYER_OFFSET/2); // put the button just below the video overlay
1716
                fullscreenIconBox.y = FULLSCREEN_HEIGHT - fullscreenIconBox.h - (BUTTONS_LAYER_OFFSET/2); // put the button at the bottom edge of the screen
1717
                
1718
                //Set the window state flag
1719
                fullscreen = 1;
1720
        }
1721
        
1722
        //If the screen is fullscreen
1723
        else
1724
        {
1725
                //Window the screen
1726
#ifndef __DARWIN__
1727
                screen = SDL_SetVideoMode(window_width, window_height, 0, SDL_SWSURFACE | SDL_RESIZABLE);
1728
#else
1729
                screen = SDL_SetVideoMode(window_width, window_height, 24, SDL_SWSURFACE | SDL_RESIZABLE);
1730
#endif
1731
                
1732
                //If there's an error
1733
                if( screen == NULL )
1734
                {
1735
                        fprintf(stderr, "SDL_SetVideoMode returned null: could not toggle fullscreen mode - exiting\n");
1736
                        exit(1);
1737
                }
1738
                
1739
                aspect_ratio_rect(ratio, window_width, window_height - BUTTONS_LAYER_OFFSET - fullscreenIconBox.h);
1740
                fullscreenIconBox.x = (window_width - fullscreenIcon->w) / 2;
1741
                // fullscreenIcon.y = rect.y+rect.h + (BUTTONS_LAYER_OFFSET/2); // put the button just below the video overlay
1742
                fullscreenIconBox.y = window_height - fullscreenIconBox.h - (BUTTONS_LAYER_OFFSET/2); // put the button at the bottom edge of the screen
1743
                
1744
                //Set the window state flag
1745
                fullscreen = 0;
1746
        }
1747
}