/* $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"
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;
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 )
hb_mux_object_t * m = NULL;
/* Get a real muxer */
- if( job->pass != 1 )
+ if( job->pass == 0 || job->pass == 2)
{
switch( job->mux )
{
case HB_MUX_OGM:
m = hb_mux_ogm_init( job );
break;
+ case HB_MUX_MKV:
+ m = hb_mux_mkv_init( job );
}
}
- /* 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->fifo_out ) )
- {
- ready = 0;
- break;
- }
- }
-
- if( ready )
- {
- break;
- }
-
- hb_snooze( 50 );
- }
-
/* Create file, write headers */
- if( job->pass != 1 )
+ if( job->pass == 0 || job->pass == 2 )
{
m->init( m );
}
{
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 );
}
- while( !*job->die && !job->done )
+ int thread_sleep_interval = 50;
+ while( !*job->die )
{
- if( !( track = GetTrack( list ) ) )
+ if( !( track = GetTrack( list, job ) ) )
{
- hb_snooze( 50 );
+ if ( AllTracksDone( list ) )
+ {
+ // all our input fifos have signaled EOF
+ break;
+ }
+ hb_snooze( thread_sleep_interval );
continue;
}
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;
hb_buffer_close( &buf );
}
- if( job->pass != 1 )
+ if( job->pass == 0 || job->pass == 2 )
{
struct stat sb;
uint64_t bytes_total, frames_total;