1 /* $Id: sync.c,v 1.38 2005/04/14 21:57:58 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
9 #include "samplerate.h"
10 #include "ffmpeg/avcodec.h"
13 #undef INT64_MIN /* Because it isn't defined correctly in Zeta */
15 #define INT64_MIN (-9223372036854775807LL-1)
17 #define AC3_SAMPLES_PER_FRAME 1536
34 struct hb_work_object_s
42 hb_subtitle_t * subtitle;
44 int64_t pts_offset_old;
46 int64_t count_frames_max;
47 hb_buffer_t * cur; /* The next picture to process */
50 hb_sync_audio_t sync_audio[8];
53 uint64_t st_counts[4];
58 /***********************************************************************
60 **********************************************************************/
61 static void InitAudio( hb_work_object_t * w, int i );
62 static void Close( hb_work_object_t ** _w );
63 static int Work( hb_work_object_t * w, hb_buffer_t ** unused1,
64 hb_buffer_t ** unused2 );
65 static int SyncVideo( hb_work_object_t * w );
66 static void SyncAudio( hb_work_object_t * w, int i );
67 static int NeedSilence( hb_work_object_t * w, hb_audio_t * );
68 static void InsertSilence( hb_work_object_t * w, int i );
69 static void UpdateState( hb_work_object_t * w );
71 /***********************************************************************
73 ***********************************************************************
74 * Initialize the work object
75 **********************************************************************/
76 hb_work_object_t * hb_work_sync_init( hb_job_t * job )
79 hb_title_t * title = job->title;
80 hb_chapter_t * chapter;
84 w = calloc( sizeof( hb_work_object_t ), 1 );
85 w->name = strdup( "Synchronization" );
90 w->pts_offset = INT64_MIN;
91 w->pts_offset_old = INT64_MIN;
94 /* Calculate how many video frames we are expecting */
96 for( i = job->chapter_start; i <= job->chapter_end; i++ )
98 chapter = hb_list_item( title->list_chapter, i - 1 );
99 duration += chapter->duration;
102 /* 1 second safety so we're sure we won't miss anything */
103 w->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
105 hb_log( "sync: expecting %lld video frames", w->count_frames_max );
107 /* Initialize libsamplerate for every audio track we have */
108 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
113 /* Get subtitle info, if any */
114 w->subtitle = hb_list_item( title->list_subtitle, 0 );
119 static void InitAudio( hb_work_object_t * w, int i )
121 hb_job_t * job = w->job;
122 hb_title_t * title = job->title;
123 hb_sync_audio_t * sync;
125 sync = &w->sync_audio[i];
126 sync->audio = hb_list_item( title->list_audio, i );
128 if( job->acodec & HB_ACODEC_AC3 )
130 /* Have a silent AC-3 frame ready in case we have to fill a
136 codec = avcodec_find_encoder( CODEC_ID_AC3 );
137 c = avcodec_alloc_context();
139 c->bit_rate = sync->audio->bitrate;
140 c->sample_rate = sync->audio->rate;
141 c->channels = sync->audio->channels;
143 if( avcodec_open( c, codec ) < 0 )
145 hb_log( "sync: avcodec_open failed" );
149 zeros = calloc( AC3_SAMPLES_PER_FRAME *
150 sizeof( short ) * c->channels, 1 );
151 sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /
152 sync->audio->rate / 8;
153 sync->ac3_buf = malloc( sync->ac3_size );
155 if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
156 zeros ) != sync->ac3_size )
158 hb_log( "sync: avcodec_encode_audio failed" );
167 /* Initialize libsamplerate */
169 sync->state = src_new( SRC_LINEAR, 2, &error );
170 sync->data.end_of_input = 0;
174 /***********************************************************************
176 ***********************************************************************
178 **********************************************************************/
179 static void Close( hb_work_object_t ** _w )
181 hb_work_object_t * w = *_w;
182 hb_job_t * job = w->job;
183 hb_title_t * title = job->title;
187 if( w->cur ) hb_buffer_close( &w->cur );
189 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
191 if( job->acodec & HB_ACODEC_AC3 )
193 free( w->sync_audio[i].ac3_buf );
197 src_delete( w->sync_audio[i].state );
206 /***********************************************************************
208 ***********************************************************************
209 * The root routine of this work abject
210 **********************************************************************/
211 static int Work( hb_work_object_t * w, hb_buffer_t ** unused1,
212 hb_buffer_t ** unused2 )
216 /* If we ever got a video frame, handle audio now */
217 if( w->pts_offset != INT64_MIN )
219 for( i = 0; i < hb_list_count( w->job->title->list_audio ); i++ )
226 return SyncVideo( w );
229 /***********************************************************************
231 ***********************************************************************
233 **********************************************************************/
234 static int SyncVideo( hb_work_object_t * w )
236 hb_buffer_t * cur, * next, * sub = NULL;
237 hb_job_t * job = w->job;
238 int64_t pts_expected;
245 if( hb_thread_has_exited( job->reader ) &&
246 !hb_fifo_size( job->fifo_mpeg2 ) &&
247 !hb_fifo_size( job->fifo_raw ) )
249 /* All video data has been processed already, we won't get
251 hb_log( "sync: got %lld frames, %lld expected",
252 w->count_frames, w->count_frames_max );
257 if( !w->cur && !( w->cur = hb_fifo_get( job->fifo_raw ) ) )
259 /* We haven't even got a frame yet */
264 /* At this point we have a frame to process. Let's check
265 1) if we will be able to push into the fifo ahead
266 2) if the next frame is there already, since we need it to
267 know whether we'll have to repeat the current frame or not */
268 while( !hb_fifo_is_full( job->fifo_sync ) &&
269 ( next = hb_fifo_see( job->fifo_raw ) ) )
271 hb_buffer_t * buf_tmp;
273 if( w->pts_offset == INT64_MIN )
275 /* This is our first frame */
276 hb_log( "sync: first pts is %lld", cur->start );
277 w->pts_offset = cur->start;
280 /* Check for PTS jumps over 0.5 second */
281 if( next->start < cur->start - 45000 ||
282 next->start > cur->start + 45000 )
284 hb_log( "PTS discontinuity (%lld, %lld)",
285 cur->start, next->start );
287 /* Trash all subtitles */
290 while( ( sub = hb_fifo_get( w->subtitle->fifo_raw ) ) )
292 hb_buffer_close( &sub );
296 /* Trash current picture */
297 hb_buffer_close( &cur );
298 w->cur = cur = hb_fifo_get( job->fifo_raw );
300 /* Calculate new offset */
301 w->pts_offset_old = w->pts_offset;
302 w->pts_offset = cur->start -
303 w->count_frames * w->job->vrate_base / 300;
307 /* Look for a subtitle for this frame */
310 /* Trash subtitles older than this picture */
311 while( ( sub = hb_fifo_see( w->subtitle->fifo_raw ) ) &&
312 sub->stop < cur->start )
314 sub = hb_fifo_get( w->subtitle->fifo_raw );
315 hb_buffer_close( &sub );
318 /* If we have subtitles left in the fifo, check if we should
319 apply the first one to the current frame or if we should
321 if( sub && sub->start > cur->start )
327 /* The PTS of the frame we are expecting now */
328 pts_expected = w->pts_offset +
329 w->count_frames * w->job->vrate_base / 300;
331 if( cur->start < pts_expected - w->job->vrate_base / 300 / 2 &&
332 next->start < pts_expected + w->job->vrate_base / 300 / 2 )
334 /* The current frame is too old but the next one matches,
336 hb_buffer_close( &cur );
337 w->cur = cur = hb_fifo_get( job->fifo_raw );
341 if( next->start > pts_expected + 3 * w->job->vrate_base / 300 / 2 )
343 /* We'll need the current frame more than one time. Make a
344 copy of it and keep it */
345 buf_tmp = hb_buffer_init( cur->size );
346 memcpy( buf_tmp->data, cur->data, cur->size );
350 /* The frame has the expected date and won't have to be
351 duplicated, just put it through */
353 w->cur = cur = hb_fifo_get( job->fifo_raw );
356 /* Replace those MPEG-2 dates with our dates */
357 buf_tmp->start = (uint64_t) w->count_frames *
358 w->job->vrate_base / 300;
359 buf_tmp->stop = (uint64_t) ( w->count_frames + 1 ) *
360 w->job->vrate_base / 300;
362 /* If we have a subtitle for this picture, copy it */
363 /* FIXME: we should avoid this memcpy */
366 buf_tmp->sub = hb_buffer_init( sub->size );
367 buf_tmp->sub->x = sub->x;
368 buf_tmp->sub->y = sub->y;
369 buf_tmp->sub->width = sub->width;
370 buf_tmp->sub->height = sub->height;
371 memcpy( buf_tmp->sub->data, sub->data, sub->size );
374 /* Push the frame to the renderer */
375 hb_fifo_push( job->fifo_sync, buf_tmp );
380 /* Make sure we won't get more frames then expected */
381 if( w->count_frames >= w->count_frames_max )
383 hb_log( "sync: got %lld frames", w->count_frames );
392 /***********************************************************************
394 ***********************************************************************
396 **********************************************************************/
397 static void SyncAudio( hb_work_object_t * w, int i )
402 hb_sync_audio_t * sync;
407 int64_t pts_expected;
411 sync = &w->sync_audio[i];
414 if( job->acodec & HB_ACODEC_AC3 )
416 fifo = audio->fifo_out;
421 fifo = audio->fifo_sync;
425 while( !hb_fifo_is_full( fifo ) &&
426 ( buf = hb_fifo_see( audio->fifo_raw ) ) )
428 /* The PTS of the samples we are expecting now */
429 pts_expected = w->pts_offset + sync->count_frames * 90000 / rate;
431 if( ( buf->start > pts_expected + 45000 ||
432 buf->start < pts_expected - 45000 ) &&
433 w->pts_offset_old > INT64_MIN )
435 /* There has been a PTS discontinuity, and this frame might
436 be from before the discontinuity */
437 pts_expected = w->pts_offset_old + sync->count_frames *
440 if( buf->start > pts_expected + 45000 ||
441 buf->start < pts_expected - 45000 )
443 /* There is really nothing we can do with it */
444 buf = hb_fifo_get( audio->fifo_raw );
445 hb_buffer_close( &buf );
449 /* Use the older offset */
450 start = pts_expected - w->pts_offset_old;
454 start = pts_expected - w->pts_offset;
457 if( ( buf->start + buf->stop ) / 2 < pts_expected )
459 /* Late audio, trash it */
460 buf = hb_fifo_get( audio->fifo_raw );
461 hb_buffer_close( &buf );
465 if( buf->start > pts_expected + ( buf->stop - buf->start ) / 2 )
467 /* Audio push, send a frame of silence */
468 InsertSilence( w, i );
472 if( job->acodec & HB_ACODEC_AC3 )
474 buf = hb_fifo_get( audio->fifo_raw );
476 buf->stop = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
478 sync->count_frames += AC3_SAMPLES_PER_FRAME;
482 hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
484 int count_in, count_out;
486 count_in = buf_raw->size / 2 / sizeof( float );
487 count_out = ( buf->stop - pts_expected ) * job->arate / 90000;
489 sync->data.data_in = (float *) buf_raw->data;
490 sync->data.input_frames = count_in;
492 if( buf->start < pts_expected - ( buf->stop - buf->start ) / 5 )
494 /* Avoid too heavy downsampling, trash the beginning of
495 the buffer instead */
497 drop = count_in * ( pts_expected - buf->start ) /
498 ( buf->stop - buf->start );
499 sync->data.data_in += 2 * drop;
500 sync->data.input_frames -= drop;
501 hb_log( "dropping %d of %d samples", drop, count_in );
504 sync->data.output_frames = count_out;
505 sync->data.src_ratio = (double) sync->data.output_frames /
506 (double) sync->data.input_frames;
508 buf = hb_buffer_init( sync->data.output_frames * 2 *
510 sync->data.data_out = (float *) buf->data;
511 if( src_process( sync->state, &sync->data ) )
513 /* XXX If this happens, we're screwed */
514 hb_log( "sync: src_process failed" );
516 hb_buffer_close( &buf_raw );
518 buf->size = sync->data.output_frames_gen * 2 * sizeof( float );
520 /* Set dates for resampled data */
522 buf->stop = start + sync->data.output_frames_gen *
525 sync->count_frames += sync->data.output_frames_gen;
529 hb_fifo_push( fifo, buf );
532 if( NeedSilence( w, audio ) )
534 InsertSilence( w, i );
538 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
540 hb_job_t * job = w->job;
542 if( hb_fifo_size( audio->fifo_in ) ||
543 hb_fifo_size( audio->fifo_raw ) ||
544 hb_fifo_size( audio->fifo_sync ) ||
545 hb_fifo_size( audio->fifo_out ) )
547 /* We have some audio, we are fine */
551 /* No audio left in fifos */
553 if( hb_thread_has_exited( job->reader ) )
555 /* We might miss some audio to complete encoding and muxing
560 if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
561 hb_fifo_is_full( job->fifo_raw ) &&
562 hb_fifo_is_full( job->fifo_sync ) &&
563 hb_fifo_is_full( job->fifo_render ) &&
564 hb_fifo_is_full( job->fifo_mpeg4 ) )
566 /* Too much video and no audio, oh-oh */
573 static void InsertSilence( hb_work_object_t * w, int i )
576 hb_sync_audio_t * sync;
580 sync = &w->sync_audio[i];
582 if( job->acodec & HB_ACODEC_AC3 )
584 buf = hb_buffer_init( sync->ac3_size );
585 buf->start = sync->count_frames * 90000 / sync->audio->rate;
586 buf->stop = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
588 memcpy( buf->data, sync->ac3_buf, buf->size );
590 hb_log( "sync: adding a silent AC-3 frame for track %x",
592 hb_fifo_push( sync->audio->fifo_out, buf );
594 sync->count_frames += AC3_SAMPLES_PER_FRAME;
599 buf = hb_buffer_init( 2 * job->arate / 20 *
601 buf->start = sync->count_frames * 90000 / job->arate;
602 buf->stop = buf->start + 90000 / 20;
603 memset( buf->data, 0, buf->size );
605 hb_log( "sync: adding 50 ms of silence for track %x",
607 hb_fifo_push( sync->audio->fifo_sync, buf );
609 sync->count_frames += job->arate / 20;
613 static void UpdateState( hb_work_object_t * w )
617 if( !w->count_frames )
619 w->st_first = hb_get_date();
623 if( hb_get_date() > w->st_dates[3] + 1000 )
625 memmove( &w->st_dates[0], &w->st_dates[1],
626 3 * sizeof( uint64_t ) );
627 memmove( &w->st_counts[0], &w->st_counts[1],
628 3 * sizeof( uint64_t ) );
629 w->st_dates[3] = hb_get_date();
630 w->st_counts[3] = w->count_frames;
633 #define p state.param.working
634 state.state = HB_STATE_WORKING;
635 p.progress = (float) w->count_frames / (float) w->count_frames_max;
636 if( p.progress > 1.0 )
640 p.rate_cur = 1000.0 *
641 (float) ( w->st_counts[3] - w->st_counts[0] ) /
642 (float) ( w->st_dates[3] - w->st_dates[0] );
643 if( hb_get_date() > w->st_first + 4000 )
646 p.rate_avg = 1000.0 * (float) w->st_counts[3] /
647 (float) ( w->st_dates[3] - w->st_first );
648 eta = (float) ( w->count_frames_max - w->st_counts[3] ) /
650 p.hours = eta / 3600;
651 p.minutes = ( eta % 3600 ) / 60;
652 p.seconds = eta % 60;
663 hb_set_state( w->job->h, &state );