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. */
9 #define MAX_BUFFERING (1024*1024*50)
11 struct hb_mux_object_s
19 uint32_t in; // number of bufs put into fifo
20 uint32_t out; // number of bufs taken out of fifo
21 uint32_t flen; // fifo length (must be power of two)
26 hb_mux_data_t * mux_data;
39 double pts; // end time of next muxing chunk
40 double interleave; // size in 90KHz ticks of media chunks we mux
41 uint32_t ntracks; // total number of tracks we're muxing
42 uint32_t eof; // bitmask of track with eof
43 uint32_t rdy; // bitmask of tracks ready to output
44 uint32_t allEof; // valid bits in eof (all tracks)
45 uint32_t allRdy; // valid bits in rdy (audio & video tracks)
46 hb_track_t * track[32]; // array of tracks to mux ('ntrack' elements)
47 // NOTE- this array could be dynamically
48 // allocated but the eof & rdy logic has to
49 // be changed to handle more than 32 tracks
50 // anyway so we keep it simple and fast.
53 struct hb_work_private_s
60 // The muxer handles two different kinds of media: Video and audio tracks
61 // are continuous: once they start they generate continuous, consecutive
62 // sequence of bufs until they end. The muxer will time align all continuous
63 // media tracks so that their data will be well interleaved in the output file.
64 // (Smooth, low latency playback with minimal player buffering requires that
65 // data that's going to be presented close together in time also be close
66 // together in the output file). Since HB's audio and video encoders run at
67 // different speeds, the time-aligning involves buffering *all* the continuous
68 // media tracks until a frame with a timestamp beyond the current alignment
69 // point arrives on the slowest fifo (usually the video encoder).
71 // The other kind of media, subtitles, close-captions, vobsubs and
72 // similar tracks, are intermittent. They generate frames sporadically or on
73 // human time scales (seconds) rather than near the video frame rate (milliseconds).
74 // If intermittent sources were treated like continuous sources huge sections of
75 // audio and video would get buffered waiting for the next subtitle to show up.
76 // To keep this from happening the muxer doesn't wait for intermittent tracks
77 // (essentially it assumes that they will always go through the HB processing
78 // pipeline faster than the associated video). They are still time aligned and
79 // interleaved at the appropriate point in the output file.
81 // This routine adds another track for the muxer to process. The media input
82 // stream will be read from HandBrake fifo 'fifo'. Buffers read from that
83 // stream will be time-aligned with all the other media streams then passed
84 // to the container-specific 'mux' routine with argument 'mux_data' (see
85 // routine OutputTrackChunk). 'is_continuous' must be 1 for an audio or video
86 // track and 0 otherwise (see above).
88 static void add_mux_track( hb_mux_t *mux, hb_mux_data_t *mux_data,
91 int max_tracks = sizeof(mux->track) / sizeof(*(mux->track));
92 if ( mux->ntracks >= max_tracks )
94 hb_error( "add_mux_track: too many tracks (>%d)", max_tracks );
98 hb_track_t *track = calloc( sizeof( hb_track_t ), 1 );
99 track->mux_data = mux_data;
101 track->mf.fifo = calloc( sizeof(track->mf.fifo[0]), track->mf.flen );
103 int t = mux->ntracks++;
104 mux->track[t] = track;
105 mux->allEof |= 1 << t;
106 mux->allRdy |= is_continuous << t;
109 static int mf_full( hb_track_t * track )
111 if ( track->buffered_size > MAX_BUFFERING )
117 static void mf_push( hb_mux_t * mux, int tk, hb_buffer_t *buf )
119 hb_track_t * track = mux->track[tk];
120 uint32_t mask = track->mf.flen - 1;
121 uint32_t in = track->mf.in;
123 if ( track->buffered_size > MAX_BUFFERING )
125 mux->rdy = mux->allRdy;
127 if ( ( ( in + 1 ) & mask ) == ( track->mf.out & mask ) )
129 // fifo is full - expand it to double the current size.
130 // This is a bit tricky because when we change the size
131 // it changes the modulus (mask) used to convert the in
132 // and out counters to fifo indices. Since existing items
133 // will be referenced at a new location after the expand
134 // we can't just realloc the fifo. If there were
135 // hundreds of fifo entries it would be worth it to have code
136 // for each of the four possible before/after configurations
137 // but these fifos are small so we just allocate a new chunk
138 // of memory then do element by element copies using the old &
139 // new masks then free the old fifo's memory..
141 uint32_t nmask = track->mf.flen - 1;
142 hb_buffer_t **nfifo = malloc( track->mf.flen * sizeof(*nfifo) );
143 int indx = track->mf.out;
144 while ( indx != track->mf.in )
146 nfifo[indx & nmask] = track->mf.fifo[indx & mask];
149 free( track->mf.fifo );
150 track->mf.fifo = nfifo;
153 track->mf.fifo[in & mask] = buf;
154 track->mf.in = in + 1;
155 track->buffered_size += buf->alloc;
158 static hb_buffer_t *mf_pull( hb_track_t *track )
160 hb_buffer_t *b = NULL;
161 if ( track->mf.out != track->mf.in )
163 // the fifo isn't empty
164 b = track->mf.fifo[track->mf.out & (track->mf.flen - 1)];
167 track->buffered_size -= b->alloc;
172 static hb_buffer_t *mf_peek( hb_track_t *track )
174 return track->mf.out == track->mf.in ?
175 NULL : track->mf.fifo[track->mf.out & (track->mf.flen - 1)];
178 static void MoveToInternalFifos( int tk, hb_mux_t *mux, hb_buffer_t * buf )
180 // move all the buffers on the track's fifo to our internal
181 // fifo so that (a) we don't deadlock in the reader and
182 // (b) we can control how data from multiple tracks is
183 // interleaved in the output file.
184 mf_push( mux, tk, buf );
185 if ( buf->stop >= mux->pts )
187 // buffer is past our next interleave point so
188 // note that this track is ready to be output.
189 mux->rdy |= ( 1 << tk );
193 static void OutputTrackChunk( hb_mux_t *mux, hb_track_t *track, hb_mux_object_t *m )
197 while ( ( buf = mf_peek( track ) ) != NULL && buf->start < mux->pts )
199 buf = mf_pull( track );
201 track->bytes += buf->size;
202 m->mux( m, track->mux_data, buf );
206 static int muxWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
207 hb_buffer_t ** buf_out )
209 hb_work_private_t * pv = w->private_data;
210 hb_job_t * job = pv->job;
211 hb_mux_t * mux = pv->mux;
214 hb_buffer_t * buf = *buf_in;
216 hb_lock( mux->mutex );
219 hb_unlock( mux->mutex );
223 if ( buf->size <= 0 )
225 // EOF - mark this track as done
226 hb_buffer_close( &buf );
227 mux->eof |= ( 1 << pv->track );
228 mux->rdy |= ( 1 << pv->track );
230 else if ( ( job->pass != 0 && job->pass != 2 ) ||
231 ( mux->eof & (1 << pv->track) ) )
233 hb_buffer_close( &buf );
237 MoveToInternalFifos( pv->track, mux, buf );
241 if ( ( mux->rdy & mux->allRdy ) != mux->allRdy )
243 hb_unlock( mux->mutex );
248 // all tracks have at least 'interleave' ticks of data. Output
249 // all that we can in 'interleave' size chunks.
250 while ( (( mux->rdy & mux->allRdy ) == mux->allRdy && more) ||
251 ( mux->eof == mux->allEof ) )
254 for ( i = 0; i < mux->ntracks; ++i )
256 track = mux->track[i];
257 OutputTrackChunk( mux, track, mux->m );
258 if ( mf_full( track ) )
260 // If the track's fifo is still full, advance
261 // the currint interleave point and try again.
262 mux->rdy = mux->allRdy;
266 // if the track is at eof or still has data that's past
267 // our next interleave point then leave it marked as rdy.
268 // Otherwise clear rdy.
269 if ( ( mux->eof & (1 << i) ) == 0 &&
270 ( track->mf.out == track->mf.in ||
271 track->mf.fifo[(track->mf.in-1) & (track->mf.flen-1)]->stop
272 < mux->pts + mux->interleave ) )
274 mux->rdy &=~ ( 1 << i );
276 if ( track->mf.out != track->mf.in )
282 // if all the tracks are at eof we're just purging their
283 // remaining data -- keep going until all internal fifos are empty.
284 if ( mux->eof == mux->allEof )
286 for ( i = 0; i < mux->ntracks; ++i )
288 if ( mux->track[i]->mf.out != mux->track[i]->mf.in )
293 if ( i >= mux->ntracks )
296 hb_unlock( mux->mutex );
300 mux->pts += mux->interleave;
302 hb_unlock( mux->mutex );
306 void muxClose( hb_work_object_t * w )
308 hb_work_private_t * pv = w->private_data;
309 hb_mux_t * mux = pv->mux;
310 hb_job_t * job = pv->job;
314 hb_lock( mux->mutex );
315 if ( --mux->ref == 0 )
317 // Update state before closing muxer. Closing the muxer
318 // may initiate optimization which can take a while and
319 // we want the muxing state to be visible while this is
321 if( job->pass == 0 || job->pass == 2 )
325 state.state = HB_STATE_MUXING;
326 state.param.muxing.progress = 0;
327 hb_set_state( job->h, &state );
332 mux->m->end( mux->m );
336 // we're all done muxing -- print final stats and cleanup.
337 if( job->pass == 0 || job->pass == 2 )
340 uint64_t bytes_total, frames_total;
342 if( !stat( job->file, &sb ) )
344 hb_deep_log( 2, "mux: file size, %"PRId64" bytes", (uint64_t) sb.st_size );
348 for( i = 0; i < mux->ntracks; ++i )
350 track = mux->track[i];
351 hb_log( "mux: track %d, %"PRId64" frames, %"PRId64" bytes, %.2f kbps, fifo %d",
352 i, track->frames, track->bytes,
353 90000.0 * track->bytes / mux->pts / 125,
355 if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) )
358 hb_deep_log( 2, "mux: video bitrate error, %+"PRId64" bytes",
359 (int64_t)(track->bytes - mux->pts * job->vbitrate * 125 / 90000) );
361 bytes_total += track->bytes;
362 frames_total += track->frames;
365 if( bytes_total && frames_total )
367 hb_deep_log( 2, "mux: overhead, %.2f bytes per frame",
368 (float) ( sb.st_size - bytes_total ) /
374 for( i = 0; i < mux->ntracks; ++i )
377 track = mux->track[i];
378 while ( (b = mf_pull( track )) != NULL )
380 hb_buffer_close( &b );
382 if( track->mux_data )
384 free( track->mux_data );
385 free( track->mf.fifo );
389 hb_unlock( mux->mutex );
390 hb_lock_close( &mux->mutex );
395 hb_unlock( mux->mutex );
398 w->private_data = NULL;
401 static void mux_loop( void * _w )
403 hb_work_object_t * w = _w;
404 hb_work_private_t * pv = w->private_data;
405 hb_job_t * job = pv->job;
406 hb_buffer_t * buf_in;
408 while ( !*job->die && w->status != HB_WORK_DONE )
410 buf_in = hb_fifo_get_wait( w->fifo_in );
413 if ( buf_in == NULL )
419 hb_buffer_close( &buf_in );
424 w->status = w->work( w, &buf_in, NULL );
427 hb_buffer_close( &buf_in );
432 hb_work_object_t * hb_muxer_init( hb_job_t * job )
434 hb_title_t * title = job->title;
436 hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
437 hb_work_object_t * w;
438 hb_work_object_t * muxer;
440 mux->mutex = hb_lock_init();
442 // set up to interleave track data in blocks of 1 video frame time.
443 // (the best case for buffering and playout latency). The container-
444 // specific muxers can reblock this into bigger chunks if necessary.
445 mux->interleave = 90000. * (double)job->vrate_base / (double)job->vrate;
446 mux->pts = mux->interleave;
448 /* Get a real muxer */
449 if( job->pass == 0 || job->pass == 2)
454 mux->m = hb_mux_mp4_init( job );
457 mux->m = hb_mux_mkv_init( job );
460 hb_error( "No muxer selected, exiting" );
464 /* Create file, write headers */
467 mux->m->init( mux->m );
471 /* Initialize the work objects that will receive fifo data */
473 muxer = hb_get_work( WORK_MUX );
474 muxer->private_data = calloc( sizeof( hb_work_private_t ), 1 );
475 muxer->private_data->job = job;
476 muxer->private_data->mux = mux;
478 muxer->private_data->track = mux->ntracks;
479 muxer->fifo_in = job->fifo_mpeg4;
480 add_mux_track( mux, job->mux_data, 1 );
481 muxer->done = &muxer->private_data->mux->done;
483 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
485 hb_audio_t *audio = hb_list_item( title->list_audio, i );
487 w = hb_get_work( WORK_MUX );
488 w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
489 w->private_data->job = job;
490 w->private_data->mux = mux;
492 w->private_data->track = mux->ntracks;
493 w->fifo_in = audio->priv.fifo_out;
494 add_mux_track( mux, audio->priv.mux_data, 1 );
495 w->done = &job->done;
496 hb_list_add( job->list_work, w );
497 w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
500 for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
502 hb_subtitle_t *subtitle = hb_list_item( title->list_subtitle, i );
504 if (subtitle->config.dest != PASSTHRUSUB)
507 w = hb_get_work( WORK_MUX );
508 w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
509 w->private_data->job = job;
510 w->private_data->mux = mux;
512 w->private_data->track = mux->ntracks;
513 w->fifo_in = subtitle->fifo_out;
514 add_mux_track( mux, subtitle->mux_data, 0 );
515 w->done = &job->done;
516 hb_list_add( job->list_work, w );
517 w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
522 // muxInit does nothing because the muxer has a special initializer
523 // that takes care of initializing all muxer work objects
524 static int muxInit( hb_work_object_t * w, hb_job_t * job )
529 hb_work_object_t hb_muxer =