Revision 10c75ef7

View differences:

chunker_player/Makefile
45 45

  
46 46
all: chunker_player
47 47

  
48
chunker_player: ../chunk_transcoding/external_chunk_transcoding.o	chunk_puller.o chunker_player.o
48
chunker_player: ../chunk_transcoding/external_chunk_transcoding.o chunk_puller.o chunker_player.o player_core.o player_gui.o
49 49

  
50 50
clean:
51 51
	rm -f chunker_player
chunker_player/channels.conf
1 1
ExecPath = "/home/carmelo/napa/napawine-software/trunk/Applications/OfferStreamer/"
2
ExecName = "offerstreamer-ml-monl-http"
2
ExecName = "offerstreamer-ml-monl-http-debug"
3 3

  
4 4
Channel RaiStoria_CT
5 5
{
6
	LaunchString = "-i 151.97.8.10 -p 6051 -P 8888 -C RaiStoria_CT"
6
#	LaunchString = "-i 151.97.8.10 -p 6051 -P 10002 -C RaiStoria_CT"
7
	LaunchString = "-i 151.97.8.10 -p 6051 -C RaiStoria_CT"
7 8
	AudioChannels = 2
8 9
	SampleRate = 48000
9 10
	Width = 704
......
13 14

  
14 15
Channel BBCChannel_TO
15 16
{
16
	LaunchString = "-i 130.192.86.31 -p 6666 -P 8888 -C BBCChannel_TO"
17
	LaunchString = "-i 130.192.86.31 -p 6666 -C BBCChannel_TO"
17 18
	AudioChannels = 2
18 19
	SampleRate = 48000
19 20
	Width = 704
chunker_player/chunker_player.c
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_ttf.h>
27
#include <SDL_image.h>
28
#include <SDL_video.h>
29
#include <math.h>
30
#include <confuse.h>
31
#include <assert.h>
32

  
33
#ifdef __MINGW32__
34
#undef main /* Prevents SDL from overriding main() */
35
#endif
36

  
37
#include "http_default_urls.h"
38
#include "chunker_player.h"
39
#include "codec_definitions.h"
40

  
41
#ifdef __WIN32__
42
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "taskkill /pid %d /F", pid); system(command_name);}
43
#define KILLALL(pname) {char command_name[255]; sprintf(command_name, "taskkill /im %s /F", pname); system(command_name);}
44
#endif
45
#ifdef __LINUX__
46
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "kill %d", pid); system(command_name);}
47
#define KILLALL(pname) {char command_name[255]; sprintf(command_name, "killall %s -9", pname); system(command_name);}
48
#endif
49
#ifdef __MACOS__
50
#define KILL_PROCESS(pid) {char command_name[255]; sprintf(command_name, "kill %d", pid); system(command_name);}
51
#define KILLALL(pname) {char command_name[255]; sprintf(command_name, "killall %s -9", pname); system(command_name);}
52
#endif
53

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

  
76
void packet_queue_reset(PacketQueue *q, short int Type) {
77
	AVPacketList *tmp,*tmp1;
78
#ifdef DEBUG_QUEUE
79
	printf("QUEUE: RESET BEGIN: NPackets=%d Type=%d LastExtr=%d\n", q->nb_packets, q->queueType, q->last_frame_extracted);
80
#endif
81
	SDL_LockMutex(q->mutex);
82

  
83
	tmp = q->first_pkt;
84
	while(tmp) {
85
		tmp1 = tmp;
86
		tmp = tmp->next;
87
		av_free_packet(&(tmp1->pkt));
88
		av_free(tmp1);
89
#ifdef DEBUG_QUEUE
90
		printf("F ");
91
#endif
92
	}
93
#ifdef DEBUG_QUEUE
94
	printf("\n");
95
#endif
96

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

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

  
133
	if(!pkt1) {
134
		av_free_packet(pkt);
135
		return -1;
136
	}
137
	pkt1->pkt = *pkt;
138
	pkt1->next = NULL;
139

  
140
	SDL_LockMutex(q->mutex);
141

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

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

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

  
211

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

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

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

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

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

  
295
void update_queue_stats(PacketQueue *q, int packet_index)
296
{
297
	static int N = 50;
298
	
299
	assert(q != NULL);
300
	assert(q->last_pkt != NULL);
301
	assert(q->first_pkt != NULL);
302
	
303
	if(q->last_pkt->pkt.stream_index > q->first_pkt->pkt.stream_index)
304
		q->density = (double)q->nb_packets / (double)(q->last_pkt->pkt.stream_index - q->first_pkt->pkt.stream_index) * 100.0;
305
	
306
#ifdef DEBUG_STATS
307
	if(q->queueType == AUDIO)
308
		printf("STATS: AUDIO QUEUE DENSITY percentage %f\n", q->density);
309
	if(q->queueType == VIDEO)
310
		printf("STATS: VIDEO QUEUE DENSITY percentage %f\n", q->density);
311
#endif
312
	
313
	if(packet_index != -1)
314
	{
315
		double percentage = 0.0;	
316
		//compute lost frame statistics
317
		if(q->last_frame_extracted > 0 && packet_index > q->last_frame_extracted)
318
		{
319
			int lost_frames = packet_index - q->last_frame_extracted - 1;
320
			q->total_lost_frames += lost_frames ;
321
			percentage = (double)q->total_lost_frames / (double)q->last_frame_extracted * 100.0;
322
			
323
			q->loss_history[q->history_index] = lost_frames;
324
			q->history_index = (q->history_index+1)%N;
325
			
326
			int i;
327
			q->instant_lost_frames = 0;
328
			for(i=0; i<N; i++)
329
				q->instant_lost_frames += q->loss_history[i];
330
			
331
#ifdef DEBUG_STATS
332
			if(q->queueType == AUDIO)
333
				printf("STATS: AUDIO FRAMES LOST: instant %d, total %d, total percentage %f\n", q->instant_lost_frames, q->total_lost_frames, percentage);
334
			else if(q->queueType == VIDEO)
335
				printf("STATS: VIDEO FRAMES LOST: instant %d, total %d, total percentage %f\n", q->instant_lost_frames, q->total_lost_frames, percentage);
336
#endif
337
		}
338
	}
339
}
340

  
341
int packet_queue_get(PacketQueue *q, AVPacket *pkt, short int av) {
342
	//AVPacket tmp;
343
	AVPacketList *pkt1 = NULL;
344
	int ret=-1;
345
	int SizeToCopy=0;
346

  
347
	SDL_LockMutex(q->mutex);
348

  
349
#ifdef DEBUG_QUEUE
350
	printf("QUEUE: Get NPackets=%d Type=%d\n", q->nb_packets, q->queueType);
351
#endif
352

  
353
	if((q->queueType==AUDIO && QueueFillingMode) || QueueStopped)
354
	{
355
		SDL_UnlockMutex(q->mutex);
356
		return -1;
357
	}
358

  
359
	if(av==1) { //somebody requested an audio packet, q is the audio queue
360
		//try to dequeue the first packet of the audio queue
361
		pkt1 = seek_and_decode_packet_starting_from(q->first_pkt, q);
362
		if(pkt1) { //yes we have them!
363
			if(pkt1->pkt.size-AudioQueueOffset > dimAudioQ) {
364
				//one packet if enough to give us the requested number of bytes by the audio_callback
365
#ifdef DEBUG_QUEUE
366
				printf("  AV=1 and Extract from the same packet\n");
367
#endif
368
				pkt->size = dimAudioQ;
369
				memcpy(pkt->data,pkt1->pkt.data+AudioQueueOffset,dimAudioQ);
370
				pkt->dts = pkt1->pkt.dts;
371
				pkt->pts = pkt1->pkt.pts;
372
				pkt->stream_index = pkt1->pkt.stream_index;//1;
373
				pkt->flags = 1;
374
				pkt->pos = -1;
375
				pkt->convergence_duration = -1;
376
#ifdef DEBUG_QUEUE
377
				printf("   Adjust timestamps Old = %lld New = %lld\n", pkt1->pkt.dts, (int64_t)(pkt1->pkt.dts + deltaAudioQ + deltaAudioQError));
378
#endif
379
				int64_t Olddts=pkt1->pkt.dts;
380
				pkt1->pkt.dts += deltaAudioQ + deltaAudioQError;
381
				pkt1->pkt.pts += deltaAudioQ + deltaAudioQError;
382
				deltaAudioQError=(float)Olddts + deltaAudioQ + deltaAudioQError - (float)pkt1->pkt.dts;
383
				AudioQueueOffset += dimAudioQ;
384
#ifdef DEBUG_QUEUE
385
				printf("   deltaAudioQError = %f\n",deltaAudioQError);
386
#endif
387
				//update overall state of queue
388
				//size is diminished because we played some audio samples
389
				//but packet is not removed since a portion has still to be played
390
				//HINT ERRATA we had a size mismatch since size grows with the
391
				//number of compressed bytes, and diminishes here with the number
392
				//of raw uncompressed bytes, hence we update size during the
393
				//real removes and not here anymore
394
				//q->size -= dimAudioQ;
395
				update_queue_stats(q, pkt->stream_index);
396
				//update index of last frame extracted
397
				q->last_frame_extracted = pkt->stream_index;
398
#ifdef DEBUG_AUDIO_BUFFER
399
				printf("1: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
400
#endif
401
				ret = 1; //OK
402
			}
403
			else {
404
				//we need bytes from two consecutive packets to satisfy the audio_callback
405
#ifdef DEBUG_QUEUE
406
				printf("  AV = 1 and Extract from 2 packets\n");
407
#endif
408
				//check for a valid next packet since we will finish the current packet
409
				//and also take some bytes from the next one
410
				pkt1->next = seek_and_decode_packet_starting_from(pkt1->next, q);
411
				if(pkt1->next) {
412
#ifdef DEBUG_QUEUE
413
					printf("   we have a next...\n");
414
#endif
415
					pkt->size = dimAudioQ;
416
					pkt->dts = pkt1->pkt.dts;
417
					pkt->pts = pkt1->pkt.pts;
418
					pkt->stream_index = pkt1->pkt.stream_index;//1;
419
					pkt->flags = 1;
420
					pkt->pos = -1;
421
					pkt->convergence_duration = -1;
422
					{
423
						SizeToCopy=pkt1->pkt.size-AudioQueueOffset;
424
#ifdef DEBUG_QUEUE
425
						printf("      SizeToCopy=%d\n",SizeToCopy);
426
#endif
427
						memcpy(pkt->data, pkt1->pkt.data+AudioQueueOffset, SizeToCopy);
428
						memcpy(pkt->data+SizeToCopy, pkt1->next->pkt.data, (dimAudioQ-SizeToCopy)*sizeof(uint8_t));
429
					}
430
#ifdef DEBUG_AUDIO_BUFFER
431
					printf("2: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
432
#endif
433
				}
434
#ifdef DEBUG_AUDIO_BUFFER
435
				else {
436
					printf("2: NONEXT\n");
437
				}
438
#endif
439
				//HINT SEE before q->size -= SizeToCopy;
440
				q->first_pkt = remove_from_queue(q, pkt1);
441

  
442
				// Adjust timestamps
443
				pkt1 = q->first_pkt;
444
				if(pkt1) {
445
					int Offset=(dimAudioQ-SizeToCopy)*1000/(spec.freq*2*spec.channels);
446
					int64_t LastDts=pkt1->pkt.dts;
447
					pkt1->pkt.dts += Offset + deltaAudioQError;
448
					pkt1->pkt.pts += Offset + deltaAudioQError;
449
					deltaAudioQError = (float)LastDts + (float)Offset + deltaAudioQError - (float)pkt1->pkt.dts;
450
#ifdef DEBUG_QUEUE
451
					printf("   Adjust timestamps Old = %lld New = %lld\n", LastDts, pkt1->pkt.dts);
452
#endif
453
					AudioQueueOffset = dimAudioQ - SizeToCopy;
454
					//SEE BEFORE HINT q->size -= AudioQueueOffset;
455
					ret = 1;
456
					update_queue_stats(q, pkt->stream_index);
457
				}
458
				else {
459
					AudioQueueOffset=0;
460
#ifdef DEBUG_AUDIO_BUFFER
461
					printf("0: idx %d    \taqo %d    \tstc %d    \taqe %f    \tpsz %d\n", pkt1->pkt.stream_index, AudioQueueOffset, SizeToCopy, deltaAudioQError, pkt1->pkt.size);
462
#endif
463
				}
464
#ifdef DEBUG_QUEUE
465
				printf("   deltaAudioQError = %f\n",deltaAudioQError);
466
#endif
467
				//update index of last frame extracted
468
				q->last_frame_extracted = pkt->stream_index;
469
			}
470
		}
471
	}
472
	else { //somebody requested a video packet, q is the video queue
473
		pkt1 = q->first_pkt;
474
		if(pkt1) {
475
#ifdef DEBUG_QUEUE
476
			printf("  AV not 1\n");
477
#endif
478
			pkt->size = pkt1->pkt.size;
479
			pkt->dts = pkt1->pkt.dts;
480
			pkt->pts = pkt1->pkt.pts;
481
			pkt->stream_index = pkt1->pkt.stream_index;
482
			pkt->flags = pkt1->pkt.flags;
483
			pkt->pos = pkt1->pkt.pos;
484
			pkt->convergence_duration = pkt1->pkt.convergence_duration;
485
			//*pkt = pkt1->pkt;
486
			memcpy(pkt->data, pkt1->pkt.data, pkt1->pkt.size);
487

  
488
			//HINT SEE BEFORE q->size -= pkt1->pkt.size;
489
			q->first_pkt = remove_from_queue(q, pkt1);
490

  
491
			ret = 1;
492
			update_queue_stats(q, pkt->stream_index);
493
			//update index of last frame extracted
494
			q->last_frame_extracted = pkt->stream_index;
495
		}
496
#ifdef DEBUG_QUEUE
497
		else {
498
			printf("  VIDEO pk1 NULL!!!!\n");
499
		}
500
#endif
501
	}
502

  
503
	if(q->nb_packets==0 && q->queueType==AUDIO) {
504
		QueueFillingMode=1;
505
#ifdef DEBUG_QUEUE
506
		printf("QUEUE: Get FillingMode ON\n");
507
#endif
508
	}
509
#ifdef DEBUG_QUEUE
510
	printf("QUEUE: Get LastFrameExtracted = %d\n",q->last_frame_extracted);
511
	printf("QUEUE: Get Tot lost frames = %d\n",q->total_lost_frames);
512
#endif
513

  
514
	SDL_UnlockMutex(q->mutex);
515
	return ret;
516
}
517

  
518

  
519
int audio_decode_frame(uint8_t *audio_buf, int buf_size) {
520
	//struct timeval now;
521
	int audio_pkt_size = 0;
522
	long long Now;
523
	short int DecodeAudio=0, SkipAudio=0;
524
	//int len1, data_size;
525

  
526
	//gettimeofday(&now,NULL);
527
	//Now = (now.tv_sec)*1000+now.tv_usec/1000;
528
	Now=(long long)SDL_GetTicks();
529

  
530
	if(QueueFillingMode || QueueStopped)
531
	{
532
		//SDL_LockMutex(timing_mutex);
533
		FirstTimeAudio=1;
534
		FirstTime = 1;
535
		//SDL_UnlockMutex(timing_mutex);
536
		return -1;
537
	}
538

  
539
	if((FirstTime==1 || FirstTimeAudio==1) && audioq.size>0) {
540
		if(audioq.first_pkt->pkt.pts>0)
541
		{
542
			//SDL_LockMutex(timing_mutex);
543
			DeltaTime=Now-(long long)(audioq.first_pkt->pkt.pts);
544
			FirstTimeAudio = 0;
545
			FirstTime = 0;
546
			//SDL_UnlockMutex(timing_mutex);
547
#ifdef DEBUG_AUDIO 
548
		 	printf("AUDIO: audio_decode_frame - DeltaTimeAudio=%lld\n",DeltaTime);
549
#endif
550
		}
551
	}
552

  
553
#ifdef DEBUG_AUDIO 
554
	if(audioq.first_pkt)
555
	{
556
		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);
557
		printf("AUDIO: QueueLen=%d ",(int)audioq.nb_packets);
558
		printf("AUDIO: QueueSize=%d\n",(int)audioq.size);
559
	}
560
	else
561
		printf("AUDIO: audio_decode_frame - Empty queue\n");
562
#endif
563

  
564

  
565
	if(audioq.nb_packets>0) {
566
		if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
567
			SkipAudio = 1;
568
			DecodeAudio = 0;
569
		}
570
		else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
571
			(long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
572
				SkipAudio = 0;
573
				DecodeAudio = 1;
574
		}
575
	}
576
		
577
	while(SkipAudio==1 && audioq.size>0) {
578
		SkipAudio = 0;
579
#ifdef DEBUG_AUDIO
580
 		printf("AUDIO: skipaudio: queue size=%d\n",audioq.size);
581
#endif
582
		if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
583
			return -1;
584
		}
585
		if(audioq.first_pkt)
586
		{
587
			if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
588
				SkipAudio = 1;
589
				DecodeAudio = 0;
590
			}
591
			else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
592
				(long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
593
					SkipAudio = 0;
594
					DecodeAudio = 1;
595
			}
596
		}
597
	}
598
	if(DecodeAudio==1) {
599
		if(packet_queue_get(&audioq,&AudioPkt,1) < 0) {
600
			return -1;
601
		}
602
		memcpy(audio_buf,AudioPkt.data,AudioPkt.size);
603
		audio_pkt_size = AudioPkt.size;
604
#ifdef DEBUG_AUDIO
605
 		printf("AUDIO: Decode audio\n");
606
#endif
607
	}
608

  
609
	return audio_pkt_size;
610
}
611

  
612

  
613
int video_callback(void *valthread) {
614
	//AVPacket pktvideo;
615
	AVCodecContext  *pCodecCtx;
616
	AVCodec         *pCodec;
617
	AVFrame         *pFrame;
618
	AVPacket        packet;
619
	int frameFinished;
620
	int countexit;
621
	AVPicture pict;
622
	//FILE *frecon;
623
	SDL_Event event;
624
	long long Now;
625
	short int SkipVideo, DecodeVideo;
626

  
627
	//double frame_rate = 0.0,time_between_frames=0.0;
628
	//struct timeval now;
629

  
630
	//int wait_for_sync = 1;
631
	ThreadVal *tval;
632
	tval = (ThreadVal *)valthread;
633

  
634
	//frame_rate = tval->framerate;
635
	//time_between_frames = 1.e6 / frame_rate;
636
	//gettimeofday(&time_now,0);
637

  
638
	//frecon = fopen("recondechunk.mpg","wb");
639

  
640
	pCodecCtx=avcodec_alloc_context();
641
	pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
642
#ifdef H264_VIDEO_ENCODER
643
	pCodecCtx->codec_id  = CODEC_ID_H264;
644
	pCodecCtx->me_range = 16;
645
	pCodecCtx->max_qdiff = 4;
646
	pCodecCtx->qmin = 10;
647
	pCodecCtx->qmax = 51;
648
	pCodecCtx->qcompress = 0.6;
649
#else
650
	pCodecCtx->codec_id  = CODEC_ID_MPEG4;
651
#endif
652
	//pCodecCtx->bit_rate = 400000;
653
	// resolution must be a multiple of two
654
	pCodecCtx->width = tval->width;//176;//352;
655
	pCodecCtx->height = tval->height;//144;//288;
656
	
657
	// frames per second
658
	//pCodecCtx->time_base = (AVRational){1,25};
659
	//pCodecCtx->gop_size = 10; // emit one intra frame every ten frames
660
	//pCodecCtx->max_b_frames=1;
661
	pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
662
	pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
663

  
664
	if(pCodec==NULL) {
665
		fprintf(stderr, "Unsupported codec!\n");
666
		return -1; // Codec not found
667
	}
668
	if(avcodec_open(pCodecCtx, pCodec) < 0) {
669
		fprintf(stderr, "could not open codec\n");
670
		return -1; // Could not open codec
671
	}
672
	pFrame=avcodec_alloc_frame();
673
	if(pFrame==NULL) {
674
		printf("Memory error!!!\n");
675
		return -1;
676
	}
677
	
678
#ifdef DEBUG_VIDEO
679
 	printf("VIDEO: video_callback entering main cycle\n");
680
#endif
681
	while(AVPlaying && !quit) {
682
		if(QueueFillingMode || QueueStopped)
683
		{
684
			//SDL_LockMutex(timing_mutex);
685
			FirstTime = 1;
686
			//SDL_UnlockMutex(timing_mutex);
687
			usleep(5000);
688
			continue;
689
		}
690

  
691
		DecodeVideo = 0;
692
		SkipVideo = 0;
693
		Now=(long long)SDL_GetTicks();
694
		if(FirstTime==1 && videoq.size>0) {
695
			if(videoq.first_pkt->pkt.pts>0)
696
			{
697
				//SDL_LockMutex(timing_mutex);
698
				DeltaTime=Now-(long long)videoq.first_pkt->pkt.pts;
699
				FirstTime = 0;
700
				//SDL_UnlockMutex(timing_mutex);
701
			}
702
#ifdef DEBUG_VIDEO 
703
		 	printf("VIDEO: VideoCallback - DeltaTimeAudio=%lld\n",DeltaTime);
704
#endif
705
		}
706

  
707
#ifdef DEBUG_VIDEO 
708
		if(videoq.first_pkt)
709
		{
710
			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);
711
			printf("VIDEO: Index=%d ", (int)videoq.first_pkt->pkt.stream_index);
712
			printf("VIDEO: QueueLen=%d ", (int)videoq.nb_packets);
713
			printf("VIDEO: QueueSize=%d\n", (int)videoq.size);
714
		}
715
		else
716
			printf("VIDEO: VideoCallback - Empty queue\n");
717
#endif
718

  
719
		if(videoq.nb_packets>0) {
720
			if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)<Now-(long long)MAX_TOLLERANCE) {
721
				SkipVideo = 1;
722
				DecodeVideo = 0;
723
			}
724
			else 
725
				if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)>=Now-(long long)MAX_TOLLERANCE &&
726
				   ((long long)videoq.first_pkt->pkt.pts+DeltaTime)<=Now+(long long)MAX_TOLLERANCE) {
727
					SkipVideo = 0;
728
					DecodeVideo = 1;
729
				}
730
		}
731
#ifdef DEBUG_VIDEO
732
		printf("VIDEO: skipvideo:%d decodevideo:%d\n",SkipVideo,DecodeVideo);
733
#endif
734

  
735
		while(SkipVideo==1 && videoq.size>0) {
736
			SkipVideo = 0;
737
#ifdef DEBUG_VIDEO 
738
 			printf("VIDEO: Skip Video\n");
739
#endif
740
			if(packet_queue_get(&videoq,&VideoPkt,0) < 0) {
741
				break;
742
			}
743
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
744
			if(videoq.first_pkt)
745
			{
746
				if((long long)videoq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) {
747
					SkipVideo = 1;
748
					DecodeVideo = 0;
749
				}
750
				else if((long long)videoq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE &&
751
								(long long)videoq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) {
752
					SkipVideo = 0;
753
					DecodeVideo = 1;
754
				}
755
			}
756
		}
757
		
758
		if(DecodeVideo==1) {
759
			if(packet_queue_get(&videoq,&VideoPkt,0) > 0) {
760

  
761
#ifdef DEBUG_VIDEO
762
				printf("VIDEO: Decode video FrameTime=%lld Now=%lld\n",(long long)VideoPkt.pts+DeltaTime,Now);
763
#endif
764

  
765
				avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt);
766

  
767
				if(frameFinished) { // it must be true all the time else error
768
#ifdef DEBUG_VIDEO
769
					printf("VIDEO: FrameFinished\n");
770
#endif
771
					if(SaveYUV)
772
						SaveFrame(pFrame, pCodecCtx->width, pCodecCtx->height);
773
					//fwrite(pktvideo.data, 1, pktvideo.size, frecon);
774

  
775
					if(silentMode)
776
						continue;
777

  
778
					// Lock SDL_yuv_overlay
779
					if(SDL_MUSTLOCK(screen)) {
780
						if(SDL_LockSurface(screen) < 0) {
781
							continue;
782
						}
783
					}
784

  
785
					if(SDL_LockYUVOverlay(yuv_overlay) < 0) {
786
						if(SDL_MUSTLOCK(screen)) {
787
							SDL_UnlockSurface(screen);
788
						}
789
						continue;
790
					}
791
					
792
					pict.data[0] = yuv_overlay->pixels[0];
793
					pict.data[1] = yuv_overlay->pixels[2];
794
					pict.data[2] = yuv_overlay->pixels[1];
795

  
796
					pict.linesize[0] = yuv_overlay->pitches[0];
797
					pict.linesize[1] = yuv_overlay->pitches[2];
798
					pict.linesize[2] = yuv_overlay->pitches[1];
799

  
800
					if(img_convert_ctx == NULL) {
801
						img_convert_ctx = sws_getContext(tval->width, tval->height, PIX_FMT_YUV420P, initRect->w, initRect->h, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
802
						if(img_convert_ctx == NULL) {
803
							fprintf(stderr, "Cannot initialize the conversion context!\n");
804
							exit(1);
805
						}
806
					}
807
					// let's draw the data (*yuv[3]) on a SDL screen (*screen)
808
					sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, tval->height, pict.data, pict.linesize);
809
					SDL_UnlockYUVOverlay(yuv_overlay);
810
					// Show, baby, show!
811
					SDL_LockMutex(RedrawMutex);
812
					SDL_DisplayYUVOverlay(yuv_overlay, &rect);
813
					SDL_UnlockMutex(RedrawMutex);
814

  
815
					//redisplay logo
816
					/**SDL_BlitSurface(image, NULL, screen, &dest);*/
817
					/* Update the screen area just changed */
818
					/**SDL_UpdateRects(screen, 1, &dest);*/
819

  
820
					if(SDL_MUSTLOCK(screen)) {
821
						SDL_UnlockSurface(screen);
822
					}
823
				} //if FrameFinished
824
			} // if packet_queue_get
825
		} //if DecodeVideo=1
826

  
827
		usleep(5000);
828
	}
829
	
830
	av_free(pCodecCtx);
831
	//fclose(frecon);
832
#ifdef DEBUG_VIDEO
833
 	printf("VIDEO: video callback end\n");
834
#endif
835
	return 1;
836
}
837

  
838
/**
839
 * Updates the overlay surface size, mantaining the aspect ratio
840
 */
841
void UpdateOverlaySize(float aspect_ratio, int width, int height)
842
{
843
	height -= (BUTTONS_LAYER_OFFSET + BUTTONS_CONTAINER_HEIGHT);
844
	int h = 0, w = 0, x, y;
845
	aspect_ratio_resize(aspect_ratio, width, height, &w, &h);
846
	x = (width - w) / 2;
847
	y = (height - h) / 2;
848
	rect.x = x;
849
	rect.y = y;
850
	rect.w = w;
851
	rect.h = h;
852
}
853

  
854
void audio_callback(void *userdata, Uint8 *stream, int len) {
855

  
856
	//AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
857
	int audio_size;
858

  
859
	static uint8_t audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
860

  
861
	audio_size = audio_decode_frame(audio_buf, sizeof(audio_buf));
862
	if(audio_size != len) {
863
		memset(stream, 0, len);
864
	} else {
865
		memcpy(stream, (uint8_t *)audio_buf, len);
866
	}
867
}
868

  
869
void SetupGUI()
870
{
871
	//Initialize SDL_ttf 
872
	if( TTF_Init() == -1 )
873
	{
874
		printf("TTF_Init: Failed to init SDL_ttf library!\n");
875
		printf("TTF_Init: %s\n", TTF_GetError());
876
		exit(1);
877
	}
878
	
879
	//Open the font
880
	MainFont = TTF_OpenFont(MAIN_FONT_FILE , MAIN_FONT_SIZE );
881
	
882
	//If there was an error in loading the font
883
	if( MainFont == NULL )
884
	{
885
		printf("Cannot initialize GUI, %s file not found\n", MAIN_FONT_FILE);
886
		exit(1);
887
	}
888
	
889
	// init SDL_image
890
	int flags=IMG_INIT_JPG|IMG_INIT_PNG;
891
	int initted=IMG_Init(flags);
892
	if(initted&flags != flags)
893
	{
894
		printf("IMG_Init: Failed to init required jpg and png support!\n");
895
		printf("IMG_Init: %s\n", IMG_GetError());
896
		exit(1);
897
	}
898
	
899
	SDL_VideoInfo* InitialVideoInfo = SDL_GetVideoInfo();
900
	FullscreenWidth = InitialVideoInfo->current_w;
901
	FullscreenHeight = InitialVideoInfo->current_h;
902

  
903
	SDL_Surface *temp;
904
	int screen_w = 0, screen_h = 0;
905

  
906
	if(rect.w > BUTTONS_CONTAINER_WIDTH)
907
		screen_w = rect.w;
908
	else
909
		screen_w = BUTTONS_CONTAINER_WIDTH;
910
	screen_h = rect.h + BUTTONS_CONTAINER_HEIGHT + BUTTONS_LAYER_OFFSET;
911

  
912
	SDL_WM_SetCaption("Filling buffer...", NULL);
913
	// Make a screen to put our video
914
#ifndef __DARWIN__
915
	screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
916
#else
917
	screen = SDL_SetVideoMode(screen_w, screen_h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
918
#endif
919
	if(!screen) {
920
		fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
921
		exit(1);
922
	}
923
	
924
	window_width = screen_w;
925
	window_height = screen_h;
926
	
927
	/** Setting up cursors */
928
	defaultCursor = SDL_GetCursor();
929
	handCursor = init_system_cursor(handXPM);
930
	
931
	/** Init Buttons */
932
	int i;
933
	for(i=0; i<NBUTTONS; i++)
934
	{
935
		SButton* tmp = &(Buttons[i]);
936
		tmp->Hover = 0;
937
		tmp->ToggledButton = NULL;
938
		tmp->Visible = 1;
939
		tmp->HoverCallback = NULL;
940
		tmp->LButtonUpCallback = NULL;
941
	}
942
	
943
	/** Loading icons */
944
	
945
	// fullscreen
946
	temp = IMG_Load(FULLSCREEN_ICON_FILE);
947
	if (temp == NULL) {
948
		fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_ICON_FILE, SDL_GetError());
949
		exit(1);
950
	}
951
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
952
	if(Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon == NULL)
953
	{
954
		printf("ERROR in SDL_DisplayFormatAlpha, cannot load fullscreen button, error message: '%s'\n", SDL_GetError());
955
		exit(1);
956
	}
957
	SDL_FreeSurface(temp);
958
	
959
	// fullscreen hover
960
	temp = IMG_Load(FULLSCREEN_HOVER_ICON_FILE);
961
	if (temp == NULL) {
962
		fprintf(stderr, "Error loading %s: %s\n", FULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
963
		exit(1);
964
	}
965
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
966
	SDL_FreeSurface(temp);
967

  
968
	// no fullscreen
969
	temp = IMG_Load(NOFULLSCREEN_ICON_FILE);
970
	if (temp == NULL) {
971
		fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_ICON_FILE, SDL_GetError());
972
		exit(1);
973
	}
974
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
975
	SDL_FreeSurface(temp);
976

  
977
	// no fullscreen hover
978
	temp = IMG_Load(NOFULLSCREEN_HOVER_ICON_FILE);
979
	if (temp == NULL) {
980
		fprintf(stderr, "Error loading %s: %s\n", NOFULLSCREEN_HOVER_ICON_FILE, SDL_GetError());
981
		exit(1);
982
	}
983
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
984
	SDL_FreeSurface(temp);
985
	
986
	// channel up
987
	temp = IMG_Load(CHANNEL_UP_ICON_FILE);
988
	if (temp == NULL) {
989
		fprintf(stderr, "Error loading %s: %s\n", CHANNEL_UP_ICON_FILE, SDL_GetError());
990
		exit(1);
991
	}
992
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
993
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
994
	SDL_FreeSurface(temp);
995
	
996
	// channel down
997
	temp = IMG_Load(CHANNEL_DOWN_ICON_FILE);
998
	if (temp == NULL) {
999
		fprintf(stderr, "Error loading %s: %s\n", CHANNEL_DOWN_ICON_FILE, SDL_GetError());
1000
		exit(1);
1001
	}
1002
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon = SDL_DisplayFormatAlpha(temp);
1003
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonHoverIcon = SDL_DisplayFormatAlpha(temp);
1004
	SDL_FreeSurface(temp);
1005

  
1006
	/** Setting up icon boxes */
1007
	Buttons[FULLSCREEN_BUTTON_INDEX].XOffset = Buttons[NO_FULLSCREEN_BUTTON_INDEX].XOffset = 20;
1008
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.x = 20;
1009
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.w = Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon->w;
1010
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h = Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIcon->h;
1011
	Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1012
	
1013
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.x = 20;
1014
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.w = Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon->w;
1015
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h = Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIcon->h;
1016
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[NO_FULLSCREEN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1017
	
1018
	Buttons[CHANNEL_UP_BUTTON_INDEX].XOffset = -61;
1019
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.w = Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon->w;
1020
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.h = Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIcon->h;
1021
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.x = (screen_w + Buttons[CHANNEL_UP_BUTTON_INDEX].XOffset);
1022
	Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[CHANNEL_UP_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1023
	
1024
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].XOffset = -36;
1025
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.w = Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon->w;
1026
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.h = Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIcon->h;
1027
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.x = (screen_w + Buttons[CHANNEL_DOWN_BUTTON_INDEX].XOffset);
1028
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.y = screen_h - Buttons[CHANNEL_DOWN_BUTTON_INDEX].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1029
	
1030
	/** Setting up buttons events */
1031
	Buttons[FULLSCREEN_BUTTON_INDEX].ToggledButton = &(Buttons[NO_FULLSCREEN_BUTTON_INDEX]);
1032
	Buttons[FULLSCREEN_BUTTON_INDEX].LButtonUpCallback = &toggle_fullscreen;
1033
	Buttons[NO_FULLSCREEN_BUTTON_INDEX].LButtonUpCallback = &toggle_fullscreen;
1034
	Buttons[CHANNEL_UP_BUTTON_INDEX].LButtonUpCallback = &zap_up;
1035
	Buttons[CHANNEL_DOWN_BUTTON_INDEX].LButtonUpCallback = &zap_down;
1036

  
1037
	//create video overlay for display of video frames
1038
	yuv_overlay = SDL_CreateYUVOverlay(rect.w, rect.h, SDL_YV12_OVERLAY, screen);
1039
	if ( yuv_overlay == NULL ) {
1040
		fprintf(stderr,"SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError());
1041
		exit(1);
1042
	}
1043

  
1044
	if ( yuv_overlay->hw_overlay )
1045
		fprintf(stderr,"SDL: Using hardware overlay.\n");
1046
	rect.x = (screen_w - rect.w) / 2;
1047
	SDL_DisplayYUVOverlay(yuv_overlay, &rect);
1048
	redraw_buttons();
1049
	redraw_channel_name();
1050
}
1051

  
1052
void SaveFrame(AVFrame *pFrame, int width, int height) {
1053
	FILE *pFile;
1054
	int  y;
1055
  
1056
	 // Open file
1057
	pFile=fopen(YUVFileName, "ab");
1058
	if(pFile==NULL)
1059
		return;
1060
  
1061
	// Write header
1062
	//fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1063
  
1064
	// Write Y data
1065
	for(y=0; y<height; y++)
1066
  		fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile);
1067
	// Write U data
1068
	for(y=0; y<height/2; y++)
1069
  		fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile);
1070
	// Write V data
1071
	for(y=0; y<height/2; y++)
1072
  		fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile);
1073
  
1074
	// Close file
1075
	fclose(pFile);
1076
}
1077

  
1078
void sigint_handler (int signal) {
1079
	printf("Caught SIGINT, exiting...");
1080
	got_sigint = 1;
1081
}
1082

  
1083
void ProcessKeys() {
1084
	static Uint32 LastTime=0;
1085
	static int LastKey=-1;
1086

  
1087
	Uint32 Now=SDL_GetTicks();
1088
	Uint8* keystate=SDL_GetKeyState(NULL);
1089
	/*if(keystate[SDLK_SPACE] &&
1090
	  (LastKey!=SDLK_SPACE || (LastKey==SDLK_SPACE && (Now-LastTime>1000))))
1091
	{
1092
		LastKey=SDLK_SPACE;
1093
		LastTime=Now;
1094
		QueueStopped=!QueueStopped;
1095
		if(QueueStopped) CurrStatus = PAUSED;
1096
		else CurrStatus = RUNNING;
1097
		// refresh_fullscreen_button(0);
1098
	}*/
1099
	if(keystate[SDLK_ESCAPE] &&
1100
	  (LastKey!=SDLK_ESCAPE || (LastKey==SDLK_ESCAPE && (Now-LastTime>1000))))
1101
	{
1102
		LastKey=SDLK_ESCAPE;
1103
		LastTime=Now;
1104
		quit=1;
1105
	}
1106
	/*if(keystate[SDLK_f] &&
1107
	  (LastKey!=SDLK_f || (LastKey==SDLK_f && (Now-LastTime>1000))))
1108
	{
1109
		LastKey=SDLK_f;
1110
		LastTime=Now;
1111
		SDL_WM_ToggleFullScreen(NULL);
1112
	}*/
1113
}
1
#include <stdio.h>
2
#include <unistd.h>
3
#include <SDL.h>
4
#include <SDL_mutex.h>
5
#include "player_defines.h"
6
#include <confuse.h>
7
#include "http_default_urls.h"
8
#include "codec_definitions.h"
9
#include "player_defines.h"
10
#include "chunker_player.h"
11
#include "player_gui.h"
1114 12

  
1115
int main(int argc, char *argv[]) {
1116
	int i, j, videoStream, outbuf_size, out_size, out_size_audio, seq_current_chunk = 0, audioStream;
1117
	int len1, data_size, stime, cont=0;
1118
	int frameFinished, len_audio;
1119
	int numBytes, outbuf_audio_size, audio_size;
13
int main(int argc, char *argv[])
14
{
15
	// some initializations
16
	SilentMode = 0;
17
	queue_filling_threshold = 0;
18
	SaveYUV = 0;
19
	quit = 0;
20
	QueueFillingMode=1;
21
	P2PProcessID = -1;
22
	NChannels = 0;
23
	SelectedChannel = -1;
1120 24
	
1121
	memset((void*)Channels, 0, (255*sizeof(SChannel)));
25
	memset((void*)Channels, 0, (MAX_CHANNELS_NUM*sizeof(SChannel)));
1122 26

  
1123
	int y;
1124
	int httpPort = -1;
27
	HttpPort = -1;
1125 28
	struct MHD_Daemon *daemon = NULL;
1126
	
1127 29
	SDL_Event event;
30
	OverlayMutex = SDL_CreateMutex();
1128 31

  
1129
	char buf[1024],outfile[1024], basereadfile[1024],readfile[1024];
1130 32
	FILE *fp;
1131
	int width,height,asample_rate,achannels;
1132 33
		
1133 34
	if(argc<4) {
1134 35
		printf("chunker_player queue_thresh httpd_port silentMode <YUVFilename>\n");
1135 36
		exit(1);
1136 37
	}
1137
	// sscanf(argv[1],"%d",&width);
1138
	// sscanf(argv[2],"%d",&height);
1139
	// sscanf(argv[3],"%f",&ratio);
1140 38
	sscanf(argv[1],"%d",&queue_filling_threshold);
1141
	sscanf(argv[2],"%d",&httpPort);
1142
	sscanf(argv[3],"%d",&silentMode);
39
	sscanf(argv[2],"%d",&HttpPort);
40
	sscanf(argv[3],"%d",&SilentMode);
1143 41
	
1144 42
	if(argc==5)
1145 43
	{
1146 44
		sscanf(argv[4],"%s",YUVFileName);
1147 45
		printf("YUVFile: %s\n",YUVFileName);
1148
		FILE* fp=fopen(YUVFileName, "wb");
46
		fp=fopen(YUVFileName, "wb");
1149 47
		if(fp)
1150 48
		{
1151 49
			SaveYUV=1;
......
1155 53
			printf("ERROR: Unable to create YUVFile\n");
1156 54
	}
1157 55
	
1158
	//calculate aspect ratio and put updated values in rect
1159
	ratio = DEFAULT_RATIO;
1160
	UpdateOverlaySize(ratio, DEFAULT_WIDTH, DEFAULT_HEIGHT);
1161
	
1162 56
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
1163 57
		fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
1164 58
		return -1;
1165 59
	}
1166 60
	
1167
	RedrawMutex = SDL_CreateMutex();
1168
	if(!silentMode)
1169
		SetupGUI();
1170
	
1171
	if(parse_conf())
61
	if(ParseConf())
1172 62
	{
63
		printf("ERROR: Cannot parse configuration file, exit...\n");
1173 64
		exit(1);
1174 65
	}
1175 66
	
1176
	SelectedChannel = 0;
1177
	KILLALL("offerstreamer-ml-monl-http");
1178
	switch_channel(&(Channels[SelectedChannel]));
1179

  
1180
	initRect = (SDL_Rect*) malloc(sizeof(SDL_Rect));
1181
	if(!initRect)
67
	if(ChunkerPlayerGUI_Init())
1182 68
	{
1183
		printf("Memory error!!!\n");
1184
		return -1;
69
		printf("ERROR: Cannot init player gui, exit...\n");
70
		exit(1);
1185 71
	}
1186
	initRect->x = rect.x;
1187
	initRect->y = rect.y;
1188
	initRect->w = rect.w;
1189
	initRect->h = rect.h;
72
	
73
	SelectedChannel = 0;
74
	// KILLALL("offerstreamer-ml-monl-http-debug");
75
	SwitchChannel(&(Channels[SelectedChannel]));
1190 76
	
1191 77
	//this thread fetches chunks from the network by listening to the following path, port
1192
	daemon = initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, httpPort);
78
	daemon = initChunkPuller(UL_DEFAULT_EXTERNALPLAYER_PATH, HttpPort);
1193 79
	if(daemon == NULL)
1194 80
	{
1195 81
		printf("CANNOT START MICROHTTPD SERVICE, EXITING...\n");
......
1201 87
		if(QueueFillingMode) {
1202 88
			SDL_WM_SetCaption("Filling buffer...", NULL);
1203 89

  
1204
			if(audioq.nb_packets==0 && audioq.last_frame_extracted>0) {	// video ended therefore init queues
1205
#ifdef DEBUG_QUEUE
1206
				printf("QUEUE: MAIN SHOULD RESET\n");
1207
#endif
1208
				packet_queue_reset(&audioq, AUDIO);
1209
				packet_queue_reset(&videoq, VIDEO);
1210
			}
90
			if(ChunkerPlayerCore_VideoEnded())
91
				ChunkerPlayerCore_ResetAVQueues();
1211 92

  
1212 93
#ifdef DEBUG_QUEUE
1213 94
			//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);
......
1216 97
		else
1217 98
			SDL_WM_SetCaption("NAPA-Wine Player", NULL);
1218 99

  
1219
		int x = 0, y = 0;
1220
		int resize_w, resize_h;
1221
		int tmp_switch = 0;
1222
		int i;
1223 100
		//listen for key and mouse
1224 101
		while(SDL_PollEvent(&event)) {
1225 102
			switch(event.type) {
1226 103
				case SDL_QUIT:
1227
					StopAVPlaying();
1228 104
					quit=1;
1229 105
				break;
1230 106
				case SDL_VIDEORESIZE:
1231
					SDL_LockMutex(RedrawMutex);
1232
#ifndef __DARWIN__
1233
					screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_SWSURFACE | SDL_RESIZABLE);
1234
#else
1235
					screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 24, SDL_SWSURFACE | SDL_RESIZABLE);
1236
#endif
1237
					if(!screen) {
1238
						fprintf(stderr, "SDL_SetVideoMode returned null: could not set video mode - exiting\n");
1239
						exit(1);
1240
					}
1241
					
1242
					SDL_UnlockMutex(RedrawMutex);
1243
					
1244
					window_width = event.resize.w;
1245
					window_height = event.resize.h;
1246
					
1247
					// update the overlay surface size, mantaining the aspect ratio
1248
					UpdateOverlaySize(ratio, event.resize.w, event.resize.h);
1249
					
1250
					// update each button coordinates
1251
					for(i=0; i<NBUTTONS; i++)
1252
					{
1253
						if(Buttons[i].XOffset > 0)
1254
							Buttons[i].ButtonIconBox.x = Buttons[i].XOffset;
1255
						else
1256
							Buttons[i].ButtonIconBox.x = (event.resize.w + Buttons[i].XOffset);
1257
							
1258
						Buttons[i].ButtonIconBox.y = event.resize.h - Buttons[i].ButtonIconBox.h - (BUTTONS_LAYER_OFFSET/2);
1259
					}
1260
					
1261
					SDL_LockMutex(RedrawMutex);
1262
					redraw_buttons();
1263
					redraw_channel_name();
1264
					SDL_UnlockMutex(RedrawMutex);
1265
					
107
					// printf("\tSDL_VIDEORESIZE event received!! \n");
108
					if(!FullscreenMode)
109
						ChunkerPlayerGUI_HandleResize(event.resize.w, event.resize.h);
110
					else
111
						ChunkerPlayerGUI_HandleResize(FullscreenWidth, FullscreenHeight);
1266 112
				break;
1267 113
				case SDL_ACTIVEEVENT:
1268
					//printf("\tSDL_ACTIVEEVENT\n");
1269 114
					// if the window was iconified or restored
1270 115
					if(event.active.state & SDL_APPACTIVE)
1271 116
					{
1272 117
						//If the application is being reactivated
1273 118
						if( event.active.gain != 0 )
1274 119
						{
1275
							//SDL_WM_SetCaption( "Window Event Test restored", NULL );
1276
							redraw_buttons();
1277
							redraw_channel_name();
120
							ChunkerPlayerGUI_HandleGetFocus();
1278 121
						}
1279 122
					}
1280 123

  
......
1284 127
						//If the application gained keyboard focus
1285 128
						if( event.active.gain != 0 )
1286 129
						{
1287
							redraw_buttons();
1288
							redraw_channel_name();
130
							ChunkerPlayerGUI_HandleGetFocus();
1289 131
						}
1290 132
					}
1291 133
					//If something happened to the mouse focus
......
1294 136
						//If the application gained mouse focus
1295 137
						if( event.active.gain != 0 )
1296 138
						{
1297
							redraw_buttons();
1298
							redraw_channel_name();
139
							ChunkerPlayerGUI_HandleGetFocus();
1299 140
						}
1300 141
					}
1301 142
					break;
1302 143
				case SDL_MOUSEMOTION:
1303
					//printf("\tSDL_MOUSEMOTION\n");
1304
					x = event.motion.x;
1305
					y = event.motion.y;
1306
					
1307
					for(i=0; i<NBUTTONS; i++)
1308
					{
1309
						//If the mouse is over the button
1310
						if(
1311
							( x > Buttons[i].ButtonIconBox.x ) && ( x < Buttons[i].ButtonIconBox.x + Buttons[i].ButtonIcon->w )
1312
							&& ( y > Buttons[i].ButtonIconBox.y ) && ( y < Buttons[i].ButtonIconBox.y + Buttons[i].ButtonIcon->h )
1313
						)
1314
						{
1315
							Buttons[i].Hover = 1;
1316
							SDL_SetCursor(handCursor);
1317
							break;
1318
						}
1319
						
1320
						else
1321
						{
1322
							Buttons[i].Hover = 0;
1323
							SDL_SetCursor(defaultCursor);
1324
						}
1325
					}
144
					ChunkerPlayerGUI_HandleMouseMotion(event.motion.x, event.motion.y);
1326 145
				break;
1327 146
				case SDL_MOUSEBUTTONUP:
1328
					//printf("\tSDL_MOUSEBUTTONUP\n");
1329 147
					if( event.button.button != SDL_BUTTON_LEFT )
1330 148
						break;
1331
					
1332
					x = event.motion.x;
1333
					y = event.motion.y;
1334
					
1335
					for(i=0; i<NBUTTONS; i++)
1336
					{
1337
						//If the mouse is over the button
1338
						if(
1339
							( x > Buttons[i].ButtonIconBox.x ) && ( x < Buttons[i].ButtonIconBox.x + Buttons[i].ButtonIcon->w )
1340
							&& ( y > Buttons[i].ButtonIconBox.y ) && ( y < Buttons[i].ButtonIconBox.y + Buttons[i].ButtonIcon->h )
1341
						)
1342
						{
1343
							Buttons[i].LButtonUpCallback();
1344
							break;
1345
						}
1346
					}
149

  
150
					ChunkerPlayerGUI_HandleLButton(event.motion.x, event.motion.y);
1347 151
				break;
1348 152
			}
1349
			ProcessKeys();
153
			ChunkerPlayerGUI_HandleKey();
1350 154
		}
1351 155
		usleep(120000);
1352 156
	}
......
1355 159
		KILL_PROCESS(P2PProcessID);
1356 160

  
1357 161
	//TERMINATE
1358
	if(ChannelTitleSurface != NULL)
1359
		SDL_FreeSurface( ChannelTitleSurface );
1360
	if(yuv_overlay != NULL)
1361
		SDL_FreeYUVOverlay(yuv_overlay);
1362
	TTF_CloseFont( MainFont );
1363
	TTF_Quit();
1364
	IMG_Quit();
162
	ChunkerPlayerCore_Stop();
163
	if(YUVOverlay != NULL)
164
		SDL_FreeYUVOverlay(YUVOverlay);
165
	
166
	ChunkerPlayerGUI_Close();
167
	SDL_DestroyMutex(OverlayMutex);
1365 168
	SDL_Quit();
1366 169
	finalizeChunkPuller(daemon);
1367
	free(initRect);
1368 170
	return 0;
1369 171
}
1370 172

  
1371
int enqueueBlock(const uint8_t *block, const int block_size) {
1372
	Chunk *gchunk = NULL;
1373
	ExternalChunk *echunk = NULL;
1374
	int decoded_size = -1;
1375
	uint8_t *tempdata, *buffer;
1376
	int i, j;
1377
	Frame *frame = NULL;
1378
	AVPacket packet, packetaudio;
1379

  
1380
	uint16_t *audio_bufQ = NULL;
1381
	int16_t *dataQ = NULL;
1382
	int data_sizeQ;
1383
	int lenQ;
1384

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

  
1389
	audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
1390
	if(!audio_bufQ) {
1391
		printf("Memory error in audio_bufQ!\n");
1392
		return PLAYER_FAIL_RETURN;
1393
	}
1394

  
1395
	gchunk = (Chunk *)malloc(sizeof(Chunk));
1396
	if(!gchunk) {
1397
		printf("Memory error in gchunk!\n");
1398
		av_free(audio_bufQ);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff