Statistics
| Branch: | Revision:

chunker-player / chunker_streamer.c @ bd209760

History | View | Annotate | Download (25 KB)

1
// chunker_streamer.c
2
// Author 
3
// Diego Reforgiato
4
// Giuseppe Tropea
5
// Dario Marchese
6
// Carmelo Daniele
7
//
8
// Use the file compile.localffmpeg.static to build the program
9

    
10

    
11
#include <libavcodec/avcodec.h>
12
#include <libavformat/avformat.h>
13

    
14
#include <stdio.h>
15

    
16
#include "chunker_streamer.h"
17
#include "codec_definitions.h"
18

    
19
//#define DEBUG_AUDIO_FRAMES
20
//#define DEBUG_VIDEO_FRAMES
21
//#define DEBUG_CHUNKER
22
//#define DEBUG_TIME
23

    
24

    
25
/*
26
int alphasortNew(const struct dirent **a, const struct dirent **b) {
27
        int idx1 = atoi((*a)->d_name+5);
28
        int idx2 = atoi((*b)->d_name+5);
29
        return (idx2<idx1);
30
//        return (strcmp((*a)->d_name,(*b)->d_name));
31
}
32
*/
33

    
34
ChunkerMetadata *cmeta=NULL;
35

    
36
int chunkFilled(ExternalChunk *echunk, ChunkerMetadata *cmeta) {
37
        // different strategies to implement
38
        if(cmeta->strategy == 0) // number of frames per chunk constant
39
                if(echunk->frames_num == cmeta->val_strategy)
40
                        return 1;
41
        
42
        if(cmeta->strategy == 1) // constant size. Note that for now each chunk will have a size just greater or equal than the required value - It can be considered as constant size. If that is not good we need to change the code. Also, to prevent too low values of strategy_val. This choice is more robust
43
                if(echunk->payload_len >= cmeta->val_strategy)
44
                        return 1;
45
        
46
        return 0;
47
}
48

    
49
/*
50
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
51
        FILE *pFile;
52
        char szFilename[32];
53
        int  y;
54
  
55
  // Open file
56
        sprintf(szFilename, "frame%d.ppm", iFrame);
57

58
          pFile=fopen(szFilename, "wb");
59
          if(pFile==NULL)
60
                    return;
61
  
62
  // Write header
63
        fprintf(pFile, "P5\n%d %d\n255\n", width, height);
64
  
65
  // Write pixel data
66
          for(y=0; y<height; y++)
67
                    fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile);
68
  
69
  // Close file
70
          fclose(pFile);
71
}
72
*/
73

    
74
/*
75
void saveChunkOnFile(ExternalChunk *chunk) {
76
        char buf[1024], outfile[1024];
77
        FILE *fp;
78
        
79
        strcpy(buf,"chunks//CHUNK");
80
        strcat(buf,"\0");
81
        sprintf(outfile,"%s%d",buf,chunk->seq);
82
        fp = fopen(outfile,"wb");
83
        fwrite(&(chunk->seq),sizeof(int),1,fp);
84
        fwrite(&(chunk->frames_num),sizeof(int),1,fp);
85
        fwrite(&(chunk->start_time),sizeof(struct timeval),1,fp);
86
        fwrite(&(chunk->end_time),sizeof(struct timeval),1,fp);
87
        fwrite(&(chunk->payload_len),sizeof(int),1,fp);
88
        fwrite(&(chunk->len),sizeof(int),1,fp);
89
        fwrite(&(chunk->category),sizeof(int),1,fp);
90
        fwrite(&(chunk->priority),sizeof(double),1,fp);
91
        fwrite(&(chunk->_refcnt),sizeof(int),1,fp);
92
        fwrite(chunk->data,sizeof(uint8_t),sizeof(uint8_t)*chunk->payload_len,fp);
93
        fclose(fp);
94
}
95
*/
96

    
97
void initChunk(ExternalChunk *chunk, int *seq_num) {
98
        chunk->seq = (*seq_num)++;
99
        chunk->frames_num = 0;
100
        chunk->payload_len = 0;
101
        chunk->len=0;
102
  if(chunk->data != NULL)
103
    free(chunk->data);
104
        chunk->data = NULL;
105
        chunk->start_time.tv_sec = -1;
106
        chunk->start_time.tv_usec = -1;
107
        chunk->end_time.tv_sec = -1;
108
        chunk->end_time.tv_usec = -1;
109
        chunk->priority = 0;
110
        chunk->category = 0;
111
        chunk->_refcnt = 0;
112
}
113

    
114
int main(int argc, char *argv[]) {
115
        int i=0;
116
        int videoStream, outbuf_size, out_size, seq_current_chunk = 0, audioStream; //HINT MORE BYTES IN SEQ
117
        int len1, data_size;
118
        int frameFinished;
119
        int numBytes, outbuf_audio_size, audio_size;
120
        int sizeFrame = 0;
121
        int sizeChunk = 0;
122
        int dir_entries;
123
        int audio_bitrate;
124
        int video_bitrate;
125
        int contFrameAudio=0, contFrameVideo=0;
126
        int live_source=0;
127
        
128
        uint8_t *buffer,*outbuf,*outbuf_audio;
129
        uint8_t *outbuf_audi_audio,*tempdata;
130
        //uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
131
        uint16_t *audio_buf = NULL;
132

    
133
        unsigned int audio_buf_size = 0;
134
        long double newtimestamp;
135
        
136
        AVFormatContext *pFormatCtx;
137
        AVCodecContext  *pCodecCtx,*pCodecCtxEnc,*aCodecCtxEnc,*aCodecCtx;
138
        AVCodec         *pCodec,*pCodecEnc,*aCodec,*aCodecEnc;
139
        AVFrame         *pFrame; 
140
        AVFrame         *pFrameRGB;
141
        AVPacket         packet;
142
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
143

    
144
        Frame *frame=NULL;
145

    
146
        ExternalChunk *chunk=NULL;
147
        ExternalChunk *chunkaudio=NULL;
148
        
149
        char buf[1024], outfile[1024], basedelfile[1024], delfile[1024];
150
        short int FirstTimeAudio=1, FirstTimeVideo=1;
151
        long long newTime;
152

    
153
        double ptsvideo1=0.0;
154
        double ptsaudio1=0.0;
155
        
156
//        struct dirent **namelist;
157
        
158
        if(argc < 4) {
159
                fprintf(stderr, "execute ./chunker_streamer moviefile audiobitrate videobitrate <live source flag (0 or 1)>\n");
160
                return -1;
161
        }
162
        sscanf(argv[2],"%d", &audio_bitrate);
163
        sscanf(argv[3],"%d", &video_bitrate);
164
        if(argc==5) sscanf(argv[4],"%d", &live_source);
165

    
166
        // read the configuration file
167
        cmeta = chunkerInit();
168
        if(live_source)
169
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
170

    
171
        audio_buf = (uint16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
172
        outbuf_audio_size = 10000;
173
        outbuf_audio = malloc(outbuf_audio_size);
174

    
175
        // Register all formats and codecs
176
        av_register_all();
177

    
178
        // Open video file
179
        if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) != 0) {
180
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
181
                exit(-1);
182
        }
183

    
184
        // Retrieve stream information
185
        if(av_find_stream_info(pFormatCtx) < 0) {
186
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
187
                exit(-1);
188
        }
189

    
190
        // Dump information about file onto standard error
191
        dump_format(pFormatCtx, 0, argv[1], 0);
192

    
193
        // Find the first video stream
194
        videoStream=-1;
195
        audioStream=-1;
196
        
197
        for(i=0; i<pFormatCtx->nb_streams; i++) {
198
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
199
                        videoStream=i;
200
                }
201
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
202
                        audioStream=i;
203
                }
204
        }
205
        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);
206

    
207
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
208
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
209

    
210
        if(videoStream==-1 && audioStream==-1) {
211
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
212
                exit(-1);
213
        }
214

    
215
        // Get a pointer to the codec context for the video stream
216
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
217
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
218

    
219
        fprintf(stderr, "INIT: Width:%d Height:%d\n",pCodecCtx->width,pCodecCtx->height);
220

    
221
        if(audioStream!=-1) {
222
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
223
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
224
        }
225

    
226
        pCodecCtxEnc=avcodec_alloc_context();
227
#ifdef H264_VIDEO_ENCODER
228
        pCodecCtxEnc->me_range=16;
229
        pCodecCtxEnc->max_qdiff=4;
230
        pCodecCtxEnc->qmin=10;
231
        pCodecCtxEnc->qmax=51;
232
        pCodecCtxEnc->qcompress=0.6;
233
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
234
        pCodecCtxEnc->codec_id   = CODEC_ID_H264;//13;//pCodecCtx->codec_id;
235
        pCodecCtxEnc->bit_rate = video_bitrate;///400000;
236
        // resolution must be a multiple of two 
237
        pCodecCtxEnc->width = pCodecCtx->width;
238
        pCodecCtxEnc->height = pCodecCtx->height;
239
        // frames per second 
240
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
241
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
242
        //pCodecCtxEnc->max_b_frames=1;
243
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
244
#else
245
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
246
        pCodecCtxEnc->codec_id   = CODEC_ID_MPEG4;
247
        pCodecCtxEnc->bit_rate = video_bitrate;
248
        pCodecCtxEnc->width = pCodecCtx->width;
249
        pCodecCtxEnc->height = pCodecCtx->height;
250
        // frames per second 
251
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
252
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
253
        //pCodecCtxEnc->max_b_frames=1;
254
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
255
#endif
256
        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);
257

    
258

    
259
        aCodecCtxEnc = avcodec_alloc_context();
260
        aCodecCtxEnc->bit_rate = audio_bitrate; //256000
261
        aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
262
        aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
263
        aCodecCtxEnc->channels = aCodecCtx->channels;
264
        //fprintf(stderr, "InitAUDIOFRAMESIZE:%d %d\n",aCodecCtxEnc->frame_size,av_rescale(44100,1,25));
265
        fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
266

    
267
        // Find the decoder for the video stream
268
        
269
        if(audioStream!=-1) {
270
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
271
#ifdef MP3_AUDIO_ENCODER
272
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP3);
273
#else
274
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP2);
275
#endif
276
                if(aCodec==NULL) {
277
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
278
                        return -1;
279
                }
280
                if(aCodecEnc==NULL) {
281
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
282
                        return -1;
283
                }
284
        
285
                if(avcodec_open(aCodecCtx, aCodec)<0) {
286
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
287
                        return -1; // Could not open codec
288
                }
289
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
290
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
291
                        return -1; // Could not open codec
292
                }
293

    
294
        }
295
#ifdef H264_VIDEO_ENCODER
296
        fprintf(stderr, "INIT: Setting VIDEO codecID to H264: %d %d\n",pCodecCtx->codec_id, CODEC_ID_H264);
297
        pCodecEnc = avcodec_find_encoder(CODEC_ID_H264);//pCodecCtx->codec_id);
298
#else
299
        fprintf(stderr, "INIT: Setting VIDEO codecID to mpeg4: %d %d\n",pCodecCtx->codec_id, CODEC_ID_MPEG4);
300
        pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG4);
301
#endif
302
        if(pCodec==NULL) {
303
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
304
                return -1; // Codec not found
305
        }
306
        if(pCodecEnc==NULL) {
307
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
308
                return -1; // Codec not found
309
        }
310
        if(avcodec_open(pCodecCtx, pCodec)<0) {
311
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
312
                return -1; // Could not open codec
313
        }
314
        if(avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
315
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
316
                return -1; // Could not open codec
317
        }
318

    
319
        // Allocate video frame
320
        pFrame=avcodec_alloc_frame();
321
        if(pFrame==NULL) {
322
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
323
                return -1;
324
        }
325
  
326
        i=0;
327
        outbuf_size = 100000;
328
        outbuf = malloc(outbuf_size);
329
        if(!outbuf) {
330
                fprintf(stderr, "INIT: Memory error alloc outbuf!!!\n");
331
                return -1;
332
        }
333
        frame = (Frame *)malloc(sizeof(Frame));
334
        if(!frame) {
335
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
336
                return -1;
337
        }
338
        sizeFrame = 3*sizeof(int32_t)+sizeof(struct timeval);
339
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
340
        if(!chunk) {
341
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
342
                return -1;
343
        }
344
        sizeChunk = 6*sizeof(int32_t)+2*sizeof(struct timeval)+sizeof(double);
345
    chunk->data=NULL;
346
        initChunk(chunk, &seq_current_chunk);
347
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
348
        if(!chunkaudio) {
349
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
350
                return -1;
351
        }
352
    chunkaudio->data=NULL;
353
        initChunk(chunkaudio, &seq_current_chunk+1);
354
        
355
        //av_init_packet(&packet);
356

    
357
        /* initialize the HTTP chunk pusher */
358
        initChunkPusher(); //TRIPLO
359

    
360

    
361
        while(av_read_frame(pFormatCtx, &packet)>=0) {
362
                // Is this a packet from the video stream?
363
                if(packet.stream_index==videoStream) {
364
                        // Decode video frame
365
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0) {
366
#ifdef DEBUG_VIDEO_FRAMES
367
                                fprintf(stderr, "-------VIDEO FRAME type %d\n", pFrame->pict_type);
368
                                fprintf(stderr, "VIDEO: dts %lld pts %lld\n", packet.dts, packet.pts);
369
#endif
370
                                if(frameFinished) { // it must be true all the time else error
371
                                        frame->number = contFrameVideo;
372
#ifdef DEBUG_VIDEO_FRAMES
373
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
374
#endif
375
                                        if(frame->number==0) {
376
                                                if(packet.dts==AV_NOPTS_VALUE)
377
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
378
                                                        continue;
379
                                                last_pkt_dts = packet.dts;
380
                                                newTime = 0;
381
                                        }
382
                                        else {
383
                                                if(packet.dts!=AV_NOPTS_VALUE) {
384
                                                        delta_video = packet.dts-last_pkt_dts;
385
/*
386
                                                        DeltaTimeVideo=((double)packet.dts-(double)last_pkt_dts)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
387
                                                        if(DeltaTimeVideo<0) DeltaTimeVideo=10;
388
                                                        if(DeltaTimeVideo>80) DeltaTimeVideo=80;
389
*/
390
                                                        last_pkt_dts = packet.dts;
391
                                                }
392
                                                else if(delta_video==0)
393
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
394
                                                        continue;
395
                                        }
396
#ifdef DEBUG_VIDEO_FRAMES
397
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
398
#endif
399
                                        out_size = avcodec_encode_video(pCodecCtxEnc, outbuf, outbuf_size, pFrame);
400
#ifdef DEBUG_VIDEO_FRAMES
401
                                        fprintf(stderr, "VIDEO: original codec frame number %d\n", pCodecCtx->frame_number);
402
                                        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);
403
#endif
404

    
405
                                        //use pts if dts is invalid
406
                                        if(packet.dts!=AV_NOPTS_VALUE)
407
                                                target_pts = packet.dts;
408
                                        else if(packet.pts!=AV_NOPTS_VALUE)
409
                                                target_pts = packet.pts;
410
                                        else
411
                                                continue;
412

    
413
                                        if(!live_source)
414
                                        {
415
                                                if(FirstTimeVideo && packet.pts>0) {
416
                                                        ptsvideo1 = (double)packet.dts;
417
                                                        FirstTimeVideo = 0;
418
#ifdef DEBUG_VIDEO_FRAMES
419
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %f\n", ptsvideo1);
420
#endif
421
                                                }
422
                                                if(frame->number>0) {
423
                                                        //if(ptsaudio1>0)
424
                                                                //use audio-based timestamps when available (both for video and audio frames)
425
                                                                //newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
426
                                                        //else
427
                                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
428
                                                }
429
                                        }
430
                                        else //live source
431
                                        {
432
                                                if(FirstTimeVideo && packet.dts>0) {
433
                                                        //maintain the offset between audio pts and video pts
434
                                                        //because in case of live source they have the same numbering
435
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
436
                                                                ptsvideo1 = ptsaudio1;
437
                                                        else
438
                                                                ptsvideo1 = (double)packet.dts;
439
                                                        FirstTimeVideo = 0;
440
#ifdef DEBUG_VIDEO_FRAMES
441
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %f\n", ptsvideo1);
442
#endif
443
                                                }
444
                                                if(frame->number>0) {
445
                                                        newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
446
                                                }
447
                                                //this was for on-the-fly timestamping
448
                                                //newTime=Now-StartTime;
449
                                        }
450
#ifdef DEBUG_VIDEO_FRAMES
451
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
452
#endif
453
                                        if(newTime<0) {
454
#ifdef DEBUG_VIDEO_FRAMES
455
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
456
#endif
457
                                                continue; //SKIP THIS FRAME, bad timestamp
458
                                        }
459
        
460
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
461
                                        frame->timestamp.tv_usec = newTime%1000;
462
        
463
                                        frame->size = out_size;
464
                                        frame->type = pFrame->pict_type;
465
#ifdef DEBUG_VIDEO_FRAMES
466
                                        fprintf(stderr, "VIDEO: encapsulated frame num:%d size:%d type:%d\n", frame->number, frame->size, frame->type);
467
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
468
                                        //fprintf(stderr, "out_size:%d outbuf_size:%d packet.size:%d\n",out_size,outbuf_size,packet.size);
469
#endif
470
                                        // Save the frame to disk
471
                                        //++i;
472
                                        //SaveFrame(pFrame, pCodecCtx->width, pCodecCtx->height, i);
473
                                        //HINT on malloc
474
                                        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len+out_size+sizeFrame));
475
                                        if(!chunk->data)  {
476
                                                fprintf(stderr, "Memory error in chunk!!!\n");
477
                                                return -1;
478
                                        }
479
                                        chunk->frames_num++; // number of frames in the current chunk
480
                                        //lets increase the numbering of the frames
481
                                        contFrameVideo++;
482
#ifdef DEBUG_VIDEO_FRAMES
483
                                        //fprintf(stderr, "rialloco data di dim:%d con nuova dim:%d\n",chunk->payload_len,out_size);
484
#endif
485

    
486
                                        tempdata = chunk->data+chunk->payload_len;
487
                                        *((int32_t *)tempdata) = frame->number;
488
                                        tempdata+=sizeof(int32_t);
489
                                        *((struct timeval *)tempdata) = frame->timestamp;
490
                                        tempdata+=sizeof(struct timeval);
491
                                        *((int32_t *)tempdata) = frame->size;
492
                                        tempdata+=sizeof(int32_t);
493
                                        *((int32_t *)tempdata) = frame->type;
494
                                        tempdata+=sizeof(int32_t);
495
                                        
496
                                        memcpy(chunk->data+chunk->payload_len+sizeFrame,outbuf,out_size); // insert new data
497
                                        chunk->payload_len += out_size + sizeFrame; // update payload length
498
                                        //fprintf(stderr, "outsize:%d payload_len:%d\n",out_size,chunk->payload_len);
499
                                        chunk->len = sizeChunk+chunk->payload_len ; // update overall length
500
                                        
501
                                        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) {
502
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
503
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
504
                                        }
505
                                        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) {
506
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
507
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
508
                                        }
509
        
510
                                        if(chunkFilled(chunk, cmeta)) { // is chunk filled using current strategy?
511
                                                //SAVE ON FILE
512
                                                //saveChunkOnFile(chunk);
513
                                                //Send the chunk via http to an external transport/player
514
                                                pushChunkHttp(chunk, cmeta->outside_world_url);
515
                                                initChunk(chunk, &seq_current_chunk);
516
                                        }
517
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
518
                                }
519
                        }
520
                }
521
                else if(packet.stream_index==audioStream) {
522
                        data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
523
                        if(avcodec_decode_audio3(aCodecCtx, audio_buf, &data_size, &packet)>0) {
524
#ifdef DEBUG_AUDIO_FRAMES
525
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
526
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
527
#endif
528
                                if(data_size>0) {
529
#ifdef DEBUG_AUDIO_FRAMES
530
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", data_size);
531
#endif
532
                                        /* if a frame has been decoded, output it */
533
                                        //fwrite(audio_buf, 1, data_size, outfileaudio);
534
                                }
535
                                else
536
                                        continue;
537
        
538
                                audio_size = avcodec_encode_audio(aCodecCtxEnc,outbuf_audio,data_size,audio_buf);
539
                                frame->number = contFrameAudio;
540

    
541
                                if(frame->number==0) {
542
                                        if(packet.dts==AV_NOPTS_VALUE)
543
                                                continue;
544
                                        last_pkt_dts_audio = packet.dts;
545
                                        newTime = 0;
546
                                }
547
                                else {
548
                                        if(packet.dts!=AV_NOPTS_VALUE) {
549
                                                delta_audio = packet.dts-last_pkt_dts_audio;
550
/*
551
                                                DeltaTimeAudio=(((double)packet.dts-last_pkt_dts_audio)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));
552
                                                if(DeltaTimeAudio<0) DeltaTimeAudio=10;
553
                                                if(DeltaTimeAudio>1500) DeltaTimeAudio=1500;
554
*/
555
                                                last_pkt_dts_audio = packet.dts;
556
                                        }
557
                                        else if(delta_audio==0)
558
                                                continue;
559
                                }
560

    
561
                                //use pts if dts is invalid
562
                                if(packet.dts!=AV_NOPTS_VALUE)
563
                                        target_pts = packet.dts;
564
                                else if(packet.pts!=AV_NOPTS_VALUE)
565
                                        target_pts = packet.pts;
566
                                else
567
                                        continue;
568

    
569
                                if(!live_source)
570
                                {
571
                                        if(FirstTimeAudio && packet.pts>0) {
572
                                                //maintain the offset between audio pts and video pts
573
                                                //because in case of live source they have the same numbering
574
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
575
                                                        ptsaudio1 = ptsvideo1;
576
                                                else
577
                                                        ptsaudio1 = (double)packet.dts;
578
                                                FirstTimeAudio = 0;
579
#ifdef DEBUG_AUDIO_FRAMES
580
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %f\n", ptsaudio1);
581
#endif
582
                                        }
583
                                        if(frame->number>0) {
584
                                                        if(ptsaudio1>0)
585
                                                                //use audio-based timestamps when available (both for video and audio frames)
586
                                                                newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
587
                                                        else
588
                                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
589
                                        }
590
                                }
591
                                else //live source
592
                                {
593
                                        if(FirstTimeAudio && packet.pts>0) {
594
                                                //maintain the offset between audio pts and video pts
595
                                                //because in case of live source they have the same numbering
596
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
597
                                                        ptsaudio1 = ptsvideo1;
598
                                                else
599
                                                        ptsaudio1 = (double)packet.dts;
600
                                                FirstTimeAudio = 0;
601
#ifdef DEBUG_AUDIO_FRAMES
602
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
603
#endif
604
                                        }
605

    
606
                                        if(frame->number>0) {
607
                                                        //if(ptsaudio1>0)
608
                                                                //use audio-based timestamps when available (both for video and audio frames)
609
                                                                newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
610
                                                        //else
611
                                                        //        newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
612
                                        }
613
                                        //this was for on-the-fly timestamping
614
                                        //newTime=Now-StartTime;
615
                                }
616
#ifdef DEBUG_AUDIO_FRAMES
617
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
618
#endif
619
                                if(newTime<0) {
620
#ifdef DEBUG_AUDIO_FRAMES
621
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
622
#endif
623
                                        continue; //SKIP THIS FRAME, bad timestamp
624
                                }
625

    
626
                                frame->timestamp.tv_sec = (unsigned int)newTime/1000;
627
                                frame->timestamp.tv_usec = newTime%1000;
628
#ifdef DEBUG_AUDIO_FRAMES
629
                                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);
630
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
631
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
632
#endif
633

    
634
                                frame->size = audio_size;
635
                                frame->type = 5; // 5 is audio type
636

    
637
                                chunkaudio->data = (uint8_t *)realloc(chunkaudio->data,sizeof(uint8_t)*(chunkaudio->payload_len+audio_size+sizeFrame));
638
                                if(!chunkaudio->data) {
639
                                        fprintf(stderr, "Memory error AUDIO chunk!!!\n");
640
                                        return -1;
641
                                }
642
                                chunkaudio->frames_num++; // number of frames in the current chunk
643
                                contFrameAudio++;
644
                                tempdata = chunkaudio->data+chunkaudio->payload_len;
645
                                *((int32_t *)tempdata) = frame->number;
646
                                tempdata+=sizeof(int32_t);
647
                                *((struct timeval *)tempdata) = frame->timestamp;
648
                                tempdata+=sizeof(struct timeval);
649
                                *((int32_t *)tempdata) = frame->size;
650
                                tempdata+=sizeof(int32_t);
651
                                *((int32_t *)tempdata) = frame->type;
652
                                tempdata+=sizeof(int32_t);
653
                                        
654
                                memcpy(chunkaudio->data+chunkaudio->payload_len+sizeFrame,outbuf_audio,audio_size);
655
                                chunkaudio->payload_len += audio_size + sizeFrame; // update payload length
656
                                        //fprintf(stderr, "outsize:%d payload_len:%d\n",out_size,chunk->payload_len);
657
                                chunkaudio->len = sizeChunk+chunkaudio->payload_len ; // update overall length
658
                                
659
                                if(((int)frame->timestamp.tv_sec < (int)chunkaudio->start_time.tv_sec) || ((int)frame->timestamp.tv_sec==(int)chunkaudio->start_time.tv_sec && (int)frame->timestamp.tv_usec < (int)chunkaudio->start_time.tv_usec) || (int)chunkaudio->start_time.tv_sec==-1) {
660
                                        chunkaudio->start_time.tv_sec = frame->timestamp.tv_sec;
661
                                        chunkaudio->start_time.tv_usec = frame->timestamp.tv_usec;
662
                                }
663
                                if(((int)frame->timestamp.tv_sec > (int)chunkaudio->end_time.tv_sec) || ((int)frame->timestamp.tv_sec==(int)chunkaudio->end_time.tv_sec && (int)frame->timestamp.tv_usec > (int)chunkaudio->end_time.tv_usec) || (int)chunkaudio->end_time.tv_sec==-1) {
664
                                        chunkaudio->end_time.tv_sec = frame->timestamp.tv_sec;
665
                                        chunkaudio->end_time.tv_usec = frame->timestamp.tv_usec;
666
                                }
667

    
668
                                //set priority
669
                                chunkaudio->priority = 1;
670

    
671
                                if(chunkFilled(chunkaudio, cmeta)) { // is chunk filled using current strategy?
672
                                        //SAVE ON FILE
673
                                        //saveChunkOnFile(chunkaudio);
674
                                        //Send the chunk via http to an external transport/player
675
                                        pushChunkHttp(chunkaudio, cmeta->outside_world_url);
676
                                        initChunk(chunkaudio, &seq_current_chunk+1);
677
                                }
678
                        }
679
                }
680
                else {
681
#ifdef DEBUG_AUDIO_FRAMES
682
                        fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
683
#endif
684
                        av_free_packet(&packet);
685
                }
686
        }
687

    
688
        if(chunk->frames_num>0) {
689
                //SAVE ON FILE
690
                //saveChunkOnFile(chunk);
691
                //Send the chunk via http to an external transport/player
692
                pushChunkHttp(chunk, cmeta->outside_world_url);
693
        }
694
        if(chunkaudio->frames_num>0) {
695
                //SAVE ON FILE
696
                //saveChunkOnFile(chunkaudio);
697
                //Send the chunk via http to an external transport/player
698
                pushChunkHttp(chunkaudio, cmeta->outside_world_url);
699
        }
700

    
701
        /* finalize the HTTP chunk pusher */
702
        finalizeChunkPusher();
703

    
704
        free(chunk);
705
        free(chunkaudio);
706
        free(frame);
707
        free(outbuf);
708
        free(outbuf_audio);
709
        free(cmeta);
710

    
711
        // Free the YUV frame
712
        av_free(pFrame);
713
        av_free(audio_buf);
714
  
715
        // Close the codec
716
        avcodec_close(pCodecCtx);
717
        avcodec_close(pCodecCtxEnc);
718

    
719
        if(audioStream!=-1) {
720
                avcodec_close(aCodecCtx);
721
                avcodec_close(aCodecCtxEnc);
722
        }
723
  
724
        // Close the video file
725
        av_close_input_file(pFormatCtx);
726
        return 0;
727
}