X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fmuxcommon.c;h=cb61739acc9df634077094d4cf21b2fcb5082a33;hb=8d3d6aaf3b18b8694ae556bf8c2d0d1c03a1a210;hp=dbaa9c4782fcb34a84ee6c7c2df1244e974253e0;hpb=a7f8bd6842d316d2a19cf63355b1d343a244b42d;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c index dbaa9c47..cb61739a 100644 --- a/libhb/muxcommon.c +++ b/libhb/muxcommon.c @@ -6,6 +6,8 @@ #include "hb.h" +#define MAX_BUFFERING (1024*1024*50) + struct hb_mux_object_s { HB_MUX_COMMON; @@ -25,6 +27,7 @@ typedef struct uint64_t frames; uint64_t bytes; mux_fifo_t mf; + int buffered_size; } hb_track_t; typedef struct @@ -103,10 +106,24 @@ static void add_mux_track( hb_mux_t *mux, hb_mux_data_t *mux_data, mux->allRdy |= is_continuous << t; } -static void mf_push( hb_track_t *track, hb_buffer_t *buf ) +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 ( track->buffered_size > MAX_BUFFERING ) + { + mux->rdy = mux->allRdy; + } if ( ( ( in + 1 ) & mask ) == ( track->mf.out & mask ) ) { // fifo is full - expand it to double the current size. @@ -135,6 +152,7 @@ static void mf_push( hb_track_t *track, hb_buffer_t *buf ) } 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 ) @@ -145,6 +163,8 @@ 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; } @@ -157,13 +177,11 @@ static hb_buffer_t *mf_peek( hb_track_t *track ) static void MoveToInternalFifos( int tk, hb_mux_t *mux, hb_buffer_t * buf ) { - hb_track_t *track = mux->track[tk]; - // move all the buffers on the track's fifo to our internal // fifo so that (a) we don't deadlock in the reader and // (b) we can control how data from multiple tracks is // interleaved in the output file. - mf_push( track, buf ); + mf_push( mux, tk, buf ); if ( buf->stop >= mux->pts ) { // buffer is past our next interleave point so @@ -178,10 +196,10 @@ static void OutputTrackChunk( hb_mux_t *mux, hb_track_t *track, hb_mux_object_t 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; - hb_buffer_close( &buf ); + m->mux( m, track->mux_data, buf ); } } @@ -226,14 +244,23 @@ static int muxWork( hb_work_object_t * w, hb_buffer_t ** buf_in, 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. @@ -245,6 +272,10 @@ static int muxWork( hb_work_object_t * w, hb_buffer_t ** buf_in, { 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 @@ -279,62 +310,74 @@ void muxClose( hb_work_object_t * w ) hb_track_t * track; int i; - // we're all done muxing -- print final stats and cleanup. - if( job->pass == 0 || job->pass == 2 ) + hb_lock( mux->mutex ); + if ( --mux->ref == 0 ) { - struct stat sb; - uint64_t bytes_total, frames_total; + // 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 ); + } - /* 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 ); + free( mux->m ); + } - if( !stat( job->file, &sb ) ) + // we're all done muxing -- print final stats and cleanup. + if( job->pass == 0 || job->pass == 2 ) { - hb_deep_log( 2, "mux: file size, %"PRId64" bytes", (uint64_t) sb.st_size ); + struct stat sb; + uint64_t bytes_total, frames_total; - bytes_total = 0; - frames_total = 0; - for( i = 0; i < mux->ntracks; ++i ) + if( !stat( job->file, &sb ) ) { - track = mux->track[i]; - hb_log( "mux: track %d, %"PRId64" frames, %"PRId64" bytes, %.2f kbps, fifo %d", - i, track->frames, track->bytes, - 90000.0 * track->bytes / mux->pts / 125, - track->mf.flen ); - if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) ) + hb_deep_log( 2, "mux: file size, %"PRId64" bytes", (uint64_t) sb.st_size ); + + bytes_total = 0; + frames_total = 0; + for( i = 0; i < mux->ntracks; ++i ) { - /* Video */ - hb_deep_log( 2, "mux: video bitrate error, %+"PRId64" bytes", - (int64_t)(track->bytes - mux->pts * job->vbitrate * 125 / 90000) ); + track = mux->track[i]; + hb_log( "mux: track %d, %"PRId64" frames, %"PRId64" bytes, %.2f kbps, fifo %d", + i, track->frames, track->bytes, + 90000.0 * track->bytes / mux->pts / 125, + track->mf.flen ); + if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) ) + { + /* Video */ + hb_deep_log( 2, "mux: video bitrate error, %+"PRId64" bytes", + (int64_t)(track->bytes - mux->pts * job->vbitrate * 125 / 90000) ); + } + bytes_total += track->bytes; + frames_total += track->frames; } - bytes_total += track->bytes; - frames_total += track->frames; - } - if( bytes_total && frames_total ) - { - hb_deep_log( 2, "mux: overhead, %.2f bytes per frame", - (float) ( sb.st_size - bytes_total ) / - frames_total ); + if( bytes_total && frames_total ) + { + hb_deep_log( 2, "mux: overhead, %.2f bytes per frame", + (float) ( sb.st_size - bytes_total ) / + frames_total ); + } } } - } - hb_lock( mux->mutex ); - if ( --mux->ref == 0 ) - { - if( mux->m ) - { - mux->m->end( mux->m ); - free( mux->m ); - } - 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 ); @@ -369,9 +412,19 @@ static void mux_loop( void * _w ) if ( buf_in == NULL ) continue; if ( *job->die ) + { + if( buf_in ) + { + hb_buffer_close( &buf_in ); + } break; + } w->status = w->work( w, &buf_in, NULL ); + if( buf_in ) + { + hb_buffer_close( &buf_in ); + } } } @@ -432,8 +485,7 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job ) 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++ ) {