Statistics
| Branch: | Revision:

chunker-player / chunker_streamer / chunker_streamer.c @ df2ad829

History | View | Annotate | Download (27.3 KB)

1 34149271 GiuseppeTropea
// chunker_streamer.c
2 1e69ae95 GiuseppeTropea
// Author 
3
// Diego Reforgiato
4
// Giuseppe Tropea
5 34149271 GiuseppeTropea
// Dario Marchese
6
// Carmelo Daniele
7 1e69ae95 GiuseppeTropea
//
8 34149271 GiuseppeTropea
// Use the file compile.localffmpeg.static to build the program
9
10 1e69ae95 GiuseppeTropea
11
#include "chunker_streamer.h"
12 8b52d5cf GiuseppeTropea
13 1e69ae95 GiuseppeTropea
14 df2ad829 GiuseppeTropea
//#define DEBUG_AUDIO_FRAMES
15
//#define DEBUG_VIDEO_FRAMES
16 269f1314 GiuseppeTropea
#define DEBUG_CHUNKER
17 eb0c9035 GiuseppeTropea
#define DEBUG_ANOMALIES
18 df2ad829 GiuseppeTropea
#define DEBUG_TIMESTAMPING
19 11e39d44 GiuseppeTropea
20 69fd123e GiuseppeTropea
#define MAX(a,b) ((a>b)?(a):(b))
21
22 648357d7 GiuseppeTropea
ChunkerMetadata *cmeta = NULL;
23 269f1314 GiuseppeTropea
int seq_current_chunk = 1; //chunk numbering starts from 1; HINT do i need more bytes?
24 1e69ae95 GiuseppeTropea
25
26
int chunkFilled(ExternalChunk *echunk, ChunkerMetadata *cmeta) {
27
        // different strategies to implement
28 269f1314 GiuseppeTropea
        if(cmeta->strategy == 0) { // number of frames per chunk constant
29
#ifdef DEBUG_CHUNKER
30
                fprintf(stderr, "CHUNKER: check if frames num %d == %d in chunk %d\n", echunk->frames_num, cmeta->val_strategy, echunk->seq);
31
#endif
32 34149271 GiuseppeTropea
                if(echunk->frames_num == cmeta->val_strategy)
33 1e69ae95 GiuseppeTropea
                        return 1;
34 269f1314 GiuseppeTropea
  }
35 1e69ae95 GiuseppeTropea
        
36 34149271 GiuseppeTropea
        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
37
                if(echunk->payload_len >= cmeta->val_strategy)
38 1e69ae95 GiuseppeTropea
                        return 1;
39
        
40
        return 0;
41
}
42
43
44 34149271 GiuseppeTropea
void initChunk(ExternalChunk *chunk, int *seq_num) {
45 1e69ae95 GiuseppeTropea
        chunk->seq = (*seq_num)++;
46
        chunk->frames_num = 0;
47
        chunk->payload_len = 0;
48
        chunk->len=0;
49 26379a77 GiuseppeTropea
  if(chunk->data != NULL)
50
    free(chunk->data);
51 1e69ae95 GiuseppeTropea
        chunk->data = NULL;
52
        chunk->start_time.tv_sec = -1;
53
        chunk->start_time.tv_usec = -1;
54
        chunk->end_time.tv_sec = -1;
55
        chunk->end_time.tv_usec = -1;
56
        chunk->priority = 0;
57
        chunk->category = 0;
58
        chunk->_refcnt = 0;
59
}
60
61 8b52d5cf GiuseppeTropea
62 1e69ae95 GiuseppeTropea
int main(int argc, char *argv[]) {
63 34149271 GiuseppeTropea
        int i=0;
64 648357d7 GiuseppeTropea
65
        //output variables
66
        uint8_t *video_outbuf = NULL;
67
        int video_outbuf_size, video_frame_size;
68
        uint8_t *audio_outbuf = NULL;
69
        int audio_outbuf_size, audio_frame_size;
70
        int audio_data_size;
71
72
        //numeric identifiers of input streams
73
        int videoStream = -1;
74
        int audioStream = -1;
75
76
        int len1;
77 1e69ae95 GiuseppeTropea
        int frameFinished;
78 648357d7 GiuseppeTropea
        //frame sequential counters
79 269f1314 GiuseppeTropea
        int contFrameAudio=1, contFrameVideo=1;
80 648357d7 GiuseppeTropea
        int numBytes;
81
82
        //command line parameters
83 1e69ae95 GiuseppeTropea
        int audio_bitrate;
84
        int video_bitrate;
85 c75b5711 GiuseppeTropea
        int live_source = 0; //tells to sleep before reading next frame in not live (i.e. file)
86
        int offset_av = 0; //tells to compensate for offset between audio and video in the file
87 1e69ae95 GiuseppeTropea
        
88 648357d7 GiuseppeTropea
        //a raw buffer for decoded uncompressed audio samples
89
        int16_t *samples = NULL;
90
        //a raw uncompressed video picture
91
        AVFrame *pFrame = NULL;
92 11e39d44 GiuseppeTropea
93 1e69ae95 GiuseppeTropea
        AVFormatContext *pFormatCtx;
94
        AVCodecContext  *pCodecCtx,*pCodecCtxEnc,*aCodecCtxEnc,*aCodecCtx;
95
        AVCodec         *pCodec,*pCodecEnc,*aCodec,*aCodecEnc;
96
        AVPacket         packet;
97
98 648357d7 GiuseppeTropea
        //stuff needed to compute the right timestamps
99 1e69ae95 GiuseppeTropea
        short int FirstTimeAudio=1, FirstTimeVideo=1;
100 eb0c9035 GiuseppeTropea
        short int pts_anomalies_counter=0;
101 df2ad829 GiuseppeTropea
        short int newtime_anomalies_counter=0;
102 69fd123e GiuseppeTropea
        long long newTime=0, newTime_audio=0, newTime_prev=0;
103
        struct timeval lastAudioSent = {0, 0};
104 34149271 GiuseppeTropea
        double ptsvideo1=0.0;
105
        double ptsaudio1=0.0;
106 648357d7 GiuseppeTropea
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
107
108 8b52d5cf GiuseppeTropea
        //Napa-Wine specific Frame and Chunk structures for transport
109
        Frame *frame = NULL;
110
        ExternalChunk *chunk = NULL;
111
        ExternalChunk *chunkaudio = NULL;
112
113 648357d7 GiuseppeTropea
114
        //scan the command line
115 1e69ae95 GiuseppeTropea
        if(argc < 4) {
116 c75b5711 GiuseppeTropea
                fprintf(stderr, "execute ./chunker_streamer moviefile audiobitrate videobitrate <live source flag (0 or 1)> <offset av flag (0 or 1)>\n");
117 1e69ae95 GiuseppeTropea
                return -1;
118
        }
119 34149271 GiuseppeTropea
        sscanf(argv[2],"%d", &audio_bitrate);
120
        sscanf(argv[3],"%d", &video_bitrate);
121 c75b5711 GiuseppeTropea
        if(argc>=5) sscanf(argv[4],"%d", &live_source);
122
        if(argc==6) sscanf(argv[5],"%d", &offset_av);
123 34149271 GiuseppeTropea
124 ac723195 GiuseppeTropea
restart:
125 34149271 GiuseppeTropea
        // read the configuration file
126
        cmeta = chunkerInit();
127
        if(live_source)
128
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
129 c75b5711 GiuseppeTropea
        if(offset_av)
130
                fprintf(stderr, "INIT: Compensating AV OFFSET in file\n");
131 1e69ae95 GiuseppeTropea
132
        // Register all formats and codecs
133
        av_register_all();
134
135 648357d7 GiuseppeTropea
        // Open input file
136 34149271 GiuseppeTropea
        if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) != 0) {
137
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
138
                exit(-1);
139
        }
140
141 1e69ae95 GiuseppeTropea
        // Retrieve stream information
142 34149271 GiuseppeTropea
        if(av_find_stream_info(pFormatCtx) < 0) {
143
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
144
                exit(-1);
145
        }
146
147 1e69ae95 GiuseppeTropea
        // Dump information about file onto standard error
148
        dump_format(pFormatCtx, 0, argv[1], 0);
149 34149271 GiuseppeTropea
150 648357d7 GiuseppeTropea
        // Find the video and audio stream numbers
151 1e69ae95 GiuseppeTropea
        for(i=0; i<pFormatCtx->nb_streams; i++) {
152
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
153
                        videoStream=i;
154
                }
155
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
156
                        audioStream=i;
157
                }
158
        }
159 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);
160 e810bf7b GiuseppeTropea
161 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
162
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
163
164
        if(videoStream==-1 && audioStream==-1) {
165
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
166
                exit(-1);
167
        }
168 1e69ae95 GiuseppeTropea
169 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input video stream
170 1e69ae95 GiuseppeTropea
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
171
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
172 648357d7 GiuseppeTropea
        //extract W and H
173
        fprintf(stderr, "INIT: Width:%d Height:%d\n", pCodecCtx->width, pCodecCtx->height);
174 1e69ae95 GiuseppeTropea
175 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input audio stream
176
        if(audioStream != -1) {
177 1e69ae95 GiuseppeTropea
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
178 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
179 1e69ae95 GiuseppeTropea
        }
180
181 648357d7 GiuseppeTropea
        //setup video output encoder
182 1e69ae95 GiuseppeTropea
        pCodecCtxEnc=avcodec_alloc_context();
183 e810bf7b GiuseppeTropea
#ifdef H264_VIDEO_ENCODER
184 11e39d44 GiuseppeTropea
        pCodecCtxEnc->me_range=16;
185
        pCodecCtxEnc->max_qdiff=4;
186
        pCodecCtxEnc->qmin=10;
187
        pCodecCtxEnc->qmax=51;
188
        pCodecCtxEnc->qcompress=0.6;
189 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
190 11e39d44 GiuseppeTropea
        pCodecCtxEnc->codec_id   = CODEC_ID_H264;//13;//pCodecCtx->codec_id;
191 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->bit_rate = video_bitrate;///400000;
192
        // resolution must be a multiple of two 
193
        pCodecCtxEnc->width = pCodecCtx->width;
194
        pCodecCtxEnc->height = pCodecCtx->height;
195
        // frames per second 
196 11e39d44 GiuseppeTropea
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
197 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
198
        //pCodecCtxEnc->max_b_frames=1;
199
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
200 4c879040 GiuseppeTropea
201
        pCodecCtxEnc->bit_rate_tolerance = video_bitrate;
202
        pCodecCtxEnc->rc_min_rate = 0;
203
        pCodecCtxEnc->rc_max_rate = 0;
204
        pCodecCtxEnc->rc_buffer_size = 0;
205
        pCodecCtxEnc->flags |= CODEC_FLAG_PSNR;
206
        pCodecCtxEnc->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
207
        pCodecCtxEnc->crf = 0.0f;
208
209 e810bf7b GiuseppeTropea
#else
210
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
211
        pCodecCtxEnc->codec_id   = CODEC_ID_MPEG4;
212
        pCodecCtxEnc->bit_rate = video_bitrate;
213
        pCodecCtxEnc->width = pCodecCtx->width;
214
        pCodecCtxEnc->height = pCodecCtx->height;
215
        // frames per second 
216
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
217
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
218
        //pCodecCtxEnc->max_b_frames=1;
219
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
220
#endif
221 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);
222 e810bf7b GiuseppeTropea
223 648357d7 GiuseppeTropea
        // Find the decoder for the video stream
224
#ifdef H264_VIDEO_ENCODER
225
        fprintf(stderr, "INIT: Setting VIDEO codecID to H264: %d %d\n",pCodecCtx->codec_id, CODEC_ID_H264);
226
        pCodecEnc = avcodec_find_encoder(CODEC_ID_H264);//pCodecCtx->codec_id);
227
#else
228
        fprintf(stderr, "INIT: Setting VIDEO codecID to mpeg4: %d %d\n",pCodecCtx->codec_id, CODEC_ID_MPEG4);
229
        pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG4);
230
#endif
231
        if(pCodec==NULL) {
232
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
233
                return -1; // Codec not found
234
        }
235
        if(pCodecEnc==NULL) {
236
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
237
                return -1; // Codec not found
238
        }
239
        if(avcodec_open(pCodecCtx, pCodec)<0) {
240
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
241
                return -1; // Could not open codec
242
        }
243
        if(avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
244
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
245
                return -1; // Could not open codec
246
        }
247 1e69ae95 GiuseppeTropea
248 648357d7 GiuseppeTropea
249
        //setup audio output encoder
250 1e69ae95 GiuseppeTropea
        aCodecCtxEnc = avcodec_alloc_context();
251 11e39d44 GiuseppeTropea
        aCodecCtxEnc->bit_rate = audio_bitrate; //256000
252 1e69ae95 GiuseppeTropea
        aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
253 11e39d44 GiuseppeTropea
        aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
254
        aCodecCtxEnc->channels = aCodecCtx->channels;
255 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
256 1e69ae95 GiuseppeTropea
257 648357d7 GiuseppeTropea
        // Find the decoder for the audio stream
258 1e69ae95 GiuseppeTropea
        if(audioStream!=-1) {
259
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
260 e810bf7b GiuseppeTropea
#ifdef MP3_AUDIO_ENCODER
261 11e39d44 GiuseppeTropea
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP3);
262 e810bf7b GiuseppeTropea
#else
263
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP2);
264
#endif
265 1e69ae95 GiuseppeTropea
                if(aCodec==NULL) {
266 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
267 1e69ae95 GiuseppeTropea
                        return -1;
268
                }
269
                if(aCodecEnc==NULL) {
270 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
271 1e69ae95 GiuseppeTropea
                        return -1;
272
                }
273
        
274
                if(avcodec_open(aCodecCtx, aCodec)<0) {
275 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
276 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
277
                }
278
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
279 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
280 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
281
                }
282
        }
283 648357d7 GiuseppeTropea
284
        // Allocate audio in and out buffers
285
        samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
286
        if(samples == NULL) {
287
                fprintf(stderr, "INIT: Memory error alloc audio samples!!!\n");
288
                return -1;
289 1e69ae95 GiuseppeTropea
        }
290 648357d7 GiuseppeTropea
        audio_outbuf_size = STREAMER_MAX_AUDIO_BUFFER_SIZE;
291
        audio_outbuf = av_malloc(audio_outbuf_size);
292
        if(audio_outbuf == NULL) {
293
                fprintf(stderr, "INIT: Memory error alloc audio_outbuf!!!\n");
294
                return -1;
295 1e69ae95 GiuseppeTropea
        }
296
297 648357d7 GiuseppeTropea
        // Allocate video in frame and out buffer
298 1e69ae95 GiuseppeTropea
        pFrame=avcodec_alloc_frame();
299
        if(pFrame==NULL) {
300 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
301 1e69ae95 GiuseppeTropea
                return -1;
302
        }
303 648357d7 GiuseppeTropea
        video_outbuf_size = STREAMER_MAX_VIDEO_BUFFER_SIZE;
304
        video_outbuf = av_malloc(video_outbuf_size);
305
        if(!video_outbuf) {
306
                fprintf(stderr, "INIT: Memory error alloc video_outbuf!!!\n");
307 1e69ae95 GiuseppeTropea
                return -1;
308
        }
309 648357d7 GiuseppeTropea
310
        //allocate Napa-Wine transport
311 1e69ae95 GiuseppeTropea
        frame = (Frame *)malloc(sizeof(Frame));
312
        if(!frame) {
313 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
314 1e69ae95 GiuseppeTropea
                return -1;
315
        }
316 269f1314 GiuseppeTropea
        //create an empty first video chunk
317 1e69ae95 GiuseppeTropea
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
318
        if(!chunk) {
319 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
320 1e69ae95 GiuseppeTropea
                return -1;
321
        }
322 269f1314 GiuseppeTropea
        chunk->data = NULL;
323
        chunk->seq = 0;
324
        //initChunk(chunk, &seq_current_chunk); if i init them now i get out of sequence
325 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
326
        fprintf(stderr, "INIT: chunk video %d\n", chunk->seq);
327
#endif
328 269f1314 GiuseppeTropea
        //create empty first audio chunk
329 1e69ae95 GiuseppeTropea
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
330
        if(!chunkaudio) {
331 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
332 1e69ae95 GiuseppeTropea
                return -1;
333
        }
334 648357d7 GiuseppeTropea
  chunkaudio->data=NULL;
335 269f1314 GiuseppeTropea
        chunkaudio->seq = 0;
336
        //initChunk(chunkaudio, &seq_current_chunk);
337 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
338
        fprintf(stderr, "INIT: chunk audio %d\n", chunkaudio->seq);
339
#endif
340 1e69ae95 GiuseppeTropea
341
        /* initialize the HTTP chunk pusher */
342 8de6681e GiuseppeTropea
        initChunkPusher(); //TRIPLO
343 1e69ae95 GiuseppeTropea
344 4c879040 GiuseppeTropea
        long sleep=0;
345 69fd123e GiuseppeTropea
        struct timeval now_tv;
346
        struct timeval tmp_tv;
347
        long long lateTime = 0;
348
        long long maxAudioInterval = 0;
349
        long long maxVDecodeTime = 0;
350 ac723195 GiuseppeTropea
351 648357d7 GiuseppeTropea
        //main loop to read from the input file
352 69fd123e GiuseppeTropea
        while(av_read_frame(pFormatCtx, &packet)>=0)
353
        {
354 4c879040 GiuseppeTropea
                //detect if a strange number of anomalies is occurring
355 eb0c9035 GiuseppeTropea
                if(ptsvideo1 < 0 || ptsvideo1 > packet.dts || ptsaudio1 < 0 || ptsaudio1 > packet.dts) {
356
                        pts_anomalies_counter++;
357
#ifdef DEBUG_ANOMALIES
358
                        fprintf(stderr, "READLOOP: pts BASE anomaly detected number %d\n", pts_anomalies_counter);
359
#endif
360
                        if(live_source) { //reset just in case of live source
361
                                if(pts_anomalies_counter > 25) { //just a random threshold
362
                                        pts_anomalies_counter = 0;
363
                                        FirstTimeVideo = 1;
364
                                        FirstTimeAudio = 1;
365
#ifdef DEBUG_ANOMALIES
366
                                        fprintf(stderr, "READLOOP: too many pts BASE anomalies. resetting pts base\n");
367
#endif
368
                                }
369
                        }
370
                }
371
372 df2ad829 GiuseppeTropea
                if(newtime_anomalies_counter > 50) { //just a random threshold
373
                        if(live_source) { //restart just in case of live source
374
#ifdef DEBUG_ANOMALIES
375
                                fprintf(stderr, "READLOOP: too many NEGATIVE TIMESTAMPS anomalies. Restarting.\n");
376
#endif
377
                                goto close;
378
                        }
379
                }
380
381 1e69ae95 GiuseppeTropea
                // Is this a packet from the video stream?
382 69fd123e GiuseppeTropea
                if(packet.stream_index==videoStream)
383
                {
384
                        if(!live_source)
385
                        {
386
                                // lateTime < 0 means a positive time account that can be used to decode video frames
387
                                // if (lateTime + maxVDecodeTime) >= 0 then we may have a negative time account after video transcoding
388
                                // therefore, it's better to skip the frame
389
                                if((lateTime+maxVDecodeTime) >= 0)
390
                                {
391
#ifdef DEBUG_ANOMALIES
392
                                        fprintf(stderr, "\n\n\t\t************************* SKIPPING VIDEO FRAME ***********************************\n\n", sleep);
393
#endif
394
                                        continue;
395
                                }
396
                        }
397
                        
398
                        gettimeofday(&tmp_tv, NULL);
399
                        
400 648357d7 GiuseppeTropea
                        //decode the video packet into a raw pFrame
401 69fd123e GiuseppeTropea
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0)
402
                        {
403
                                // usleep(5000);
404 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
405 269f1314 GiuseppeTropea
                                fprintf(stderr, "\n-------VIDEO FRAME type %d\n", pFrame->pict_type);
406 34149271 GiuseppeTropea
                                fprintf(stderr, "VIDEO: dts %lld pts %lld\n", packet.dts, packet.pts);
407 e810bf7b GiuseppeTropea
#endif
408 11e39d44 GiuseppeTropea
                                if(frameFinished) { // it must be true all the time else error
409 34149271 GiuseppeTropea
                                        frame->number = contFrameVideo;
410 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
411 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
412 e810bf7b GiuseppeTropea
#endif
413
                                        if(frame->number==0) {
414
                                                if(packet.dts==AV_NOPTS_VALUE)
415 34149271 GiuseppeTropea
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
416 e810bf7b GiuseppeTropea
                                                        continue;
417
                                                last_pkt_dts = packet.dts;
418
                                                newTime = 0;
419
                                        }
420
                                        else {
421
                                                if(packet.dts!=AV_NOPTS_VALUE) {
422 34149271 GiuseppeTropea
                                                        delta_video = packet.dts-last_pkt_dts;
423 e810bf7b GiuseppeTropea
                                                        last_pkt_dts = packet.dts;
424
                                                }
425 34149271 GiuseppeTropea
                                                else if(delta_video==0)
426
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
427 e810bf7b GiuseppeTropea
                                                        continue;
428
                                        }
429
#ifdef DEBUG_VIDEO_FRAMES
430 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
431 e810bf7b GiuseppeTropea
#endif
432 648357d7 GiuseppeTropea
                                        video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, pFrame);
433 69fd123e GiuseppeTropea
                                        if(video_frame_size <= 0)
434
                                                continue;
435 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
436 269f1314 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: original codec frame number %d vs. encoded %d vs. packed %d\n", pCodecCtx->frame_number, pCodecCtxEnc->frame_number, frame->number);
437 34149271 GiuseppeTropea
                                        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);
438 11e39d44 GiuseppeTropea
#endif
439 e810bf7b GiuseppeTropea
440 34149271 GiuseppeTropea
                                        //use pts if dts is invalid
441
                                        if(packet.dts!=AV_NOPTS_VALUE)
442
                                                target_pts = packet.dts;
443
                                        else if(packet.pts!=AV_NOPTS_VALUE)
444
                                                target_pts = packet.pts;
445 11e39d44 GiuseppeTropea
                                        else
446 34149271 GiuseppeTropea
                                                continue;
447
448 c75b5711 GiuseppeTropea
                                        if(!offset_av)
449 34149271 GiuseppeTropea
                                        {
450 eb0c9035 GiuseppeTropea
                                                if(FirstTimeVideo && packet.dts>0) {
451 34149271 GiuseppeTropea
                                                        ptsvideo1 = (double)packet.dts;
452
                                                        FirstTimeVideo = 0;
453 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
454 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %f\n", ptsvideo1);
455 11e39d44 GiuseppeTropea
#endif
456 34149271 GiuseppeTropea
                                                }
457
                                        }
458 7ea4a367 GiuseppeTropea
                                        else //we want to compensate audio and video offset for this source
459 34149271 GiuseppeTropea
                                        {
460
                                                if(FirstTimeVideo && packet.dts>0) {
461
                                                        //maintain the offset between audio pts and video pts
462
                                                        //because in case of live source they have the same numbering
463
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
464
                                                                ptsvideo1 = ptsaudio1;
465
                                                        else
466
                                                                ptsvideo1 = (double)packet.dts;
467
                                                        FirstTimeVideo = 0;
468 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
469 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %f\n", ptsvideo1);
470 11e39d44 GiuseppeTropea
#endif
471 34149271 GiuseppeTropea
                                                }
472 4c879040 GiuseppeTropea
                                        }
473
                                        //compute the new video timestamp in milliseconds
474
                                        if(frame->number>0) {
475
                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
476 11e39d44 GiuseppeTropea
                                        }
477 df2ad829 GiuseppeTropea
#ifdef DEBUG_TIMESTAMPING
478 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
479 e810bf7b GiuseppeTropea
#endif
480 34149271 GiuseppeTropea
                                        if(newTime<0) {
481
#ifdef DEBUG_VIDEO_FRAMES
482
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
483
#endif
484 df2ad829 GiuseppeTropea
                                                newtime_anomalies_counter++;
485 34149271 GiuseppeTropea
                                                continue; //SKIP THIS FRAME, bad timestamp
486
                                        }
487 e810bf7b GiuseppeTropea
        
488
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
489 11e39d44 GiuseppeTropea
                                        frame->timestamp.tv_usec = newTime%1000;
490 648357d7 GiuseppeTropea
                                        frame->size = video_frame_size;
491 11e39d44 GiuseppeTropea
                                        frame->type = pFrame->pict_type;
492
#ifdef DEBUG_VIDEO_FRAMES
493 269f1314 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: encapsulated frame size:%d type:%d\n", frame->size, frame->type);
494 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
495 11e39d44 GiuseppeTropea
#endif
496 648357d7 GiuseppeTropea
                                        contFrameVideo++; //lets increase the numbering of the frames
497 e810bf7b GiuseppeTropea
498 648357d7 GiuseppeTropea
                                        if(update_chunk(chunk, frame, video_outbuf) == -1) {
499
                                                fprintf(stderr, "VIDEO: unable to update chunk %d. Exiting.\n", chunk->seq);
500
                                                exit(-1);
501 11e39d44 GiuseppeTropea
                                        }
502 648357d7 GiuseppeTropea
503 34149271 GiuseppeTropea
                                        if(chunkFilled(chunk, cmeta)) { // is chunk filled using current strategy?
504 11e39d44 GiuseppeTropea
                                                //SAVE ON FILE
505 34149271 GiuseppeTropea
                                                //saveChunkOnFile(chunk);
506
                                                //Send the chunk via http to an external transport/player
507
                                                pushChunkHttp(chunk, cmeta->outside_world_url);
508 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
509 269f1314 GiuseppeTropea
                                                fprintf(stderr, "VIDEO: sent chunk video %d\n", chunk->seq);
510 51ba8aaa GiuseppeTropea
#endif
511 269f1314 GiuseppeTropea
                                                chunk->seq = 0; //signal that we need an increase
512
                                                //initChunk(chunk, &seq_current_chunk);
513 69fd123e GiuseppeTropea
                                                
514
                                                gettimeofday(&now_tv, NULL);
515
                                                long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
516
                                                usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
517
                                                
518
                                                if(usec > maxVDecodeTime)
519
                                                        maxVDecodeTime = usec;
520 11e39d44 GiuseppeTropea
                                        }
521
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
522
                                }
523
                        }
524
                }
525 69fd123e GiuseppeTropea
                else if(packet.stream_index==audioStream)
526
                {
527
                        if(sleep > 0)
528
                        {
529
#ifdef DEBUG_ANOMALIES
530
                                fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
531
#endif
532
                                usleep(sleep);
533
                        }
534
                        
535 648357d7 GiuseppeTropea
                        audio_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
536
                        //decode the audio packet into a raw audio source buffer
537 69fd123e GiuseppeTropea
                        if(avcodec_decode_audio3(aCodecCtx, samples, &audio_data_size, &packet)>0)
538
                        {
539 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
540 34149271 GiuseppeTropea
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
541
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
542 11e39d44 GiuseppeTropea
#endif
543 648357d7 GiuseppeTropea
                                if(audio_data_size>0) {
544 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
545 648357d7 GiuseppeTropea
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", audio_data_size);
546 11e39d44 GiuseppeTropea
#endif
547 e810bf7b GiuseppeTropea
                                        /* if a frame has been decoded, output it */
548 648357d7 GiuseppeTropea
                                        //fwrite(samples, 1, audio_data_size, outfileaudio);
549 11e39d44 GiuseppeTropea
                                }
550 e810bf7b GiuseppeTropea
                                else
551 34149271 GiuseppeTropea
                                        continue;
552 e810bf7b GiuseppeTropea
        
553 648357d7 GiuseppeTropea
                                audio_frame_size = avcodec_encode_audio(aCodecCtxEnc, audio_outbuf, audio_data_size, samples);
554 69fd123e GiuseppeTropea
                                if(audio_frame_size <= 0)
555
                                        continue;
556
                                
557 34149271 GiuseppeTropea
                                frame->number = contFrameAudio;
558
559 e810bf7b GiuseppeTropea
                                if(frame->number==0) {
560
                                        if(packet.dts==AV_NOPTS_VALUE)
561
                                                continue;
562
                                        last_pkt_dts_audio = packet.dts;
563
                                        newTime = 0;
564
                                }
565
                                else {
566
                                        if(packet.dts!=AV_NOPTS_VALUE) {
567
                                                delta_audio = packet.dts-last_pkt_dts_audio;
568
                                                last_pkt_dts_audio = packet.dts;
569
                                        }
570
                                        else if(delta_audio==0)
571
                                                continue;
572
                                }
573 269f1314 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
574
                                fprintf(stderr, "AUDIO: original codec frame number %d vs. encoded %d vs. packed %d\n", aCodecCtx->frame_number, aCodecCtxEnc->frame_number, frame->number);
575
#endif
576 34149271 GiuseppeTropea
                                //use pts if dts is invalid
577
                                if(packet.dts!=AV_NOPTS_VALUE)
578
                                        target_pts = packet.dts;
579
                                else if(packet.pts!=AV_NOPTS_VALUE)
580
                                        target_pts = packet.pts;
581 1e69ae95 GiuseppeTropea
                                else
582 34149271 GiuseppeTropea
                                        continue;
583
584 c75b5711 GiuseppeTropea
                                if(!offset_av)
585 34149271 GiuseppeTropea
                                {
586 eb0c9035 GiuseppeTropea
                                        if(FirstTimeAudio && packet.dts>0) {
587
                                                ptsaudio1 = (double)packet.dts;
588 34149271 GiuseppeTropea
                                                FirstTimeAudio = 0;
589 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
590 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %f\n", ptsaudio1);
591 e810bf7b GiuseppeTropea
#endif
592 34149271 GiuseppeTropea
                                        }
593 1e69ae95 GiuseppeTropea
                                }
594 7ea4a367 GiuseppeTropea
                                else //we want to compensate audio and video offset for this source
595 34149271 GiuseppeTropea
                                {
596 eb0c9035 GiuseppeTropea
                                        if(FirstTimeAudio && packet.dts>0) {
597 34149271 GiuseppeTropea
                                                //maintain the offset between audio pts and video pts
598
                                                //because in case of live source they have the same numbering
599
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
600
                                                        ptsaudio1 = ptsvideo1;
601
                                                else
602
                                                        ptsaudio1 = (double)packet.dts;
603
                                                FirstTimeAudio = 0;
604 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
605 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
606 11e39d44 GiuseppeTropea
#endif
607 34149271 GiuseppeTropea
                                        }
608 4c879040 GiuseppeTropea
                                }
609
                                //compute the new audio timestamps in milliseconds
610
                                if(frame->number>0) {
611
                                        newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
612 69fd123e GiuseppeTropea
                                        
613
                                        // store timestamp in useconds for next frame sleep
614
                                        newTime_audio = newTime*1000;
615
                                        
616 34149271 GiuseppeTropea
                                }
617 df2ad829 GiuseppeTropea
#ifdef DEBUG_TIMESTAMPING
618 34149271 GiuseppeTropea
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
619
#endif
620
                                if(newTime<0) {
621
#ifdef DEBUG_AUDIO_FRAMES
622
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
623
#endif
624 df2ad829 GiuseppeTropea
                                        newtime_anomalies_counter++;
625 34149271 GiuseppeTropea
                                        continue; //SKIP THIS FRAME, bad timestamp
626
                                }
627 e810bf7b GiuseppeTropea
628 1e69ae95 GiuseppeTropea
                                frame->timestamp.tv_sec = (unsigned int)newTime/1000;
629
                                frame->timestamp.tv_usec = newTime%1000;
630 648357d7 GiuseppeTropea
                                frame->size = audio_frame_size;
631
                                frame->type = 5; // 5 is audio type
632 34149271 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
633
                                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);
634
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
635
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
636 11e39d44 GiuseppeTropea
#endif
637 34149271 GiuseppeTropea
                                contFrameAudio++;
638
639 648357d7 GiuseppeTropea
                                if(update_chunk(chunkaudio, frame, audio_outbuf) == -1) {
640
                                        fprintf(stderr, "AUDIO: unable to update chunk %d. Exiting.\n", chunkaudio->seq);
641
                                        exit(-1);
642
                                }
643 34149271 GiuseppeTropea
                                //set priority
644 11e39d44 GiuseppeTropea
                                chunkaudio->priority = 1;
645 34149271 GiuseppeTropea
646 69fd123e GiuseppeTropea
                                if(chunkFilled(chunkaudio, cmeta))
647
                                {
648
                                        if(!live_source)
649
                                        {
650
                                                if(newTime_prev != 0)
651
                                                {
652
                                                        long long maxDelay = newTime_audio - newTime_prev;
653
654
                                                        gettimeofday(&now_tv, NULL);
655
                                                        long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
656
                                                        usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
657
658
                                                        if(usec > maxAudioInterval)
659
                                                                maxAudioInterval = usec;
660
661
                                                        lateTime -= (maxDelay - usec);
662
#ifdef DEBUG_ANOMALIES
663
                                                        printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
664
                                                        printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
665
#endif
666
667
                                                        if((lateTime+maxAudioInterval) < 0)
668
                                                                sleep = (lateTime+maxAudioInterval)*-1;
669
                                                        else
670
                                                                sleep = 0;
671
                                                }
672
                                                else
673
                                                        sleep = 0;
674
675
                                                newTime_prev = newTime_audio;
676
                                                gettimeofday(&lastAudioSent, NULL);
677
                                        }
678
                                        
679
                                        // is chunk filled using current strategy?
680 1e69ae95 GiuseppeTropea
                                        //SAVE ON FILE
681 34149271 GiuseppeTropea
                                        //saveChunkOnFile(chunkaudio);
682
                                        //Send the chunk via http to an external transport/player
683
                                        pushChunkHttp(chunkaudio, cmeta->outside_world_url);
684 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
685 269f1314 GiuseppeTropea
                                        fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
686 51ba8aaa GiuseppeTropea
#endif
687 269f1314 GiuseppeTropea
                                        chunkaudio->seq = 0; //signal that we need an increase
688
                                        //initChunk(chunkaudio, &seq_current_chunk);
689 1e69ae95 GiuseppeTropea
                                }
690
                        }
691
                }
692
                else {
693 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
694 11e39d44 GiuseppeTropea
                        fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
695
#endif
696 1e69ae95 GiuseppeTropea
                        av_free_packet(&packet);
697
                }
698
        }
699
700 df2ad829 GiuseppeTropea
close:
701 7ea4a367 GiuseppeTropea
        if(chunk->seq != 0 && chunk->frames_num>0) {
702 1e69ae95 GiuseppeTropea
                //SAVE ON FILE
703 34149271 GiuseppeTropea
                //saveChunkOnFile(chunk);
704
                //Send the chunk via http to an external transport/player
705
                pushChunkHttp(chunk, cmeta->outside_world_url);
706 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
707
                fprintf(stderr, "CHUNKER: SENDING LAST VIDEO CHUNK\n");
708
#endif
709 a573b3de GiuseppeTropea
                chunk->seq = 0; //signal that we need an increase just in case we will restart
710 1e69ae95 GiuseppeTropea
        }
711 7ea4a367 GiuseppeTropea
        if(chunkaudio->seq != 0 && chunkaudio->frames_num>0) {
712 a573b3de GiuseppeTropea
                //SAVE ON FILE     
713 34149271 GiuseppeTropea
                //saveChunkOnFile(chunkaudio);
714
                //Send the chunk via http to an external transport/player
715
                pushChunkHttp(chunkaudio, cmeta->outside_world_url);
716 7ea4a367 GiuseppeTropea
#ifdef DEBUG_CHUNKER
717
                fprintf(stderr, "CHUNKER: SENDING LAST AUDIO CHUNK\n");
718
#endif
719 a573b3de GiuseppeTropea
                chunkaudio->seq = 0; //signal that we need an increase just in case we will restart
720 1e69ae95 GiuseppeTropea
        }
721
722 34149271 GiuseppeTropea
        /* finalize the HTTP chunk pusher */
723 8de6681e GiuseppeTropea
        finalizeChunkPusher();
724 1e69ae95 GiuseppeTropea
725
        free(chunk);
726
        free(chunkaudio);
727
        free(frame);
728 648357d7 GiuseppeTropea
        av_free(video_outbuf);
729
        av_free(audio_outbuf);
730 34149271 GiuseppeTropea
        free(cmeta);
731 1e69ae95 GiuseppeTropea
732
        // Free the YUV frame
733
        av_free(pFrame);
734 648357d7 GiuseppeTropea
        av_free(samples);
735 1e69ae95 GiuseppeTropea
  
736
        // Close the codec
737
        avcodec_close(pCodecCtx);
738
        avcodec_close(pCodecCtxEnc);
739
740
        if(audioStream!=-1) {
741
                avcodec_close(aCodecCtx);
742
                avcodec_close(aCodecCtxEnc);
743
        }
744
  
745
        // Close the video file
746
        av_close_input_file(pFormatCtx);
747 ac723195 GiuseppeTropea
748 0864b2dc GiuseppeTropea
        if(LOOP_MODE) {
749
                //we want video to continue, but the av_read_frame stopped
750 ac723195 GiuseppeTropea
                //lets wait a 5 secs, and cycle in again
751
                usleep(5000000);
752
#ifdef DEBUG_CHUNKER
753
                fprintf(stderr, "CHUNKER: WAITING 5 secs FOR LIVE SOURCE TO SKIP ERRORS AND RESTARTING\n");
754
#endif
755
                videoStream = -1;
756
                audioStream = -1;
757
                FirstTimeAudio=1;
758
                FirstTimeVideo=1;
759
                pts_anomalies_counter=0;
760 df2ad829 GiuseppeTropea
                newtime_anomalies_counter=0;
761 ac723195 GiuseppeTropea
                newTime=0;
762 69fd123e GiuseppeTropea
                newTime_audio=0;
763 ac723195 GiuseppeTropea
                newTime_prev=0;
764
                ptsvideo1=0.0;
765
                ptsaudio1=0.0;
766
                last_pkt_dts=0;
767
                delta_video=0;
768
                delta_audio=0;
769
                last_pkt_dts_audio=0;
770
                target_pts=0;
771
                i=0;
772
                goto restart;
773
        }
774
775 1e69ae95 GiuseppeTropea
        return 0;
776
}
777 648357d7 GiuseppeTropea
778
779
int update_chunk(ExternalChunk *chunk, Frame *frame, uint8_t *outbuf) {
780 8b52d5cf GiuseppeTropea
        //the frame.h gets encoded into 5 slots of 32bits (3 ints plus 2 more for the timeval struct
781
        static int sizeFrameHeader = 5*sizeof(int32_t);
782 648357d7 GiuseppeTropea
783
        //moving temp pointer to encode Frame on the wire
784
        uint8_t *tempdata = NULL;
785
786 269f1314 GiuseppeTropea
        if(chunk->seq == 0) {
787
                initChunk(chunk, &seq_current_chunk);
788
        }
789 648357d7 GiuseppeTropea
        //HINT on malloc
790
        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len + frame->size + sizeFrameHeader));
791
        if(!chunk->data)  {
792
                fprintf(stderr, "Memory error in chunk!!!\n");
793
                return -1;
794
        }
795
        chunk->frames_num++; // number of frames in the current chunk
796
797 8b52d5cf GiuseppeTropea
/*
798 648357d7 GiuseppeTropea
        //package the Frame header
799
        tempdata = chunk->data+chunk->payload_len;
800
        *((int32_t *)tempdata) = frame->number;
801
        tempdata+=sizeof(int32_t);
802
        *((struct timeval *)tempdata) = frame->timestamp;
803
        tempdata+=sizeof(struct timeval);
804
        *((int32_t *)tempdata) = frame->size;
805
        tempdata+=sizeof(int32_t);
806
        *((int32_t *)tempdata) = frame->type;
807
        tempdata+=sizeof(int32_t);
808 8b52d5cf GiuseppeTropea
*/
809
        //package the Frame header: network order and platform independent
810
        tempdata = chunk->data+chunk->payload_len;
811
        bit32_encoded_push(frame->number, tempdata);
812
        bit32_encoded_push(frame->timestamp.tv_sec, tempdata + CHUNK_TRANSCODING_INT_SIZE);
813
        bit32_encoded_push(frame->timestamp.tv_usec, tempdata + CHUNK_TRANSCODING_INT_SIZE*2);
814
        bit32_encoded_push(frame->size, tempdata + CHUNK_TRANSCODING_INT_SIZE*3);
815
        bit32_encoded_push(frame->type, tempdata + CHUNK_TRANSCODING_INT_SIZE*4);
816 648357d7 GiuseppeTropea
817
         //insert the new frame data
818
        memcpy(chunk->data + chunk->payload_len + sizeFrameHeader, outbuf, frame->size);
819
        chunk->payload_len += frame->size + sizeFrameHeader; // update payload length
820 8b52d5cf GiuseppeTropea
        //chunk lenght is updated just prior to pushing it out because
821
        //the chunk header len is better calculated there
822
        //chunk->len = sizeChunkHeader + chunk->payload_len; // update overall length
823 648357d7 GiuseppeTropea
824
        //update timestamps
825
        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) {
826
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
827
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
828
        }
829
        
830
        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) {
831
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
832
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
833
        }
834
        return 0;
835
}