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 );
620 // sub too early. Leave it in the fifo.
630 // For rendered subtitles (and, for backward compatibility, passthru VOBSUBs),
631 // delay pushing subtitle packets through the pipeline until the video catches up
632 if( subtitle->config.dest == RENDERSUB || subtitle->source == VOBSUB )
635 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
640 * EOF, pass it through immediately.
645 hb_lock( pv->common->mutex );
646 sub_start = sub->start - pv->common->video_pts_slip;
647 hb_unlock( pv->common->mutex );
648 duration = sub->stop - sub->start;
649 sub_stop = sub_start + duration;
651 /* If two subtitles overlap, make the first one stop
652 when the second one starts */
653 sub2 = hb_fifo_see2( subtitle->fifo_raw );
654 if( sub2 && sub->stop > sub2->start )
656 sub->stop = sub2->start;
659 // hb_log("0x%x: video seq: %"PRId64" subtitle sequence: %"PRId64,
660 // sub, cur->sequence, sub->sequence);
662 if( sub->sequence > cur->sequence )
665 * The video is behind where we are, so wait until
666 * it catches up to the same reader point on the
667 * DVD. Then our PTS should be in the same region
674 if( sub_stop > start )
677 * The stop time is in the future, so fall through
678 * and we'll deal with it in the next block of
683 * There is a valid subtitle, is it time to display it?
685 if( sub_stop > sub_start)
688 * Normal subtitle which ends after it starts,
689 * check to see that the current video is between
692 if( start > sub_start &&
696 * We should be playing this, so leave the
699 * fall through to display
705 * Defer until the play point is within
714 * The end of the subtitle is less than the start,
715 * this is a sign of a PTS discontinuity.
717 if( sub_start > start )
720 * we haven't reached the start time yet, or
721 * we have jumped backwards after having
722 * already started this subtitle.
724 if( start < sub_stop )
727 * We have jumped backwards and so should
728 * continue displaying this subtitle.
730 * fall through to display.
736 * Defer until the play point is
737 * within the subtitle
743 * Play this subtitle as the start is
744 * greater than our video point.
746 * fall through to display/
756 * The subtitle is older than this picture, trash it
758 sub = hb_fifo_get( subtitle->fifo_raw );
759 hb_buffer_close( &sub );
763 /* If we have a subtitle for this picture, copy it */
768 if( subtitle->config.dest == RENDERSUB )
770 // Only allow one subtitle to be showing at once; ignore others
771 if ( cur->sub == NULL )
774 * Tack onto the video buffer for rendering
776 /* FIXME: we should avoid this memcpy */
777 cur->sub = copy_subtitle( sub );
778 cur->sub->start = sub_start;
779 cur->sub->stop = sub_stop;
781 // Leave the subtitle on the raw queue
782 // (until it no longer needs to be displayed)
786 * Pass-Through, pop it off of the raw queue,
788 sub = hb_fifo_get( subtitle->fifo_raw );
789 sub->start = sub_start;
790 sub->stop = sub_stop;
791 hb_fifo_push( subtitle->fifo_sync, sub );
795 * EOF - consume for rendered, else pass through
797 if( subtitle->config.dest == RENDERSUB )
799 sub = hb_fifo_get( subtitle->fifo_raw );
800 hb_buffer_close( &sub );
802 sub = hb_fifo_get( subtitle->fifo_raw );
803 sub->start = sub_start;
804 sub->stop = sub_stop;
805 hb_fifo_push( subtitle->fifo_sync, sub );
813 * Adjust the pts of the current frame so that it's contiguous
814 * with the previous frame. The start time of the current frame
815 * has to be the end time of the previous frame and the stop
816 * time has to be the start of the next frame. We don't
817 * make any adjustments to the source timestamps other than removing
818 * the clock offsets (which also removes pts discontinuities).
819 * This means we automatically encode at the source's frame rate.
820 * MP2 uses an implicit duration (frames end when the next frame
821 * starts) but more advanced containers like MP4 use an explicit
822 * duration. Since we're looking ahead one frame we set the
823 * explicit stop time from the start time of the next frame.
826 sync->cur = cur = next;
828 int64_t duration = next_start - start;
832 hb_log( "sync: invalid video duration %"PRId64", start %"PRId64", next %"PRId64"",
833 duration, start, next_start );
836 (*buf_out)->start = sync->next_start;
837 sync->next_start += duration;
838 (*buf_out)->stop = sync->next_start;
840 if ( sync->chap_mark )
842 // we have a pending chapter mark from a recent drop - put it on this
843 // buffer (this may make it one frame late but we can't do any better).
844 (*buf_out)->new_chap = sync->chap_mark;
854 static hb_buffer_t * copy_subtitle( hb_buffer_t * src_list )
856 hb_buffer_t * dst_list = NULL;
860 hb_buffer_t ** dst_ptr = &dst_list;
861 for ( src = src_list, dst_ptr = &dst_list;
863 src = src->next_subpicture, dst_ptr = &dst->next_subpicture )
865 (*dst_ptr) = hb_buffer_init( src->size );
869 dst->width = src->width;
870 dst->height = src->height;
871 memcpy( dst->data, src->data, src->size );
877 // sync*Init does nothing because sync has a special initializer
878 // that takes care of initializing video and all audio tracks
879 int syncVideoInit( hb_work_object_t * w, hb_job_t * job)
884 hb_work_object_t hb_sync_video =
887 "Video Synchronization",
893 /***********************************************************************
895 ***********************************************************************
897 **********************************************************************/
898 void syncAudioClose( hb_work_object_t * w )
900 hb_work_private_t * pv = w->private_data;
901 hb_sync_audio_t * sync = &pv->type.audio;
903 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
905 free( sync->ac3_buf );
909 src_delete( sync->state );
912 hb_lock( pv->common->mutex );
913 if ( --pv->common->ref == 0 )
915 hb_unlock( pv->common->mutex );
916 hb_lock_close( &pv->common->mutex );
921 hb_unlock( pv->common->mutex );
925 w->private_data = NULL;
928 int syncAudioInit( hb_work_object_t * w, hb_job_t * job)
933 /***********************************************************************
935 ***********************************************************************
937 **********************************************************************/
938 static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
939 hb_buffer_t ** buf_out )
941 hb_work_private_t * pv = w->private_data;
942 hb_job_t * job = pv->job;
943 hb_sync_audio_t * sync = &pv->type.audio;
950 /* if the next buffer is an eof send it downstream */
951 if ( buf->size <= 0 )
953 hb_buffer_close( &buf );
954 *buf_out = hb_buffer_init( 0 );
958 /* Wait till we can determine the initial pts of all streams */
959 if( pv->common->pts_offset == INT64_MIN )
961 pv->common->first_pts[sync->index+1] = buf->start;
962 hb_lock( pv->common->mutex );
963 while( pv->common->pts_offset == INT64_MIN )
965 // Full fifos will make us wait forever, so get the
966 // pts offset from the available streams if full
967 if (hb_fifo_is_full(w->fifo_in))
970 hb_cond_broadcast( pv->common->next_frame );
972 else if ( checkPtsOffset( w ) )
973 hb_cond_broadcast( pv->common->next_frame );
975 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
977 hb_unlock( pv->common->mutex );
980 /* Wait for start frame if doing point-to-point */
981 hb_lock( pv->common->mutex );
982 start = buf->start - pv->common->audio_pts_slip;
983 while ( !pv->common->start_found )
985 if ( pv->common->audio_pts_thresh < 0 )
987 // I would initialize this in hb_sync_init, but
988 // job->pts_to_start can be modified by reader
989 // after hb_sync_init is called.
990 pv->common->audio_pts_thresh = job->pts_to_start;
992 if ( start < pv->common->audio_pts_thresh )
994 hb_buffer_close( &buf );
995 hb_unlock( pv->common->mutex );
998 while ( !pv->common->start_found &&
999 start >= pv->common->audio_pts_thresh )
1001 hb_cond_timedwait( pv->common->next_frame, pv->common->mutex, 200 );
1003 start = buf->start - pv->common->audio_pts_slip;
1007 hb_buffer_close( &buf );
1008 hb_unlock( pv->common->mutex );
1011 hb_unlock( pv->common->mutex );
1013 if( job->frame_to_stop && pv->common->count_frames >= job->frame_to_stop )
1015 hb_buffer_close( &buf );
1016 *buf_out = hb_buffer_init( 0 );
1017 return HB_WORK_DONE;
1020 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
1022 hb_buffer_close( &buf );
1023 *buf_out = hb_buffer_init( 0 );
1024 return HB_WORK_DONE;
1027 if ( start - sync->next_start < 0 )
1029 // audio time went backwards.
1030 // If our output clock is more than a half frame ahead of the
1031 // input clock drop this frame to move closer to sync.
1032 // Otherwise drop frames until the input clock matches the output clock.
1033 if ( sync->first_drop || sync->next_start - start > 90*15 )
1035 // Discard data that's in the past.
1036 if ( sync->first_drop == 0 )
1038 sync->first_drop = sync->next_start;
1041 hb_buffer_close( &buf );
1045 if ( sync->first_drop )
1047 // we were dropping old data but input buf time is now current
1048 hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
1049 "(next %"PRId64", current %"PRId64")", w->audio->id,
1050 (int)( sync->next_start - sync->first_drop ) / 90,
1051 sync->drop_count, sync->first_drop, (int64_t)sync->next_start );
1052 sync->first_drop = 0;
1053 sync->drop_count = 0;
1055 if ( start - sync->next_start >= (90 * 70) )
1057 if ( start - sync->next_start > (90000LL * 60) )
1059 // there's a gap of more than a minute between the last
1060 // frame and this. assume we got a corrupted timestamp
1061 // and just drop the next buf.
1062 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
1063 " start %"PRId64", next %"PRId64,
1064 (int)((start - sync->next_start) / (90000*60)),
1065 w->audio->id, start, (int64_t)sync->next_start );
1066 hb_buffer_close( &buf );
1070 * there's a gap of at least 70ms between the last
1071 * frame we processed & the next. Fill it with silence.
1072 * Or in the case of DCA, skip some frames from the
1075 if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1077 hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d"
1078 " start %"PRId64", next %"PRId64,
1079 (int)((start - sync->next_start) / 90),
1080 w->audio->id, start, (int64_t)sync->next_start );
1081 hb_lock( pv->common->mutex );
1082 pv->common->audio_pts_slip += (start - sync->next_start);
1083 pv->common->video_pts_slip += (start - sync->next_start);
1084 hb_unlock( pv->common->mutex );
1088 hb_log( "sync: adding %d ms of silence to audio %d"
1089 " start %"PRId64", next %"PRId64,
1090 (int)((start - sync->next_start) / 90),
1091 w->audio->id, start, (int64_t)sync->next_start );
1092 InsertSilence( w, start - sync->next_start );
1096 * When we get here we've taken care of all the dups and gaps in the
1097 * audio stream and are ready to inject the next input frame into
1098 * the output stream.
1100 *buf_out = OutputAudioFrame( w->audio, buf, sync );
1104 hb_work_object_t hb_sync_audio =
1107 "AudioSynchronization",
1113 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
1115 hb_work_object_t * w;
1116 hb_work_private_t * pv;
1117 hb_title_t * title = job->title;
1118 hb_sync_audio_t * sync;
1120 pv = calloc( 1, sizeof( hb_work_private_t ) );
1121 sync = &pv->type.audio;
1124 pv->common = common;
1126 pv->common->pts_count++;
1128 w = hb_get_work( WORK_SYNC_AUDIO );
1129 w->private_data = pv;
1130 w->audio = hb_list_item( title->list_audio, i );
1131 w->fifo_in = w->audio->priv.fifo_raw;
1133 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1134 w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1136 w->fifo_out = w->audio->priv.fifo_out;
1140 w->fifo_out = w->audio->priv.fifo_sync;
1143 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1145 /* Have a silent AC-3 frame ready in case we have to fill a
1151 codec = avcodec_find_encoder( CODEC_ID_AC3 );
1152 c = avcodec_alloc_context();
1154 c->bit_rate = w->audio->config.in.bitrate;
1155 c->sample_rate = w->audio->config.in.samplerate;
1156 c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( w->audio->config.in.channel_layout );
1158 if( hb_avcodec_open( c, codec ) < 0 )
1160 hb_log( "sync: avcodec_open failed" );
1164 zeros = calloc( AC3_SAMPLES_PER_FRAME *
1165 sizeof( short ) * c->channels, 1 );
1166 sync->ac3_size = w->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
1167 w->audio->config.in.samplerate / 8;
1168 sync->ac3_buf = malloc( sync->ac3_size );
1170 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
1171 zeros ) != sync->ac3_size )
1173 hb_log( "sync: avcodec_encode_audio failed" );
1177 hb_avcodec_close( c );
1182 /* Initialize libsamplerate */
1184 sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
1185 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1186 w->audio->config.out.mixdown), &error );
1187 sync->data.end_of_input = 0;
1189 hb_list_add( job->list_work, w );
1192 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
1193 hb_sync_audio_t *sync )
1195 int64_t start = (int64_t)sync->next_start;
1196 double duration = buf->stop - buf->start;
1198 if( audio->config.in.samplerate == audio->config.out.samplerate ||
1199 audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1200 audio->config.out.codec == HB_ACODEC_DCA_PASS )
1203 * If we don't have to do sample rate conversion or this audio is
1204 * pass-thru just send the input buffer downstream after adjusting
1205 * its timestamps to make the output stream continuous.
1210 /* Not pass-thru - do sample rate conversion */
1211 int count_in, count_out;
1212 hb_buffer_t * buf_raw = buf;
1213 int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
1216 count_in = buf_raw->size / channel_count;
1218 * When using stupid rates like 44.1 there will always be some
1219 * truncation error. E.g., a 1536 sample AC3 frame will turn into a
1220 * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
1221 * the error will build up over time and eventually the audio will
1222 * substantially lag the video. libsamplerate will keep track of the
1223 * fractional sample & give it to us when appropriate if we give it
1224 * an extra sample of space in the output buffer.
1226 count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
1228 sync->data.input_frames = count_in;
1229 sync->data.output_frames = count_out;
1230 sync->data.src_ratio = (double)audio->config.out.samplerate /
1231 (double)audio->config.in.samplerate;
1233 buf = hb_buffer_init( count_out * channel_count );
1234 sync->data.data_in = (float *) buf_raw->data;
1235 sync->data.data_out = (float *) buf->data;
1236 if( src_process( sync->state, &sync->data ) )
1238 /* XXX If this happens, we're screwed */
1239 hb_log( "sync: audio %d src_process failed", audio->id );
1241 hb_buffer_close( &buf_raw );
1243 buf->size = sync->data.output_frames_gen * channel_count;
1244 duration = (double)( sync->data.output_frames_gen * 90000 ) /
1245 audio->config.out.samplerate;
1247 buf->frametype = HB_FRAME_AUDIO;
1249 sync->next_start += duration;
1250 buf->stop = (int64_t)sync->next_start;
1254 static void InsertSilence( hb_work_object_t * w, int64_t duration )
1256 hb_work_private_t * pv = w->private_data;
1257 hb_sync_audio_t *sync = &pv->type.audio;
1261 // to keep pass-thru and regular audio in sync we generate silence in
1262 // AC3 frame-sized units. If the silence duration isn't an integer multiple
1263 // of the AC3 frame duration we will truncate or round up depending on
1264 // which minimizes the timing error.
1265 const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
1266 w->audio->config.in.samplerate;
1267 int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
1269 while ( --frame_count >= 0 )
1271 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1273 buf = hb_buffer_init( sync->ac3_size );
1274 buf->start = sync->next_start;
1275 buf->stop = buf->start + frame_dur;
1276 memcpy( buf->data, sync->ac3_buf, buf->size );
1277 fifo = w->audio->priv.fifo_out;
1281 buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
1282 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1283 w->audio->config.out.mixdown) );
1284 buf->start = sync->next_start;
1285 buf->stop = buf->start + frame_dur;
1286 memset( buf->data, 0, buf->size );
1287 fifo = w->audio->priv.fifo_sync;
1289 buf = OutputAudioFrame( w->audio, buf, sync );
1290 hb_fifo_push( fifo, buf );
1294 static void UpdateState( hb_work_object_t * w )
1296 hb_work_private_t * pv = w->private_data;
1297 hb_sync_video_t * sync = &pv->type.video;
1300 if( !pv->common->count_frames )
1302 sync->st_first = hb_get_date();
1303 pv->job->st_pause_date = -1;
1304 pv->job->st_paused = 0;
1306 pv->common->count_frames++;
1308 if( hb_get_date() > sync->st_dates[3] + 1000 )
1310 memmove( &sync->st_dates[0], &sync->st_dates[1],
1311 3 * sizeof( uint64_t ) );
1312 memmove( &sync->st_counts[0], &sync->st_counts[1],
1313 3 * sizeof( uint64_t ) );
1314 sync->st_dates[3] = hb_get_date();
1315 sync->st_counts[3] = pv->common->count_frames;
1318 #define p state.param.working
1319 state.state = HB_STATE_WORKING;
1320 p.progress = (float) pv->common->count_frames / (float) sync->count_frames_max;
1321 if( p.progress > 1.0 )
1325 p.rate_cur = 1000.0 *
1326 (float) ( sync->st_counts[3] - sync->st_counts[0] ) /
1327 (float) ( sync->st_dates[3] - sync->st_dates[0] );
1328 if( hb_get_date() > sync->st_first + 4000 )
1331 p.rate_avg = 1000.0 * (float) sync->st_counts[3] /
1332 (float) ( sync->st_dates[3] - sync->st_first - pv->job->st_paused);
1333 eta = (float) ( sync->count_frames_max - sync->st_counts[3] ) /
1335 p.hours = eta / 3600;
1336 p.minutes = ( eta % 3600 ) / 60;
1337 p.seconds = eta % 60;
1348 hb_set_state( pv->job->h, &state );
1351 static void UpdateSearchState( hb_work_object_t * w, int64_t start )
1353 hb_work_private_t * pv = w->private_data;
1354 hb_sync_video_t * sync = &pv->type.video;
1359 now = hb_get_date();
1360 if( !pv->common->count_frames )
1362 sync->st_first = now;
1363 pv->job->st_pause_date = -1;
1364 pv->job->st_paused = 0;
1366 pv->common->count_frames++;
1368 #define p state.param.working
1369 state.state = HB_STATE_SEARCHING;
1370 if ( pv->job->frame_to_start )
1371 p.progress = (float) pv->common->count_frames /
1372 (float) pv->job->frame_to_start;
1373 else if ( pv->job->pts_to_start )
1374 p.progress = (float) start / (float) pv->job->pts_to_start;
1377 if( p.progress > 1.0 )
1381 if (now > sync->st_first)
1385 if ( pv->job->frame_to_start )
1387 avg = 1000.0 * (double)pv->common->count_frames / (now - sync->st_first);
1388 eta = ( pv->job->frame_to_start - pv->common->count_frames ) / avg;
1390 else if ( pv->job->pts_to_start )
1392 avg = 1000.0 * (double)start / (now - sync->st_first);
1393 eta = ( pv->job->pts_to_start - start ) / avg;
1395 p.hours = eta / 3600;
1396 p.minutes = ( eta % 3600 ) / 60;
1397 p.seconds = eta % 60;
1408 hb_set_state( pv->job->h, &state );
1411 static void getPtsOffset( hb_work_object_t * w )
1413 hb_work_private_t * pv = w->private_data;
1415 int64_t first_pts = INT64_MAX;
1417 for( i = 0; i < pv->common->pts_count; i++ )
1419 if ( pv->common->first_pts[i] < first_pts )
1420 first_pts = pv->common->first_pts[i];
1422 pv->common->video_pts_slip = pv->common->audio_pts_slip = pv->common->pts_offset = first_pts;
1426 static int checkPtsOffset( hb_work_object_t * w )
1428 hb_work_private_t * pv = w->private_data;
1431 for( i = 0; i < pv->common->pts_count; i++ )
1433 if ( pv->common->first_pts[i] == INT64_MAX )