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 );
1005 hb_buffer_close( &buf );
1006 hb_unlock( pv->common->mutex );
1009 hb_unlock( pv->common->mutex );
1011 if( job->frame_to_stop && pv->common->count_frames >= job->frame_to_stop )
1013 hb_buffer_close( &buf );
1014 *buf_out = hb_buffer_init( 0 );
1015 return HB_WORK_DONE;
1018 if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
1020 hb_buffer_close( &buf );
1021 *buf_out = hb_buffer_init( 0 );
1022 return HB_WORK_DONE;
1025 if ( start - sync->next_start < 0 )
1027 // audio time went backwards.
1028 // If our output clock is more than a half frame ahead of the
1029 // input clock drop this frame to move closer to sync.
1030 // Otherwise drop frames until the input clock matches the output clock.
1031 if ( sync->first_drop || sync->next_start - start > 90*15 )
1033 // Discard data that's in the past.
1034 if ( sync->first_drop == 0 )
1036 sync->first_drop = sync->next_start;
1039 hb_buffer_close( &buf );
1043 if ( sync->first_drop )
1045 // we were dropping old data but input buf time is now current
1046 hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
1047 "(next %"PRId64", current %"PRId64")", w->audio->id,
1048 (int)( sync->next_start - sync->first_drop ) / 90,
1049 sync->drop_count, sync->first_drop, (int64_t)sync->next_start );
1050 sync->first_drop = 0;
1051 sync->drop_count = 0;
1053 if ( start - sync->next_start >= (90 * 70) )
1055 if ( start - sync->next_start > (90000LL * 60) )
1057 // there's a gap of more than a minute between the last
1058 // frame and this. assume we got a corrupted timestamp
1059 // and just drop the next buf.
1060 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
1061 " start %"PRId64", next %"PRId64,
1062 (int)((start - sync->next_start) / (90000*60)),
1063 w->audio->id, start, (int64_t)sync->next_start );
1064 hb_buffer_close( &buf );
1068 * there's a gap of at least 70ms between the last
1069 * frame we processed & the next. Fill it with silence.
1070 * Or in the case of DCA, skip some frames from the
1073 if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1075 hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d"
1076 " start %"PRId64", next %"PRId64,
1077 (int)((start - sync->next_start) / 90),
1078 w->audio->id, start, (int64_t)sync->next_start );
1079 hb_lock( pv->common->mutex );
1080 pv->common->audio_pts_slip += (start - sync->next_start);
1081 pv->common->video_pts_slip += (start - sync->next_start);
1082 hb_unlock( pv->common->mutex );
1086 hb_log( "sync: adding %d ms of silence to audio %d"
1087 " start %"PRId64", next %"PRId64,
1088 (int)((start - sync->next_start) / 90),
1089 w->audio->id, start, (int64_t)sync->next_start );
1090 InsertSilence( w, start - sync->next_start );
1094 * When we get here we've taken care of all the dups and gaps in the
1095 * audio stream and are ready to inject the next input frame into
1096 * the output stream.
1098 *buf_out = OutputAudioFrame( w->audio, buf, sync );
1102 hb_work_object_t hb_sync_audio =
1105 "AudioSynchronization",
1111 static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
1113 hb_work_object_t * w;
1114 hb_work_private_t * pv;
1115 hb_title_t * title = job->title;
1116 hb_sync_audio_t * sync;
1118 pv = calloc( 1, sizeof( hb_work_private_t ) );
1119 sync = &pv->type.audio;
1122 pv->common = common;
1124 pv->common->pts_count++;
1126 w = hb_get_work( WORK_SYNC_AUDIO );
1127 w->private_data = pv;
1128 w->audio = hb_list_item( title->list_audio, i );
1129 w->fifo_in = w->audio->priv.fifo_raw;
1131 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1132 w->audio->config.out.codec == HB_ACODEC_DCA_PASS )
1134 w->fifo_out = w->audio->priv.fifo_out;
1138 w->fifo_out = w->audio->priv.fifo_sync;
1141 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1143 /* Have a silent AC-3 frame ready in case we have to fill a
1149 codec = avcodec_find_encoder( CODEC_ID_AC3 );
1150 c = avcodec_alloc_context();
1152 c->bit_rate = w->audio->config.in.bitrate;
1153 c->sample_rate = w->audio->config.in.samplerate;
1154 c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( w->audio->config.in.channel_layout );
1156 if( hb_avcodec_open( c, codec ) < 0 )
1158 hb_log( "sync: avcodec_open failed" );
1162 zeros = calloc( AC3_SAMPLES_PER_FRAME *
1163 sizeof( short ) * c->channels, 1 );
1164 sync->ac3_size = w->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
1165 w->audio->config.in.samplerate / 8;
1166 sync->ac3_buf = malloc( sync->ac3_size );
1168 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
1169 zeros ) != sync->ac3_size )
1171 hb_log( "sync: avcodec_encode_audio failed" );
1175 hb_avcodec_close( c );
1180 /* Initialize libsamplerate */
1182 sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
1183 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1184 w->audio->config.out.mixdown), &error );
1185 sync->data.end_of_input = 0;
1187 hb_list_add( job->list_work, w );
1190 static hb_buffer_t * OutputAudioFrame( hb_audio_t *audio, hb_buffer_t *buf,
1191 hb_sync_audio_t *sync )
1193 int64_t start = (int64_t)sync->next_start;
1194 double duration = buf->stop - buf->start;
1196 if( audio->config.in.samplerate == audio->config.out.samplerate ||
1197 audio->config.out.codec == HB_ACODEC_AC3_PASS ||
1198 audio->config.out.codec == HB_ACODEC_DCA_PASS )
1201 * If we don't have to do sample rate conversion or this audio is
1202 * pass-thru just send the input buffer downstream after adjusting
1203 * its timestamps to make the output stream continuous.
1208 /* Not pass-thru - do sample rate conversion */
1209 int count_in, count_out;
1210 hb_buffer_t * buf_raw = buf;
1211 int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
1214 count_in = buf_raw->size / channel_count;
1216 * When using stupid rates like 44.1 there will always be some
1217 * truncation error. E.g., a 1536 sample AC3 frame will turn into a
1218 * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
1219 * the error will build up over time and eventually the audio will
1220 * substantially lag the video. libsamplerate will keep track of the
1221 * fractional sample & give it to us when appropriate if we give it
1222 * an extra sample of space in the output buffer.
1224 count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
1226 sync->data.input_frames = count_in;
1227 sync->data.output_frames = count_out;
1228 sync->data.src_ratio = (double)audio->config.out.samplerate /
1229 (double)audio->config.in.samplerate;
1231 buf = hb_buffer_init( count_out * channel_count );
1232 sync->data.data_in = (float *) buf_raw->data;
1233 sync->data.data_out = (float *) buf->data;
1234 if( src_process( sync->state, &sync->data ) )
1236 /* XXX If this happens, we're screwed */
1237 hb_log( "sync: audio %d src_process failed", audio->id );
1239 hb_buffer_close( &buf_raw );
1241 buf->size = sync->data.output_frames_gen * channel_count;
1242 duration = (double)( sync->data.output_frames_gen * 90000 ) /
1243 audio->config.out.samplerate;
1245 buf->frametype = HB_FRAME_AUDIO;
1247 sync->next_start += duration;
1248 buf->stop = (int64_t)sync->next_start;
1252 static void InsertSilence( hb_work_object_t * w, int64_t duration )
1254 hb_work_private_t * pv = w->private_data;
1255 hb_sync_audio_t *sync = &pv->type.audio;
1259 // to keep pass-thru and regular audio in sync we generate silence in
1260 // AC3 frame-sized units. If the silence duration isn't an integer multiple
1261 // of the AC3 frame duration we will truncate or round up depending on
1262 // which minimizes the timing error.
1263 const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
1264 w->audio->config.in.samplerate;
1265 int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
1267 while ( --frame_count >= 0 )
1269 if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
1271 buf = hb_buffer_init( sync->ac3_size );
1272 buf->start = sync->next_start;
1273 buf->stop = buf->start + frame_dur;
1274 memcpy( buf->data, sync->ac3_buf, buf->size );
1275 fifo = w->audio->priv.fifo_out;
1279 buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
1280 HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
1281 w->audio->config.out.mixdown) );
1282 buf->start = sync->next_start;
1283 buf->stop = buf->start + frame_dur;
1284 memset( buf->data, 0, buf->size );
1285 fifo = w->audio->priv.fifo_sync;
1287 buf = OutputAudioFrame( w->audio, buf, sync );
1288 hb_fifo_push( fifo, buf );
1292 static void UpdateState( hb_work_object_t * w )
1294 hb_work_private_t * pv = w->private_data;
1295 hb_sync_video_t * sync = &pv->type.video;
1298 if( !pv->common->count_frames )
1300 sync->st_first = hb_get_date();
1301 pv->job->st_pause_date = -1;
1302 pv->job->st_paused = 0;
1304 pv->common->count_frames++;
1306 if( hb_get_date() > sync->st_dates[3] + 1000 )
1308 memmove( &sync->st_dates[0], &sync->st_dates[1],
1309 3 * sizeof( uint64_t ) );
1310 memmove( &sync->st_counts[0], &sync->st_counts[1],
1311 3 * sizeof( uint64_t ) );
1312 sync->st_dates[3] = hb_get_date();
1313 sync->st_counts[3] = pv->common->count_frames;
1316 #define p state.param.working
1317 state.state = HB_STATE_WORKING;
1318 p.progress = (float) pv->common->count_frames / (float) sync->count_frames_max;
1319 if( p.progress > 1.0 )
1323 p.rate_cur = 1000.0 *
1324 (float) ( sync->st_counts[3] - sync->st_counts[0] ) /
1325 (float) ( sync->st_dates[3] - sync->st_dates[0] );
1326 if( hb_get_date() > sync->st_first + 4000 )
1329 p.rate_avg = 1000.0 * (float) sync->st_counts[3] /
1330 (float) ( sync->st_dates[3] - sync->st_first - pv->job->st_paused);
1331 eta = (float) ( sync->count_frames_max - sync->st_counts[3] ) /
1333 p.hours = eta / 3600;
1334 p.minutes = ( eta % 3600 ) / 60;
1335 p.seconds = eta % 60;
1346 hb_set_state( pv->job->h, &state );
1349 static void UpdateSearchState( hb_work_object_t * w, int64_t start )
1351 hb_work_private_t * pv = w->private_data;
1352 hb_sync_video_t * sync = &pv->type.video;
1357 now = hb_get_date();
1358 if( !pv->common->count_frames )
1360 sync->st_first = now;
1361 pv->job->st_pause_date = -1;
1362 pv->job->st_paused = 0;
1364 pv->common->count_frames++;
1366 #define p state.param.working
1367 state.state = HB_STATE_SEARCHING;
1368 if ( pv->job->frame_to_start )
1369 p.progress = (float) pv->common->count_frames /
1370 (float) pv->job->frame_to_start;
1371 else if ( pv->job->pts_to_start )
1372 p.progress = (float) start / (float) pv->job->pts_to_start;
1375 if( p.progress > 1.0 )
1379 if (now > sync->st_first)
1383 if ( pv->job->frame_to_start )
1385 avg = 1000.0 * (double)pv->common->count_frames / (now - sync->st_first);
1386 eta = ( pv->job->frame_to_start - pv->common->count_frames ) / avg;
1388 else if ( pv->job->pts_to_start )
1390 avg = 1000.0 * (double)start / (now - sync->st_first);
1391 eta = ( pv->job->pts_to_start - start ) / avg;
1393 p.hours = eta / 3600;
1394 p.minutes = ( eta % 3600 ) / 60;
1395 p.seconds = eta % 60;
1406 hb_set_state( pv->job->h, &state );
1409 static void getPtsOffset( hb_work_object_t * w )
1411 hb_work_private_t * pv = w->private_data;
1413 int64_t first_pts = INT64_MAX;
1415 for( i = 0; i < pv->common->pts_count; i++ )
1417 if ( pv->common->first_pts[i] < first_pts )
1418 first_pts = pv->common->first_pts[i];
1420 pv->common->video_pts_slip = pv->common->audio_pts_slip = pv->common->pts_offset = first_pts;
1424 static int checkPtsOffset( hb_work_object_t * w )
1426 hb_work_private_t * pv = w->private_data;
1429 for( i = 0; i < pv->common->pts_count; i++ )
1431 if ( pv->common->first_pts[i] == INT64_MAX )