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 hb_buffer_t * sub_list; /* list of subtitles to be passed thru or rendered */
76 struct hb_work_private_s
79 hb_sync_common_t * common;
82 hb_sync_video_t video;
83 hb_sync_audio_t audio;
87 /***********************************************************************
89 **********************************************************************/
90 static void getPtsOffset( hb_work_object_t * w );
91 static int checkPtsOffset( hb_work_object_t * w );
92 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i );
93 static void InsertSilence( hb_work_object_t * w, int64_t d );
94 static void UpdateState( hb_work_object_t * w );
95 static void UpdateSearchState( hb_work_object_t * w, int64_t start );
96 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
97 hb_sync_audio_t *sync );
99 /***********************************************************************
101 ***********************************************************************
102 * Initialize the work object
103 **********************************************************************/
104 hb_work_object_t * hb_sync_init( hb_job_t * job )
106 hb_title_t * title = job->title;
107 hb_chapter_t * chapter;
110 hb_work_private_t * pv;
111 hb_sync_video_t * sync;
112 hb_work_object_t * w;
113 hb_work_object_t * ret = NULL;
115 pv = calloc( 1, sizeof( hb_work_private_t ) );
116 sync = &pv->type.video;
117 pv->common = calloc( 1, sizeof( hb_sync_common_t ) );
119 pv->common->mutex = hb_lock_init();
120 pv->common->audio_pts_thresh = -1;
121 pv->common->next_frame = hb_cond_init();
122 pv->common->pts_count = 1;
123 if ( job->frame_to_start || job->pts_to_start )
125 pv->common->start_found = 0;
129 pv->common->start_found = 1;
132 ret = w = hb_get_work( WORK_SYNC_VIDEO );
133 w->private_data = pv;
134 w->fifo_in = job->fifo_raw;
135 w->fifo_out = job->fifo_sync;
138 pv->common->pts_offset = INT64_MIN;
139 sync->first_frame = 1;
143 /* We already have an accurate frame count from pass 1 */
144 hb_interjob_t * interjob = hb_interjob_get( job->h );
145 sync->count_frames_max = interjob->frame_count;
149 /* Calculate how many video frames we are expecting */
150 if ( job->pts_to_stop )
152 duration = job->pts_to_stop + 90000;
154 else if( job->frame_to_stop )
156 /* Set the duration to a rough estimate */
157 duration = ( job->frame_to_stop / ( title->rate / title->rate_base ) ) * 90000;
162 for( i = job->chapter_start; i <= job->chapter_end; i++ )
164 chapter = hb_list_item( title->list_chapter, i - 1 );
165 duration += chapter->duration;
168 /* 1 second safety so we're sure we won't miss anything */
170 sync->count_frames_max = duration * title->rate / title->rate_base / 90000;
173 hb_log( "sync: expecting %d video frames", sync->count_frames_max );
175 /* Initialize libsamplerate for every audio track we have */
176 if ( ! job->indepth_scan )
178 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
180 InitAudio( job, pv->common, i );
183 pv->common->first_pts = malloc( sizeof(int64_t) * pv->common->pts_count );
184 for ( i = 0; i < pv->common->pts_count; i++ )
185 pv->common->first_pts[i] = INT64_MAX;
190 /***********************************************************************
192 ***********************************************************************
194 **********************************************************************/
195 void syncVideoClose( hb_work_object_t * w )
197 hb_work_private_t * pv = w->private_data;
198 hb_job_t * job = pv->job;
199 hb_sync_video_t * sync = &pv->type.video;
201 // Wake up audio sync if it's still waiting on condition.
202 pv->common->pts_offset = 0;
203 pv->common->start_found = 1;
204 hb_cond_broadcast( pv->common->next_frame );
208 hb_buffer_close( &sync->cur );
211 hb_log( "sync: got %d frames, %d expected",
212 pv->common->count_frames, sync->count_frames_max );
214 /* save data for second pass */
217 /* Preserve frame count for better accuracy in pass 2 */
218 hb_interjob_t * interjob = hb_interjob_get( job->h );
219 interjob->frame_count = pv->common->count_frames;
220 interjob->last_job = job->sequence_id;
221 interjob->total_time = sync->next_start;
224 if (sync->drops || sync->dups )
226 hb_log( "sync: %d frames dropped, %d duplicated",
227 sync->drops, sync->dups );
230 hb_lock( pv->common->mutex );
231 if ( --pv->common->ref == 0 )
233 hb_unlock( pv->common->mutex );
234 hb_lock_close( &pv->common->mutex );
239 hb_unlock( pv->common->mutex );
243 w->private_data = NULL;
246 /***********************************************************************
248 ***********************************************************************
250 **********************************************************************/
251 static hb_buffer_t * copy_subtitle( hb_buffer_t * src );
253 int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
254 hb_buffer_t ** buf_out )
256 hb_buffer_t * cur, * next, * sub = NULL;
257 hb_work_private_t * pv = w->private_data;
258 hb_job_t * job = pv->job;
259 hb_subtitle_t * subtitle;
260 hb_sync_video_t * sync = &pv->type.video;
262 int64_t start, next_start;
268 /* Wait till we can determine the initial pts of all streams */
269 if( next->size != 0 && pv->common->pts_offset == INT64_MIN )
271 pv->common->first_pts[0] = next->start;
272 hb_lock( pv->common->mutex );
273 while( pv->common->pts_offset == INT64_MIN )
275 // Full fifos will make us wait forever, so get the
276 // pts offset from the available streams if full
277 if ( hb_fifo_is_full( job->fifo_raw ) )
280 hb_cond_broadcast( pv->common->next_frame );
282 else if ( checkPtsOffset( w ) )
283 hb_cond_broadcast( pv->common->next_frame );
285 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
287 hb_unlock( pv->common->mutex );
290 hb_lock( pv->common->mutex );
291 next_start = next->start - pv->common->video_pts_slip;
292 hb_unlock( pv->common->mutex );
294 /* Wait for start of point-to-point encoding */
295 if( !pv->common->start_found )
297 hb_sync_video_t * sync = &pv->type.video;
299 if( next->size == 0 )
302 pv->common->start_found = 1;
303 pv->common->first_pts[0] = INT64_MAX - 1;
304 hb_cond_broadcast( pv->common->next_frame );
307 * Push through any subtitle EOFs in case they
308 * were not synced through.
310 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
312 subtitle = hb_list_item( job->list_subtitle, i );
313 if( subtitle->config.dest == PASSTHRUSUB )
315 if( subtitle->source == VOBSUB )
316 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
318 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
323 if ( pv->common->count_frames < job->frame_to_start ||
324 next->start < job->pts_to_start )
326 // Flush any subtitles that have pts prior to the
328 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
330 subtitle = hb_list_item( job->list_subtitle, i );
331 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
333 if ( sub->start > next->start )
335 sub = hb_fifo_get( subtitle->fifo_raw );
336 hb_buffer_close( &sub );
339 hb_lock( pv->common->mutex );
340 // Tell the audio threads what must be dropped
341 pv->common->audio_pts_thresh = next_start + pv->common->video_pts_slip;
342 hb_cond_broadcast( pv->common->next_frame );
343 hb_unlock( pv->common->mutex );
345 UpdateSearchState( w, next_start );
346 hb_buffer_close( &next );
350 hb_lock( pv->common->mutex );
351 pv->common->audio_pts_thresh = 0;
352 pv->common->audio_pts_slip += next_start;
353 pv->common->video_pts_slip += next_start;
355 pv->common->start_found = 1;
356 pv->common->count_frames = 0;
357 hb_cond_broadcast( pv->common->next_frame );
358 hb_unlock( pv->common->mutex );
365 if( sync->cur->size == 0 )
367 /* we got an end-of-stream as our first video packet?
368 * Feed it downstream & signal that we're done.
370 *buf_out = hb_buffer_init( 0 );
372 pv->common->start_found = 1;
373 pv->common->first_pts[0] = INT64_MAX - 1;
374 hb_cond_broadcast( pv->common->next_frame );
377 * Push through any subtitle EOFs in case they
378 * were not synced through.
380 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
382 subtitle = hb_list_item( job->list_subtitle, i );
383 if( subtitle->config.dest == PASSTHRUSUB )
385 if( subtitle->source == VOBSUB )
386 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
388 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
396 /* At this point we have a frame to process. Let's check
397 1) if we will be able to push into the fifo ahead
398 2) if the next frame is there already, since we need it to
399 compute the duration of the current frame*/
400 if( next->size == 0 )
402 hb_buffer_close( &next );
404 pv->common->first_pts[0] = INT64_MAX - 1;
405 cur->start = sync->next_start;
406 cur->stop = cur->start + 90000. / ((double)job->vrate / (double)job->vrate_base);
408 /* Make sure last frame is reflected in frame count */
409 pv->common->count_frames++;
411 /* Push the frame to the renderer */
412 hb_fifo_push( job->fifo_sync, cur );
415 /* we got an end-of-stream. Feed it downstream & signal that
416 * we're done. Note that this means we drop the final frame of
417 * video (we don't know its duration). On DVDs the final frame
418 * is often strange and dropping it seems to be a good idea. */
419 *buf_out = hb_buffer_init( 0 );
422 * Push through any subtitle EOFs in case they were not synced through.
424 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
426 subtitle = hb_list_item( job->list_subtitle, i );
427 if( subtitle->config.dest == PASSTHRUSUB )
429 if( subtitle->source == VOBSUB )
430 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
432 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
435 pv->common->start_found = 1;
436 hb_cond_broadcast( pv->common->next_frame );
440 /* Check for end of point-to-point frame encoding */
441 if( job->frame_to_stop && pv->common->count_frames > job->frame_to_stop )
443 // Drop an empty buffer into our output to ensure that things
444 // get flushed all the way out.
445 hb_buffer_close( &sync->cur );
446 hb_buffer_close( &next );
447 *buf_out = hb_buffer_init( 0 );
448 hb_log( "sync: reached %d frames, exiting early",
449 pv->common->count_frames );
452 * Push through any subtitle EOFs in case they were not synced through.
454 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
456 subtitle = hb_list_item( job->list_subtitle, i );
457 if( subtitle->config.dest == PASSTHRUSUB )
459 if( subtitle->source == VOBSUB )
460 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
462 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
468 hb_lock( pv->common->mutex );
469 start = cur->start - pv->common->video_pts_slip;
470 hb_unlock( pv->common->mutex );
472 /* Check for end of point-to-point pts encoding */
473 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
475 // Drop an empty buffer into our output to ensure that things
476 // get flushed all the way out.
477 hb_log( "sync: reached pts %"PRId64", exiting early", start );
478 hb_buffer_close( &sync->cur );
479 hb_buffer_close( &next );
480 *buf_out = hb_buffer_init( 0 );
483 * Push through any subtitle EOFs in case they were not synced through.
485 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
487 subtitle = hb_list_item( job->list_subtitle, i );
488 if( subtitle->config.dest == PASSTHRUSUB )
490 if( subtitle->source == VOBSUB )
491 hb_fifo_push( subtitle->fifo_sync, hb_buffer_init( 0 ) );
493 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
499 if( sync->first_frame )
501 /* This is our first frame */
505 * The first pts from a dvd should always be zero but
506 * can be non-zero with a transport or program stream since
507 * we're not guaranteed to start on an IDR frame. If we get
508 * a non-zero initial PTS extend its duration so it behaves
509 * as if it started at zero so that our audio timing will
512 hb_log( "sync: first pts is %"PRId64, start );
515 sync->first_frame = 0;
519 * since the first frame is always 0 and the upstream reader code
520 * is taking care of adjusting for pts discontinuities, we just have
521 * to deal with the next frame's start being in the past. This can
522 * happen when the PTS is adjusted after data loss but video frame
523 * reordering causes some frames with the old clock to appear after
524 * the clock change. This creates frames that overlap in time which
525 * looks to us like time going backward. The downstream muxing code
526 * can deal with overlaps of up to a frame time but anything larger
527 * we handle by dropping frames here.
529 if ( next_start - start <= 0 )
531 if ( sync->first_drop == 0 )
533 sync->first_drop = next_start;
536 if ( next->new_chap )
538 // don't drop a chapter mark when we drop the buffer
539 sync->chap_mark = next->new_chap;
541 hb_buffer_close( &next );
544 if ( sync->first_drop )
546 hb_log( "sync: video time didn't advance - dropped %d frames "
547 "(delta %d ms, current %"PRId64", next %"PRId64", dur %d)",
548 sync->drop_count, (int)( start - sync->first_drop ) / 90,
549 start, next_start, (int)( next_start - start ) );
550 sync->first_drop = 0;
551 sync->drop_count = 0;
555 * Track the video sequence number locally so that we can sync the audio
556 * to it using the sequence number as well as the PTS.
558 sync->video_sequence = cur->sequence;
560 /* Process subtitles that apply to this video frame */
562 // NOTE: There is no logic in either subtitle-sync algorithm that waits for the
563 // subtitle-decoder if it is lagging behind the video-decoder.
565 // Therefore there is the implicit assumption that the subtitle-decoder
566 // is always faster than the video-decoder. This assumption is definitely
567 // incorrect in some cases where the SSA subtitle decoder is used.
568 // Enable the SUBSYNC_VERBOSE_TIMING flag below to debug.
570 #define SUBSYNC_ALGORITHM_SIMULTANEOUS 1
571 #define SUBSYNC_ALGORITHM_CLASSIC 0
574 * Enables logging of three kinds of events:
575 * SUB***: Subtitle received by sync object
576 * SUB+++: Subtitle now shown
577 * SUB---: Subtitle now hidden and disposed
579 * Lead times on SUB*** events should be positive.
580 * Negative lead times lead to lag times on SUB+++ or the complete drop of a subtitle.
581 * Lag times on SUB+++ and SUB--- should be small positive values in the 0-40ms range.
583 #define SUBSYNC_VERBOSE_TIMING 0
585 #if SUBSYNC_ALGORITHM_SIMULTANEOUS
586 #define sub_list sync->sub_list
588 * 1. Find all subtitles that need to be burned into the current video frame
589 * and attach them to the frame.
590 * 2. Find all subtitles that need to be passed thru and do so immediately.
592 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
594 subtitle = hb_list_item( job->list_subtitle, i );
596 // If this subtitle track's packets are to be passed thru, do so immediately
597 if( subtitle->config.dest == PASSTHRUSUB )
599 while ( ( sub = hb_fifo_get( subtitle->fifo_raw ) ) != NULL )
601 if ( subtitle->source == VOBSUB )
603 hb_fifo_push( subtitle->fifo_sync, sub );
607 hb_fifo_push( subtitle->fifo_out, sub );
611 // If this subtitle track's packets are to be rendered, identify the
612 // packets that need to be rendered on the current video frame
613 else if( subtitle->config.dest == RENDERSUB )
615 // Migrate subtitles from 'subtitle->fifo_raw' to 'sub_list' immediately.
616 // Note that the size of 'sub_list' is unbounded.
617 while ( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) != NULL )
619 sub = hb_fifo_get( subtitle->fifo_raw ); // pop
621 #if SUBSYNC_VERBOSE_TIMING
622 printf( "\nSUB*** (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lead by %"PRId64"ms)\n",
623 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
624 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
625 (sub->start - cur->start)/90);
626 if (pv->common->video_pts_slip)
628 printf( " VIDEO-LAG: %"PRId64"\n", pv->common->video_pts_slip );
632 // Prepend to sub_list
633 hb_buffer_t *sub_list_next = sub_list;
635 sub_list->next = sub_list_next;
638 hb_buffer_t *last_sub = NULL;
639 for ( sub = sub_list; sub != NULL; )
641 // NOTE: Strictly speaking this sequence check is probably unnecessary.
642 // It is a holdover behavior inherited from the classic subsync algorithm.
643 if ( sub->sequence > cur->sequence )
645 // Subtitle sequence in the future
647 // (Keep the subtitle in the stream)
653 if ( cur->start < sub->start )
655 // Subtitle starts in the future
657 // (Keep the subtitle in the stream)
664 // Subtitle starts in the past...
666 if ( cur->start < sub->stop )
668 // Subtitle starts in the past and finishes in the future
670 // Attach a copy of the subtitle packet to the current video packet
671 // to be burned in by the 'render' work-object.
672 // (Can't just alias it because we don't know when the 'render'
673 // work-object will dispose of it.)
674 hb_buffer_t * old_sublist_head = cur->sub;
675 cur->sub = copy_subtitle( sub );
676 cur->sub->next = old_sublist_head;
678 #if SUBSYNC_VERBOSE_TIMING
679 if (!(sub->new_chap & 0x01))
681 printf( "\nSUB+++ (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lag by %"PRId64"ms)\n",
682 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
683 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
684 (cur->start - sub->start)/90 );
685 if (pv->common->video_pts_slip)
687 printf( " VIDEO-LAG: %"PRId64"\n", pv->common->video_pts_slip );
690 sub->new_chap |= 0x01;
694 // (Keep the subtitle in the stream)
701 // Subtitle starts in the past and has already finished
703 #if SUBSYNC_VERBOSE_TIMING
704 printf( "\nSUB--- (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lag by %"PRId64"ms)\n",
705 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
706 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
707 (cur->start - sub->stop)/90 );
708 if (pv->common->video_pts_slip)
710 printf( " VIDEO-LAG: %"PRId64"\n", pv->common->video_pts_slip );
714 // Remove it from the stream...
715 if (last_sub != NULL)
717 last_sub->next = sub->next;
721 sub_list = sub->next;
725 hb_buffer_t *next_sub = sub->next;
726 // XXX: Prevent hb_buffer_close from killing the whole list
727 // before we finish iterating over it
730 hb_buffer_t * subpicture_list = sub;
731 hb_buffer_t * subpicture;
732 hb_buffer_t * subpicture_next;
733 for ( subpicture = subpicture_list; subpicture; subpicture = subpicture_next )
735 subpicture_next = subpicture->next_subpicture;
737 hb_buffer_close( &subpicture );
740 // (last_sub remains the same)
750 #elif SUBSYNC_ALGORITHM_CLASSIC
751 // NOTE: This algorithm does not correctly support the simultaneous display of temporally overlapping subtitles.
754 * Look for a subtitle for this frame.
756 * If found then it will be tagged onto a video buffer of the correct time and
757 * sent in to the render pipeline. This only needs to be done for VOBSUBs which
758 * get rendered, other types of subtitles can just sit in their raw_queue until
759 * delt with at muxing.
761 for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
763 int64_t sub_start, sub_stop, duration;
764 subtitle = hb_list_item( job->list_subtitle, i );
767 * Rewrite timestamps on subtitles that need it (on raw queue).
769 // NOTE: It's probably fine to use this logic for passthru VOBSUBs as well,
770 // but I am currently preserving backwards compatibility with the old
771 // VOBSUB behavior, which uses the more complex logic following this if-statement.
772 if( subtitle->config.dest == PASSTHRUSUB && subtitle->source != VOBSUB )
775 * Rewrite timestamps on subtitles that came from Closed Captions
776 * since they are using the MPEG2 timestamps.
778 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
780 hb_lock( pv->common->mutex );
781 sub_start = sub->start - pv->common->video_pts_slip;
782 hb_unlock( pv->common->mutex );
783 duration = sub->stop - sub->start;
784 sub_stop = sub_start + duration;
787 * Rewrite the timestamps as and when the video
788 * (cur->start) reaches the same timestamp as a
789 * closed caption (sub->start).
791 * What about discontinuity boundaries - not delt
794 * Bypass the sync fifo altogether.
798 sub = hb_fifo_get( subtitle->fifo_raw );
799 hb_fifo_push( subtitle->fifo_out, sub );
804 * Sync the subtitles to the incoming video, and use
805 * the matching converted video timestamp.
807 * Note that it doesn't appear that we need to convert
808 * timestamps, I guess that they were already correct,
809 * so just push them through for rendering.
812 if( sub_start <= start )
814 sub = hb_fifo_get( subtitle->fifo_raw );
815 sub->start = sub_start;
816 sub->stop = sub_stop;
817 hb_fifo_push( subtitle->fifo_out, sub );
819 // sub too early. Leave it in the fifo.
829 // For rendered subtitles (and, for backward compatibility, passthru VOBSUBs),
830 // delay pushing subtitle packets through the pipeline until the video catches up
831 if( subtitle->config.dest == RENDERSUB || subtitle->source == VOBSUB )
834 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
839 * EOF, pass it through immediately.
844 hb_lock( pv->common->mutex );
845 sub_start = sub->start - pv->common->video_pts_slip;
846 hb_unlock( pv->common->mutex );
847 duration = sub->stop - sub->start;
848 sub_stop = sub_start + duration;
850 /* If two DVD subtitles overlap, make the first one stop
851 when the second one starts */
852 // TODO: Consider removing this entirely. Currently retained
853 // to preserve old DVD subtitle behavior.
854 if ( subtitle->source == VOBSUB )
856 sub2 = hb_fifo_see2( subtitle->fifo_raw );
857 if( sub2 && sub->stop > sub2->start )
859 sub->stop = sub2->start;
864 // hb_log("0x%x: video seq: %"PRId64" subtitle sequence: %"PRId64,
865 // sub, cur->sequence, sub->sequence);
867 if( sub->sequence > cur->sequence )
870 * The video is behind where we are, so wait until
871 * it catches up to the same reader point on the
872 * DVD. Then our PTS should be in the same region
879 #if SUBSYNC_VERBOSE_TIMING
880 if (!(sub->new_chap & 0x02))
882 printf( "\nSUB*** (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lead by %"PRId64"ms)\n",
883 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
884 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
885 (sub->start - cur->start)/90);
887 sub->new_chap |= 0x02;
891 if( sub_stop > start )
893 // CONDITION: cur->start < sub->stop
896 * The stop time is in the future, so fall through
897 * and we'll deal with it in the next block of
902 * There is a valid subtitle, is it time to display it?
904 if( sub_stop > sub_start)
906 // CONDITION: {cur->start, sub->start} < sub->stop
909 * Normal subtitle which ends after it starts,
910 * check to see that the current video is between
913 if( start > sub_start &&
916 // CONDITION: sub->start < cur->start < sub->stop
919 * We should be playing this, so leave the
922 * fall through to display
927 // CONDITION: cur->start < sub->start < sub->stop
930 * Defer until the play point is within
938 // CONDITION: cur->start < sub->stop < sub->start
941 * The end of the subtitle is less than the start,
942 * this is a sign of a PTS discontinuity.
944 if( sub_start > start )
946 // CONDITION: cur->start < sub->stop < sub->start
949 * we haven't reached the start time yet, or
950 * we have jumped backwards after having
951 * already started this subtitle.
953 if( start < sub_stop )
955 // CONDITION: cur->start < sub->stop < sub->start
958 * We have jumped backwards and so should
959 * continue displaying this subtitle.
961 * fall through to display.
966 // CONDITION: Mathematically impossible to get here
969 * Defer until the play point is
970 * within the subtitle
975 // CONDITION: Mathematically impossible to get here
978 * Play this subtitle as the start is
979 * greater than our video point.
981 * fall through to display/
989 // CONDITION: sub->stop < cur->start
991 #if SUBSYNC_VERBOSE_TIMING
992 printf( "\nSUB--- (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lag by %"PRId64"ms)\n",
993 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
994 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
995 (cur->start - sub->stop)/90 );
999 * The subtitle is older than this picture, trash it
1001 sub = hb_fifo_get( subtitle->fifo_raw );
1002 hb_buffer_close( &sub );
1006 /* If we have a subtitle for this picture, copy it */
1009 #if SUBSYNC_VERBOSE_TIMING
1010 if (!(sub->new_chap & 0x01))
1012 printf( "\nSUB+++ (%"PRId64"/%"PRId64":%"PRId64") @ %"PRId64"/%"PRId64":%"PRId64" (lag by %"PRId64"ms)\n",
1013 sub->start/90, sub->start/90/1000/60, sub->start/90/1000%60,
1014 cur->start/90, cur->start/90/1000/60, cur->start/90/1000%60,
1015 (cur->start - sub->start)/90 );
1017 sub->new_chap |= 0x01;
1023 if( subtitle->config.dest == RENDERSUB )
1026 * Tack onto the video buffer for rendering.
1028 * Note that there may be multiple subtitles
1029 * whose time intervals overlap which must display
1030 * on the same frame.
1032 hb_buffer_t * old_sublist_head = cur->sub;
1034 /* FIXME: we should avoid this memcpy */
1035 cur->sub = copy_subtitle( sub );
1036 cur->sub->next = old_sublist_head;
1037 cur->sub->start = sub_start;
1038 cur->sub->stop = sub_stop;
1040 // Leave the subtitle on the raw queue
1041 // (until it no longer needs to be displayed)
1044 * Pass-Through, pop it off of the raw queue,
1046 sub = hb_fifo_get( subtitle->fifo_raw );
1047 sub->start = sub_start;
1048 sub->stop = sub_stop;
1049 hb_fifo_push( subtitle->fifo_sync, sub );
1053 * EOF - consume for rendered, else pass through
1055 if( subtitle->config.dest == RENDERSUB )
1057 sub = hb_fifo_get( subtitle->fifo_raw );
1058 hb_buffer_close( &sub );
1060 sub = hb_fifo_get( subtitle->fifo_raw );
1061 sub->start = sub_start;
1062 sub->stop = sub_stop;
1063 hb_fifo_push( subtitle->fifo_sync, sub );
1070 #error "Must select a subtitle sync algorithm."
1074 * Adjust the pts of the current frame so that it's contiguous
1075 * with the previous frame. The start time of the current frame
1076 * has to be the end time of the previous frame and the stop
1077 * time has to be the start of the next frame. We don't
1078 * make any adjustments to the source timestamps other than removing
1079 * the clock offsets (which also removes pts discontinuities).
1080 * This means we automatically encode at the source's frame rate.
1081 * MP2 uses an implicit duration (frames end when the next frame
1082 * starts) but more advanced containers like MP4 use an explicit
1083 * duration. Since we're looking ahead one frame we set the
1084 * explicit stop time from the start time of the next frame.
1087 sync->cur = cur = next;
1089 int64_t duration = next_start - start;
1091 if ( duration <= 0 )
1093 hb_log( "sync: invalid video duration %"PRId64", start %"PRId64", next %"PRId64"",
1094 duration, start, next_start );
1097 (*buf_out)->start = sync->next_start;
1098 sync->next_start += duration;
1099 (*buf_out)->stop = sync->next_start;
1101 if ( sync->chap_mark )
1103 // we have a pending chapter mark from a recent drop - put it on this
1104 // buffer (this may make it one frame late but we can't do any better).
1105 (*buf_out)->new_chap = sync->chap_mark;
1106 sync->chap_mark = 0;
1115 static hb_buffer_t * copy_subtitle( hb_buffer_t * src_list )
1117 hb_buffer_t * dst_list = NULL;
1121 hb_buffer_t ** dst_ptr = &dst_list;
1122 for ( src = src_list, dst_ptr = &dst_list;
1124 src = src->next_subpicture, dst_ptr = &dst->next_subpicture )
1126 (*dst_ptr) = hb_buffer_init( src->size );
1130 dst->width = src->width;
1131 dst->height = src->height;
1132 memcpy( dst->data, src->data, src->size );
1138 // sync*Init does nothing because sync has a special initializer
1139 // that takes care of initializing video and all audio tracks
1140 int syncVideoInit( hb_work_object_t * w, hb_job_t * job)
1145 hb_work_object_t hb_sync_video =
1148 "Video Synchronization",
1154 /***********************************************************************
1156 ***********************************************************************
1158 **********************************************************************/
1159 void syncAudioClose( hb_work_object_t * w )
1161 hb_work_private_t * pv = w->private_data;
1162 hb_sync_audio_t * sync = &pv->type.audio;
1164 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1166 free( sync->ac3_buf );
1170 src_delete( sync->state );
1173 hb_lock( pv->common->mutex );
1174 if ( --pv->common->ref == 0 )
1176 hb_unlock( pv->common->mutex );
1177 hb_lock_close( &pv->common->mutex );
1182 hb_unlock( pv->common->mutex );
1186 w->private_data = NULL;
1189 int syncAudioInit( hb_work_object_t * w, hb_job_t * job)
1194 /***********************************************************************
1196 ***********************************************************************
1198 **********************************************************************/
1199 static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
1200 hb_buffer_t ** buf_out )
1202 hb_work_private_t * pv = w->private_data;
1203 hb_job_t * job = pv->job;
1204 hb_sync_audio_t * sync = &pv->type.audio;
1211 /* if the next buffer is an eof send it downstream */
1212 if ( buf->size <= 0 )
1214 hb_buffer_close( &buf );
1215 *buf_out = hb_buffer_init( 0 );
1216 pv->common->first_pts[sync->index+1] = INT64_MAX - 1;
1217 return HB_WORK_DONE;
1220 /* Wait till we can determine the initial pts of all streams */
1221 if( pv->common->pts_offset == INT64_MIN )
1223 pv->common->first_pts[sync->index+1] = buf->start;
1224 hb_lock( pv->common->mutex );
1225 while( pv->common->pts_offset == INT64_MIN )
1227 // Full fifos will make us wait forever, so get the
1228 // pts offset from the available streams if full
1229 if (hb_fifo_is_full(w->fifo_in))
1232 hb_cond_broadcast( pv->common->next_frame );
1234 else if ( checkPtsOffset( w ) )
1235 hb_cond_broadcast( pv->common->next_frame );
1237 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
1239 hb_unlock( pv->common->mutex );
1242 /* Wait for start frame if doing point-to-point */
1243 hb_lock( pv->common->mutex );
1244 start = buf->start - pv->common->audio_pts_slip;
1245 while ( !pv->common->start_found )
1247 if ( pv->common->audio_pts_thresh < 0 )
1249 // I would initialize this in hb_sync_init, but
1250 // job->pts_to_start can be modified by reader
1251 // after hb_sync_init is called.
1252 pv->common->audio_pts_thresh = job->pts_to_start;
1254 if ( buf->start < pv->common->audio_pts_thresh )
1256 hb_buffer_close( &buf );
1257 hb_unlock( pv->common->mutex );
1260 while ( !pv->common->start_found &&
1261 buf->start >= pv->common->audio_pts_thresh )
1263 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
1265 start = buf->start - pv->common->audio_pts_slip;
1269 hb_buffer_close( &buf );
1270 hb_unlock( pv->common->mutex );
1273 hb_unlock( pv->common->mutex );
1275 if( job->frame_to_stop && pv->common->count_frames >= job->frame_to_stop )
1277 hb_buffer_close( &buf );
1278 *buf_out = hb_buffer_init( 0 );
1279 return HB_WORK_DONE;
1282 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
1284 hb_buffer_close( &buf );
1285 *buf_out = hb_buffer_init( 0 );
1286 return HB_WORK_DONE;
1289 if ( start - sync->next_start < 0 )
1291 // audio time went backwards.
1292 // If our output clock is more than a half frame ahead of the
1293 // input clock drop this frame to move closer to sync.
1294 // Otherwise drop frames until the input clock matches the output clock.
1295 if ( sync->first_drop || sync->next_start - start > 90*15 )
1297 // Discard data that's in the past.
1298 if ( sync->first_drop == 0 )
1300 sync->first_drop = sync->next_start;
1303 hb_buffer_close( &buf );
1307 if ( sync->first_drop )
1309 // we were dropping old data but input buf time is now current
1310 hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
1311 "(next %"PRId64", current %"PRId64")", w->audio->id,
1312 (int)( sync->next_start - sync->first_drop ) / 90,
1313 sync->drop_count, sync->first_drop, (int64_t)sync->next_start );
1314 sync->first_drop = 0;
1315 sync->drop_count = 0;
1317 if ( start - sync->next_start >= (90 * 70) )
1319 if ( start - sync->next_start > (90000LL * 60) )
1321 // there's a gap of more than a minute between the last
1322 // frame and this. assume we got a corrupted timestamp
1323 // and just drop the next buf.
1324 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
1325 " start %"PRId64", next %"PRId64,
1326 (int)((start - sync->next_start) / (90000*60)),
1327 w->audio->id, start, (int64_t)sync->next_start );
1328 hb_buffer_close( &buf );
1332 * there's a gap of at least 70ms between the last
1333 * frame we processed & the next. Fill it with silence.
1334 * Or in the case of DCA, skip some frames from the
1337 if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1339 hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d"
1340 " start %"PRId64", next %"PRId64,
1341 (int)((start - sync->next_start) / 90),
1342 w->audio->id, start, (int64_t)sync->next_start );
1343 hb_lock( pv->common->mutex );
1344 pv->common->audio_pts_slip += (start - sync->next_start);
1345 pv->common->video_pts_slip += (start - sync->next_start);
1346 hb_unlock( pv->common->mutex );
1350 hb_log( "sync: adding %d ms of silence to audio %d"
1351 " start %"PRId64", next %"PRId64,
1352 (int)((start - sync->next_start) / 90),
1353 w->audio->id, start, (int64_t)sync->next_start );
1354 InsertSilence( w, start - sync->next_start );
1358 * When we get here we've taken care of all the dups and gaps in the
1359 * audio stream and are ready to inject the next input frame into
1360 * the output stream.
1362 *buf_out = OutputAudioFrame( w->audio, buf, sync );
1366 hb_work_object_t hb_sync_audio =
1369 "AudioSynchronization",
1375 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
1377 hb_work_object_t * w;
1378 hb_work_private_t * pv;
1379 hb_title_t * title = job->title;
1380 hb_sync_audio_t * sync;
1382 pv = calloc( 1, sizeof( hb_work_private_t ) );
1383 sync = &pv->type.audio;
1386 pv->common = common;
1388 pv->common->pts_count++;
1390 w = hb_get_work( WORK_SYNC_AUDIO );
1391 w->private_data = pv;
1392 w->audio = hb_list_item( title->list_audio, i );
1393 w->fifo_in = w->audio->priv.fifo_raw;
1395 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1396 w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1398 w->fifo_out = w->audio->priv.fifo_out;
1402 w->fifo_out = w->audio->priv.fifo_sync;
1405 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1407 /* Have a silent AC-3 frame ready in case we have to fill a
1413 codec = avcodec_find_encoder( CODEC_ID_AC3 );
1414 c = avcodec_alloc_context();
1416 c->bit_rate = w->audio->config.in.bitrate;
1417 c->sample_rate = w->audio->config.in.samplerate;
1418 c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( w->audio->config.in.channel_layout );
1419 c->sample_fmt = AV_SAMPLE_FMT_FLT;
1421 if( hb_avcodec_open( c, codec ) < 0 )
1423 hb_log( "sync: avcodec_open failed" );
1427 zeros = calloc( AC3_SAMPLES_PER_FRAME *
1428 sizeof( float ) * c->channels, 1 );
1429 sync->ac3_size = w->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
1430 w->audio->config.in.samplerate / 8;
1431 sync->ac3_buf = malloc( sync->ac3_size );
1433 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
1434 zeros ) != sync->ac3_size )
1436 hb_log( "sync: avcodec_encode_audio failed" );
1440 hb_avcodec_close( c );
1445 /* Initialize libsamplerate */
1447 sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
1448 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1449 w->audio->config.out.mixdown), &error );
1450 sync->data.end_of_input = 0;
1452 hb_list_add( job->list_work, w );
1455 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
1456 hb_sync_audio_t *sync )
1458 int64_t start = (int64_t)sync->next_start;
1459 double duration = buf->stop - buf->start;
1461 if( audio->config.in.samplerate == audio->config.out.samplerate ||
1462 audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1463 audio->config.out.codec == HB_ACODEC_DCA_PASS )
1466 * If we don't have to do sample rate conversion or this audio is
1467 * pass-thru just send the input buffer downstream after adjusting
1468 * its timestamps to make the output stream continuous.
1473 /* Not pass-thru - do sample rate conversion */
1474 int count_in, count_out;
1475 hb_buffer_t * buf_raw = buf;
1476 int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
1479 count_in = buf_raw->size / channel_count;
1481 * When using stupid rates like 44.1 there will always be some
1482 * truncation error. E.g., a 1536 sample AC3 frame will turn into a
1483 * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
1484 * the error will build up over time and eventually the audio will
1485 * substantially lag the video. libsamplerate will keep track of the
1486 * fractional sample & give it to us when appropriate if we give it
1487 * an extra sample of space in the output buffer.
1489 count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
1491 sync->data.input_frames = count_in;
1492 sync->data.output_frames = count_out;
1493 sync->data.src_ratio = (double)audio->config.out.samplerate /
1494 (double)audio->config.in.samplerate;
1496 buf = hb_buffer_init( count_out * channel_count );
1497 sync->data.data_in = (float *) buf_raw->data;
1498 sync->data.data_out = (float *) buf->data;
1499 if( src_process( sync->state, &sync->data ) )
1501 /* XXX If this happens, we're screwed */
1502 hb_log( "sync: audio %d src_process failed", audio->id );
1504 hb_buffer_close( &buf_raw );
1506 buf->size = sync->data.output_frames_gen * channel_count;
1507 duration = (double)( sync->data.output_frames_gen * 90000 ) /
1508 audio->config.out.samplerate;
1510 buf->frametype = HB_FRAME_AUDIO;
1512 sync->next_start += duration;
1513 buf->stop = (int64_t)sync->next_start;
1517 static void InsertSilence( hb_work_object_t * w, int64_t duration )
1519 hb_work_private_t * pv = w->private_data;
1520 hb_sync_audio_t *sync = &pv->type.audio;
1524 // to keep pass-thru and regular audio in sync we generate silence in
1525 // AC3 frame-sized units. If the silence duration isn't an integer multiple
1526 // of the AC3 frame duration we will truncate or round up depending on
1527 // which minimizes the timing error.
1528 const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
1529 w->audio->config.in.samplerate;
1530 int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
1532 while ( --frame_count >= 0 )
1534 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1536 buf = hb_buffer_init( sync->ac3_size );
1537 buf->start = sync->next_start;
1538 buf->stop = buf->start + frame_dur;
1539 memcpy( buf->data, sync->ac3_buf, buf->size );
1540 fifo = w->audio->priv.fifo_out;
1544 buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
1545 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1546 w->audio->config.out.mixdown) );
1547 buf->start = sync->next_start;
1548 buf->stop = buf->start + frame_dur;
1549 memset( buf->data, 0, buf->size );
1550 fifo = w->audio->priv.fifo_sync;
1552 buf = OutputAudioFrame( w->audio, buf, sync );
1553 hb_fifo_push( fifo, buf );
1557 static void UpdateState( hb_work_object_t * w )
1559 hb_work_private_t * pv = w->private_data;
1560 hb_sync_video_t * sync = &pv->type.video;
1563 if( !pv->common->count_frames )
1565 sync->st_first = hb_get_date();
1566 pv->job->st_pause_date = -1;
1567 pv->job->st_paused = 0;
1569 pv->common->count_frames++;
1571 if( hb_get_date() > sync->st_dates[3] + 1000 )
1573 memmove( &sync->st_dates[0], &sync->st_dates[1],
1574 3 * sizeof( uint64_t ) );
1575 memmove( &sync->st_counts[0], &sync->st_counts[1],
1576 3 * sizeof( uint64_t ) );
1577 sync->st_dates[3] = hb_get_date();
1578 sync->st_counts[3] = pv->common->count_frames;
1581 #define p state.param.working
1582 state.state = HB_STATE_WORKING;
1583 p.progress = (float) pv->common->count_frames / (float) sync->count_frames_max;
1584 if( p.progress > 1.0 )
1588 p.rate_cur = 1000.0 *
1589 (float) ( sync->st_counts[3] - sync->st_counts[0] ) /
1590 (float) ( sync->st_dates[3] - sync->st_dates[0] );
1591 if( hb_get_date() > sync->st_first + 4000 )
1594 p.rate_avg = 1000.0 * (float) sync->st_counts[3] /
1595 (float) ( sync->st_dates[3] - sync->st_first - pv->job->st_paused);
1596 eta = (float) ( sync->count_frames_max - sync->st_counts[3] ) /
1598 p.hours = eta / 3600;
1599 p.minutes = ( eta % 3600 ) / 60;
1600 p.seconds = eta % 60;
1611 hb_set_state( pv->job->h, &state );
1614 static void UpdateSearchState( hb_work_object_t * w, int64_t start )
1616 hb_work_private_t * pv = w->private_data;
1617 hb_sync_video_t * sync = &pv->type.video;
1622 now = hb_get_date();
1623 if( !pv->common->count_frames )
1625 sync->st_first = now;
1626 pv->job->st_pause_date = -1;
1627 pv->job->st_paused = 0;
1629 pv->common->count_frames++;
1631 #define p state.param.working
1632 state.state = HB_STATE_SEARCHING;
1633 if ( pv->job->frame_to_start )
1634 p.progress = (float) pv->common->count_frames /
1635 (float) pv->job->frame_to_start;
1636 else if ( pv->job->pts_to_start )
1637 p.progress = (float) start / (float) pv->job->pts_to_start;
1640 if( p.progress > 1.0 )
1644 if (now > sync->st_first)
1648 if ( pv->job->frame_to_start )
1650 avg = 1000.0 * (double)pv->common->count_frames / (now - sync->st_first);
1651 eta = ( pv->job->frame_to_start - pv->common->count_frames ) / avg;
1653 else if ( pv->job->pts_to_start )
1655 avg = 1000.0 * (double)start / (now - sync->st_first);
1656 eta = ( pv->job->pts_to_start - start ) / avg;
1658 p.hours = eta / 3600;
1659 p.minutes = ( eta % 3600 ) / 60;
1660 p.seconds = eta % 60;
1671 hb_set_state( pv->job->h, &state );
1674 static void getPtsOffset( hb_work_object_t * w )
1676 hb_work_private_t * pv = w->private_data;
1678 int64_t first_pts = INT64_MAX;
1680 for( i = 0; i < pv->common->pts_count; i++ )
1682 if ( pv->common->first_pts[i] < first_pts )
1683 first_pts = pv->common->first_pts[i];
1685 pv->common->video_pts_slip = pv->common->audio_pts_slip = pv->common->pts_offset = first_pts;
1689 static int checkPtsOffset( hb_work_object_t * w )
1691 hb_work_private_t * pv = w->private_data;
1694 for( i = 0; i < pv->common->pts_count; i++ )
1696 if ( pv->common->first_pts[i] == INT64_MAX )