OSDN Git Service

Fix mkv A/V sync problem created by R1542.
[handbrake-jp/handbrake-jp-git.git] / libhb / muxcommon.c
index 3fc13b8..b3337b7 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id: muxcommon.c,v 1.23 2005/03/30 17:27:19 titer Exp $
 
    This file is part of the HandBrake source code.
-   Homepage: <http://handbrake.m0k.org/>.
+   Homepage: <http://handbrake.fr/>.
    It may be used under the terms of the GNU General Public License. */
 
 #include "hb.h"
@@ -27,7 +27,7 @@ typedef struct
 
 } hb_track_t;
 
-static hb_track_t * GetTrack( hb_list_t * list )
+static hb_track_t * GetTrack( hb_list_t * list, hb_job_t *job )
 {
     hb_buffer_t * buf;
     hb_track_t  * track = NULL, * track2;
@@ -40,7 +40,23 @@ static hb_track_t * GetTrack( hb_list_t * list )
         buf    = hb_fifo_see( track2->fifo );
         if( !buf )
         {
-            return NULL;
+            // XXX libmkv uses a very simple minded muxer that will fail if the
+            // audio & video are out of sync.  To keep them in sync we require
+            // that *all* fifos have a buffer then we take the oldest.
+            // Unfortunately this means we can hang in a deadlock with the
+            // reader process filling the fifos. With the current libmkv
+            // there's no way to avoid occasional deadlocks & we can only
+            // suggest that users evolve to using mp4s.
+            if ( job->mux == HB_MUX_MKV )
+            {
+                return NULL;
+            }
+
+            // To make sure we don't camp on one fifo & prevent the others
+            // from making progress we take the earliest data of all the
+            // data that's currently available but we don't care if some
+            // fifos don't have data.
+            continue;
         }
         if( !track || buf->start < pts )
         {
@@ -65,7 +81,7 @@ static void MuxerFunc( void * _mux )
     hb_mux_object_t * m = NULL;
 
     /* Get a real muxer */
-    if( job->pass != 1 )
+    if( job->pass == 0 || job->pass == 2)
     {
         switch( job->mux )
         {
@@ -80,6 +96,8 @@ static void MuxerFunc( void * _mux )
             case HB_MUX_OGM:
                 m = hb_mux_ogm_init( job );
                 break;
+            case HB_MUX_MKV:
+                m = hb_mux_mkv_init( job );
         }
     }
 
@@ -96,7 +114,7 @@ static void MuxerFunc( void * _mux )
         for( i = 0; i < hb_list_count( title->list_audio ); i++ )
         {
             audio = hb_list_item( title->list_audio, i );
-            if( !hb_fifo_size( audio->fifo_out ) )
+            if( !hb_fifo_size( audio->priv.fifo_out ) )
             {
                 ready = 0;
                 break;
@@ -112,7 +130,7 @@ static void MuxerFunc( void * _mux )
     }
 
     /* Create file, write headers */
-    if( job->pass != 1 )
+    if( job->pass == 0 || job->pass == 2 )
     {
         m->init( m );
     }
@@ -129,24 +147,22 @@ static void MuxerFunc( void * _mux )
     {
         audio           = hb_list_item( title->list_audio, i );
         track           = calloc( sizeof( hb_track_t ), 1 );
-        track->fifo     = audio->fifo_out;
-        track->mux_data = audio->mux_data;
+        track->fifo     = audio->priv.fifo_out;
+        track->mux_data = audio->priv.mux_data;
         hb_list_add( list, track );
     }
 
        int thread_sleep_interval = 50;
        while( !*job->die && !job->done )
     {
-        if( !( track = GetTrack( list ) ) )
+        if( !( track = GetTrack( list, job ) ) )
         {
             hb_snooze( thread_sleep_interval );
-//                     thread_sleep_interval += 1;
             continue;
         }
-//             thread_sleep_interval = MAX(1, (thread_sleep_interval - 1));
 
         buf = hb_fifo_get( track->fifo );
-        if( job->pass != 1 )
+        if( job->pass == 0 || job->pass == 2 )
         {
             m->mux( m, track->mux_data, buf );
             track->frames += 1;
@@ -156,7 +172,7 @@ static void MuxerFunc( void * _mux )
         hb_buffer_close( &buf );
     }
 
-    if( job->pass != 1 )
+    if( job->pass == 0 || job->pass == 2 )
     {
         struct stat sb;
         uint64_t bytes_total, frames_total;