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;
45 int64_t count_frames_max;
46 int64_t video_sequence;
47 hb_buffer_t * cur; /* The next picture to process */
50 hb_sync_audio_t sync_audio[8];
56 uint64_t st_counts[4];
60 /* Throttle message flags */
62 int inserting_silence;
66 /***********************************************************************
68 **********************************************************************/
69 static void InitAudio( hb_work_object_t * w, int i );
70 static int SyncVideo( hb_work_object_t * w );
71 static void SyncAudio( hb_work_object_t * w, int i );
72 static int NeedSilence( hb_work_object_t * w, hb_audio_t * );
73 static void InsertSilence( hb_work_object_t * w, int i );
74 static void UpdateState( hb_work_object_t * w );
76 /***********************************************************************
78 ***********************************************************************
79 * Initialize the work object
80 **********************************************************************/
81 int syncInit( hb_work_object_t * w, hb_job_t * job )
83 hb_title_t * title = job->title;
84 hb_chapter_t * chapter;
87 hb_work_private_t * pv;
89 pv = calloc( 1, sizeof( hb_work_private_t ) );
93 pv->pts_offset = INT64_MIN;
94 pv->pts_offset_old = INT64_MIN;
97 pv->discontinuity = 0;
99 pv->trashing_audio = 0;
100 pv->inserting_silence = 0;
101 pv->way_out_of_sync = 0;
103 /* Calculate how many video frames we are expecting */
105 for( i = job->chapter_start; i <= job->chapter_end; i++ )
107 chapter = hb_list_item( title->list_chapter, i - 1 );
108 duration += chapter->duration;
111 /* 1 second safety so we're sure we won't miss anything */
112 pv->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
114 hb_log( "sync: expecting %lld video frames", pv->count_frames_max );
116 /* Initialize libsamplerate for every audio track we have */
117 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
122 /* Get subtitle info, if any */
123 pv->subtitle = hb_list_item( title->list_subtitle, 0 );
125 pv->video_sequence = 0;
130 /***********************************************************************
132 ***********************************************************************
134 **********************************************************************/
135 void syncClose( hb_work_object_t * w )
137 hb_work_private_t * pv = w->private_data;
138 hb_job_t * job = pv->job;
139 hb_title_t * title = job->title;
143 if( pv->cur ) hb_buffer_close( &pv->cur );
145 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
147 if( job->acodec & HB_ACODEC_AC3 ||
148 job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
150 free( pv->sync_audio[i].ac3_buf );
154 src_delete( pv->sync_audio[i].state );
159 w->private_data = NULL;
162 /***********************************************************************
164 ***********************************************************************
165 * The root routine of this work abject
167 * The way this works is that we are syncing the audio to the PTS of
168 * the last video that we processed. That's why we skip the audio sync
169 * if we haven't got a valid PTS from the video yet.
171 **********************************************************************/
172 int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
173 hb_buffer_t ** unused2 )
175 hb_work_private_t * pv = w->private_data;
178 /* If we ever got a video frame, handle audio now */
179 if( pv->pts_offset != INT64_MIN )
181 for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
188 return SyncVideo( w );
191 hb_work_object_t hb_sync =
200 static void InitAudio( hb_work_object_t * w, int i )
202 hb_work_private_t * pv = w->private_data;
203 hb_job_t * job = pv->job;
204 hb_title_t * title = job->title;
205 hb_sync_audio_t * sync;
207 sync = &pv->sync_audio[i];
208 sync->audio = hb_list_item( title->list_audio, i );
210 if( job->acodec & HB_ACODEC_AC3 ||
211 job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
213 /* Have a silent AC-3 frame ready in case we have to fill a
219 codec = avcodec_find_encoder( CODEC_ID_AC3 );
220 c = avcodec_alloc_context();
222 c->bit_rate = sync->audio->bitrate;
223 c->sample_rate = sync->audio->rate;
226 if( avcodec_open( c, codec ) < 0 )
228 hb_log( "sync: avcodec_open failed" );
232 zeros = calloc( AC3_SAMPLES_PER_FRAME *
233 sizeof( short ) * c->channels, 1 );
234 sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /
235 sync->audio->rate / 8;
236 sync->ac3_buf = malloc( sync->ac3_size );
238 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
239 zeros ) != sync->ac3_size )
241 hb_log( "sync: avcodec_encode_audio failed" );
250 /* Initialize libsamplerate */
252 sync->state = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error );
253 sync->data.end_of_input = 0;
259 #define PTS_DISCONTINUITY_TOLERANCE 90000
261 /***********************************************************************
263 ***********************************************************************
265 **********************************************************************/
266 static int SyncVideo( hb_work_object_t * w )
268 hb_work_private_t * pv = w->private_data;
269 hb_buffer_t * cur, * next, * sub = NULL;
270 hb_job_t * job = pv->job;
271 int64_t pts_expected;
279 if( hb_thread_has_exited( job->reader ) &&
280 !hb_fifo_size( job->fifo_mpeg2 ) &&
281 !hb_fifo_size( job->fifo_raw ) )
283 /* All video data has been processed already, we won't get
285 hb_log( "sync: got %lld frames, %lld expected",
286 pv->count_frames, pv->count_frames_max );
289 hb_buffer_t * buf_tmp;
291 // Drop an empty buffer into our output to ensure that things
292 // get flushed all the way out.
293 buf_tmp = hb_buffer_init(0); // Empty end buffer
294 hb_fifo_push( job->fifo_sync, buf_tmp );
299 if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
301 /* We haven't even got a frame yet */
306 /* At this point we have a frame to process. Let's check
307 1) if we will be able to push into the fifo ahead
308 2) if the next frame is there already, since we need it to
309 know whether we'll have to repeat the current frame or not */
310 while( !hb_fifo_is_full( job->fifo_sync ) &&
311 ( next = hb_fifo_see( job->fifo_raw ) ) )
313 hb_buffer_t * buf_tmp;
315 if( pv->pts_offset == INT64_MIN )
317 /* This is our first frame */
318 hb_log( "sync: first pts is %lld", cur->start );
319 pv->pts_offset = cur->start;
323 * Track the video sequence number localy so that we can sync the audio
324 * to it using the sequence number as well as the PTS.
326 pv->video_sequence = cur->sequence;
328 /* Check for PTS jumps over 0.5 second */
329 if( next->start < cur->start - PTS_DISCONTINUITY_TOLERANCE ||
330 next->start > cur->start + PTS_DISCONTINUITY_TOLERANCE )
332 hb_log( "Sync: Video PTS discontinuity %s (current buffer start=%lld, next buffer start=%lld)",
333 pv->discontinuity ? "second" : "first", cur->start, next->start );
336 * Do we need to trash the subtitle, is it from the next->start period
337 * or is it from our old position. If the latter then trash it.
341 while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
343 if( ( sub->start > ( cur->start - PTS_DISCONTINUITY_TOLERANCE ) ) &&
344 ( sub->start < ( cur->start + PTS_DISCONTINUITY_TOLERANCE ) ) )
347 * The subtitle is from our current time region which we are
348 * jumping from. So trash it as we are about to jump backwards
349 * or forwards and don't want it blocking the subtitle fifo.
351 hb_log("Trashing subtitle 0x%x due to PTS discontinuity", sub);
352 sub = hb_fifo_get( pv->subtitle->fifo_raw );
353 hb_buffer_close( &sub );
360 /* Trash current picture */
361 /* Also, make sure we don't trash a chapter break */
362 chap_break = cur->new_chap;
363 hb_buffer_close( &cur );
364 pv->cur = cur = hb_fifo_get( job->fifo_raw );
365 cur->new_chap |= chap_break; // Don't stomp existing chapter breaks
367 /* Calculate new offset */
368 pv->pts_offset_old = pv->pts_offset;
371 pv->pts_offset = cur->start - pv->next_start;
373 pv->pts_offset = cur->start -
374 pv->count_frames * pv->job->vrate_base / 300;
377 if( !pv->discontinuity )
379 pv->discontinuity = 1;
382 pv->video_sequence = cur->sequence;
386 /* Look for a subtitle for this frame */
390 while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
392 /* If two subtitles overlap, make the first one stop
393 when the second one starts */
394 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
395 if( sub2 && sub->stop > sub2->start )
396 sub->stop = sub2->start;
398 // hb_log("0x%x: video seq: %lld subtitle sequence: %lld",
399 // sub, cur->sequence, sub->sequence);
401 if( sub->sequence > cur->sequence )
404 * The video is behind where we are, so wait until
405 * it catches up to the same reader point on the
406 * DVD. Then our PTS should be in the same region
413 if( sub->stop > cur->start ) {
415 * The stop time is in the future, so fall through
416 * and we'll deal with it in the next block of
424 * The stop time is in the past. But is it due to
425 * it having been played already, or has the PTS
428 if( ( cur->start - sub->stop ) > PTS_DISCONTINUITY_TOLERANCE ) {
430 * There is a lot of time between our current
431 * video and where this subtitle is ending,
432 * assume that we are about to reset the PTS
433 * and do not throw away this subtitle.
440 * The subtitle is older than this picture, trash it
442 sub = hb_fifo_get( pv->subtitle->fifo_raw );
443 hb_buffer_close( &sub );
447 * There is a valid subtitle, is it time to display it?
451 if( sub->stop > sub->start)
454 * Normal subtitle which ends after it starts, check to
455 * see that the current video is between the start and end.
457 if( cur->start > sub->start &&
458 cur->start < sub->stop )
461 * We should be playing this, so leave the
464 * fall through to display
466 if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
469 * Subtitle is on for less than three seconds, extend
470 * the time that it is displayed to make it easier
471 * to read. Make it 3 seconds or until the next
472 * subtitle is displayed.
474 * This is in response to Indochine which only
475 * displays subs for 1 second - too fast to read.
477 sub->stop = sub->start + ( 3 * 90000 );
479 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
481 if( sub2 && sub->stop > sub2->start )
483 sub->stop = sub2->start;
490 * Defer until the play point is within the subtitle
498 * The end of the subtitle is less than the start, this is a
499 * sign of a PTS discontinuity.
501 if( sub->start > cur->start )
504 * we haven't reached the start time yet, or
505 * we have jumped backwards after having
506 * already started this subtitle.
508 if( cur->start < sub->stop )
511 * We have jumped backwards and so should
512 * continue displaying this subtitle.
514 * fall through to display.
520 * Defer until the play point is within the subtitle
526 * Play this subtitle as the start is greater than our
529 * fall through to display/
539 * adjust the pts of the current frame so that it's contiguous
540 * with the previous frame. pts_offset tracks the time difference
541 * between the pts values in the input content (which start at some
542 * random time) and our timestamps (which start at zero). We don't
543 * make any adjustments to the source timestamps other than removing
544 * the clock offsets (which also removes pts discontinuities).
545 * This means we automatically encode at the source's frame rate.
546 * MP2 uses an implicit duration (frames end when the next frame
547 * starts) but more advanced containers like MP4 use an explicit
548 * duration. Since we're looking ahead one frame we set the
549 * explicit stop time from the start time of the next frame.
552 pv->cur = cur = hb_fifo_get( job->fifo_raw );
553 buf_tmp->start = pv->next_start;
554 pv->next_start = next->start - pv->pts_offset;
555 buf_tmp->stop = pv->next_start;
559 /* The PTS of the frame we are expecting now */
560 pts_expected = pv->pts_offset +
561 pv->count_frames * pv->job->vrate_base / 300;
563 //hb_log("Video expecting PTS %lld, current frame: %lld, next frame: %lld, cf: %lld",
564 // pts_expected, cur->start, next->start, pv->count_frames * pv->job->vrate_base / 300 );
566 if( cur->start < pts_expected - pv->job->vrate_base / 300 / 2 &&
567 next->start < pts_expected + pv->job->vrate_base / 300 / 2 )
569 /* The current frame is too old but the next one matches,
571 /* Also, make sure we don't trash a chapter break */
572 chap_break = cur->new_chap;
573 hb_buffer_close( &cur );
574 pv->cur = cur = hb_fifo_get( job->fifo_raw );
575 cur->new_chap |= chap_break; // Make sure we don't stomp the existing one.
580 if( next->start > pts_expected + 3 * pv->job->vrate_base / 300 / 2 )
582 /* We'll need the current frame more than one time. Make a
583 copy of it and keep it */
584 buf_tmp = hb_buffer_init( cur->size );
585 memcpy( buf_tmp->data, cur->data, cur->size );
586 buf_tmp->sequence = cur->sequence;
590 /* The frame has the expected date and won't have to be
591 duplicated, just put it through */
593 pv->cur = cur = hb_fifo_get( job->fifo_raw );
596 /* Replace those MPEG-2 dates with our dates */
597 buf_tmp->start = (uint64_t) pv->count_frames *
598 pv->job->vrate_base / 300;
599 buf_tmp->stop = (uint64_t) ( pv->count_frames + 1 ) *
600 pv->job->vrate_base / 300;
603 /* If we have a subtitle for this picture, copy it */
604 /* FIXME: we should avoid this memcpy */
607 buf_tmp->sub = hb_buffer_init( sub->size );
608 buf_tmp->sub->x = sub->x;
609 buf_tmp->sub->y = sub->y;
610 buf_tmp->sub->width = sub->width;
611 buf_tmp->sub->height = sub->height;
612 memcpy( buf_tmp->sub->data, sub->data, sub->size );
615 /* Push the frame to the renderer */
616 hb_fifo_push( job->fifo_sync, buf_tmp );
621 /* Make sure we won't get more frames then expected */
622 if( pv->count_frames >= pv->count_frames_max * 2)
624 hb_log( "sync: got too many frames (%lld), exiting early", pv->count_frames );
627 // Drop an empty buffer into our output to ensure that things
628 // get flushed all the way out.
629 buf_tmp = hb_buffer_init(0); // Empty end buffer
630 hb_fifo_push( job->fifo_sync, buf_tmp );
639 /***********************************************************************
641 ***********************************************************************
643 **********************************************************************/
644 static void SyncAudio( hb_work_object_t * w, int i )
646 hb_work_private_t * pv = w->private_data;
650 hb_sync_audio_t * sync;
655 int64_t pts_expected;
659 sync = &pv->sync_audio[i];
662 if( job->acodec & HB_ACODEC_AC3 ||
663 job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
665 fifo = audio->fifo_out;
670 fifo = audio->fifo_sync;
674 while( !hb_fifo_is_full( fifo ) &&
675 ( buf = hb_fifo_see( audio->fifo_raw ) ) )
677 /* The PTS of the samples we are expecting now */
678 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
680 // hb_log("Video Sequence: %lld, Audio Sequence: %lld", pv->video_sequence, buf->sequence);
683 * Using the same logic as the Video have we crossed a VOB
684 * boundary as detected by the expected PTS and the PTS of our
685 * audio being out by more than the tolerance value.
687 if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
688 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE )
690 /* There has been a PTS discontinuity, and this frame might
691 be from before the discontinuity*/
693 if( pv->discontinuity )
696 * There is an outstanding discontinuity, so use the offset from
697 * that discontinuity.
699 pts_expected = pv->pts_offset_old + sync->count_frames *
705 * No outstanding discontinuity, so the audio must be leading the
706 * video (or the PTS values are really stuffed). So lets mark this
707 * as a discontinuity ourselves for the audio to use until
708 * the video also crosses the discontinuity.
710 * pts_offset is used when we are in the same time space as the video
711 * pts_offset_old when in a discontinuity.
713 * Therefore set the pts_offset_old given the new pts_offset for this
716 pv->discontinuity = 1;
717 pv->pts_offset_old = buf->start - sync->count_frames *
719 pts_expected = pv->pts_offset_old + sync->count_frames *
722 hb_log("Sync: Audio discontinuity (sequence: vid %lld aud %lld) (pts %lld < %lld < %lld)",
723 pv->video_sequence, buf->sequence,
724 pts_expected - PTS_DISCONTINUITY_TOLERANCE, buf->start,
725 pts_expected + PTS_DISCONTINUITY_TOLERANCE );
729 * Is the audio from a valid period given the previous
730 * Video PTS. I.e. has there just been a video PTS
731 * discontinuity and this audio belongs to the vdeo from
734 if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
735 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE )
738 * It's outside of our tolerance for where the video
739 * is now, and it's outside of the tolerance for
740 * where we have been in the case of a VOB change.
741 * Try and reconverge regardless. so continue on to
742 * our convergence code below which will kick in as
743 * it will be more than 100ms out.
745 * Note that trashing the Audio could make things
746 * worse if the Audio is in front because we will end
747 * up diverging even more. We need to hold on to the
748 * audio until the video catches up.
750 if( !pv->way_out_of_sync )
752 hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");
753 pv->way_out_of_sync = 1;
757 * It wasn't from the old place, so we must be from
758 * the new, but just too far out. So attempt to
759 * reconverge by resetting the point we want to be to
760 * where we are currently wanting to be.
762 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
763 start = pts_expected - pv->pts_offset;
765 /* Use the older offset */
766 start = pts_expected - pv->pts_offset_old;
771 start = pts_expected - pv->pts_offset;
773 if( pv->discontinuity )
776 * The Audio is tracking the Video again using the normal pts_offset, so the
777 * discontinuity is over.
779 hb_log( "Sync: Audio joined Video after discontinuity at PTS %lld", buf->start );
780 pv->discontinuity = 0;
784 /* Tolerance: 100 ms */
785 if( buf->start < pts_expected - 9000 )
787 if( !pv->trashing_audio )
789 /* Audio is behind the Video, trash it, can't use it now. */
790 hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",
791 buf->start, pts_expected);
792 pv->trashing_audio = 1;
794 buf = hb_fifo_get( audio->fifo_raw );
795 hb_buffer_close( &buf );
798 else if( buf->start > pts_expected + 9000 )
800 /* Audio is ahead of the Video, insert silence until we catch up*/
801 if( !pv->inserting_silence )
803 hb_log("Sync: Audio PTS (%lld) > Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);
804 pv->inserting_silence = 1;
806 InsertSilence( w, i );
811 if( pv->trashing_audio || pv->inserting_silence )
813 hb_log( "Sync: Audio back in Sync at PTS %lld", buf->start );
814 pv->trashing_audio = 0;
815 pv->inserting_silence = 0;
817 if( pv->way_out_of_sync )
819 hb_log( "Sync: Audio no longer way out of sync at PTS %lld",
821 pv->way_out_of_sync = 0;
825 if( job->acodec & HB_ACODEC_AC3 ||
826 job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
828 buf = hb_fifo_get( audio->fifo_raw );
830 buf->stop = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
832 sync->count_frames += AC3_SAMPLES_PER_FRAME;
836 hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
838 int count_in, count_out;
840 count_in = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );
841 count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
842 if( buf->start < pts_expected - 1500 )
844 else if( buf->start > pts_expected + 1500 )
847 sync->data.data_in = (float *) buf_raw->data;
848 sync->data.input_frames = count_in;
849 sync->data.output_frames = count_out;
851 sync->data.src_ratio = (double) sync->data.output_frames /
852 (double) sync->data.input_frames;
854 buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *
856 sync->data.data_out = (float *) buf->data;
857 if( src_process( sync->state, &sync->data ) )
859 /* XXX If this happens, we're screwed */
860 hb_log( "sync: src_process failed" );
862 hb_buffer_close( &buf_raw );
864 buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );
866 /* Set dates for resampled data */
868 buf->stop = start + sync->data.output_frames_gen *
871 sync->count_frames += sync->data.output_frames_gen;
874 buf->frametype = HB_FRAME_AUDIO;
875 hb_fifo_push( fifo, buf );
878 if( hb_fifo_is_full( fifo ) &&
879 pv->way_out_of_sync )
882 * Trash the top audio packet to avoid dead lock as we reconverge.
884 if ( (buf = hb_fifo_get( audio->fifo_raw ) ) != NULL)
885 hb_buffer_close( &buf );
888 if( NeedSilence( w, audio ) )
890 InsertSilence( w, i );
894 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
896 hb_work_private_t * pv = w->private_data;
897 hb_job_t * job = pv->job;
899 if( hb_fifo_size( audio->fifo_in ) ||
900 hb_fifo_size( audio->fifo_raw ) ||
901 hb_fifo_size( audio->fifo_sync ) ||
902 hb_fifo_size( audio->fifo_out ) )
904 /* We have some audio, we are fine */
908 /* No audio left in fifos */
910 if( hb_thread_has_exited( job->reader ) )
912 /* We might miss some audio to complete encoding and muxing
914 hb_log("Reader has exited early, inserting silence.");
918 if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
919 hb_fifo_is_full( job->fifo_raw ) &&
920 hb_fifo_is_full( job->fifo_sync ) &&
921 hb_fifo_is_full( job->fifo_render ) &&
922 hb_fifo_is_full( job->fifo_mpeg4 ) )
924 /* Too much video and no audio, oh-oh */
925 hb_log("Still got some video - and nothing in the audio fifo, insert silence");
932 static void InsertSilence( hb_work_object_t * w, int i )
934 hb_work_private_t * pv = w->private_data;
936 hb_sync_audio_t * sync;
940 sync = &pv->sync_audio[i];
942 if( job->acodec & HB_ACODEC_AC3 ||
943 job->audio_mixdowns[i] == HB_AMIXDOWN_AC3 )
945 buf = hb_buffer_init( sync->ac3_size );
946 buf->start = sync->count_frames * 90000 / sync->audio->rate;
947 buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
949 memcpy( buf->data, sync->ac3_buf, buf->size );
951 hb_log( "sync: adding a silent AC-3 frame for track %x",
953 hb_fifo_push( sync->audio->fifo_out, buf );
955 sync->count_frames += AC3_SAMPLES_PER_FRAME;
960 buf = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *
962 buf->start = sync->count_frames * 90000 / job->arate;
963 buf->stop = buf->start + 90000 / 20;
964 memset( buf->data, 0, buf->size );
966 hb_fifo_push( sync->audio->fifo_sync, buf );
968 sync->count_frames += job->arate / 20;
972 static void UpdateState( hb_work_object_t * w )
974 hb_work_private_t * pv = w->private_data;
977 if( !pv->count_frames )
979 pv->st_first = hb_get_date();
983 if( hb_get_date() > pv->st_dates[3] + 1000 )
985 memmove( &pv->st_dates[0], &pv->st_dates[1],
986 3 * sizeof( uint64_t ) );
987 memmove( &pv->st_counts[0], &pv->st_counts[1],
988 3 * sizeof( uint64_t ) );
989 pv->st_dates[3] = hb_get_date();
990 pv->st_counts[3] = pv->count_frames;
993 #define p state.param.working
994 state.state = HB_STATE_WORKING;
995 p.progress = (float) pv->count_frames / (float) pv->count_frames_max;
996 if( p.progress > 1.0 )
1000 p.rate_cur = 1000.0 *
1001 (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
1002 (float) ( pv->st_dates[3] - pv->st_dates[0] );
1003 if( hb_get_date() > pv->st_first + 4000 )
1006 p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
1007 (float) ( pv->st_dates[3] - pv->st_first );
1008 eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
1010 p.hours = eta / 3600;
1011 p.minutes = ( eta % 3600 ) / 60;
1012 p.seconds = eta % 60;
1023 hb_set_state( pv->job->h, &state );