OSDN Git Service

Wait until 4 frames are stashed in the delay_queue before outputting any frames from...
[handbrake-jp/handbrake-jp-git.git] / libhb / muxcommon.c
index 04e876a..dcbba15 100644 (file)
@@ -24,10 +24,10 @@ typedef struct
     hb_mux_data_t * mux_data;
     uint64_t        frames;
     uint64_t        bytes;
-
+    int             eof;
 } 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;
@@ -37,18 +37,59 @@ static hb_track_t * GetTrack( hb_list_t * list )
     for( i = 0; i < hb_list_count( list ); i++ )
     {
         track2 = hb_list_item( list, i );
-        buf    = hb_fifo_see( track2->fifo );
-        if( !buf )
+        if ( ! track2->eof )
         {
-            return NULL;
+            buf    = hb_fifo_see( track2->fifo );
+            if( !buf )
+            {
+                // XXX the libmkv muxer will produce unplayable files if the
+                // audio & video are far 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.
+                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 ( buf->size <= 0 )
+            {
+                // EOF - mark this track as done
+                buf = hb_fifo_get( track2->fifo );
+                hb_buffer_close( &buf );
+                track2->eof = 1;
+                continue;
+            }
+            if( !track || buf->start < pts )
+            {
+                track = track2;
+                pts   = buf->start;
+            }
         }
-        if( !track || buf->start < pts )
+    }
+    return track;
+}
+
+static int AllTracksDone( hb_list_t * list )
+{
+    hb_track_t  * track;
+    int           i;
+
+    for( i = 0; i < hb_list_count( list ); i++ )
+    {
+        track = hb_list_item( list, i );
+        if ( track->eof == 0 )
         {
-            track = track2;
-            pts   = buf->start;
+            return 0;
         }
     }
-    return track;
+    return 1;
 }
 
 static void MuxerFunc( void * _mux )
@@ -85,34 +126,6 @@ static void MuxerFunc( void * _mux )
         }
     }
 
-    /* Wait for one buffer for each track */
-    while( !*job->die && !job->done )
-    {
-        int ready;
-
-        ready = 1;
-        if( !hb_fifo_size( job->fifo_mpeg4 ) )
-        {
-            ready = 0;
-        }
-        for( i = 0; i < hb_list_count( title->list_audio ); i++ )
-        {
-            audio = hb_list_item( title->list_audio, i );
-            if( !hb_fifo_size( audio->priv.fifo_out ) )
-            {
-                ready = 0;
-                break;
-            }
-        }
-
-        if( ready )
-        {
-            break;
-        }
-
-        hb_snooze( 50 );
-    }
-
     /* Create file, write headers */
     if( job->pass == 0 || job->pass == 2 )
     {
@@ -137,15 +150,18 @@ static void MuxerFunc( void * _mux )
     }
 
        int thread_sleep_interval = 50;
-       while( !*job->die && !job->done )
+       while( !*job->die )
     {
-        if( !( track = GetTrack( list ) ) )
+        if( !( track = GetTrack( list, job ) ) )
         {
+            if ( AllTracksDone( list )  )
+            {
+                // all our input fifos have signaled EOF
+                break;
+            }
             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 == 0 || job->pass == 2 )