Statistics
| Branch: | Revision:

chunker-player / chunker_streamer.c @ 648357d7

History | View | Annotate | Download (23.1 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 <libavcodec/avcodec.h>
12
#include <libavformat/avformat.h>
13
14
#include <stdio.h>
15
16
#include "chunker_streamer.h"
17 e810bf7b GiuseppeTropea
#include "codec_definitions.h"
18 1e69ae95 GiuseppeTropea
19 34149271 GiuseppeTropea
//#define DEBUG_AUDIO_FRAMES
20
//#define DEBUG_VIDEO_FRAMES
21 11e39d44 GiuseppeTropea
//#define DEBUG_CHUNKER
22 34149271 GiuseppeTropea
//#define DEBUG_TIME
23 11e39d44 GiuseppeTropea
24 648357d7 GiuseppeTropea
ChunkerMetadata *cmeta = NULL;
25 1e69ae95 GiuseppeTropea
26
27
int chunkFilled(ExternalChunk *echunk, ChunkerMetadata *cmeta) {
28
        // different strategies to implement
29 34149271 GiuseppeTropea
        if(cmeta->strategy == 0) // number of frames per chunk constant
30
                if(echunk->frames_num == cmeta->val_strategy)
31 1e69ae95 GiuseppeTropea
                        return 1;
32
        
33 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
34
                if(echunk->payload_len >= cmeta->val_strategy)
35 1e69ae95 GiuseppeTropea
                        return 1;
36
        
37
        return 0;
38
}
39
40 34149271 GiuseppeTropea
/*
41 1e69ae95 GiuseppeTropea
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
42
        FILE *pFile;
43
        char szFilename[32];
44
        int  y;
45
  
46
  // Open file
47
        sprintf(szFilename, "frame%d.ppm", iFrame);
48

49
          pFile=fopen(szFilename, "wb");
50
          if(pFile==NULL)
51
                    return;
52
  
53
  // Write header
54
        fprintf(pFile, "P5\n%d %d\n255\n", width, height);
55
  
56
  // Write pixel data
57
          for(y=0; y<height; y++)
58
                    fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width, pFile);
59
  
60
  // Close file
61
          fclose(pFile);
62
}
63 34149271 GiuseppeTropea
*/
64 1e69ae95 GiuseppeTropea
65 34149271 GiuseppeTropea
/*
66 1e69ae95 GiuseppeTropea
void saveChunkOnFile(ExternalChunk *chunk) {
67
        char buf[1024], outfile[1024];
68 34149271 GiuseppeTropea
        FILE *fp;
69 1e69ae95 GiuseppeTropea
        
70
        strcpy(buf,"chunks//CHUNK");
71
        strcat(buf,"\0");
72
        sprintf(outfile,"%s%d",buf,chunk->seq);
73
        fp = fopen(outfile,"wb");
74
        fwrite(&(chunk->seq),sizeof(int),1,fp);
75
        fwrite(&(chunk->frames_num),sizeof(int),1,fp);
76
        fwrite(&(chunk->start_time),sizeof(struct timeval),1,fp);
77
        fwrite(&(chunk->end_time),sizeof(struct timeval),1,fp);
78
        fwrite(&(chunk->payload_len),sizeof(int),1,fp);
79
        fwrite(&(chunk->len),sizeof(int),1,fp);
80
        fwrite(&(chunk->category),sizeof(int),1,fp);
81
        fwrite(&(chunk->priority),sizeof(double),1,fp);
82
        fwrite(&(chunk->_refcnt),sizeof(int),1,fp);
83
        fwrite(chunk->data,sizeof(uint8_t),sizeof(uint8_t)*chunk->payload_len,fp);
84
        fclose(fp);
85
}
86 34149271 GiuseppeTropea
*/
87 1e69ae95 GiuseppeTropea
88 34149271 GiuseppeTropea
void initChunk(ExternalChunk *chunk, int *seq_num) {
89 1e69ae95 GiuseppeTropea
        chunk->seq = (*seq_num)++;
90
        chunk->frames_num = 0;
91
        chunk->payload_len = 0;
92
        chunk->len=0;
93 26379a77 GiuseppeTropea
  if(chunk->data != NULL)
94
    free(chunk->data);
95 1e69ae95 GiuseppeTropea
        chunk->data = NULL;
96
        chunk->start_time.tv_sec = -1;
97
        chunk->start_time.tv_usec = -1;
98
        chunk->end_time.tv_sec = -1;
99
        chunk->end_time.tv_usec = -1;
100
        chunk->priority = 0;
101
        chunk->category = 0;
102
        chunk->_refcnt = 0;
103
}
104
105
int main(int argc, char *argv[]) {
106 34149271 GiuseppeTropea
        int i=0;
107 648357d7 GiuseppeTropea
108
        //output variables
109
        int seq_current_chunk = 1; //chunk numbering starts from 1; HINT do i need more bytes?
110
        uint8_t *video_outbuf = NULL;
111
        int video_outbuf_size, video_frame_size;
112
        uint8_t *audio_outbuf = NULL;
113
        int audio_outbuf_size, audio_frame_size;
114
        int audio_data_size;
115
116
        //numeric identifiers of input streams
117
        int videoStream = -1;
118
        int audioStream = -1;
119
120
        int len1;
121 1e69ae95 GiuseppeTropea
        int frameFinished;
122 648357d7 GiuseppeTropea
        //frame sequential counters
123
        int contFrameAudio=0, contFrameVideo=0;
124
        int numBytes;
125
126
        //command line parameters
127 1e69ae95 GiuseppeTropea
        int audio_bitrate;
128
        int video_bitrate;
129 648357d7 GiuseppeTropea
        int live_source = 0;
130 1e69ae95 GiuseppeTropea
        
131 648357d7 GiuseppeTropea
        //a raw buffer for decoded uncompressed audio samples
132
        int16_t *samples = NULL;
133
        //a raw uncompressed video picture
134
        AVFrame *pFrame = NULL;
135 11e39d44 GiuseppeTropea
136 1e69ae95 GiuseppeTropea
        AVFormatContext *pFormatCtx;
137
        AVCodecContext  *pCodecCtx,*pCodecCtxEnc,*aCodecCtxEnc,*aCodecCtx;
138
        AVCodec         *pCodec,*pCodecEnc,*aCodec,*aCodecEnc;
139
        AVPacket         packet;
140
141 648357d7 GiuseppeTropea
        //Napa-Wine specific Frame and Chunk structures for transport
142
        Frame *frame = NULL;
143
        ExternalChunk *chunk = NULL;
144
        ExternalChunk *chunkaudio = NULL;
145 1e69ae95 GiuseppeTropea
        
146 648357d7 GiuseppeTropea
        //char buf[1024], outfile[1024];
147
148
        //stuff needed to compute the right timestamps
149 1e69ae95 GiuseppeTropea
        short int FirstTimeAudio=1, FirstTimeVideo=1;
150 34149271 GiuseppeTropea
        long long newTime;
151
        double ptsvideo1=0.0;
152
        double ptsaudio1=0.0;
153 648357d7 GiuseppeTropea
        int64_t last_pkt_dts=0, delta_video=0, delta_audio=0, last_pkt_dts_audio=0, target_pts=0;
154
155
156
        //scan the command line
157 1e69ae95 GiuseppeTropea
        if(argc < 4) {
158 34149271 GiuseppeTropea
                fprintf(stderr, "execute ./chunker_streamer moviefile audiobitrate videobitrate <live source flag (0 or 1)>\n");
159 1e69ae95 GiuseppeTropea
                return -1;
160
        }
161 34149271 GiuseppeTropea
        sscanf(argv[2],"%d", &audio_bitrate);
162
        sscanf(argv[3],"%d", &video_bitrate);
163
        if(argc==5) sscanf(argv[4],"%d", &live_source);
164
165
        // read the configuration file
166
        cmeta = chunkerInit();
167
        if(live_source)
168
                fprintf(stderr, "INIT: Using LIVE SOURCE TimeStamps\n");
169 1e69ae95 GiuseppeTropea
170
        // Register all formats and codecs
171
        av_register_all();
172
173 648357d7 GiuseppeTropea
        // Open input file
174 34149271 GiuseppeTropea
        if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) != 0) {
175
                fprintf(stdout, "INIT: Couldn't open video file. Exiting.\n");
176
                exit(-1);
177
        }
178
179 1e69ae95 GiuseppeTropea
        // Retrieve stream information
180 34149271 GiuseppeTropea
        if(av_find_stream_info(pFormatCtx) < 0) {
181
                fprintf(stdout, "INIT: Couldn't find stream information. Exiting.\n");
182
                exit(-1);
183
        }
184
185 1e69ae95 GiuseppeTropea
        // Dump information about file onto standard error
186
        dump_format(pFormatCtx, 0, argv[1], 0);
187 34149271 GiuseppeTropea
188 648357d7 GiuseppeTropea
        // Find the video and audio stream numbers
189 1e69ae95 GiuseppeTropea
        for(i=0; i<pFormatCtx->nb_streams; i++) {
190
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0) {
191
                        videoStream=i;
192
                }
193
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream<0) {
194
                        audioStream=i;
195
                }
196
        }
197 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);
198 e810bf7b GiuseppeTropea
199 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: Video stream has id : %d\n",videoStream);
200
        fprintf(stderr, "INIT: Audio stream has id : %d\n",audioStream);
201
202
        if(videoStream==-1 && audioStream==-1) {
203
                fprintf(stdout, "INIT: Didn't find audio and video streams. Exiting.\n");
204
                exit(-1);
205
        }
206 1e69ae95 GiuseppeTropea
207 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input video stream
208 1e69ae95 GiuseppeTropea
        pCodecCtx=pFormatCtx->streams[videoStream]->codec;
209
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
210 648357d7 GiuseppeTropea
        //extract W and H
211
        fprintf(stderr, "INIT: Width:%d Height:%d\n", pCodecCtx->width, pCodecCtx->height);
212 1e69ae95 GiuseppeTropea
213 648357d7 GiuseppeTropea
        // Get a pointer to the codec context for the input audio stream
214
        if(audioStream != -1) {
215 1e69ae95 GiuseppeTropea
                aCodecCtx=pFormatCtx->streams[audioStream]->codec;
216 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: AUDIO Codecid: %d channels %d samplerate %d\n", aCodecCtx->codec_id, aCodecCtx->channels, aCodecCtx->sample_rate);
217 1e69ae95 GiuseppeTropea
        }
218
219 648357d7 GiuseppeTropea
        //setup video output encoder
220 1e69ae95 GiuseppeTropea
        pCodecCtxEnc=avcodec_alloc_context();
221 e810bf7b GiuseppeTropea
#ifdef H264_VIDEO_ENCODER
222 11e39d44 GiuseppeTropea
        pCodecCtxEnc->me_range=16;
223
        pCodecCtxEnc->max_qdiff=4;
224
        pCodecCtxEnc->qmin=10;
225
        pCodecCtxEnc->qmax=51;
226
        pCodecCtxEnc->qcompress=0.6;
227 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
228 11e39d44 GiuseppeTropea
        pCodecCtxEnc->codec_id   = CODEC_ID_H264;//13;//pCodecCtx->codec_id;
229 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->bit_rate = video_bitrate;///400000;
230
        // resolution must be a multiple of two 
231
        pCodecCtxEnc->width = pCodecCtx->width;
232
        pCodecCtxEnc->height = pCodecCtx->height;
233
        // frames per second 
234 11e39d44 GiuseppeTropea
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
235 1e69ae95 GiuseppeTropea
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
236
        //pCodecCtxEnc->max_b_frames=1;
237
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
238 e810bf7b GiuseppeTropea
#else
239
        pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
240
        pCodecCtxEnc->codec_id   = CODEC_ID_MPEG4;
241
        pCodecCtxEnc->bit_rate = video_bitrate;
242
        pCodecCtxEnc->width = pCodecCtx->width;
243
        pCodecCtxEnc->height = pCodecCtx->height;
244
        // frames per second 
245
        pCodecCtxEnc->time_base= pCodecCtx->time_base;//(AVRational){1,25};
246
        pCodecCtxEnc->gop_size = 10; // emit one intra frame every ten frames 
247
        //pCodecCtxEnc->max_b_frames=1;
248
        pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
249
#endif
250 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);
251 e810bf7b GiuseppeTropea
252 648357d7 GiuseppeTropea
        // Find the decoder for the video stream
253
#ifdef H264_VIDEO_ENCODER
254
        fprintf(stderr, "INIT: Setting VIDEO codecID to H264: %d %d\n",pCodecCtx->codec_id, CODEC_ID_H264);
255
        pCodecEnc = avcodec_find_encoder(CODEC_ID_H264);//pCodecCtx->codec_id);
256
#else
257
        fprintf(stderr, "INIT: Setting VIDEO codecID to mpeg4: %d %d\n",pCodecCtx->codec_id, CODEC_ID_MPEG4);
258
        pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG4);
259
#endif
260
        if(pCodec==NULL) {
261
                fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
262
                return -1; // Codec not found
263
        }
264
        if(pCodecEnc==NULL) {
265
                fprintf(stderr, "INIT: Unsupported OUT VIDEO pcodecenc!\n");
266
                return -1; // Codec not found
267
        }
268
        if(avcodec_open(pCodecCtx, pCodec)<0) {
269
                fprintf(stderr, "INIT: could not open IN VIDEO codec\n");
270
                return -1; // Could not open codec
271
        }
272
        if(avcodec_open(pCodecCtxEnc, pCodecEnc)<0) {
273
                fprintf(stderr, "INIT: could not open OUT VIDEO codecEnc\n");
274
                return -1; // Could not open codec
275
        }
276 1e69ae95 GiuseppeTropea
277 648357d7 GiuseppeTropea
278
        //setup audio output encoder
279 1e69ae95 GiuseppeTropea
        aCodecCtxEnc = avcodec_alloc_context();
280 11e39d44 GiuseppeTropea
        aCodecCtxEnc->bit_rate = audio_bitrate; //256000
281 1e69ae95 GiuseppeTropea
        aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
282 11e39d44 GiuseppeTropea
        aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
283
        aCodecCtxEnc->channels = aCodecCtx->channels;
284 34149271 GiuseppeTropea
        fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
285 1e69ae95 GiuseppeTropea
286 648357d7 GiuseppeTropea
        // Find the decoder for the audio stream
287 1e69ae95 GiuseppeTropea
        if(audioStream!=-1) {
288
                aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
289 e810bf7b GiuseppeTropea
#ifdef MP3_AUDIO_ENCODER
290 11e39d44 GiuseppeTropea
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP3);
291 e810bf7b GiuseppeTropea
#else
292
                aCodecEnc = avcodec_find_encoder(CODEC_ID_MP2);
293
#endif
294 1e69ae95 GiuseppeTropea
                if(aCodec==NULL) {
295 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodec!\n");
296 1e69ae95 GiuseppeTropea
                        return -1;
297
                }
298
                if(aCodecEnc==NULL) {
299 34149271 GiuseppeTropea
                        fprintf(stderr,"INIT: Unsupported acodecEnc!\n");
300 1e69ae95 GiuseppeTropea
                        return -1;
301
                }
302
        
303
                if(avcodec_open(aCodecCtx, aCodec)<0) {
304 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open IN AUDIO codec\n");
305 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
306
                }
307
                if(avcodec_open(aCodecCtxEnc, aCodecEnc)<0) {
308 34149271 GiuseppeTropea
                        fprintf(stderr, "INIT: could not open OUT AUDIO codec\n");
309 1e69ae95 GiuseppeTropea
                        return -1; // Could not open codec
310
                }
311
        }
312 648357d7 GiuseppeTropea
313
        // Allocate audio in and out buffers
314
        samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
315
        if(samples == NULL) {
316
                fprintf(stderr, "INIT: Memory error alloc audio samples!!!\n");
317
                return -1;
318 1e69ae95 GiuseppeTropea
        }
319 648357d7 GiuseppeTropea
        audio_outbuf_size = STREAMER_MAX_AUDIO_BUFFER_SIZE;
320
        audio_outbuf = av_malloc(audio_outbuf_size);
321
        if(audio_outbuf == NULL) {
322
                fprintf(stderr, "INIT: Memory error alloc audio_outbuf!!!\n");
323
                return -1;
324 1e69ae95 GiuseppeTropea
        }
325
326 648357d7 GiuseppeTropea
        // Allocate video in frame and out buffer
327 1e69ae95 GiuseppeTropea
        pFrame=avcodec_alloc_frame();
328
        if(pFrame==NULL) {
329 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc video frame!!!\n");
330 1e69ae95 GiuseppeTropea
                return -1;
331
        }
332 648357d7 GiuseppeTropea
        video_outbuf_size = STREAMER_MAX_VIDEO_BUFFER_SIZE;
333
        video_outbuf = av_malloc(video_outbuf_size);
334
        if(!video_outbuf) {
335
                fprintf(stderr, "INIT: Memory error alloc video_outbuf!!!\n");
336 1e69ae95 GiuseppeTropea
                return -1;
337
        }
338 648357d7 GiuseppeTropea
339
        //allocate Napa-Wine transport
340 1e69ae95 GiuseppeTropea
        frame = (Frame *)malloc(sizeof(Frame));
341
        if(!frame) {
342 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc Frame!!!\n");
343 1e69ae95 GiuseppeTropea
                return -1;
344
        }
345
        chunk = (ExternalChunk *)malloc(sizeof(ExternalChunk));
346
        if(!chunk) {
347 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunk!!!\n");
348 1e69ae95 GiuseppeTropea
                return -1;
349
        }
350 648357d7 GiuseppeTropea
351
        //init an empty first video chunk
352
        chunk->data=NULL;
353 34149271 GiuseppeTropea
        initChunk(chunk, &seq_current_chunk);
354 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
355
        fprintf(stderr, "INIT: chunk video %d\n", chunk->seq);
356
#endif
357 648357d7 GiuseppeTropea
        //init empty first audio chunk
358 1e69ae95 GiuseppeTropea
        chunkaudio = (ExternalChunk *)malloc(sizeof(ExternalChunk));
359
        if(!chunkaudio) {
360 34149271 GiuseppeTropea
                fprintf(stderr, "INIT: Memory error alloc chunkaudio!!!\n");
361 1e69ae95 GiuseppeTropea
                return -1;
362
        }
363 648357d7 GiuseppeTropea
  chunkaudio->data=NULL;
364 51ba8aaa GiuseppeTropea
        initChunk(chunkaudio, &seq_current_chunk);
365
#ifdef DEBUG_CHUNKER
366
        fprintf(stderr, "INIT: chunk audio %d\n", chunkaudio->seq);
367
#endif
368 1e69ae95 GiuseppeTropea
369
        /* initialize the HTTP chunk pusher */
370 8de6681e GiuseppeTropea
        initChunkPusher(); //TRIPLO
371 1e69ae95 GiuseppeTropea
372 648357d7 GiuseppeTropea
//        i=0;
373 1e69ae95 GiuseppeTropea
374 648357d7 GiuseppeTropea
        //main loop to read from the input file
375 1e69ae95 GiuseppeTropea
        while(av_read_frame(pFormatCtx, &packet)>=0) {
376
                // Is this a packet from the video stream?
377
                if(packet.stream_index==videoStream) {
378 648357d7 GiuseppeTropea
                        //decode the video packet into a raw pFrame
379 e810bf7b GiuseppeTropea
                        if(avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet)>0) {
380 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
381 34149271 GiuseppeTropea
                                fprintf(stderr, "-------VIDEO FRAME type %d\n", pFrame->pict_type);
382
                                fprintf(stderr, "VIDEO: dts %lld pts %lld\n", packet.dts, packet.pts);
383 e810bf7b GiuseppeTropea
#endif
384 11e39d44 GiuseppeTropea
                                if(frameFinished) { // it must be true all the time else error
385 34149271 GiuseppeTropea
                                        frame->number = contFrameVideo;
386 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
387 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: finished frame %d dts %lld pts %lld\n", frame->number, packet.dts, packet.pts);
388 e810bf7b GiuseppeTropea
#endif
389
                                        if(frame->number==0) {
390
                                                if(packet.dts==AV_NOPTS_VALUE)
391 34149271 GiuseppeTropea
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
392 e810bf7b GiuseppeTropea
                                                        continue;
393
                                                last_pkt_dts = packet.dts;
394
                                                newTime = 0;
395
                                        }
396
                                        else {
397
                                                if(packet.dts!=AV_NOPTS_VALUE) {
398 34149271 GiuseppeTropea
                                                        delta_video = packet.dts-last_pkt_dts;
399 e810bf7b GiuseppeTropea
                                                        last_pkt_dts = packet.dts;
400
                                                }
401 34149271 GiuseppeTropea
                                                else if(delta_video==0)
402
                                                        //a Dts with a noPts value is troublesome case for delta calculation based on Dts
403 e810bf7b GiuseppeTropea
                                                        continue;
404
                                        }
405
#ifdef DEBUG_VIDEO_FRAMES
406 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: deltavideo : %d\n", (int)delta_video);
407 e810bf7b GiuseppeTropea
#endif
408 648357d7 GiuseppeTropea
                                        video_frame_size = avcodec_encode_video(pCodecCtxEnc, video_outbuf, video_outbuf_size, pFrame);
409 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
410 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: original codec frame number %d\n", pCodecCtx->frame_number);
411
                                        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);
412 11e39d44 GiuseppeTropea
#endif
413 e810bf7b GiuseppeTropea
414 34149271 GiuseppeTropea
                                        //use pts if dts is invalid
415
                                        if(packet.dts!=AV_NOPTS_VALUE)
416
                                                target_pts = packet.dts;
417
                                        else if(packet.pts!=AV_NOPTS_VALUE)
418
                                                target_pts = packet.pts;
419 11e39d44 GiuseppeTropea
                                        else
420 34149271 GiuseppeTropea
                                                continue;
421
422
                                        if(!live_source)
423
                                        {
424
                                                if(FirstTimeVideo && packet.pts>0) {
425
                                                        ptsvideo1 = (double)packet.dts;
426
                                                        FirstTimeVideo = 0;
427 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
428 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO: SET PTS BASE OFFSET %f\n", ptsvideo1);
429 11e39d44 GiuseppeTropea
#endif
430 34149271 GiuseppeTropea
                                                }
431
                                                if(frame->number>0) {
432 648357d7 GiuseppeTropea
                                                        newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
433 34149271 GiuseppeTropea
                                                }
434
                                        }
435
                                        else //live source
436
                                        {
437
                                                if(FirstTimeVideo && packet.dts>0) {
438
                                                        //maintain the offset between audio pts and video pts
439
                                                        //because in case of live source they have the same numbering
440
                                                        if(ptsaudio1 > 0) //if we have already seen some audio frames...
441
                                                                ptsvideo1 = ptsaudio1;
442
                                                        else
443
                                                                ptsvideo1 = (double)packet.dts;
444
                                                        FirstTimeVideo = 0;
445 11e39d44 GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
446 34149271 GiuseppeTropea
                                                        fprintf(stderr, "VIDEO LIVE: SET PTS BASE OFFSET %f\n", ptsvideo1);
447 11e39d44 GiuseppeTropea
#endif
448 34149271 GiuseppeTropea
                                                }
449
                                                if(frame->number>0) {
450
                                                        newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
451
                                                }
452 11e39d44 GiuseppeTropea
                                        }
453 e810bf7b GiuseppeTropea
#ifdef DEBUG_VIDEO_FRAMES
454 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
455 e810bf7b GiuseppeTropea
#endif
456 34149271 GiuseppeTropea
                                        if(newTime<0) {
457
#ifdef DEBUG_VIDEO_FRAMES
458
                                                fprintf(stderr, "VIDEO: SKIPPING FRAME\n");
459
#endif
460
                                                continue; //SKIP THIS FRAME, bad timestamp
461
                                        }
462 e810bf7b GiuseppeTropea
        
463
                                        frame->timestamp.tv_sec = (long long)newTime/1000;
464 11e39d44 GiuseppeTropea
                                        frame->timestamp.tv_usec = newTime%1000;
465 648357d7 GiuseppeTropea
                                        frame->size = video_frame_size;
466 11e39d44 GiuseppeTropea
                                        frame->type = pFrame->pict_type;
467
#ifdef DEBUG_VIDEO_FRAMES
468 34149271 GiuseppeTropea
                                        fprintf(stderr, "VIDEO: encapsulated frame num:%d size:%d type:%d\n", frame->number, frame->size, frame->type);
469
                                        fprintf(stderr, "VIDEO: timestamped sec %d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
470 11e39d44 GiuseppeTropea
#endif
471 648357d7 GiuseppeTropea
                                        contFrameVideo++; //lets increase the numbering of the frames
472 e810bf7b GiuseppeTropea
473 648357d7 GiuseppeTropea
                                        if(update_chunk(chunk, frame, video_outbuf) == -1) {
474
                                                fprintf(stderr, "VIDEO: unable to update chunk %d. Exiting.\n", chunk->seq);
475
                                                exit(-1);
476 11e39d44 GiuseppeTropea
                                        }
477 648357d7 GiuseppeTropea
478 34149271 GiuseppeTropea
                                        if(chunkFilled(chunk, cmeta)) { // is chunk filled using current strategy?
479 11e39d44 GiuseppeTropea
                                                //SAVE ON FILE
480 34149271 GiuseppeTropea
                                                //saveChunkOnFile(chunk);
481
                                                //Send the chunk via http to an external transport/player
482
                                                pushChunkHttp(chunk, cmeta->outside_world_url);
483
                                                initChunk(chunk, &seq_current_chunk);
484 51ba8aaa GiuseppeTropea
#ifdef DEBUG_CHUNKER
485
                                                fprintf(stderr, "VIDEO: chunk video %d\n", chunk->seq);
486
#endif
487 11e39d44 GiuseppeTropea
                                        }
488
                                        /* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
489
                                }
490
                        }
491
                }
492
                else if(packet.stream_index==audioStream) {
493 648357d7 GiuseppeTropea
                        audio_data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
494
                        //decode the audio packet into a raw audio source buffer
495
                        if(avcodec_decode_audio3(aCodecCtx, samples, &audio_data_size, &packet)>0) {
496 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
497 34149271 GiuseppeTropea
                                fprintf(stderr, "\n-------AUDIO FRAME\n");
498
                                fprintf(stderr, "AUDIO: newTimeaudioSTART : %lf\n", (double)(packet.pts)*av_q2d(pFormatCtx->streams[audioStream]->time_base));
499 11e39d44 GiuseppeTropea
#endif
500 648357d7 GiuseppeTropea
                                if(audio_data_size>0) {
501 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
502 648357d7 GiuseppeTropea
                                        fprintf(stderr, "AUDIO: datasizeaudio:%d\n", audio_data_size);
503 11e39d44 GiuseppeTropea
#endif
504 e810bf7b GiuseppeTropea
                                        /* if a frame has been decoded, output it */
505 648357d7 GiuseppeTropea
                                        //fwrite(samples, 1, audio_data_size, outfileaudio);
506 11e39d44 GiuseppeTropea
                                }
507 e810bf7b GiuseppeTropea
                                else
508 34149271 GiuseppeTropea
                                        continue;
509 e810bf7b GiuseppeTropea
        
510 648357d7 GiuseppeTropea
                                audio_frame_size = avcodec_encode_audio(aCodecCtxEnc, audio_outbuf, audio_data_size, samples);
511 34149271 GiuseppeTropea
                                frame->number = contFrameAudio;
512
513 e810bf7b GiuseppeTropea
                                if(frame->number==0) {
514
                                        if(packet.dts==AV_NOPTS_VALUE)
515
                                                continue;
516
                                        last_pkt_dts_audio = packet.dts;
517
                                        newTime = 0;
518
                                }
519
                                else {
520
                                        if(packet.dts!=AV_NOPTS_VALUE) {
521
                                                delta_audio = packet.dts-last_pkt_dts_audio;
522
                                                last_pkt_dts_audio = packet.dts;
523
                                        }
524
                                        else if(delta_audio==0)
525
                                                continue;
526
                                }
527
528 34149271 GiuseppeTropea
                                //use pts if dts is invalid
529
                                if(packet.dts!=AV_NOPTS_VALUE)
530
                                        target_pts = packet.dts;
531
                                else if(packet.pts!=AV_NOPTS_VALUE)
532
                                        target_pts = packet.pts;
533 1e69ae95 GiuseppeTropea
                                else
534 34149271 GiuseppeTropea
                                        continue;
535
536
                                if(!live_source)
537
                                {
538
                                        if(FirstTimeAudio && packet.pts>0) {
539
                                                //maintain the offset between audio pts and video pts
540
                                                //because in case of live source they have the same numbering
541
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
542
                                                        ptsaudio1 = ptsvideo1;
543
                                                else
544
                                                        ptsaudio1 = (double)packet.dts;
545
                                                FirstTimeAudio = 0;
546 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
547 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO: SET PTS BASE OFFSET %f\n", ptsaudio1);
548 e810bf7b GiuseppeTropea
#endif
549 34149271 GiuseppeTropea
                                        }
550
                                        if(frame->number>0) {
551
                                                        if(ptsaudio1>0)
552
                                                                //use audio-based timestamps when available (both for video and audio frames)
553
                                                                newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
554
                                                        else
555
                                                                newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
556
                                        }
557 1e69ae95 GiuseppeTropea
                                }
558 34149271 GiuseppeTropea
                                else //live source
559
                                {
560
                                        if(FirstTimeAudio && packet.pts>0) {
561
                                                //maintain the offset between audio pts and video pts
562
                                                //because in case of live source they have the same numbering
563
                                                if(ptsvideo1 > 0) //if we have already seen some video frames...
564
                                                        ptsaudio1 = ptsvideo1;
565
                                                else
566
                                                        ptsaudio1 = (double)packet.dts;
567
                                                FirstTimeAudio = 0;
568 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
569 34149271 GiuseppeTropea
                                                fprintf(stderr, "AUDIO LIVE: SET PTS BASE OFFSET %f\n", ptsaudio1);
570 11e39d44 GiuseppeTropea
#endif
571 34149271 GiuseppeTropea
                                        }
572 e810bf7b GiuseppeTropea
573 34149271 GiuseppeTropea
                                        if(frame->number>0) {
574
                                                                newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
575
                                        }
576
                                }
577
#ifdef DEBUG_AUDIO_FRAMES
578
                                fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
579
#endif
580
                                if(newTime<0) {
581
#ifdef DEBUG_AUDIO_FRAMES
582
                                        fprintf(stderr, "AUDIO: SKIPPING FRAME\n");
583
#endif
584
                                        continue; //SKIP THIS FRAME, bad timestamp
585
                                }
586 e810bf7b GiuseppeTropea
587 1e69ae95 GiuseppeTropea
                                frame->timestamp.tv_sec = (unsigned int)newTime/1000;
588
                                frame->timestamp.tv_usec = newTime%1000;
589 648357d7 GiuseppeTropea
                                frame->size = audio_frame_size;
590
                                frame->type = 5; // 5 is audio type
591 34149271 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
592
                                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);
593
                                fprintf(stderr, "AUDIO: timestamp sec:%d usec:%d\n", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
594
                                fprintf(stderr, "AUDIO: deltaaudio %lld\n", delta_audio);        
595 11e39d44 GiuseppeTropea
#endif
596 34149271 GiuseppeTropea
                                contFrameAudio++;
597
598 648357d7 GiuseppeTropea
                                if(update_chunk(chunkaudio, frame, audio_outbuf) == -1) {
599
                                        fprintf(stderr, "AUDIO: unable to update chunk %d. Exiting.\n", chunkaudio->seq);
600
                                        exit(-1);
601
                                }
602 34149271 GiuseppeTropea
                                //set priority
603 11e39d44 GiuseppeTropea
                                chunkaudio->priority = 1;
604 34149271 GiuseppeTropea
605
                                if(chunkFilled(chunkaudio, cmeta)) { // is chunk filled using current strategy?
606 1e69ae95 GiuseppeTropea
                                        //SAVE ON FILE
607 34149271 GiuseppeTropea
                                        //saveChunkOnFile(chunkaudio);
608
                                        //Send the chunk via http to an external transport/player
609
                                        pushChunkHttp(chunkaudio, cmeta->outside_world_url);
610 51ba8aaa GiuseppeTropea
                                        initChunk(chunkaudio, &seq_current_chunk);
611
#ifdef DEBUG_CHUNKER
612
                                        fprintf(stderr, "AUDIO: chunk audio %d\n", chunkaudio->seq);
613
#endif
614 1e69ae95 GiuseppeTropea
                                }
615
                        }
616
                }
617
                else {
618 11e39d44 GiuseppeTropea
#ifdef DEBUG_AUDIO_FRAMES
619
                        fprintf(stderr,"Free the packet that was allocated by av_read_frame\n");
620
#endif
621 1e69ae95 GiuseppeTropea
                        av_free_packet(&packet);
622
                }
623
        }
624
625
        if(chunk->frames_num>0) {
626
                //SAVE ON FILE
627 34149271 GiuseppeTropea
                //saveChunkOnFile(chunk);
628
                //Send the chunk via http to an external transport/player
629
                pushChunkHttp(chunk, cmeta->outside_world_url);
630 1e69ae95 GiuseppeTropea
        }
631
        if(chunkaudio->frames_num>0) {
632
                //SAVE ON FILE
633 34149271 GiuseppeTropea
                //saveChunkOnFile(chunkaudio);
634
                //Send the chunk via http to an external transport/player
635
                pushChunkHttp(chunkaudio, cmeta->outside_world_url);
636 1e69ae95 GiuseppeTropea
        }
637
638 34149271 GiuseppeTropea
        /* finalize the HTTP chunk pusher */
639 8de6681e GiuseppeTropea
        finalizeChunkPusher();
640 1e69ae95 GiuseppeTropea
641
        free(chunk);
642
        free(chunkaudio);
643
        free(frame);
644 648357d7 GiuseppeTropea
        av_free(video_outbuf);
645
        av_free(audio_outbuf);
646 34149271 GiuseppeTropea
        free(cmeta);
647 1e69ae95 GiuseppeTropea
648
        // Free the YUV frame
649
        av_free(pFrame);
650 648357d7 GiuseppeTropea
        av_free(samples);
651 1e69ae95 GiuseppeTropea
  
652
        // Close the codec
653
        avcodec_close(pCodecCtx);
654
        avcodec_close(pCodecCtxEnc);
655
656
        if(audioStream!=-1) {
657
                avcodec_close(aCodecCtx);
658
                avcodec_close(aCodecCtxEnc);
659
        }
660
  
661
        // Close the video file
662
        av_close_input_file(pFormatCtx);
663
        return 0;
664
}
665 648357d7 GiuseppeTropea
666
667
int update_chunk(ExternalChunk *chunk, Frame *frame, uint8_t *outbuf) {
668
        static int sizeFrameHeader = 3*sizeof(int32_t)+sizeof(struct timeval);
669
        static int sizeChunkHeader = 6*sizeof(int32_t)+2*sizeof(struct timeval)+sizeof(double);
670
671
        //moving temp pointer to encode Frame on the wire
672
        uint8_t *tempdata = NULL;
673
674
        //HINT on malloc
675
        chunk->data = (uint8_t *)realloc(chunk->data, sizeof(uint8_t)*(chunk->payload_len + frame->size + sizeFrameHeader));
676
        if(!chunk->data)  {
677
                fprintf(stderr, "Memory error in chunk!!!\n");
678
                return -1;
679
        }
680
        chunk->frames_num++; // number of frames in the current chunk
681
682
        //package the Frame header
683
        tempdata = chunk->data+chunk->payload_len;
684
        *((int32_t *)tempdata) = frame->number;
685
        tempdata+=sizeof(int32_t);
686
        *((struct timeval *)tempdata) = frame->timestamp;
687
        tempdata+=sizeof(struct timeval);
688
        *((int32_t *)tempdata) = frame->size;
689
        tempdata+=sizeof(int32_t);
690
        *((int32_t *)tempdata) = frame->type;
691
        tempdata+=sizeof(int32_t);
692
693
         //insert the new frame data
694
        memcpy(chunk->data + chunk->payload_len + sizeFrameHeader, outbuf, frame->size);
695
        chunk->payload_len += frame->size + sizeFrameHeader; // update payload length
696
        chunk->len = sizeChunkHeader + chunk->payload_len; // update overall length
697
698
        //update timestamps
699
        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) {
700
                                                chunk->start_time.tv_sec = frame->timestamp.tv_sec;
701
                                                chunk->start_time.tv_usec = frame->timestamp.tv_usec;
702
        }
703
        
704
        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) {
705
                                                chunk->end_time.tv_sec = frame->timestamp.tv_sec;
706
                                                chunk->end_time.tv_usec = frame->timestamp.tv_usec;
707
        }
708
        return 0;
709
}