OSDN Git Service

Somehow this went missing as I prepared these subtitle changes for commit in 1011...
[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                     } else {
339                         break;
340                     }
341                 }
342             }
343
344             /* Trash current picture */
345             /* Also, make sure we don't trash a chapter break */
346             chap_break = cur->new_chap;
347             hb_buffer_close( &cur );
348             pv->cur = cur = hb_fifo_get( job->fifo_raw );
349             cur->new_chap |= chap_break; // Don't stomp existing chapter breaks
350
351             /* Calculate new offset */
352             pv->pts_offset_old = pv->pts_offset;
353             pv->pts_offset     = cur->start -
354                 pv->count_frames * pv->job->vrate_base / 300;
355
356             pv->video_sequence = cur->sequence;
357             continue;
358         }
359
360         /* Look for a subtitle for this frame */
361         if( pv->subtitle )
362         {
363             hb_buffer_t * sub2;
364             while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
365             {
366                 /* If two subtitles overlap, make the first one stop
367                    when the second one starts */
368                 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
369                 if( sub2 && sub->stop > sub2->start )
370                     sub->stop = sub2->start;
371
372                 // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld", 
373                 //       sub, cur->sequence, sub->sequence);
374
375                 if( sub->sequence > cur->sequence )
376                 {
377                     /*
378                      * The video is behind where we are, so wait until
379                      * it catches up to the same reader point on the
380                      * DVD. Then our PTS should be in the same region
381                      * as the video.
382                      */
383                     sub = NULL;
384                     break;
385                 }
386
387                 if( sub->stop > cur->start ) {
388                     /*
389                      * The stop time is in the future, so fall through
390                      * and we'll deal with it in the next block of
391                      * code.
392                      */
393                     break;
394                 } 
395                 else 
396                 {
397                     /*
398                      * The stop time is in the past. But is it due to
399                      * it having been played already, or has the PTS
400                      * been reset to 0?
401                      */
402                     if( ( cur->start - sub->stop ) > PTS_DISCONTINUITY_TOLERANCE ) {
403                         /*
404                          * There is a lot of time between our current
405                          * video and where this subtitle is ending,
406                          * assume that we are about to reset the PTS
407                          * and do not throw away this subtitle.
408                          */
409                         break;
410                     }
411                 }
412
413                 /* 
414                  * The subtitle is older than this picture, trash it 
415                  */
416                 sub = hb_fifo_get( pv->subtitle->fifo_raw );
417                 hb_buffer_close( &sub );
418             }
419
420             /*
421              * There is a valid subtitle, is it time to display it?
422              */
423             if( sub )
424             {
425                 if( sub->stop > sub->start)
426                 {
427                     /*
428                      * Normal subtitle which ends after it starts, check to 
429                      * see that the current video is between the start and end.
430                      */
431                     if( cur->start > sub->start &&
432                         cur->start < sub->stop )
433                     {
434                         /*
435                          * We should be playing this, so leave the
436                          * subtitle in place.
437                          *
438                          * fall through to display
439                          */
440                     } 
441                     else
442                     {
443                         /*
444                          * Defer until the play point is within the subtitle
445                          */
446                         sub = NULL;
447                     }
448                 }
449                 else
450                 {
451                     /*
452                      * The end of the subtitle is less than the start, this is a
453                      * sign of a PTS discontinuity.
454                      */
455                     if( sub->start > cur->start )
456                     {
457                         /*
458                          * we haven't reached the start time yet, or
459                          * we have jumped backwards after having
460                          * already started this subtitle.
461                          */
462                         if( cur->start < sub->stop )
463                         {
464                             /*
465                              * We have jumped backwards and so should
466                              * continue displaying this subtitle.
467                              *
468                              * fall through to display.
469                              */
470                         } 
471                         else 
472                         {
473                             /*
474                              * Defer until the play point is within the subtitle
475                              */
476                             sub = NULL;
477                         }
478                     } else {
479                         /*
480                          * Play this subtitle as the start is greater than our
481                          * video point.
482                          *
483                          * fall through to display/
484                          */
485                     }
486                 }
487             }
488         }
489
490         /* The PTS of the frame we are expecting now */
491         pts_expected = pv->pts_offset +
492             pv->count_frames * pv->job->vrate_base / 300;
493
494         //hb_log("Video expecting PTS %lld, current frame: %lld, next frame: %lld, cf: %lld", 
495         //       pts_expected, cur->start, next->start, pv->count_frames * pv->job->vrate_base / 300 );
496
497         if( cur->start < pts_expected - pv->job->vrate_base / 300 / 2 &&
498             next->start < pts_expected + pv->job->vrate_base / 300 / 2 )
499         {
500             /* The current frame is too old but the next one matches,
501                let's trash */
502             /* Also, make sure we don't trash a chapter break */
503             chap_break = cur->new_chap;
504             hb_buffer_close( &cur );
505             pv->cur = cur = hb_fifo_get( job->fifo_raw );
506             cur->new_chap |= chap_break; // Make sure we don't stomp the existing one.
507             
508             continue;
509         }
510
511         if( next->start > pts_expected + 3 * pv->job->vrate_base / 300 / 2 )
512         {
513             /* We'll need the current frame more than one time. Make a
514                copy of it and keep it */
515             buf_tmp = hb_buffer_init( cur->size );
516             memcpy( buf_tmp->data, cur->data, cur->size ); 
517             buf_tmp->sequence = cur->sequence;
518         }
519         else
520         {
521             /* The frame has the expected date and won't have to be
522                duplicated, just put it through */
523             buf_tmp = cur;
524             pv->cur = cur = hb_fifo_get( job->fifo_raw );
525         }
526         
527         /* Replace those MPEG-2 dates with our dates */
528         buf_tmp->start = (uint64_t) pv->count_frames *
529             pv->job->vrate_base / 300;
530         buf_tmp->stop  = (uint64_t) ( pv->count_frames + 1 ) *
531             pv->job->vrate_base / 300;
532
533         /* If we have a subtitle for this picture, copy it */
534         /* FIXME: we should avoid this memcpy */
535         if( sub )
536         {
537             buf_tmp->sub         = hb_buffer_init( sub->size );
538             buf_tmp->sub->x      = sub->x;
539             buf_tmp->sub->y      = sub->y;
540             buf_tmp->sub->width  = sub->width;
541             buf_tmp->sub->height = sub->height;
542             memcpy( buf_tmp->sub->data, sub->data, sub->size );
543         }
544
545         /* Push the frame to the renderer */
546         hb_fifo_push( job->fifo_sync, buf_tmp );
547
548         /* Update UI */
549         UpdateState( w );
550
551         /* Make sure we won't get more frames then expected */
552         if( pv->count_frames >= pv->count_frames_max )
553         {
554             hb_log( "sync: got %lld frames", pv->count_frames );
555             pv->done = 1;
556             
557            // Drop an empty buffer into our output to ensure that things
558            // get flushed all the way out.
559            buf_tmp = hb_buffer_init(0); // Empty end buffer
560            hb_fifo_push( job->fifo_sync, buf_tmp );
561             
562             break;
563         }
564     }
565
566     return HB_WORK_OK;
567 }
568
569 /***********************************************************************
570  * SyncAudio
571  ***********************************************************************
572  * 
573  **********************************************************************/
574 static void SyncAudio( hb_work_object_t * w, int i )
575 {
576     hb_work_private_t * pv = w->private_data;
577     hb_job_t        * job;
578     hb_audio_t      * audio;
579     hb_buffer_t     * buf;
580     hb_sync_audio_t * sync;
581
582     hb_fifo_t       * fifo;
583     int               rate;
584
585     int64_t           pts_expected;
586     int64_t           start;
587
588     job    = pv->job;
589     sync   = &pv->sync_audio[i];
590     audio  = sync->audio;
591
592     if( job->acodec & HB_ACODEC_AC3 )
593     {
594         fifo = audio->fifo_out;
595         rate = audio->rate;
596     }
597     else
598     {
599         fifo = audio->fifo_sync;
600         rate = job->arate;
601     }
602
603     while( !hb_fifo_is_full( fifo ) &&
604            ( buf = hb_fifo_see( audio->fifo_raw ) ) )
605     {
606         /* The PTS of the samples we are expecting now */
607         pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
608
609         // hb_log("Video Sequence: %lld, Audio Sequence: %lld", pv->video_sequence, buf->sequence);
610         /*
611          * Using the same logic as the Video have we crossed a VOB
612          * boundary as detected by the expected PTS and the PTS of our
613          * audio being out by more than the tolerance value.
614          */
615         if( ( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
616               buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE ) &&
617             pv->pts_offset_old > INT64_MIN )
618         {
619             /*
620              * Useful debug, but too verbose for normal use.
621              */
622             hb_log("Sync: Audio discontinuity (sequence: vid %lld aud %lld) (pts %lld < %lld < %lld)",
623                    pv->video_sequence, buf->sequence,
624                    pts_expected - PTS_DISCONTINUITY_TOLERANCE, buf->start,
625                    pts_expected + PTS_DISCONTINUITY_TOLERANCE );
626             
627             /* There has been a PTS discontinuity, and this frame might
628                be from before the discontinuity*/
629             pts_expected = pv->pts_offset_old + sync->count_frames *
630                 90000 / rate;
631
632             /*
633              * Is the audio from a valid period given the previous
634              * Video PTS. I.e. has there just been a video PTS
635              * discontinuity and this audio belongs to the vdeo from
636              * before?
637              */
638             if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||
639                 buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE )
640             {
641                 /*
642                  * It's outside of our tolerance for where the video
643                  * is now, and it's outside of the tolerance for
644                  * where we have been in the case of a VOB change.
645                  * Try and reconverge regardless. so continue on to
646                  * our convergence code below which will kick in as
647                  * it will be more than 100ms out.
648                  * 
649                  * Note that trashing the Audio could make things
650                  * worse if the Audio is in front because we will end
651                  * up diverging even more. We need to hold on to the
652                  * audio until the video catches up.
653                  */
654                 hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");
655                 
656                 /*
657                  * It wasn't from the old place, so we must be from
658                  * the new, but just too far out. So attempt to
659                  * reconverge by resetting the point we want to be to
660                  * where we are currently wanting to be.
661                  */
662                 pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate;
663                 start = pts_expected - pv->pts_offset;
664             } else {
665                  /* Use the older offset */
666                 start = pts_expected - pv->pts_offset_old;
667             }
668         }
669         else
670         {
671             start = pts_expected - pv->pts_offset;
672         }
673
674         /* Tolerance: 100 ms */
675         if( buf->start < pts_expected - 9000 )
676         {
677             /* Audio is behind the Video, trash it, can't use it now. */
678             hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",
679                       buf->start, pts_expected);
680             buf = hb_fifo_get( audio->fifo_raw );
681             hb_buffer_close( &buf );
682             continue;
683         }
684         else if( buf->start > pts_expected + 9000 )
685         {
686             /* Audio is ahead of the Video, insert silence until we catch up*/
687             hb_log("Sync: Audio PTS (%lld) >  Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);
688             InsertSilence( w, i );
689             continue;
690         }
691
692         if( job->acodec & HB_ACODEC_AC3 )
693         {
694             buf        = hb_fifo_get( audio->fifo_raw );
695             buf->start = start;
696             buf->stop  = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
697
698             sync->count_frames += AC3_SAMPLES_PER_FRAME;
699         }
700         else
701         {
702             hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
703
704             int count_in, count_out;
705
706             count_in  = buf_raw->size / HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) / sizeof( float );
707             count_out = ( buf_raw->stop - buf_raw->start ) * job->arate / 90000;
708             if( buf->start < pts_expected - 1500 )
709                 count_out--;
710             else if( buf->start > pts_expected + 1500 )
711                 count_out++;
712
713             sync->data.data_in      = (float *) buf_raw->data;
714             sync->data.input_frames = count_in;
715             sync->data.output_frames = count_out;
716
717             sync->data.src_ratio = (double) sync->data.output_frames /
718                                    (double) sync->data.input_frames;
719
720             buf = hb_buffer_init( sync->data.output_frames * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) *
721                                   sizeof( float ) );
722             sync->data.data_out = (float *) buf->data;
723             if( src_process( sync->state, &sync->data ) )
724             {
725                 /* XXX If this happens, we're screwed */
726                 hb_log( "sync: src_process failed" );
727             }
728             hb_buffer_close( &buf_raw );
729
730             buf->size = sync->data.output_frames_gen * HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->amixdown) * sizeof( float );
731
732             /* Set dates for resampled data */
733             buf->start = start;
734             buf->stop  = start + sync->data.output_frames_gen *
735                             90000 / job->arate;
736
737             sync->count_frames += sync->data.output_frames_gen;
738         }
739
740         buf->frametype = HB_FRAME_AUDIO;
741         hb_fifo_push( fifo, buf );
742     }
743
744     if( NeedSilence( w, audio ) )
745     {
746         InsertSilence( w, i );
747     }
748 }
749
750 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
751 {
752     hb_work_private_t * pv = w->private_data;
753     hb_job_t * job = pv->job;
754
755     if( hb_fifo_size( audio->fifo_in ) ||
756         hb_fifo_size( audio->fifo_raw ) ||
757         hb_fifo_size( audio->fifo_sync ) ||
758         hb_fifo_size( audio->fifo_out ) )
759     {
760         /* We have some audio, we are fine */
761         return 0;
762     }
763
764     /* No audio left in fifos */
765
766     if( hb_thread_has_exited( job->reader ) )
767     {
768         /* We might miss some audio to complete encoding and muxing
769            the video track */
770         hb_log("Reader has exited early, inserting silence.");
771         return 1;
772     }
773
774     if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
775         hb_fifo_is_full( job->fifo_raw ) &&
776         hb_fifo_is_full( job->fifo_sync ) &&
777         hb_fifo_is_full( job->fifo_render ) &&
778         hb_fifo_is_full( job->fifo_mpeg4 ) )
779     {
780         /* Too much video and no audio, oh-oh */
781         hb_log("Still got some video - and nothing in the audio fifo, insert silence");
782         return 1;
783     }
784
785     return 0;
786 }
787
788 static void InsertSilence( hb_work_object_t * w, int i )
789 {
790     hb_work_private_t * pv = w->private_data;
791     hb_job_t        * job;
792     hb_sync_audio_t * sync;
793     hb_buffer_t     * buf;
794
795     job    = pv->job;
796     sync   = &pv->sync_audio[i];
797
798     if( job->acodec & HB_ACODEC_AC3 )
799     {
800         buf        = hb_buffer_init( sync->ac3_size );
801         buf->start = sync->count_frames * 90000 / sync->audio->rate;
802         buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
803                      sync->audio->rate;
804         memcpy( buf->data, sync->ac3_buf, buf->size );
805
806         hb_log( "sync: adding a silent AC-3 frame for track %x",
807                 sync->audio->id );
808         hb_fifo_push( sync->audio->fifo_out, buf );
809
810         sync->count_frames += AC3_SAMPLES_PER_FRAME;
811
812     }
813     else
814     {
815         buf        = hb_buffer_init( HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->amixdown) * job->arate / 20 *
816                                      sizeof( float ) );
817         buf->start = sync->count_frames * 90000 / job->arate;
818         buf->stop  = buf->start + 90000 / 20;
819         memset( buf->data, 0, buf->size );
820
821         hb_log( "sync: adding 50 ms of silence for track %x",
822                 sync->audio->id );
823         hb_fifo_push( sync->audio->fifo_sync, buf );
824
825         sync->count_frames += job->arate / 20;
826     }
827 }
828
829 static void UpdateState( hb_work_object_t * w )
830 {
831     hb_work_private_t * pv = w->private_data;
832     hb_state_t state;
833
834     if( !pv->count_frames )
835     {
836         pv->st_first = hb_get_date();
837     }
838     pv->count_frames++;
839
840     if( hb_get_date() > pv->st_dates[3] + 1000 )
841     {
842         memmove( &pv->st_dates[0], &pv->st_dates[1],
843                  3 * sizeof( uint64_t ) );
844         memmove( &pv->st_counts[0], &pv->st_counts[1],
845                  3 * sizeof( uint64_t ) );
846         pv->st_dates[3]  = hb_get_date();
847         pv->st_counts[3] = pv->count_frames;
848     } 
849
850 #define p state.param.working
851     state.state = HB_STATE_WORKING;
852     p.progress  = (float) pv->count_frames / (float) pv->count_frames_max;
853     if( p.progress > 1.0 )
854     {
855         p.progress = 1.0; 
856     }
857     p.rate_cur   = 1000.0 *
858         (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
859         (float) ( pv->st_dates[3] - pv->st_dates[0] );
860     if( hb_get_date() > pv->st_first + 4000 )
861     {
862         int eta;
863         p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
864             (float) ( pv->st_dates[3] - pv->st_first );
865         eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
866             p.rate_avg;
867         p.hours   = eta / 3600;
868         p.minutes = ( eta % 3600 ) / 60;
869         p.seconds = eta % 60;
870     }
871     else
872     {
873         p.rate_avg = 0.0;
874         p.hours    = -1;
875         p.minutes  = -1;
876         p.seconds  = -1;
877     }
878 #undef p
879
880     hb_set_state( pv->job->h, &state );
881 }