#include "hb.h"
+#define MAX_BUFFERING (1024*1024*50)
+
struct hb_mux_object_s
{
HB_MUX_COMMON;
uint64_t frames;
uint64_t bytes;
mux_fifo_t mf;
+ int buffered_size;
} hb_track_t;
typedef struct
mux->allRdy |= is_continuous << t;
}
+static int mf_full( hb_track_t * track )
+{
+ if ( track->buffered_size > MAX_BUFFERING )
+ return 1;
+
+ return 0;
+}
+
static void mf_push( hb_mux_t * mux, int tk, hb_buffer_t *buf )
{
hb_track_t * track = mux->track[tk];
uint32_t mask = track->mf.flen - 1;
uint32_t in = track->mf.in;
- if ( ( ( in + 2 ) & mask ) == ( track->mf.out & mask ) )
+ if ( track->buffered_size > MAX_BUFFERING )
{
- if ( track->mf.flen >= 256 )
- {
- mux->rdy = mux->allRdy;
- }
+ mux->rdy = mux->allRdy;
}
if ( ( ( in + 1 ) & mask ) == ( track->mf.out & mask ) )
{
}
track->mf.fifo[in & mask] = buf;
track->mf.in = in + 1;
+ track->buffered_size += buf->alloc;
}
static hb_buffer_t *mf_pull( hb_track_t *track )
// the fifo isn't empty
b = track->mf.fifo[track->mf.out & (track->mf.flen - 1)];
++track->mf.out;
+
+ track->buffered_size -= b->alloc;
}
return b;
}
while ( ( buf = mf_peek( track ) ) != NULL && buf->start < mux->pts )
{
- m->mux( m, track->mux_data, mf_pull( track ) );
+ buf = mf_pull( track );
track->frames += 1;
track->bytes += buf->size;
+ m->mux( m, track->mux_data, buf );
}
}
return HB_WORK_OK;
}
+ int more = mux->rdy;
// all tracks have at least 'interleave' ticks of data. Output
// all that we can in 'interleave' size chunks.
- while ( ( mux->rdy & mux->allRdy ) == mux->allRdy )
+ while ( ( mux->rdy & mux->allRdy ) == mux->allRdy && more )
{
+ more = 0;
for ( i = 0; i < mux->ntracks; ++i )
{
track = mux->track[i];
OutputTrackChunk( mux, track, mux->m );
+ if ( mf_full( track ) )
+ {
+ // If the track's fifo is still full, advance
+ // the currint interleave point and try again.
+ mux->rdy = mux->allRdy;
+ break;
+ }
// if the track is at eof or still has data that's past
// our next interleave point then leave it marked as rdy.
{
mux->rdy &=~ ( 1 << i );
}
+ if ( track->mf.out != track->mf.in )
+ {
+ more |= ( 1 << i );
+ }
}
// if all the tracks are at eof we're just purging their
hb_lock( mux->mutex );
if ( --mux->ref == 0 )
{
+ // Update state before closing muxer. Closing the muxer
+ // may initiate optimization which can take a while and
+ // we want the muxing state to be visible while this is
+ // happening.
+ if( job->pass == 0 || job->pass == 2 )
+ {
+ /* Update the UI */
+ hb_state_t state;
+ state.state = HB_STATE_MUXING;
+ state.param.muxing.progress = 0;
+ hb_set_state( job->h, &state );
+ }
+
if( mux->m )
{
mux->m->end( mux->m );
struct stat sb;
uint64_t bytes_total, frames_total;
- /* Update the UI */
- hb_state_t state;
- state.state = HB_STATE_MUXING;
- state.param.muxing.progress = 0;
- hb_set_state( job->h, &state );
-
if( !stat( job->file, &sb ) )
{
hb_deep_log( 2, "mux: file size, %"PRId64" bytes", (uint64_t) sb.st_size );
for( i = 0; i < mux->ntracks; ++i )
{
+ hb_buffer_t * b;
track = mux->track[i];
+ while ( (b = mf_pull( track )) != NULL )
+ {
+ hb_buffer_close( &b );
+ }
if( track->mux_data )
{
free( track->mux_data );
}
w->status = w->work( w, &buf_in, NULL );
+ if( buf_in )
+ {
+ hb_buffer_close( &buf_in );
+ }
}
}
muxer->private_data->track = mux->ntracks;
muxer->fifo_in = job->fifo_mpeg4;
add_mux_track( mux, job->mux_data, 1 );
- muxer->done = &job->done;
- muxer->thread = hb_thread_init( muxer->name, mux_loop, muxer, HB_NORMAL_PRIORITY );
+ muxer->done = &muxer->private_data->mux->done;
for( i = 0; i < hb_list_count( title->list_audio ); i++ )
{