Statistics
| Branch: | Revision:

chunker-player / chunker_streamer / chunker_streamer.c @ 046e7b49

History | View | Annotate | Download (43 KB)

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