OSDN Git Service

920a0e3889a7948acbeebe421d28755c8b8473df
[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     hb_subtitle_t * subtitle;
48     int64_t pts_offset;
49     int64_t next_start;         /* start time of next output frame */
50     int64_t next_pts;           /* start time of next input frame */
51     int64_t first_drop;         /* PTS of first 'went backwards' frame dropped */
52     int drop_count;             /* count of 'time went backwards' drops */
53     int drops;                  /* frames dropped to make a cbr video stream */
54     int dups;                   /* frames duplicated to make a cbr video stream */
55     int video_sequence;
56     int count_frames;
57     int count_frames_max;
58     int chap_mark;              /* to propagate chapter mark across a drop */
59     hb_buffer_t * cur; /* The next picture to process */
60
61     /* Audio */
62     hb_sync_audio_t sync_audio[8];
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++ )
128         {
129             pv->busy |= ( 1 << (i + 1) );
130             InitAudio( w, i );
131         }
132     }
133
134     /* Get subtitle info, if any */
135     pv->subtitle = hb_list_item( title->list_subtitle, 0 );
136
137     return 0;
138 }
139
140 /***********************************************************************
141  * Close
142  ***********************************************************************
143  *
144  **********************************************************************/
145 void syncClose( hb_work_object_t * w )
146 {
147     hb_work_private_t * pv = w->private_data;
148     hb_job_t          * job   = pv->job;
149     hb_title_t        * title = job->title;
150     hb_audio_t        * audio = NULL;
151     int i;
152
153     if( pv->cur )
154     {
155         hb_buffer_close( &pv->cur );
156     }
157
158     hb_log( "sync: got %d frames, %d expected",
159             pv->count_frames, pv->count_frames_max );
160
161     if (pv->drops || pv->dups )
162     {
163         hb_log( "sync: %d frames dropped, %d duplicated", pv->drops, pv->dups );
164     }
165
166     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
167     {
168         audio = hb_list_item( title->list_audio, i );
169         if( audio->config.out.codec == HB_ACODEC_AC3 )
170         {
171             free( pv->sync_audio[i].ac3_buf );
172         }
173         else
174         {
175             src_delete( pv->sync_audio[i].state );
176         }
177     }
178
179     free( pv );
180     w->private_data = NULL;
181 }
182
183 /***********************************************************************
184  * Work
185  ***********************************************************************
186  * The root routine of this work abject
187  *
188  * The way this works is that we are syncing the audio to the PTS of
189  * the last video that we processed. That's why we skip the audio sync
190  * if we haven't got a valid PTS from the video yet.
191  *
192  **********************************************************************/
193 int syncWork( hb_work_object_t * w, hb_buffer_t ** unused1,
194               hb_buffer_t ** unused2 )
195 {
196     hb_work_private_t * pv = w->private_data;
197     int i;
198
199     if ( pv->busy & 1 )
200         SyncVideo( w );
201
202     for( i = 0; i < hb_list_count( pv->job->title->list_audio ); i++ )
203     {
204         if ( pv->busy & ( 1 << (i + 1) ) )
205             SyncAudio( w, i );
206     }
207
208     return ( pv->busy? HB_WORK_OK : HB_WORK_DONE );
209 }
210
211 hb_work_object_t hb_sync =
212 {
213     WORK_SYNC,
214     "Synchronization",
215     syncInit,
216     syncWork,
217     syncClose
218 };
219
220 static void InitAudio( hb_work_object_t * w, int i )
221 {
222     hb_work_private_t * pv = w->private_data;
223     hb_job_t        * job   = pv->job;
224     hb_title_t      * title = job->title;
225     hb_sync_audio_t * sync;
226
227     sync        = &pv->sync_audio[i];
228     sync->audio = hb_list_item( title->list_audio, i );
229
230     if( sync->audio->config.out.codec == HB_ACODEC_AC3 )
231     {
232         /* Have a silent AC-3 frame ready in case we have to fill a
233            gap */
234         AVCodec        * codec;
235         AVCodecContext * c;
236         short          * zeros;
237
238         codec = avcodec_find_encoder( CODEC_ID_AC3 );
239         c     = avcodec_alloc_context();
240
241         c->bit_rate    = sync->audio->config.in.bitrate;
242         c->sample_rate = sync->audio->config.in.samplerate;
243         c->channels    = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( sync->audio->config.in.channel_layout );
244
245         if( hb_avcodec_open( c, codec ) < 0 )
246         {
247             hb_log( "sync: avcodec_open failed" );
248             return;
249         }
250
251         zeros          = calloc( AC3_SAMPLES_PER_FRAME *
252                                  sizeof( short ) * c->channels, 1 );
253         sync->ac3_size = sync->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
254                              sync->audio->config.in.samplerate / 8;
255         sync->ac3_buf  = malloc( sync->ac3_size );
256
257         if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
258                                   zeros ) != sync->ac3_size )
259         {
260             hb_log( "sync: avcodec_encode_audio failed" );
261         }
262
263         free( zeros );
264         hb_avcodec_close( c );
265         av_free( c );
266     }
267     else
268     {
269         /* Initialize libsamplerate */
270         int error;
271         sync->state             = src_new( SRC_SINC_MEDIUM_QUALITY, HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(sync->audio->config.out.mixdown), &error );
272         sync->data.end_of_input = 0;
273     }
274 }
275
276 /***********************************************************************
277  * SyncVideo
278  ***********************************************************************
279  *
280  **********************************************************************/
281 static void SyncVideo( hb_work_object_t * w )
282 {
283     hb_work_private_t * pv = w->private_data;
284     hb_buffer_t * cur, * next, * sub = NULL;
285     hb_job_t * job = pv->job;
286
287     if( !pv->cur && !( pv->cur = hb_fifo_get( job->fifo_raw ) ) )
288     {
289         /* We haven't even got a frame yet */
290         return;
291     }
292     cur = pv->cur;
293     if( cur->size == 0 )
294     {
295         /* we got an end-of-stream. Feed it downstream & signal that we're done. */
296         hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
297         pv->busy &=~ 1;
298         return;
299     }
300
301     /* At this point we have a frame to process. Let's check
302         1) if we will be able to push into the fifo ahead
303         2) if the next frame is there already, since we need it to
304            compute the duration of the current frame*/
305     while( !hb_fifo_is_full( job->fifo_sync ) &&
306            ( next = hb_fifo_see( job->fifo_raw ) ) )
307     {
308         hb_buffer_t * buf_tmp;
309
310         if( next->size == 0 )
311         {
312             /* we got an end-of-stream. Feed it downstream & signal that
313              * we're done. Note that this means we drop the final frame of
314              * video (we don't know its duration). On DVDs the final frame
315              * is often strange and dropping it seems to be a good idea. */
316             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
317             pv->busy &=~ 1;
318             return;
319         }
320         if( pv->pts_offset == INT64_MIN )
321         {
322             /* This is our first frame */
323             pv->pts_offset = 0;
324             if ( cur->start != 0 )
325             {
326                 /*
327                  * The first pts from a dvd should always be zero but
328                  * can be non-zero with a transport or program stream since
329                  * we're not guaranteed to start on an IDR frame. If we get
330                  * a non-zero initial PTS extend its duration so it behaves
331                  * as if it started at zero so that our audio timing will
332                  * be in sync.
333                  */
334                 hb_log( "sync: first pts is %lld", cur->start );
335                 cur->start = 0;
336             }
337         }
338
339         if( cur->new_chap ) {
340             hb_log("sync got new chapter %d", cur->new_chap );
341         }
342
343         /*
344          * since the first frame is always 0 and the upstream reader code
345          * is taking care of adjusting for pts discontinuities, we just have
346          * to deal with the next frame's start being in the past. This can
347          * happen when the PTS is adjusted after data loss but video frame
348          * reordering causes some frames with the old clock to appear after
349          * the clock change. This creates frames that overlap in time which
350          * looks to us like time going backward. The downstream muxing code
351          * can deal with overlaps of up to a frame time but anything larger
352          * we handle by dropping frames here.
353          */
354         if ( (int64_t)( next->start - cur->start ) <= 0 )
355         {
356             if ( pv->first_drop == 0 )
357             {
358                 pv->first_drop = next->start;
359             }
360             ++pv->drop_count;
361             buf_tmp = hb_fifo_get( job->fifo_raw );
362             if ( buf_tmp->new_chap )
363             {
364                 // don't drop a chapter mark when we drop the buffer
365                 pv->chap_mark = buf_tmp->new_chap;
366             }
367             hb_buffer_close( &buf_tmp );
368             continue;
369         }
370         if ( pv->first_drop )
371         {
372             hb_log( "sync: video time didn't advance - dropped %d frames "
373                     "(delta %d ms, current %lld, next %lld, dur %d)",
374                     pv->drop_count, (int)( cur->start - pv->first_drop ) / 90,
375                     cur->start, next->start, (int)( next->start - cur->start ) );
376             pv->first_drop = 0;
377             pv->drop_count = 0;
378         }
379
380         /*
381          * Track the video sequence number localy so that we can sync the audio
382          * to it using the sequence number as well as the PTS.
383          */
384         pv->video_sequence = cur->sequence;
385
386         /* Look for a subtitle for this frame */
387         if( pv->subtitle )
388         {
389             hb_buffer_t * sub2;
390             while( ( sub = hb_fifo_see( pv->subtitle->fifo_raw ) ) )
391             {
392                 /* If two subtitles overlap, make the first one stop
393                    when the second one starts */
394                 sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
395                 if( sub2 && sub->stop > sub2->start )
396                     sub->stop = sub2->start;
397
398                 // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld",
399                 //       sub, cur->sequence, sub->sequence);
400
401                 if( sub->sequence > cur->sequence )
402                 {
403                     /*
404                      * The video is behind where we are, so wait until
405                      * it catches up to the same reader point on the
406                      * DVD. Then our PTS should be in the same region
407                      * as the video.
408                      */
409                     sub = NULL;
410                     break;
411                 }
412
413                 if( sub->stop > cur->start ) {
414                     /*
415                      * The stop time is in the future, so fall through
416                      * and we'll deal with it in the next block of
417                      * code.
418                      */
419                     break;
420                 }
421
422                 /*
423                  * The subtitle is older than this picture, trash it
424                  */
425                 sub = hb_fifo_get( pv->subtitle->fifo_raw );
426                 hb_buffer_close( &sub );
427             }
428
429             /*
430              * There is a valid subtitle, is it time to display it?
431              */
432             if( sub )
433             {
434                 if( sub->stop > sub->start)
435                 {
436                     /*
437                      * Normal subtitle which ends after it starts, check to
438                      * see that the current video is between the start and end.
439                      */
440                     if( cur->start > sub->start &&
441                         cur->start < sub->stop )
442                     {
443                         /*
444                          * We should be playing this, so leave the
445                          * subtitle in place.
446                          *
447                          * fall through to display
448                          */
449                         if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
450                         {
451                             /*
452                              * Subtitle is on for less than three seconds, extend
453                              * the time that it is displayed to make it easier
454                              * to read. Make it 3 seconds or until the next
455                              * subtitle is displayed.
456                              *
457                              * This is in response to Indochine which only
458                              * displays subs for 1 second - too fast to read.
459                              */
460                             sub->stop = sub->start + ( 3 * 90000 );
461
462                             sub2 = hb_fifo_see2( pv->subtitle->fifo_raw );
463
464                             if( sub2 && sub->stop > sub2->start )
465                             {
466                                 sub->stop = sub2->start;
467                             }
468                         }
469                     }
470                     else
471                     {
472                         /*
473                          * Defer until the play point is within the subtitle
474                          */
475                         sub = NULL;
476                     }
477                 }
478                 else
479                 {
480                     /*
481                      * The end of the subtitle is less than the start, this is a
482                      * sign of a PTS discontinuity.
483                      */
484                     if( sub->start > cur->start )
485                     {
486                         /*
487                          * we haven't reached the start time yet, or
488                          * we have jumped backwards after having
489                          * already started this subtitle.
490                          */
491                         if( cur->start < sub->stop )
492                         {
493                             /*
494                              * We have jumped backwards and so should
495                              * continue displaying this subtitle.
496                              *
497                              * fall through to display.
498                              */
499                         }
500                         else
501                         {
502                             /*
503                              * Defer until the play point is within the subtitle
504                              */
505                             sub = NULL;
506                         }
507                     } else {
508                         /*
509                          * Play this subtitle as the start is greater than our
510                          * video point.
511                          *
512                          * fall through to display/
513                          */
514                     }
515                 }
516             }
517         }
518
519         int64_t duration;
520         if ( job->mux & HB_MUX_AVI || job->cfr )
521         {
522             /*
523              * The concept of variable frame rate video was a bit too advanced
524              * for Microsoft so AVI doesn't support it. Since almost all dvd
525              * video is VFR we have to convert it to constant frame rate to
526              * put it in an AVI container. So here we duplicate, drop and
527              * otherwise trash video frames to appease the gods of Redmond.
528              */
529
530             /* mpeg durations are exact when expressed in ticks of the
531              * 27MHz System clock but not in HB's 90KHz PTS clock. To avoid
532              * a truncation bias that will eventually cause the audio to desync
533              * we compute the duration of the next frame using 27MHz ticks
534              * then truncate it to 90KHz. */
535             duration = ( (int64_t)(pv->count_frames + 1 ) * job->vrate_base ) / 300 -
536                        pv->next_start;
537
538             /* We don't want the input & output clocks to be exactly in phase
539              * otherwise small variations in the time will cause us to think
540              * we're a full frame off & there will be lots of drops and dups.
541              * We offset the input clock by half the duration so it's maximally
542              * out of phase with the output clock. */
543             if( cur->start < pv->next_start  - ( duration >> 1 ) )
544             {
545                 /* current frame too old - drop it */
546                 if ( cur->new_chap )
547                 {
548                     pv->chap_mark = cur->new_chap;
549                 }
550                 hb_buffer_close( &cur );
551                 pv->cur = cur = hb_fifo_get( job->fifo_raw );
552                 pv->next_pts = next->start;
553                 ++pv->drops;
554                 continue;
555             }
556
557             if( next->start > pv->next_start + duration + ( duration >> 1 ) )
558             {
559                 /* next frame too far ahead - dup current frame */
560                 buf_tmp = hb_buffer_init( cur->size );
561                 hb_buffer_copy_settings( buf_tmp, cur );
562                 memcpy( buf_tmp->data, cur->data, cur->size );
563                 buf_tmp->sequence = cur->sequence;
564                 ++pv->dups;
565             }
566             else
567             {
568                 /* this frame in our time window & doesn't need to be duped */
569                 buf_tmp = cur;
570                 pv->cur = cur = hb_fifo_get( job->fifo_raw );
571                 pv->next_pts = next->start;
572             }
573         }
574         else
575         {
576             /*
577              * Adjust the pts of the current frame so that it's contiguous
578              * with the previous frame. The start time of the current frame
579              * has to be the end time of the previous frame and the stop
580              * time has to be the start of the next frame.  We don't
581              * make any adjustments to the source timestamps other than removing
582              * the clock offsets (which also removes pts discontinuities).
583              * This means we automatically encode at the source's frame rate.
584              * MP2 uses an implicit duration (frames end when the next frame
585              * starts) but more advanced containers like MP4 use an explicit
586              * duration. Since we're looking ahead one frame we set the
587              * explicit stop time from the start time of the next frame.
588              */
589             buf_tmp = cur;
590             pv->cur = cur = hb_fifo_get( job->fifo_raw );
591             pv->next_pts = cur->start;
592             duration = cur->start - buf_tmp->start;
593             if ( duration <= 0 )
594             {
595                 hb_log( "sync: invalid video duration %lld, start %lld, next %lld",
596                         duration, buf_tmp->start, next->start );
597             }
598         }
599
600         buf_tmp->start = pv->next_start;
601         pv->next_start += duration;
602         buf_tmp->stop = pv->next_start;
603
604         if ( pv->chap_mark )
605         {
606             // we have a pending chapter mark from a recent drop - put it on this
607             // buffer (this may make it one frame late but we can't do any better).
608             buf_tmp->new_chap = pv->chap_mark;
609             pv->chap_mark = 0;
610         }
611
612         /* If we have a subtitle for this picture, copy it */
613         /* FIXME: we should avoid this memcpy */
614         if( sub )
615         {
616             buf_tmp->sub         = hb_buffer_init( sub->size );
617             buf_tmp->sub->x      = sub->x;
618             buf_tmp->sub->y      = sub->y;
619             buf_tmp->sub->width  = sub->width;
620             buf_tmp->sub->height = sub->height;
621             memcpy( buf_tmp->sub->data, sub->data, sub->size );
622         }
623
624         /* Push the frame to the renderer */
625         hb_fifo_push( job->fifo_sync, buf_tmp );
626
627         /* Update UI */
628         UpdateState( w );
629         
630         if( job->frame_to_stop && pv->count_frames > job->frame_to_stop )
631         {
632             // Drop an empty buffer into our output to ensure that things
633             // get flushed all the way out.
634             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
635             pv->busy &=~ 1;
636             hb_log( "sync: reached %d frames, exiting early (%i busy)",
637                     pv->count_frames, pv->busy );
638             return;
639         }
640
641         /* Make sure we won't get more frames then expected */
642         if( pv->count_frames >= pv->count_frames_max * 2)
643         {
644             hb_log( "sync: got too many frames (%d), exiting early",
645                     pv->count_frames );
646
647             // Drop an empty buffer into our output to ensure that things
648             // get flushed all the way out.
649             hb_fifo_push( job->fifo_sync, hb_buffer_init( 0 ) );
650             pv->busy &=~ 1;
651             return;
652         }
653     }
654 }
655
656 static void OutputAudioFrame( hb_job_t *job, hb_audio_t *audio, hb_buffer_t *buf,
657                               hb_sync_audio_t *sync, hb_fifo_t *fifo, int i )
658 {
659     int64_t start = sync->next_start;
660     int64_t duration = buf->stop - buf->start;
661
662     sync->next_pts += duration;
663
664     if( audio->config.in.samplerate == audio->config.out.samplerate ||
665         audio->config.out.codec == HB_ACODEC_AC3 ||
666         audio->config.out.codec == HB_ACODEC_DCA )
667     {
668         /*
669          * If we don't have to do sample rate conversion or this audio is 
670          * pass-thru just send the input buffer downstream after adjusting
671          * its timestamps to make the output stream continuous.
672          */
673     }
674     else
675     {
676         /* Not pass-thru - do sample rate conversion */
677         int count_in, count_out;
678         hb_buffer_t * buf_raw = buf;
679         int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
680                             sizeof( float );
681
682         count_in  = buf_raw->size / channel_count;
683         /*
684          * When using stupid rates like 44.1 there will always be some
685          * truncation error. E.g., a 1536 sample AC3 frame will turn into a
686          * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
687          * the error will build up over time and eventually the audio will
688          * substantially lag the video. libsamplerate will keep track of the
689          * fractional sample & give it to us when appropriate if we give it
690          * an extra sample of space in the output buffer.
691          */
692         count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
693
694         sync->data.input_frames = count_in;
695         sync->data.output_frames = count_out;
696         sync->data.src_ratio = (double)audio->config.out.samplerate /
697                                (double)audio->config.in.samplerate;
698
699         buf = hb_buffer_init( count_out * channel_count );
700         sync->data.data_in  = (float *) buf_raw->data;
701         sync->data.data_out = (float *) buf->data;
702         if( src_process( sync->state, &sync->data ) )
703         {
704             /* XXX If this happens, we're screwed */
705             hb_log( "sync: audio %d src_process failed", i );
706         }
707         hb_buffer_close( &buf_raw );
708
709         buf->size = sync->data.output_frames_gen * channel_count;
710         duration = ( sync->data.output_frames_gen * 90000 ) /
711                    audio->config.out.samplerate;
712     }
713     buf->frametype = HB_FRAME_AUDIO;
714     buf->start = start;
715     buf->stop  = start + duration;
716     sync->next_start = start + duration;
717     hb_fifo_push( fifo, buf );
718 }
719
720 /***********************************************************************
721  * SyncAudio
722  ***********************************************************************
723  *
724  **********************************************************************/
725 static void SyncAudio( hb_work_object_t * w, int i )
726 {
727     hb_work_private_t * pv = w->private_data;
728     hb_job_t        * job = pv->job;
729     hb_sync_audio_t * sync = &pv->sync_audio[i];
730     hb_audio_t      * audio = sync->audio;
731     hb_buffer_t     * buf;
732     hb_fifo_t       * fifo;
733
734     if( audio->config.out.codec == HB_ACODEC_AC3 )
735     {
736         fifo = audio->priv.fifo_out;
737     }
738     else
739     {
740         fifo = audio->priv.fifo_sync;
741     }
742
743     while( !hb_fifo_is_full( fifo ) && ( buf = hb_fifo_see( audio->priv.fifo_raw ) ) )
744     {
745         /* if the next buffer is an eof send it downstream */
746         if ( buf->size <= 0 )
747         {
748             buf = hb_fifo_get( audio->priv.fifo_raw );
749             hb_fifo_push( fifo, buf );
750             pv->busy &=~ (1 << (i + 1) );
751             return;
752         }
753         if( job->frame_to_stop && pv->count_frames >= job->frame_to_stop )
754         {
755             hb_fifo_push( fifo, hb_buffer_init(0) );
756             pv->busy &=~ (1 << (i + 1) );
757             return;
758         }
759         if ( (int64_t)( buf->start - sync->next_pts ) < 0 )
760         {
761             // audio time went backwards.
762             // If our output clock is more than a half frame ahead of the
763             // input clock drop this frame to move closer to sync.
764             // Otherwise drop frames until the input clock matches the output clock.
765             if ( sync->first_drop || sync->next_start - buf->start > 90*15 )
766             {
767                 // Discard data that's in the past.
768                 if ( sync->first_drop == 0 )
769                 {
770                     sync->first_drop = sync->next_pts;
771                 }
772                 ++sync->drop_count;
773                 buf = hb_fifo_get( audio->priv.fifo_raw );
774                 hb_buffer_close( &buf );
775                 continue;
776             }
777             sync->next_pts = buf->start;
778         }
779         if ( sync->first_drop )
780         {
781             // we were dropping old data but input buf time is now current
782             hb_log( "sync: audio %d time went backwards %d ms, dropped %d frames "
783                     "(next %lld, current %lld)", i,
784                     (int)( sync->next_pts - sync->first_drop ) / 90,
785                     sync->drop_count, sync->first_drop, sync->next_pts );
786             sync->first_drop = 0;
787             sync->drop_count = 0;
788             sync->next_pts = buf->start;
789         }
790         if ( buf->start - sync->next_pts >= (90 * 70) )
791         {
792             if ( buf->start - sync->next_pts > (90000LL * 60) )
793             {
794                 // there's a gap of more than a minute between the last
795                 // frame and this. assume we got a corrupted timestamp
796                 // and just drop the next buf.
797                 hb_log( "sync: %d minute time gap in audio %d - dropping buf"
798                         "  start %lld, next %lld",
799                         (int)((buf->start - sync->next_pts) / (90000*60)),
800                         i, buf->start, sync->next_pts );
801                 buf = hb_fifo_get( audio->priv.fifo_raw );
802                 hb_buffer_close( &buf );
803                 continue;
804             }
805             /*
806              * there's a gap of at least 70ms between the last
807              * frame we processed & the next. Fill it with silence.
808              */
809             hb_log( "sync: adding %d ms of silence to audio %d"
810                     "  start %lld, next %lld",
811                     (int)((buf->start - sync->next_pts) / 90),
812                     i, buf->start, sync->next_pts );
813             InsertSilence( w, i, buf->start - sync->next_pts );
814             return;
815         }
816
817         /*
818          * When we get here we've taken care of all the dups and gaps in the
819          * audio stream and are ready to inject the next input frame into
820          * the output stream.
821          */
822         buf = hb_fifo_get( audio->priv.fifo_raw );
823         OutputAudioFrame( job, audio, buf, sync, fifo, i );
824     }
825 }
826
827 static void InsertSilence( hb_work_object_t * w, int i, int64_t duration )
828 {
829     hb_work_private_t * pv = w->private_data;
830     hb_job_t        *job = pv->job;
831     hb_sync_audio_t *sync = &pv->sync_audio[i];
832     hb_buffer_t     *buf;
833     hb_fifo_t       *fifo;
834
835     // to keep pass-thru and regular audio in sync we generate silence in
836     // AC3 frame-sized units. If the silence duration isn't an integer multiple
837     // of the AC3 frame duration we will truncate or round up depending on
838     // which minimizes the timing error.
839     const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
840                           sync->audio->config.in.samplerate;
841     int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
842
843     while ( --frame_count >= 0 )
844     {
845         if( sync->audio->config.out.codec == HB_ACODEC_AC3 )
846         {
847             buf        = hb_buffer_init( sync->ac3_size );
848             buf->start = sync->next_pts;
849             buf->stop  = buf->start + frame_dur;
850             memcpy( buf->data, sync->ac3_buf, buf->size );
851             fifo = sync->audio->priv.fifo_out;
852         }
853         else
854         {
855             buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
856                                      HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
857                                          sync->audio->config.out.mixdown) );
858             buf->start = sync->next_pts;
859             buf->stop  = buf->start + frame_dur;
860             memset( buf->data, 0, buf->size );
861             fifo = sync->audio->priv.fifo_sync;
862         }
863         OutputAudioFrame( job, sync->audio, buf, sync, fifo, i );
864     }
865 }
866
867 static void UpdateState( hb_work_object_t * w )
868 {
869     hb_work_private_t * pv = w->private_data;
870     hb_state_t state;
871
872     if( !pv->count_frames )
873     {
874         pv->st_first = hb_get_date();
875     }
876     pv->count_frames++;
877
878     if( hb_get_date() > pv->st_dates[3] + 1000 )
879     {
880         memmove( &pv->st_dates[0], &pv->st_dates[1],
881                  3 * sizeof( uint64_t ) );
882         memmove( &pv->st_counts[0], &pv->st_counts[1],
883                  3 * sizeof( uint64_t ) );
884         pv->st_dates[3]  = hb_get_date();
885         pv->st_counts[3] = pv->count_frames;
886     }
887
888 #define p state.param.working
889     state.state = HB_STATE_WORKING;
890     p.progress  = (float) pv->count_frames / (float) pv->count_frames_max;
891     if( p.progress > 1.0 )
892     {
893         p.progress = 1.0;
894     }
895     p.rate_cur   = 1000.0 *
896         (float) ( pv->st_counts[3] - pv->st_counts[0] ) /
897         (float) ( pv->st_dates[3] - pv->st_dates[0] );
898     if( hb_get_date() > pv->st_first + 4000 )
899     {
900         int eta;
901         p.rate_avg = 1000.0 * (float) pv->st_counts[3] /
902             (float) ( pv->st_dates[3] - pv->st_first );
903         eta = (float) ( pv->count_frames_max - pv->st_counts[3] ) /
904             p.rate_avg;
905         p.hours   = eta / 3600;
906         p.minutes = ( eta % 3600 ) / 60;
907         p.seconds = eta % 60;
908     }
909     else
910     {
911         p.rate_avg = 0.0;
912         p.hours    = -1;
913         p.minutes  = -1;
914         p.seconds  = -1;
915     }
916 #undef p
917
918     hb_set_state( pv->job->h, &state );
919 }