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.fr/>.
5 It may be used under the terms of the GNU General Public License. */
10 #include "samplerate.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
22 int ref; /* Reference count to tell us when it's unused */
24 int64_t audio_pts_slip;
25 int64_t video_pts_slip;
28 /* Frame based point-to-point support */
29 int64_t audio_pts_thresh;
31 hb_cond_t * next_frame;
39 double next_start; /* start time of next output frame */
40 int64_t first_drop; /* PTS of first 'went backwards' frame dropped */
41 int drop_count; /* count of 'time went backwards' drops */
57 int64_t next_start; /* start time of next output frame */
58 int64_t first_drop; /* PTS of first 'went backwards' frame dropped */
59 int drop_count; /* count of 'time went backwards' drops */
60 int drops; /* frames dropped to make a cbr video stream */
61 int dups; /* frames duplicated to make a cbr video stream */
64 int chap_mark; /* to propagate chapter mark across a drop */
65 hb_buffer_t * cur; /* The next picture to process */
68 uint64_t st_counts[4];
73 struct hb_work_private_s
76 hb_sync_common_t * common;
79 hb_sync_video_t video;
80 hb_sync_audio_t audio;
84 /***********************************************************************
86 **********************************************************************/
87 static void getPtsOffset( hb_work_object_t * w );
88 static int checkPtsOffset( hb_work_object_t * w );
89 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i );
90 static void InsertSilence( hb_work_object_t * w, int64_t d );
91 static void UpdateState( hb_work_object_t * w );
92 static void UpdateSearchState( hb_work_object_t * w, int64_t start );
93 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
94 hb_sync_audio_t *sync );
96 /***********************************************************************
98 ***********************************************************************
99 * Initialize the work object
100 **********************************************************************/
101 hb_work_object_t * hb_sync_init( hb_job_t * job )
103 hb_title_t * title = job->title;
104 hb_chapter_t * chapter;
107 hb_work_private_t * pv;
108 hb_sync_video_t * sync;
109 hb_work_object_t * w;
110 hb_work_object_t * ret = NULL;
112 pv = calloc( 1, sizeof( hb_work_private_t ) );
113 sync = &pv->type.video;
114 pv->common = calloc( 1, sizeof( hb_sync_common_t ) );
116 pv->common->mutex = hb_lock_init();
117 pv->common->audio_pts_thresh = -1;
118 pv->common->next_frame = hb_cond_init();
119 pv->common->pts_count = 1;
120 if ( job->frame_to_start || job->pts_to_start )
122 pv->common->start_found = 0;
126 pv->common->start_found = 1;
129 ret = w = hb_get_work( WORK_SYNC_VIDEO );
130 w->private_data = pv;
131 w->fifo_in = job->fifo_raw;
132 w->fifo_out = job->fifo_sync;
135 pv->common->pts_offset = INT64_MIN;
136 sync->first_frame = 1;
140 /* We already have an accurate frame count from pass 1 */
141 hb_interjob_t * interjob = hb_interjob_get( job->h );
142 sync->count_frames_max = interjob->frame_count;
146 /* Calculate how many video frames we are expecting */
147 if ( job->pts_to_stop )
149 duration = job->pts_to_stop + 90000;
151 else if( job->frame_to_stop )
153 /* Set the duration to a rough estimate */
154 duration = ( job->frame_to_stop / ( title->rate / title->rate_base ) ) * 90000;
159 for( i = job->chapter_start; i <= job->chapter_end; i++ )
161 chapter = hb_list_item( title->list_chapter, i - 1 );
162 duration += chapter->duration;
165 /* 1 second safety so we're sure we won't miss anything */
167 sync->count_frames_max = duration * title->rate / title->rate_base / 90000;
170 hb_log( "sync: expecting %d video frames", sync->count_frames_max );
172 /* Initialize libsamplerate for every audio track we have */
173 if ( ! job->indepth_scan )
175 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
177 InitAudio( job, pv->common, i );
180 pv->common->first_pts = malloc( sizeof(int64_t) * pv->common->pts_count );
181 for ( i = 0; i < pv->common->pts_count; i++ )
182 pv->common->first_pts[i] = INT64_MAX;
187 /***********************************************************************
189 ***********************************************************************
191 **********************************************************************/
192 void syncVideoClose( hb_work_object_t * w )
194 hb_work_private_t * pv = w->private_data;
195 hb_job_t * job = pv->job;
196 hb_sync_video_t * sync = &pv->type.video;
198 // Wake up audio sync if it's still waiting on condition.
199 pv->common->pts_offset = 0;
200 pv->common->start_found = 1;
201 hb_cond_broadcast( pv->common->next_frame );
205 hb_buffer_close( &sync->cur );
208 hb_log( "sync: got %d frames, %d expected",
209 pv->common->count_frames, sync->count_frames_max );
211 /* save data for second pass */
214 /* Preserve frame count for better accuracy in pass 2 */
215 hb_interjob_t * interjob = hb_interjob_get( job->h );
216 interjob->frame_count = pv->common->count_frames;
217 interjob->last_job = job->sequence_id;
218 interjob->total_time = sync->next_start;
221 if (sync->drops || sync->dups )
223 hb_log( "sync: %d frames dropped, %d duplicated",
224 sync->drops, sync->dups );
227 hb_lock( pv->common->mutex );
228 if ( --pv->common->ref == 0 )
230 hb_unlock( pv->common->mutex );
231 hb_lock_close( &pv->common->mutex );
236 hb_unlock( pv->common->mutex );
240 w->private_data = NULL;
243 /***********************************************************************
245 ***********************************************************************
247 **********************************************************************/
248 static hb_buffer_t * copy_subtitle( hb_buffer_t * src );
250 int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
251 hb_buffer_t ** buf_out )
253 hb_buffer_t * cur, * next, * sub = NULL;
254 hb_work_private_t * pv = w->private_data;
255 hb_job_t * job = pv->job;
256 hb_subtitle_t * subtitle;
257 hb_sync_video_t * sync = &pv->type.video;
259 int64_t start, next_start;
265 /* Wait till we can determine the initial pts of all streams */
266 if( next->size != 0 && pv->common->pts_offset == INT64_MIN )
268 pv->common->first_pts[0] = next->start;
269 hb_lock( pv->common->mutex );
270 while( pv->common->pts_offset == INT64_MIN )
272 // Full fifos will make us wait forever, so get the
273 // pts offset from the available streams if full
274 if ( hb_fifo_is_full( job->fifo_raw ) )
277 hb_cond_broadcast( pv->common->next_frame );
279 else if ( checkPtsOffset( w ) )
280 hb_cond_broadcast( pv->common->next_frame );
282 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
284 hb_unlock( pv->common->mutex );
287 hb_lock( pv->common->mutex );
288 next_start = next->start - pv->common->video_pts_slip;
289 hb_unlock( pv->common->mutex );
291 /* Wait for start of point-to-point encoding */
292 if( !pv->common->start_found )
294 hb_sync_video_t * sync = &pv->type.video;
296 if( next->size == 0 )
299 pv->common->start_found = 1;
300 hb_cond_broadcast( pv->common->next_frame );
303 * Push through any subtitle EOFs in case they
304 * were not synced through.
306 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
308 subtitle = hb_list_item( job->list_subtitle, i );
309 if( subtitle->config.dest == PASSTHRUSUB )
311 if( subtitle->source == VOBSUB )
312 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
314 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
319 if ( pv->common->count_frames < job->frame_to_start ||
320 next_start < job->pts_to_start )
322 // Flush any subtitles that have pts prior to the
324 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
326 subtitle = hb_list_item( job->list_subtitle, i );
327 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
329 if ( sub->start > next->start )
331 sub = hb_fifo_get( subtitle->fifo_raw );
332 hb_buffer_close( &sub );
335 hb_lock( pv->common->mutex );
336 // Tell the audio threads what must be dropped
337 pv->common->audio_pts_thresh = next_start;
338 hb_cond_broadcast( pv->common->next_frame );
339 hb_unlock( pv->common->mutex );
341 UpdateSearchState( w, next->start );
342 hb_buffer_close( &next );
346 hb_lock( pv->common->mutex );
347 pv->common->audio_pts_thresh = 0;
348 pv->common->audio_pts_slip = next_start;
349 pv->common->video_pts_slip = next_start;
351 pv->common->start_found = 1;
352 pv->common->count_frames = 0;
353 hb_cond_broadcast( pv->common->next_frame );
354 hb_unlock( pv->common->mutex );
361 if( sync->cur->size == 0 )
363 /* we got an end-of-stream as our first video packet?
364 * Feed it downstream & signal that we're done.
366 *buf_out = hb_buffer_init( 0 );
368 pv->common->start_found = 1;
369 hb_cond_broadcast( pv->common->next_frame );
372 * Push through any subtitle EOFs in case they
373 * were not synced through.
375 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
377 subtitle = hb_list_item( job->list_subtitle, i );
378 if( subtitle->config.dest == PASSTHRUSUB )
380 if( subtitle->source == VOBSUB )
381 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
383 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
391 /* At this point we have a frame to process. Let's check
392 1) if we will be able to push into the fifo ahead
393 2) if the next frame is there already, since we need it to
394 compute the duration of the current frame*/
395 if( next->size == 0 )
397 hb_buffer_close( &next );
399 cur->start = sync->next_start;
400 cur->stop = cur->start + 90000. / ((double)job->vrate / (double)job->vrate_base);
402 /* Make sure last frame is reflected in frame count */
403 pv->common->count_frames++;
405 /* Push the frame to the renderer */
406 hb_fifo_push( job->fifo_sync, cur );
409 /* we got an end-of-stream. Feed it downstream & signal that
410 * we're done. Note that this means we drop the final frame of
411 * video (we don't know its duration). On DVDs the final frame
412 * is often strange and dropping it seems to be a good idea. */
413 *buf_out = hb_buffer_init( 0 );
416 * Push through any subtitle EOFs in case they were not synced through.
418 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
420 subtitle = hb_list_item( job->list_subtitle, i );
421 if( subtitle->config.dest == PASSTHRUSUB )
423 if( subtitle->source == VOBSUB )
424 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
426 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
429 pv->common->start_found = 1;
430 hb_cond_broadcast( pv->common->next_frame );
434 /* Check for end of point-to-point frame encoding */
435 if( job->frame_to_stop && pv->common->count_frames > job->frame_to_stop )
437 // Drop an empty buffer into our output to ensure that things
438 // get flushed all the way out.
439 hb_buffer_close( &sync->cur );
440 hb_buffer_close( &next );
441 *buf_out = hb_buffer_init( 0 );
442 hb_log( "sync: reached %d frames, exiting early",
443 pv->common->count_frames );
446 * Push through any subtitle EOFs in case they were not synced through.
448 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
450 subtitle = hb_list_item( job->list_subtitle, i );
451 if( subtitle->config.dest == PASSTHRUSUB )
453 if( subtitle->source == VOBSUB )
454 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
456 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
462 hb_lock( pv->common->mutex );
463 start = cur->start - pv->common->video_pts_slip;
464 hb_unlock( pv->common->mutex );
466 /* Check for end of point-to-point pts encoding */
467 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
469 // Drop an empty buffer into our output to ensure that things
470 // get flushed all the way out.
471 hb_log( "sync: reached pts %"PRId64", exiting early", start );
472 hb_buffer_close( &sync->cur );
473 hb_buffer_close( &next );
474 *buf_out = hb_buffer_init( 0 );
477 * Push through any subtitle EOFs in case they were not synced through.
479 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
481 subtitle = hb_list_item( job->list_subtitle, i );
482 if( subtitle->config.dest == PASSTHRUSUB )
484 if( subtitle->source == VOBSUB )
485 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
487 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
493 if( sync->first_frame )
495 /* This is our first frame */
499 * The first pts from a dvd should always be zero but
500 * can be non-zero with a transport or program stream since
501 * we're not guaranteed to start on an IDR frame. If we get
502 * a non-zero initial PTS extend its duration so it behaves
503 * as if it started at zero so that our audio timing will
506 hb_log( "sync: first pts is %"PRId64, start );
509 sync->first_frame = 0;
513 * since the first frame is always 0 and the upstream reader code
514 * is taking care of adjusting for pts discontinuities, we just have
515 * to deal with the next frame's start being in the past. This can
516 * happen when the PTS is adjusted after data loss but video frame
517 * reordering causes some frames with the old clock to appear after
518 * the clock change. This creates frames that overlap in time which
519 * looks to us like time going backward. The downstream muxing code
520 * can deal with overlaps of up to a frame time but anything larger
521 * we handle by dropping frames here.
523 if ( next_start - start <= 0 )
525 if ( sync->first_drop == 0 )
527 sync->first_drop = next_start;
530 if ( next->new_chap )
532 // don't drop a chapter mark when we drop the buffer
533 sync->chap_mark = next->new_chap;
535 hb_buffer_close( &next );
538 if ( sync->first_drop )
540 hb_log( "sync: video time didn't advance - dropped %d frames "
541 "(delta %d ms, current %"PRId64", next %"PRId64", dur %d)",
542 sync->drop_count, (int)( start - sync->first_drop ) / 90,
543 start, next_start, (int)( next_start - start ) );
544 sync->first_drop = 0;
545 sync->drop_count = 0;
549 * Track the video sequence number localy so that we can sync the audio
550 * to it using the sequence number as well as the PTS.
552 sync->video_sequence = cur->sequence;
555 * Look for a subtitle for this frame.
557 * If found then it will be tagged onto a video buffer of the correct time and
558 * sent in to the render pipeline. This only needs to be done for VOBSUBs which
559 * get rendered, other types of subtitles can just sit in their raw_queue until
560 * delt with at muxing.
562 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
564 int64_t sub_start, sub_stop, duration;
565 subtitle = hb_list_item( job->list_subtitle, i );
568 * Rewrite timestamps on subtitles that need it (on raw queue).
570 // NOTE: It's probably fine to use this logic for passthru VOBSUBs as well,
571 // but I am currently preserving backwards compatibility with the old
572 // VOBSUB behavior, which uses the more complex logic following this if-statement.
573 if( subtitle->config.dest == PASSTHRUSUB && subtitle->source != VOBSUB )
576 * Rewrite timestamps on subtitles that came from Closed Captions
577 * since they are using the MPEG2 timestamps.
579 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
581 hb_lock( pv->common->mutex );
582 sub_start = sub->start - pv->common->video_pts_slip;
583 hb_unlock( pv->common->mutex );
584 duration = sub->stop - sub->start;
585 sub_stop = sub_start + duration;
588 * Rewrite the timestamps as and when the video
589 * (cur->start) reaches the same timestamp as a
590 * closed caption (sub->start).
592 * What about discontinuity boundaries - not delt
595 * Bypass the sync fifo altogether.
599 sub = hb_fifo_get( subtitle->fifo_raw );
600 hb_fifo_push( subtitle->fifo_out, sub );
605 * Sync the subtitles to the incoming video, and use
606 * the matching converted video timestamp.
608 * Note that it doesn't appear that we need to convert
609 * timestamps, I guess that they were already correct,
610 * so just push them through for rendering.
613 if( sub_start < start )
615 sub = hb_fifo_get( subtitle->fifo_raw );
616 sub->start = sub_start;
617 sub->stop = sub_stop;
618 hb_fifo_push( subtitle->fifo_out, sub );
629 // For rendered subtitles (and, for backward compatibility, passthru VOBSUBs),
630 // delay pushing subtitle packets through the pipeline until the video catches up
631 if( subtitle->config.dest == RENDERSUB || subtitle->source == VOBSUB )
634 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
639 * EOF, pass it through immediately.
644 hb_lock( pv->common->mutex );
645 sub_start = sub->start - pv->common->video_pts_slip;
646 hb_unlock( pv->common->mutex );
647 duration = sub->stop - sub->start;
648 sub_stop = sub_start + duration;
650 /* If two subtitles overlap, make the first one stop
651 when the second one starts */
652 sub2 = hb_fifo_see2( subtitle->fifo_raw );
653 if( sub2 && sub->stop > sub2->start )
655 sub->stop = sub2->start;
658 // hb_log("0x%x: video seq: %"PRId64" subtitle sequence: %"PRId64,
659 // sub, cur->sequence, sub->sequence);
661 if( sub->sequence > cur->sequence )
664 * The video is behind where we are, so wait until
665 * it catches up to the same reader point on the
666 * DVD. Then our PTS should be in the same region
673 if( sub_stop > start )
676 * The stop time is in the future, so fall through
677 * and we'll deal with it in the next block of
682 * There is a valid subtitle, is it time to display it?
684 if( sub_stop > sub_start)
687 * Normal subtitle which ends after it starts,
688 * check to see that the current video is between
691 if( start > sub_start &&
695 * We should be playing this, so leave the
698 * fall through to display
704 * Defer until the play point is within
713 * The end of the subtitle is less than the start,
714 * this is a sign of a PTS discontinuity.
716 if( sub_start > start )
719 * we haven't reached the start time yet, or
720 * we have jumped backwards after having
721 * already started this subtitle.
723 if( start < sub_stop )
726 * We have jumped backwards and so should
727 * continue displaying this subtitle.
729 * fall through to display.
735 * Defer until the play point is
736 * within the subtitle
742 * Play this subtitle as the start is
743 * greater than our video point.
745 * fall through to display/
755 * The subtitle is older than this picture, trash it
757 sub = hb_fifo_get( subtitle->fifo_raw );
758 hb_buffer_close( &sub );
762 /* If we have a subtitle for this picture, copy it */
767 if( subtitle->config.dest == RENDERSUB )
769 // Only allow one subtitle to be showing at once; ignore others
770 if ( cur->sub == NULL )
773 * Tack onto the video buffer for rendering
775 /* FIXME: we should avoid this memcpy */
776 cur->sub = copy_subtitle( sub );
777 cur->sub->start = sub_start;
778 cur->sub->stop = sub_stop;
780 // Leave the subtitle on the raw queue
781 // (until it no longer needs to be displayed)
785 * Pass-Through, pop it off of the raw queue,
787 sub = hb_fifo_get( subtitle->fifo_raw );
788 sub->start = sub_start;
789 sub->stop = sub_stop;
790 hb_fifo_push( subtitle->fifo_sync, sub );
794 * EOF - consume for rendered, else pass through
796 if( subtitle->config.dest == RENDERSUB )
798 sub = hb_fifo_get( subtitle->fifo_raw );
799 hb_buffer_close( &sub );
801 sub = hb_fifo_get( subtitle->fifo_raw );
802 sub->start = sub_start;
803 sub->stop = sub_stop;
804 hb_fifo_push( subtitle->fifo_sync, sub );
812 * Adjust the pts of the current frame so that it's contiguous
813 * with the previous frame. The start time of the current frame
814 * has to be the end time of the previous frame and the stop
815 * time has to be the start of the next frame. We don't
816 * make any adjustments to the source timestamps other than removing
817 * the clock offsets (which also removes pts discontinuities).
818 * This means we automatically encode at the source's frame rate.
819 * MP2 uses an implicit duration (frames end when the next frame
820 * starts) but more advanced containers like MP4 use an explicit
821 * duration. Since we're looking ahead one frame we set the
822 * explicit stop time from the start time of the next frame.
825 sync->cur = cur = next;
827 int64_t duration = next_start - start;
831 hb_log( "sync: invalid video duration %"PRId64", start %"PRId64", next %"PRId64"",
832 duration, start, next_start );
835 (*buf_out)->start = sync->next_start;
836 sync->next_start += duration;
837 (*buf_out)->stop = sync->next_start;
839 if ( sync->chap_mark )
841 // we have a pending chapter mark from a recent drop - put it on this
842 // buffer (this may make it one frame late but we can't do any better).
843 (*buf_out)->new_chap = sync->chap_mark;
853 static hb_buffer_t * copy_subtitle( hb_buffer_t * src_list )
855 hb_buffer_t * dst_list = NULL;
859 hb_buffer_t ** dst_ptr = &dst_list;
860 for ( src = src_list, dst_ptr = &dst_list;
862 src = src->next_subpicture, dst_ptr = &dst->next_subpicture )
864 (*dst_ptr) = hb_buffer_init( src->size );
868 dst->width = src->width;
869 dst->height = src->height;
870 memcpy( dst->data, src->data, src->size );
876 // sync*Init does nothing because sync has a special initializer
877 // that takes care of initializing video and all audio tracks
878 int syncVideoInit( hb_work_object_t * w, hb_job_t * job)
883 hb_work_object_t hb_sync_video =
886 "Video Synchronization",
892 /***********************************************************************
894 ***********************************************************************
896 **********************************************************************/
897 void syncAudioClose( hb_work_object_t * w )
899 hb_work_private_t * pv = w->private_data;
900 hb_sync_audio_t * sync = &pv->type.audio;
902 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
904 free( sync->ac3_buf );
908 src_delete( sync->state );
911 hb_lock( pv->common->mutex );
912 if ( --pv->common->ref == 0 )
914 hb_unlock( pv->common->mutex );
915 hb_lock_close( &pv->common->mutex );
920 hb_unlock( pv->common->mutex );
924 w->private_data = NULL;
927 int syncAudioInit( hb_work_object_t * w, hb_job_t * job)
932 /***********************************************************************
934 ***********************************************************************
936 **********************************************************************/
937 static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
938 hb_buffer_t ** buf_out )
940 hb_work_private_t * pv = w->private_data;
941 hb_job_t * job = pv->job;
942 hb_sync_audio_t * sync = &pv->type.audio;
949 /* if the next buffer is an eof send it downstream */
950 if ( buf->size <= 0 )
952 hb_buffer_close( &buf );
953 *buf_out = hb_buffer_init( 0 );
957 /* Wait till we can determine the initial pts of all streams */
958 if( pv->common->pts_offset == INT64_MIN )
960 pv->common->first_pts[sync->index+1] = buf->start;
961 hb_lock( pv->common->mutex );
962 while( pv->common->pts_offset == INT64_MIN )
964 // Full fifos will make us wait forever, so get the
965 // pts offset from the available streams if full
966 if (hb_fifo_is_full(w->fifo_in))
969 hb_cond_broadcast( pv->common->next_frame );
971 else if ( checkPtsOffset( w ) )
972 hb_cond_broadcast( pv->common->next_frame );
974 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
976 hb_unlock( pv->common->mutex );
979 /* Wait for start frame if doing point-to-point */
980 hb_lock( pv->common->mutex );
981 start = buf->start - pv->common->audio_pts_slip;
982 while ( !pv->common->start_found )
984 if ( pv->common->audio_pts_thresh < 0 )
986 // I would initialize this in hb_sync_init, but
987 // job->pts_to_start can be modified by reader
988 // after hb_sync_init is called.
989 pv->common->audio_pts_thresh = job->pts_to_start;
991 if ( start < pv->common->audio_pts_thresh )
993 hb_buffer_close( &buf );
994 hb_unlock( pv->common->mutex );
997 while ( !pv->common->start_found &&
998 start >= pv->common->audio_pts_thresh )
1000 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
1002 start = buf->start - pv->common->audio_pts_slip;
1006 hb_buffer_close( &buf );
1007 hb_unlock( pv->common->mutex );
1010 hb_unlock( pv->common->mutex );
1012 if( job->frame_to_stop && pv->common->count_frames >= job->frame_to_stop )
1014 hb_buffer_close( &buf );
1015 *buf_out = hb_buffer_init( 0 );
1016 return HB_WORK_DONE;
1019 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
1021 hb_buffer_close( &buf );
1022 *buf_out = hb_buffer_init( 0 );
1023 return HB_WORK_DONE;
1026 if ( start - sync->next_start < 0 )
1028 // audio time went backwards.
1029 // If our output clock is more than a half frame ahead of the
1030 // input clock drop this frame to move closer to sync.
1031 // Otherwise drop frames until the input clock matches the output clock.
1032 if ( sync->first_drop || sync->next_start - start > 90*15 )
1034 // Discard data that's in the past.
1035 if ( sync->first_drop == 0 )
1037 sync->first_drop = sync->next_start;
1040 hb_buffer_close( &buf );
1044 if ( sync->first_drop )
1046 // we were dropping old data but input buf time is now current
1047 hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
1048 "(next %"PRId64", current %"PRId64")", w->audio->id,
1049 (int)( sync->next_start - sync->first_drop ) / 90,
1050 sync->drop_count, sync->first_drop, (int64_t)sync->next_start );
1051 sync->first_drop = 0;
1052 sync->drop_count = 0;
1054 if ( start - sync->next_start >= (90 * 70) )
1056 if ( start - sync->next_start > (90000LL * 60) )
1058 // there's a gap of more than a minute between the last
1059 // frame and this. assume we got a corrupted timestamp
1060 // and just drop the next buf.
1061 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
1062 " start %"PRId64", next %"PRId64,
1063 (int)((start - sync->next_start) / (90000*60)),
1064 w->audio->id, start, (int64_t)sync->next_start );
1065 hb_buffer_close( &buf );
1069 * there's a gap of at least 70ms between the last
1070 * frame we processed & the next. Fill it with silence.
1071 * Or in the case of DCA, skip some frames from the
1074 if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1076 hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d"
1077 " start %"PRId64", next %"PRId64,
1078 (int)((start - sync->next_start) / 90),
1079 w->audio->id, start, (int64_t)sync->next_start );
1080 hb_lock( pv->common->mutex );
1081 pv->common->audio_pts_slip += (start - sync->next_start);
1082 pv->common->video_pts_slip += (start - sync->next_start);
1083 hb_unlock( pv->common->mutex );
1087 hb_log( "sync: adding %d ms of silence to audio %d"
1088 " start %"PRId64", next %"PRId64,
1089 (int)((start - sync->next_start) / 90),
1090 w->audio->id, start, (int64_t)sync->next_start );
1091 InsertSilence( w, start - sync->next_start );
1095 * When we get here we've taken care of all the dups and gaps in the
1096 * audio stream and are ready to inject the next input frame into
1097 * the output stream.
1099 *buf_out = OutputAudioFrame( w->audio, buf, sync );
1103 hb_work_object_t hb_sync_audio =
1106 "AudioSynchronization",
1112 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
1114 hb_work_object_t * w;
1115 hb_work_private_t * pv;
1116 hb_title_t * title = job->title;
1117 hb_sync_audio_t * sync;
1119 pv = calloc( 1, sizeof( hb_work_private_t ) );
1120 sync = &pv->type.audio;
1123 pv->common = common;
1125 pv->common->pts_count++;
1127 w = hb_get_work( WORK_SYNC_AUDIO );
1128 w->private_data = pv;
1129 w->audio = hb_list_item( title->list_audio, i );
1130 w->fifo_in = w->audio->priv.fifo_raw;
1132 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1133 w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1135 w->fifo_out = w->audio->priv.fifo_out;
1139 w->fifo_out = w->audio->priv.fifo_sync;
1142 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1144 /* Have a silent AC-3 frame ready in case we have to fill a
1150 codec = avcodec_find_encoder( CODEC_ID_AC3 );
1151 c = avcodec_alloc_context();
1153 c->bit_rate = w->audio->config.in.bitrate;
1154 c->sample_rate = w->audio->config.in.samplerate;
1155 c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( w->audio->config.in.channel_layout );
1157 if( hb_avcodec_open( c, codec ) < 0 )
1159 hb_log( "sync: avcodec_open failed" );
1163 zeros = calloc( AC3_SAMPLES_PER_FRAME *
1164 sizeof( short ) * c->channels, 1 );
1165 sync->ac3_size = w->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
1166 w->audio->config.in.samplerate / 8;
1167 sync->ac3_buf = malloc( sync->ac3_size );
1169 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
1170 zeros ) != sync->ac3_size )
1172 hb_log( "sync: avcodec_encode_audio failed" );
1176 hb_avcodec_close( c );
1181 /* Initialize libsamplerate */
1183 sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
1184 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1185 w->audio->config.out.mixdown), &error );
1186 sync->data.end_of_input = 0;
1188 hb_list_add( job->list_work, w );
1191 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
1192 hb_sync_audio_t *sync )
1194 int64_t start = (int64_t)sync->next_start;
1195 double duration = buf->stop - buf->start;
1197 if( audio->config.in.samplerate == audio->config.out.samplerate ||
1198 audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1199 audio->config.out.codec == HB_ACODEC_DCA_PASS )
1202 * If we don't have to do sample rate conversion or this audio is
1203 * pass-thru just send the input buffer downstream after adjusting
1204 * its timestamps to make the output stream continuous.
1209 /* Not pass-thru - do sample rate conversion */
1210 int count_in, count_out;
1211 hb_buffer_t * buf_raw = buf;
1212 int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
1215 count_in = buf_raw->size / channel_count;
1217 * When using stupid rates like 44.1 there will always be some
1218 * truncation error. E.g., a 1536 sample AC3 frame will turn into a
1219 * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
1220 * the error will build up over time and eventually the audio will
1221 * substantially lag the video. libsamplerate will keep track of the
1222 * fractional sample & give it to us when appropriate if we give it
1223 * an extra sample of space in the output buffer.
1225 count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
1227 sync->data.input_frames = count_in;
1228 sync->data.output_frames = count_out;
1229 sync->data.src_ratio = (double)audio->config.out.samplerate /
1230 (double)audio->config.in.samplerate;
1232 buf = hb_buffer_init( count_out * channel_count );
1233 sync->data.data_in = (float *) buf_raw->data;
1234 sync->data.data_out = (float *) buf->data;
1235 if( src_process( sync->state, &sync->data ) )
1237 /* XXX If this happens, we're screwed */
1238 hb_log( "sync: audio %d src_process failed", audio->id );
1240 hb_buffer_close( &buf_raw );
1242 buf->size = sync->data.output_frames_gen * channel_count;
1243 duration = (double)( sync->data.output_frames_gen * 90000 ) /
1244 audio->config.out.samplerate;
1246 buf->frametype = HB_FRAME_AUDIO;
1248 sync->next_start += duration;
1249 buf->stop = (int64_t)sync->next_start;
1253 static void InsertSilence( hb_work_object_t * w, int64_t duration )
1255 hb_work_private_t * pv = w->private_data;
1256 hb_sync_audio_t *sync = &pv->type.audio;
1260 // to keep pass-thru and regular audio in sync we generate silence in
1261 // AC3 frame-sized units. If the silence duration isn't an integer multiple
1262 // of the AC3 frame duration we will truncate or round up depending on
1263 // which minimizes the timing error.
1264 const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
1265 w->audio->config.in.samplerate;
1266 int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
1268 while ( --frame_count >= 0 )
1270 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1272 buf = hb_buffer_init( sync->ac3_size );
1273 buf->start = sync->next_start;
1274 buf->stop = buf->start + frame_dur;
1275 memcpy( buf->data, sync->ac3_buf, buf->size );
1276 fifo = w->audio->priv.fifo_out;
1280 buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
1281 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1282 w->audio->config.out.mixdown) );
1283 buf->start = sync->next_start;
1284 buf->stop = buf->start + frame_dur;
1285 memset( buf->data, 0, buf->size );
1286 fifo = w->audio->priv.fifo_sync;
1288 buf = OutputAudioFrame( w->audio, buf, sync );
1289 hb_fifo_push( fifo, buf );
1293 static void UpdateState( hb_work_object_t * w )
1295 hb_work_private_t * pv = w->private_data;
1296 hb_sync_video_t * sync = &pv->type.video;
1299 if( !pv->common->count_frames )
1301 sync->st_first = hb_get_date();
1302 pv->job->st_pause_date = -1;
1303 pv->job->st_paused = 0;
1305 pv->common->count_frames++;
1307 if( hb_get_date() > sync->st_dates[3] + 1000 )
1309 memmove( &sync->st_dates[0], &sync->st_dates[1],
1310 3 * sizeof( uint64_t ) );
1311 memmove( &sync->st_counts[0], &sync->st_counts[1],
1312 3 * sizeof( uint64_t ) );
1313 sync->st_dates[3] = hb_get_date();
1314 sync->st_counts[3] = pv->common->count_frames;
1317 #define p state.param.working
1318 state.state = HB_STATE_WORKING;
1319 p.progress = (float) pv->common->count_frames / (float) sync->count_frames_max;
1320 if( p.progress > 1.0 )
1324 p.rate_cur = 1000.0 *
1325 (float) ( sync->st_counts[3] - sync->st_counts[0] ) /
1326 (float) ( sync->st_dates[3] - sync->st_dates[0] );
1327 if( hb_get_date() > sync->st_first + 4000 )
1330 p.rate_avg = 1000.0 * (float) sync->st_counts[3] /
1331 (float) ( sync->st_dates[3] - sync->st_first - pv->job->st_paused);
1332 eta = (float) ( sync->count_frames_max - sync->st_counts[3] ) /
1334 p.hours = eta / 3600;
1335 p.minutes = ( eta % 3600 ) / 60;
1336 p.seconds = eta % 60;
1347 hb_set_state( pv->job->h, &state );
1350 static void UpdateSearchState( hb_work_object_t * w, int64_t start )
1352 hb_work_private_t * pv = w->private_data;
1353 hb_sync_video_t * sync = &pv->type.video;
1358 now = hb_get_date();
1359 if( !pv->common->count_frames )
1361 sync->st_first = now;
1362 pv->job->st_pause_date = -1;
1363 pv->job->st_paused = 0;
1365 pv->common->count_frames++;
1367 #define p state.param.working
1368 state.state = HB_STATE_SEARCHING;
1369 if ( pv->job->frame_to_start )
1370 p.progress = (float) pv->common->count_frames /
1371 (float) pv->job->frame_to_start;
1372 else if ( pv->job->pts_to_start )
1373 p.progress = (float) start / (float) pv->job->pts_to_start;
1376 if( p.progress > 1.0 )
1380 if (now > sync->st_first)
1384 if ( pv->job->frame_to_start )
1386 avg = 1000.0 * (double)pv->common->count_frames / (now - sync->st_first);
1387 eta = ( pv->job->frame_to_start - pv->common->count_frames ) / avg;
1389 else if ( pv->job->pts_to_start )
1391 avg = 1000.0 * (double)start / (now - sync->st_first);
1392 eta = ( pv->job->pts_to_start - start ) / avg;
1394 p.hours = eta / 3600;
1395 p.minutes = ( eta % 3600 ) / 60;
1396 p.seconds = eta % 60;
1407 hb_set_state( pv->job->h, &state );
1410 static void getPtsOffset( hb_work_object_t * w )
1412 hb_work_private_t * pv = w->private_data;
1414 int64_t first_pts = INT64_MAX;
1416 for( i = 0; i < pv->common->pts_count; i++ )
1418 if ( pv->common->first_pts[i] < first_pts )
1419 first_pts = pv->common->first_pts[i];
1421 pv->common->video_pts_slip = pv->common->audio_pts_slip = pv->common->pts_offset = first_pts;
1425 static int checkPtsOffset( hb_work_object_t * w )
1427 hb_work_private_t * pv = w->private_data;
1430 for( i = 0; i < pv->common->pts_count; i++ )
1432 if ( pv->common->first_pts[i] == INT64_MAX )