OSDN Git Service

c5842148caf594fc00084e946081d19341504392
[handbrake-jp/handbrake-jp-git.git] / libhb / sync.c
1 /* $Id: sync.c,v 1.38 2005/04/14 21:57:58 titer Exp $
2
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. */
6
7 #include "hb.h"
8 #include "hbffmpeg.h"
9 #include <stdio.h>
10 #include "samplerate.h"
11
12 #ifdef INT64_MIN
13 #undef INT64_MIN /* Because it isn't defined correctly in Zeta */
14 #endif
15 #define INT64_MIN (-9223372036854775807LL-1)
16
17 #define AC3_SAMPLES_PER_FRAME 1536
18
19 typedef struct
20 {
21     hb_audio_t * audio;
22
23     int64_t      next_start;    /* start time of next output frame */
24     int64_t      next_pts;      /* start time of next input frame */
25     int64_t      first_drop;    /* PTS of first 'went backwards' frame dropped */
26     int          drop_count;    /* count of 'time went backwards' drops */
27
28     /* Raw */
29     SRC_STATE  * state;
30     SRC_DATA     data;
31
32     /* AC-3 */
33     int          ac3_size;
34     uint8_t    * ac3_buf;
35
36 } hb_sync_audio_t;
37
38 struct hb_work_private_s
39 {
40     hb_job_t * job;
41     int        busy;            // bitmask with one bit for each active input
42                                 // (bit 0 = video; 1 = audio 0, 2 = audio 1, ...
43                                 // appropriate bit is cleared when input gets
44                                 // an eof buf. syncWork returns done when all
45                                 // bits are clear.
46     /* Video */
47     int64_t pts_offset;
48     int64_t next_start;         /* start time of next output frame */
49     int64_t next_pts;           /* start time of next input frame */
50     int64_t first_drop;         /* PTS of first 'went backwards' frame dropped */
51     int drop_count;             /* count of 'time went backwards' drops */
52     int drops;                  /* frames dropped to make a cbr video stream */
53     int dups;                   /* frames duplicated to make a cbr video stream */
54     int video_sequence;
55     int count_frames;
56     int count_frames_max;
57     int chap_mark;              /* to propagate chapter mark across a drop */
58     hb_buffer_t * cur; /* The next picture to process */
59
60     /* Audio */
61     hb_sync_audio_t sync_audio[8];
62     int64_t audio_passthru_slip;
63
64     /* Statistics */
65     uint64_t st_counts[4];
66     uint64_t st_dates[4];
67     uint64_t st_first;
68 };
69
70 /***********************************************************************
71  * Local prototypes
72  **********************************************************************/
73 static void InitAudio( hb_work_object_t * w, int i );
74 static void SyncVideo( hb_work_object_t * w );
75 static void SyncAudio( hb_work_object_t * w, int i );
76 static void InsertSilence( hb_work_object_t * w, int i, int64_t d );
77 static void UpdateState( hb_work_object_t * w );
78
79 /***********************************************************************
80  * hb_work_sync_init
81  ***********************************************************************
82  * Initialize the work object
83  **********************************************************************/
84 int syncInit( hb_work_object_t * w, hb_job_t * job )
85 {
86     hb_title_t       * title = job->title;
87     hb_chapter_t     * chapter;
88     int                i;
89     uint64_t           duration;
90     hb_work_private_t * pv;
91
92     pv = calloc( 1, sizeof( hb_work_private_t ) );
93     w->private_data = pv;
94
95     pv->job            = job;
96     pv->pts_offset     = INT64_MIN;
97
98     /* Calculate how many video frames we are expecting */
99     if (job->pts_to_stop)
100     {
101         duration = job->pts_to_stop + 90000;
102     }
103     else if( job->frame_to_stop )
104     {
105         /* Set the duration to a rough estimate */
106         duration = ( job->frame_to_stop / ( job->vrate / job->vrate_base ) ) * 90000;
107     }
108     else
109     {
110         duration = 0;
111         for( i = job->chapter_start; i <= job->chapter_end; i++ )
112         {
113             chapter   = hb_list_item( title->list_chapter, i - 1 );
114             duration += chapter->duration;
115         }
116         duration += 90000;
117         /* 1 second safety so we're sure we won't miss anything */
118     }
119     pv->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
120
121     hb_log( "sync: expecting %d video frames", pv->count_frames_max );
122     pv->busy |= 1;
123
124     /* Initialize libsamplerate for every audio track we have */
125     if ( ! job->indepth_scan )
126     {
127         for( i = 0; i < hb_list_count( title->list_audio ) && i < 8; i++ )
128         {
129             pv->busy |= ( 1 << (i + 1) );
130             InitAudio( w, i );
131         }
132     }
133
134     return 0;
135 }
136
137 /***********************************************************************
138  * Close
139  ***********************************************************************
140  *
141  **********************************************************************/
142 void syncClose( hb_work_object_t * w )
143 {
144     hb_work_private_t * pv = w->private_data;
145     hb_job_t          * job   = pv->job;
146     hb_title_t        * title = job->title;
147     hb_audio_t        * audio = NULL;
148     int i;
149
150     if( pv->cur )
151     {
152         hb_buffer_close( &pv->cur );
153     }
154
155     hb_log( "sync: got %d frames, %d expected",
156             pv->count_frames, pv->count_frames_max );
157
158     if (pv->drops || pv->dups )
159     {
160         hb_log( "sync: %d frames dropped, %d duplicated", pv->drops, pv->dups );
161     }
162
163     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
164     {
165         audio = hb_list_item( title->list_audio, i );
166         if( audio->config.out.codec == HB_ACODEC_AC3 )
167         {
168             free( pv->sync_audio[i].ac3_buf );
169         }
170         else
171         {
172             src_delete( pv->sync_audio[i].state );
173         }
174     }
175
176     free( pv );
177     w->private_data = NULL;
178 }
179
180 /***********************************************************************
181  * Work
182  ***********************************************************************
183  * The root routine of this work abject
184  *
185  * The way this works is that we are syncing the audio to the PTS of
186  * the last video that we processed. That's why we skip the audio sync
187  * if we haven't got a valid PTS from the video yet.
188  *
189  **********************************************************************/
190 int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
191               hb_buffer_t ** unused2 )
192 {
193     hb_work_private_t * pv = w->private_data;
194     int i;
195
196     if ( pv->busy & 1 )
197         SyncVideo( w );
198
199     for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
200     {
201         if ( pv->busy & ( 1 << (i + 1) ) )
202             SyncAudio( w, i );
203     }
204
205     return ( pv->busy? HB_WORK_OK : HB_WORK_DONE );
206 }
207
208 hb_work_object_t hb_sync =
209 {
210     WORK_SYNC,
211     "Synchronization",
212     syncInit,
213     syncWork,
214     syncClose
215 };
216
217 static void InitAudio( hb_work_object_t * w, int i )
218 {
219     hb_work_private_t * pv = w->private_data;
220     hb_job_t        * job   = pv->job;
221     hb_title_t      * title = job->title;
222     hb_sync_audio_t * sync;
223
224     sync        = &pv->sync_audio[i];
225     sync->audio = hb_list_item( title->list_audio, i );
226
227     if( sync->audio->config.out.codec == HB_ACODEC_AC3 )
228     {
229         /* Have a silent AC-3 frame ready in case we have to fill a
230            gap */
231         AVCodec        * codec;
232         AVCodecContext * c;
233         short          * zeros;
234
235         codec = avcodec_find_encoder( CODEC_ID_AC3 );
236         c     = avcodec_alloc_context();
237
238         c->bit_rate    = sync->audio->config.in.bitrate;
239         c->sample_rate = sync->audio->config.in.samplerate;
240         c->channels    = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( sync->audio->config.in.channel_layout );
241
242         if( hb_avcodec_open( c, codec ) < 0 )
243         {
244             hb_log( "sync: avcodec_open failed" );
245             return;
246         }
247
248         zeros          = calloc( AC3_SAMPLES_PER_FRAME *
249                                  sizeof( short ) * c->channels, 1 );
250         sync->ac3_size = sync->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
251                              sync->audio->config.in.samplerate / 8;
252         sync->ac3_buf  = malloc( sync->ac3_size );
253
254         if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
255                                   zeros ) != sync->ac3_size )
256         {
257             hb_log( "sync: avcodec_encode_audio failed" );
258         }
259
260         free( zeros );
261         hb_avcodec_close( c );
262         av_free( c );
263     }
264     else
265     {
266         /* Initialize libsamplerate */
267         int error;
268         sync->state             = src_new( SRC_SINC_MEDIUM_QUALITY, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown), &error );
269         sync->data.end_of_input = 0;
270     }
271 }
272
273 /***********************************************************************
274  * SyncVideo
275  ***********************************************************************
276  *
277  **********************************************************************/
278 static void SyncVideo( hb_work_object_t * w )
279 {
280     hb_work_private_t * pv = w->private_data;
281     hb_buffer_t * cur, * next, * sub = NULL;
282     hb_job_t * job = pv->job;
283     hb_subtitle_t *subtitle;
284     int i;
285
286     if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
287     {
288         /* We haven't even got a frame yet */
289         return;
290     }
291     cur = pv->cur;
292     if( cur->size == 0 )
293     {
294         /* we got an end-of-stream. Feed it downstream & signal that we're done. */
295         hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
296
297         /*
298          * Push through any subtitle EOFs in case they were not synced through.
299          */
300         for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
301         {
302             subtitle = hb_list_item( job->list_subtitle, i );
303             if( subtitle->dest == PASSTHRUSUB )
304             {
305                 hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
306             }
307         }
308
309         pv->busy &=~ 1;
310         return;
311     }
312
313     /* At this point we have a frame to process. Let's check
314         1) if we will be able to push into the fifo ahead
315         2) if the next frame is there already, since we need it to
316            compute the duration of the current frame*/
317     while( !hb_fifo_is_full( job->fifo_sync ) &&
318            ( next = hb_fifo_see( job->fifo_raw ) ) )
319     {
320         hb_buffer_t * buf_tmp;
321
322         if( next->size == 0 )
323         {
324             /* we got an end-of-stream. Feed it downstream & signal that
325              * we're done. Note that this means we drop the final frame of
326              * video (we don't know its duration). On DVDs the final frame
327              * is often strange and dropping it seems to be a good idea. */
328             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
329
330             /*
331              * Push through any subtitle EOFs in case they were not synced through.
332              */
333             for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
334             {
335                 subtitle = hb_list_item( job->list_subtitle, i );
336                 if( subtitle->dest == PASSTHRUSUB )
337                 {
338                     hb_fifo_push( subtitle->fifo_out, hb_buffer_init( 0 ) );
339                 }
340             }
341             pv->busy &=~ 1;
342             return;
343         }
344         if( pv->pts_offset == INT64_MIN )
345         {
346             /* This is our first frame */
347             pv->pts_offset = 0;
348             if ( cur->start != 0 )
349             {
350                 /*
351                  * The first pts from a dvd should always be zero but
352                  * can be non-zero with a transport or program stream since
353                  * we're not guaranteed to start on an IDR frame. If we get
354                  * a non-zero initial PTS extend its duration so it behaves
355                  * as if it started at zero so that our audio timing will
356                  * be in sync.
357                  */
358                 hb_log( "sync: first pts is %lld", cur->start );
359                 cur->start = 0;
360             }
361         }
362
363         if( cur->new_chap ) {
364             hb_log("sync got new chapter %d", cur->new_chap );
365         }
366
367         /*
368          * since the first frame is always 0 and the upstream reader code
369          * is taking care of adjusting for pts discontinuities, we just have
370          * to deal with the next frame's start being in the past. This can
371          * happen when the PTS is adjusted after data loss but video frame
372          * reordering causes some frames with the old clock to appear after
373          * the clock change. This creates frames that overlap in time which
374          * looks to us like time going backward. The downstream muxing code
375          * can deal with overlaps of up to a frame time but anything larger
376          * we handle by dropping frames here.
377          */
378         if ( (int64_t)( next->start - cur->start ) <= 0 ||
379              (int64_t)( (cur->start - pv->audio_passthru_slip ) - pv->next_pts ) < 0 )
380         {
381             if ( pv->first_drop == 0 )
382             {
383                 pv->first_drop = next->start;
384             }
385             ++pv->drop_count;
386             buf_tmp = hb_fifo_get( job->fifo_raw );
387             if ( buf_tmp->new_chap )
388             {
389                 // don't drop a chapter mark when we drop the buffer
390                 pv->chap_mark = buf_tmp->new_chap;
391             }
392             hb_buffer_close( &buf_tmp );
393             continue;
394         }
395         if ( pv->first_drop )
396         {
397             hb_log( "sync: video time didn't advance - dropped %d frames "
398                     "(delta %d ms, current %lld, next %lld, dur %d)",
399                     pv->drop_count, (int)( cur->start - pv->first_drop ) / 90,
400                     cur->start, next->start, (int)( next->start - cur->start ) );
401             pv->first_drop = 0;
402             pv->drop_count = 0;
403         }
404
405         /*
406          * Track the video sequence number localy so that we can sync the audio
407          * to it using the sequence number as well as the PTS.
408          */
409         pv->video_sequence = cur->sequence;
410
411         /*
412          * Look for a subtitle for this frame.
413          *
414          * If found then it will be tagged onto a video buffer of the correct time and 
415          * sent in to the render pipeline. This only needs to be done for VOBSUBs which
416          * get rendered, other types of subtitles can just sit in their raw_queue until
417          * delt with at muxing.
418          */
419         for( i = 0; i < hb_list_count( job->list_subtitle ); i++)
420         {
421             subtitle = hb_list_item( job->list_subtitle, i );
422
423             /*
424              * Rewrite timestamps on subtitles that need it (on raw queue).
425              */
426             if( subtitle->source == CC608SUB ||
427                 subtitle->source == CC708SUB )
428             {
429                 /*
430                  * Rewrite timestamps on subtitles that came from Closed Captions
431                  * since they are using the MPEG2 timestamps.
432                  */
433                 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
434                 {
435                     /*
436                      * Rewrite the timestamps as and when the video
437                      * (cur->start) reaches the same timestamp as a
438                      * closed caption (sub->start).
439                      *
440                      * What about discontinuity boundaries - not delt
441                      * with here - Van?
442                      *
443                      * Bypass the sync fifo altogether.
444                      */
445                     if( sub->size <= 0 )
446                     {
447                         sub = hb_fifo_get( subtitle->fifo_raw );
448                         hb_fifo_push( subtitle->fifo_out, sub );
449                         sub = NULL;
450                         break;
451                     } else {
452                         if( sub->start < cur->start )
453                         {
454                             uint64_t duration;
455                             duration = sub->stop - sub->start;
456                             sub = hb_fifo_get( subtitle->fifo_raw );
457                             sub->start = pv->next_start;
458                             sub->stop = sub->start + duration;
459                             hb_fifo_push( subtitle->fifo_out, sub );
460                         } else {
461                             sub = NULL;
462                             break;
463                         }
464                     }
465                 }
466             }
467
468             if( subtitle->source == VOBSUB ) 
469             {
470                 hb_buffer_t * sub2;
471                 while( ( sub = hb_fifo_see( subtitle->fifo_raw ) ) )
472                 {
473                     if( sub->size == 0 )
474                     {
475                         /*
476                          * EOF, pass it through immediately.
477                          */
478                         break;
479                     }
480
481                     /* If two subtitles overlap, make the first one stop
482                        when the second one starts */
483                     sub2 = hb_fifo_see2( subtitle->fifo_raw );
484                     if( sub2 && sub->stop > sub2->start )
485                         sub->stop = sub2->start;
486                     
487                     // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld",
488                     //       sub, cur->sequence, sub->sequence);
489                     
490                     if( sub->sequence > cur->sequence )
491                     {
492                         /*
493                          * The video is behind where we are, so wait until
494                          * it catches up to the same reader point on the
495                          * DVD. Then our PTS should be in the same region
496                          * as the video.
497                          */
498                         sub = NULL;
499                         break;
500                     }
501                     
502                     if( sub->stop > cur->start ) {
503                         /*
504                          * The stop time is in the future, so fall through
505                          * and we'll deal with it in the next block of
506                          * code.
507                          */
508                         break;
509                     }
510                     
511                     /*
512                      * The subtitle is older than this picture, trash it
513                      */
514                     sub = hb_fifo_get( subtitle->fifo_raw );
515                     hb_buffer_close( &sub );
516                 }
517                 
518                 if( sub && sub->size == 0 )
519                 {
520                     /* 
521                      * Continue immediately on subtitle EOF
522                      */
523                     break;
524                 }
525
526                 /*
527                  * There is a valid subtitle, is it time to display it?
528                  */
529                 if( sub )
530                 {
531                     if( sub->stop > sub->start)
532                     {
533                         /*
534                          * Normal subtitle which ends after it starts, check to
535                          * see that the current video is between the start and end.
536                          */
537                         if( cur->start > sub->start &&
538                             cur->start < sub->stop )
539                         {
540                             /*
541                              * We should be playing this, so leave the
542                              * subtitle in place.
543                              *
544                              * fall through to display
545                              */
546                             if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
547                             {
548                                 /*
549                                  * Subtitle is on for less than three seconds, extend
550                                  * the time that it is displayed to make it easier
551                                  * to read. Make it 3 seconds or until the next
552                                  * subtitle is displayed.
553                                  *
554                                  * This is in response to Indochine which only
555                                  * displays subs for 1 second - too fast to read.
556                                  */
557                                 sub->stop = sub->start + ( 3 * 90000 );
558                                 
559                                 sub2 = hb_fifo_see2( subtitle->fifo_raw );
560                                 
561                                 if( sub2 && sub->stop > sub2->start )
562                                 {
563                                     sub->stop = sub2->start;
564                                 }
565                             }
566                         }
567                         else
568                         {
569                             /*
570                              * Defer until the play point is within the subtitle
571                              */
572                             sub = NULL;
573                         }
574                     }
575                     else
576                     {
577                         /*
578                          * The end of the subtitle is less than the start, this is a
579                          * sign of a PTS discontinuity.
580                          */
581                         if( sub->start > cur->start )
582                         {
583                             /*
584                              * we haven't reached the start time yet, or
585                              * we have jumped backwards after having
586                              * already started this subtitle.
587                              */
588                             if( cur->start < sub->stop )
589                             {
590                                 /*
591                                  * We have jumped backwards and so should
592                                  * continue displaying this subtitle.
593                                  *
594                                  * fall through to display.
595                                  */
596                             }
597                             else
598                             {
599                                 /*
600                                  * Defer until the play point is within the subtitle
601                                  */
602                                 sub = NULL;
603                             }
604                         } else {
605                             /*
606                              * Play this subtitle as the start is greater than our
607                              * video point.
608                              *
609                              * fall through to display/
610                              */
611                         }
612                     }
613                 }
614             }
615             if( sub )
616             {
617                 /*
618                  * Got a sub to display...
619                  */
620                 break;
621             }
622         } // end subtitles
623
624         /*
625          * Adjust the pts of the current frame so that it's contiguous
626          * with the previous frame. The start time of the current frame
627          * has to be the end time of the previous frame and the stop
628          * time has to be the start of the next frame.  We don't
629          * make any adjustments to the source timestamps other than removing
630          * the clock offsets (which also removes pts discontinuities).
631          * This means we automatically encode at the source's frame rate.
632          * MP2 uses an implicit duration (frames end when the next frame
633          * starts) but more advanced containers like MP4 use an explicit
634          * duration. Since we're looking ahead one frame we set the
635          * explicit stop time from the start time of the next frame.
636          */
637         buf_tmp = cur;
638         pv->cur = cur = hb_fifo_get( job->fifo_raw );
639         pv->next_pts = cur->start;
640         int64_t duration = cur->start - buf_tmp->start;
641         if ( duration <= 0 )
642         {
643             hb_log( "sync: invalid video duration %lld, start %lld, next %lld",
644                     duration, buf_tmp->start, next->start );
645         }
646
647         buf_tmp->start = pv->next_start;
648         pv->next_start += duration;
649         buf_tmp->stop = pv->next_start;
650
651         if ( pv->chap_mark )
652         {
653             // we have a pending chapter mark from a recent drop - put it on this
654             // buffer (this may make it one frame late but we can't do any better).
655             buf_tmp->new_chap = pv->chap_mark;
656             pv->chap_mark = 0;
657         }
658
659         /* If we have a subtitle for this picture, copy it */
660         /* FIXME: we should avoid this memcpy */
661         if( sub && subtitle && 
662             subtitle->format == PICTURESUB )
663         {
664             if( sub->size > 0 )
665             {
666                 if( subtitle->dest == RENDERSUB )
667                 {
668                     /*
669                      * Tack onto the video buffer for rendering
670                      */
671                     buf_tmp->sub         = hb_buffer_init( sub->size );
672                     buf_tmp->sub->x      = sub->x;
673                     buf_tmp->sub->y      = sub->y;
674                     buf_tmp->sub->width  = sub->width;
675                     buf_tmp->sub->height = sub->height;
676                     memcpy( buf_tmp->sub->data, sub->data, sub->size ); 
677                 } else {
678                     /*
679                      * Pass-Through, pop it off of the raw queue, rewrite times and
680                      * make it available to be reencoded.
681                      */
682                     uint64_t sub_duration;
683                     sub = hb_fifo_get( subtitle->fifo_raw );
684                     sub_duration = sub->stop - sub->start;
685                     sub->start = buf_tmp->start;
686                     sub->stop = sub->start + duration;
687                     hb_fifo_push( subtitle->fifo_sync, sub );
688                 }
689             } else {
690                 /*
691                  * EOF - consume for rendered, else pass through
692                  */
693                 if( subtitle->dest == RENDERSUB )
694                 {
695                     sub = hb_fifo_get( subtitle->fifo_raw );
696                     hb_buffer_close( &sub );
697                 } else {
698                     sub = hb_fifo_get( subtitle->fifo_raw );
699                     hb_fifo_push( subtitle->fifo_out, sub );
700                 }
701             }
702         }
703
704         /* Push the frame to the renderer */
705         hb_fifo_push( job->fifo_sync, buf_tmp );
706
707         /* Update UI */
708         UpdateState( w );
709         
710         if( job->frame_to_stop && pv->count_frames > job->frame_to_stop )
711         {
712             // Drop an empty buffer into our output to ensure that things
713             // get flushed all the way out.
714             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
715             pv->busy &=~ 1;
716             hb_log( "sync: reached %d frames, exiting early (%i busy)",
717                     pv->count_frames, pv->busy );
718             return;
719         }
720
721         /* Make sure we won't get more frames then expected */
722         if( pv->count_frames >= pv->count_frames_max * 2)
723         {
724             hb_log( "sync: got too many frames (%d), exiting early",
725                     pv->count_frames );
726
727             // Drop an empty buffer into our output to ensure that things
728             // get flushed all the way out.
729             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
730             pv->busy &=~ 1;
731             return;
732         }
733     }
734 }
735
736 static void OutputAudioFrame( hb_job_t *job, hb_audio_t *audio, hb_buffer_t *buf,
737                               hb_sync_audio_t *sync, hb_fifo_t *fifo, int i )
738 {
739     int64_t start = sync->next_start;
740     int64_t duration = buf->stop - buf->start;
741
742     sync->next_pts += duration;
743
744     if( audio->config.in.samplerate == audio->config.out.samplerate ||
745         audio->config.out.codec == HB_ACODEC_AC3 ||
746         audio->config.out.codec == HB_ACODEC_DCA )
747     {
748         /*
749          * If we don't have to do sample rate conversion or this audio is 
750          * pass-thru just send the input buffer downstream after adjusting
751          * its timestamps to make the output stream continuous.
752          */
753     }
754     else
755     {
756         /* Not pass-thru - do sample rate conversion */
757         int count_in, count_out;
758         hb_buffer_t * buf_raw = buf;
759         int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
760                             sizeof( float );
761
762         count_in  = buf_raw->size / channel_count;
763         /*
764          * When using stupid rates like 44.1 there will always be some
765          * truncation error. E.g., a 1536 sample AC3 frame will turn into a
766          * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
767          * the error will build up over time and eventually the audio will
768          * substantially lag the video. libsamplerate will keep track of the
769          * fractional sample & give it to us when appropriate if we give it
770          * an extra sample of space in the output buffer.
771          */
772         count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
773
774         sync->data.input_frames = count_in;
775         sync->data.output_frames = count_out;
776         sync->data.src_ratio = (double)audio->config.out.samplerate /
777                                (double)audio->config.in.samplerate;
778
779         buf = hb_buffer_init( count_out * channel_count );
780         sync->data.data_in  = (float *) buf_raw->data;
781         sync->data.data_out = (float *) buf->data;
782         if( src_process( sync->state, &sync->data ) )
783         {
784             /* XXX If this happens, we're screwed */
785             hb_log( "sync: audio %d src_process failed", i );
786         }
787         hb_buffer_close( &buf_raw );
788
789         buf->size = sync->data.output_frames_gen * channel_count;
790         duration = ( sync->data.output_frames_gen * 90000 ) /
791                    audio->config.out.samplerate;
792     }
793     buf->frametype = HB_FRAME_AUDIO;
794     buf->start = start;
795     buf->stop  = start + duration;
796     sync->next_start = start + duration;
797     hb_fifo_push( fifo, buf );
798 }
799
800 /***********************************************************************
801  * SyncAudio
802  ***********************************************************************
803  *
804  **********************************************************************/
805 static void SyncAudio( hb_work_object_t * w, int i )
806 {
807     hb_work_private_t * pv = w->private_data;
808     hb_job_t        * job = pv->job;
809     hb_sync_audio_t * sync = &pv->sync_audio[i];
810     hb_audio_t      * audio = sync->audio;
811     hb_buffer_t     * buf;
812     hb_fifo_t       * fifo;
813     int64_t start;
814
815     if( audio->config.out.codec == HB_ACODEC_AC3 ||
816         audio->config.out.codec == HB_ACODEC_DCA )
817     {
818         fifo = audio->priv.fifo_out;
819     }
820     else
821     {
822         fifo = audio->priv.fifo_sync;
823     }
824
825     while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->priv.fifo_raw ) ) )
826     {
827         start = buf->start - pv->audio_passthru_slip;
828         /* if the next buffer is an eof send it downstream */
829         if ( buf->size <= 0 )
830         {
831             buf = hb_fifo_get( audio->priv.fifo_raw );
832             hb_fifo_push( fifo, buf );
833             pv->busy &=~ (1 << (i + 1) );
834             return;
835         }
836         if( job->frame_to_stop && pv->count_frames >= job->frame_to_stop )
837         {
838             hb_fifo_push( fifo, hb_buffer_init(0) );
839             pv->busy &=~ (1 << (i + 1) );
840             return;
841         }
842         if ( (int64_t)( start - sync->next_pts ) < 0 )
843         {
844             // audio time went backwards.
845             // If our output clock is more than a half frame ahead of the
846             // input clock drop this frame to move closer to sync.
847             // Otherwise drop frames until the input clock matches the output clock.
848             if ( sync->first_drop || sync->next_start - start > 90*15 )
849             {
850                 // Discard data that's in the past.
851                 if ( sync->first_drop == 0 )
852                 {
853                     sync->first_drop = sync->next_pts;
854                 }
855                 ++sync->drop_count;
856                 buf = hb_fifo_get( audio->priv.fifo_raw );
857                 hb_buffer_close( &buf );
858                 continue;
859             }
860             sync->next_pts = start;
861         }
862         if ( sync->first_drop )
863         {
864             // we were dropping old data but input buf time is now current
865             hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
866                     "(next %lld, current %lld)", i,
867                     (int)( sync->next_pts - sync->first_drop ) / 90,
868                     sync->drop_count, sync->first_drop, sync->next_pts );
869             sync->first_drop = 0;
870             sync->drop_count = 0;
871             sync->next_pts = start;
872         }
873         if ( start - sync->next_pts >= (90 * 70) )
874         {
875             if ( start - sync->next_pts > (90000LL * 60) )
876             {
877                 // there's a gap of more than a minute between the last
878                 // frame and this. assume we got a corrupted timestamp
879                 // and just drop the next buf.
880                 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
881                         "  start %lld, next %lld",
882                         (int)((start - sync->next_pts) / (90000*60)),
883                         i, start, sync->next_pts );
884                 buf = hb_fifo_get( audio->priv.fifo_raw );
885                 hb_buffer_close( &buf );
886                 continue;
887             }
888             /*
889              * there's a gap of at least 70ms between the last
890              * frame we processed & the next. Fill it with silence.
891              * Or in the case of DCA, skip some frames from the
892              * other streams.
893              */
894             if( sync->audio->config.out.codec == HB_ACODEC_DCA )
895             {
896                 hb_log( "sync: audio gap %d ms. Skipping frames. Audio %d"
897                         "  start %lld, next %lld",
898                         (int)((start - sync->next_pts) / 90),
899                         i, start, sync->next_pts );
900                 pv->audio_passthru_slip += (start - sync->next_pts);
901                 return;
902             }
903             hb_log( "sync: adding %d ms of silence to audio %d"
904                     "  start %lld, next %lld",
905                     (int)((start - sync->next_pts) / 90),
906                     i, start, sync->next_pts );
907             InsertSilence( w, i, start - sync->next_pts );
908             return;
909         }
910
911         /*
912          * When we get here we've taken care of all the dups and gaps in the
913          * audio stream and are ready to inject the next input frame into
914          * the output stream.
915          */
916         buf = hb_fifo_get( audio->priv.fifo_raw );
917         OutputAudioFrame( job, audio, buf, sync, fifo, i );
918     }
919 }
920
921 static void InsertSilence( hb_work_object_t * w, int i, int64_t duration )
922 {
923     hb_work_private_t * pv = w->private_data;
924     hb_job_t        *job = pv->job;
925     hb_sync_audio_t *sync = &pv->sync_audio[i];
926     hb_buffer_t     *buf;
927     hb_fifo_t       *fifo;
928
929     // to keep pass-thru and regular audio in sync we generate silence in
930     // AC3 frame-sized units. If the silence duration isn't an integer multiple
931     // of the AC3 frame duration we will truncate or round up depending on
932     // which minimizes the timing error.
933     const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
934                           sync->audio->config.in.samplerate;
935     int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
936
937     while ( --frame_count >= 0 )
938     {
939         if( sync->audio->config.out.codec == HB_ACODEC_AC3 )
940         {
941             buf        = hb_buffer_init( sync->ac3_size );
942             buf->start = sync->next_pts;
943             buf->stop  = buf->start + frame_dur;
944             memcpy( buf->data, sync->ac3_buf, buf->size );
945             fifo = sync->audio->priv.fifo_out;
946         }
947         else
948         {
949             buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
950                                      HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
951                                          sync->audio->config.out.mixdown) );
952             buf->start = sync->next_pts;
953             buf->stop  = buf->start + frame_dur;
954             memset( buf->data, 0, buf->size );
955             fifo = sync->audio->priv.fifo_sync;
956         }
957         OutputAudioFrame( job, sync->audio, buf, sync, fifo, i );
958     }
959 }
960
961 static void UpdateState( hb_work_object_t * w )
962 {
963     hb_work_private_t * pv = w->private_data;
964     hb_state_t state;
965
966     if( !pv->count_frames )
967     {
968         pv->st_first = hb_get_date();
969     }
970     pv->count_frames++;
971
972     if( hb_get_date() > pv->st_dates[3] + 1000 )
973     {
974         memmove( &pv->st_dates[0], &pv->st_dates[1],
975                  3 * sizeof( uint64_t ) );
976         memmove( &pv->st_counts[0], &pv->st_counts[1],
977                  3 * sizeof( uint64_t ) );
978         pv->st_dates[3]  = hb_get_date();
979         pv->st_counts[3] = pv->count_frames;
980     }
981
982 #define p state.param.working
983     state.state = HB_STATE_WORKING;
984     p.progress  = (float) pv->count_frames / (float) pv->count_frames_max;
985     if( p.progress > 1.0 )
986     {
987         p.progress = 1.0;
988     }
989     p.rate_cur   = 1000.0 *
990         (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
991         (float) ( pv->st_dates[3] - pv->st_dates[0] );
992     if( hb_get_date() > pv->st_first + 4000 )
993     {
994         int eta;
995         p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
996             (float) ( pv->st_dates[3] - pv->st_first );
997         eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
998             p.rate_avg;
999         p.hours   = eta / 3600;
1000         p.minutes = ( eta % 3600 ) / 60;
1001         p.seconds = eta % 60;
1002     }
1003     else
1004     {
1005         p.rate_avg = 0.0;
1006         p.hours    = -1;
1007         p.minutes  = -1;
1008         p.seconds  = -1;
1009     }
1010 #undef p
1011
1012     hb_set_state( pv->job->h, &state );
1013 }