chunker-player / chunker_player.c @ e810bf7b
History | View | Annotate | Download (29.8 KB)
1 |
// player.c
|
---|---|
2 |
// Author
|
3 |
// Diego Reforgiato, Dario Marchese, Carmelo Daniele
|
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 |
|
27 |
#ifdef __MINGW32__
|
28 |
#undef main /* Prevents SDL from overriding main() */ |
29 |
#endif
|
30 |
|
31 |
#include <platform.h> |
32 |
#include <microhttpd.h> |
33 |
//#include <AntTweakBar.h>
|
34 |
|
35 |
#include "chunker_player.h" |
36 |
#include "codec_definitions.h" |
37 |
|
38 |
#define SDL_AUDIO_BUFFER_SIZE 1024 |
39 |
|
40 |
#define QUEUE_FILLING_THRESHOLD 50 |
41 |
#define AUDIO 1 |
42 |
#define VIDEO 2 |
43 |
|
44 |
#define DEBUG_AUDIO
|
45 |
#define DEBUG_VIDEO
|
46 |
#define DEBUG_QUEUE
|
47 |
#define DEBUG_SOURCE
|
48 |
|
49 |
short int QueueFillingMode=1; |
50 |
short int QueueStopped=0; |
51 |
|
52 |
typedef struct PacketQueue { |
53 |
AVPacketList *first_pkt, *last_pkt; |
54 |
int nb_packets;
|
55 |
int size;
|
56 |
SDL_mutex *mutex; |
57 |
SDL_cond *cond; |
58 |
short int queueType; |
59 |
int last_frame_extracted;
|
60 |
int total_lost_frames;
|
61 |
} PacketQueue; |
62 |
|
63 |
typedef struct threadVal { |
64 |
int width;
|
65 |
int height;
|
66 |
} ThreadVal; |
67 |
|
68 |
int AudioQueueOffset=0; |
69 |
PacketQueue audioq; |
70 |
PacketQueue videoq; |
71 |
AVPacket AudioPkt, VideoPkt; |
72 |
int quit = 0; |
73 |
|
74 |
SDL_Surface *screen; |
75 |
SDL_Overlay *yuv_overlay; |
76 |
SDL_Rect rect; |
77 |
|
78 |
int got_sigint = 0; |
79 |
|
80 |
#define MAX_TOLLERANCE 60 |
81 |
|
82 |
long long DeltaTime; |
83 |
short int FirstTimeAudio=1, FirstTimeVideo = 1, FirstTime = 1; |
84 |
|
85 |
int dimAudioQ;
|
86 |
float deltaAudioQ;
|
87 |
|
88 |
void packet_queue_init(PacketQueue *q, short int Type) { |
89 |
memset(q,0,sizeof(PacketQueue)); |
90 |
q->mutex = SDL_CreateMutex(); |
91 |
q->cond = SDL_CreateCond(); |
92 |
QueueFillingMode=1;
|
93 |
q->queueType=Type; |
94 |
q->last_frame_extracted = 0;
|
95 |
q->total_lost_frames = 0;
|
96 |
} |
97 |
|
98 |
int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
|
99 |
short int skip = 0; |
100 |
AVPacketList *pkt1, *tmp, *prevtmp; |
101 |
if(av_dup_packet(pkt) < 0) { |
102 |
return -1; |
103 |
} |
104 |
pkt1 = av_malloc(sizeof(AVPacketList));
|
105 |
if (!pkt1)
|
106 |
return -1; |
107 |
pkt1->pkt = *pkt; |
108 |
pkt1->next = NULL;
|
109 |
|
110 |
SDL_LockMutex(q->mutex); |
111 |
|
112 |
// INSERTION SORT ALGORITHM
|
113 |
// before inserting pkt, check if pkt.stream_index is <= current_extracted_frame.
|
114 |
|
115 |
if(pkt->stream_index>q->last_frame_extracted) {
|
116 |
|
117 |
// either checking starting from the first_pkt or needed other struct like AVPacketList with next and prev....
|
118 |
if (!q->last_pkt)
|
119 |
q->first_pkt = pkt1; |
120 |
else {
|
121 |
tmp = q->first_pkt; |
122 |
while(tmp->pkt.stream_index<pkt->stream_index) {
|
123 |
prevtmp = tmp; |
124 |
tmp = tmp->next; |
125 |
if(!tmp)
|
126 |
break;
|
127 |
} |
128 |
if(tmp && tmp->pkt.stream_index==pkt->stream_index) {
|
129 |
skip = 1;
|
130 |
} |
131 |
else {
|
132 |
prevtmp->next = pkt1; |
133 |
pkt1->next = tmp; |
134 |
} |
135 |
// q->last_pkt->next = pkt1; // It was uncommented when not insertion sort
|
136 |
} |
137 |
if(skip==0) { |
138 |
q->last_pkt = pkt1; |
139 |
q->nb_packets++; |
140 |
q->size += pkt1->pkt.size; |
141 |
#ifdef DEBUG_QUEUE
|
142 |
printf("PUT in Queue: NPackets=%d Type=%d\n",q->nb_packets,q->queueType);
|
143 |
#endif
|
144 |
|
145 |
if(q->nb_packets>=QUEUE_FILLING_THRESHOLD && QueueFillingMode) // && q->queueType==AUDIO) |
146 |
{ |
147 |
QueueFillingMode=0;
|
148 |
#ifdef DEBUG_QUEUE
|
149 |
printf("PUT in Queue: FillingMode set to zero\n");
|
150 |
#endif
|
151 |
//SDL_CondSignal(q->cond);
|
152 |
} |
153 |
//WHYYYYYYYYY q->last_frame_extracted = pkt->stream_index;
|
154 |
//#ifdef DEBUG_QUEUE
|
155 |
// printf("PUT LastFrameExtracted set to %d\n",q->last_frame_extracted);
|
156 |
//#endif
|
157 |
} |
158 |
} |
159 |
|
160 |
SDL_UnlockMutex(q->mutex); |
161 |
return 0; |
162 |
} |
163 |
|
164 |
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, short int av) { |
165 |
//AVPacket tmp;
|
166 |
AVPacketList *pkt1; |
167 |
int ret=-1; |
168 |
int SizeToCopy=0; |
169 |
|
170 |
#ifdef DEBUG_QUEUE
|
171 |
printf("QUEUE Get NPackets=%d Type=%d\n",q->nb_packets,q->queueType);
|
172 |
#endif
|
173 |
|
174 |
if((q->queueType==AUDIO && QueueFillingMode) || QueueStopped)
|
175 |
{ |
176 |
return -1; |
177 |
//SDL_CondWait(q->cond, q->mutex);
|
178 |
} |
179 |
|
180 |
SDL_LockMutex(q->mutex); |
181 |
pkt1 = q->first_pkt; |
182 |
if (pkt1) {
|
183 |
if(av==1) { |
184 |
if(pkt1->pkt.size-AudioQueueOffset>dimAudioQ) {
|
185 |
#ifdef DEBUG_QUEUE
|
186 |
printf(" AV=1 and Extract from the same packet\n");
|
187 |
#endif
|
188 |
//av_init_packet(&tmp);
|
189 |
q->size -= dimAudioQ; |
190 |
pkt->size = dimAudioQ; |
191 |
//tmp.data = pkt1->pkt.data+AudioQueueOffset;
|
192 |
memcpy(pkt->data,pkt1->pkt.data+AudioQueueOffset,dimAudioQ); |
193 |
pkt->dts = pkt1->pkt.dts; |
194 |
pkt->pts = pkt1->pkt.pts; |
195 |
pkt->stream_index = pkt1->pkt.stream_index;//1;
|
196 |
pkt->flags = 1;
|
197 |
pkt->pos = -1;
|
198 |
pkt->convergence_duration = -1;
|
199 |
|
200 |
//*pkt = tmp;
|
201 |
//pkt1->pkt.size -= dimAudioQ;
|
202 |
pkt1->pkt.dts += deltaAudioQ; |
203 |
pkt1->pkt.pts += deltaAudioQ; |
204 |
AudioQueueOffset += dimAudioQ; |
205 |
#ifdef DEBUG_QUEUE
|
206 |
printf(" AudioQueueOffset = %d\n",AudioQueueOffset);
|
207 |
#endif
|
208 |
|
209 |
ret = 1;
|
210 |
//compute lost frame statistics
|
211 |
if(q->last_frame_extracted > 0 && pkt->stream_index > q->last_frame_extracted) { |
212 |
#ifdef DEBUG_QUEUE
|
213 |
printf(" stats: stidx %d last %d tot %d\n", pkt->stream_index, q->last_frame_extracted, q->total_lost_frames);
|
214 |
#endif
|
215 |
q->total_lost_frames = q->total_lost_frames + pkt->stream_index - q->last_frame_extracted - 1;
|
216 |
} |
217 |
//update index of last frame extracted
|
218 |
q->last_frame_extracted = pkt->stream_index; |
219 |
} |
220 |
else {
|
221 |
#ifdef DEBUG_QUEUE
|
222 |
printf(" AV = 1 and Extract from 2 packets\n");
|
223 |
#endif
|
224 |
// Check for loss
|
225 |
if(pkt1->next)
|
226 |
{ |
227 |
#ifdef DEBUG_QUEUE
|
228 |
printf(" we have a next...\n");
|
229 |
#endif
|
230 |
//av_init_packet(&tmp);
|
231 |
pkt->size = dimAudioQ; |
232 |
pkt->dts = pkt1->pkt.dts; |
233 |
pkt->pts = pkt1->pkt.pts; |
234 |
pkt->stream_index = pkt1->pkt.stream_index;//1;
|
235 |
pkt->flags = 1;
|
236 |
pkt->pos = -1;
|
237 |
pkt->convergence_duration = -1;
|
238 |
//tmp.data = (uint8_t *)malloc(sizeof(uint8_t)*dimAudioQ);
|
239 |
//if(tmp.data)
|
240 |
{ |
241 |
SizeToCopy=pkt1->pkt.size-AudioQueueOffset; |
242 |
#ifdef DEBUG_QUEUE
|
243 |
printf(" SizeToCopy=%d\n",SizeToCopy);
|
244 |
#endif
|
245 |
memcpy(pkt->data,pkt1->pkt.data+AudioQueueOffset,SizeToCopy); |
246 |
memcpy(pkt->data+SizeToCopy,pkt1->next->pkt.data,(dimAudioQ-SizeToCopy)*sizeof(uint8_t));
|
247 |
} |
248 |
//*pkt = tmp;
|
249 |
} |
250 |
q->first_pkt = pkt1->next; |
251 |
if (!q->first_pkt)
|
252 |
q->last_pkt = NULL;
|
253 |
q->nb_packets--; |
254 |
q->size -= SizeToCopy; |
255 |
#ifdef DEBUG_QUEUE
|
256 |
printf(" about to free... ");
|
257 |
#endif
|
258 |
free(pkt1->pkt.data); |
259 |
av_free(pkt1); |
260 |
#ifdef DEBUG_QUEUE
|
261 |
printf("freeed\n");
|
262 |
#endif
|
263 |
// Adjust timestamps
|
264 |
pkt1 = q->first_pkt; |
265 |
if(pkt1)
|
266 |
{ |
267 |
pkt1->pkt.dts = pkt->dts + deltaAudioQ; |
268 |
pkt1->pkt.pts = pkt->pts + deltaAudioQ; |
269 |
AudioQueueOffset=dimAudioQ-SizeToCopy; |
270 |
q->size -= AudioQueueOffset; |
271 |
ret = 1;
|
272 |
} |
273 |
else
|
274 |
{ |
275 |
AudioQueueOffset=0;
|
276 |
} |
277 |
#ifdef DEBUG_QUEUE
|
278 |
printf(" AudioQueueOffset = %d\n",AudioQueueOffset);
|
279 |
#endif
|
280 |
|
281 |
//compute lost frame statistics
|
282 |
if(q->last_frame_extracted > 0 && pkt->stream_index > q->last_frame_extracted) { |
283 |
#ifdef DEBUG_QUEUE
|
284 |
printf(" stats: stidx %d last %d tot %d\n", pkt->stream_index, q->last_frame_extracted, q->total_lost_frames);
|
285 |
#endif
|
286 |
q->total_lost_frames = q->total_lost_frames + pkt->stream_index - q->last_frame_extracted - 1;
|
287 |
} |
288 |
//update index of last frame extracted
|
289 |
q->last_frame_extracted = pkt->stream_index; |
290 |
} |
291 |
} |
292 |
else {
|
293 |
#ifdef DEBUG_QUEUE
|
294 |
printf(" AV not 1\n");
|
295 |
#endif
|
296 |
q->first_pkt = pkt1->next; |
297 |
if (!q->first_pkt)
|
298 |
q->last_pkt = NULL;
|
299 |
q->nb_packets--; |
300 |
q->size -= pkt1->pkt.size; |
301 |
|
302 |
pkt->size = pkt1->pkt.size; |
303 |
pkt->dts = pkt1->pkt.dts; |
304 |
pkt->pts = pkt1->pkt.pts; |
305 |
pkt->stream_index = pkt1->pkt.stream_index; |
306 |
pkt->flags = pkt1->pkt.flags; |
307 |
pkt->pos = pkt1->pkt.pos; |
308 |
pkt->convergence_duration = pkt1->pkt.convergence_duration; |
309 |
//*pkt = pkt1->pkt;
|
310 |
#ifdef DEBUG_QUEUE
|
311 |
printf(" about to free... ");
|
312 |
#endif
|
313 |
memcpy(pkt->data,pkt1->pkt.data,pkt1->pkt.size); |
314 |
free(pkt1->pkt.data); |
315 |
av_free(pkt1); |
316 |
#ifdef DEBUG_QUEUE
|
317 |
printf("freeed\n");
|
318 |
#endif
|
319 |
ret = 1;
|
320 |
//compute lost frame statistics
|
321 |
if(q->last_frame_extracted > 0 && pkt->stream_index > q->last_frame_extracted) { |
322 |
#ifdef DEBUG_QUEUE
|
323 |
printf(" stats: stidx %d last %d tot %d\n", pkt->stream_index, q->last_frame_extracted, q->total_lost_frames);
|
324 |
#endif
|
325 |
q->total_lost_frames = q->total_lost_frames + pkt->stream_index - q->last_frame_extracted - 1;
|
326 |
} |
327 |
//update index of last frame extracted
|
328 |
q->last_frame_extracted = pkt->stream_index; |
329 |
} |
330 |
} |
331 |
#ifdef DEBUG_QUEUE
|
332 |
else {
|
333 |
printf(" pk1 NULLLLLLLLLL!!!!\n");
|
334 |
} |
335 |
#endif
|
336 |
|
337 |
if(q->nb_packets==0 && q->queueType==AUDIO) { |
338 |
QueueFillingMode=1;
|
339 |
#ifdef DEBUG_QUEUE
|
340 |
printf("QUEUE Get FillingMode ON\n");
|
341 |
#endif
|
342 |
} |
343 |
#ifdef DEBUG_QUEUE
|
344 |
printf("QUEUE Get LastFrameExtracted = %d\n",q->last_frame_extracted);
|
345 |
printf("QUEUE Get Tot lost frames = %d\n",q->total_lost_frames);
|
346 |
#endif
|
347 |
|
348 |
SDL_UnlockMutex(q->mutex); |
349 |
return ret;
|
350 |
} |
351 |
|
352 |
|
353 |
int audio_decode_frame(uint8_t *audio_buf, int buf_size) { |
354 |
//struct timeval now;
|
355 |
int audio_pkt_size = 0; |
356 |
long long Now; |
357 |
short int DecodeAudio=0, SkipAudio=0; |
358 |
//int len1, data_size;
|
359 |
|
360 |
//gettimeofday(&now,NULL);
|
361 |
//Now = (now.tv_sec)*1000+now.tv_usec/1000;
|
362 |
Now=(long long)SDL_GetTicks(); |
363 |
|
364 |
if(QueueFillingMode || QueueStopped)
|
365 |
{ |
366 |
FirstTimeAudio=1;
|
367 |
FirstTime = 1;
|
368 |
return -1; |
369 |
} |
370 |
|
371 |
if((FirstTime==1 || FirstTimeAudio==1) && audioq.size>0) { |
372 |
if(audioq.first_pkt->pkt.pts>0) |
373 |
{ |
374 |
DeltaTime=Now-(long long)(audioq.first_pkt->pkt.pts); |
375 |
FirstTimeAudio = 0;
|
376 |
FirstTime = 0;
|
377 |
#ifdef DEBUG_AUDIO
|
378 |
printf("audio_decode_frame - DeltaTimeAudio=%lld\n",DeltaTime);
|
379 |
#endif
|
380 |
} |
381 |
} |
382 |
|
383 |
#ifdef DEBUG_AUDIO
|
384 |
if(audioq.first_pkt)
|
385 |
{ |
386 |
printf("audio_decode_frame - Syncro params: DeltaNow-pts=%lld ",(Now-((long long)audioq.first_pkt->pkt.pts+DeltaTime))); |
387 |
printf("pts=%lld ",(long long)audioq.first_pkt->pkt.pts); |
388 |
printf("Tollerance=%d ",(int)MAX_TOLLERANCE); |
389 |
printf("QueueLen=%d ",(int)audioq.nb_packets); |
390 |
printf("QueueSize=%d\n",(int)audioq.size); |
391 |
} |
392 |
else
|
393 |
printf("audio_decode_frame - Empty queue\n");
|
394 |
#endif
|
395 |
|
396 |
|
397 |
if(audioq.nb_packets>0) { |
398 |
if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) { |
399 |
SkipAudio = 1;
|
400 |
DecodeAudio = 0;
|
401 |
} |
402 |
else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE && |
403 |
(long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) { |
404 |
SkipAudio = 0;
|
405 |
DecodeAudio = 1;
|
406 |
} |
407 |
} |
408 |
|
409 |
while(SkipAudio==1 && audioq.size>0) { |
410 |
SkipAudio = 0;
|
411 |
#ifdef DEBUG_AUDIO
|
412 |
printf("skipaudio: queue size=%d\n",audioq.size);
|
413 |
#endif
|
414 |
if(packet_queue_get(&audioq,&AudioPkt,1) < 0) { |
415 |
return -1; |
416 |
} |
417 |
if(audioq.first_pkt)
|
418 |
{ |
419 |
if((long long)audioq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) { |
420 |
SkipAudio = 1;
|
421 |
DecodeAudio = 0;
|
422 |
} |
423 |
else if((long long)audioq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE && |
424 |
(long long)audioq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) { |
425 |
SkipAudio = 0;
|
426 |
DecodeAudio = 1;
|
427 |
} |
428 |
} |
429 |
} |
430 |
if(DecodeAudio==1) { |
431 |
if(packet_queue_get(&audioq,&AudioPkt,1) < 0) { |
432 |
return -1; |
433 |
} |
434 |
memcpy(audio_buf,AudioPkt.data,AudioPkt.size); |
435 |
audio_pkt_size = AudioPkt.size; |
436 |
#ifdef DEBUG_AUDIO
|
437 |
printf("Decode audio\n");
|
438 |
#endif
|
439 |
} |
440 |
|
441 |
return audio_pkt_size;
|
442 |
|
443 |
} |
444 |
|
445 |
/*static long get_time_diff(struct timeval time_now) {
|
446 |
struct timeval time_now2;
|
447 |
gettimeofday(&time_now2,0);
|
448 |
return time_now2.tv_sec*1.e6 - time_now.tv_sec*1.e6 + time_now2.tv_usec - time_now.tv_usec;
|
449 |
}*/
|
450 |
|
451 |
int video_callback(void *valthread) { |
452 |
//AVPacket pktvideo;
|
453 |
AVCodecContext *pCodecCtx; |
454 |
AVCodec *pCodec; |
455 |
AVFrame *pFrame; |
456 |
AVPacket packet; |
457 |
int frameFinished;
|
458 |
int countexit;
|
459 |
AVPicture pict; |
460 |
static struct SwsContext *img_convert_ctx; |
461 |
//FILE *frecon;
|
462 |
SDL_Event event; |
463 |
long long Now; |
464 |
short int SkipVideo, DecodeVideo; |
465 |
|
466 |
//double frame_rate = 0.0,time_between_frames=0.0;
|
467 |
//struct timeval now;
|
468 |
|
469 |
//int wait_for_sync = 1;
|
470 |
ThreadVal *tval; |
471 |
tval = (ThreadVal *)valthread; |
472 |
|
473 |
//frame_rate = tval->framerate;
|
474 |
//time_between_frames = 1.e6 / frame_rate;
|
475 |
//gettimeofday(&time_now,0);
|
476 |
|
477 |
//frecon = fopen("recondechunk.mpg","wb");
|
478 |
|
479 |
pCodecCtx=avcodec_alloc_context(); |
480 |
pCodecCtx->codec_type = CODEC_TYPE_VIDEO; |
481 |
#ifdef H264_VIDEO_ENCODER
|
482 |
pCodecCtx->codec_id = CODEC_ID_H264; |
483 |
pCodecCtx->me_range = 16;
|
484 |
pCodecCtx->max_qdiff = 4;
|
485 |
pCodecCtx->qmin = 10;
|
486 |
pCodecCtx->qmax = 51;
|
487 |
pCodecCtx->qcompress = 0.6; |
488 |
#else
|
489 |
pCodecCtx->codec_id = CODEC_ID_MPEG4; |
490 |
#endif
|
491 |
//pCodecCtx->bit_rate = 400000;
|
492 |
// resolution must be a multiple of two
|
493 |
pCodecCtx->width = tval->width;//176;//352;
|
494 |
pCodecCtx->height = tval->height;//144;//288;
|
495 |
// frames per second
|
496 |
//pCodecCtx->time_base = (AVRational){1,25};
|
497 |
//pCodecCtx->gop_size = 10; // emit one intra frame every ten frames
|
498 |
//pCodecCtx->max_b_frames=1;
|
499 |
pCodecCtx->pix_fmt = PIX_FMT_YUV420P; |
500 |
pCodec=avcodec_find_decoder(pCodecCtx->codec_id); |
501 |
|
502 |
if(pCodec==NULL) { |
503 |
fprintf(stderr, "Unsupported codec!\n");
|
504 |
return -1; // Codec not found |
505 |
} |
506 |
if(avcodec_open(pCodecCtx, pCodec)<0) { |
507 |
fprintf(stderr, "could not open codec\n");
|
508 |
return -1; // Could not open codec |
509 |
} |
510 |
pFrame=avcodec_alloc_frame(); |
511 |
if(pFrame==NULL) { |
512 |
printf("Memory error!!!\n");
|
513 |
return -1; |
514 |
} |
515 |
|
516 |
while(!quit) {
|
517 |
if(QueueFillingMode || QueueStopped)
|
518 |
{ |
519 |
FirstTime = 1;
|
520 |
usleep(5000);
|
521 |
continue;
|
522 |
} |
523 |
|
524 |
DecodeVideo = 0;
|
525 |
SkipVideo = 0;
|
526 |
//gettimeofday(&now,NULL);
|
527 |
//Now = (unsigned long long)now.tv_sec*1000+(unsigned long long)now.tv_usec/1000;
|
528 |
Now=(long long)SDL_GetTicks(); |
529 |
if(FirstTime==1 && videoq.size>0) { |
530 |
if(videoq.first_pkt->pkt.pts>0) |
531 |
{ |
532 |
DeltaTime=Now-(long long)videoq.first_pkt->pkt.pts; |
533 |
FirstTime = 0;
|
534 |
} |
535 |
#ifdef DEBUG_VIDEO
|
536 |
printf("VideoCallback - DeltaTimeAudio=%lld\n",DeltaTime);
|
537 |
#endif
|
538 |
} |
539 |
|
540 |
#ifdef DEBUG_VIDEO
|
541 |
if(videoq.first_pkt)
|
542 |
{ |
543 |
printf("VideoCallback - Syncro params: Delta:%lld Now:%lld pts=%lld ",(long long)DeltaTime,Now,(long long)videoq.first_pkt->pkt.pts); |
544 |
printf("pts=%lld ",(long long)videoq.first_pkt->pkt.pts); |
545 |
printf("Tollerance=%d ",(int)MAX_TOLLERANCE); |
546 |
printf("QueueLen=%d ",(int)videoq.nb_packets); |
547 |
printf("QueueSize=%d\n",(int)videoq.size); |
548 |
} |
549 |
else
|
550 |
printf("VideoCallback - Empty queue\n");
|
551 |
#endif
|
552 |
|
553 |
if(videoq.nb_packets>0) { |
554 |
if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)<Now-(long long)MAX_TOLLERANCE) { |
555 |
SkipVideo = 1;
|
556 |
DecodeVideo = 0;
|
557 |
} |
558 |
else
|
559 |
if(((long long)videoq.first_pkt->pkt.pts+DeltaTime)>=Now-(long long)MAX_TOLLERANCE && |
560 |
((long long)videoq.first_pkt->pkt.pts+DeltaTime)<=Now+(long long)MAX_TOLLERANCE) { |
561 |
SkipVideo = 0;
|
562 |
DecodeVideo = 1;
|
563 |
} |
564 |
} |
565 |
#ifdef DEBUG_VIDEO
|
566 |
printf("skipvideo:%d decodevideo:%d\n",SkipVideo,DecodeVideo);
|
567 |
#endif
|
568 |
|
569 |
while(SkipVideo==1 && videoq.size>0) { |
570 |
SkipVideo = 0;
|
571 |
#ifdef DEBUG_VIDEO
|
572 |
printf("Skip Video\n");
|
573 |
#endif
|
574 |
if(packet_queue_get(&videoq,&VideoPkt,0) < 0) { |
575 |
break;
|
576 |
} |
577 |
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt); |
578 |
if(videoq.first_pkt)
|
579 |
{ |
580 |
if((long long)videoq.first_pkt->pkt.pts+DeltaTime<Now-(long long)MAX_TOLLERANCE) { |
581 |
SkipVideo = 1;
|
582 |
DecodeVideo = 0;
|
583 |
} |
584 |
else if((long long)videoq.first_pkt->pkt.pts+DeltaTime>=Now-(long long)MAX_TOLLERANCE && |
585 |
(long long)videoq.first_pkt->pkt.pts+DeltaTime<=Now+(long long)MAX_TOLLERANCE) { |
586 |
SkipVideo = 0;
|
587 |
DecodeVideo = 1;
|
588 |
} |
589 |
} |
590 |
} |
591 |
|
592 |
if(DecodeVideo==1) { |
593 |
if(packet_queue_get(&videoq,&VideoPkt,0) > 0) { |
594 |
|
595 |
#ifdef DEBUG_VIDEO
|
596 |
printf("Decode video FrameTime=%lld Now=%lld\n",(long long)VideoPkt.pts+DeltaTime,Now); |
597 |
#endif
|
598 |
|
599 |
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &VideoPkt); |
600 |
|
601 |
if(frameFinished) { // it must be true all the time else error |
602 |
#ifdef DEBUG_VIDEO
|
603 |
printf("FrameFinished\n");
|
604 |
#endif
|
605 |
//SaveFrame(pFrame, pCodecCtx->width, pCodecCtx->height, cont++);
|
606 |
//fwrite(pktvideo.data, 1, pktvideo.size, frecon);
|
607 |
|
608 |
// Lock SDL_yuv_overlay
|
609 |
if ( SDL_MUSTLOCK(screen) ) {
|
610 |
#ifdef DEBUG_VIDEO
|
611 |
printf("-1 ");
|
612 |
#endif
|
613 |
|
614 |
if ( SDL_LockSurface(screen) < 0 ) { |
615 |
#ifdef DEBUG_VIDEO
|
616 |
printf("0 ");
|
617 |
#endif
|
618 |
break;
|
619 |
} |
620 |
} |
621 |
#ifdef DEBUG_VIDEO
|
622 |
printf("1 ");
|
623 |
#endif
|
624 |
if (SDL_LockYUVOverlay(yuv_overlay) < 0) break; |
625 |
#ifdef DEBUG_VIDEO
|
626 |
printf("2 ");
|
627 |
#endif
|
628 |
|
629 |
pict.data[0] = yuv_overlay->pixels[0]; |
630 |
pict.data[1] = yuv_overlay->pixels[2]; |
631 |
pict.data[2] = yuv_overlay->pixels[1]; |
632 |
|
633 |
pict.linesize[0] = yuv_overlay->pitches[0]; |
634 |
pict.linesize[1] = yuv_overlay->pitches[2]; |
635 |
pict.linesize[2] = yuv_overlay->pitches[1]; |
636 |
#ifdef DEBUG_VIDEO
|
637 |
printf("3 ");
|
638 |
#endif
|
639 |
|
640 |
img_convert_ctx = sws_getContext(tval->width,tval->height,PIX_FMT_YUV420P,tval->width,tval->height,PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL); |
641 |
#ifdef DEBUG_VIDEO
|
642 |
printf("4 ");
|
643 |
#endif
|
644 |
|
645 |
if(img_convert_ctx==NULL) { |
646 |
fprintf(stderr,"Cannot initialize the conversion context!\n");
|
647 |
exit(1);
|
648 |
} |
649 |
sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,tval->height,pict.data,pict.linesize);
|
650 |
#ifdef DEBUG_VIDEO
|
651 |
printf("5 ");
|
652 |
#endif
|
653 |
|
654 |
// let's draw the data (*yuv[3]) on a SDL screen (*screen)
|
655 |
if ( SDL_MUSTLOCK(screen) ) {
|
656 |
SDL_UnlockSurface(screen); |
657 |
} |
658 |
#ifdef DEBUG_VIDEO
|
659 |
printf("6 ");
|
660 |
#endif
|
661 |
|
662 |
SDL_UnlockYUVOverlay(yuv_overlay); |
663 |
|
664 |
// Show, baby, show!
|
665 |
SDL_DisplayYUVOverlay(yuv_overlay, &rect); |
666 |
#ifdef DEBUG_VIDEO
|
667 |
printf("7\n");
|
668 |
#endif
|
669 |
|
670 |
} |
671 |
} |
672 |
} |
673 |
|
674 |
usleep(5000);
|
675 |
|
676 |
/*SDL_PollEvent(&event);
|
677 |
switch(event.type) {
|
678 |
case SDL_QUIT:
|
679 |
quit=1;
|
680 |
//exit(0);
|
681 |
break;
|
682 |
}*/
|
683 |
} |
684 |
av_free(pCodecCtx); |
685 |
//fclose(frecon);
|
686 |
#ifdef DEBUG_VIDEO
|
687 |
printf("video callback end\n");
|
688 |
#endif
|
689 |
return 1; |
690 |
} |
691 |
|
692 |
/*int audio_decode_frame2(uint8_t *audio_buf,int len) {
|
693 |
AVPacket pkt;
|
694 |
if(packet_queue_get(&audioq, &pkt, 1,1) < 0) {
|
695 |
return -1;
|
696 |
}
|
697 |
memcpy(audio_buf,pkt.data,pkt.size);
|
698 |
//printf("tornato : %d bytes\n",pkt.size);
|
699 |
return pkt.size;
|
700 |
}*/
|
701 |
|
702 |
void audio_callback(void *userdata, Uint8 *stream, int len) { |
703 |
|
704 |
//AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
|
705 |
int audio_size;
|
706 |
|
707 |
static uint8_t audio_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
|
708 |
|
709 |
audio_size = audio_decode_frame(audio_buf, sizeof(audio_buf));
|
710 |
if(audio_size != len) {
|
711 |
memset(stream, 0, len);
|
712 |
} else {
|
713 |
memcpy(stream, (uint8_t *)audio_buf, len); |
714 |
} |
715 |
} |
716 |
|
717 |
void ShowBMP(char *file, SDL_Surface *screen, int x, int y) { |
718 |
SDL_Surface *image; |
719 |
SDL_Rect dest; |
720 |
|
721 |
/* Load a BMP file on a surface */
|
722 |
image = SDL_LoadBMP(file); |
723 |
if ( image == NULL ) { |
724 |
fprintf(stderr, "Error loading %s: %s\n", file, SDL_GetError());
|
725 |
return;
|
726 |
} |
727 |
|
728 |
/* Copy on the screen surface
|
729 |
surface should be blocked now.
|
730 |
*/
|
731 |
dest.x = x; |
732 |
dest.y = y; |
733 |
dest.w = image->w; |
734 |
dest.h = image->h; |
735 |
SDL_BlitSurface(image, NULL, screen, &dest);
|
736 |
|
737 |
/* Update the screen area just changed */
|
738 |
SDL_UpdateRects(screen, 1, &dest);
|
739 |
} |
740 |
|
741 |
int alphasortNew(const struct dirent **a, const struct dirent **b) { |
742 |
int idx1 = atoi((*a)->d_name+5); |
743 |
int idx2 = atoi((*b)->d_name+5); |
744 |
return (idx2<idx1);
|
745 |
// return (strcmp((*a)->d_name,(*b)->d_name));
|
746 |
} |
747 |
|
748 |
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { |
749 |
FILE *pFile; |
750 |
char szFilename[32]; |
751 |
int y;
|
752 |
|
753 |
// Open file
|
754 |
sprintf(szFilename, "frame%d.ppm", iFrame);
|
755 |
pFile=fopen(szFilename, "wb");
|
756 |
if(pFile==NULL) |
757 |
return;
|
758 |
|
759 |
// Write header
|
760 |
fprintf(pFile, "P5\n%d %d\n255\n", width, height);
|
761 |
|
762 |
// Write pixel data
|
763 |
for(y=0; y<height; y++) |
764 |
fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile); |
765 |
|
766 |
// Close file
|
767 |
fclose(pFile); |
768 |
} |
769 |
|
770 |
static void sigint_handler (int signal) { |
771 |
printf("Caught SIGINT, exiting...");
|
772 |
got_sigint = 1;
|
773 |
} |
774 |
|
775 |
void ProcessKeys()
|
776 |
{ |
777 |
static Uint32 LastTime=0; |
778 |
static int LastKey=-1; |
779 |
|
780 |
Uint32 Now=SDL_GetTicks(); |
781 |
Uint8* keystate=SDL_GetKeyState(NULL);
|
782 |
if(keystate[SDLK_SPACE] &&
|
783 |
(LastKey!=SDLK_SPACE || (LastKey==SDLK_SPACE && (Now-LastTime>1000))))
|
784 |
{ |
785 |
LastKey=SDLK_SPACE; |
786 |
LastTime=Now; |
787 |
QueueStopped=!QueueStopped; |
788 |
} |
789 |
if(keystate[SDLK_ESCAPE] &&
|
790 |
(LastKey!=SDLK_ESCAPE || (LastKey==SDLK_ESCAPE && (Now-LastTime>1000))))
|
791 |
{ |
792 |
LastKey=SDLK_ESCAPE; |
793 |
LastTime=Now; |
794 |
quit=1;
|
795 |
} |
796 |
/*if(keystate[SDLK_f] &&
|
797 |
(LastKey!=SDLK_f || (LastKey==SDLK_f && (Now-LastTime>1000))))
|
798 |
{
|
799 |
LastKey=SDLK_f;
|
800 |
LastTime=Now;
|
801 |
SDL_WM_ToggleFullScreen(NULL);
|
802 |
}*/
|
803 |
} |
804 |
|
805 |
int main(int argc, char *argv[]) { |
806 |
int i, j, videoStream,outbuf_size,out_size,out_size_audio,seq_current_chunk = 0,audioStream; |
807 |
int len1, data_size, stime,cont=0; |
808 |
int frameFinished, len_audio;
|
809 |
int numBytes,outbuf_audio_size,audio_size;
|
810 |
|
811 |
int y;
|
812 |
|
813 |
uint8_t *outbuf,*outbuf_audio; |
814 |
uint8_t *outbuf_audi_audio; |
815 |
|
816 |
AVFormatContext *pFormatCtx; |
817 |
|
818 |
AVCodec *pCodec,*aCodec; |
819 |
AVFrame *pFrame; |
820 |
|
821 |
AVPicture pict; |
822 |
static struct SwsContext *img_convert_ctx; |
823 |
SDL_Thread *video_thread;//exit_thread,*exit_thread2;
|
824 |
SDL_Event event; |
825 |
//SDL_mutex *lock;
|
826 |
SDL_AudioSpec wanted_spec, spec; |
827 |
|
828 |
struct MHD_Daemon *daemon = NULL; |
829 |
|
830 |
char buf[1024],outfile[1024], basereadfile[1024],readfile[1024]; |
831 |
FILE *fp; |
832 |
// struct dirent **namelist;
|
833 |
int width,height,asample_rate,achannels;
|
834 |
//double framerate;
|
835 |
|
836 |
// TwBar *bar;
|
837 |
|
838 |
ThreadVal *tval; |
839 |
tval = (ThreadVal *)malloc(sizeof(ThreadVal));
|
840 |
|
841 |
if(argc<5) { |
842 |
printf("player width height sample_rate channels\n");
|
843 |
exit(1);
|
844 |
} |
845 |
sscanf(argv[1],"%d",&width); |
846 |
sscanf(argv[2],"%d",&height); |
847 |
sscanf(argv[3],"%d",&asample_rate); |
848 |
sscanf(argv[4],"%d",&achannels); |
849 |
tval->width = width; |
850 |
tval->height = height; |
851 |
//tval->framerate = framerate;
|
852 |
|
853 |
|
854 |
|
855 |
|
856 |
|
857 |
// Register all formats and codecs
|
858 |
|
859 |
av_register_all(); |
860 |
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
|
861 |
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
|
862 |
return -1; |
863 |
} |
864 |
|
865 |
aCodecCtx = avcodec_alloc_context(); |
866 |
//aCodecCtx->bit_rate = 64000;
|
867 |
aCodecCtx->sample_rate = asample_rate; |
868 |
aCodecCtx->channels = achannels; |
869 |
#ifdef MP3_AUDIO_ENCODER
|
870 |
aCodec = avcodec_find_decoder(CODEC_ID_MP3); // codec audio
|
871 |
#else
|
872 |
aCodec = avcodec_find_decoder(CODEC_ID_MP2); |
873 |
#endif
|
874 |
printf("MP2 codec id %d MP3 codec id %d\n",CODEC_ID_MP2,CODEC_ID_MP3);
|
875 |
if(!aCodec) {
|
876 |
printf("Codec not found!\n");
|
877 |
return -1; |
878 |
} |
879 |
if(avcodec_open(aCodecCtx, aCodec)<0) { |
880 |
fprintf(stderr, "could not open codec\n");
|
881 |
return -1; // Could not open codec |
882 |
} |
883 |
printf("using audio Codecid: %d ",aCodecCtx->codec_id);
|
884 |
printf("samplerate: %d ",aCodecCtx->sample_rate);
|
885 |
printf("channels: %d\n",aCodecCtx->channels);
|
886 |
wanted_spec.freq = aCodecCtx->sample_rate; |
887 |
wanted_spec.format = AUDIO_S16SYS; |
888 |
wanted_spec.channels = aCodecCtx->channels; |
889 |
wanted_spec.silence = 0;
|
890 |
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; |
891 |
wanted_spec.callback = audio_callback; |
892 |
wanted_spec.userdata = aCodecCtx; |
893 |
printf("wantedsizeSDL:%d\n",wanted_spec.size);
|
894 |
if(SDL_OpenAudio(&wanted_spec,&spec)<0) { |
895 |
fprintf(stderr,"SDL_OpenAudio: %s\n",SDL_GetError());
|
896 |
return -1; |
897 |
} |
898 |
dimAudioQ = spec.size; |
899 |
deltaAudioQ = (float)((float)spec.samples)*1000/spec.freq; |
900 |
|
901 |
printf("wantedsizeSDL:%d %d\n",wanted_spec.size,wanted_spec.samples);
|
902 |
|
903 |
printf("freq:%d\n",spec.freq);
|
904 |
printf("format:%d\n",spec.format);
|
905 |
printf("channels:%d\n",spec.channels);
|
906 |
printf("silence:%d\n",spec.silence);
|
907 |
printf("samples:%d\n",spec.samples);
|
908 |
printf("size:%d\n",spec.size);
|
909 |
|
910 |
pFrame=avcodec_alloc_frame(); |
911 |
if(pFrame==NULL) { |
912 |
printf("Memory error!!!\n");
|
913 |
return -1; |
914 |
} |
915 |
outbuf_audio = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); |
916 |
|
917 |
strcpy(basereadfile,"chunks/");
|
918 |
|
919 |
packet_queue_init(&audioq,AUDIO); |
920 |
packet_queue_init(&videoq,VIDEO); |
921 |
SDL_WM_SetCaption("Filling buffer...", NULL); |
922 |
// Make a screen to put our video
|
923 |
#ifndef __DARWIN__
|
924 |
screen = SDL_SetVideoMode(width, height, 0, 0); |
925 |
#else
|
926 |
screen = SDL_SetVideoMode(width, height, 24, 0); |
927 |
#endif
|
928 |
if(!screen) {
|
929 |
fprintf(stderr, "SDL: could not set video mode - exiting\n");
|
930 |
exit(1);
|
931 |
} |
932 |
|
933 |
/*
|
934 |
// Initialize AntTweakBar
|
935 |
TwInit(TW_OPENGL, NULL);
|
936 |
// Tell the window size to AntTweakBar
|
937 |
TwWindowSize(width, height);
|
938 |
// Create a tweak bar
|
939 |
bar = TwNewBar("TweakBar");
|
940 |
// Add 'width' and 'height' to 'bar': they are read-only (RO) variables of type TW_TYPE_INT32.
|
941 |
TwAddVarRO(bar, "Width", TW_TYPE_INT32, &width, " label='Wnd width' help='Width of the graphics window (in pixels)' ");
|
942 |
*/
|
943 |
|
944 |
yuv_overlay = SDL_CreateYUVOverlay(width, height,SDL_YV12_OVERLAY, screen); |
945 |
|
946 |
if ( yuv_overlay == NULL ) { |
947 |
fprintf(stderr,"SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError());
|
948 |
exit(1);
|
949 |
} |
950 |
|
951 |
if ( yuv_overlay->hw_overlay )
|
952 |
fprintf(stderr,"SDL: Using hardware overlay.");
|
953 |
|
954 |
rect.x = 0;
|
955 |
rect.y = 0;
|
956 |
rect.w = width; |
957 |
rect.h = height; |
958 |
|
959 |
SDL_DisplayYUVOverlay(yuv_overlay, &rect); |
960 |
|
961 |
//signal (SIGINT, sigint_handler);
|
962 |
|
963 |
// Init audio and video buffers
|
964 |
av_init_packet(&AudioPkt); |
965 |
av_init_packet(&VideoPkt); |
966 |
AudioPkt.data=(uint8_t *)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); |
967 |
if(!AudioPkt.data) return 0; |
968 |
VideoPkt.data=(uint8_t *)malloc(width*height*3/2); |
969 |
if(!VideoPkt.data) return 0; |
970 |
|
971 |
|
972 |
SDL_PauseAudio(0);
|
973 |
video_thread = SDL_CreateThread(video_callback,tval); |
974 |
|
975 |
|
976 |
//lock = SDL_CreateMutex();
|
977 |
//SDL_WaitThread(exit_thread2,NULL);
|
978 |
|
979 |
|
980 |
|
981 |
daemon = initChunkPuller(); |
982 |
|
983 |
|
984 |
|
985 |
// Wait for user input
|
986 |
while(!quit)
|
987 |
{ |
988 |
if(QueueFillingMode)
|
989 |
SDL_WM_SetCaption("Filling buffer...", NULL); |
990 |
else
|
991 |
SDL_WM_SetCaption("NAPA-Wine Player", NULL); |
992 |
SDL_PollEvent(&event); |
993 |
switch(event.type) {
|
994 |
case SDL_QUIT:
|
995 |
//exit(0);
|
996 |
quit=1;
|
997 |
break;
|
998 |
} |
999 |
ProcessKeys(); |
1000 |
usleep(20000);
|
1001 |
} |
1002 |
// Stop audio&video playback
|
1003 |
|
1004 |
printf("1\n");
|
1005 |
SDL_WaitThread(video_thread,NULL);
|
1006 |
printf("2\n");
|
1007 |
SDL_PauseAudio(1);
|
1008 |
printf("3\n");
|
1009 |
SDL_CloseAudio(); |
1010 |
printf("4\n");
|
1011 |
SDL_Quit(); |
1012 |
|
1013 |
//SDL_DestroyMutex(lock);
|
1014 |
printf("5\n");
|
1015 |
av_free(aCodecCtx); |
1016 |
printf("6\n");
|
1017 |
free(AudioPkt.data); |
1018 |
printf("7\n");
|
1019 |
free(VideoPkt.data); |
1020 |
// free(namelist);
|
1021 |
printf("8\n");
|
1022 |
free(outbuf_audio); |
1023 |
|
1024 |
printf("9\n");
|
1025 |
finalizeChunkPuller(daemon); |
1026 |
printf("10\n");
|
1027 |
|
1028 |
return 0; |
1029 |
} |
1030 |
|
1031 |
|
1032 |
|
1033 |
int enqueueBlock(const uint8_t *block, const int block_size) { |
1034 |
Chunk *gchunk=NULL;
|
1035 |
ExternalChunk *echunk=NULL;
|
1036 |
uint8_t *tempdata, *buffer; |
1037 |
int i, j;
|
1038 |
Frame *frame=NULL;
|
1039 |
AVPacket packet, packetaudio; |
1040 |
|
1041 |
uint8_t *video_bufQ = NULL;
|
1042 |
uint16_t *audio_bufQ = NULL;
|
1043 |
//uint8_t audio_bufQ[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
|
1044 |
int16_t *dataQ; |
1045 |
int data_sizeQ;
|
1046 |
int lenQ;
|
1047 |
int sizeFrame = 0; |
1048 |
sizeFrame = 3*sizeof(int)+sizeof(struct timeval); |
1049 |
|
1050 |
audio_bufQ = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); |
1051 |
gchunk = (Chunk *)malloc(sizeof(Chunk));
|
1052 |
if(!gchunk) {
|
1053 |
printf("Memory error in gchunk!\n");
|
1054 |
return PLAYER_FAIL_RETURN;
|
1055 |
} |
1056 |
|
1057 |
decodeChunk(gchunk, block, block_size); |
1058 |
|
1059 |
echunk = grapesChunkToExternalChunk(gchunk); |
1060 |
if(echunk == NULL) { |
1061 |
printf("Memory error in echunk!\n");
|
1062 |
free(gchunk->attributes); |
1063 |
free(gchunk->data); |
1064 |
free(gchunk); |
1065 |
return PLAYER_FAIL_RETURN;
|
1066 |
} |
1067 |
free(gchunk->attributes); |
1068 |
free(gchunk); |
1069 |
|
1070 |
frame = (Frame *)malloc(sizeof(Frame));
|
1071 |
if(!frame) {
|
1072 |
printf("Memory error!\n");
|
1073 |
return -1; |
1074 |
} |
1075 |
|
1076 |
tempdata = echunk->data; |
1077 |
j=echunk->payload_len; |
1078 |
while(j>0 && !quit) { |
1079 |
//usleep(30000);
|
1080 |
frame->number = *((int *)tempdata);
|
1081 |
tempdata+=sizeof(int); |
1082 |
frame->timestamp = *((struct timeval *)tempdata);
|
1083 |
tempdata += sizeof(struct timeval); |
1084 |
frame->size = *((int *)tempdata);
|
1085 |
tempdata+=sizeof(int); |
1086 |
frame->type = *((int *)tempdata);
|
1087 |
tempdata+=sizeof(int); |
1088 |
|
1089 |
buffer = tempdata; // here coded frame information
|
1090 |
tempdata+=frame->size; |
1091 |
//printf("%d %d %d %d\n",frame->number,frame->timestamp.tv_usec,frame->size,frame->type);
|
1092 |
|
1093 |
if(frame->type!=5) { // video frame |
1094 |
av_init_packet(&packet); |
1095 |
video_bufQ = (uint8_t *)malloc(frame->size); //this gets freed at the time of packet_queue_get
|
1096 |
if(video_bufQ) {
|
1097 |
memcpy(video_bufQ, buffer, frame->size); |
1098 |
packet.data = video_bufQ; |
1099 |
packet.size = frame->size; |
1100 |
packet.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec; |
1101 |
packet.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec; |
1102 |
packet.stream_index = frame->number; // use of stream_index for number frame
|
1103 |
//packet.duration = frame->timestamp.tv_sec;
|
1104 |
packet_queue_put(&videoq,&packet); |
1105 |
#ifdef DEBUG_SOURCE
|
1106 |
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); |
1107 |
#endif
|
1108 |
} |
1109 |
} |
1110 |
else { // audio frame |
1111 |
av_init_packet(&packetaudio); |
1112 |
packetaudio.data = buffer; |
1113 |
packetaudio.size = frame->size; |
1114 |
|
1115 |
packetaudio.pts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec; |
1116 |
packetaudio.dts = frame->timestamp.tv_sec*(unsigned long long)1000+frame->timestamp.tv_usec; |
1117 |
//packetaudio.duration = frame->timestamp.tv_sec;
|
1118 |
packetaudio.stream_index = 1;
|
1119 |
packetaudio.flags = 1;
|
1120 |
packetaudio.pos = -1;
|
1121 |
packetaudio.convergence_duration = -1;
|
1122 |
|
1123 |
// insert the audio frame into the queue
|
1124 |
data_sizeQ = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
1125 |
lenQ = avcodec_decode_audio3(aCodecCtx, (int16_t *)audio_bufQ, &data_sizeQ, &packetaudio); |
1126 |
if(lenQ>0) |
1127 |
{ |
1128 |
// for freeing there is some memory still in tempdata to be freed
|
1129 |
dataQ = (int16_t *)malloc(data_sizeQ); //this gets freed at the time of packet_queue_get
|
1130 |
if(dataQ)
|
1131 |
{ |
1132 |
memcpy(dataQ,audio_bufQ,data_sizeQ); |
1133 |
packetaudio.data = (int8_t *)dataQ; |
1134 |
packetaudio.size = data_sizeQ; |
1135 |
packetaudio.stream_index = frame->number; // use of stream_index for number frame
|
1136 |
|
1137 |
packet_queue_put(&audioq,&packetaudio); |
1138 |
#ifdef DEBUG_SOURCE
|
1139 |
printf("SOURCE: Insert audio in queue pts=%lld\n",packetaudio.pts);
|
1140 |
#endif
|
1141 |
} |
1142 |
} |
1143 |
|
1144 |
} |
1145 |
j = j - sizeFrame - frame->size; |
1146 |
} |
1147 |
|
1148 |
|
1149 |
/*
|
1150 |
if(QueueFillingMode)
|
1151 |
SDL_WM_SetCaption("Filling buffer...", NULL);
|
1152 |
else
|
1153 |
SDL_WM_SetCaption("NAPA-Wine Player", NULL);
|
1154 |
SDL_PollEvent(&event);
|
1155 |
switch(event.type) {
|
1156 |
case SDL_QUIT:
|
1157 |
//exit(0);
|
1158 |
quit=1;
|
1159 |
break;
|
1160 |
}
|
1161 |
ProcessKeys();
|
1162 |
*/
|
1163 |
free(echunk->data); |
1164 |
free(echunk); |
1165 |
free(frame); |
1166 |
av_free(audio_bufQ); |
1167 |
} |