OSDN Git Service

Don't drop subtitles when crossing PTS discontinuities by using buffer sequence numbe...
[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.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8
9 #include "samplerate.h"
10 #include "ffmpeg/avcodec.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     int64_t      count_frames;
23     
24     /* Raw */
25     SRC_STATE  * state;
26     SRC_DATA     data;
27
28     /* AC-3 */
29     int          ac3_size;
30     uint8_t    * ac3_buf;
31
32 } hb_sync_audio_t;
33
34 struct hb_work_private_s
35 {
36     hb_job_t * job;
37     int        done;
38
39     /* Video */
40     hb_subtitle_t * subtitle;
41     int64_t pts_offset;
42     int64_t pts_offset_old;
43     int64_t count_frames;
44     int64_t count_frames_max;
45     int64_t video_sequence;
46     hb_buffer_t * cur; /* The next picture to process */
47
48     /* Audio */
49     hb_sync_audio_t sync_audio[8];
50
51     /* Statistics */
52     uint64_t st_counts[4];
53     uint64_t st_dates[4];
54     uint64_t st_first;
55 };
56
57 /***********************************************************************
58  * Local prototypes
59  **********************************************************************/
60 static void InitAudio( hb_work_object_t * w, int i );
61 static int  SyncVideo( hb_work_object_t * w );
62 static void SyncAudio( hb_work_object_t * w, int i );
63 static int  NeedSilence( hb_work_object_t * w, hb_audio_t * );
64 static void InsertSilence( hb_work_object_t * w, int i );
65 static void UpdateState( hb_work_object_t * w );
66
67 /***********************************************************************
68  * hb_work_sync_init
69  ***********************************************************************
70  * Initialize the work object
71  **********************************************************************/
72 int syncInit( hb_work_object_t * w, hb_job_t * job )
73 {
74     hb_title_t       * title = job->title;
75     hb_chapter_t     * chapter;
76     int                i;
77     uint64_t           duration;
78     hb_work_private_t * pv;
79
80     pv = calloc( 1, sizeof( hb_work_private_t ) );
81     w->private_data = pv;
82
83     pv->job            = job;
84     pv->pts_offset     = INT64_MIN;
85     pv->pts_offset_old = INT64_MIN;
86     pv->count_frames   = 0;
87
88     /* Calculate how many video frames we are expecting */
89     duration = 0;
90     for( i = job->chapter_start; i <= job->chapter_end; i++ )
91     {
92         chapter   = hb_list_item( title->list_chapter, i - 1 );
93         duration += chapter->duration;
94     }                                                                           
95     duration += 90000;
96         /* 1 second safety so we're sure we won't miss anything */
97     pv->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
98
99     hb_log( "sync: expecting %lld video frames", pv->count_frames_max );
100
101     /* Initialize libsamplerate for every audio track we have */
102     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
103     {
104         InitAudio( w, i );
105     }
106
107     /* Get subtitle info, if any */
108     pv->subtitle = hb_list_item( title->list_subtitle, 0 );
109
110     pv->video_sequence = 0;
111
112     return 0;
113 }
114
115 /***********************************************************************
116  * Close
117  ***********************************************************************
118  *
119  **********************************************************************/
120 void syncClose( hb_work_object_t * w )
121 {
122     hb_work_private_t * pv = w->private_data;
123     hb_job_t          * job   = pv->job;
124     hb_title_t        * title = job->title;
125     
126     int i;
127
128     if( pv->cur ) hb_buffer_close( &pv->cur );
129
130     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
131     {
132         if( job->acodec & HB_ACODEC_AC3 )
133         {
134             free( pv->sync_audio[i].ac3_buf );
135         }
136         else
137         {
138             src_delete( pv->sync_audio[i].state );
139         }
140     }
141     
142     free( pv );
143     w->private_data = NULL;
144 }
145
146 /***********************************************************************
147  * Work
148  ***********************************************************************
149  * The root routine of this work abject
150  *
151  * The way this works is that we are syncing the audio to the PTS of
152  * the last video that we processed. That's why we skip the audio sync
153  * if we haven't got a valid PTS from the video yet.
154  *
155  **********************************************************************/
156 int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
157               hb_buffer_t ** unused2 )
158 {
159     hb_work_private_t * pv = w->private_data;
160     int i;
161
162     /* If we ever got a video frame, handle audio now */
163     if( pv->pts_offset != INT64_MIN )
164     {
165         for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
166         {
167             SyncAudio( w, i );
168         }
169     }
170
171     /* Handle video */
172     return SyncVideo( w );
173 }
174
175 hb_work_object_t hb_sync =
176 {
177     WORK_SYNC,
178     "Synchronization",
179     syncInit,
180     syncWork,
181     syncClose
182 };
183
184 static void InitAudio( hb_work_object_t * w, int i )
185 {
186     hb_work_private_t * pv = w->private_data;
187     hb_job_t        * job   = pv->job;
188     hb_title_t      * title = job->title;
189     hb_sync_audio_t * sync;
190
191     sync        = &pv->sync_audio[i];
192     sync->audio = hb_list_item( title->list_audio, i );
193
194     if( job->acodec & HB_ACODEC_AC3 )
195     {
196         /* Have a silent AC-3 frame ready in case we have to fill a
197            gap */
198         AVCodec        * codec;
199         AVCodecContext * c;
200         short          * zeros;
201
202         codec = avcodec_find_encoder( CODEC_ID_AC3 );
203         c     = avcodec_alloc_context();
204
205         c->bit_rate    = sync->audio->bitrate;
206         c->sample_rate = sync->audio->rate;
207         c->channels    = 2;
208
209         if( avcodec_open( c, codec ) < 0 )
210         {
211             hb_log( "sync: avcodec_open failed" );
212             return;
213         }
214
215         zeros          = calloc( AC3_SAMPLES_PER_FRAME *
216                                  sizeof( short ) * c->channels, 1 );
217         sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /
218                              sync->audio->rate / 8;
219         sync->ac3_buf  = malloc( sync->ac3_size );
220
221         if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
222                                   zeros ) != sync->ac3_size )
223         {
224             hb_log( "sync: avcodec_encode_audio failed" );
225         }
226         
227         free( zeros );
228         avcodec_close( c );
229         av_free( c );
230     }
231     else
232     {
233         /* Initialize libsamplerate */
234         int error;
235         sync->state             = src_new( SRC_LINEAR, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown), &error );
236         sync->data.end_of_input = 0;
237     }
238 }
239
240
241
242 #define PTS_DISCONTINUITY_TOLERANCE 90000
243
244 /***********************************************************************
245  * SyncVideo
246  ***********************************************************************
247  * 
248  **********************************************************************/
249 static int SyncVideo( hb_work_object_t * w )
250 {
251     hb_work_private_t * pv = w->private_data;
252     hb_buffer_t * cur, * next, * sub = NULL;
253     hb_job_t * job = pv->job;
254     int64_t pts_expected;
255     int chap_break;
256
257     if( pv->done )
258     {
259         return HB_WORK_DONE;
260     }
261
262     if( hb_thread_has_exited( job->reader ) &&
263         !hb_fifo_size( job->fifo_mpeg2 ) &&
264         !hb_fifo_size( job->fifo_raw ) )
265     {
266         /* All video data has been processed already, we won't get
267            more */
268         hb_log( "sync: got %lld frames, %lld expected",
269                 pv->count_frames, pv->count_frames_max );
270         pv->done = 1;
271         
272         hb_buffer_t * buf_tmp;
273
274        // Drop an empty buffer into our output to ensure that things
275        // get flushed all the way out.
276         buf_tmp = hb_buffer_init(0); // Empty end buffer
277         hb_fifo_push( job->fifo_sync, buf_tmp );
278         
279         return HB_WORK_DONE;
280     }
281
282     if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
283     {
284         /* We haven't even got a frame yet */
285         return HB_WORK_OK;
286     }
287     cur = pv->cur;
288
289     /* At this point we have a frame to process. Let's check
290         1) if we will be able to push into the fifo ahead
291         2) if the next frame is there already, since we need it to
292            know whether we'll have to repeat the current frame or not */
293     while( !hb_fifo_is_full( job->fifo_sync ) &&
294            ( next = hb_fifo_see( job->fifo_raw ) ) )
295     {
296         hb_buffer_t * buf_tmp;
297
298         if( pv->pts_offset == INT64_MIN )
299         {
300             /* This is our first frame */
301             hb_log( "sync: first pts is %lld", cur->start );
302             pv->pts_offset = cur->start;
303         }
304
305         /*
306
307          * Track the video sequence number localy so that we can sync the audio
308          * to it using the sequence number as well as the PTS.
309          */
310         pv->video_sequence = cur->sequence;
311
312         /* Check for PTS jumps over 0.5 second */
313         if( next->start < cur->start - PTS_DISCONTINUITY_TOLERANCE ||
314             next->start > cur->start + PTS_DISCONTINUITY_TOLERANCE )
315         {
316             hb_log( "Sync: Video PTS discontinuity (current buffer start=%lld, next buffer start=%lld), trash Video",
317                     cur->start, next->start );
318             
319             /*
320              * Do we need to trash the subtitle, is it from the next->start period
321              * or is it from our old position. If the latter then trash it.
322              */
323             if( pv->subtitle )
324             {
325                 while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
326                 {
327                     if( ( sub->start > ( cur->start - PTS_DISCONTINUITY_TOLERANCE ) ) &&
328                         ( sub->start < ( cur->start + PTS_DISCONTINUITY_TOLERANCE ) ) )
329                     {
330                         /*
331                          * The subtitle is from our current time region which we are
332                          * jumping from. So trash it as we are about to jump backwards
333                          * or forwards and don't want it blocking the subtitle fifo.
334                          */
335                         hb_log("Trashing subtitle 0x%x due to PTS discontinuity", sub);
336                         sub = hb_fifo_get( pv->subtitle->fifo_raw );
337                         hb_buffer_close( &sub );
338                     }
339                 }
340             }
341
342             /* Trash current picture */
343             /* Also, make sure we don't trash a chapter break */
344             chap_break = cur->new_chap;
345             hb_buffer_close( &cur );
346             pv->cur = cur = hb_fifo_get( job->fifo_raw );
347             cur->new_chap |= chap_break; // Don't stomp existing chapter breaks
348
349             /* Calculate new offset */
350             pv->pts_offset_old = pv->pts_offset;
351             pv->pts_offset     = cur->start -
352                 pv->count_frames * pv->job->vrate_base / 300;
353
354             pv->video_sequence = cur->sequence;
355             continue;
356         }
357
358         /* Look for a subtitle for this frame */
359         if( pv->subtitle )
360         {
361             hb_buffer_t * sub2;
362             while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
363             {
364                 /* If two subtitles overlap, make the first one stop
365                    when the second one starts */
366                 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
367                 if( sub2 && sub->stop > sub2->start )
368                     sub->stop = sub2->start;
369
370                 // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld", 
371                 //       sub, cur->sequence, sub->sequence);
372
373                 if( sub->sequence > cur->sequence )
374                 {
375                     /*
376                      * The video is behind where we are, so wait until
377                      * it catches up to the same reader point on the
378                      * DVD. Then our PTS should be in the same region
379                      * as the video.
380                      */
381                     sub = NULL;
382                     break;
383                 }
384
385                 if( sub->stop > cur->start ) {
386                     /*
387                      * The stop time is in the future, so fall through
388                      * and we'll deal with it in the next block of
389                      * code.
390                      */
391                     break;
392                 } 
393                 else 
394                 {
395                     /*
396                      * The stop time is in the past. But is it due to
397                      * it having been played already, or has the PTS
398                      * been reset to 0?
399                      */
400                     if( ( cur->start - sub->stop ) > PTS_DISCONTINUITY_TOLERANCE ) {
401                         /*
402                          * There is a lot of time between our current
403                          * video and where this subtitle is ending,
404                          * assume that we are about to reset the PTS
405                          * and do not throw away this subtitle.
406                          */
407                         break;
408                     }
409                 }
410
411                 /* 
412                  * The subtitle is older than this picture, trash it 
413                  */
414                 sub = hb_fifo_get( pv->subtitle->fifo_raw );
415                 hb_buffer_close( &sub );
416             }
417
418             /*
419              * There is a valid subtitle, is it time to display it?
420              */
421             if( sub )
422             {
423                 if( sub->stop > sub->start)
424                 {
425                     /*
426                      * Normal subtitle which ends after it starts, check to 
427                      * see that the current video is between the start and end.
428                      */
429                     if( cur->start > sub->start &&
430                         cur->start < sub->stop )
431                     {
432                         /*
433                          * We should be playing this, so leave the
434                          * subtitle in place.
435                          *
436                          * fall through to display
437                          */
438                     } 
439                     else
440                     {
441                         /*
442                          * Defer until the play point is within the subtitle
443                          */
444                         sub = NULL;
445                     }
446                 }
447                 else
448                 {
449                     /*
450                      * The end of the subtitle is less than the start, this is a
451                      * sign of a PTS discontinuity.
452                      */
453                     if( sub->start > cur->start )
454                     {
455                         /*
456                          * we haven't reached the start time yet, or
457                          * we have jumped backwards after having
458                          * already started this subtitle.
459                          */
460                         if( cur->start < sub->stop )
461                         {
462                             /*
463                              * We have jumped backwards and so should
464                              * continue displaying this subtitle.
465                              *
466                              * fall through to display.
467                              */
468                         } 
469                         else 
470                         {
471                             /*
472                              * Defer until the play point is within the subtitle
473                              */
474                             sub = NULL;
475                         }
476                     } else {
477                         /*
478                          * Play this subtitle as the start is greater than our
479                          * video point.
480                          *
481                          * fall through to display/
482                          */
483                     }
484                 }
485             }
486         }
487
488         /* The PTS of the frame we are expecting now */
489         pts_expected = pv->pts_offset +
490             pv->count_frames * pv->job->vrate_base / 300;
491
492         //hb_log("Video expecting PTS %lld, current frame: %lld, next frame: %lld, cf: %lld", 
493         //       pts_expected, cur->start, next->start, pv->count_frames * pv->job->vrate_base / 300 );
494
495         if( cur->start < pts_expected - pv->job->vrate_base / 300 / 2 &&
496             next->start < pts_expected + pv->job->vrate_base / 300 / 2 )
497         {
498             /* The current frame is too old but the next one matches,
499                let's trash */
500             /* Also, make sure we don't trash a chapter break */
501             chap_break = cur->new_chap;
502             hb_buffer_close( &cur );
503             pv->cur = cur = hb_fifo_get( job->fifo_raw );
504             cur->new_chap |= chap_break; // Make sure we don't stomp the existing one.
505             
506             continue;
507         }
508
509         if( next->start > pts_expected + 3 * pv->job->vrate_base / 300 / 2 )
510         {
511             /* We'll need the current frame more than one time. Make a
512                copy of it and keep it */
513             buf_tmp = hb_buffer_init( cur->size );
514             memcpy( buf_tmp->data, cur->data, cur->size ); 
515             buf_tmp->sequence = cur->sequence;
516         }
517         else
518         {
519             /* The frame has the expected date and won't have to be
520                duplicated, just put it through */
521             buf_tmp = cur;
522             pv->cur = cur = hb_fifo_get( job->fifo_raw );
523         }
524         
525         /* Replace those MPEG-2 dates with our dates */
526         buf_tmp->start = (uint64_t) pv->count_frames *
527             pv->job->vrate_base / 300;
528         buf_tmp->stop  = (uint64_t) ( pv->count_frames + 1 ) *
529             pv->job->vrate_base / 300;
530
531         /* If we have a subtitle for this picture, copy it */
532         /* FIXME: we should avoid this memcpy */
533         if( sub )
534         {
535             buf_tmp->sub         = hb_buffer_init( sub->size );
536             buf_tmp->sub->x      = sub->x;
537             buf_tmp->sub->y      = sub->y;
538             buf_tmp->sub->width  = sub->width;
539             buf_tmp->sub->height = sub->height;
540             memcpy( buf_tmp->sub->data, sub->data, sub->size );
541         }
542
543         /* Push the frame to the renderer */
544         hb_fifo_push( job->fifo_sync, buf_tmp );
545
546         /* Update UI */
547         UpdateState( w );
548
549         /* Make sure we won't get more frames then expected */
550         if( pv->count_frames >= pv->count_frames_max )
551         {
552             hb_log( "sync: got %lld frames", pv->count_frames );
553             pv->done = 1;
554             
555            // Drop an empty buffer into our output to ensure that things
556            // get flushed all the way out.
557            buf_tmp = hb_buffer_init(0); // Empty end buffer
558            hb_fifo_push( job->fifo_sync, buf_tmp );
559             
560             break;
561         }
562     }
563
564     return HB_WORK_OK;
565 }
566
567 /***********************************************************************
568  * SyncAudio
569  ***********************************************************************
570  * 
571  **********************************************************************/
572 static void SyncAudio( hb_work_object_t * w, int i )
573 {
574     hb_work_private_t * pv = w->private_data;
575     hb_job_t        * job;
576     hb_audio_t      * audio;
577     hb_buffer_t     * buf;
578     hb_sync_audio_t * sync;
579
580     hb_fifo_t       * fifo;
581     int               rate;
582
583     int64_t           pts_expected;
584     int64_t           start;
585
586     job    = pv->job;
587     sync   = &pv->sync_audio[i];
588     audio  = sync->audio;
589
590     if( job->acodec & HB_ACODEC_AC3 )
591     {
592         fifo = audio->fifo_out;
593         rate = audio->rate;
594     }
595     else
596     {
597         fifo = audio->fifo_sync;
598         rate = job->arate;
599     }
600
601     while( !hb_fifo_is_full( fifo ) &&
602            ( buf = hb_fifo_see( audio->fifo_raw ) ) )
603     {
604         /* The PTS of the samples we are expecting now */
605         pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
606
607         // hb_log("Video Sequence: %lld, Audio Sequence: %lld", pv->video_sequence, buf->sequence);
608         /*
609          * Using the same logic as the Video have we crossed a VOB
610          * boundary as detected by the expected PTS and the PTS of our
611          * audio being out by more than the tolerance value.
612          */
613         if( ( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
614               buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE ) &&
615             pv->pts_offset_old > INT64_MIN )
616         {
617             /*
618              * Useful debug, but too verbose for normal use.
619              */
620             hb_log("Sync: Audio discontinuity (sequence: vid %lld aud %lld) (pts %lld < %lld < %lld)",
621                    pv->video_sequence, buf->sequence,
622                    pts_expected - PTS_DISCONTINUITY_TOLERANCE, buf->start,
623                    pts_expected + PTS_DISCONTINUITY_TOLERANCE );
624             
625             /* There has been a PTS discontinuity, and this frame might
626                be from before the discontinuity*/
627             pts_expected = pv->pts_offset_old + sync->count_frames *
628                 90000 / rate;
629
630             /*
631              * Is the audio from a valid period given the previous
632              * Video PTS. I.e. has there just been a video PTS
633              * discontinuity and this audio belongs to the vdeo from
634              * before?
635              */
636             if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
637                 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE )
638             {
639                 /*
640                  * It's outside of our tolerance for where the video
641                  * is now, and it's outside of the tolerance for
642                  * where we have been in the case of a VOB change.
643                  * Try and reconverge regardless. so continue on to
644                  * our convergence code below which will kick in as
645                  * it will be more than 100ms out.
646                  * 
647                  * Note that trashing the Audio could make things
648                  * worse if the Audio is in front because we will end
649                  * up diverging even more. We need to hold on to the
650                  * audio until the video catches up.
651                  */
652                 hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");
653                 
654                 /*
655                  * It wasn't from the old place, so we must be from
656                  * the new, but just too far out. So attempt to
657                  * reconverge by resetting the point we want to be to
658                  * where we are currently wanting to be.
659                  */
660                 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
661                 start = pts_expected - pv->pts_offset;
662             } else {
663                  /* Use the older offset */
664                 start = pts_expected - pv->pts_offset_old;
665             }
666         }
667         else
668         {
669             start = pts_expected - pv->pts_offset;
670         }
671
672         /* Tolerance: 100 ms */
673         if( buf->start < pts_expected - 9000 )
674         {
675             /* Audio is behind the Video, trash it, can't use it now. */
676             hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",
677                       buf->start, pts_expected);
678             buf = hb_fifo_get( audio->fifo_raw );
679             hb_buffer_close( &buf );
680             continue;
681         }
682         else if( buf->start > pts_expected + 9000 )
683         {
684             /* Audio is ahead of the Video, insert silence until we catch up*/
685             hb_log("Sync: Audio PTS (%lld) >  Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);
686             InsertSilence( w, i );
687             continue;
688         }
689
690         if( job->acodec & HB_ACODEC_AC3 )
691         {
692             buf        = hb_fifo_get( audio->fifo_raw );
693             buf->start = start;
694             buf->stop  = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
695
696             sync->count_frames += AC3_SAMPLES_PER_FRAME;
697         }
698         else
699         {
700             hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
701
702             int count_in, count_out;
703
704             count_in  = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );
705             count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
706             if( buf->start < pts_expected - 1500 )
707                 count_out--;
708             else if( buf->start > pts_expected + 1500 )
709                 count_out++;
710
711             sync->data.data_in      = (float *) buf_raw->data;
712             sync->data.input_frames = count_in;
713             sync->data.output_frames = count_out;
714
715             sync->data.src_ratio = (double) sync->data.output_frames /
716                                    (double) sync->data.input_frames;
717
718             buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *
719                                   sizeof( float ) );
720             sync->data.data_out = (float *) buf->data;
721             if( src_process( sync->state, &sync->data ) )
722             {
723                 /* XXX If this happens, we're screwed */
724                 hb_log( "sync: src_process failed" );
725             }
726             hb_buffer_close( &buf_raw );
727
728             buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );
729
730             /* Set dates for resampled data */
731             buf->start = start;
732             buf->stop  = start + sync->data.output_frames_gen *
733                             90000 / job->arate;
734
735             sync->count_frames += sync->data.output_frames_gen;
736         }
737
738         buf->frametype = HB_FRAME_AUDIO;
739         hb_fifo_push( fifo, buf );
740     }
741
742     if( NeedSilence( w, audio ) )
743     {
744         InsertSilence( w, i );
745     }
746 }
747
748 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
749 {
750     hb_work_private_t * pv = w->private_data;
751     hb_job_t * job = pv->job;
752
753     if( hb_fifo_size( audio->fifo_in ) ||
754         hb_fifo_size( audio->fifo_raw ) ||
755         hb_fifo_size( audio->fifo_sync ) ||
756         hb_fifo_size( audio->fifo_out ) )
757     {
758         /* We have some audio, we are fine */
759         return 0;
760     }
761
762     /* No audio left in fifos */
763
764     if( hb_thread_has_exited( job->reader ) )
765     {
766         /* We might miss some audio to complete encoding and muxing
767            the video track */
768         hb_log("Reader has exited early, inserting silence.");
769         return 1;
770     }
771
772     if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
773         hb_fifo_is_full( job->fifo_raw ) &&
774         hb_fifo_is_full( job->fifo_sync ) &&
775         hb_fifo_is_full( job->fifo_render ) &&
776         hb_fifo_is_full( job->fifo_mpeg4 ) )
777     {
778         /* Too much video and no audio, oh-oh */
779         hb_log("Still got some video - and nothing in the audio fifo, insert silence");
780         return 1;
781     }
782
783     return 0;
784 }
785
786 static void InsertSilence( hb_work_object_t * w, int i )
787 {
788     hb_work_private_t * pv = w->private_data;
789     hb_job_t        * job;
790     hb_sync_audio_t * sync;
791     hb_buffer_t     * buf;
792
793     job    = pv->job;
794     sync   = &pv->sync_audio[i];
795
796     if( job->acodec & HB_ACODEC_AC3 )
797     {
798         buf        = hb_buffer_init( sync->ac3_size );
799         buf->start = sync->count_frames * 90000 / sync->audio->rate;
800         buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
801                      sync->audio->rate;
802         memcpy( buf->data, sync->ac3_buf, buf->size );
803
804         hb_log( "sync: adding a silent AC-3 frame for track %x",
805                 sync->audio->id );
806         hb_fifo_push( sync->audio->fifo_out, buf );
807
808         sync->count_frames += AC3_SAMPLES_PER_FRAME;
809
810     }
811     else
812     {
813         buf        = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *
814                                      sizeof( float ) );
815         buf->start = sync->count_frames * 90000 / job->arate;
816         buf->stop  = buf->start + 90000 / 20;
817         memset( buf->data, 0, buf->size );
818
819         hb_log( "sync: adding 50 ms of silence for track %x",
820                 sync->audio->id );
821         hb_fifo_push( sync->audio->fifo_sync, buf );
822
823         sync->count_frames += job->arate / 20;
824     }
825 }
826
827 static void UpdateState( hb_work_object_t * w )
828 {
829     hb_work_private_t * pv = w->private_data;
830     hb_state_t state;
831
832     if( !pv->count_frames )
833     {
834         pv->st_first = hb_get_date();
835     }
836     pv->count_frames++;
837
838     if( hb_get_date() > pv->st_dates[3] + 1000 )
839     {
840         memmove( &pv->st_dates[0], &pv->st_dates[1],
841                  3 * sizeof( uint64_t ) );
842         memmove( &pv->st_counts[0], &pv->st_counts[1],
843                  3 * sizeof( uint64_t ) );
844         pv->st_dates[3]  = hb_get_date();
845         pv->st_counts[3] = pv->count_frames;
846     } 
847
848 #define p state.param.working
849     state.state = HB_STATE_WORKING;
850     p.progress  = (float) pv->count_frames / (float) pv->count_frames_max;
851     if( p.progress > 1.0 )
852     {
853         p.progress = 1.0; 
854     }
855     p.rate_cur   = 1000.0 *
856         (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
857         (float) ( pv->st_dates[3] - pv->st_dates[0] );
858     if( hb_get_date() > pv->st_first + 4000 )
859     {
860         int eta;
861         p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
862             (float) ( pv->st_dates[3] - pv->st_first );
863         eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
864             p.rate_avg;
865         p.hours   = eta / 3600;
866         p.minutes = ( eta % 3600 ) / 60;
867         p.seconds = eta % 60;
868     }
869     else
870     {
871         p.rate_avg = 0.0;
872         p.hours    = -1;
873         p.minutes  = -1;
874         p.seconds  = -1;
875     }
876 #undef p
877
878     hb_set_state( pv->job->h, &state );
879 }