1 /* $Id: sync.c,v 1.38 2005/04/14 21:57:58 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
9 #include "samplerate.h"
10 #include "ffmpeg/avcodec.h"
13 #undef INT64_MIN /* Because it isn't defined correctly in Zeta */
15 #define INT64_MIN (-9223372036854775807LL-1)
17 #define AC3_SAMPLES_PER_FRAME 1536
34 struct hb_work_private_s
40 hb_subtitle_t * subtitle;
42 int64_t pts_offset_old;
44 int64_t count_frames_max;
45 int64_t video_sequence;
46 hb_buffer_t * cur; /* The next picture to process */
49 hb_sync_audio_t sync_audio[8];
52 uint64_t st_counts[4];
57 /***********************************************************************
59 **********************************************************************/
60 static void InitAudio( hb_work_object_t * w, int i );
61 static int SyncVideo( hb_work_object_t * w );
62 static void SyncAudio( hb_work_object_t * w, int i );
63 static int NeedSilence( hb_work_object_t * w, hb_audio_t * );
64 static void InsertSilence( hb_work_object_t * w, int i );
65 static void UpdateState( hb_work_object_t * w );
67 /***********************************************************************
69 ***********************************************************************
70 * Initialize the work object
71 **********************************************************************/
72 int syncInit( hb_work_object_t * w, hb_job_t * job )
74 hb_title_t * title = job->title;
75 hb_chapter_t * chapter;
78 hb_work_private_t * pv;
80 pv = calloc( 1, sizeof( hb_work_private_t ) );
84 pv->pts_offset = INT64_MIN;
85 pv->pts_offset_old = INT64_MIN;
88 /* Calculate how many video frames we are expecting */
90 for( i = job->chapter_start; i <= job->chapter_end; i++ )
92 chapter = hb_list_item( title->list_chapter, i - 1 );
93 duration += chapter->duration;
96 /* 1 second safety so we're sure we won't miss anything */
97 pv->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
99 hb_log( "sync: expecting %lld video frames", pv->count_frames_max );
101 /* Initialize libsamplerate for every audio track we have */
102 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
107 /* Get subtitle info, if any */
108 pv->subtitle = hb_list_item( title->list_subtitle, 0 );
110 pv->video_sequence = 0;
115 /***********************************************************************
117 ***********************************************************************
119 **********************************************************************/
120 void syncClose( hb_work_object_t * w )
122 hb_work_private_t * pv = w->private_data;
123 hb_job_t * job = pv->job;
124 hb_title_t * title = job->title;
128 if( pv->cur ) hb_buffer_close( &pv->cur );
130 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
132 if( job->acodec & HB_ACODEC_AC3 )
134 free( pv->sync_audio[i].ac3_buf );
138 src_delete( pv->sync_audio[i].state );
143 w->private_data = NULL;
146 /***********************************************************************
148 ***********************************************************************
149 * The root routine of this work abject
151 * The way this works is that we are syncing the audio to the PTS of
152 * the last video that we processed. That's why we skip the audio sync
153 * if we haven't got a valid PTS from the video yet.
155 **********************************************************************/
156 int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
157 hb_buffer_t ** unused2 )
159 hb_work_private_t * pv = w->private_data;
162 /* If we ever got a video frame, handle audio now */
163 if( pv->pts_offset != INT64_MIN )
165 for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
172 return SyncVideo( w );
175 hb_work_object_t hb_sync =
184 static void InitAudio( hb_work_object_t * w, int i )
186 hb_work_private_t * pv = w->private_data;
187 hb_job_t * job = pv->job;
188 hb_title_t * title = job->title;
189 hb_sync_audio_t * sync;
191 sync = &pv->sync_audio[i];
192 sync->audio = hb_list_item( title->list_audio, i );
194 if( job->acodec & HB_ACODEC_AC3 )
196 /* Have a silent AC-3 frame ready in case we have to fill a
202 codec = avcodec_find_encoder( CODEC_ID_AC3 );
203 c = avcodec_alloc_context();
205 c->bit_rate = sync->audio->bitrate;
206 c->sample_rate = sync->audio->rate;
209 if( avcodec_open( c, codec ) < 0 )
211 hb_log( "sync: avcodec_open failed" );
215 zeros = calloc( AC3_SAMPLES_PER_FRAME *
216 sizeof( short ) * c->channels, 1 );
217 sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /
218 sync->audio->rate / 8;
219 sync->ac3_buf = malloc( sync->ac3_size );
221 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
222 zeros ) != sync->ac3_size )
224 hb_log( "sync: avcodec_encode_audio failed" );
233 /* Initialize libsamplerate */
235 sync->state = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error );
236 sync->data.end_of_input = 0;
242 #define PTS_DISCONTINUITY_TOLERANCE 90000
244 /***********************************************************************
246 ***********************************************************************
248 **********************************************************************/
249 static int SyncVideo( hb_work_object_t * w )
251 hb_work_private_t * pv = w->private_data;
252 hb_buffer_t * cur, * next, * sub = NULL;
253 hb_job_t * job = pv->job;
254 int64_t pts_expected;
262 if( hb_thread_has_exited( job->reader ) &&
263 !hb_fifo_size( job->fifo_mpeg2 ) &&
264 !hb_fifo_size( job->fifo_raw ) )
266 /* All video data has been processed already, we won't get
268 hb_log( "sync: got %lld frames, %lld expected",
269 pv->count_frames, pv->count_frames_max );
272 hb_buffer_t * buf_tmp;
274 // Drop an empty buffer into our output to ensure that things
275 // get flushed all the way out.
276 buf_tmp = hb_buffer_init(0); // Empty end buffer
277 hb_fifo_push( job->fifo_sync, buf_tmp );
282 if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
284 /* We haven't even got a frame yet */
289 /* At this point we have a frame to process. Let's check
290 1) if we will be able to push into the fifo ahead
291 2) if the next frame is there already, since we need it to
292 know whether we'll have to repeat the current frame or not */
293 while( !hb_fifo_is_full( job->fifo_sync ) &&
294 ( next = hb_fifo_see( job->fifo_raw ) ) )
296 hb_buffer_t * buf_tmp;
298 if( pv->pts_offset == INT64_MIN )
300 /* This is our first frame */
301 hb_log( "sync: first pts is %lld", cur->start );
302 pv->pts_offset = cur->start;
307 * Track the video sequence number localy so that we can sync the audio
308 * to it using the sequence number as well as the PTS.
310 pv->video_sequence = cur->sequence;
312 /* Check for PTS jumps over 0.5 second */
313 if( next->start < cur->start - PTS_DISCONTINUITY_TOLERANCE ||
314 next->start > cur->start + PTS_DISCONTINUITY_TOLERANCE )
316 hb_log( "Sync: Video PTS discontinuity (current buffer start=%lld, next buffer start=%lld), trash Video",
317 cur->start, next->start );
320 * Do we need to trash the subtitle, is it from the next->start period
321 * or is it from our old position. If the latter then trash it.
325 while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
327 if( ( sub->start > ( cur->start - PTS_DISCONTINUITY_TOLERANCE ) ) &&
328 ( sub->start < ( cur->start + PTS_DISCONTINUITY_TOLERANCE ) ) )
331 * The subtitle is from our current time region which we are
332 * jumping from. So trash it as we are about to jump backwards
333 * or forwards and don't want it blocking the subtitle fifo.
335 hb_log("Trashing subtitle 0x%x due to PTS discontinuity", sub);
336 sub = hb_fifo_get( pv->subtitle->fifo_raw );
337 hb_buffer_close( &sub );
342 /* Trash current picture */
343 /* Also, make sure we don't trash a chapter break */
344 chap_break = cur->new_chap;
345 hb_buffer_close( &cur );
346 pv->cur = cur = hb_fifo_get( job->fifo_raw );
347 cur->new_chap |= chap_break; // Don't stomp existing chapter breaks
349 /* Calculate new offset */
350 pv->pts_offset_old = pv->pts_offset;
351 pv->pts_offset = cur->start -
352 pv->count_frames * pv->job->vrate_base / 300;
354 pv->video_sequence = cur->sequence;
358 /* Look for a subtitle for this frame */
362 while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
364 /* If two subtitles overlap, make the first one stop
365 when the second one starts */
366 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
367 if( sub2 && sub->stop > sub2->start )
368 sub->stop = sub2->start;
370 // hb_log("0x%x: video seq: %lld subtitle sequence: %lld",
371 // sub, cur->sequence, sub->sequence);
373 if( sub->sequence > cur->sequence )
376 * The video is behind where we are, so wait until
377 * it catches up to the same reader point on the
378 * DVD. Then our PTS should be in the same region
385 if( sub->stop > cur->start ) {
387 * The stop time is in the future, so fall through
388 * and we'll deal with it in the next block of
396 * The stop time is in the past. But is it due to
397 * it having been played already, or has the PTS
400 if( ( cur->start - sub->stop ) > PTS_DISCONTINUITY_TOLERANCE ) {
402 * There is a lot of time between our current
403 * video and where this subtitle is ending,
404 * assume that we are about to reset the PTS
405 * and do not throw away this subtitle.
412 * The subtitle is older than this picture, trash it
414 sub = hb_fifo_get( pv->subtitle->fifo_raw );
415 hb_buffer_close( &sub );
419 * There is a valid subtitle, is it time to display it?
423 if( sub->stop > sub->start)
426 * Normal subtitle which ends after it starts, check to
427 * see that the current video is between the start and end.
429 if( cur->start > sub->start &&
430 cur->start < sub->stop )
433 * We should be playing this, so leave the
436 * fall through to display
442 * Defer until the play point is within the subtitle
450 * The end of the subtitle is less than the start, this is a
451 * sign of a PTS discontinuity.
453 if( sub->start > cur->start )
456 * we haven't reached the start time yet, or
457 * we have jumped backwards after having
458 * already started this subtitle.
460 if( cur->start < sub->stop )
463 * We have jumped backwards and so should
464 * continue displaying this subtitle.
466 * fall through to display.
472 * Defer until the play point is within the subtitle
478 * Play this subtitle as the start is greater than our
481 * fall through to display/
488 /* The PTS of the frame we are expecting now */
489 pts_expected = pv->pts_offset +
490 pv->count_frames * pv->job->vrate_base / 300;
492 //hb_log("Video expecting PTS %lld, current frame: %lld, next frame: %lld, cf: %lld",
493 // pts_expected, cur->start, next->start, pv->count_frames * pv->job->vrate_base / 300 );
495 if( cur->start < pts_expected - pv->job->vrate_base / 300 / 2 &&
496 next->start < pts_expected + pv->job->vrate_base / 300 / 2 )
498 /* The current frame is too old but the next one matches,
500 /* Also, make sure we don't trash a chapter break */
501 chap_break = cur->new_chap;
502 hb_buffer_close( &cur );
503 pv->cur = cur = hb_fifo_get( job->fifo_raw );
504 cur->new_chap |= chap_break; // Make sure we don't stomp the existing one.
509 if( next->start > pts_expected + 3 * pv->job->vrate_base / 300 / 2 )
511 /* We'll need the current frame more than one time. Make a
512 copy of it and keep it */
513 buf_tmp = hb_buffer_init( cur->size );
514 memcpy( buf_tmp->data, cur->data, cur->size );
515 buf_tmp->sequence = cur->sequence;
519 /* The frame has the expected date and won't have to be
520 duplicated, just put it through */
522 pv->cur = cur = hb_fifo_get( job->fifo_raw );
525 /* Replace those MPEG-2 dates with our dates */
526 buf_tmp->start = (uint64_t) pv->count_frames *
527 pv->job->vrate_base / 300;
528 buf_tmp->stop = (uint64_t) ( pv->count_frames + 1 ) *
529 pv->job->vrate_base / 300;
531 /* If we have a subtitle for this picture, copy it */
532 /* FIXME: we should avoid this memcpy */
535 buf_tmp->sub = hb_buffer_init( sub->size );
536 buf_tmp->sub->x = sub->x;
537 buf_tmp->sub->y = sub->y;
538 buf_tmp->sub->width = sub->width;
539 buf_tmp->sub->height = sub->height;
540 memcpy( buf_tmp->sub->data, sub->data, sub->size );
543 /* Push the frame to the renderer */
544 hb_fifo_push( job->fifo_sync, buf_tmp );
549 /* Make sure we won't get more frames then expected */
550 if( pv->count_frames >= pv->count_frames_max )
552 hb_log( "sync: got %lld frames", pv->count_frames );
555 // Drop an empty buffer into our output to ensure that things
556 // get flushed all the way out.
557 buf_tmp = hb_buffer_init(0); // Empty end buffer
558 hb_fifo_push( job->fifo_sync, buf_tmp );
567 /***********************************************************************
569 ***********************************************************************
571 **********************************************************************/
572 static void SyncAudio( hb_work_object_t * w, int i )
574 hb_work_private_t * pv = w->private_data;
578 hb_sync_audio_t * sync;
583 int64_t pts_expected;
587 sync = &pv->sync_audio[i];
590 if( job->acodec & HB_ACODEC_AC3 )
592 fifo = audio->fifo_out;
597 fifo = audio->fifo_sync;
601 while( !hb_fifo_is_full( fifo ) &&
602 ( buf = hb_fifo_see( audio->fifo_raw ) ) )
604 /* The PTS of the samples we are expecting now */
605 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
607 // hb_log("Video Sequence: %lld, Audio Sequence: %lld", pv->video_sequence, buf->sequence);
609 * Using the same logic as the Video have we crossed a VOB
610 * boundary as detected by the expected PTS and the PTS of our
611 * audio being out by more than the tolerance value.
613 if( ( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
614 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE ) &&
615 pv->pts_offset_old > INT64_MIN )
618 * Useful debug, but too verbose for normal use.
620 hb_log("Sync: Audio discontinuity (sequence: vid %lld aud %lld) (pts %lld < %lld < %lld)",
621 pv->video_sequence, buf->sequence,
622 pts_expected - PTS_DISCONTINUITY_TOLERANCE, buf->start,
623 pts_expected + PTS_DISCONTINUITY_TOLERANCE );
625 /* There has been a PTS discontinuity, and this frame might
626 be from before the discontinuity*/
627 pts_expected = pv->pts_offset_old + sync->count_frames *
631 * Is the audio from a valid period given the previous
632 * Video PTS. I.e. has there just been a video PTS
633 * discontinuity and this audio belongs to the vdeo from
636 if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
637 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE )
640 * It's outside of our tolerance for where the video
641 * is now, and it's outside of the tolerance for
642 * where we have been in the case of a VOB change.
643 * Try and reconverge regardless. so continue on to
644 * our convergence code below which will kick in as
645 * it will be more than 100ms out.
647 * Note that trashing the Audio could make things
648 * worse if the Audio is in front because we will end
649 * up diverging even more. We need to hold on to the
650 * audio until the video catches up.
652 hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");
655 * It wasn't from the old place, so we must be from
656 * the new, but just too far out. So attempt to
657 * reconverge by resetting the point we want to be to
658 * where we are currently wanting to be.
660 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
661 start = pts_expected - pv->pts_offset;
663 /* Use the older offset */
664 start = pts_expected - pv->pts_offset_old;
669 start = pts_expected - pv->pts_offset;
672 /* Tolerance: 100 ms */
673 if( buf->start < pts_expected - 9000 )
675 /* Audio is behind the Video, trash it, can't use it now. */
676 hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",
677 buf->start, pts_expected);
678 buf = hb_fifo_get( audio->fifo_raw );
679 hb_buffer_close( &buf );
682 else if( buf->start > pts_expected + 9000 )
684 /* Audio is ahead of the Video, insert silence until we catch up*/
685 hb_log("Sync: Audio PTS (%lld) > Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);
686 InsertSilence( w, i );
690 if( job->acodec & HB_ACODEC_AC3 )
692 buf = hb_fifo_get( audio->fifo_raw );
694 buf->stop = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
696 sync->count_frames += AC3_SAMPLES_PER_FRAME;
700 hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
702 int count_in, count_out;
704 count_in = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );
705 count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
706 if( buf->start < pts_expected - 1500 )
708 else if( buf->start > pts_expected + 1500 )
711 sync->data.data_in = (float *) buf_raw->data;
712 sync->data.input_frames = count_in;
713 sync->data.output_frames = count_out;
715 sync->data.src_ratio = (double) sync->data.output_frames /
716 (double) sync->data.input_frames;
718 buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *
720 sync->data.data_out = (float *) buf->data;
721 if( src_process( sync->state, &sync->data ) )
723 /* XXX If this happens, we're screwed */
724 hb_log( "sync: src_process failed" );
726 hb_buffer_close( &buf_raw );
728 buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );
730 /* Set dates for resampled data */
732 buf->stop = start + sync->data.output_frames_gen *
735 sync->count_frames += sync->data.output_frames_gen;
738 buf->frametype = HB_FRAME_AUDIO;
739 hb_fifo_push( fifo, buf );
742 if( NeedSilence( w, audio ) )
744 InsertSilence( w, i );
748 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
750 hb_work_private_t * pv = w->private_data;
751 hb_job_t * job = pv->job;
753 if( hb_fifo_size( audio->fifo_in ) ||
754 hb_fifo_size( audio->fifo_raw ) ||
755 hb_fifo_size( audio->fifo_sync ) ||
756 hb_fifo_size( audio->fifo_out ) )
758 /* We have some audio, we are fine */
762 /* No audio left in fifos */
764 if( hb_thread_has_exited( job->reader ) )
766 /* We might miss some audio to complete encoding and muxing
768 hb_log("Reader has exited early, inserting silence.");
772 if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
773 hb_fifo_is_full( job->fifo_raw ) &&
774 hb_fifo_is_full( job->fifo_sync ) &&
775 hb_fifo_is_full( job->fifo_render ) &&
776 hb_fifo_is_full( job->fifo_mpeg4 ) )
778 /* Too much video and no audio, oh-oh */
779 hb_log("Still got some video - and nothing in the audio fifo, insert silence");
786 static void InsertSilence( hb_work_object_t * w, int i )
788 hb_work_private_t * pv = w->private_data;
790 hb_sync_audio_t * sync;
794 sync = &pv->sync_audio[i];
796 if( job->acodec & HB_ACODEC_AC3 )
798 buf = hb_buffer_init( sync->ac3_size );
799 buf->start = sync->count_frames * 90000 / sync->audio->rate;
800 buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
802 memcpy( buf->data, sync->ac3_buf, buf->size );
804 hb_log( "sync: adding a silent AC-3 frame for track %x",
806 hb_fifo_push( sync->audio->fifo_out, buf );
808 sync->count_frames += AC3_SAMPLES_PER_FRAME;
813 buf = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *
815 buf->start = sync->count_frames * 90000 / job->arate;
816 buf->stop = buf->start + 90000 / 20;
817 memset( buf->data, 0, buf->size );
819 hb_log( "sync: adding 50 ms of silence for track %x",
821 hb_fifo_push( sync->audio->fifo_sync, buf );
823 sync->count_frames += job->arate / 20;
827 static void UpdateState( hb_work_object_t * w )
829 hb_work_private_t * pv = w->private_data;
832 if( !pv->count_frames )
834 pv->st_first = hb_get_date();
838 if( hb_get_date() > pv->st_dates[3] + 1000 )
840 memmove( &pv->st_dates[0], &pv->st_dates[1],
841 3 * sizeof( uint64_t ) );
842 memmove( &pv->st_counts[0], &pv->st_counts[1],
843 3 * sizeof( uint64_t ) );
844 pv->st_dates[3] = hb_get_date();
845 pv->st_counts[3] = pv->count_frames;
848 #define p state.param.working
849 state.state = HB_STATE_WORKING;
850 p.progress = (float) pv->count_frames / (float) pv->count_frames_max;
851 if( p.progress > 1.0 )
855 p.rate_cur = 1000.0 *
856 (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
857 (float) ( pv->st_dates[3] - pv->st_dates[0] );
858 if( hb_get_date() > pv->st_first + 4000 )
861 p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
862 (float) ( pv->st_dates[3] - pv->st_first );
863 eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
865 p.hours = eta / 3600;
866 p.minutes = ( eta % 3600 ) / 60;
867 p.seconds = eta % 60;
878 hb_set_state( pv->job->h, &state );