Statistics
| Branch: | Revision:

chunker-player / chunker_streamer / chunker_streamer.c @ f35f46e8

History | View | Annotate | Download (38.7 KB)

1 01f952d0 GiuseppeTropea
/*
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 1e69ae95 GiuseppeTropea
8
#include "chunker_streamer.h"
9 e11386c0 CsabaKiraly
#include <signal.h>
10
#include <math.h>
11
#include <getopt.h>
12
#include <libswscale/swscale.h>
13 8b52d5cf GiuseppeTropea
14 e11386c0 CsabaKiraly
#define STREAMER_MAX(a,b) ((a>b)?(a):(b))
15
#define STREAMER_MIN(a,b) ((a<b)?(a):(b))
16 1e69ae95 GiuseppeTropea
17 df2ad829 GiuseppeTropea
//#define DEBUG_AUDIO_FRAMES
18
//#define DEBUG_VIDEO_FRAMES
19 9996b19f CsabaKiraly
//#define DEBUG_CHUNKER
20 eb0c9035 GiuseppeTropea
#define DEBUG_ANOMALIES
21 e11386c0 CsabaKiraly
//~ #define DEBUG_TIMESTAMPING
22
#define GET_PSNR(x) ((x==0) ? 0 : (-10.0*log(x)/log(10)))
23 69fd123e GiuseppeTropea
24 648357d7 GiuseppeTropea
ChunkerMetadata *cmeta = NULL;
25 269f1314 GiuseppeTropea
int seq_current_chunk = 1; //chunk numbering starts from 1; HINT do i need more bytes?
26 1e69ae95 GiuseppeTropea
27 e11386c0 CsabaKiraly
#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 video_record_count = 0;
33
int savedVideoFrames = 0;
34
long int firstSavedVideoFrame = 0;
35
ChunkerStreamerTestMode = 0;
36 1e69ae95 GiuseppeTropea
37 41b6e126 Csaba Kiraly
int pts_anomaly_threshold = 0;
38
int newtime_anomaly_threshold = 0;
39 f35f46e8 Csaba Kiraly
bool timebank = false;
40 36fdd607 Csaba Kiraly
41 e11386c0 CsabaKiraly
// Constant number of frames per chunk
42
int chunkFilledFramesStrategy(ExternalChunk *echunk, int chunkType)
43
{
44 269f1314 GiuseppeTropea
#ifdef DEBUG_CHUNKER
45 e11386c0 CsabaKiraly
        fprintf(stderr, "CHUNKER: check if frames num %d == %d in chunk %d\n", echunk->frames_num, cmeta->framesPerChunk[chunkType], echunk->seq);
46 269f1314 GiuseppeTropea
#endif
47 e11386c0 CsabaKiraly
        if(echunk->frames_num == cmeta->framesPerChunk[chunkType])
48
                return 1;
49
50
        return 0;
51
}
52
53
// Constant size. Note that for now each chunk will have a size just greater or equal than the required value
54
// It can be considered as constant size.
55
int chunkFilledSizeStrategy(ExternalChunk *echunk, int chunkType)
56
{
57
#ifdef DEBUG_CHUNKER
58
        fprintf(stderr, "CHUNKER: check if chunk size %d >= %d in chunk %d\n", echunk->payload_len, cmeta->targetChunkSize, echunk->seq);
59
#endif
60
        if(echunk->payload_len >= cmeta->targetChunkSize)
61
                return 1;
62 1e69ae95 GiuseppeTropea
        
63
        return 0;
64
}
65
66 e11386c0 CsabaKiraly
// Performace optimization.
67
// The chunkFilled function has been splitted into two functions (one for each strategy).
68
// Instead of continuously check the strategy flag (which is constant),
69
// 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)
70
int (*chunkFilled)(ExternalChunk *echunk, int chunkType);
71 1e69ae95 GiuseppeTropea
72 34149271 GiuseppeTropea
void initChunk(ExternalChunk *chunk, int *seq_num) {
73 1e69ae95 GiuseppeTropea
        chunk->seq = (*seq_num)++;
74
        chunk->frames_num = 0;
75
        chunk->payload_len = 0;
76
        chunk->len=0;
77 26379a77 GiuseppeTropea
  if(chunk->data != NULL)
78
    free(chunk->data);
79 1e69ae95 GiuseppeTropea
        chunk->data = NULL;
80
        chunk->start_time.tv_sec = -1;
81
        chunk->start_time.tv_usec = -1;
82
        chunk->end_time.tv_sec = -1;
83
        chunk->end_time.tv_usec = -1;
84
        chunk->priority = 0;
85
        chunk->category = 0;
86
        chunk->_refcnt = 0;
87
}
88
89 e11386c0 CsabaKiraly
int quit = 0;
90
91
void sigproc()
92
{
93
        printf("you have pressed ctrl-c, terminating...\n");
94
        quit = 1;
95
}
96
97
static void print_usage(int argc, char *argv[])
98
{
99
  fprintf (stderr,
100
    "\nUsage:%s [options]\n"
101
    "\n"
102
    "Mandatory options:\n"
103
    "\t[-i input file]\n"
104
    "\t[-a audio bitrate]\n"
105 8751781d Csaba Kiraly
    "\t[-v video bitrate]\n\n"
106 e11386c0 CsabaKiraly
    "Other options:\n"
107 8751781d Csaba Kiraly
    "\t[-A audioencoder]\n"
108
    "\t[-V videoencoder]\n"
109 e11386c0 CsabaKiraly
    "\t[-s WxH]: force video size.\n"
110
    "\t[-l]: this is a live stream.\n"
111
    "\t[-o]: adjust av frames timestamps.\n"
112
    "\t[-t]: QoE test mode\n\n"
113
    "=======================================================\n", argv[0]
114
    );
115
  }
116 8b52d5cf GiuseppeTropea
117 03590124 Csaba Kiraly
sendChunk(ExternalChunk *chunk) {
118
#ifdef HTTPIO
119
                                                pushChunkHttp(chunk, cmeta->outside_world_url);
120
#endif
121
#ifdef TCPIO
122
                                                pushChunkTcp(chunk);
123
#endif
124 13836171 Csaba Kiraly
#ifdef UDPIO
125
                                                pushChunkUDP(chunk);
126
#endif
127 03590124 Csaba Kiraly
}
128
129 1e69ae95 GiuseppeTropea
int main(int argc, char *argv[]) {
130 e11386c0 CsabaKiraly
        signal(SIGINT, sigproc);
131
        
132 34149271 GiuseppeTropea
        int i=0;
133 648357d7 GiuseppeTropea
134
        //output variables
135
        uint8_t *video_outbuf = NULL;
136
        int video_outbuf_size, video_frame_size;
137
        uint8_t *audio_outbuf = NULL;
138
        int audio_outbuf_size, audio_frame_size;
139
        int audio_data_size;
140
141
        //numeric identifiers of input streams
142
        int videoStream = -1;
143
        int audioStream = -1;
144
145
        int len1;
146 1e69ae95 GiuseppeTropea
        int frameFinished;
147 648357d7 GiuseppeTropea
        //frame sequential counters
148 e11386c0 CsabaKiraly
        int contFrameAudio=1, contFrameVideo=0;
149 648357d7 GiuseppeTropea
        int numBytes;
150
151
        //command line parameters
152 e11386c0 CsabaKiraly
        int audio_bitrate = -1;
153
        int video_bitrate = -1;
154 2efccd13 Csaba Kiraly
        char *audio_codec = "mp2";
155
        char *video_codec = "mpeg4";
156 c75b5711 GiuseppeTropea
        int live_source = 0; //tells to sleep before reading next frame in not live (i.e. file)
157
        int offset_av = 0; //tells to compensate for offset between audio and video in the file
158 1e69ae95 GiuseppeTropea
        
159 648357d7 GiuseppeTropea
        //a raw buffer for decoded uncompressed audio samples
160
        int16_t *samples = NULL;
161
        //a raw uncompressed video picture
162
        AVFrame *pFrame = NULL;
163 e11386c0 CsabaKiraly
        AVFrame *scaledFrame = NULL;
164 11e39d44 GiuseppeTropea
165 1e69ae95 GiuseppeTropea
        AVFormatContext *pFormatCtx;
166
        AVCodecContext  *pCodecCtx,*pCodecCtxEnc,*aCodecCtxEnc,*aCodecCtx;
167
        AVCodec         *pCodec,*pCodecEnc,*aCodec,*aCodecEnc;
168
        AVPacket         packet;
169
170 648357d7 GiuseppeTropea
        //stuff needed to compute the right timestamps
171 1e69ae95 GiuseppeTropea
        short int FirstTimeAudio=1, FirstTimeVideo=1;
172 eb0c9035 GiuseppeTropea
        short int pts_anomalies_counter=0;
173 df2ad829 GiuseppeTropea
        short int newtime_anomalies_counter=0;
174 0452f734 GiuseppeTropea
        long long newTime=0, newTime_audio=0, newTime_video=0, newTime_prev=0;
175 69fd123e GiuseppeTropea
        struct timeval lastAudioSent = {0, 0};
176 34149271 GiuseppeTropea
        double ptsvideo1=0.0;
177
        double ptsaudio1=0.0;
178 648357d7 GiuseppeTropea
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
179
180 8b52d5cf GiuseppeTropea
        //Napa-Wine specific Frame and Chunk structures for transport
181
        Frame *frame = NULL;
182
        ExternalChunk *chunk = NULL;
183
        ExternalChunk *chunkaudio = NULL;
184 e11386c0 CsabaKiraly
        
185
        char av_input[1024];
186
        int dest_width = -1;
187
        int dest_height = -1;
188
        
189
        static struct option long_options[] =
190
        {
191
                /* These options set a flag. */
192
                {"long_option", required_argument, 0, 0},
193
                {0, 0, 0, 0}
194
        };
195
        /* `getopt_long' stores the option index here. */
196
        int option_index = 0, c;
197
        int mandatories = 0;
198 2efccd13 Csaba Kiraly
        while ((c = getopt_long (argc, argv, "i:a:v:A:V:s:lot", long_options, &option_index)) != -1)
199 e11386c0 CsabaKiraly
        {
200
                switch (c) {
201
                        case 0: //for long options
202
                                break;
203
                        case 'i':
204
                                sprintf(av_input, "%s", optarg);
205
                                mandatories++;
206
                                break;
207
                        case 'a':
208
                                sscanf(optarg, "%d", &audio_bitrate);
209
                                mandatories++;
210
                                break;
211
                        case 'v':
212
                                sscanf(optarg, "%d", &video_bitrate);
213
                                mandatories++;
214
                                break;
215 2efccd13 Csaba Kiraly
                        case 'A':
216
                                audio_codec = strdup(optarg);
217
                                break;
218
                        case 'V':
219
                                video_codec = strdup(optarg);
220
                                break;
221 e11386c0 CsabaKiraly
                        case 's':
222
                                sscanf(optarg, "%dx%d", &dest_width, &dest_height);
223
                                break;
224
                        case 'l':
225
                                live_source = 1;
226
                                break;
227
                        case 'o':
228
                                offset_av = 1;
229
                                break;
230
                        case 't':
231
                                ChunkerStreamerTestMode = 1;
232
                                break;
233
                        default:
234
                                print_usage(argc, argv);
235
                                return -1;
236
                }
237
        }
238
        
239
        if(mandatories < 3) 
240
        {
241
                print_usage(argc, argv);
242 1e69ae95 GiuseppeTropea
                return -1;
243
        }
244 e11386c0 CsabaKiraly
245
#ifdef YUV_RECORD_ENABLED
246
        if(ChunkerStreamerTestMode)
247
        {
248
                DELETE_DIR("yuv_data");
249
                CREATE_DIR("yuv_data");
250
                //FILE* pFile=fopen("yuv_data/streamer_out.yuv", "w");
251
                //fclose(pFile);
252
        }
253
#endif
254 34149271 GiuseppeTropea
255 ac723195 GiuseppeTropea
restart:
256 34149271 GiuseppeTropea
        // read the configuration file
257
        cmeta = chunkerInit();
258 e11386c0 CsabaKiraly
        switch(cmeta->strategy)
259
        {
260
                case 1:
261
                        chunkFilled = chunkFilledSizeStrategy;
262
                        break;
263
                default:
264
                        chunkFilled = chunkFilledFramesStrategy;
265
        }
266
                
267 34149271 GiuseppeTropea
        if(live_source)
268
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
269 c75b5711 GiuseppeTropea
        if(offset_av)
270
                fprintf(stderr, "INIT: Compensating AV OFFSET in file\n");
271 1e69ae95 GiuseppeTropea
272
        // Register all formats and codecs
273
        av_register_all();
274
275 648357d7 GiuseppeTropea
        // Open input file
276 e11386c0 CsabaKiraly
        if(av_open_input_file(&pFormatCtx, av_input, NULL, 0, NULL) != 0) {
277 34149271 GiuseppeTropea
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
278
                exit(-1);
279
        }
280
281 1e69ae95 GiuseppeTropea
        // Retrieve stream information
282 34149271 GiuseppeTropea
        if(av_find_stream_info(pFormatCtx) < 0) {
283
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
284
                exit(-1);
285
        }
286
287 1e69ae95 GiuseppeTropea
        // Dump information about file onto standard error
288 e11386c0 CsabaKiraly
        dump_format(pFormatCtx, 0, av_input, 0);
289 34149271 GiuseppeTropea
290 648357d7 GiuseppeTropea
        // Find the video and audio stream numbers
291 1e69ae95 GiuseppeTropea
        for(i=0; i<pFormatCtx->nb_streams; i++) {
292
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
293
                        videoStream=i;
294
                }
295
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
296
                        audioStream=i;
297
                }
298
        }
299 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: Num streams : %d TBR: %d %d RFRAMERATE:%d %d Duration:%d\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);
300 e810bf7b GiuseppeTropea
301 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
302
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
303
304
        if(videoStream==-1 && audioStream==-1) {
305
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
306
                exit(-1);
307
        }
308 1e69ae95 GiuseppeTropea
309 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input video stream
310 1e69ae95 GiuseppeTropea
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
311
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
312 648357d7 GiuseppeTropea
        //extract W and H
313
        fprintf(stderr, "INIT: Width:%d Height:%d\n", pCodecCtx->width, pCodecCtx->height);
314 1e69ae95 GiuseppeTropea
315 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input audio stream
316
        if(audioStream != -1) {
317 1e69ae95 GiuseppeTropea
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
318 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
319 1e69ae95 GiuseppeTropea
        }
320
321 648357d7 GiuseppeTropea
        //setup video output encoder
322 2efccd13 Csaba Kiraly
        pCodecEnc = avcodec_find_encoder_by_name(video_codec);
323
        if (pCodecEnc) {
324
                fprintf(stderr, "INIT: Setting VIDEO codecID to: %d\n",pCodecEnc->id);
325
        } else {
326
                fprintf(stderr, "INIT: Unknown OUT VIDEO codec: %s!\n", video_codec);
327
                return -1; // Codec not found
328
        }
329
330 1e69ae95 GiuseppeTropea
        pCodecCtxEnc=avcodec_alloc_context();
331
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
332 2efccd13 Csaba Kiraly
        pCodecCtxEnc->codec_id = pCodecEnc->id;
333
334
        pCodecCtxEnc->bit_rate = video_bitrate;
335
        //~ pCodecCtxEnc->qmin = 30;
336
        //~ pCodecCtxEnc->qmax = 30;
337
        //times 20 follows the defaults, was not needed in previous versions of libavcodec
338
        pCodecCtxEnc->bit_rate_tolerance = video_bitrate*20;
339
//        pCodecCtxEnc->crf = 20.0f;
340 1e69ae95 GiuseppeTropea
        // resolution must be a multiple of two 
341 e11386c0 CsabaKiraly
        pCodecCtxEnc->width = (dest_width > 0) ? dest_width : pCodecCtx->width;
342
        pCodecCtxEnc->height = (dest_height > 0) ? dest_height : pCodecCtx->height;
343 1e69ae95 GiuseppeTropea
        // frames per second 
344 2efccd13 Csaba Kiraly
        //~ pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
345
        //printf("pCodecCtx->time_base=%d/%d\n", pCodecCtx->time_base.num, pCodecCtx->time_base.den);
346 11e39d44 GiuseppeTropea
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
347 2efccd13 Csaba Kiraly
        pCodecCtxEnc->gop_size = 12; // emit one intra frame every twelve frames 
348 3bcbf04c Csaba Kiraly
        pCodecCtxEnc->max_b_frames=1;
349 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
350 2efccd13 Csaba Kiraly
        pCodecCtxEnc->flags = CODEC_FLAG_PSNR;
351
        //~ pCodecCtxEnc->flags |= CODEC_FLAG_QSCALE;
352
  switch (pCodecEnc->id) {
353
    case CODEC_ID_H264 :
354
        pCodecCtxEnc->me_range=16;
355
        pCodecCtxEnc->max_qdiff=4;
356
        pCodecCtxEnc->qmin=1;
357
        pCodecCtxEnc->qmax=30;
358
        pCodecCtxEnc->qcompress=0.6;
359
        // frames per second 
360 4c879040 GiuseppeTropea
361 38617dba GiuseppeTropea
//        pCodecCtxEnc->rc_min_rate = 0;
362
//        pCodecCtxEnc->rc_max_rate = 0;
363
//        pCodecCtxEnc->rc_buffer_size = 0;
364
//        pCodecCtxEnc->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
365
//        pCodecCtxEnc->crf = 0.0f;
366 e11386c0 CsabaKiraly
        
367
#ifdef STREAMER_X264_USE_SSIM
368
        pCodecCtxEnc->flags2 |= CODEC_FLAG2_SSIM;
369
#endif
370
371
        pCodecCtxEnc->weighted_p_pred=2; //maps wpredp=2; weighted prediction analysis method
372
        // pCodecCtxEnc->rc_min_rate = 0;
373
        // pCodecCtxEnc->rc_max_rate = video_bitrate*2;
374
        // pCodecCtxEnc->rc_buffer_size = 0;
375 2efccd13 Csaba Kiraly
        break;
376
    case CODEC_ID_MPEG4 :
377
        break;
378
    default:
379
        fprintf(stderr, "INIT: Unsupported OUT VIDEO codec: %s!\n", video_codec);
380
  }
381 0452f734 GiuseppeTropea
382 34149271 GiuseppeTropea
        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);
383 e810bf7b GiuseppeTropea
384 648357d7 GiuseppeTropea
        if(pCodec==NULL) {
385
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
386
                return -1; // Codec not found
387
        }
388
        if(pCodecEnc==NULL) {
389
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
390
                return -1; // Codec not found
391
        }
392
        if(avcodec_open(pCodecCtx, pCodec)<0) {
393
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
394
                return -1; // Could not open codec
395
        }
396
        if(avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
397
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
398
                return -1; // Could not open codec
399
        }
400 1e69ae95 GiuseppeTropea
401
        if(audioStream!=-1) {
402 0452f734 GiuseppeTropea
                //setup audio output encoder
403
                aCodecCtxEnc = avcodec_alloc_context();
404
                aCodecCtxEnc->bit_rate = audio_bitrate; //256000
405
                aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
406
                aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
407
                aCodecCtxEnc->channels = aCodecCtx->channels;
408
                fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
409
410
                // Find the decoder for the audio stream
411 1e69ae95 GiuseppeTropea
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
412 2efccd13 Csaba Kiraly
                aCodecEnc = avcodec_find_encoder_by_name(audio_codec);
413 1e69ae95 GiuseppeTropea
                if(aCodec==NULL) {
414 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
415 1e69ae95 GiuseppeTropea
                        return -1;
416
                }
417
                if(aCodecEnc==NULL) {
418 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
419 1e69ae95 GiuseppeTropea
                        return -1;
420
                }
421
        
422
                if(avcodec_open(aCodecCtx, aCodec)<0) {
423 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
424 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
425
                }
426
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
427 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
428 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
429
                }
430
        }
431 0452f734 GiuseppeTropea
        else {
432
                fprintf(stderr,"INIT: NO AUDIO TRACK IN INPUT FILE\n");
433
        }
434 648357d7 GiuseppeTropea
435
        // Allocate audio in and out buffers
436
        samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
437
        if(samples == NULL) {
438
                fprintf(stderr, "INIT: Memory error alloc audio samples!!!\n");
439
                return -1;
440 1e69ae95 GiuseppeTropea
        }
441 648357d7 GiuseppeTropea
        audio_outbuf_size = STREAMER_MAX_AUDIO_BUFFER_SIZE;
442
        audio_outbuf = av_malloc(audio_outbuf_size);
443
        if(audio_outbuf == NULL) {
444
                fprintf(stderr, "INIT: Memory error alloc audio_outbuf!!!\n");
445
                return -1;
446 1e69ae95 GiuseppeTropea
        }
447
448 648357d7 GiuseppeTropea
        // Allocate video in frame and out buffer
449 1e69ae95 GiuseppeTropea
        pFrame=avcodec_alloc_frame();
450 e11386c0 CsabaKiraly
        scaledFrame=avcodec_alloc_frame();
451
        if(pFrame==NULL || scaledFrame == NULL) {
452 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
453 1e69ae95 GiuseppeTropea
                return -1;
454
        }
455 648357d7 GiuseppeTropea
        video_outbuf_size = STREAMER_MAX_VIDEO_BUFFER_SIZE;
456
        video_outbuf = av_malloc(video_outbuf_size);
457 e11386c0 CsabaKiraly
        int scaledFrame_buf_size = avpicture_get_size( PIX_FMT_YUV420P, pCodecCtxEnc->width, pCodecCtxEnc->height);
458
        uint8_t* scaledFrame_buffer = (uint8_t *) av_malloc( scaledFrame_buf_size * sizeof( uint8_t ) );
459
        avpicture_fill( (AVPicture*) scaledFrame, scaledFrame_buffer, PIX_FMT_YUV420P, pCodecCtxEnc->width, pCodecCtxEnc->height);
460
        if(!video_outbuf || !scaledFrame_buffer) {
461 648357d7 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc video_outbuf!!!\n");
462 1e69ae95 GiuseppeTropea
                return -1;
463
        }
464 648357d7 GiuseppeTropea
465
        //allocate Napa-Wine transport
466 1e69ae95 GiuseppeTropea
        frame = (Frame *)malloc(sizeof(Frame));
467
        if(!frame) {
468 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
469 1e69ae95 GiuseppeTropea
                return -1;
470
        }
471 269f1314 GiuseppeTropea
        //create an empty first video chunk
472 1e69ae95 GiuseppeTropea
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
473
        if(!chunk) {
474 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
475 1e69ae95 GiuseppeTropea
                return -1;
476
        }
477 269f1314 GiuseppeTropea
        chunk->data = NULL;
478
        chunk->seq = 0;
479
        //initChunk(chunk, &seq_current_chunk); if i init them now i get out of sequence
480 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
481
        fprintf(stderr, "INIT: chunk video %d\n", chunk->seq);
482
#endif
483 269f1314 GiuseppeTropea
        //create empty first audio chunk
484 1e69ae95 GiuseppeTropea
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
485
        if(!chunkaudio) {
486 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
487 1e69ae95 GiuseppeTropea
                return -1;
488
        }
489 648357d7 GiuseppeTropea
  chunkaudio->data=NULL;
490 269f1314 GiuseppeTropea
        chunkaudio->seq = 0;
491
        //initChunk(chunkaudio, &seq_current_chunk);
492 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
493
        fprintf(stderr, "INIT: chunk audio %d\n", chunkaudio->seq);
494
#endif
495 1e69ae95 GiuseppeTropea
496 03590124 Csaba Kiraly
#ifdef HTTPIO
497 1e69ae95 GiuseppeTropea
        /* initialize the HTTP chunk pusher */
498 8de6681e GiuseppeTropea
        initChunkPusher(); //TRIPLO
499 03590124 Csaba Kiraly
#endif
500 1e69ae95 GiuseppeTropea
501 4c879040 GiuseppeTropea
        long sleep=0;
502 69fd123e GiuseppeTropea
        struct timeval now_tv;
503
        struct timeval tmp_tv;
504
        long long lateTime = 0;
505
        long long maxAudioInterval = 0;
506
        long long maxVDecodeTime = 0;
507 e11386c0 CsabaKiraly
        unsigned char lastIFrameDistance = 0;
508
509
#ifdef TCPIO
510
        static char peer_ip[16];
511
        static int peer_port;
512
        int res = sscanf(cmeta->outside_world_url, "tcp://%15[0-9.]:%d", peer_ip, &peer_port);
513
        if (res < 2) {
514
                fprintf(stderr,"error parsing output url: %s\n", cmeta->outside_world_url);
515
                return -2;
516
        }
517
        
518
        initTCPPush(peer_ip, peer_port);
519
#endif
520 13836171 Csaba Kiraly
#ifdef UDPIO
521
        static char peer_ip[16];
522
        static int peer_port;
523
        int res = sscanf(cmeta->outside_world_url, "udp://%15[0-9.]:%d", peer_ip, &peer_port);
524
        if (res < 2) {
525
                fprintf(stderr,"error parsing output url: %s\n", cmeta->outside_world_url);
526
                return -2;
527
        }
528
        
529
        initUDPPush(peer_ip, peer_port);
530
#endif
531 e11386c0 CsabaKiraly
        
532
        char videotrace_filename[255];
533
        char psnr_filename[255];
534
        sprintf(videotrace_filename, "yuv_data/videotrace.log");
535
        sprintf(psnr_filename, "yuv_data/psnrtrace.log");
536
        FILE* videotrace = fopen(videotrace_filename, "w");
537
        FILE* psnrtrace = fopen(psnr_filename, "w");
538 ac723195 GiuseppeTropea
539 648357d7 GiuseppeTropea
        //main loop to read from the input file
540 e11386c0 CsabaKiraly
        while((av_read_frame(pFormatCtx, &packet)>=0) && !quit)
541 69fd123e GiuseppeTropea
        {
542 4c879040 GiuseppeTropea
                //detect if a strange number of anomalies is occurring
543 eb0c9035 GiuseppeTropea
                if(ptsvideo1 < 0 || ptsvideo1 > packet.dts || ptsaudio1 < 0 || ptsaudio1 > packet.dts) {
544
                        pts_anomalies_counter++;
545
#ifdef DEBUG_ANOMALIES
546
                        fprintf(stderr, "READLOOP: pts BASE anomaly detected number %d\n", pts_anomalies_counter);
547
#endif
548
                        if(live_source) { //reset just in case of live source
549 36fdd607 Csaba Kiraly
                                if(pts_anomalies_counter > pts_anomaly_threshold) {
550 eb0c9035 GiuseppeTropea
                                        pts_anomalies_counter = 0;
551
                                        FirstTimeVideo = 1;
552
                                        FirstTimeAudio = 1;
553
#ifdef DEBUG_ANOMALIES
554
                                        fprintf(stderr, "READLOOP: too many pts BASE anomalies. resetting pts base\n");
555
#endif
556
                                }
557
                        }
558
                }
559
560 e11386c0 CsabaKiraly
                //newTime_video and _audio are in usec
561
                //if video and audio stamps differ more than 5sec
562
                if( newTime_video - newTime_audio > 5000000 || newTime_video - newTime_audio < -5000000 ) {
563
                        newtime_anomalies_counter++;
564
#ifdef DEBUG_ANOMALIES
565
                        fprintf(stderr, "READLOOP: NEWTIME audio video differ anomaly detected number %d\n", newtime_anomalies_counter);
566
#endif
567
                }
568
569 36fdd607 Csaba Kiraly
                if(newtime_anomalies_counter > newtime_anomaly_threshold) {
570 df2ad829 GiuseppeTropea
                        if(live_source) { //restart just in case of live source
571
#ifdef DEBUG_ANOMALIES
572
                                fprintf(stderr, "READLOOP: too many NEGATIVE TIMESTAMPS anomalies. Restarting.\n");
573
#endif
574
                                goto close;
575
                        }
576
                }
577
578 1e69ae95 GiuseppeTropea
                // Is this a packet from the video stream?
579 69fd123e GiuseppeTropea
                if(packet.stream_index==videoStream)
580
                {
581
                        if(!live_source)
582
                        {
583 e11386c0 CsabaKiraly
                                if(audioStream != -1) { //take this "time bank" method into account only if we have audio track
584
                                        // lateTime < 0 means a positive time account that can be used to decode video frames
585
                                        // if (lateTime + maxVDecodeTime) >= 0 then we may have a negative time account after video transcoding
586
                                        // therefore, it's better to skip the frame
587 dc3cdade Csaba Kiraly
                                        if(timebank && (lateTime+maxVDecodeTime) >= 0)
588 e11386c0 CsabaKiraly
                                        {
589 69fd123e GiuseppeTropea
#ifdef DEBUG_ANOMALIES
590 e11386c0 CsabaKiraly
                                                fprintf(stderr, "\n\n\t\t************************* SKIPPING VIDEO FRAME ***********************************\n\n", sleep);
591 69fd123e GiuseppeTropea
#endif
592 e11386c0 CsabaKiraly
                                                continue;
593
                                        }
594 69fd123e GiuseppeTropea
                                }
595
                        }
596
                        
597
                        gettimeofday(&tmp_tv, NULL);
598
                        
599 648357d7 GiuseppeTropea
                        //decode the video packet into a raw pFrame
600 69fd123e GiuseppeTropea
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0)
601
                        {
602
                                // usleep(5000);
603 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
604 269f1314 GiuseppeTropea
                                fprintf(stderr, "\n-------VIDEO FRAME type %d\n", pFrame->pict_type);
605 34149271 GiuseppeTropea
                                fprintf(stderr, "VIDEO: dts %lld pts %lld\n", packet.dts, packet.pts);
606 e810bf7b GiuseppeTropea
#endif
607 e11386c0 CsabaKiraly
                                if(frameFinished)
608
                                { // it must be true all the time else error
609
                                
610
                                        frame->number = ++contFrameVideo;
611
612
#ifdef VIDEO_DEINTERLACE
613
                                        avpicture_deinterlace(
614
                                                (AVPicture*) pFrame,
615
                                                (const AVPicture*) pFrame,
616
                                                pCodecCtxEnc->pix_fmt,
617
                                                pCodecCtxEnc->width,
618
                                                pCodecCtxEnc->height);
619
#endif
620
621 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
622 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
623 e810bf7b GiuseppeTropea
#endif
624
                                        if(frame->number==0) {
625
                                                if(packet.dts==AV_NOPTS_VALUE)
626 e11386c0 CsabaKiraly
                                                {
627 34149271 GiuseppeTropea
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
628 e11386c0 CsabaKiraly
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
629 e810bf7b GiuseppeTropea
                                                        continue;
630 e11386c0 CsabaKiraly
                                                }
631 e810bf7b GiuseppeTropea
                                                last_pkt_dts = packet.dts;
632
                                                newTime = 0;
633
                                        }
634
                                        else {
635
                                                if(packet.dts!=AV_NOPTS_VALUE) {
636 34149271 GiuseppeTropea
                                                        delta_video = packet.dts-last_pkt_dts;
637 e810bf7b GiuseppeTropea
                                                        last_pkt_dts = packet.dts;
638
                                                }
639 34149271 GiuseppeTropea
                                                else if(delta_video==0)
640 e11386c0 CsabaKiraly
                                                {
641 34149271 GiuseppeTropea
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
642 e11386c0 CsabaKiraly
                                                        contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
643 e810bf7b GiuseppeTropea
                                                        continue;
644 e11386c0 CsabaKiraly
                                                }
645 e810bf7b GiuseppeTropea
                                        }
646
#ifdef DEBUG_VIDEO_FRAMES
647 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
648 e810bf7b GiuseppeTropea
#endif
649 e11386c0 CsabaKiraly
650
                                        if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width)
651
                                        {
652
                                                static AVPicture pict;
653
                                                static struct SwsContext *img_convert_ctx = NULL;
654
                                                
655
                                                if(img_convert_ctx == NULL)
656
                                                {
657
                                                        img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, pCodecCtxEnc->width, pCodecCtxEnc->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
658
                                                        if(img_convert_ctx == NULL) {
659
                                                                fprintf(stderr, "Cannot initialize the conversion context!\n");
660
                                                                exit(1);
661
                                                        }
662
                                                }
663
                                                sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, scaledFrame->data, scaledFrame->linesize);
664
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, scaledFrame);
665
                                        }
666
                                        else
667
                                                video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, pFrame);
668
                                        
669 69fd123e GiuseppeTropea
                                        if(video_frame_size <= 0)
670 e11386c0 CsabaKiraly
                                        {
671
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
672 69fd123e GiuseppeTropea
                                                continue;
673 e11386c0 CsabaKiraly
                                        }
674 e810bf7b GiuseppeTropea
675 3e0c28b0 CsabaKiraly
#ifdef DEBUG_VIDEO_FRAMES
676
                                        if(pCodecCtxEnc->coded_frame) {
677
                                                fprintf(stderr, "\n-------VIDEO FRAME intype %d%s -> outtype: %d%s\n",
678
                                                        pFrame->pict_type, pFrame->key_frame ? " (key)" : "",
679
                                                        pCodecCtxEnc->coded_frame->pict_type, pCodecCtxEnc->coded_frame->key_frame ? " (key)" : "");
680
                                        }
681
#endif
682
683 34149271 GiuseppeTropea
                                        //use pts if dts is invalid
684
                                        if(packet.dts!=AV_NOPTS_VALUE)
685
                                                target_pts = packet.dts;
686
                                        else if(packet.pts!=AV_NOPTS_VALUE)
687
                                                target_pts = packet.pts;
688 11e39d44 GiuseppeTropea
                                        else
689 e11386c0 CsabaKiraly
                                        {
690
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
691 34149271 GiuseppeTropea
                                                continue;
692 e11386c0 CsabaKiraly
                                        }
693 34149271 GiuseppeTropea
694 c75b5711 GiuseppeTropea
                                        if(!offset_av)
695 34149271 GiuseppeTropea
                                        {
696 eb0c9035 GiuseppeTropea
                                                if(FirstTimeVideo && packet.dts>0) {
697 34149271 GiuseppeTropea
                                                        ptsvideo1 = (double)packet.dts;
698
                                                        FirstTimeVideo = 0;
699 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
700 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %f\n", ptsvideo1);
701 11e39d44 GiuseppeTropea
#endif
702 34149271 GiuseppeTropea
                                                }
703
                                        }
704 7ea4a367 GiuseppeTropea
                                        else //we want to compensate audio and video offset for this source
705 34149271 GiuseppeTropea
                                        {
706
                                                if(FirstTimeVideo && packet.dts>0) {
707
                                                        //maintain the offset between audio pts and video pts
708
                                                        //because in case of live source they have the same numbering
709
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
710
                                                                ptsvideo1 = ptsaudio1;
711
                                                        else
712
                                                                ptsvideo1 = (double)packet.dts;
713
                                                        FirstTimeVideo = 0;
714 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
715 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %f\n", ptsvideo1);
716 11e39d44 GiuseppeTropea
#endif
717 34149271 GiuseppeTropea
                                                }
718 4c879040 GiuseppeTropea
                                        }
719
                                        //compute the new video timestamp in milliseconds
720
                                        if(frame->number>0) {
721
                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
722 0452f734 GiuseppeTropea
                                                // store timestamp in useconds for next frame sleep
723
                                                newTime_video = newTime*1000;
724 11e39d44 GiuseppeTropea
                                        }
725 df2ad829 GiuseppeTropea
#ifdef DEBUG_TIMESTAMPING
726 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
727 e810bf7b GiuseppeTropea
#endif
728 34149271 GiuseppeTropea
                                        if(newTime<0) {
729
#ifdef DEBUG_VIDEO_FRAMES
730
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
731
#endif
732 df2ad829 GiuseppeTropea
                                                newtime_anomalies_counter++;
733 e11386c0 CsabaKiraly
#ifdef DEBUG_ANOMALIES
734
                                                fprintf(stderr, "READLOOP: NEWTIME negative video timestamp anomaly detected number %d\n", newtime_anomalies_counter);
735
#endif
736
                                                contFrameVideo = STREAMER_MAX(contFrameVideo-1, 0);
737 34149271 GiuseppeTropea
                                                continue; //SKIP THIS FRAME, bad timestamp
738
                                        }
739 e11386c0 CsabaKiraly
                                        
740
                                        //~ printf("pCodecCtxEnc->error[0]=%lld\n", pFrame->error[0]);
741 e810bf7b GiuseppeTropea
        
742
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
743 11e39d44 GiuseppeTropea
                                        frame->timestamp.tv_usec = newTime%1000;
744 648357d7 GiuseppeTropea
                                        frame->size = video_frame_size;
745 0452f734 GiuseppeTropea
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
746 202967c7 CsabaKiraly
                                        frame->type = (unsigned char)pCodecCtxEnc->coded_frame->pict_type;
747 e11386c0 CsabaKiraly
748
#ifdef DEBUG_VIDEO_FRAMES
749
                                        fprintf(stderr, "VIDEO: original codec frame number %d vs. encoded %d vs. packed %d\n", pCodecCtx->frame_number, pCodecCtxEnc->frame_number, frame->number);
750
                                        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);
751
#endif
752
753
#ifdef YUV_RECORD_ENABLED
754
                                        if(ChunkerStreamerTestMode)
755
                                        {
756
                                                if(videotrace)
757
                                                        fprintf(videotrace, "%d %d %d\n", frame->number, pFrame->pict_type, frame->size);
758
759
                                                if(pCodecCtx->height != pCodecCtxEnc->height || pCodecCtx->width != pCodecCtxEnc->width)
760
                                                        SaveFrame(scaledFrame, pCodecCtxEnc->width, pCodecCtxEnc->height);
761
                                                else
762
                                                        SaveFrame(pFrame, pCodecCtxEnc->width, pCodecCtxEnc->height);
763
764
                                                ++savedVideoFrames;
765
                                                SaveEncodedFrame(frame, video_outbuf);
766
767
                                                if(!firstSavedVideoFrame)
768
                                                        firstSavedVideoFrame = frame->number;
769
                                                
770
                                                char tmp_filename[255];
771
                                                sprintf(tmp_filename, "yuv_data/streamer_out_context.txt");
772
                                                FILE* tmp = fopen(tmp_filename, "w");
773
                                                if(tmp)
774
                                                {
775
                                                        fprintf(tmp, "width = %d\nheight = %d\ntotal_frames_saved = %d\ntotal_frames_decoded = %d\nfirst_frame_number = %d\nlast_frame_number = %d\n"
776
                                                                ,pCodecCtxEnc->width, pCodecCtxEnc->height
777
                                                                ,savedVideoFrames, savedVideoFrames, firstSavedVideoFrame, frame->number);
778
                                                        fclose(tmp);
779
                                                }
780
                                        }
781
#endif
782
783 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
784 269f1314 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: encapsulated frame size:%d type:%d\n", frame->size, frame->type);
785 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
786 11e39d44 GiuseppeTropea
#endif
787 e11386c0 CsabaKiraly
                                        //contFrameVideo++; //lets increase the numbering of the frames
788 e810bf7b GiuseppeTropea
789 648357d7 GiuseppeTropea
                                        if(update_chunk(chunk, frame, video_outbuf) == -1) {
790
                                                fprintf(stderr, "VIDEO: unable to update chunk %d. Exiting.\n", chunk->seq);
791
                                                exit(-1);
792 11e39d44 GiuseppeTropea
                                        }
793 648357d7 GiuseppeTropea
794 e11386c0 CsabaKiraly
                                        if(chunkFilled(chunk, VIDEO_CHUNK)) { // is chunk filled using current strategy?
795 11e39d44 GiuseppeTropea
                                                //SAVE ON FILE
796 34149271 GiuseppeTropea
                                                //saveChunkOnFile(chunk);
797 03590124 Csaba Kiraly
                                                //Send the chunk to an external transport/player
798
                                                sendChunk(chunk);
799 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
800 269f1314 GiuseppeTropea
                                                fprintf(stderr, "VIDEO: sent chunk video %d\n", chunk->seq);
801 51ba8aaa GiuseppeTropea
#endif
802 269f1314 GiuseppeTropea
                                                chunk->seq = 0; //signal that we need an increase
803
                                                //initChunk(chunk, &seq_current_chunk);
804 11e39d44 GiuseppeTropea
                                        }
805 0452f734 GiuseppeTropea
806
                                        //compute how long it took to encode video frame
807
                                        gettimeofday(&now_tv, NULL);
808
                                        long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
809
                                        usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
810
                                        if(usec > maxVDecodeTime)
811
                                                maxVDecodeTime = usec;
812
813
                                        //we DONT have an audio track, so we compute timings and determine
814
                                        //how much time we have to sleep at next VIDEO frame taking
815
                                        //also into account how much time was needed to encode the current
816
                                        //video frame
817
                                        //all this in case the video source is not live, i.e. not self-timing
818
                                        //and only in case there is no audio track
819
                                        if(audioStream == -1) {
820
                                                if(!live_source) {
821
                                                        if(newTime_prev != 0) {
822
                                                                //how much delay between video frames ideally
823
                                                                long long maxDelay = newTime_video - newTime_prev;
824
                                                                sleep = (maxDelay - usec);
825
#ifdef DEBUG_ANOMALIES
826
                                                                printf("\tmaxDelay=%ld\n", ((long)maxDelay));
827
                                                                printf("\tlast video frame interval=%ld; sleep time=%ld\n", ((long)usec), ((long)sleep));
828
#endif
829
                                                        }
830
                                                        else
831
                                                                sleep = 0;
832
833
                                                        //update and store counters
834
                                                        newTime_prev = newTime_video;
835
836
                                                        //i can also sleep now instead of at the beginning of
837
                                                        //the next frame because in this case we only have video
838
                                                        //frames, hence it would immediately be the next thing to do
839
                                                        if(sleep > 0) {
840
#ifdef DEBUG_ANOMALIES
841
                                                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
842
#endif
843
                                                                usleep(sleep);
844
                                                        }
845
846
                                                }
847
                                        }
848
849 11e39d44 GiuseppeTropea
                                }
850
                        }
851
                }
852 69fd123e GiuseppeTropea
                else if(packet.stream_index==audioStream)
853
                {
854
                        if(sleep > 0)
855
                        {
856
#ifdef DEBUG_ANOMALIES
857
                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
858
#endif
859
                                usleep(sleep);
860
                        }
861
                        
862 648357d7 GiuseppeTropea
                        audio_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
863
                        //decode the audio packet into a raw audio source buffer
864 69fd123e GiuseppeTropea
                        if(avcodec_decode_audio3(aCodecCtx, samples, &audio_data_size, &packet)>0)
865
                        {
866 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
867 34149271 GiuseppeTropea
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
868
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
869 11e39d44 GiuseppeTropea
#endif
870 648357d7 GiuseppeTropea
                                if(audio_data_size>0) {
871 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
872 648357d7 GiuseppeTropea
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", audio_data_size);
873 11e39d44 GiuseppeTropea
#endif
874 e810bf7b GiuseppeTropea
                                        /* if a frame has been decoded, output it */
875 648357d7 GiuseppeTropea
                                        //fwrite(samples, 1, audio_data_size, outfileaudio);
876 11e39d44 GiuseppeTropea
                                }
877 e810bf7b GiuseppeTropea
                                else
878 34149271 GiuseppeTropea
                                        continue;
879 e810bf7b GiuseppeTropea
        
880 648357d7 GiuseppeTropea
                                audio_frame_size = avcodec_encode_audio(aCodecCtxEnc, audio_outbuf, audio_data_size, samples);
881 69fd123e GiuseppeTropea
                                if(audio_frame_size <= 0)
882
                                        continue;
883
                                
884 34149271 GiuseppeTropea
                                frame->number = contFrameAudio;
885
886 e810bf7b GiuseppeTropea
                                if(frame->number==0) {
887
                                        if(packet.dts==AV_NOPTS_VALUE)
888
                                                continue;
889
                                        last_pkt_dts_audio = packet.dts;
890
                                        newTime = 0;
891
                                }
892
                                else {
893
                                        if(packet.dts!=AV_NOPTS_VALUE) {
894
                                                delta_audio = packet.dts-last_pkt_dts_audio;
895
                                                last_pkt_dts_audio = packet.dts;
896
                                        }
897
                                        else if(delta_audio==0)
898
                                                continue;
899
                                }
900 269f1314 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
901
                                fprintf(stderr, "AUDIO: original codec frame number %d vs. encoded %d vs. packed %d\n", aCodecCtx->frame_number, aCodecCtxEnc->frame_number, frame->number);
902
#endif
903 34149271 GiuseppeTropea
                                //use pts if dts is invalid
904
                                if(packet.dts!=AV_NOPTS_VALUE)
905
                                        target_pts = packet.dts;
906
                                else if(packet.pts!=AV_NOPTS_VALUE)
907
                                        target_pts = packet.pts;
908 1e69ae95 GiuseppeTropea
                                else
909 34149271 GiuseppeTropea
                                        continue;
910
911 c75b5711 GiuseppeTropea
                                if(!offset_av)
912 34149271 GiuseppeTropea
                                {
913 eb0c9035 GiuseppeTropea
                                        if(FirstTimeAudio && packet.dts>0) {
914
                                                ptsaudio1 = (double)packet.dts;
915 34149271 GiuseppeTropea
                                                FirstTimeAudio = 0;
916 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
917 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %f\n", ptsaudio1);
918 e810bf7b GiuseppeTropea
#endif
919 34149271 GiuseppeTropea
                                        }
920 1e69ae95 GiuseppeTropea
                                }
921 7ea4a367 GiuseppeTropea
                                else //we want to compensate audio and video offset for this source
922 34149271 GiuseppeTropea
                                {
923 eb0c9035 GiuseppeTropea
                                        if(FirstTimeAudio && packet.dts>0) {
924 34149271 GiuseppeTropea
                                                //maintain the offset between audio pts and video pts
925
                                                //because in case of live source they have the same numbering
926
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
927
                                                        ptsaudio1 = ptsvideo1;
928
                                                else
929
                                                        ptsaudio1 = (double)packet.dts;
930
                                                FirstTimeAudio = 0;
931 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
932 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
933 11e39d44 GiuseppeTropea
#endif
934 34149271 GiuseppeTropea
                                        }
935 4c879040 GiuseppeTropea
                                }
936
                                //compute the new audio timestamps in milliseconds
937
                                if(frame->number>0) {
938
                                        newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
939 69fd123e GiuseppeTropea
                                        // store timestamp in useconds for next frame sleep
940
                                        newTime_audio = newTime*1000;
941 34149271 GiuseppeTropea
                                }
942 df2ad829 GiuseppeTropea
#ifdef DEBUG_TIMESTAMPING
943 34149271 GiuseppeTropea
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
944
#endif
945
                                if(newTime<0) {
946
#ifdef DEBUG_AUDIO_FRAMES
947
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
948
#endif
949 df2ad829 GiuseppeTropea
                                        newtime_anomalies_counter++;
950 e11386c0 CsabaKiraly
#ifdef DEBUG_ANOMALIES
951
                                        fprintf(stderr, "READLOOP: NEWTIME negative audio timestamp anomaly detected number %d\n", newtime_anomalies_counter);
952
#endif
953 34149271 GiuseppeTropea
                                        continue; //SKIP THIS FRAME, bad timestamp
954
                                }
955 e810bf7b GiuseppeTropea
956 1e69ae95 GiuseppeTropea
                                frame->timestamp.tv_sec = (unsigned int)newTime/1000;
957
                                frame->timestamp.tv_usec = newTime%1000;
958 648357d7 GiuseppeTropea
                                frame->size = audio_frame_size;
959
                                frame->type = 5; // 5 is audio type
960 34149271 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
961
                                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);
962
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
963
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
964 11e39d44 GiuseppeTropea
#endif
965 34149271 GiuseppeTropea
                                contFrameAudio++;
966
967 648357d7 GiuseppeTropea
                                if(update_chunk(chunkaudio, frame, audio_outbuf) == -1) {
968
                                        fprintf(stderr, "AUDIO: unable to update chunk %d. Exiting.\n", chunkaudio->seq);
969
                                        exit(-1);
970
                                }
971 34149271 GiuseppeTropea
                                //set priority
972 11e39d44 GiuseppeTropea
                                chunkaudio->priority = 1;
973 34149271 GiuseppeTropea
974 e11386c0 CsabaKiraly
                                if(chunkFilled(chunkaudio, AUDIO_CHUNK)) {
975 0452f734 GiuseppeTropea
                                        // is chunk filled using current strategy?
976
                                        //SAVE ON FILE
977
                                        //saveChunkOnFile(chunkaudio);
978 03590124 Csaba Kiraly
                                        //Send the chunk to an external transport/player
979
                                        sendChunk(chunkaudio);
980 0452f734 GiuseppeTropea
#ifdef DEBUG_CHUNKER
981
                                        fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
982
#endif
983
                                        chunkaudio->seq = 0; //signal that we need an increase
984
                                        //initChunk(chunkaudio, &seq_current_chunk);
985
                                }
986
987
                                //we have an audio track, so we compute timings and determine
988
                                //how much time we have to sleep at next audio frame taking
989
                                //also into account how much time was needed to encode the
990
                                //video frames
991
                                //all this in case the video source is not live, i.e. not self-timing
992
                                if(!live_source)
993 69fd123e GiuseppeTropea
                                {
994 0452f734 GiuseppeTropea
                                        if(newTime_prev != 0)
995 69fd123e GiuseppeTropea
                                        {
996 0452f734 GiuseppeTropea
                                                long long maxDelay = newTime_audio - newTime_prev;
997 69fd123e GiuseppeTropea
998 0452f734 GiuseppeTropea
                                                gettimeofday(&now_tv, NULL);
999
                                                long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
1000
                                                usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
1001 69fd123e GiuseppeTropea
1002 0452f734 GiuseppeTropea
                                                if(usec > maxAudioInterval)
1003
                                                        maxAudioInterval = usec;
1004 69fd123e GiuseppeTropea
1005 0452f734 GiuseppeTropea
                                                lateTime -= (maxDelay - usec);
1006 69fd123e GiuseppeTropea
#ifdef DEBUG_ANOMALIES
1007 0452f734 GiuseppeTropea
                                                printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
1008
                                                printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
1009 69fd123e GiuseppeTropea
#endif
1010
1011 0452f734 GiuseppeTropea
                                                if((lateTime+maxAudioInterval) < 0)
1012
                                                        sleep = (lateTime+maxAudioInterval)*-1;
1013 69fd123e GiuseppeTropea
                                                else
1014
                                                        sleep = 0;
1015
                                        }
1016 0452f734 GiuseppeTropea
                                        else
1017
                                                sleep = 0;
1018
1019
                                        newTime_prev = newTime_audio;
1020
                                        gettimeofday(&lastAudioSent, NULL);
1021 1e69ae95 GiuseppeTropea
                                }
1022
                        }
1023
                }
1024
                else {
1025 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
1026 11e39d44 GiuseppeTropea
                        fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
1027
#endif
1028 1e69ae95 GiuseppeTropea
                        av_free_packet(&packet);
1029
                }
1030
        }
1031 e11386c0 CsabaKiraly
        
1032
        if(videotrace)
1033
                fclose(videotrace);
1034
        if(psnrtrace)
1035
                fclose(psnrtrace);
1036 1e69ae95 GiuseppeTropea
1037 df2ad829 GiuseppeTropea
close:
1038 7ea4a367 GiuseppeTropea
        if(chunk->seq != 0 && chunk->frames_num>0) {
1039 1e69ae95 GiuseppeTropea
                //SAVE ON FILE
1040 34149271 GiuseppeTropea
                //saveChunkOnFile(chunk);
1041 03590124 Csaba Kiraly
                //Send the chunk to an external transport/player
1042
                sendChunk(chunk);
1043 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
1044
                fprintf(stderr, "CHUNKER: SENDING LAST VIDEO CHUNK\n");
1045
#endif
1046 a573b3de GiuseppeTropea
                chunk->seq = 0; //signal that we need an increase just in case we will restart
1047 1e69ae95 GiuseppeTropea
        }
1048 7ea4a367 GiuseppeTropea
        if(chunkaudio->seq != 0 && chunkaudio->frames_num>0) {
1049 a573b3de GiuseppeTropea
                //SAVE ON FILE     
1050 34149271 GiuseppeTropea
                //saveChunkOnFile(chunkaudio);
1051
                //Send the chunk via http to an external transport/player
1052 03590124 Csaba Kiraly
                sendChunk(chunkaudio);
1053 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
1054
                fprintf(stderr, "CHUNKER: SENDING LAST AUDIO CHUNK\n");
1055
#endif
1056 a573b3de GiuseppeTropea
                chunkaudio->seq = 0; //signal that we need an increase just in case we will restart
1057 1e69ae95 GiuseppeTropea
        }
1058
1059 e11386c0 CsabaKiraly
#ifdef HTTPIO
1060 34149271 GiuseppeTropea
        /* finalize the HTTP chunk pusher */
1061 8de6681e GiuseppeTropea
        finalizeChunkPusher();
1062 e11386c0 CsabaKiraly
#elif TCPIO
1063
        finalizeTCPChunkPusher();
1064
#endif
1065 1e69ae95 GiuseppeTropea
1066
        free(chunk);
1067
        free(chunkaudio);
1068
        free(frame);
1069 648357d7 GiuseppeTropea
        av_free(video_outbuf);
1070 e11386c0 CsabaKiraly
        av_free(scaledFrame_buffer);
1071 648357d7 GiuseppeTropea
        av_free(audio_outbuf);
1072 34149271 GiuseppeTropea
        free(cmeta);
1073 1e69ae95 GiuseppeTropea
1074
        // Free the YUV frame
1075
        av_free(pFrame);
1076 e11386c0 CsabaKiraly
        av_free(scaledFrame);
1077 648357d7 GiuseppeTropea
        av_free(samples);
1078 1e69ae95 GiuseppeTropea
  
1079
        // Close the codec
1080
        avcodec_close(pCodecCtx);
1081
        avcodec_close(pCodecCtxEnc);
1082
1083
        if(audioStream!=-1) {
1084
                avcodec_close(aCodecCtx);
1085
                avcodec_close(aCodecCtxEnc);
1086
        }
1087
  
1088
        // Close the video file
1089
        av_close_input_file(pFormatCtx);
1090 ac723195 GiuseppeTropea
1091 0864b2dc GiuseppeTropea
        if(LOOP_MODE) {
1092
                //we want video to continue, but the av_read_frame stopped
1093 ac723195 GiuseppeTropea
                //lets wait a 5 secs, and cycle in again
1094
                usleep(5000000);
1095
#ifdef DEBUG_CHUNKER
1096
                fprintf(stderr, "CHUNKER: WAITING 5 secs FOR LIVE SOURCE TO SKIP ERRORS AND RESTARTING\n");
1097
#endif
1098
                videoStream = -1;
1099
                audioStream = -1;
1100
                FirstTimeAudio=1;
1101
                FirstTimeVideo=1;
1102
                pts_anomalies_counter=0;
1103 df2ad829 GiuseppeTropea
                newtime_anomalies_counter=0;
1104 ac723195 GiuseppeTropea
                newTime=0;
1105 69fd123e GiuseppeTropea
                newTime_audio=0;
1106 ac723195 GiuseppeTropea
                newTime_prev=0;
1107
                ptsvideo1=0.0;
1108
                ptsaudio1=0.0;
1109
                last_pkt_dts=0;
1110
                delta_video=0;
1111
                delta_audio=0;
1112
                last_pkt_dts_audio=0;
1113
                target_pts=0;
1114
                i=0;
1115 e11386c0 CsabaKiraly
                //~ contFrameVideo = 0;
1116
                //~ contFrameAudio = 1;
1117
                
1118
#ifdef YUV_RECORD_ENABLED
1119
                if(ChunkerStreamerTestMode)
1120
                {
1121
                        video_record_count++;
1122
                        //~ savedVideoFrames = 0;
1123
                        
1124
                        //~ char tmp_filename[255];
1125
                        //~ sprintf(tmp_filename, "yuv_data/out_%d.yuv", video_record_count);
1126
                        //~ FILE *pFile=fopen(tmp_filename, "w");
1127
                        //~ if(pFile!=NULL)
1128
                                //~ fclose(pFile);
1129
                }
1130
#endif
1131
1132 ac723195 GiuseppeTropea
                goto restart;
1133
        }
1134
1135 1e69ae95 GiuseppeTropea
        return 0;
1136
}
1137 648357d7 GiuseppeTropea
1138
int update_chunk(ExternalChunk *chunk, Frame *frame, uint8_t *outbuf) {
1139 8b52d5cf GiuseppeTropea
        //the frame.h gets encoded into 5 slots of 32bits (3 ints plus 2 more for the timeval struct
1140
        static int sizeFrameHeader = 5*sizeof(int32_t);
1141 648357d7 GiuseppeTropea
1142
        //moving temp pointer to encode Frame on the wire
1143
        uint8_t *tempdata = NULL;
1144
1145 269f1314 GiuseppeTropea
        if(chunk->seq == 0) {
1146
                initChunk(chunk, &seq_current_chunk);
1147
        }
1148 648357d7 GiuseppeTropea
        //HINT on malloc
1149
        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len + frame->size + sizeFrameHeader));
1150
        if(!chunk->data)  {
1151
                fprintf(stderr, "Memory error in chunk!!!\n");
1152
                return -1;
1153
        }
1154
        chunk->frames_num++; // number of frames in the current chunk
1155
1156 8b52d5cf GiuseppeTropea
/*
1157 648357d7 GiuseppeTropea
        //package the Frame header
1158
        tempdata = chunk->data+chunk->payload_len;
1159
        *((int32_t *)tempdata) = frame->number;
1160
        tempdata+=sizeof(int32_t);
1161
        *((struct timeval *)tempdata) = frame->timestamp;
1162
        tempdata+=sizeof(struct timeval);
1163
        *((int32_t *)tempdata) = frame->size;
1164
        tempdata+=sizeof(int32_t);
1165
        *((int32_t *)tempdata) = frame->type;
1166
        tempdata+=sizeof(int32_t);
1167 8b52d5cf GiuseppeTropea
*/
1168
        //package the Frame header: network order and platform independent
1169
        tempdata = chunk->data+chunk->payload_len;
1170
        bit32_encoded_push(frame->number, tempdata);
1171
        bit32_encoded_push(frame->timestamp.tv_sec, tempdata + CHUNK_TRANSCODING_INT_SIZE);
1172
        bit32_encoded_push(frame->timestamp.tv_usec, tempdata + CHUNK_TRANSCODING_INT_SIZE*2);
1173
        bit32_encoded_push(frame->size, tempdata + CHUNK_TRANSCODING_INT_SIZE*3);
1174
        bit32_encoded_push(frame->type, tempdata + CHUNK_TRANSCODING_INT_SIZE*4);
1175 648357d7 GiuseppeTropea
1176
         //insert the new frame data
1177
        memcpy(chunk->data + chunk->payload_len + sizeFrameHeader, outbuf, frame->size);
1178
        chunk->payload_len += frame->size + sizeFrameHeader; // update payload length
1179 8b52d5cf GiuseppeTropea
        //chunk lenght is updated just prior to pushing it out because
1180
        //the chunk header len is better calculated there
1181
        //chunk->len = sizeChunkHeader + chunk->payload_len; // update overall length
1182 648357d7 GiuseppeTropea
1183
        //update timestamps
1184
        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) {
1185
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
1186
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
1187
        }
1188
        
1189
        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) {
1190
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
1191
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
1192
        }
1193
        return 0;
1194
}
1195
1196 e11386c0 CsabaKiraly
void SaveFrame(AVFrame *pFrame, int width, int height)
1197
{
1198
        FILE *pFile;
1199
        int  y;
1200
1201
         // Open file
1202
        char tmp_filename[255];
1203
        sprintf(tmp_filename, "yuv_data/streamer_out.yuv");
1204
        pFile=fopen(tmp_filename, "ab");
1205
        if(pFile==NULL)
1206
                return;
1207
1208
        // Write header
1209
        //fprintf(pFile, "P5\n%d %d\n255\n", width, height);
1210
  
1211
        // Write Y data
1212
        for(y=0; y<height; y++)
1213
                  if(fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile) != width)
1214
                {
1215
                        printf("errno = %d\n", errno);
1216
                        exit(1);
1217
                }
1218
        // Write U data
1219
        for(y=0; y<height/2; y++)
1220
                  if(fwrite(pFrame->data[1]+y*pFrame->linesize[1], 1, width/2, pFile) != width/2)
1221
                  {
1222
                        printf("errno = %d\n", errno);
1223
                        exit(1);
1224
                }
1225
        // Write V data
1226
        for(y=0; y<height/2; y++)
1227
                  if(fwrite(pFrame->data[2]+y*pFrame->linesize[2], 1, width/2, pFile) != width/2)
1228
                  {
1229
                        printf("errno = %d\n", errno);
1230
                        exit(1);
1231
                }
1232
  
1233
        // Close file
1234
        fclose(pFile);
1235
}
1236
1237
void SaveEncodedFrame(Frame* frame, uint8_t *video_outbuf)
1238
{
1239
        static FILE* pFile = NULL;
1240
        
1241
        pFile=fopen("yuv_data/streamer_out.mpeg4", "ab");
1242
        fwrite(frame, sizeof(Frame), 1, pFile);
1243
        fwrite(video_outbuf, frame->size, 1, pFile);
1244
        fclose(pFile);
1245
}