diff options
Diffstat (limited to 'libhb/muxcommon.c')
-rw-r--r-- | libhb/muxcommon.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c new file mode 100644 index 000000000..090f332b2 --- /dev/null +++ b/libhb/muxcommon.c @@ -0,0 +1,215 @@ +/* $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/>. + It may be used under the terms of the GNU General Public License. */ + +#include "hb.h" + +struct hb_mux_object_s +{ + HB_MUX_COMMON; +}; + +typedef struct +{ + hb_job_t * job; + uint64_t pts; + +} hb_mux_t; + +typedef struct +{ + hb_fifo_t * fifo; + hb_mux_data_t * mux_data; + uint64_t frames; + uint64_t bytes; + +} hb_track_t; + +static hb_track_t * GetTrack( hb_list_t * list ) +{ + hb_buffer_t * buf; + hb_track_t * track = NULL, * track2; + int64_t pts = 0; + int i; + + for( i = 0; i < hb_list_count( list ); i++ ) + { + track2 = hb_list_item( list, i ); + buf = hb_fifo_see( track2->fifo ); + if( !buf ) + { + return NULL; + } + if( !track || buf->start < pts ) + { + track = track2; + pts = buf->start; + } + } + return track; +} + +static void MuxerFunc( void * _mux ) +{ + hb_mux_t * mux = _mux; + hb_job_t * job = mux->job; + hb_title_t * title = job->title; + hb_audio_t * audio; + hb_list_t * list; + hb_buffer_t * buf; + hb_track_t * track; + int i; + + hb_mux_object_t * m = NULL; + + /* Get a real muxer */ + if( job->pass != 1 ) + { + switch( job->mux ) + { + case HB_MUX_MP4: + m = hb_mux_mp4_init( job ); + break; + case HB_MUX_AVI: + m = hb_mux_avi_init( job ); + break; + case HB_MUX_OGM: + m = hb_mux_ogm_init( job ); + break; + } + } + + /* 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 ) + { + m->init( m ); + } + + /* Build list of fifos we're interested in */ + list = hb_list_init(); + + track = calloc( sizeof( hb_track_t ), 1 ); + track->fifo = job->fifo_mpeg4; + track->mux_data = job->mux_data; + hb_list_add( list, track ); + + for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + { + 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; + hb_list_add( list, track ); + } + + while( !*job->die && !job->done ) + { + if( !( track = GetTrack( list ) ) ) + { + hb_snooze( 50 ); + continue; + } + + buf = hb_fifo_get( track->fifo ); + if( job->pass != 1 ) + { + m->mux( m, track->mux_data, buf ); + track->frames += 1; + track->bytes += buf->size; + mux->pts = buf->stop; + } + hb_buffer_close( &buf ); + } + + if( job->pass != 1 ) + { + struct stat sb; + uint64_t bytes_total, frames_total; + + m->end( m ); + + if( !stat( job->file, &sb ) ) + { + hb_log( "mux: file size, %lld bytes", (uint64_t) sb.st_size ); + + bytes_total = 0; + frames_total = 0; + for( i = 0; i < hb_list_count( list ); i++ ) + { + track = hb_list_item( list, i ); + hb_log( "mux: track %d, %lld bytes, %.2f kbps", + i, track->bytes, + 90000.0 * track->bytes / mux->pts / 125 ); + if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) ) + { + /* Video */ + hb_log( "mux: video bitrate error, %+lld bytes", + track->bytes - mux->pts * job->vbitrate * + 125 / 90000 ); + } + bytes_total += track->bytes; + frames_total += track->frames; + } + + if( bytes_total && frames_total ) + { + hb_log( "mux: overhead, %.2f bytes per frame", + (float) ( sb.st_size - bytes_total ) / + frames_total ); + } + } + } + + free( m ); + + for( i = 0; i < hb_list_count( list ); i++ ) + { + track = hb_list_item( list, i ); + if( track->mux_data ) + { + free( track->mux_data ); + } + free( track ); + } + hb_list_close( &list ); + + free( mux ); +} + +hb_thread_t * hb_muxer_init( hb_job_t * job ) +{ + hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 ); + mux->job = job; + return hb_thread_init( "muxer", MuxerFunc, mux, + HB_NORMAL_PRIORITY ); +} |