1 /* $Id: muxcommon.c,v 1.23 2005/03/30 17:27:19 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
24 hb_mux_data_t * mux_data;
30 static hb_track_t * GetTrack( hb_list_t * list, hb_job_t *job )
33 hb_track_t * track = NULL, * track2;
37 for( i = 0; i < hb_list_count( list ); i++ )
39 track2 = hb_list_item( list, i );
42 buf = hb_fifo_see( track2->fifo );
45 // XXX the libmkv muxer will produce unplayable files if the
46 // audio & video are far out of sync. To keep them in sync we require
47 // that *all* fifos have a buffer then we take the oldest.
48 // Unfortunately this means we can hang in a deadlock with the
49 // reader process filling the fifos.
50 if ( job->mux == HB_MUX_MKV )
55 // To make sure we don't camp on one fifo & prevent the others
56 // from making progress we take the earliest data of all the
57 // data that's currently available but we don't care if some
58 // fifos don't have data.
63 // EOF - mark this track as done
64 buf = hb_fifo_get( track2->fifo );
65 hb_buffer_close( &buf );
69 if( !track || buf->start < pts )
79 static int AllTracksDone( hb_list_t * list )
84 for( i = 0; i < hb_list_count( list ); i++ )
86 track = hb_list_item( list, i );
87 if ( track->eof == 0 )
95 static void MuxerFunc( void * _mux )
97 hb_mux_t * mux = _mux;
98 hb_job_t * job = mux->job;
99 hb_title_t * title = job->title;
106 hb_mux_object_t * m = NULL;
108 /* Get a real muxer */
109 if( job->pass == 0 || job->pass == 2)
116 m = hb_mux_mp4_init( job );
119 m = hb_mux_avi_init( job );
122 m = hb_mux_ogm_init( job );
125 m = hb_mux_mkv_init( job );
129 /* Create file, write headers */
130 if( job->pass == 0 || job->pass == 2 )
135 /* Build list of fifos we're interested in */
136 list = hb_list_init();
138 track = calloc( sizeof( hb_track_t ), 1 );
139 track->fifo = job->fifo_mpeg4;
140 track->mux_data = job->mux_data;
141 hb_list_add( list, track );
143 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
145 audio = hb_list_item( title->list_audio, i );
146 track = calloc( sizeof( hb_track_t ), 1 );
147 track->fifo = audio->priv.fifo_out;
148 track->mux_data = audio->priv.mux_data;
149 hb_list_add( list, track );
152 int thread_sleep_interval = 50;
155 if( !( track = GetTrack( list, job ) ) )
157 if ( AllTracksDone( list ) )
159 // all our input fifos have signaled EOF
162 hb_snooze( thread_sleep_interval );
166 buf = hb_fifo_get( track->fifo );
167 if( job->pass == 0 || job->pass == 2 )
169 m->mux( m, track->mux_data, buf );
171 track->bytes += buf->size;
172 mux->pts = buf->stop;
174 hb_buffer_close( &buf );
177 if( job->pass == 0 || job->pass == 2 )
180 uint64_t bytes_total, frames_total;
182 #define p state.param.muxing
185 state.state = HB_STATE_MUXING;
187 hb_set_state( job->h, &state );
191 if( !stat( job->file, &sb ) )
193 hb_deep_log( 2, "mux: file size, %lld bytes", (uint64_t) sb.st_size );
197 for( i = 0; i < hb_list_count( list ); i++ )
199 track = hb_list_item( list, i );
200 hb_deep_log( 2, "mux: track %d, %lld bytes, %.2f kbps",
202 90000.0 * track->bytes / mux->pts / 125 );
203 if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) )
206 hb_deep_log( 2, "mux: video bitrate error, %+lld bytes",
207 track->bytes - mux->pts * job->vbitrate *
210 bytes_total += track->bytes;
211 frames_total += track->frames;
214 if( bytes_total && frames_total )
216 hb_deep_log( 2, "mux: overhead, %.2f bytes per frame",
217 (float) ( sb.st_size - bytes_total ) /
225 for( i = 0; i < hb_list_count( list ); i++ )
227 track = hb_list_item( list, i );
228 if( track->mux_data )
230 free( track->mux_data );
234 hb_list_close( &list );
239 hb_thread_t * hb_muxer_init( hb_job_t * job )
241 hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
243 return hb_thread_init( "muxer", MuxerFunc, mux,
244 HB_NORMAL_PRIORITY );