summaryrefslogtreecommitdiffstats
path: root/libhb/muxcommon.c
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2015-11-03 09:46:28 -0800
committerJohn Stebbins <[email protected]>2015-11-09 11:06:59 -0800
commita986f54a4109bb8c3b2fb57849b4b0ea01e3c522 (patch)
tree7add9d007dc8bdd72114637c8f3f7361621ad4a5 /libhb/muxcommon.c
parent63b340ebc33d57aeda22e340dab48b1df2106541 (diff)
libhb: make muxer, sync, and reader behave like other work objects
simplify job initialization sequence, clean up code, and document dependencies in the sequence better. Make hb_add set job->sequence_id. It is no longer necessary for the frontend to do this. If the frontend needs the sequence_id, it is returned by hb_add(). Clean up use of interjob. do_job() now uses sequence_id to detect when a new sequence of related jobs is running and automatically clears interjob.
Diffstat (limited to 'libhb/muxcommon.c')
-rw-r--r--libhb/muxcommon.c275
1 files changed, 126 insertions, 149 deletions
diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c
index 990614540..452e41fb0 100644
--- a/libhb/muxcommon.c
+++ b/libhb/muxcommon.c
@@ -43,7 +43,6 @@ typedef struct
typedef struct
{
hb_lock_t * mutex;
- int ref;
int done;
hb_mux_object_t * m;
double pts; // end time of next muxing chunk
@@ -60,9 +59,10 @@ typedef struct
struct hb_work_private_s
{
- hb_job_t * job;
- int track;
- hb_mux_t * mux;
+ hb_job_t * job;
+ int track;
+ hb_mux_t * mux;
+ hb_list_t * list_work;
};
@@ -444,6 +444,7 @@ static int muxWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
if ( i >= mux->ntracks )
{
mux->done = 1;
+ *w->done = 1;
hb_unlock( mux->mutex );
hb_bitvec_free(&more);
return HB_WORK_DONE;
@@ -477,147 +478,133 @@ static void muxFlush(hb_mux_t * mux)
}
}
-static void muxClose( hb_work_object_t * w )
+static void muxClose( hb_work_object_t * muxer )
{
- hb_work_private_t * pv = w->private_data;
- hb_mux_t * mux = pv->mux;
- hb_job_t * job = pv->job;
- hb_track_t * track;
- int i;
+ hb_work_private_t * pv = muxer->private_data;
+ if (pv == NULL)
+ {
+ // Not initialized
+ return;
+ }
+
+ hb_mux_t * mux = pv->mux;
+ hb_job_t * job = pv->job;
+ hb_track_t * track;
+ hb_work_object_t * w;
+ int i;
hb_lock( mux->mutex );
- if ( --mux->ref == 0 )
+ muxFlush(mux);
+
+ // 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_id == HB_PASS_ENCODE ||
+ job->pass_id == HB_PASS_ENCODE_2ND )
{
- muxFlush(mux);
-
- // 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_id == HB_PASS_ENCODE ||
- job->pass_id == HB_PASS_ENCODE_2ND )
- {
- /* 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( mux->m )
+ {
+ mux->m->end( mux->m );
+ free( mux->m );
+ }
+
+ // we're all done muxing -- print final stats and cleanup.
+ if( job->pass_id == HB_PASS_ENCODE ||
+ job->pass_id == HB_PASS_ENCODE_2ND )
+ {
+ hb_stat_t sb;
+ uint64_t bytes_total, frames_total;
- // we're all done muxing -- print final stats and cleanup.
- if( job->pass_id == HB_PASS_ENCODE ||
- job->pass_id == HB_PASS_ENCODE_2ND )
+ if (!hb_stat(job->file, &sb))
{
- hb_stat_t sb;
- uint64_t bytes_total, frames_total;
+ hb_deep_log( 2, "mux: file size, %"PRId64" bytes", (uint64_t) sb.st_size );
- if (!hb_stat(job->file, &sb))
+ bytes_total = 0;
+ frames_total = 0;
+ for( i = 0; i < mux->ntracks; ++i )
{
- 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 )
- {
- 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 )
- {
- /* 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;
- }
-
- if( bytes_total && frames_total )
+ 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 )
{
- hb_deep_log( 2, "mux: overhead, %.2f bytes per frame",
- (float) ( sb.st_size - bytes_total ) /
- frames_total );
+ /* 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;
}
- }
- for( i = 0; i < mux->ntracks; ++i )
- {
- hb_buffer_t * b;
- track = mux->track[i];
- while ( (b = mf_pull( mux, i )) != NULL )
- {
- hb_buffer_close( &b );
- }
- if( track->mux_data )
+ if( bytes_total && frames_total )
{
- free( track->mux_data );
- free( track->mf.fifo );
+ hb_deep_log( 2, "mux: overhead, %.2f bytes per frame",
+ (float) ( sb.st_size - bytes_total ) /
+ frames_total );
}
- free( track );
}
- free(mux->track);
- hb_unlock( mux->mutex );
- hb_lock_close( &mux->mutex );
- hb_bitvec_free(&mux->eof);
- hb_bitvec_free(&mux->rdy);
- hb_bitvec_free(&mux->allEof);
- hb_bitvec_free(&mux->allRdy);
- free( mux );
- }
- else
- {
- hb_unlock( mux->mutex );
}
- free( pv );
- w->private_data = NULL;
-}
-
-static void mux_loop( void * _w )
-{
- hb_work_object_t * w = _w;
- hb_work_private_t * pv = w->private_data;
- hb_job_t * job = pv->job;
- hb_buffer_t * buf_in;
- while ( !*job->die && w->status != HB_WORK_DONE )
+ for (i = 0; i < mux->ntracks; ++i)
{
- buf_in = hb_fifo_get_wait( w->fifo_in );
- if ( pv->mux->done )
- break;
- if ( buf_in == NULL )
- continue;
- if ( *job->die )
+ hb_buffer_t * b;
+ track = mux->track[i];
+ while ( (b = mf_pull( mux, i )) != NULL )
{
- if( buf_in )
- {
- hb_buffer_close( &buf_in );
- }
- break;
+ hb_buffer_close( &b );
}
-
- w->status = w->work( w, &buf_in, NULL );
- if( buf_in )
+ if( track->mux_data )
+ {
+ free( track->mux_data );
+ free( track->mf.fifo );
+ }
+ free( track );
+ }
+ free(mux->track);
+ hb_unlock( mux->mutex );
+ hb_lock_close( &mux->mutex );
+ hb_bitvec_free(&mux->eof);
+ hb_bitvec_free(&mux->rdy);
+ hb_bitvec_free(&mux->allEof);
+ hb_bitvec_free(&mux->allRdy);
+ free( mux );
+
+ // Close mux work threads
+ while ((w = hb_list_item(pv->list_work, 0)))
+ {
+ hb_list_rem(pv->list_work, w);
+ if (w->thread != NULL)
{
- hb_buffer_close( &buf_in );
+ hb_thread_close( &w->thread );
}
+ free(w->private_data);
+ free(w);
}
+ hb_list_close(&pv->list_work);
+ free( pv );
+ muxer->private_data = NULL;
}
-hb_work_object_t * hb_muxer_init( hb_job_t * job )
+static int muxInit( hb_work_object_t * muxer, hb_job_t * job )
{
- int i;
- hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
- hb_work_object_t * w;
- hb_work_object_t * muxer;
+ muxer->private_data = calloc( sizeof( hb_work_private_t ), 1 );
+ hb_work_private_t * pv = muxer->private_data;
+
+ hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
+ int i;
+ hb_work_object_t * w;
+
+ pv->list_work = hb_list_init();
// The bit vectors must be allocated before hb_thread_init for the
// audio and subtitle muxer jobs below.
@@ -649,7 +636,7 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
hb_error( "No muxer selected, exiting" );
*job->done_error = HB_ERROR_INIT;
*job->die = 1;
- return NULL;
+ return -1;
}
/* Create file, write headers */
if( mux->m )
@@ -659,60 +646,50 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
}
/* Initialize the work objects that will receive fifo data */
-
- muxer = hb_get_work( job->h, WORK_MUX );
- muxer->private_data = calloc( sizeof( hb_work_private_t ), 1 );
- muxer->private_data->job = job;
- muxer->private_data->mux = mux;
- mux->ref++;
- muxer->private_data->track = mux->ntracks;
+ pv->job = job;
+ pv->mux = mux;
+ pv->track = mux->ntracks;
muxer->fifo_in = job->fifo_mpeg4;
add_mux_track( mux, job->mux_data, 1 );
- muxer->done = &muxer->private_data->mux->done;
- for( i = 0; i < hb_list_count( job->list_audio ); i++ )
+ for (i = 0; i < hb_list_count(job->list_audio); i++)
{
hb_audio_t *audio = hb_list_item( job->list_audio, i );
- w = hb_get_work( job->h, WORK_MUX );
- w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
+ w = hb_get_work(job->h, WORK_MUX);
+ w->private_data = calloc(sizeof(hb_work_private_t), 1);
w->private_data->job = job;
w->private_data->mux = mux;
- mux->ref++;
w->private_data->track = mux->ntracks;
w->fifo_in = audio->priv.fifo_out;
- add_mux_track( mux, audio->priv.mux_data, 1 );
- w->done = &job->done;
- hb_list_add( job->list_work, w );
- w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
+ add_mux_track(mux, audio->priv.mux_data, 1);
+ hb_list_add(pv->list_work, w);
}
- for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
+ for (i = 0; i < hb_list_count(job->list_subtitle); i++)
{
hb_subtitle_t *subtitle = hb_list_item( job->list_subtitle, i );
if (subtitle->config.dest != PASSTHRUSUB)
continue;
- w = hb_get_work( job->h, WORK_MUX );
- w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
+ w = hb_get_work(job->h, WORK_MUX);
+ w->private_data = calloc(sizeof(hb_work_private_t), 1);
w->private_data->job = job;
w->private_data->mux = mux;
- mux->ref++;
w->private_data->track = mux->ntracks;
w->fifo_in = subtitle->fifo_out;
- add_mux_track( mux, subtitle->mux_data, 0 );
- w->done = &job->done;
- hb_list_add( job->list_work, w );
- w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
+ add_mux_track(mux, subtitle->mux_data, 0);
+ hb_list_add(pv->list_work, w);
}
- return muxer;
-}
-// muxInit does nothing because the muxer has a special initializer
-// that takes care of initializing all muxer work objects
-static int muxInit( hb_work_object_t * w, hb_job_t * job )
-{
+ /* Launch processing threads */
+ for (i = 0; i < hb_list_count(pv->list_work); i++)
+ {
+ w = hb_list_item(pv->list_work, i);
+ w->done = muxer->done;
+ w->thread = hb_thread_init(w->name, hb_work_loop, w, HB_LOW_PRIORITY);
+ }
return 0;
}