OSDN Git Service

HandBrake 0.7.0
[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_object_s
35 {
36     HB_WORK_COMMON;
37
38     hb_job_t * job;
39     int        done;
40
41     /* Video */
42     hb_subtitle_t * subtitle;
43     int64_t pts_offset;
44     int64_t pts_offset_old;
45     int64_t count_frames;
46     int64_t count_frames_max;
47     hb_buffer_t * cur; /* The next picture to process */
48
49     /* Audio */
50     hb_sync_audio_t sync_audio[8];
51
52     /* Statistics */
53     uint64_t st_counts[4];
54     uint64_t st_dates[4];
55     uint64_t st_first;
56 };
57
58 /***********************************************************************
59  * Local prototypes
60  **********************************************************************/
61 static void InitAudio( hb_work_object_t * w, int i );
62 static void Close( hb_work_object_t ** _w );
63 static int  Work( hb_work_object_t * w, hb_buffer_t ** unused1,
64                   hb_buffer_t ** unused2 );
65 static int  SyncVideo( hb_work_object_t * w );
66 static void SyncAudio( hb_work_object_t * w, int i );
67 static int  NeedSilence( hb_work_object_t * w, hb_audio_t * );
68 static void InsertSilence( hb_work_object_t * w, int i );
69 static void UpdateState( hb_work_object_t * w );
70
71 /***********************************************************************
72  * hb_work_sync_init
73  ***********************************************************************
74  * Initialize the work object
75  **********************************************************************/
76 hb_work_object_t * hb_work_sync_init( hb_job_t * job )
77 {
78     hb_work_object_t * w;
79     hb_title_t       * title = job->title;
80     hb_chapter_t     * chapter;
81     int                i;
82     uint64_t           duration;
83
84     w        = calloc( sizeof( hb_work_object_t ), 1 );
85     w->name  = strdup( "Synchronization" );
86     w->work  = Work;
87     w->close = Close;
88
89     w->job            = job;
90     w->pts_offset     = INT64_MIN;
91     w->pts_offset_old = INT64_MIN;
92     w->count_frames   = 0;
93
94     /* Calculate how many video frames we are expecting */
95     duration = 0;
96     for( i = job->chapter_start; i <= job->chapter_end; i++ )
97     {
98         chapter   = hb_list_item( title->list_chapter, i - 1 );
99         duration += chapter->duration;
100     }                                                                           
101     duration += 90000;
102         /* 1 second safety so we're sure we won't miss anything */
103     w->count_frames_max = duration * job->vrate / job->vrate_base / 90000;
104
105     hb_log( "sync: expecting %lld video frames", w->count_frames_max );
106
107     /* Initialize libsamplerate for every audio track we have */
108     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
109     {
110         InitAudio( w, i );
111     }
112
113     /* Get subtitle info, if any */
114     w->subtitle = hb_list_item( title->list_subtitle, 0 );
115
116     return w;
117 }
118
119 static void InitAudio( hb_work_object_t * w, int i )
120 {
121     hb_job_t        * job   = w->job;
122     hb_title_t      * title = job->title;
123     hb_sync_audio_t * sync;
124
125     sync        = &w->sync_audio[i];
126     sync->audio = hb_list_item( title->list_audio, i );
127
128     if( job->acodec & HB_ACODEC_AC3 )
129     {
130         /* Have a silent AC-3 frame ready in case we have to fill a
131            gap */
132         AVCodec        * codec;
133         AVCodecContext * c;
134         short          * zeros;
135
136         codec = avcodec_find_encoder( CODEC_ID_AC3 );
137         c     = avcodec_alloc_context();
138
139         c->bit_rate    = sync->audio->bitrate;
140         c->sample_rate = sync->audio->rate;
141         c->channels    = sync->audio->channels;
142
143         if( avcodec_open( c, codec ) < 0 )
144         {
145             hb_log( "sync: avcodec_open failed" );
146             return;
147         }
148
149         zeros          = calloc( AC3_SAMPLES_PER_FRAME *
150                                  sizeof( short ) * c->channels, 1 );
151         sync->ac3_size = sync->audio->bitrate * AC3_SAMPLES_PER_FRAME /
152                              sync->audio->rate / 8;
153         sync->ac3_buf  = malloc( sync->ac3_size );
154
155         if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
156                                   zeros ) != sync->ac3_size )
157         {
158             hb_log( "sync: avcodec_encode_audio failed" );
159         }
160         
161         free( zeros );
162         avcodec_close( c );
163         av_free( c );
164     }
165     else
166     {
167         /* Initialize libsamplerate */
168         int error;
169         sync->state             = src_new( SRC_LINEAR, 2, &error );
170         sync->data.end_of_input = 0;
171     }
172 }
173
174 /***********************************************************************
175  * Close
176  ***********************************************************************
177  *
178  **********************************************************************/
179 static void Close( hb_work_object_t ** _w )
180 {
181     hb_work_object_t * w     = *_w;
182     hb_job_t         * job   = w->job;
183     hb_title_t       * title = job->title;
184     
185     int i;
186
187     if( w->cur ) hb_buffer_close( &w->cur );
188
189     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
190     {
191         if( job->acodec & HB_ACODEC_AC3 )
192         {
193             free( w->sync_audio[i].ac3_buf );
194         }
195         else
196         {
197             src_delete( w->sync_audio[i].state );
198         }
199     }
200
201     free( w->name );    
202     free( w );
203     *_w = NULL;
204 }
205
206 /***********************************************************************
207  * Work
208  ***********************************************************************
209  * The root routine of this work abject
210  **********************************************************************/
211 static int Work( hb_work_object_t * w, hb_buffer_t ** unused1,
212                  hb_buffer_t ** unused2 )
213 {
214     int i;
215
216     /* If we ever got a video frame, handle audio now */
217     if( w->pts_offset != INT64_MIN )
218     {
219         for( i = 0; i < hb_list_count( w->job->title->list_audio ); i++ )
220         {
221             SyncAudio( w, i );
222         }
223     }
224
225     /* Handle video */
226     return SyncVideo( w );
227 }
228
229 /***********************************************************************
230  * SyncVideo
231  ***********************************************************************
232  * 
233  **********************************************************************/
234 static int SyncVideo( hb_work_object_t * w )
235 {
236     hb_buffer_t * cur, * next, * sub = NULL;
237     hb_job_t * job = w->job;
238     int64_t pts_expected;
239
240     if( w->done )
241     {
242         return HB_WORK_DONE;
243     }
244
245     if( hb_thread_has_exited( job->reader ) &&
246         !hb_fifo_size( job->fifo_mpeg2 ) &&
247         !hb_fifo_size( job->fifo_raw ) )
248     {
249         /* All video data has been processed already, we won't get
250            more */
251         hb_log( "sync: got %lld frames, %lld expected",
252                 w->count_frames, w->count_frames_max );
253         w->done = 1;
254         return HB_WORK_DONE;
255     }
256
257     if( !w->cur && !( w->cur = hb_fifo_get( job->fifo_raw ) ) )
258     {
259         /* We haven't even got a frame yet */
260         return HB_WORK_OK;
261     }
262     cur = w->cur;
263
264     /* At this point we have a frame to process. Let's check
265         1) if we will be able to push into the fifo ahead
266         2) if the next frame is there already, since we need it to
267            know whether we'll have to repeat the current frame or not */
268     while( !hb_fifo_is_full( job->fifo_sync ) &&
269            ( next = hb_fifo_see( job->fifo_raw ) ) )
270     {
271         hb_buffer_t * buf_tmp;
272
273         if( w->pts_offset == INT64_MIN )
274         {
275             /* This is our first frame */
276             hb_log( "sync: first pts is %lld", cur->start );
277             w->pts_offset = cur->start;
278         }
279
280         /* Check for PTS jumps over 0.5 second */
281         if( next->start < cur->start - 45000 ||
282             next->start > cur->start + 45000 )
283         {
284             hb_log( "PTS discontinuity (%lld, %lld)",
285                     cur->start, next->start );
286             
287             /* Trash all subtitles */
288             if( w->subtitle )
289             {
290                 while( ( sub = hb_fifo_get( w->subtitle->fifo_raw ) ) )
291                 {
292                     hb_buffer_close( &sub );
293                 }
294             }
295
296             /* Trash current picture */
297             hb_buffer_close( &cur );
298             w->cur = cur = hb_fifo_get( job->fifo_raw );
299
300             /* Calculate new offset */
301             w->pts_offset_old = w->pts_offset;
302             w->pts_offset     = cur->start -
303                 w->count_frames * w->job->vrate_base / 300;
304             continue;
305         }
306
307         /* Look for a subtitle for this frame */
308         if( w->subtitle )
309         {
310             /* Trash subtitles older than this picture */
311             while( ( sub = hb_fifo_see( w->subtitle->fifo_raw ) ) &&
312                     sub->stop < cur->start )
313             {
314                 sub = hb_fifo_get( w->subtitle->fifo_raw );
315                 hb_buffer_close( &sub );
316             }
317
318             /* If we have subtitles left in the fifo, check if we should
319                apply the first one to the current frame or if we should
320                keep it for later */
321             if( sub && sub->start > cur->start )
322             {
323                 sub = NULL;
324             }
325         }
326
327         /* The PTS of the frame we are expecting now */
328         pts_expected = w->pts_offset +
329             w->count_frames * w->job->vrate_base / 300;
330
331         if( cur->start < pts_expected - w->job->vrate_base / 300 / 2 &&
332             next->start < pts_expected + w->job->vrate_base / 300 / 2 )
333         {
334             /* The current frame is too old but the next one matches,
335                let's trash */
336             hb_buffer_close( &cur );
337             w->cur = cur = hb_fifo_get( job->fifo_raw );
338             continue;
339         }
340
341         if( next->start > pts_expected + 3 * w->job->vrate_base / 300 / 2 )
342         {
343             /* We'll need the current frame more than one time. Make a
344                copy of it and keep it */
345             buf_tmp = hb_buffer_init( cur->size );
346             memcpy( buf_tmp->data, cur->data, cur->size );
347         }
348         else
349         {
350             /* The frame has the expected date and won't have to be
351                duplicated, just put it through */
352             buf_tmp = cur;
353             w->cur = cur = hb_fifo_get( job->fifo_raw );
354         }
355
356         /* Replace those MPEG-2 dates with our dates */
357         buf_tmp->start = (uint64_t) w->count_frames *
358             w->job->vrate_base / 300;
359         buf_tmp->stop  = (uint64_t) ( w->count_frames + 1 ) *
360             w->job->vrate_base / 300;
361
362         /* If we have a subtitle for this picture, copy it */
363         /* FIXME: we should avoid this memcpy */
364         if( sub )
365         {
366             buf_tmp->sub         = hb_buffer_init( sub->size );
367             buf_tmp->sub->x      = sub->x;
368             buf_tmp->sub->y      = sub->y;
369             buf_tmp->sub->width  = sub->width;
370             buf_tmp->sub->height = sub->height;
371             memcpy( buf_tmp->sub->data, sub->data, sub->size );
372         }
373
374         /* Push the frame to the renderer */
375         hb_fifo_push( job->fifo_sync, buf_tmp );
376
377         /* Update UI */
378         UpdateState( w );
379
380         /* Make sure we won't get more frames then expected */
381         if( w->count_frames >= w->count_frames_max )
382         {
383             hb_log( "sync: got %lld frames", w->count_frames );
384             w->done = 1;
385             break;
386         }
387     }
388
389     return HB_WORK_OK;
390 }
391
392 /***********************************************************************
393  * SyncAudio
394  ***********************************************************************
395  * 
396  **********************************************************************/
397 static void SyncAudio( hb_work_object_t * w, int i )
398 {
399     hb_job_t        * job;
400     hb_audio_t      * audio;
401     hb_buffer_t     * buf;
402     hb_sync_audio_t * sync;
403
404     hb_fifo_t       * fifo;
405     int               rate;
406
407     int64_t           pts_expected;
408     int64_t           start;
409
410     job    = w->job;
411     sync   = &w->sync_audio[i];
412     audio  = sync->audio;
413
414     if( job->acodec & HB_ACODEC_AC3 )
415     {
416         fifo = audio->fifo_out;
417         rate = audio->rate;
418     }
419     else
420     {
421         fifo = audio->fifo_sync;
422         rate = job->arate;
423     }
424
425     while( !hb_fifo_is_full( fifo ) &&
426            ( buf = hb_fifo_see( audio->fifo_raw ) ) )
427     {
428         /* The PTS of the samples we are expecting now */
429         pts_expected = w->pts_offset + sync->count_frames * 90000 / rate;
430
431         if( ( buf->start > pts_expected + 45000 ||
432               buf->start < pts_expected - 45000 ) &&
433             w->pts_offset_old > INT64_MIN )
434         {
435             /* There has been a PTS discontinuity, and this frame might
436                be from before the discontinuity */
437             pts_expected = w->pts_offset_old + sync->count_frames *
438                 90000 / rate;
439
440             if( buf->start > pts_expected + 45000 ||
441                 buf->start < pts_expected - 45000 )
442             {
443                 /* There is really nothing we can do with it */
444                 buf = hb_fifo_get( audio->fifo_raw );
445                 hb_buffer_close( &buf );
446                 continue;
447             }
448
449             /* Use the older offset */
450             start = pts_expected - w->pts_offset_old;
451         }
452         else
453         {
454             start = pts_expected - w->pts_offset;
455         }
456
457         if( ( buf->start + buf->stop ) / 2 < pts_expected )
458         {
459             /* Late audio, trash it */
460             buf = hb_fifo_get( audio->fifo_raw );
461             hb_buffer_close( &buf );
462             continue;
463         }
464
465         if( buf->start > pts_expected + ( buf->stop - buf->start ) / 2 )
466         {
467             /* Audio push, send a frame of silence */
468             InsertSilence( w, i );
469             continue;
470         }
471
472         if( job->acodec & HB_ACODEC_AC3 )
473         {
474             buf        = hb_fifo_get( audio->fifo_raw );
475             buf->start = start;
476             buf->stop  = start + 90000 * AC3_SAMPLES_PER_FRAME / rate;
477
478             sync->count_frames += AC3_SAMPLES_PER_FRAME;
479         }
480         else
481         {
482             hb_buffer_t * buf_raw = hb_fifo_get( audio->fifo_raw );
483
484             int count_in, count_out;
485
486             count_in  = buf_raw->size / 2 / sizeof( float );
487             count_out = ( buf->stop - pts_expected ) * job->arate / 90000;
488
489             sync->data.data_in      = (float *) buf_raw->data;
490             sync->data.input_frames = count_in;
491
492             if( buf->start < pts_expected - ( buf->stop - buf->start ) / 5 )
493             {
494                 /* Avoid too heavy downsampling, trash the beginning of
495                    the buffer instead */
496                 int drop;
497                 drop = count_in * ( pts_expected - buf->start ) /
498                            ( buf->stop - buf->start );
499                 sync->data.data_in      += 2 * drop;
500                 sync->data.input_frames -= drop;
501                 hb_log( "dropping %d of %d samples", drop, count_in );
502             }
503
504             sync->data.output_frames = count_out;
505             sync->data.src_ratio = (double) sync->data.output_frames /
506                                    (double) sync->data.input_frames;
507
508             buf = hb_buffer_init( sync->data.output_frames * 2 *
509                                   sizeof( float ) );
510             sync->data.data_out = (float *) buf->data;
511             if( src_process( sync->state, &sync->data ) )
512             {
513                 /* XXX If this happens, we're screwed */
514                 hb_log( "sync: src_process failed" );
515             }
516             hb_buffer_close( &buf_raw );
517
518             buf->size = sync->data.output_frames_gen * 2 * sizeof( float );
519
520             /* Set dates for resampled data */
521             buf->start = start;
522             buf->stop  = start + sync->data.output_frames_gen *
523                             90000 / job->arate;
524
525             sync->count_frames += sync->data.output_frames_gen;
526         }
527
528         buf->key = 1;
529         hb_fifo_push( fifo, buf );
530     }
531
532     if( NeedSilence( w, audio ) )
533     {
534         InsertSilence( w, i );
535     }
536 }
537
538 static int NeedSilence( hb_work_object_t * w, hb_audio_t * audio )
539 {
540     hb_job_t * job = w->job;
541
542     if( hb_fifo_size( audio->fifo_in ) ||
543         hb_fifo_size( audio->fifo_raw ) ||
544         hb_fifo_size( audio->fifo_sync ) ||
545         hb_fifo_size( audio->fifo_out ) )
546     {
547         /* We have some audio, we are fine */
548         return 0;
549     }
550
551     /* No audio left in fifos */
552
553     if( hb_thread_has_exited( job->reader ) )
554     {
555         /* We might miss some audio to complete encoding and muxing
556            the video track */
557         return 1;
558     }
559
560     if( hb_fifo_is_full( job->fifo_mpeg2 ) &&
561         hb_fifo_is_full( job->fifo_raw ) &&
562         hb_fifo_is_full( job->fifo_sync ) &&
563         hb_fifo_is_full( job->fifo_render ) &&
564         hb_fifo_is_full( job->fifo_mpeg4 ) )
565     {
566         /* Too much video and no audio, oh-oh */
567         return 1;
568     }
569
570     return 0;
571 }
572
573 static void InsertSilence( hb_work_object_t * w, int i )
574 {
575     hb_job_t        * job;
576     hb_sync_audio_t * sync;
577     hb_buffer_t     * buf;
578
579     job    = w->job;
580     sync   = &w->sync_audio[i];
581
582     if( job->acodec & HB_ACODEC_AC3 )
583     {
584         buf        = hb_buffer_init( sync->ac3_size );
585         buf->start = sync->count_frames * 90000 / sync->audio->rate;
586         buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME /
587                      sync->audio->rate;
588         memcpy( buf->data, sync->ac3_buf, buf->size );
589
590         hb_log( "sync: adding a silent AC-3 frame for track %x",
591                 sync->audio->id );
592         hb_fifo_push( sync->audio->fifo_out, buf );
593
594         sync->count_frames += AC3_SAMPLES_PER_FRAME;
595
596     }
597     else
598     {
599         buf        = hb_buffer_init( 2 * job->arate / 20 *
600                                      sizeof( float ) );
601         buf->start = sync->count_frames * 90000 / job->arate;
602         buf->stop  = buf->start + 90000 / 20;
603         memset( buf->data, 0, buf->size );
604
605         hb_log( "sync: adding 50 ms of silence for track %x",
606                 sync->audio->id );
607         hb_fifo_push( sync->audio->fifo_sync, buf );
608
609         sync->count_frames += job->arate / 20;
610     }
611 }
612
613 static void UpdateState( hb_work_object_t * w )
614 {
615     hb_state_t state;
616
617     if( !w->count_frames )
618     {
619         w->st_first = hb_get_date();
620     }
621     w->count_frames++;
622
623     if( hb_get_date() > w->st_dates[3] + 1000 )
624     {
625         memmove( &w->st_dates[0], &w->st_dates[1],
626                  3 * sizeof( uint64_t ) );
627         memmove( &w->st_counts[0], &w->st_counts[1],
628                  3 * sizeof( uint64_t ) );
629         w->st_dates[3]  = hb_get_date();
630         w->st_counts[3] = w->count_frames;
631     } 
632
633 #define p state.param.working
634     state.state = HB_STATE_WORKING;
635     p.progress  = (float) w->count_frames / (float) w->count_frames_max;
636     if( p.progress > 1.0 )
637     {
638         p.progress = 1.0; 
639     }
640     p.rate_cur   = 1000.0 *
641         (float) ( w->st_counts[3] - w->st_counts[0] ) /
642         (float) ( w->st_dates[3] - w->st_dates[0] );
643     if( hb_get_date() > w->st_first + 4000 )
644     {
645         int eta;
646         p.rate_avg = 1000.0 * (float) w->st_counts[3] /
647             (float) ( w->st_dates[3] - w->st_first );
648         eta = (float) ( w->count_frames_max - w->st_counts[3] ) /
649             p.rate_avg;
650         p.hours   = eta / 3600;
651         p.minutes = ( eta % 3600 ) / 60;
652         p.seconds = eta % 60;
653     }
654     else
655     {
656         p.rate_avg = 0.0;
657         p.hours    = -1;
658         p.minutes  = -1;
659         p.seconds  = -1;
660     }
661 #undef p
662
663     hb_set_state( w->job->h, &state );
664 }