Revision 0452f734 chunker_streamer/chunker_streamer.c

View differences:

chunker_streamer/chunker_streamer.c
99 99
	short int FirstTimeAudio=1, FirstTimeVideo=1;
100 100
	short int pts_anomalies_counter=0;
101 101
	short int newtime_anomalies_counter=0;
102
	long long newTime=0, newTime_audio=0, newTime_prev=0;
102
	long long newTime=0, newTime_audio=0, newTime_video=0, newTime_prev=0;
103 103
	struct timeval lastAudioSent = {0, 0};
104 104
	double ptsvideo1=0.0;
105 105
	double ptsaudio1=0.0;
......
205 205
//	pCodecCtxEnc->flags |= CODEC_FLAG_PSNR;
206 206
//	pCodecCtxEnc->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_P4X4 | X264_PART_B8X8;
207 207
//	pCodecCtxEnc->crf = 0.0f;
208

  
209 208
#else
210 209
	pCodecCtxEnc->codec_type = CODEC_TYPE_VIDEO;
211 210
	pCodecCtxEnc->codec_id   = CODEC_ID_MPEG4;
......
221 220
	//pCodecCtxEnc->max_b_frames=1;
222 221
	pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
223 222
#endif
223

  
224 224
	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);
225 225

  
226 226
	// Find the decoder for the video stream
......
231 231
	fprintf(stderr, "INIT: Setting VIDEO codecID to mpeg4: %d %d\n",pCodecCtx->codec_id, CODEC_ID_MPEG4);
232 232
	pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG4);
233 233
#endif
234

  
234 235
	if(pCodec==NULL) {
235 236
		fprintf(stderr, "INIT: Unsupported IN VIDEO pcodec!\n");
236 237
		return -1; // Codec not found
......
248 249
		return -1; // Could not open codec
249 250
	}
250 251

  
251

  
252
	//setup audio output encoder
253
	aCodecCtxEnc = avcodec_alloc_context();
254
	aCodecCtxEnc->bit_rate = audio_bitrate; //256000
255
	aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
256
	aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
257
	aCodecCtxEnc->channels = aCodecCtx->channels;
258
	fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
259

  
260
	// Find the decoder for the audio stream
261 252
	if(audioStream!=-1) {
253
		//setup audio output encoder
254
		aCodecCtxEnc = avcodec_alloc_context();
255
		aCodecCtxEnc->bit_rate = audio_bitrate; //256000
256
		aCodecCtxEnc->sample_fmt = SAMPLE_FMT_S16;
257
		aCodecCtxEnc->sample_rate = aCodecCtx->sample_rate;
258
		aCodecCtxEnc->channels = aCodecCtx->channels;
259
		fprintf(stderr, "INIT: AUDIO bitrate OUT:%d sample_rate:%d channels:%d\n", aCodecCtxEnc->bit_rate, aCodecCtxEnc->sample_rate, aCodecCtxEnc->channels);
260

  
261
		// Find the decoder for the audio stream
262 262
		aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
263 263
#ifdef MP3_AUDIO_ENCODER
264 264
		aCodecEnc = avcodec_find_encoder(CODEC_ID_MP3);
......
283 283
			return -1; // Could not open codec
284 284
		}
285 285
	}
286
	else {
287
		fprintf(stderr,"INIT: NO AUDIO TRACK IN INPUT FILE\n");
288
	}
286 289

  
287 290
	// Allocate audio in and out buffers
288 291
	samples = (int16_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
......
386 389
		{
387 390
			if(!live_source)
388 391
			{
392
			if(audioStream != -1) { //take this "time bank" method into account only if we have audio track
389 393
				// lateTime < 0 means a positive time account that can be used to decode video frames
390 394
				// if (lateTime + maxVDecodeTime) >= 0 then we may have a negative time account after video transcoding
391 395
				// therefore, it's better to skip the frame
......
397 401
					continue;
398 402
				}
399 403
			}
404
			}
400 405
			
401 406
			gettimeofday(&tmp_tv, NULL);
402 407
			
......
476 481
					//compute the new video timestamp in milliseconds
477 482
					if(frame->number>0) {
478 483
						newTime = ((double)target_pts-ptsvideo1)*1000.0/((double)delta_video*(double)av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate));
484
						// store timestamp in useconds for next frame sleep
485
						newTime_video = newTime*1000;
479 486
					}
480 487
#ifdef DEBUG_TIMESTAMPING
481 488
					fprintf(stderr, "VIDEO: NEWTIMESTAMP %ld\n", newTime);
......
491 498
					frame->timestamp.tv_sec = (long long)newTime/1000;
492 499
					frame->timestamp.tv_usec = newTime%1000;
493 500
					frame->size = video_frame_size;
501
					/* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
494 502
					frame->type = pFrame->pict_type;
495 503
#ifdef DEBUG_VIDEO_FRAMES
496 504
					fprintf(stderr, "VIDEO: encapsulated frame size:%d type:%d\n", frame->size, frame->type);
......
513 521
#endif
514 522
						chunk->seq = 0; //signal that we need an increase
515 523
						//initChunk(chunk, &seq_current_chunk);
516
						
517
						gettimeofday(&now_tv, NULL);
518
						long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
519
						usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
520
						
521
						if(usec > maxVDecodeTime)
522
							maxVDecodeTime = usec;
523 524
					}
524
					/* pict_type maybe 1 (I), 2 (P), 3 (B), 5 (AUDIO)*/
525

  
526
					//compute how long it took to encode video frame
527
					gettimeofday(&now_tv, NULL);
528
					long long usec = (now_tv.tv_sec-tmp_tv.tv_sec)*1000000;
529
					usec+=(now_tv.tv_usec-tmp_tv.tv_usec);
530
					if(usec > maxVDecodeTime)
531
						maxVDecodeTime = usec;
532

  
533
					//we DONT have an audio track, so we compute timings and determine
534
					//how much time we have to sleep at next VIDEO frame taking
535
					//also into account how much time was needed to encode the current
536
					//video frame
537
					//all this in case the video source is not live, i.e. not self-timing
538
					//and only in case there is no audio track
539
					if(audioStream == -1) {
540
						if(!live_source) {
541
							if(newTime_prev != 0) {
542
								//how much delay between video frames ideally
543
								long long maxDelay = newTime_video - newTime_prev;
544
								sleep = (maxDelay - usec);
545
#ifdef DEBUG_ANOMALIES
546
								printf("\tmaxDelay=%ld\n", ((long)maxDelay));
547
								printf("\tlast video frame interval=%ld; sleep time=%ld\n", ((long)usec), ((long)sleep));
548
#endif
549
							}
550
							else
551
								sleep = 0;
552

  
553
							//update and store counters
554
							newTime_prev = newTime_video;
555

  
556
							//i can also sleep now instead of at the beginning of
557
							//the next frame because in this case we only have video
558
							//frames, hence it would immediately be the next thing to do
559
							if(sleep > 0) {
560
#ifdef DEBUG_ANOMALIES
561
								fprintf(stderr, "\n\tREADLOOP: going to sleep for %ld microseconds\n", sleep);
562
#endif
563
								usleep(sleep);
564
							}
565

  
566
						}
567
					}
568

  
525 569
				}
526 570
			}
527 571
		}
......
612 656
				//compute the new audio timestamps in milliseconds
613 657
				if(frame->number>0) {
614 658
					newTime = (((double)target_pts-ptsaudio1)*1000.0*((double)av_q2d(pFormatCtx->streams[audioStream]->time_base)));//*(double)delta_audio;
615
					
616 659
					// store timestamp in useconds for next frame sleep
617 660
					newTime_audio = newTime*1000;
618
					
619 661
				}
620 662
#ifdef DEBUG_TIMESTAMPING
621 663
				fprintf(stderr, "AUDIO: NEWTIMESTAMP %d\n", newTime);
......
646 688
				//set priority
647 689
				chunkaudio->priority = 1;
648 690

  
649
				if(chunkFilled(chunkaudio, cmeta))
691
				if(chunkFilled(chunkaudio, cmeta)) {
692
					// is chunk filled using current strategy?
693
					//SAVE ON FILE
694
					//saveChunkOnFile(chunkaudio);
695
					//Send the chunk via http to an external transport/player
696
					pushChunkHttp(chunkaudio, cmeta->outside_world_url);
697
#ifdef DEBUG_CHUNKER
698
					fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
699
#endif
700
					chunkaudio->seq = 0; //signal that we need an increase
701
					//initChunk(chunkaudio, &seq_current_chunk);
702
				}
703

  
704
				//we have an audio track, so we compute timings and determine
705
				//how much time we have to sleep at next audio frame taking
706
				//also into account how much time was needed to encode the
707
				//video frames
708
				//all this in case the video source is not live, i.e. not self-timing
709
				if(!live_source)
650 710
				{
651
					if(!live_source)
711
					if(newTime_prev != 0)
652 712
					{
653
						if(newTime_prev != 0)
654
						{
655
							long long maxDelay = newTime_audio - newTime_prev;
713
						long long maxDelay = newTime_audio - newTime_prev;
656 714

  
657
							gettimeofday(&now_tv, NULL);
658
							long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
659
							usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
715
						gettimeofday(&now_tv, NULL);
716
						long long usec = (now_tv.tv_sec-lastAudioSent.tv_sec)*1000000;
717
						usec+=(now_tv.tv_usec-lastAudioSent.tv_usec);
660 718

  
661
							if(usec > maxAudioInterval)
662
								maxAudioInterval = usec;
719
						if(usec > maxAudioInterval)
720
							maxAudioInterval = usec;
663 721

  
664
							lateTime -= (maxDelay - usec);
722
						lateTime -= (maxDelay - usec);
665 723
#ifdef DEBUG_ANOMALIES
666
							printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
667
							printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
724
						printf("\tmaxDelay=%ld, maxAudioInterval=%ld\n", ((long)maxDelay), ((long) maxAudioInterval));
725
						printf("\tlast audio frame interval=%ld; lateTime=%ld\n", ((long)usec), ((long)lateTime));
668 726
#endif
669 727

  
670
							if((lateTime+maxAudioInterval) < 0)
671
								sleep = (lateTime+maxAudioInterval)*-1;
672
							else
673
								sleep = 0;
674
						}
728
						if((lateTime+maxAudioInterval) < 0)
729
							sleep = (lateTime+maxAudioInterval)*-1;
675 730
						else
676 731
							sleep = 0;
677

  
678
						newTime_prev = newTime_audio;
679
						gettimeofday(&lastAudioSent, NULL);
680 732
					}
681
					
682
					// is chunk filled using current strategy?
683
					//SAVE ON FILE
684
					//saveChunkOnFile(chunkaudio);
685
					//Send the chunk via http to an external transport/player
686
					pushChunkHttp(chunkaudio, cmeta->outside_world_url);
687
#ifdef DEBUG_CHUNKER
688
					fprintf(stderr, "AUDIO: just sent chunk audio %d\n", chunkaudio->seq);
689
#endif
690
					chunkaudio->seq = 0; //signal that we need an increase
691
					//initChunk(chunkaudio, &seq_current_chunk);
733
					else
734
						sleep = 0;
735

  
736
					newTime_prev = newTime_audio;
737
					gettimeofday(&lastAudioSent, NULL);
692 738
				}
739

  
693 740
			}
694 741
		}
695 742
		else {

Also available in: Unified diff