Statistics
| Branch: | Revision:

chunker-player / chunker_streamer / chunker_streamer.c @ 9235dfb8

History | View | Annotate | Download (43.6 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 DISPLAY_PSNR
21
#define DEBUG_ANOMALIES
22
//~ #define DEBUG_TIMESTAMPING
23
#define GET_PSNR(x) ((x==0) ? 0 : (-10.0*log(x)/log(10)))
24

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

    
28
#define AUDIO_CHUNK 0
29
#define VIDEO_CHUNK 1
30

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

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

    
44
int pts_anomaly_threshold = -1;
45
int newtime_anomaly_threshold = -1;
46
bool timebank = false;
47
char *outside_world_url = NULL;
48

    
49
int gop_size = 25;
50
int max_b_frames = 3;
51
bool vcopy = false;
52

    
53
long delay_audio = 0; //delay audio by x millisec
54

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

    
64
        return 0;
65
}
66

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

    
80
// Performace optimization.
81
// The chunkFilled function has been splitted into two functions (one for each strategy).
82
// Instead of continuously check the strategy flag (which is constant),
83
// 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)
84
int (*chunkFilled)(ExternalChunk *echunk, int chunkType);
85

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

    
103
int quit = 0;
104

    
105
void sigproc()
106
{
107
        printf("you have pressed ctrl-c, terminating...\n");
108
        quit = 1;
109
}
110

    
111
static void print_usage(int argc, char *argv[])
112
{
113
  fprintf (stderr,
114
    "\nUsage:%s [options]\n"
115
    "\n"
116
    "Mandatory options:\n"
117
    "\t[-i input file]\n"
118
    "\t[-a audio bitrate]\n"
119
    "\t[-v video bitrate]\n\n"
120
    "Other options:\n"
121
    "\t[-F output] (overrides config file)\n"
122
    "\t[-A audioencoder]\n"
123
    "\t[-V videoencoder]\n"
124
    "\t[-s WxH]: force video size.\n"
125
    "\t[-l]: this is a live stream.\n"
126
    "\t[-o]: adjust A/V frame timestamps (deafault off, use it only with flawed containers)\n"
127
    "\t[-p]: pts anomaly threshold (default: -1=off).\n"
128
    "\t[-q]: sync anomaly threshold ((default: -1=off).\n"
129
    "\t[-t]: QoE test mode\n\n"
130
    "Codec options:\n"
131
    "\t[-g GOP]: gop size\n"
132
    "\t[-b frames]: max number of consecutive b frames\n\n"
133
    "=======================================================\n", argv[0]
134
    );
135
  }
136

    
137
int sendChunk(ExternalChunk *chunk) {
138
#ifdef HTTPIO
139
                                                return pushChunkHttp(chunk, outside_world_url);
140
#endif
141
#ifdef TCPIO
142
                                                return pushChunkTcp(chunk);
143
#endif
144
#ifdef UDPIO
145
                                                return pushChunkUDP(chunk);
146
#endif
147
}
148

    
149
int main(int argc, char *argv[]) {
150
        signal(SIGINT, sigproc);
151
        
152
        int i=0;
153

    
154
        //output variables
155
        uint8_t *video_outbuf = NULL;
156
        int video_outbuf_size, video_frame_size;
157
        uint8_t *audio_outbuf = NULL;
158
        int audio_outbuf_size, audio_frame_size;
159
        int audio_data_size;
160

    
161
        //numeric identifiers of input streams
162
        int videoStream = -1;
163
        int audioStream = -1;
164

    
165
//        int len1;
166
        int frameFinished;
167
        //frame sequential counters
168
        int contFrameAudio=1, contFrameVideo=0;
169
//        int numBytes;
170

    
171
        //command line parameters
172
        int audio_bitrate = -1;
173
        int video_bitrate = -1;
174
        char *audio_codec = "mp2";
175
        char *video_codec = "mpeg4";
176
        int live_source = 0; //tells to sleep before reading next frame in not live (i.e. file)
177
        int offset_av = 0; //tells to compensate for offset between audio and video in the file
178
        
179
        //a raw buffer for decoded uncompressed audio samples
180
        int16_t *samples = NULL;
181
        //a raw uncompressed video picture
182
        AVFrame *pFrame = NULL;
183
        AVFrame *scaledFrame = NULL;
184

    
185
        AVFormatContext *pFormatCtx;
186
        AVCodecContext  *pCodecCtx = NULL ,*pCodecCtxEnc = NULL ,*aCodecCtxEnc = NULL ,*aCodecCtx = NULL;
187
        AVCodec         *pCodec = NULL ,*pCodecEnc = NULL ,*aCodec = NULL ,*aCodecEnc = NULL;
188
        AVPacket         packet;
189

    
190
        //stuff needed to compute the right timestamps
191
        short int FirstTimeAudio=1, FirstTimeVideo=1;
192
        short int pts_anomalies_counter=0;
193
        short int newtime_anomalies_counter=0;
194
        long long newTime=0, newTime_audio=0, newTime_video=0, newTime_prev=0;
195
        struct timeval lastAudioSent = {0, 0};
196
        int64_t ptsvideo1=0;
197
        int64_t ptsaudio1=0;
198
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
199

    
200
        //Napa-Wine specific Frame and Chunk structures for transport
201
        Frame *frame = NULL;
202
        ExternalChunk *chunk = NULL;
203
        ExternalChunk *chunkaudio = NULL;
204
        
205
        char av_input[1024];
206
        int dest_width = -1;
207
        int dest_height = -1;
208
        
209
        static struct option long_options[] =
210
        {
211
                /* These options set a flag. */
212
                {"long_option", required_argument, 0, 0},
213
                {0, 0, 0, 0}
214
        };
215
        /* `getopt_long' stores the option index here. */
216
        int option_index = 0, c;
217
        int mandatories = 0;
218
        while ((c = getopt_long (argc, argv, "i:a:v:A:V:s:lop:q:tF:g:b:d:", long_options, &option_index)) != -1)
219
        {
220
                switch (c) {
221
                        case 0: //for long options
222
                                break;
223
                        case 'i':
224
                                sprintf(av_input, "%s", optarg);
225
                                mandatories++;
226
                                break;
227
                        case 'a':
228
                                sscanf(optarg, "%d", &audio_bitrate);
229
                                mandatories++;
230
                                break;
231
                        case 'v':
232
                                sscanf(optarg, "%d", &video_bitrate);
233
                                mandatories++;
234
                                break;
235
                        case 'A':
236
                                audio_codec = strdup(optarg);
237
                                break;
238
                        case 'V':
239
                                video_codec = strdup(optarg);
240
                                break;
241
                        case 's':
242
                                sscanf(optarg, "%dx%d", &dest_width, &dest_height);
243
                                break;
244
                        case 'l':
245
                                live_source = 1;
246
                                break;
247
                        case 'o':
248
                                offset_av = 1;
249
                                break;
250
                        case 't':
251
                                ChunkerStreamerTestMode = 1;
252
                                break;
253
                        case 'p':
254
                                sscanf(optarg, "%d", &pts_anomaly_threshold);
255
                                break;
256
                        case 'q':
257
                                sscanf(optarg, "%d", &newtime_anomaly_threshold);
258
                                break;
259
                        case 'F':
260
                                outside_world_url = strdup(optarg);
261
                                break;
262
                        case 'g':
263
                                sscanf(optarg, "%d", &gop_size);
264
                                break;
265
                        case 'b':
266
                                sscanf(optarg, "%d", &max_b_frames);
267
                                break;
268
                        case 'd':
269
                                sscanf(optarg, "%ld", &delay_audio);
270
                                break;
271
                        default:
272
                                print_usage(argc, argv);
273
                                return -1;
274
                }
275
        }
276
        
277
        if(mandatories < 3) 
278
        {
279
                print_usage(argc, argv);
280
                return -1;
281
        }
282

    
283
#ifdef YUV_RECORD_ENABLED
284
        if(ChunkerStreamerTestMode)
285
        {
286
                DELETE_DIR("yuv_data");
287
                CREATE_DIR("yuv_data");
288
                //FILE* pFile=fopen("yuv_data/streamer_out.yuv", "w");
289
                //fclose(pFile);
290
        }
291
#endif
292

    
293
restart:
294
        // read the configuration file
295
        cmeta = chunkerInit();
296
        if (!outside_world_url) {
297
                outside_world_url = strdup(cmeta->outside_world_url);
298
        }
299
        switch(cmeta->strategy)
300
        {
301
                case 1:
302
                        chunkFilled = chunkFilledSizeStrategy;
303
                        break;
304
                default:
305
                        chunkFilled = chunkFilledFramesStrategy;
306
        }
307
                
308
        if(live_source)
309
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
310
        if(offset_av)
311
                fprintf(stderr, "INIT: Compensating AV OFFSET in file\n");
312

    
313
        // Register all formats and codecs
314
        av_register_all();
315

    
316
        // Open input file
317
        if(av_open_input_file(&pFormatCtx, av_input, NULL, 0, NULL) != 0) {
318
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
319
                exit(-1);
320
        }
321

    
322
        // Retrieve stream information
323
        if(av_find_stream_info(pFormatCtx) < 0) {
324
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
325
                exit(-1);
326
        }
327

    
328
        // Dump information about file onto standard error
329
        av_dump_format(pFormatCtx, 0, av_input, 0);
330

    
331
        // Find the video and audio stream numbers
332
        for(i=0; i<pFormatCtx->nb_streams; i++) {
333
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
334
                        videoStream=i;
335
                }
336
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
337
                        audioStream=i;
338
                }
339
        }
340
        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, (long int)pFormatCtx->streams[videoStream]->duration);
341

    
342
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
343
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
344

    
345
        if(videoStream==-1 && audioStream==-1) {
346
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
347
                exit(-1);
348
        }
349

    
350
        // Get a pointer to the codec context for the input video stream
351
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
352
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
353
        //extract W and H
354
        fprintf(stderr, "INIT: Width:%d Height:%d\n", pCodecCtx->width, pCodecCtx->height);
355

    
356
        // Get a pointer to the codec context for the input audio stream
357
        if(audioStream != -1) {
358
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
359
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
360
        }
361

    
362
        // Figure out size
363
        dest_width = (dest_width > 0) ? dest_width : pCodecCtx->width;
364
        dest_height = (dest_height > 0) ? dest_height : pCodecCtx->height;
365

    
366
        //setup video output encoder
367
 if (strcmp(video_codec, "copy") == 0) {
368
        vcopy = true;
369
 } else {
370
        pCodecEnc = avcodec_find_encoder_by_name(video_codec);
371
        if (pCodecEnc) {
372
                fprintf(stderr, "INIT: Setting VIDEO codecID to: %d\n",pCodecEnc->id);
373
        } else {
374
                fprintf(stderr, "INIT: Unknown OUT VIDEO codec: %s!\n", video_codec);
375
                return -1; // Codec not found
376
        }
377

    
378
        pCodecCtxEnc=avcodec_alloc_context();
379
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
380
        pCodecCtxEnc->codec_id = pCodecEnc->id;
381

    
382
        pCodecCtxEnc->bit_rate = video_bitrate;
383
        //~ pCodecCtxEnc->qmin = 30;
384
        //~ pCodecCtxEnc->qmax = 30;
385
        //times 20 follows the defaults, was not needed in previous versions of libavcodec
386
        pCodecCtxEnc->bit_rate_tolerance = video_bitrate*20;
387
//        pCodecCtxEnc->crf = 20.0f;
388
        // resolution must be a multiple of two 
389
        pCodecCtxEnc->width = dest_width;
390
        pCodecCtxEnc->height = dest_height;
391
        // frames per second 
392
        //~ pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
393
        //printf("pCodecCtx->time_base=%d/%d\n", pCodecCtx->time_base.num, pCodecCtx->time_base.den);
394
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
395
        pCodecCtxEnc->gop_size = gop_size; // emit one intra frame every gop_size frames 
396
        pCodecCtxEnc->max_b_frames = max_b_frames;
397
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
398
        pCodecCtxEnc->flags |= CODEC_FLAG_PSNR;
399
        //~ pCodecCtxEnc->flags |= CODEC_FLAG_QSCALE;
400

    
401
        //some generic quality tuning
402
        pCodecCtxEnc->mb_decision = FF_MB_DECISION_RD;
403

    
404
  switch (pCodecEnc->id) {
405
    case CODEC_ID_H264 :
406
        // Fast Profile
407
        // libx264-fast.ffpreset preset 
408
        pCodecCtxEnc->coder_type = FF_CODER_TYPE_AC; // coder = 1 -> enable CABAC
409
        pCodecCtxEnc->flags |= CODEC_FLAG_LOOP_FILTER; // flags=+loop -> deblock
410
        pCodecCtxEnc->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
411
        pCodecCtxEnc->partitions |= X264_PART_I8X8|X264_PART_I4X4|X264_PART_P8X8|X264_PART_B8X8;        // partitions=+parti8x8+parti4x4+partp8x8+partb8x8
412
        pCodecCtxEnc->me_method=ME_HEX; // me_method=hex
413
        pCodecCtxEnc->me_subpel_quality = 6; // subq=7
414
        pCodecCtxEnc->me_range = 16; // me_range=16
415
        //pCodecCtxEnc->gop_size = 250; // g=250
416
        //pCodecCtxEnc->keyint_min = 25; // keyint_min=25
417
        pCodecCtxEnc->scenechange_threshold = 40; // sc_threshold=40
418
        pCodecCtxEnc->i_quant_factor = 0.71; // i_qfactor=0.71
419
        pCodecCtxEnc->b_frame_strategy = 1; // b_strategy=1
420
        pCodecCtxEnc->qcompress = 0.6; // qcomp=0.6
421
        pCodecCtxEnc->qmin = 10; // qmin=10
422
        pCodecCtxEnc->qmax = 51; // qmax=51
423
        pCodecCtxEnc->max_qdiff = 4; // qdiff=4
424
        //pCodecCtxEnc->max_b_frames = 3; // bf=3
425
        pCodecCtxEnc->refs = 2; // refs=3
426
        //pCodecCtxEnc->directpred = 1; // directpred=1
427
        pCodecCtxEnc->directpred = 3; // directpred=1 in preset -> "directpred", "direct mv prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)"
428
        //pCodecCtxEnc->trellis = 1; // trellis=1
429
        pCodecCtxEnc->flags2 |= CODEC_FLAG2_BPYRAMID|CODEC_FLAG2_MIXED_REFS|CODEC_FLAG2_WPRED|CODEC_FLAG2_8X8DCT|CODEC_FLAG2_FASTPSKIP;        // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip
430
        pCodecCtxEnc->weighted_p_pred = 2; // wpredp=2
431

    
432
        // libx264-main.ffpreset preset
433
        //pCodecCtxEnc->flags2|=CODEC_FLAG2_8X8DCT;
434
        //pCodecCtxEnc->flags2^=CODEC_FLAG2_8X8DCT; // flags2=-dct8x8
435
        //pCodecCtxEnc->crf = 22;
436

    
437
#ifdef STREAMER_X264_USE_SSIM
438
        pCodecCtxEnc->flags2 |= CODEC_FLAG2_SSIM;
439
#endif
440

    
441
        //pCodecCtxEnc->weighted_p_pred=2; //maps wpredp=2; weighted prediction analysis method
442
        // pCodecCtxEnc->rc_min_rate = 0;
443
        // pCodecCtxEnc->rc_max_rate = video_bitrate*2;
444
        // pCodecCtxEnc->rc_buffer_size = 0;
445
        break;
446
    case CODEC_ID_MPEG4 :
447
        pCodecCtxEnc->qmin = 10; // qmin=10
448
        pCodecCtxEnc->qmax = 51; // qmax=51
449
        break;
450
    default:
451
        fprintf(stderr, "INIT: Unsupported OUT VIDEO codec: %s!\n", video_codec);
452
  }
453
 
454
        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);
455
 }
456

    
457
        if(pCodec==NULL) {
458
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
459
                return -1; // Codec not found
460
        }
461
        if(!vcopy && pCodecEnc==NULL) {
462
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
463
                return -1; // Codec not found
464
        }
465
        if(avcodec_open(pCodecCtx, pCodec)<0) {
466
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
467
                return -1; // Could not open codec
468
        }
469
        if(!vcopy && avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
470
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
471
                return -1; // Could not open codec
472
        }
473
        if(audioStream!=-1) {
474
                //setup audio output encoder
475
                aCodecCtxEnc = avcodec_alloc_context();
476
                aCodecCtxEnc->bit_rate = audio_bitrate; //256000
477
                aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
478
                aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
479
                aCodecCtxEnc->channels = aCodecCtx->channels;
480
                fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
481

    
482
                // Find the decoder for the audio stream
483
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
484
                aCodecEnc = avcodec_find_encoder_by_name(audio_codec);
485
                if(aCodec==NULL) {
486
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
487
                        return -1;
488
                }
489
                if(aCodecEnc==NULL) {
490
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
491
                        return -1;
492
                }
493
        
494
                if(avcodec_open(aCodecCtx, aCodec)<0) {
495
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
496
                        return -1; // Could not open codec
497
                }
498
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
499
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
500
                        return -1; // Could not open codec
501
                }
502
        }
503
        else {
504
                fprintf(stderr,"INIT: NO AUDIO TRACK IN INPUT FILE\n");
505
        }
506

    
507
        // Allocate audio in and out buffers
508
        samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
509
        if(samples == NULL) {
510
                fprintf(stderr, "INIT: Memory error alloc audio samples!!!\n");
511
                return -1;
512
        }
513
        audio_outbuf_size = STREAMER_MAX_AUDIO_BUFFER_SIZE;
514
        audio_outbuf = av_malloc(audio_outbuf_size);
515
        if(audio_outbuf == NULL) {
516
                fprintf(stderr, "INIT: Memory error alloc audio_outbuf!!!\n");
517
                return -1;
518
        }
519

    
520
        // Allocate video in frame and out buffer
521
        pFrame=avcodec_alloc_frame();
522
        scaledFrame=avcodec_alloc_frame();
523
        if(pFrame==NULL || scaledFrame == NULL) {
524
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
525
                return -1;
526
        }
527
        video_outbuf_size = STREAMER_MAX_VIDEO_BUFFER_SIZE;
528
        video_outbuf = av_malloc(video_outbuf_size);
529
        int scaledFrame_buf_size = avpicture_get_size( PIX_FMT_YUV420P, dest_width, dest_height);
530
        uint8_t* scaledFrame_buffer = (uint8_t *) av_malloc( scaledFrame_buf_size * sizeof( uint8_t ) );
531
        avpicture_fill( (AVPicture*) scaledFrame, scaledFrame_buffer, PIX_FMT_YUV420P, dest_width, dest_height);
532
        if(!video_outbuf || !scaledFrame_buffer) {
533
                fprintf(stderr, "INIT: Memory error alloc video_outbuf!!!\n");
534
                return -1;
535
        }
536

    
537
        //allocate Napa-Wine transport
538
        frame = (Frame *)malloc(sizeof(Frame));
539
        if(!frame) {
540
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
541
                return -1;
542
        }
543
        //create an empty first video chunk
544
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
545
        if(!chunk) {
546
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
547
                return -1;
548
        }
549
        chunk->data = NULL;
550
        chunk->seq = 0;
551
        //initChunk(chunk, &seq_current_chunk); if i init them now i get out of sequence
552
#ifdef DEBUG_CHUNKER
553
        fprintf(stderr, "INIT: chunk video %d\n", chunk->seq);
554
#endif
555
        //create empty first audio chunk
556
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
557
        if(!chunkaudio) {
558
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
559
                return -1;
560
        }
561
  chunkaudio->data=NULL;
562
        chunkaudio->seq = 0;
563
        //initChunk(chunkaudio, &seq_current_chunk);
564
#ifdef DEBUG_CHUNKER
565
        fprintf(stderr, "INIT: chunk audio %d\n", chunkaudio->seq);
566
#endif
567

    
568
#ifdef HTTPIO
569
        /* initialize the HTTP chunk pusher */
570
        initChunkPusher(); //TRIPLO
571
#endif
572

    
573
        long sleep=0;
574
        struct timeval now_tv;
575
        struct timeval tmp_tv;
576
        long long lateTime = 0;
577
        long long maxAudioInterval = 0;
578
        long long maxVDecodeTime = 0;
579
//        unsigned char lastIFrameDistance = 0;
580

    
581
#ifdef TCPIO
582
        static char peer_ip[16];
583
        static int peer_port;
584
        int res = sscanf(outside_world_url, "tcp://%15[0-9.]:%d", peer_ip, &peer_port);
585
        if (res < 2) {
586
                fprintf(stderr,"error parsing output url: %s\n", outside_world_url);
587
                return -2;
588
        }
589
        
590
        initTCPPush(peer_ip, peer_port);
591
#endif
592
#ifdef UDPIO
593
        static char peer_ip[16];
594
        static int peer_port;
595
        int res = sscanf(outside_world_url, "udp://%15[0-9.]:%d", peer_ip, &peer_port);
596
        if (res < 2) {
597
                fprintf(stderr,"error parsing output url: %s\n", outside_world_url);
598
                return -2;
599
        }
600
        
601
        initUDPPush(peer_ip, peer_port);
602
#endif
603
        
604
        char videotrace_filename[255];
605
        char psnr_filename[255];
606
        sprintf(videotrace_filename, "yuv_data/videotrace.log");
607
        sprintf(psnr_filename, "yuv_data/psnrtrace.log");
608
        FILE* videotrace = fopen(videotrace_filename, "w");
609
        FILE* psnrtrace = fopen(psnr_filename, "w");
610

    
611
        //main loop to read from the input file
612
        while((av_read_frame(pFormatCtx, &packet)>=0) && !quit)
613
        {
614
                //detect if a strange number of anomalies is occurring
615
                if(ptsvideo1 < 0 || ptsvideo1 > packet.dts || ptsaudio1 < 0 || ptsaudio1 > packet.dts) {
616
                        pts_anomalies_counter++;
617
#ifdef DEBUG_ANOMALIES
618
                        fprintf(stderr, "READLOOP: pts BASE anomaly detected number %d\n", pts_anomalies_counter);
619
#endif
620
                        if(pts_anomaly_threshold >=0 && live_source) { //reset just in case of live source
621
                                if(pts_anomalies_counter > pts_anomaly_threshold) {
622
#ifdef DEBUG_ANOMALIES
623
                                        fprintf(stderr, "READLOOP: too many pts BASE anomalies. resetting pts base\n");
624
#endif
625
                                        av_free_packet(&packet);
626
                                        goto close;
627
                                }
628
                        }
629
                }
630

    
631
                //newTime_video and _audio are in usec
632
                //if video and audio stamps differ more than 5sec
633
                if( newTime_video - newTime_audio > 5000000 || newTime_video - newTime_audio < -5000000 ) {
634
                        newtime_anomalies_counter++;
635
#ifdef DEBUG_ANOMALIES
636
                        fprintf(stderr, "READLOOP: NEWTIME audio video differ anomaly detected number %d\n", newtime_anomalies_counter);
637
#endif
638
                }
639

    
640
                if(newtime_anomaly_threshold >=0 && newtime_anomalies_counter > newtime_anomaly_threshold) {
641
                        if(live_source) { //restart just in case of live source
642
#ifdef DEBUG_ANOMALIES
643
                                fprintf(stderr, "READLOOP: too many NEGATIVE TIMESTAMPS anomalies. Restarting.\n");
644
#endif
645
                                av_free_packet(&packet);
646
                                goto close;
647
                        }
648
                }
649

    
650
                // Is this a packet from the video stream?
651
                if(packet.stream_index==videoStream)
652
                {
653
                        if(!live_source)
654
                        {
655
                                if(audioStream != -1) { //take this "time bank" method into account only if we have audio track
656
                                        // lateTime < 0 means a positive time account that can be used to decode video frames
657
                                        // if (lateTime + maxVDecodeTime) >= 0 then we may have a negative time account after video transcoding
658
                                        // therefore, it's better to skip the frame
659
                                        if(timebank && (lateTime+maxVDecodeTime) >= 0)
660
                                        {
661
#ifdef DEBUG_ANOMALIES
662
                                                fprintf(stderr, "\n\n\t\t************************* SKIPPING VIDEO FRAME %ld ***********************************\n\n", sleep);
663
#endif
664
                                                av_free_packet(&packet);
665
                                                continue;
666
                                        }
667
                                }
668
                        }
669
                        
670
                        gettimeofday(&tmp_tv, NULL);
671
                        
672
                        //decode the video packet into a raw pFrame
673
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0)
674
                        {
675
                                // usleep(5000);
676
#ifdef DEBUG_VIDEO_FRAMES
677
                                fprintf(stderr, "VIDEOin pkt: dts %lld pts %lld\n", packet.dts, packet.pts);
678
                                fprintf(stderr, "VIDEOdecode: pkt_dts %lld pkt_pts %lld frame.pts %lld\n", pFrame->pkt_dts, pFrame->pkt_pts, pFrame->pts);
679
                                fprintf(stderr, "VIDEOdecode intype %d%s\n", pFrame->pict_type, pFrame->key_frame ? " (key)" : "");
680
#endif
681
                                pFrame->pts = av_rescale_q(pFrame->pkt_pts, pFormatCtx->streams[videoStream]->time_base, pCodecCtxEnc->time_base);
682
                                if(frameFinished)
683
                                { // it must be true all the time else error
684
                                
685
                                        frame->number = ++contFrameVideo;
686

    
687
#ifdef VIDEO_DEINTERLACE
688
                                if (!vcopy) {
689
                                        avpicture_deinterlace(
690
                                                (AVPicture*) pFrame,
691
                                                (const AVPicture*) pFrame,
692
                                                pCodecCtxEnc->pix_fmt,
693
                                                pCodecCtxEnc->width,
694
                                                pCodecCtxEnc->height);
695
                                }
696
#endif
697

    
698
#ifdef DEBUG_VIDEO_FRAMES
699
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
700
#endif
701
                                        if(frame->number==0) {
702
                                                if(packet.dts==AV_NOPTS_VALUE)
703
                                                {
704
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
705
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
706
                                                        av_free_packet(&packet);
707
                                                        continue;
708
                                                }
709
                                                last_pkt_dts = packet.dts;
710
                                                newTime = 0;
711
                                        }
712
                                        else {
713
                                                if(packet.dts!=AV_NOPTS_VALUE) {
714
                                                        delta_video = packet.dts-last_pkt_dts;
715
                                                        last_pkt_dts = packet.dts;
716
                                                }
717
                                                else if(delta_video==0)
718
                                                {
719
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
720
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
721
                                                        av_free_packet(&packet);
722
                                                        continue;
723
                                                }
724
                                        }
725
#ifdef DEBUG_VIDEO_FRAMES
726
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
727
#endif
728

    
729
                                        if(vcopy) {
730
                                                video_frame_size = packet.size;
731
                                                if (video_frame_size > video_outbuf_size) {
732
                                                        fprintf(stderr, "VIDEO: error, outbuf too small, SKIPPING\n");;
733
                                                        av_free_packet(&packet);
734
                                                        continue;
735
                                                } else {
736
                                                        memcpy(video_outbuf, packet.data, video_frame_size);
737
                                                }
738
                                        } else if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width) {
739
//                                                static AVPicture pict;
740
                                                static struct SwsContext *img_convert_ctx = NULL;
741
                                                
742
                                                pFrame->pict_type = 0;
743
                                                if(img_convert_ctx == NULL)
744
                                                {
745
                                                        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, dest_width, dest_height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
746
                                                        if(img_convert_ctx == NULL) {
747
                                                                fprintf(stderr, "Cannot initialize the conversion context!\n");
748
                                                                exit(1);
749
                                                        }
750
                                                }
751
                                                sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, scaledFrame->data, scaledFrame->linesize);
752
                                                scaledFrame->pts = pFrame->pts;
753
                                                scaledFrame->pict_type = 0;
754
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, scaledFrame);
755
                                        } else {
756
                                                pFrame->pict_type = 0;
757
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, pFrame);
758
                                        }
759

    
760
                                        if(video_frame_size <= 0)
761
                                        {
762
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
763
                                                av_free_packet(&packet);
764
                                                continue;
765
                                        }
766

    
767
#ifdef DEBUG_VIDEO_FRAMES
768
                                        if(!vcopy && pCodecCtxEnc->coded_frame) {
769
                                                fprintf(stderr, "VIDEOout: pkt_dts %lld pkt_pts %lld frame.pts %lld\n", pCodecCtxEnc->coded_frame->pkt_dts, pCodecCtxEnc->coded_frame->pkt_pts, pCodecCtxEnc->coded_frame->pts);
770
                                                fprintf(stderr, "VIDEOout: outtype: %d%s\n", pCodecCtxEnc->coded_frame->pict_type, pCodecCtxEnc->coded_frame->key_frame ? " (key)" : "");
771
                                        }
772
#endif
773
#ifdef DISPLAY_PSNR
774
                                        static double ist_psnr = 0;
775
                                        static double cum_psnr = 0;
776
                                        static int psnr_samples = 0;
777
                                        if(!vcopy && pCodecCtxEnc->coded_frame) {
778
                                                if(pCodecCtxEnc->flags&CODEC_FLAG_PSNR) {
779
                                                        ist_psnr = GET_PSNR(pCodecCtxEnc->coded_frame->error[0]/(pCodecCtxEnc->width*pCodecCtxEnc->height*255.0*255.0));
780
                                                        psnr_samples++;
781
                                                        cum_psnr += ist_psnr;
782
                                                        fprintf(stderr, "PSNR: ist %.4f avg: %.4f\n", ist_psnr, cum_psnr / (double)psnr_samples);
783
                                                }
784
                                        }
785
#endif
786

    
787
                                        //use pts if dts is invalid
788
                                        if(pCodecCtxEnc->coded_frame->pts!=AV_NOPTS_VALUE)
789
                                                target_pts = av_rescale_q(pCodecCtxEnc->coded_frame->pts, pCodecCtxEnc->time_base, pFormatCtx->streams[videoStream]->time_base);
790
                                        else
791
                                        {
792
                                                fprintf(stderr, "VIDEOout: pts error\n");
793
                                                exit(1);
794
                                        }
795

    
796
                                        if(offset_av)
797
                                        {
798
                                                if(FirstTimeVideo && target_pts>0) {
799
                                                        ptsvideo1 = target_pts;
800
                                                        FirstTimeVideo = 0;
801
#ifdef DEBUG_VIDEO_FRAMES
802
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %lld\n", ptsvideo1);
803
#endif
804
                                                }
805
                                        }
806
                                        else //we want to compensate audio and video offset for this source
807
                                        {
808
                                                if(FirstTimeVideo && target_pts>0) {
809
                                                        //maintain the offset between audio pts and video pts
810
                                                        //because in case of live source they have the same numbering
811
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
812
                                                                ptsvideo1 = ptsaudio1;
813
                                                        else
814
                                                                ptsvideo1 = target_pts;
815
                                                        FirstTimeVideo = 0;
816
#ifdef DEBUG_VIDEO_FRAMES
817
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %lld\n", ptsvideo1);
818
#endif
819
                                                }
820
                                        }
821
                                        //compute the new video timestamp in milliseconds
822
                                        if(frame->number>0) {
823
                                                newTime = (target_pts - ptsvideo1) * 1000 * pFormatCtx->streams[videoStream]->time_base.num / pFormatCtx->streams[videoStream]->time_base.den;
824
                                                // store timestamp in useconds for next frame sleep
825
                                                newTime_video = newTime*1000;
826
                                        }
827
#ifdef DEBUG_TIMESTAMPING
828
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
829
#endif
830
                                        if(newTime<0) {
831
#ifdef DEBUG_VIDEO_FRAMES
832
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
833
#endif
834
                                                newtime_anomalies_counter++;
835
#ifdef DEBUG_ANOMALIES
836
                                                fprintf(stderr, "READLOOP: NEWTIME negative video timestamp anomaly detected number %d\n", newtime_anomalies_counter);
837
#endif
838
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
839
                                                av_free_packet(&packet);
840
                                                continue; //SKIP THIS FRAME, bad timestamp
841
                                        }
842
                                        
843
                                        //~ printf("pCodecCtxEnc->error[0]=%lld\n", pFrame->error[0]);
844
        
845
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
846
                                        frame->timestamp.tv_usec = newTime%1000;
847
                                        frame->size = video_frame_size;
848
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
849
                                        frame->type = vcopy ? pFrame->pict_type : (unsigned char)pCodecCtxEnc->coded_frame->pict_type;
850

    
851
#ifdef DEBUG_VIDEO_FRAMES
852
                                        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);
853
                                        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);
854
#endif
855

    
856
#ifdef YUV_RECORD_ENABLED
857
                                        if(!vcopy && ChunkerStreamerTestMode)
858
                                        {
859
                                                if(videotrace)
860
                                                        fprintf(videotrace, "%d %d %d\n", frame->number, pFrame->pict_type, frame->size);
861

    
862
                                                if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width)
863
                                                        SaveFrame(scaledFrame, dest_width, dest_height);
864
                                                else
865
                                                        SaveFrame(pFrame, dest_width, dest_height);
866

    
867
                                                ++savedVideoFrames;
868
                                                SaveEncodedFrame(frame, video_outbuf);
869

    
870
                                                if(!firstSavedVideoFrame)
871
                                                        firstSavedVideoFrame = frame->number;
872
                                                
873
                                                char tmp_filename[255];
874
                                                sprintf(tmp_filename, "yuv_data/streamer_out_context.txt");
875
                                                FILE* tmp = fopen(tmp_filename, "w");
876
                                                if(tmp)
877
                                                {
878
                                                        fprintf(tmp, "width = %d\nheight = %d\ntotal_frames_saved = %d\ntotal_frames_decoded = %d\nfirst_frame_number = %ld\nlast_frame_number = %d\n"
879
                                                                ,dest_width, dest_height
880
                                                                ,savedVideoFrames, savedVideoFrames, firstSavedVideoFrame, frame->number);
881
                                                        fclose(tmp);
882
                                                }
883
                                        }
884
#endif
885

    
886
#ifdef DEBUG_VIDEO_FRAMES
887
                                        fprintf(stderr, "VIDEO: encapsulated frame size:%d type:%d\n", frame->size, frame->type);
888
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
889
#endif
890
                                        //contFrameVideo++; //lets increase the numbering of the frames
891

    
892
                                        if(update_chunk(chunk, frame, video_outbuf) == -1) {
893
                                                fprintf(stderr, "VIDEO: unable to update chunk %d. Exiting.\n", chunk->seq);
894
                                                exit(-1);
895
                                        }
896

    
897
                                        if(chunkFilled(chunk, VIDEO_CHUNK)) { // is chunk filled using current strategy?
898
                                                //calculate priority
899
                                                chunk->priority /= chunk->frames_num;
900

    
901
                                                //SAVE ON FILE
902
                                                //saveChunkOnFile(chunk);
903
                                                //Send the chunk to an external transport/player
904
                                                sendChunk(chunk);
905
#ifdef DEBUG_CHUNKER
906
                                                fprintf(stderr, "VIDEO: sent chunk video %d, prio:%f\n", chunk->seq, chunk->priority);
907
#endif
908
                                                chunk->seq = 0; //signal that we need an increase
909
                                                //initChunk(chunk, &seq_current_chunk);
910
                                        }
911

    
912
                                        //compute how long it took to encode video frame
913
                                        gettimeofday(&now_tv, NULL);
914
                                        long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
915
                                        usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
916
                                        if(usec > maxVDecodeTime)
917
                                                maxVDecodeTime = usec;
918

    
919
                                        //we DONT have an audio track, so we compute timings and determine
920
                                        //how much time we have to sleep at next VIDEO frame taking
921
                                        //also into account how much time was needed to encode the current
922
                                        //video frame
923
                                        //all this in case the video source is not live, i.e. not self-timing
924
                                        //and only in case there is no audio track
925
                                        if(audioStream == -1) {
926
                                                if(!live_source) {
927
                                                        if(newTime_prev != 0) {
928
                                                                //how much delay between video frames ideally
929
                                                                long long maxDelay = newTime_video - newTime_prev;
930
                                                                sleep = (maxDelay - usec);
931
#ifdef DEBUG_ANOMALIES
932
                                                                printf("\tmaxDelay=%ld\n", ((long)maxDelay));
933
                                                                printf("\tlast video frame interval=%ld; sleep time=%ld\n", ((long)usec), ((long)sleep));
934
#endif
935
                                                        }
936
                                                        else
937
                                                                sleep = 0;
938

    
939
                                                        //update and store counters
940
                                                        newTime_prev = newTime_video;
941

    
942
                                                        //i can also sleep now instead of at the beginning of
943
                                                        //the next frame because in this case we only have video
944
                                                        //frames, hence it would immediately be the next thing to do
945
                                                        if(sleep > 0) {
946
#ifdef DEBUG_ANOMALIES
947
                                                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
948
#endif
949
                                                                usleep(sleep);
950
                                                        }
951

    
952
                                                }
953
                                        }
954

    
955
                                }
956
                        }
957
                }
958
                else if(packet.stream_index==audioStream)
959
                {
960
                        if(sleep > 0)
961
                        {
962
#ifdef DEBUG_ANOMALIES
963
                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
964
#endif
965
                                usleep(sleep);
966
                        }
967
                        
968
                        audio_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
969
                        //decode the audio packet into a raw audio source buffer
970
                        if(avcodec_decode_audio3(aCodecCtx, samples, &audio_data_size, &packet)>0)
971
                        {
972
#ifdef DEBUG_AUDIO_FRAMES
973
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
974
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
975
#endif
976
                                if(audio_data_size>0) {
977
#ifdef DEBUG_AUDIO_FRAMES
978
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", audio_data_size);
979
#endif
980
                                        /* if a frame has been decoded, output it */
981
                                        //fwrite(samples, 1, audio_data_size, outfileaudio);
982
                                }
983
                                else {
984
                                        av_free_packet(&packet);
985
                                        continue;
986
                                }
987
        
988
                                audio_frame_size = avcodec_encode_audio(aCodecCtxEnc, audio_outbuf, audio_data_size, samples);
989
                                if(audio_frame_size <= 0) {
990
                                        av_free_packet(&packet);
991
                                        continue;
992
                                }
993
                                
994
                                frame->number = contFrameAudio;
995

    
996
                                if(frame->number==0) {
997
                                        if(packet.dts==AV_NOPTS_VALUE) {
998
                                                av_free_packet(&packet);
999
                                                continue;
1000
                                        }
1001
                                        last_pkt_dts_audio = packet.dts;
1002
                                        newTime = 0;
1003
                                }
1004
                                else {
1005
                                        if(packet.dts!=AV_NOPTS_VALUE) {
1006
                                                delta_audio = packet.dts-last_pkt_dts_audio;
1007
                                                last_pkt_dts_audio = packet.dts;
1008
                                        }
1009
                                        else if(delta_audio==0) {
1010
                                                av_free_packet(&packet);
1011
                                                continue;
1012
                                        }
1013
                                }
1014
#ifdef DEBUG_AUDIO_FRAMES
1015
                                fprintf(stderr, "AUDIO: original codec frame number %d vs. encoded %d vs. packed %d\n", aCodecCtx->frame_number, aCodecCtxEnc->frame_number, frame->number);
1016
#endif
1017
                                //use pts if dts is invalid
1018
                                if(packet.dts!=AV_NOPTS_VALUE)
1019
                                        target_pts = packet.dts;
1020
                                else if(packet.pts!=AV_NOPTS_VALUE) {
1021
                                        target_pts = packet.pts;
1022
                                } else  {
1023
                                        av_free_packet(&packet);
1024
                                        continue;
1025
                                }
1026

    
1027
                                if(offset_av)
1028
                                {
1029
                                        if(FirstTimeAudio && packet.dts>0) {
1030
                                                ptsaudio1 = packet.dts;
1031
                                                FirstTimeAudio = 0;
1032
#ifdef DEBUG_AUDIO_FRAMES
1033
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %lld\n", ptsaudio1);
1034
#endif
1035
                                        }
1036
                                }
1037
                                else //we want to compensate audio and video offset for this source
1038
                                {
1039
                                        if(FirstTimeAudio && packet.dts>0) {
1040
                                                //maintain the offset between audio pts and video pts
1041
                                                //because in case of live source they have the same numbering
1042
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
1043
                                                        ptsaudio1 = ptsvideo1;
1044
                                                else
1045
                                                        ptsaudio1 = packet.dts;
1046
                                                FirstTimeAudio = 0;
1047
#ifdef DEBUG_AUDIO_FRAMES
1048
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
1049
#endif
1050
                                        }
1051
                                }
1052
                                //compute the new audio timestamps in milliseconds
1053
                                if(frame->number>0) {
1054
                                        newTime = ((target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
1055
                                        // store timestamp in useconds for next frame sleep
1056
                                        newTime_audio = newTime*1000;
1057
                                }
1058
#ifdef DEBUG_TIMESTAMPING
1059
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
1060
#endif
1061
                                if(newTime<0) {
1062
#ifdef DEBUG_AUDIO_FRAMES
1063
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
1064
#endif
1065
                                        newtime_anomalies_counter++;
1066
#ifdef DEBUG_ANOMALIES
1067
                                        fprintf(stderr, "READLOOP: NEWTIME negative audio timestamp anomaly detected number %d\n", newtime_anomalies_counter);
1068
#endif
1069
                                        av_free_packet(&packet);
1070
                                        continue; //SKIP THIS FRAME, bad timestamp
1071
                                }
1072

    
1073
                                frame->timestamp.tv_sec = (unsigned int)(newTime + delay_audio)/1000;
1074
                                frame->timestamp.tv_usec = (newTime + delay_audio)%1000;
1075
                                frame->size = audio_frame_size;
1076
                                frame->type = 5; // 5 is audio type
1077
#ifdef DEBUG_AUDIO_FRAMES
1078
                                fprintf(stderr, "AUDIO: pts %lld duration %d timebase %d %lld dts %d\n", packet.pts, (int)packet.duration, pFormatCtx->streams[audioStream]->time_base.num, pFormatCtx->streams[audioStream]->time_base.den, packet.dts);
1079
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
1080
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
1081
#endif
1082
                                contFrameAudio++;
1083

    
1084
                                if(update_chunk(chunkaudio, frame, audio_outbuf) == -1) {
1085
                                        fprintf(stderr, "AUDIO: unable to update chunk %d. Exiting.\n", chunkaudio->seq);
1086
                                        exit(-1);
1087
                                }
1088
                                //set priority
1089
                                chunkaudio->priority = 1;
1090

    
1091
                                if(chunkFilled(chunkaudio, AUDIO_CHUNK)) {
1092
                                        // is chunk filled using current strategy?
1093
                                        //SAVE ON FILE
1094
                                        //saveChunkOnFile(chunkaudio);
1095
                                        //Send the chunk to an external transport/player
1096
                                        sendChunk(chunkaudio);
1097
#ifdef DEBUG_CHUNKER
1098
                                        fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
1099
#endif
1100
                                        chunkaudio->seq = 0; //signal that we need an increase
1101
                                        //initChunk(chunkaudio, &seq_current_chunk);
1102
                                }
1103

    
1104
                                //we have an audio track, so we compute timings and determine
1105
                                //how much time we have to sleep at next audio frame taking
1106
                                //also into account how much time was needed to encode the
1107
                                //video frames
1108
                                //all this in case the video source is not live, i.e. not self-timing
1109
                                if(!live_source)
1110
                                {
1111
                                        if(newTime_prev != 0)
1112
                                        {
1113
                                                long long maxDelay = newTime_audio - newTime_prev;
1114

    
1115
                                                gettimeofday(&now_tv, NULL);
1116
                                                long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
1117
                                                usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
1118

    
1119
                                                if(usec > maxAudioInterval)
1120
                                                        maxAudioInterval = usec;
1121

    
1122
                                                lateTime -= (maxDelay - usec);
1123
#ifdef DEBUG_ANOMALIES
1124
                                                printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
1125
                                                printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
1126
#endif
1127

    
1128
                                                if((lateTime+maxAudioInterval) < 0)
1129
                                                        sleep = (lateTime+maxAudioInterval)*-1;
1130
                                                else
1131
                                                        sleep = 0;
1132
                                        }
1133
                                        else
1134
                                                sleep = 0;
1135

    
1136
                                        newTime_prev = newTime_audio;
1137
                                        gettimeofday(&lastAudioSent, NULL);
1138
                                }
1139
                        }
1140
                }
1141
#ifdef DEBUG_CHUNKER
1142
                fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
1143
#endif
1144
                av_free_packet(&packet);
1145
        }
1146
        
1147
        if(videotrace)
1148
                fclose(videotrace);
1149
        if(psnrtrace)
1150
                fclose(psnrtrace);
1151

    
1152
close:
1153
        if(chunk->seq != 0 && chunk->frames_num>0) {
1154
                //SAVE ON FILE
1155
                //saveChunkOnFile(chunk);
1156
                //Send the chunk to an external transport/player
1157
                sendChunk(chunk);
1158
#ifdef DEBUG_CHUNKER
1159
                fprintf(stderr, "CHUNKER: SENDING LAST VIDEO CHUNK\n");
1160
#endif
1161
                chunk->seq = 0; //signal that we need an increase just in case we will restart
1162
        }
1163
        if(chunkaudio->seq != 0 && chunkaudio->frames_num>0) {
1164
                //SAVE ON FILE     
1165
                //saveChunkOnFile(chunkaudio);
1166
                //Send the chunk via http to an external transport/player
1167
                sendChunk(chunkaudio);
1168
#ifdef DEBUG_CHUNKER
1169
                fprintf(stderr, "CHUNKER: SENDING LAST AUDIO CHUNK\n");
1170
#endif
1171
                chunkaudio->seq = 0; //signal that we need an increase just in case we will restart
1172
        }
1173

    
1174
#ifdef HTTPIO
1175
        /* finalize the HTTP chunk pusher */
1176
        finalizeChunkPusher();
1177
#endif
1178

    
1179
        free(chunk);
1180
        free(chunkaudio);
1181
        free(frame);
1182
        av_free(video_outbuf);
1183
        av_free(scaledFrame_buffer);
1184
        av_free(audio_outbuf);
1185
        free(cmeta);
1186

    
1187
        // Free the YUV frame
1188
        av_free(pFrame);
1189
        av_free(scaledFrame);
1190
        av_free(samples);
1191
  
1192
        // Close the codec
1193
        if (!vcopy) avcodec_close(pCodecCtx);
1194
        if (!vcopy) avcodec_close(pCodecCtxEnc);
1195

    
1196
        if(audioStream!=-1) {
1197
                avcodec_close(aCodecCtx);
1198
                avcodec_close(aCodecCtxEnc);
1199
        }
1200
  
1201
        // Close the video file
1202
        av_close_input_file(pFormatCtx);
1203

    
1204
        if(LOOP_MODE) {
1205
                //we want video to continue, but the av_read_frame stopped
1206
                //lets wait a 5 secs, and cycle in again
1207
                usleep(5000000);
1208
#ifdef DEBUG_CHUNKER
1209
                fprintf(stderr, "CHUNKER: WAITING 5 secs FOR LIVE SOURCE TO SKIP ERRORS AND RESTARTING\n");
1210
#endif
1211
                videoStream = -1;
1212
                audioStream = -1;
1213
                FirstTimeAudio=1;
1214
                FirstTimeVideo=1;
1215
                pts_anomalies_counter=0;
1216
                newtime_anomalies_counter=0;
1217
                newTime=0;
1218
                newTime_audio=0;
1219
                newTime_prev=0;
1220
                ptsvideo1=0;
1221
                ptsaudio1=0;
1222
                last_pkt_dts=0;
1223
                delta_video=0;
1224
                delta_audio=0;
1225
                last_pkt_dts_audio=0;
1226
                target_pts=0;
1227
                i=0;
1228
                //~ contFrameVideo = 0;
1229
                //~ contFrameAudio = 1;
1230
                
1231
#ifdef YUV_RECORD_ENABLED
1232
                if(ChunkerStreamerTestMode)
1233
                {
1234
                        video_record_count++;
1235
                        //~ savedVideoFrames = 0;
1236
                        
1237
                        //~ char tmp_filename[255];
1238
                        //~ sprintf(tmp_filename, "yuv_data/out_%d.yuv", video_record_count);
1239
                        //~ FILE *pFile=fopen(tmp_filename, "w");
1240
                        //~ if(pFile!=NULL)
1241
                                //~ fclose(pFile);
1242
                }
1243
#endif
1244

    
1245
                goto restart;
1246
        }
1247

    
1248
#ifdef TCPIO
1249
        finalizeTCPChunkPusher();
1250
#endif
1251

    
1252
        return 0;
1253
}
1254

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

    
1259
        //moving temp pointer to encode Frame on the wire
1260
        uint8_t *tempdata = NULL;
1261

    
1262
        if(chunk->seq == 0) {
1263
                initChunk(chunk, &seq_current_chunk);
1264
        }
1265
        //add frame priority to chunk priority (to be normalized later on)
1266
        chunk->priority += frame->type + 1; // I:2, P:3, B:4
1267

    
1268
        //HINT on malloc
1269
        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len + frame->size + sizeFrameHeader));
1270
        if(!chunk->data)  {
1271
                fprintf(stderr, "Memory error in chunk!!!\n");
1272
                return -1;
1273
        }
1274
        chunk->frames_num++; // number of frames in the current chunk
1275

    
1276
/*
1277
        //package the Frame header
1278
        tempdata = chunk->data+chunk->payload_len;
1279
        *((int32_t *)tempdata) = frame->number;
1280
        tempdata+=sizeof(int32_t);
1281
        *((struct timeval *)tempdata) = frame->timestamp;
1282
        tempdata+=sizeof(struct timeval);
1283
        *((int32_t *)tempdata) = frame->size;
1284
        tempdata+=sizeof(int32_t);
1285
        *((int32_t *)tempdata) = frame->type;
1286
        tempdata+=sizeof(int32_t);
1287
*/
1288
        //package the Frame header: network order and platform independent
1289
        tempdata = chunk->data+chunk->payload_len;
1290
        bit32_encoded_push(frame->number, tempdata);
1291
        bit32_encoded_push(frame->timestamp.tv_sec, tempdata + CHUNK_TRANSCODING_INT_SIZE);
1292
        bit32_encoded_push(frame->timestamp.tv_usec, tempdata + CHUNK_TRANSCODING_INT_SIZE*2);
1293
        bit32_encoded_push(frame->size, tempdata + CHUNK_TRANSCODING_INT_SIZE*3);
1294
        bit32_encoded_push(frame->type, tempdata + CHUNK_TRANSCODING_INT_SIZE*4);
1295

    
1296
         //insert the new frame data
1297
        memcpy(chunk->data + chunk->payload_len + sizeFrameHeader, outbuf, frame->size);
1298
        chunk->payload_len += frame->size + sizeFrameHeader; // update payload length
1299
        //chunk lenght is updated just prior to pushing it out because
1300
        //the chunk header len is better calculated there
1301
        //chunk->len = sizeChunkHeader + chunk->payload_len; // update overall length
1302

    
1303
        //update timestamps
1304
        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) {
1305
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
1306
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
1307
        }
1308
        
1309
        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) {
1310
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
1311
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
1312
        }
1313
        return 0;
1314
}
1315

    
1316
void SaveFrame(AVFrame *pFrame, int width, int height)
1317
{
1318
        FILE *pFile;
1319
        int  y;
1320

    
1321
         // Open file
1322
        char tmp_filename[255];
1323
        sprintf(tmp_filename, "yuv_data/streamer_out.yuv");
1324
        pFile=fopen(tmp_filename, "ab");
1325
        if(pFile==NULL)
1326
                return;
1327

    
1328
        // Write header
1329
        //fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1330
  
1331
        // Write Y data
1332
        for(y=0; y<height; y++)
1333
                  if(fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile) != width)
1334
                {
1335
                        printf("errno = %d\n", errno);
1336
                        exit(1);
1337
                }
1338
        // Write U data
1339
        for(y=0; y<height/2; y++)
1340
                  if(fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile) != width/2)
1341
                  {
1342
                        printf("errno = %d\n", errno);
1343
                        exit(1);
1344
                }
1345
        // Write V data
1346
        for(y=0; y<height/2; y++)
1347
                  if(fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile) != width/2)
1348
                  {
1349
                        printf("errno = %d\n", errno);
1350
                        exit(1);
1351
                }
1352
  
1353
        // Close file
1354
        fclose(pFile);
1355
}
1356

    
1357
void SaveEncodedFrame(Frame* frame, uint8_t *video_outbuf)
1358
{
1359
        static FILE* pFile = NULL;
1360
        
1361
        pFile=fopen("yuv_data/streamer_out.mpeg4", "ab");
1362
        fwrite(frame, sizeof(Frame), 1, pFile);
1363
        fwrite(video_outbuf, frame->size, 1, pFile);
1364
        fclose(pFile);
1365
}