Statistics
| Branch: | Revision:

chunker-player / chunker_streamer / chunker_streamer.c @ b9477cd0

History | View | Annotate | Download (39.7 KB)

1
/*
2
 *  Copyright (c) 2009-2011 Carmelo Daniele, Dario Marchese, Diego Reforgiato, Giuseppe Tropea
3
 *  developed for the Napa-Wine EU project. See www.napa-wine.eu
4
 *
5
 *  This is free software; see lgpl-2.1.txt
6
 */
7

    
8
#include "chunker_streamer.h"
9
#include <signal.h>
10
#include <math.h>
11
#include <getopt.h>
12
#include <libswscale/swscale.h>
13

    
14
#define STREAMER_MAX(a,b) ((a>b)?(a):(b))
15
#define STREAMER_MIN(a,b) ((a<b)?(a):(b))
16

    
17
//#define DEBUG_AUDIO_FRAMES
18
//#define DEBUG_VIDEO_FRAMES
19
//#define DEBUG_CHUNKER
20
#define DEBUG_ANOMALIES
21
//~ #define DEBUG_TIMESTAMPING
22
#define GET_PSNR(x) ((x==0) ? 0 : (-10.0*log(x)/log(10)))
23

    
24
ChunkerMetadata *cmeta = NULL;
25
int seq_current_chunk = 1; //chunk numbering starts from 1; HINT do i need more bytes?
26

    
27
#define AUDIO_CHUNK 0
28
#define VIDEO_CHUNK 1
29

    
30
void SaveFrame(AVFrame *pFrame, int width, int height);
31
void SaveEncodedFrame(Frame* frame, uint8_t *video_outbuf);
32
int pushChunkTcp(ExternalChunk *echunk);
33
void initTCPPush(char* ip, int port);
34
int update_chunk(ExternalChunk *chunk, Frame *frame, uint8_t *outbuf);
35
void finalizeTCPChunkPusher();
36
void bit32_encoded_push(uint32_t v, uint8_t *p);
37

    
38
int video_record_count = 0;
39
int savedVideoFrames = 0;
40
long int firstSavedVideoFrame = 0;
41
int ChunkerStreamerTestMode = 0;
42

    
43
int pts_anomaly_threshold = 0;
44
int newtime_anomaly_threshold = 0;
45
bool timebank = false;
46
char *outside_world_url = NULL;
47

    
48
bool vcopy = false;
49

    
50
// Constant number of frames per chunk
51
int chunkFilledFramesStrategy(ExternalChunk *echunk, int chunkType)
52
{
53
#ifdef DEBUG_CHUNKER
54
        fprintf(stderr, "CHUNKER: check if frames num %d == %d in chunk %d\n", echunk->frames_num, cmeta->framesPerChunk[chunkType], echunk->seq);
55
#endif
56
        if(echunk->frames_num == cmeta->framesPerChunk[chunkType])
57
                return 1;
58

    
59
        return 0;
60
}
61

    
62
// Constant size. Note that for now each chunk will have a size just greater or equal than the required value
63
// It can be considered as constant size.
64
int chunkFilledSizeStrategy(ExternalChunk *echunk, int chunkType)
65
{
66
#ifdef DEBUG_CHUNKER
67
        fprintf(stderr, "CHUNKER: check if chunk size %d >= %d in chunk %d\n", echunk->payload_len, cmeta->targetChunkSize, echunk->seq);
68
#endif
69
        if(echunk->payload_len >= cmeta->targetChunkSize)
70
                return 1;
71
        
72
        return 0;
73
}
74

    
75
// Performace optimization.
76
// The chunkFilled function has been splitted into two functions (one for each strategy).
77
// Instead of continuously check the strategy flag (which is constant),
78
// we change the callback just once according to the current strategy (look at the switch statement in the main in which this function pointer is set)
79
int (*chunkFilled)(ExternalChunk *echunk, int chunkType);
80

    
81
void initChunk(ExternalChunk *chunk, int *seq_num) {
82
        chunk->seq = (*seq_num)++;
83
        chunk->frames_num = 0;
84
        chunk->payload_len = 0;
85
        chunk->len=0;
86
  if(chunk->data != NULL)
87
    free(chunk->data);
88
        chunk->data = NULL;
89
        chunk->start_time.tv_sec = -1;
90
        chunk->start_time.tv_usec = -1;
91
        chunk->end_time.tv_sec = -1;
92
        chunk->end_time.tv_usec = -1;
93
        chunk->priority = 0;
94
        chunk->category = 0;
95
        chunk->_refcnt = 0;
96
}
97

    
98
int quit = 0;
99

    
100
void sigproc()
101
{
102
        printf("you have pressed ctrl-c, terminating...\n");
103
        quit = 1;
104
}
105

    
106
static void print_usage(int argc, char *argv[])
107
{
108
  fprintf (stderr,
109
    "\nUsage:%s [options]\n"
110
    "\n"
111
    "Mandatory options:\n"
112
    "\t[-i input file]\n"
113
    "\t[-a audio bitrate]\n"
114
    "\t[-v video bitrate]\n\n"
115
    "Other options:\n"
116
    "\t[-F output] (overrides config file)\n"
117
    "\t[-A audioencoder]\n"
118
    "\t[-V videoencoder]\n"
119
    "\t[-s WxH]: force video size.\n"
120
    "\t[-l]: this is a live stream.\n"
121
    "\t[-o]: adjust av frames timestamps.\n"
122
    "\t[-t]: QoE test mode\n\n"
123
    "=======================================================\n", argv[0]
124
    );
125
  }
126

    
127
int sendChunk(ExternalChunk *chunk) {
128
#ifdef HTTPIO
129
                                                return pushChunkHttp(chunk, outside_world_url);
130
#endif
131
#ifdef TCPIO
132
                                                return pushChunkTcp(chunk);
133
#endif
134
#ifdef UDPIO
135
                                                return pushChunkUDP(chunk);
136
#endif
137
}
138

    
139
int main(int argc, char *argv[]) {
140
        signal(SIGINT, sigproc);
141
        
142
        int i=0;
143

    
144
        //output variables
145
        uint8_t *video_outbuf = NULL;
146
        int video_outbuf_size, video_frame_size;
147
        uint8_t *audio_outbuf = NULL;
148
        int audio_outbuf_size, audio_frame_size;
149
        int audio_data_size;
150

    
151
        //numeric identifiers of input streams
152
        int videoStream = -1;
153
        int audioStream = -1;
154

    
155
//        int len1;
156
        int frameFinished;
157
        //frame sequential counters
158
        int contFrameAudio=1, contFrameVideo=0;
159
//        int numBytes;
160

    
161
        //command line parameters
162
        int audio_bitrate = -1;
163
        int video_bitrate = -1;
164
        char *audio_codec = "mp2";
165
        char *video_codec = "mpeg4";
166
        int live_source = 0; //tells to sleep before reading next frame in not live (i.e. file)
167
        int offset_av = 0; //tells to compensate for offset between audio and video in the file
168
        
169
        //a raw buffer for decoded uncompressed audio samples
170
        int16_t *samples = NULL;
171
        //a raw uncompressed video picture
172
        AVFrame *pFrame = NULL;
173
        AVFrame *scaledFrame = NULL;
174

    
175
        AVFormatContext *pFormatCtx;
176
        AVCodecContext  *pCodecCtx = NULL ,*pCodecCtxEnc = NULL ,*aCodecCtxEnc = NULL ,*aCodecCtx = NULL;
177
        AVCodec         *pCodec = NULL ,*pCodecEnc = NULL ,*aCodec = NULL ,*aCodecEnc = NULL;
178
        AVPacket         packet;
179

    
180
        //stuff needed to compute the right timestamps
181
        short int FirstTimeAudio=1, FirstTimeVideo=1;
182
        short int pts_anomalies_counter=0;
183
        short int newtime_anomalies_counter=0;
184
        long long newTime=0, newTime_audio=0, newTime_video=0, newTime_prev=0;
185
        struct timeval lastAudioSent = {0, 0};
186
        double ptsvideo1=0.0;
187
        double ptsaudio1=0.0;
188
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
189

    
190
        //Napa-Wine specific Frame and Chunk structures for transport
191
        Frame *frame = NULL;
192
        ExternalChunk *chunk = NULL;
193
        ExternalChunk *chunkaudio = NULL;
194
        
195
        char av_input[1024];
196
        int dest_width = -1;
197
        int dest_height = -1;
198
        
199
        static struct option long_options[] =
200
        {
201
                /* These options set a flag. */
202
                {"long_option", required_argument, 0, 0},
203
                {0, 0, 0, 0}
204
        };
205
        /* `getopt_long' stores the option index here. */
206
        int option_index = 0, c;
207
        int mandatories = 0;
208
        while ((c = getopt_long (argc, argv, "i:a:v:A:V:s:lotF:", long_options, &option_index)) != -1)
209
        {
210
                switch (c) {
211
                        case 0: //for long options
212
                                break;
213
                        case 'i':
214
                                sprintf(av_input, "%s", optarg);
215
                                mandatories++;
216
                                break;
217
                        case 'a':
218
                                sscanf(optarg, "%d", &audio_bitrate);
219
                                mandatories++;
220
                                break;
221
                        case 'v':
222
                                sscanf(optarg, "%d", &video_bitrate);
223
                                mandatories++;
224
                                break;
225
                        case 'A':
226
                                audio_codec = strdup(optarg);
227
                                break;
228
                        case 'V':
229
                                video_codec = strdup(optarg);
230
                                break;
231
                        case 's':
232
                                sscanf(optarg, "%dx%d", &dest_width, &dest_height);
233
                                break;
234
                        case 'l':
235
                                live_source = 1;
236
                                break;
237
                        case 'o':
238
                                offset_av = 1;
239
                                break;
240
                        case 't':
241
                                ChunkerStreamerTestMode = 1;
242
                                break;
243
                        case 'F':
244
                                outside_world_url = strdup(optarg);
245
                                break;
246
                        default:
247
                                print_usage(argc, argv);
248
                                return -1;
249
                }
250
        }
251
        
252
        if(mandatories < 3) 
253
        {
254
                print_usage(argc, argv);
255
                return -1;
256
        }
257

    
258
#ifdef YUV_RECORD_ENABLED
259
        if(ChunkerStreamerTestMode)
260
        {
261
                DELETE_DIR("yuv_data");
262
                CREATE_DIR("yuv_data");
263
                //FILE* pFile=fopen("yuv_data/streamer_out.yuv", "w");
264
                //fclose(pFile);
265
        }
266
#endif
267

    
268
restart:
269
        // read the configuration file
270
        cmeta = chunkerInit();
271
        if (!outside_world_url) {
272
                outside_world_url = strdup(cmeta->outside_world_url);
273
        }
274
        switch(cmeta->strategy)
275
        {
276
                case 1:
277
                        chunkFilled = chunkFilledSizeStrategy;
278
                        break;
279
                default:
280
                        chunkFilled = chunkFilledFramesStrategy;
281
        }
282
                
283
        if(live_source)
284
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
285
        if(offset_av)
286
                fprintf(stderr, "INIT: Compensating AV OFFSET in file\n");
287

    
288
        // Register all formats and codecs
289
        av_register_all();
290

    
291
        // Open input file
292
        if(av_open_input_file(&pFormatCtx, av_input, NULL, 0, NULL) != 0) {
293
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
294
                exit(-1);
295
        }
296

    
297
        // Retrieve stream information
298
        if(av_find_stream_info(pFormatCtx) < 0) {
299
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
300
                exit(-1);
301
        }
302

    
303
        // Dump information about file onto standard error
304
        dump_format(pFormatCtx, 0, av_input, 0);
305

    
306
        // Find the video and audio stream numbers
307
        for(i=0; i<pFormatCtx->nb_streams; i++) {
308
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
309
                        videoStream=i;
310
                }
311
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
312
                        audioStream=i;
313
                }
314
        }
315
        fprintf(stderr, "INIT: Num streams : %d TBR: %d %d RFRAMERATE:%d %d Duration:%ld\n", pFormatCtx->nb_streams, pFormatCtx->streams[videoStream]->time_base.num, pFormatCtx->streams[videoStream]->time_base.den, pFormatCtx->streams[videoStream]->r_frame_rate.num, pFormatCtx->streams[videoStream]->r_frame_rate.den, pFormatCtx->streams[videoStream]->duration);
316

    
317
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
318
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
319

    
320
        if(videoStream==-1 && audioStream==-1) {
321
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
322
                exit(-1);
323
        }
324

    
325
        // Get a pointer to the codec context for the input video stream
326
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
327
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
328
        //extract W and H
329
        fprintf(stderr, "INIT: Width:%d Height:%d\n", pCodecCtx->width, pCodecCtx->height);
330

    
331
        // Get a pointer to the codec context for the input audio stream
332
        if(audioStream != -1) {
333
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
334
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
335
        }
336

    
337
        // Figure out size
338
        dest_width = (dest_width > 0) ? dest_width : pCodecCtx->width;
339
        dest_height = (dest_height > 0) ? dest_height : pCodecCtx->height;
340

    
341
        //setup video output encoder
342
 if (strcmp(video_codec, "copy") == 0) {
343
        vcopy = true;
344
 } else {
345
        pCodecEnc = avcodec_find_encoder_by_name(video_codec);
346
        if (pCodecEnc) {
347
                fprintf(stderr, "INIT: Setting VIDEO codecID to: %d\n",pCodecEnc->id);
348
        } else {
349
                fprintf(stderr, "INIT: Unknown OUT VIDEO codec: %s!\n", video_codec);
350
                return -1; // Codec not found
351
        }
352

    
353
        pCodecCtxEnc=avcodec_alloc_context();
354
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
355
        pCodecCtxEnc->codec_id = pCodecEnc->id;
356

    
357
        pCodecCtxEnc->bit_rate = video_bitrate;
358
        //~ pCodecCtxEnc->qmin = 30;
359
        //~ pCodecCtxEnc->qmax = 30;
360
        //times 20 follows the defaults, was not needed in previous versions of libavcodec
361
        pCodecCtxEnc->bit_rate_tolerance = video_bitrate*20;
362
//        pCodecCtxEnc->crf = 20.0f;
363
        // resolution must be a multiple of two 
364
        pCodecCtxEnc->width = dest_width;
365
        pCodecCtxEnc->height = dest_height;
366
        // frames per second 
367
        //~ pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
368
        //printf("pCodecCtx->time_base=%d/%d\n", pCodecCtx->time_base.num, pCodecCtx->time_base.den);
369
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
370
        pCodecCtxEnc->gop_size = 12; // emit one intra frame every twelve frames 
371
        pCodecCtxEnc->max_b_frames=1;
372
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
373
        pCodecCtxEnc->flags = CODEC_FLAG_PSNR;
374
        //~ pCodecCtxEnc->flags |= CODEC_FLAG_QSCALE;
375
  switch (pCodecEnc->id) {
376
    case CODEC_ID_H264 :
377
        pCodecCtxEnc->me_range=16;
378
        pCodecCtxEnc->max_qdiff=4;
379
        pCodecCtxEnc->qmin=1;
380
        pCodecCtxEnc->qmax=30;
381
        pCodecCtxEnc->qcompress=0.6;
382
        // frames per second 
383

    
384
//        pCodecCtxEnc->rc_min_rate = 0;
385
//        pCodecCtxEnc->rc_max_rate = 0;
386
//        pCodecCtxEnc->rc_buffer_size = 0;
387
//        pCodecCtxEnc->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
388
//        pCodecCtxEnc->crf = 0.0f;
389
        
390
#ifdef STREAMER_X264_USE_SSIM
391
        pCodecCtxEnc->flags2 |= CODEC_FLAG2_SSIM;
392
#endif
393

    
394
        pCodecCtxEnc->weighted_p_pred=2; //maps wpredp=2; weighted prediction analysis method
395
        // pCodecCtxEnc->rc_min_rate = 0;
396
        // pCodecCtxEnc->rc_max_rate = video_bitrate*2;
397
        // pCodecCtxEnc->rc_buffer_size = 0;
398
        break;
399
    case CODEC_ID_MPEG4 :
400
        break;
401
    default:
402
        fprintf(stderr, "INIT: Unsupported OUT VIDEO codec: %s!\n", video_codec);
403
  }
404
 
405
        fprintf(stderr, "INIT: VIDEO timebase OUT:%d %d IN: %d %d\n", pCodecCtxEnc->time_base.num, pCodecCtxEnc->time_base.den, pCodecCtx->time_base.num, pCodecCtx->time_base.den);
406
 }
407

    
408
        if(pCodec==NULL) {
409
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
410
                return -1; // Codec not found
411
        }
412
        if(!vcopy && pCodecEnc==NULL) {
413
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
414
                return -1; // Codec not found
415
        }
416
        if(avcodec_open(pCodecCtx, pCodec)<0) {
417
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
418
                return -1; // Could not open codec
419
        }
420
        if(!vcopy && avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
421
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
422
                return -1; // Could not open codec
423
        }
424
        if(audioStream!=-1) {
425
                //setup audio output encoder
426
                aCodecCtxEnc = avcodec_alloc_context();
427
                aCodecCtxEnc->bit_rate = audio_bitrate; //256000
428
                aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
429
                aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
430
                aCodecCtxEnc->channels = aCodecCtx->channels;
431
                fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
432

    
433
                // Find the decoder for the audio stream
434
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
435
                aCodecEnc = avcodec_find_encoder_by_name(audio_codec);
436
                if(aCodec==NULL) {
437
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
438
                        return -1;
439
                }
440
                if(aCodecEnc==NULL) {
441
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
442
                        return -1;
443
                }
444
        
445
                if(avcodec_open(aCodecCtx, aCodec)<0) {
446
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
447
                        return -1; // Could not open codec
448
                }
449
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
450
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
451
                        return -1; // Could not open codec
452
                }
453
        }
454
        else {
455
                fprintf(stderr,"INIT: NO AUDIO TRACK IN INPUT FILE\n");
456
        }
457

    
458
        // Allocate audio in and out buffers
459
        samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
460
        if(samples == NULL) {
461
                fprintf(stderr, "INIT: Memory error alloc audio samples!!!\n");
462
                return -1;
463
        }
464
        audio_outbuf_size = STREAMER_MAX_AUDIO_BUFFER_SIZE;
465
        audio_outbuf = av_malloc(audio_outbuf_size);
466
        if(audio_outbuf == NULL) {
467
                fprintf(stderr, "INIT: Memory error alloc audio_outbuf!!!\n");
468
                return -1;
469
        }
470

    
471
        // Allocate video in frame and out buffer
472
        pFrame=avcodec_alloc_frame();
473
        scaledFrame=avcodec_alloc_frame();
474
        if(pFrame==NULL || scaledFrame == NULL) {
475
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
476
                return -1;
477
        }
478
        video_outbuf_size = STREAMER_MAX_VIDEO_BUFFER_SIZE;
479
        video_outbuf = av_malloc(video_outbuf_size);
480
        int scaledFrame_buf_size = avpicture_get_size( PIX_FMT_YUV420P, dest_width, dest_height);
481
        uint8_t* scaledFrame_buffer = (uint8_t *) av_malloc( scaledFrame_buf_size * sizeof( uint8_t ) );
482
        avpicture_fill( (AVPicture*) scaledFrame, scaledFrame_buffer, PIX_FMT_YUV420P, dest_width, dest_height);
483
        if(!video_outbuf || !scaledFrame_buffer) {
484
                fprintf(stderr, "INIT: Memory error alloc video_outbuf!!!\n");
485
                return -1;
486
        }
487

    
488
        //allocate Napa-Wine transport
489
        frame = (Frame *)malloc(sizeof(Frame));
490
        if(!frame) {
491
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
492
                return -1;
493
        }
494
        //create an empty first video chunk
495
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
496
        if(!chunk) {
497
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
498
                return -1;
499
        }
500
        chunk->data = NULL;
501
        chunk->seq = 0;
502
        //initChunk(chunk, &seq_current_chunk); if i init them now i get out of sequence
503
#ifdef DEBUG_CHUNKER
504
        fprintf(stderr, "INIT: chunk video %d\n", chunk->seq);
505
#endif
506
        //create empty first audio chunk
507
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
508
        if(!chunkaudio) {
509
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
510
                return -1;
511
        }
512
  chunkaudio->data=NULL;
513
        chunkaudio->seq = 0;
514
        //initChunk(chunkaudio, &seq_current_chunk);
515
#ifdef DEBUG_CHUNKER
516
        fprintf(stderr, "INIT: chunk audio %d\n", chunkaudio->seq);
517
#endif
518

    
519
#ifdef HTTPIO
520
        /* initialize the HTTP chunk pusher */
521
        initChunkPusher(); //TRIPLO
522
#endif
523

    
524
        long sleep=0;
525
        struct timeval now_tv;
526
        struct timeval tmp_tv;
527
        long long lateTime = 0;
528
        long long maxAudioInterval = 0;
529
        long long maxVDecodeTime = 0;
530
//        unsigned char lastIFrameDistance = 0;
531

    
532
#ifdef TCPIO
533
        static char peer_ip[16];
534
        static int peer_port;
535
        int res = sscanf(outside_world_url, "tcp://%15[0-9.]:%d", peer_ip, &peer_port);
536
        if (res < 2) {
537
                fprintf(stderr,"error parsing output url: %s\n", outside_world_url);
538
                return -2;
539
        }
540
        
541
        initTCPPush(peer_ip, peer_port);
542
#endif
543
#ifdef UDPIO
544
        static char peer_ip[16];
545
        static int peer_port;
546
        int res = sscanf(outside_world_url, "udp://%15[0-9.]:%d", peer_ip, &peer_port);
547
        if (res < 2) {
548
                fprintf(stderr,"error parsing output url: %s\n", outside_world_url);
549
                return -2;
550
        }
551
        
552
        initUDPPush(peer_ip, peer_port);
553
#endif
554
        
555
        char videotrace_filename[255];
556
        char psnr_filename[255];
557
        sprintf(videotrace_filename, "yuv_data/videotrace.log");
558
        sprintf(psnr_filename, "yuv_data/psnrtrace.log");
559
        FILE* videotrace = fopen(videotrace_filename, "w");
560
        FILE* psnrtrace = fopen(psnr_filename, "w");
561

    
562
        //main loop to read from the input file
563
        while((av_read_frame(pFormatCtx, &packet)>=0) && !quit)
564
        {
565
                //detect if a strange number of anomalies is occurring
566
                if(ptsvideo1 < 0 || ptsvideo1 > packet.dts || ptsaudio1 < 0 || ptsaudio1 > packet.dts) {
567
                        pts_anomalies_counter++;
568
#ifdef DEBUG_ANOMALIES
569
                        fprintf(stderr, "READLOOP: pts BASE anomaly detected number %d\n", pts_anomalies_counter);
570
#endif
571
                        if(live_source) { //reset just in case of live source
572
                                if(pts_anomalies_counter > pts_anomaly_threshold) {
573
                                        pts_anomalies_counter = 0;
574
                                        FirstTimeVideo = 1;
575
                                        FirstTimeAudio = 1;
576
#ifdef DEBUG_ANOMALIES
577
                                        fprintf(stderr, "READLOOP: too many pts BASE anomalies. resetting pts base\n");
578
#endif
579
                                }
580
                        }
581
                }
582

    
583
                //newTime_video and _audio are in usec
584
                //if video and audio stamps differ more than 5sec
585
                if( newTime_video - newTime_audio > 5000000 || newTime_video - newTime_audio < -5000000 ) {
586
                        newtime_anomalies_counter++;
587
#ifdef DEBUG_ANOMALIES
588
                        fprintf(stderr, "READLOOP: NEWTIME audio video differ anomaly detected number %d\n", newtime_anomalies_counter);
589
#endif
590
                }
591

    
592
                if(newtime_anomalies_counter > newtime_anomaly_threshold) {
593
                        if(live_source) { //restart just in case of live source
594
#ifdef DEBUG_ANOMALIES
595
                                fprintf(stderr, "READLOOP: too many NEGATIVE TIMESTAMPS anomalies. Restarting.\n");
596
#endif
597
                                goto close;
598
                        }
599
                }
600

    
601
                // Is this a packet from the video stream?
602
                if(packet.stream_index==videoStream)
603
                {
604
                        if(!live_source)
605
                        {
606
                                if(audioStream != -1) { //take this "time bank" method into account only if we have audio track
607
                                        // lateTime < 0 means a positive time account that can be used to decode video frames
608
                                        // if (lateTime + maxVDecodeTime) >= 0 then we may have a negative time account after video transcoding
609
                                        // therefore, it's better to skip the frame
610
                                        if(timebank && (lateTime+maxVDecodeTime) >= 0)
611
                                        {
612
#ifdef DEBUG_ANOMALIES
613
                                                fprintf(stderr, "\n\n\t\t************************* SKIPPING VIDEO FRAME %ld ***********************************\n\n", sleep);
614
#endif
615
                                                continue;
616
                                        }
617
                                }
618
                        }
619
                        
620
                        gettimeofday(&tmp_tv, NULL);
621
                        
622
                        //decode the video packet into a raw pFrame
623
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0)
624
                        {
625
                                // usleep(5000);
626
#ifdef DEBUG_VIDEO_FRAMES
627
                                fprintf(stderr, "\n-------VIDEO FRAME type %d\n", pFrame->pict_type);
628
                                fprintf(stderr, "VIDEO: dts %lld pts %lld\n", packet.dts, packet.pts);
629
#endif
630
                                if(frameFinished)
631
                                { // it must be true all the time else error
632
                                
633
                                        frame->number = ++contFrameVideo;
634

    
635
#ifdef VIDEO_DEINTERLACE
636
                                if (!vcopy) {
637
                                        avpicture_deinterlace(
638
                                                (AVPicture*) pFrame,
639
                                                (const AVPicture*) pFrame,
640
                                                pCodecCtxEnc->pix_fmt,
641
                                                pCodecCtxEnc->width,
642
                                                pCodecCtxEnc->height);
643
                                }
644
#endif
645

    
646
#ifdef DEBUG_VIDEO_FRAMES
647
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
648
#endif
649
                                        if(frame->number==0) {
650
                                                if(packet.dts==AV_NOPTS_VALUE)
651
                                                {
652
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
653
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
654
                                                        continue;
655
                                                }
656
                                                last_pkt_dts = packet.dts;
657
                                                newTime = 0;
658
                                        }
659
                                        else {
660
                                                if(packet.dts!=AV_NOPTS_VALUE) {
661
                                                        delta_video = packet.dts-last_pkt_dts;
662
                                                        last_pkt_dts = packet.dts;
663
                                                }
664
                                                else if(delta_video==0)
665
                                                {
666
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
667
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
668
                                                        continue;
669
                                                }
670
                                        }
671
#ifdef DEBUG_VIDEO_FRAMES
672
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
673
#endif
674

    
675
                                        if(vcopy) {
676
                                                video_frame_size = packet.size;
677
                                                if (video_frame_size > video_outbuf_size) {
678
                                                        fprintf(stderr, "VIDEO: error, outbuf too small, SKIPPING\n");;
679
                                                        continue;
680
                                                } else {
681
                                                        memcpy(video_outbuf, packet.data, video_frame_size);
682
                                                }
683
                                        } else if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width) {
684
//                                                static AVPicture pict;
685
                                                static struct SwsContext *img_convert_ctx = NULL;
686
                                                
687
                                                if(img_convert_ctx == NULL)
688
                                                {
689
                                                        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, dest_width, dest_height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
690
                                                        if(img_convert_ctx == NULL) {
691
                                                                fprintf(stderr, "Cannot initialize the conversion context!\n");
692
                                                                exit(1);
693
                                                        }
694
                                                }
695
                                                sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, scaledFrame->data, scaledFrame->linesize);
696
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, scaledFrame);
697
                                        }
698
                                        else
699
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, pFrame);
700
                                        
701
                                        if(video_frame_size <= 0)
702
                                        {
703
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
704
                                                continue;
705
                                        }
706

    
707
#ifdef DEBUG_VIDEO_FRAMES
708
                                        if(!vcopy && pCodecCtxEnc->coded_frame) {
709
                                                fprintf(stderr, "\n-------VIDEO FRAME intype %d%s -> outtype: %d%s\n",
710
                                                        pFrame->pict_type, pFrame->key_frame ? " (key)" : "",
711
                                                        pCodecCtxEnc->coded_frame->pict_type, pCodecCtxEnc->coded_frame->key_frame ? " (key)" : "");
712
                                        }
713
#endif
714

    
715
                                        //use pts if dts is invalid
716
                                        if(packet.dts!=AV_NOPTS_VALUE)
717
                                                target_pts = packet.dts;
718
                                        else if(packet.pts!=AV_NOPTS_VALUE)
719
                                                target_pts = packet.pts;
720
                                        else
721
                                        {
722
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
723
                                                continue;
724
                                        }
725

    
726
                                        if(!offset_av)
727
                                        {
728
                                                if(FirstTimeVideo && packet.dts>0) {
729
                                                        ptsvideo1 = (double)packet.dts;
730
                                                        FirstTimeVideo = 0;
731
#ifdef DEBUG_VIDEO_FRAMES
732
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %f\n", ptsvideo1);
733
#endif
734
                                                }
735
                                        }
736
                                        else //we want to compensate audio and video offset for this source
737
                                        {
738
                                                if(FirstTimeVideo && packet.dts>0) {
739
                                                        //maintain the offset between audio pts and video pts
740
                                                        //because in case of live source they have the same numbering
741
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
742
                                                                ptsvideo1 = ptsaudio1;
743
                                                        else
744
                                                                ptsvideo1 = (double)packet.dts;
745
                                                        FirstTimeVideo = 0;
746
#ifdef DEBUG_VIDEO_FRAMES
747
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %f\n", ptsvideo1);
748
#endif
749
                                                }
750
                                        }
751
                                        //compute the new video timestamp in milliseconds
752
                                        if(frame->number>0) {
753
                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
754
                                                // store timestamp in useconds for next frame sleep
755
                                                newTime_video = newTime*1000;
756
                                        }
757
#ifdef DEBUG_TIMESTAMPING
758
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
759
#endif
760
                                        if(newTime<0) {
761
#ifdef DEBUG_VIDEO_FRAMES
762
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
763
#endif
764
                                                newtime_anomalies_counter++;
765
#ifdef DEBUG_ANOMALIES
766
                                                fprintf(stderr, "READLOOP: NEWTIME negative video timestamp anomaly detected number %d\n", newtime_anomalies_counter);
767
#endif
768
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
769
                                                continue; //SKIP THIS FRAME, bad timestamp
770
                                        }
771
                                        
772
                                        //~ printf("pCodecCtxEnc->error[0]=%lld\n", pFrame->error[0]);
773
        
774
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
775
                                        frame->timestamp.tv_usec = newTime%1000;
776
                                        frame->size = video_frame_size;
777
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
778
                                        frame->type = vcopy ? pFrame->pict_type : (unsigned char)pCodecCtxEnc->coded_frame->pict_type;
779

    
780
#ifdef DEBUG_VIDEO_FRAMES
781
                                        if (!vcopy) fprintf(stderr, "VIDEO: original codec frame number %d vs. encoded %d vs. packed %d\n", pCodecCtx->frame_number, pCodecCtxEnc->frame_number, frame->number);
782
                                        if (!vcopy) fprintf(stderr, "VIDEO: duration %d timebase %d %d container timebase %d\n", (int)packet.duration, pCodecCtxEnc->time_base.den, pCodecCtxEnc->time_base.num, pCodecCtx->time_base.den);
783
#endif
784

    
785
#ifdef YUV_RECORD_ENABLED
786
                                        if(!vcopy && ChunkerStreamerTestMode)
787
                                        {
788
                                                if(videotrace)
789
                                                        fprintf(videotrace, "%d %d %d\n", frame->number, pFrame->pict_type, frame->size);
790

    
791
                                                if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width)
792
                                                        SaveFrame(scaledFrame, dest_width, dest_height);
793
                                                else
794
                                                        SaveFrame(pFrame, dest_width, dest_height);
795

    
796
                                                ++savedVideoFrames;
797
                                                SaveEncodedFrame(frame, video_outbuf);
798

    
799
                                                if(!firstSavedVideoFrame)
800
                                                        firstSavedVideoFrame = frame->number;
801
                                                
802
                                                char tmp_filename[255];
803
                                                sprintf(tmp_filename, "yuv_data/streamer_out_context.txt");
804
                                                FILE* tmp = fopen(tmp_filename, "w");
805
                                                if(tmp)
806
                                                {
807
                                                        fprintf(tmp, "width = %d\nheight = %d\ntotal_frames_saved = %d\ntotal_frames_decoded = %d\nfirst_frame_number = %ld\nlast_frame_number = %d\n"
808
                                                                ,dest_width, dest_height
809
                                                                ,savedVideoFrames, savedVideoFrames, firstSavedVideoFrame, frame->number);
810
                                                        fclose(tmp);
811
                                                }
812
                                        }
813
#endif
814

    
815
#ifdef DEBUG_VIDEO_FRAMES
816
                                        fprintf(stderr, "VIDEO: encapsulated frame size:%d type:%d\n", frame->size, frame->type);
817
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
818
#endif
819
                                        //contFrameVideo++; //lets increase the numbering of the frames
820

    
821
                                        if(update_chunk(chunk, frame, video_outbuf) == -1) {
822
                                                fprintf(stderr, "VIDEO: unable to update chunk %d. Exiting.\n", chunk->seq);
823
                                                exit(-1);
824
                                        }
825

    
826
                                        if(chunkFilled(chunk, VIDEO_CHUNK)) { // is chunk filled using current strategy?
827
                                                //SAVE ON FILE
828
                                                //saveChunkOnFile(chunk);
829
                                                //Send the chunk to an external transport/player
830
                                                sendChunk(chunk);
831
#ifdef DEBUG_CHUNKER
832
                                                fprintf(stderr, "VIDEO: sent chunk video %d\n", chunk->seq);
833
#endif
834
                                                chunk->seq = 0; //signal that we need an increase
835
                                                //initChunk(chunk, &seq_current_chunk);
836
                                        }
837

    
838
                                        //compute how long it took to encode video frame
839
                                        gettimeofday(&now_tv, NULL);
840
                                        long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
841
                                        usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
842
                                        if(usec > maxVDecodeTime)
843
                                                maxVDecodeTime = usec;
844

    
845
                                        //we DONT have an audio track, so we compute timings and determine
846
                                        //how much time we have to sleep at next VIDEO frame taking
847
                                        //also into account how much time was needed to encode the current
848
                                        //video frame
849
                                        //all this in case the video source is not live, i.e. not self-timing
850
                                        //and only in case there is no audio track
851
                                        if(audioStream == -1) {
852
                                                if(!live_source) {
853
                                                        if(newTime_prev != 0) {
854
                                                                //how much delay between video frames ideally
855
                                                                long long maxDelay = newTime_video - newTime_prev;
856
                                                                sleep = (maxDelay - usec);
857
#ifdef DEBUG_ANOMALIES
858
                                                                printf("\tmaxDelay=%ld\n", ((long)maxDelay));
859
                                                                printf("\tlast video frame interval=%ld; sleep time=%ld\n", ((long)usec), ((long)sleep));
860
#endif
861
                                                        }
862
                                                        else
863
                                                                sleep = 0;
864

    
865
                                                        //update and store counters
866
                                                        newTime_prev = newTime_video;
867

    
868
                                                        //i can also sleep now instead of at the beginning of
869
                                                        //the next frame because in this case we only have video
870
                                                        //frames, hence it would immediately be the next thing to do
871
                                                        if(sleep > 0) {
872
#ifdef DEBUG_ANOMALIES
873
                                                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
874
#endif
875
                                                                usleep(sleep);
876
                                                        }
877

    
878
                                                }
879
                                        }
880

    
881
                                }
882
                        }
883
                }
884
                else if(packet.stream_index==audioStream)
885
                {
886
                        if(sleep > 0)
887
                        {
888
#ifdef DEBUG_ANOMALIES
889
                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
890
#endif
891
                                usleep(sleep);
892
                        }
893
                        
894
                        audio_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
895
                        //decode the audio packet into a raw audio source buffer
896
                        if(avcodec_decode_audio3(aCodecCtx, samples, &audio_data_size, &packet)>0)
897
                        {
898
#ifdef DEBUG_AUDIO_FRAMES
899
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
900
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
901
#endif
902
                                if(audio_data_size>0) {
903
#ifdef DEBUG_AUDIO_FRAMES
904
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", audio_data_size);
905
#endif
906
                                        /* if a frame has been decoded, output it */
907
                                        //fwrite(samples, 1, audio_data_size, outfileaudio);
908
                                }
909
                                else
910
                                        continue;
911
        
912
                                audio_frame_size = avcodec_encode_audio(aCodecCtxEnc, audio_outbuf, audio_data_size, samples);
913
                                if(audio_frame_size <= 0)
914
                                        continue;
915
                                
916
                                frame->number = contFrameAudio;
917

    
918
                                if(frame->number==0) {
919
                                        if(packet.dts==AV_NOPTS_VALUE)
920
                                                continue;
921
                                        last_pkt_dts_audio = packet.dts;
922
                                        newTime = 0;
923
                                }
924
                                else {
925
                                        if(packet.dts!=AV_NOPTS_VALUE) {
926
                                                delta_audio = packet.dts-last_pkt_dts_audio;
927
                                                last_pkt_dts_audio = packet.dts;
928
                                        }
929
                                        else if(delta_audio==0)
930
                                                continue;
931
                                }
932
#ifdef DEBUG_AUDIO_FRAMES
933
                                fprintf(stderr, "AUDIO: original codec frame number %d vs. encoded %d vs. packed %d\n", aCodecCtx->frame_number, aCodecCtxEnc->frame_number, frame->number);
934
#endif
935
                                //use pts if dts is invalid
936
                                if(packet.dts!=AV_NOPTS_VALUE)
937
                                        target_pts = packet.dts;
938
                                else if(packet.pts!=AV_NOPTS_VALUE)
939
                                        target_pts = packet.pts;
940
                                else
941
                                        continue;
942

    
943
                                if(!offset_av)
944
                                {
945
                                        if(FirstTimeAudio && packet.dts>0) {
946
                                                ptsaudio1 = (double)packet.dts;
947
                                                FirstTimeAudio = 0;
948
#ifdef DEBUG_AUDIO_FRAMES
949
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %f\n", ptsaudio1);
950
#endif
951
                                        }
952
                                }
953
                                else //we want to compensate audio and video offset for this source
954
                                {
955
                                        if(FirstTimeAudio && packet.dts>0) {
956
                                                //maintain the offset between audio pts and video pts
957
                                                //because in case of live source they have the same numbering
958
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
959
                                                        ptsaudio1 = ptsvideo1;
960
                                                else
961
                                                        ptsaudio1 = (double)packet.dts;
962
                                                FirstTimeAudio = 0;
963
#ifdef DEBUG_AUDIO_FRAMES
964
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
965
#endif
966
                                        }
967
                                }
968
                                //compute the new audio timestamps in milliseconds
969
                                if(frame->number>0) {
970
                                        newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
971
                                        // store timestamp in useconds for next frame sleep
972
                                        newTime_audio = newTime*1000;
973
                                }
974
#ifdef DEBUG_TIMESTAMPING
975
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
976
#endif
977
                                if(newTime<0) {
978
#ifdef DEBUG_AUDIO_FRAMES
979
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
980
#endif
981
                                        newtime_anomalies_counter++;
982
#ifdef DEBUG_ANOMALIES
983
                                        fprintf(stderr, "READLOOP: NEWTIME negative audio timestamp anomaly detected number %d\n", newtime_anomalies_counter);
984
#endif
985
                                        continue; //SKIP THIS FRAME, bad timestamp
986
                                }
987

    
988
                                frame->timestamp.tv_sec = (unsigned int)newTime/1000;
989
                                frame->timestamp.tv_usec = newTime%1000;
990
                                frame->size = audio_frame_size;
991
                                frame->type = 5; // 5 is audio type
992
#ifdef DEBUG_AUDIO_FRAMES
993
                                fprintf(stderr, "AUDIO: pts %d duration %d timebase %d %d dts %d\n", (int)packet.pts, (int)packet.duration, pFormatCtx->streams[audioStream]->time_base.num, pFormatCtx->streams[audioStream]->time_base.den, (int)packet.dts);
994
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
995
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
996
#endif
997
                                contFrameAudio++;
998

    
999
                                if(update_chunk(chunkaudio, frame, audio_outbuf) == -1) {
1000
                                        fprintf(stderr, "AUDIO: unable to update chunk %d. Exiting.\n", chunkaudio->seq);
1001
                                        exit(-1);
1002
                                }
1003
                                //set priority
1004
                                chunkaudio->priority = 1;
1005

    
1006
                                if(chunkFilled(chunkaudio, AUDIO_CHUNK)) {
1007
                                        // is chunk filled using current strategy?
1008
                                        //SAVE ON FILE
1009
                                        //saveChunkOnFile(chunkaudio);
1010
                                        //Send the chunk to an external transport/player
1011
                                        sendChunk(chunkaudio);
1012
#ifdef DEBUG_CHUNKER
1013
                                        fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
1014
#endif
1015
                                        chunkaudio->seq = 0; //signal that we need an increase
1016
                                        //initChunk(chunkaudio, &seq_current_chunk);
1017
                                }
1018

    
1019
                                //we have an audio track, so we compute timings and determine
1020
                                //how much time we have to sleep at next audio frame taking
1021
                                //also into account how much time was needed to encode the
1022
                                //video frames
1023
                                //all this in case the video source is not live, i.e. not self-timing
1024
                                if(!live_source)
1025
                                {
1026
                                        if(newTime_prev != 0)
1027
                                        {
1028
                                                long long maxDelay = newTime_audio - newTime_prev;
1029

    
1030
                                                gettimeofday(&now_tv, NULL);
1031
                                                long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
1032
                                                usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
1033

    
1034
                                                if(usec > maxAudioInterval)
1035
                                                        maxAudioInterval = usec;
1036

    
1037
                                                lateTime -= (maxDelay - usec);
1038
#ifdef DEBUG_ANOMALIES
1039
                                                printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
1040
                                                printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
1041
#endif
1042

    
1043
                                                if((lateTime+maxAudioInterval) < 0)
1044
                                                        sleep = (lateTime+maxAudioInterval)*-1;
1045
                                                else
1046
                                                        sleep = 0;
1047
                                        }
1048
                                        else
1049
                                                sleep = 0;
1050

    
1051
                                        newTime_prev = newTime_audio;
1052
                                        gettimeofday(&lastAudioSent, NULL);
1053
                                }
1054
                        }
1055
                }
1056
                else {
1057
#ifdef DEBUG_CHUNKER
1058
                        fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
1059
#endif
1060
                        av_free_packet(&packet);
1061
                }
1062
        }
1063
        
1064
        if(videotrace)
1065
                fclose(videotrace);
1066
        if(psnrtrace)
1067
                fclose(psnrtrace);
1068

    
1069
close:
1070
        if(chunk->seq != 0 && chunk->frames_num>0) {
1071
                //SAVE ON FILE
1072
                //saveChunkOnFile(chunk);
1073
                //Send the chunk to an external transport/player
1074
                sendChunk(chunk);
1075
#ifdef DEBUG_CHUNKER
1076
                fprintf(stderr, "CHUNKER: SENDING LAST VIDEO CHUNK\n");
1077
#endif
1078
                chunk->seq = 0; //signal that we need an increase just in case we will restart
1079
        }
1080
        if(chunkaudio->seq != 0 && chunkaudio->frames_num>0) {
1081
                //SAVE ON FILE     
1082
                //saveChunkOnFile(chunkaudio);
1083
                //Send the chunk via http to an external transport/player
1084
                sendChunk(chunkaudio);
1085
#ifdef DEBUG_CHUNKER
1086
                fprintf(stderr, "CHUNKER: SENDING LAST AUDIO CHUNK\n");
1087
#endif
1088
                chunkaudio->seq = 0; //signal that we need an increase just in case we will restart
1089
        }
1090

    
1091
#ifdef HTTPIO
1092
        /* finalize the HTTP chunk pusher */
1093
        finalizeChunkPusher();
1094
#elif TCPIO
1095
        finalizeTCPChunkPusher();
1096
#endif
1097

    
1098
        free(chunk);
1099
        free(chunkaudio);
1100
        free(frame);
1101
        av_free(video_outbuf);
1102
        av_free(scaledFrame_buffer);
1103
        av_free(audio_outbuf);
1104
        free(cmeta);
1105

    
1106
        // Free the YUV frame
1107
        av_free(pFrame);
1108
        av_free(scaledFrame);
1109
        av_free(samples);
1110
  
1111
        // Close the codec
1112
        if (!vcopy) avcodec_close(pCodecCtx);
1113
        if (!vcopy) avcodec_close(pCodecCtxEnc);
1114

    
1115
        if(audioStream!=-1) {
1116
                avcodec_close(aCodecCtx);
1117
                avcodec_close(aCodecCtxEnc);
1118
        }
1119
  
1120
        // Close the video file
1121
        av_close_input_file(pFormatCtx);
1122

    
1123
        if(LOOP_MODE) {
1124
                //we want video to continue, but the av_read_frame stopped
1125
                //lets wait a 5 secs, and cycle in again
1126
                usleep(5000000);
1127
#ifdef DEBUG_CHUNKER
1128
                fprintf(stderr, "CHUNKER: WAITING 5 secs FOR LIVE SOURCE TO SKIP ERRORS AND RESTARTING\n");
1129
#endif
1130
                videoStream = -1;
1131
                audioStream = -1;
1132
                FirstTimeAudio=1;
1133
                FirstTimeVideo=1;
1134
                pts_anomalies_counter=0;
1135
                newtime_anomalies_counter=0;
1136
                newTime=0;
1137
                newTime_audio=0;
1138
                newTime_prev=0;
1139
                ptsvideo1=0.0;
1140
                ptsaudio1=0.0;
1141
                last_pkt_dts=0;
1142
                delta_video=0;
1143
                delta_audio=0;
1144
                last_pkt_dts_audio=0;
1145
                target_pts=0;
1146
                i=0;
1147
                //~ contFrameVideo = 0;
1148
                //~ contFrameAudio = 1;
1149
                
1150
#ifdef YUV_RECORD_ENABLED
1151
                if(ChunkerStreamerTestMode)
1152
                {
1153
                        video_record_count++;
1154
                        //~ savedVideoFrames = 0;
1155
                        
1156
                        //~ char tmp_filename[255];
1157
                        //~ sprintf(tmp_filename, "yuv_data/out_%d.yuv", video_record_count);
1158
                        //~ FILE *pFile=fopen(tmp_filename, "w");
1159
                        //~ if(pFile!=NULL)
1160
                                //~ fclose(pFile);
1161
                }
1162
#endif
1163

    
1164
                goto restart;
1165
        }
1166

    
1167
        return 0;
1168
}
1169

    
1170
int update_chunk(ExternalChunk *chunk, Frame *frame, uint8_t *outbuf) {
1171
        //the frame.h gets encoded into 5 slots of 32bits (3 ints plus 2 more for the timeval struct
1172
        static int sizeFrameHeader = 5*sizeof(int32_t);
1173

    
1174
        //moving temp pointer to encode Frame on the wire
1175
        uint8_t *tempdata = NULL;
1176

    
1177
        if(chunk->seq == 0) {
1178
                initChunk(chunk, &seq_current_chunk);
1179
        }
1180
        //HINT on malloc
1181
        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len + frame->size + sizeFrameHeader));
1182
        if(!chunk->data)  {
1183
                fprintf(stderr, "Memory error in chunk!!!\n");
1184
                return -1;
1185
        }
1186
        chunk->frames_num++; // number of frames in the current chunk
1187

    
1188
/*
1189
        //package the Frame header
1190
        tempdata = chunk->data+chunk->payload_len;
1191
        *((int32_t *)tempdata) = frame->number;
1192
        tempdata+=sizeof(int32_t);
1193
        *((struct timeval *)tempdata) = frame->timestamp;
1194
        tempdata+=sizeof(struct timeval);
1195
        *((int32_t *)tempdata) = frame->size;
1196
        tempdata+=sizeof(int32_t);
1197
        *((int32_t *)tempdata) = frame->type;
1198
        tempdata+=sizeof(int32_t);
1199
*/
1200
        //package the Frame header: network order and platform independent
1201
        tempdata = chunk->data+chunk->payload_len;
1202
        bit32_encoded_push(frame->number, tempdata);
1203
        bit32_encoded_push(frame->timestamp.tv_sec, tempdata + CHUNK_TRANSCODING_INT_SIZE);
1204
        bit32_encoded_push(frame->timestamp.tv_usec, tempdata + CHUNK_TRANSCODING_INT_SIZE*2);
1205
        bit32_encoded_push(frame->size, tempdata + CHUNK_TRANSCODING_INT_SIZE*3);
1206
        bit32_encoded_push(frame->type, tempdata + CHUNK_TRANSCODING_INT_SIZE*4);
1207

    
1208
         //insert the new frame data
1209
        memcpy(chunk->data + chunk->payload_len + sizeFrameHeader, outbuf, frame->size);
1210
        chunk->payload_len += frame->size + sizeFrameHeader; // update payload length
1211
        //chunk lenght is updated just prior to pushing it out because
1212
        //the chunk header len is better calculated there
1213
        //chunk->len = sizeChunkHeader + chunk->payload_len; // update overall length
1214

    
1215
        //update timestamps
1216
        if(((int)frame->timestamp.tv_sec < (int)chunk->start_time.tv_sec) || ((int)frame->timestamp.tv_sec==(int)chunk->start_time.tv_sec && (int)frame->timestamp.tv_usec < (int)chunk->start_time.tv_usec) || (int)chunk->start_time.tv_sec==-1) {
1217
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
1218
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
1219
        }
1220
        
1221
        if(((int)frame->timestamp.tv_sec > (int)chunk->end_time.tv_sec) || ((int)frame->timestamp.tv_sec==(int)chunk->end_time.tv_sec && (int)frame->timestamp.tv_usec > (int)chunk->end_time.tv_usec) || (int)chunk->end_time.tv_sec==-1) {
1222
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
1223
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
1224
        }
1225
        return 0;
1226
}
1227

    
1228
void SaveFrame(AVFrame *pFrame, int width, int height)
1229
{
1230
        FILE *pFile;
1231
        int  y;
1232

    
1233
         // Open file
1234
        char tmp_filename[255];
1235
        sprintf(tmp_filename, "yuv_data/streamer_out.yuv");
1236
        pFile=fopen(tmp_filename, "ab");
1237
        if(pFile==NULL)
1238
                return;
1239

    
1240
        // Write header
1241
        //fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1242
  
1243
        // Write Y data
1244
        for(y=0; y<height; y++)
1245
                  if(fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile) != width)
1246
                {
1247
                        printf("errno = %d\n", errno);
1248
                        exit(1);
1249
                }
1250
        // Write U data
1251
        for(y=0; y<height/2; y++)
1252
                  if(fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile) != width/2)
1253
                  {
1254
                        printf("errno = %d\n", errno);
1255
                        exit(1);
1256
                }
1257
        // Write V data
1258
        for(y=0; y<height/2; y++)
1259
                  if(fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile) != width/2)
1260
                  {
1261
                        printf("errno = %d\n", errno);
1262
                        exit(1);
1263
                }
1264
  
1265
        // Close file
1266
        fclose(pFile);
1267
}
1268

    
1269
void SaveEncodedFrame(Frame* frame, uint8_t *video_outbuf)
1270
{
1271
        static FILE* pFile = NULL;
1272
        
1273
        pFile=fopen("yuv_data/streamer_out.mpeg4", "ab");
1274
        fwrite(frame, sizeof(Frame), 1, pFile);
1275
        fwrite(video_outbuf, frame->size, 1, pFile);
1276
        fclose(pFile);
1277
}