diff options
author | jstebbins <[email protected]> | 2015-03-07 22:25:48 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2015-03-07 22:25:48 +0000 |
commit | 7705413a03a90c16734b40fb7bc492be8b56ab6f (patch) | |
tree | 2b3c861e0a7b78e45869a191b20f7dc57c0fe48b /libhb | |
parent | a4ad5062c3fa1787b208389123bb81ea57483142 (diff) |
json: automatically scan title when processing json jobs
Simplifies the WinGui.
This also changes how jobs are processed. Creating the sub-jobs for
multiple passes is delayed until after scanning and immediately before
running the job.
Working status has also changed. Sub-job passes are identified in status
with an ID that allows the frontend to definitively identify what pass
is in progress.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6976 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/batch.c | 6 | ||||
-rw-r--r-- | libhb/common.c | 9 | ||||
-rw-r--r-- | libhb/common.h | 14 | ||||
-rw-r--r-- | libhb/encavcodec.c | 12 | ||||
-rw-r--r-- | libhb/enctheora.c | 20 | ||||
-rw-r--r-- | libhb/encx264.c | 15 | ||||
-rw-r--r-- | libhb/encx265.c | 7 | ||||
-rw-r--r-- | libhb/hb.c | 108 | ||||
-rw-r--r-- | libhb/hb_json.c | 62 | ||||
-rw-r--r-- | libhb/hb_json.h | 1 | ||||
-rw-r--r-- | libhb/internal.h | 1 | ||||
-rw-r--r-- | libhb/muxavformat.c | 2 | ||||
-rw-r--r-- | libhb/muxcommon.c | 11 | ||||
-rw-r--r-- | libhb/reader.c | 1 | ||||
-rw-r--r-- | libhb/scan.c | 23 | ||||
-rw-r--r-- | libhb/stream.c | 2 | ||||
-rw-r--r-- | libhb/sync.c | 5 | ||||
-rw-r--r-- | libhb/work.c | 77 |
18 files changed, 249 insertions, 127 deletions
diff --git a/libhb/batch.c b/libhb/batch.c index 3aca6b00e..3a08152bb 100644 --- a/libhb/batch.c +++ b/libhb/batch.c @@ -127,7 +127,7 @@ hb_title_t * hb_batch_title_scan( hb_batch_t * d, int t ) return NULL; hb_log( "batch: scanning %s", filename ); - title = hb_title_init( filename, 0 ); + title = hb_title_init( filename, t ); stream = hb_stream_open( filename, title, 1 ); if ( stream == NULL ) { @@ -137,10 +137,6 @@ hb_title_t * hb_batch_title_scan( hb_batch_t * d, int t ) title = hb_stream_title_scan( stream, title ); hb_stream_close( &stream ); - if ( title != NULL ) - { - title->index = t; - } return title; } diff --git a/libhb/common.c b/libhb/common.c index 78b4437c6..339c3919f 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -2582,7 +2582,7 @@ void hb_list_rem( hb_list_t * l, void * p ) *********************************************************************/ void * hb_list_item( const hb_list_t * l, int i ) { - if( i < 0 || i >= l->items_count ) + if( l == NULL || i < 0 || i >= l->items_count ) { return NULL; } @@ -2712,6 +2712,9 @@ void hb_list_close( hb_list_t ** _l ) { hb_list_t * l = *_l; + if (l == NULL) + return; + free( l->items ); free( l ); @@ -3048,7 +3051,7 @@ static void job_setup(hb_job_t * job, hb_title_t * title) job->vquality = -1.0; job->vbitrate = 1000; job->twopass = 0; - job->pass = 0; + job->pass_id = HB_PASS_ENCODE; job->vrate = title->vrate; job->mux = HB_MUX_MP4; @@ -3078,6 +3081,8 @@ static void job_clean( hb_job_t * job ) hb_filter_object_t *filter; hb_attachment_t *attachment; + free((void*)job->json); + job->json = NULL; free(job->encoder_preset); job->encoder_preset = NULL; free(job->encoder_tune); diff --git a/libhb/common.h b/libhb/common.h index 41c5dd822..a8a699387 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -446,6 +446,8 @@ typedef enum *****************************************************************************/ struct hb_job_s { + PRIVATE const char * json; // JSON encoded job string + /* ID assigned by UI so it can groups job passes together */ int sequence_id; @@ -494,7 +496,7 @@ struct hb_job_s int vbitrate; hb_rational_t vrate; int cfr; - PRIVATE int pass; + PRIVATE int pass_id; int twopass; // Enable 2-pass encode. Boolean int fastfirstpass; char *encoder_preset; @@ -605,7 +607,6 @@ struct hb_job_s #ifdef __LIBHB__ /* Internal data */ hb_handle_t * h; - hb_lock_t * pause; volatile hb_error_code * done_error; volatile int * die; volatile int done; @@ -993,9 +994,14 @@ struct hb_state_s struct { /* HB_STATE_WORKING */ +#define HB_PASS_SUBTITLE -1 +#define HB_PASS_ENCODE 0 +#define HB_PASS_ENCODE_1ST 1 // Some code depends on these values being +#define HB_PASS_ENCODE_2ND 2 // 1 and 2. Do not change. + int pass_id; + int pass; + int pass_count; float progress; - int job_cur; - int job_count; float rate_cur; float rate_avg; int hours; diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index b396f9c70..fe479a393 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -99,7 +99,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) // Set things in context that we will allow the user to // override with advanced settings. - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { hb_interjob_t * interjob = hb_interjob_get( job->h ); fps.den = interjob->vrate.den; @@ -237,12 +237,13 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) context->flags |= CODEC_FLAG_GRAY; } - if( job->pass != 0 && job->pass != -1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST || + job->pass_id == HB_PASS_ENCODE_2ND ) { char filename[1024]; memset( filename, 0, 1024 ); hb_get_tempory_filename( job->h, filename, "ffmpeg.log" ); - if( job->pass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST ) { pv->file = hb_fopen(filename, "wb"); context->flags |= CODEC_FLAG_PASS1; @@ -287,7 +288,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) { job->areBframes = 1; } - if( ( job->mux & HB_MUX_MASK_MP4 ) && job->pass != 1 ) + if( ( job->mux & HB_MUX_MASK_MP4 ) && job->pass_id != HB_PASS_ENCODE_1ST ) { w->config->mpeg4.length = context->extradata_size; memcpy( w->config->mpeg4.bytes, context->extradata, @@ -589,7 +590,8 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, buf_last = buf; } /* Write stats */ - if (job->pass == 1 && pv->context->stats_out != NULL) + if (job->pass_id == HB_PASS_ENCODE_1ST && + pv->context->stats_out != NULL) { fprintf( pv->file, "%s", pv->context->stats_out ); } diff --git a/libhb/enctheora.c b/libhb/enctheora.c index 8c9c4cffa..3b9dacebb 100644 --- a/libhb/enctheora.c +++ b/libhb/enctheora.c @@ -44,12 +44,13 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) pv->job = job; - if( job->pass != 0 && job->pass != -1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST || + job->pass_id == HB_PASS_ENCODE_2ND ) { char filename[1024]; memset( filename, 0, 1024 ); hb_get_tempory_filename( job->h, filename, "theroa.log" ); - if ( job->pass == 1 ) + if ( job->pass_id == HB_PASS_ENCODE_1ST ) { pv->file = hb_fopen(filename, "wb"); } @@ -71,7 +72,7 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) ti.frame_height = (job->height + 0xf) & ~0xf; ti.pic_x = ti.pic_y = 0; - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { hb_interjob_t * interjob = hb_interjob_get( job->h ); ti.fps_numerator = interjob->vrate.num; @@ -125,7 +126,8 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) { hb_log("theora: Could not set soft ratecontrol"); } - if( job->pass != 0 && job->pass != -1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST || + job->pass_id == HB_PASS_ENCODE_2ND ) { arg = keyframe_frequency * 7 >> 1; ret = th_encode_ctl(pv->ctx, TH_ENCCTL_SET_RATE_BUFFER, &arg, sizeof(arg)); @@ -135,7 +137,7 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) } } - if( job->pass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST ) { unsigned char *buffer; int bytes; @@ -153,7 +155,7 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) } fflush( pv->file ); } - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { /* Enable the second pass here. * We make this call just to set the encoder into 2-pass mode, because @@ -233,7 +235,7 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in, *buf_out = in; *buf_in = NULL; th_encode_packetout( pv->ctx, 1, &op ); - if( job->pass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST ) { unsigned char *buffer; int bytes; @@ -256,7 +258,7 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in, return HB_WORK_DONE; } - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { for(;;) { @@ -335,7 +337,7 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in, th_encode_ycbcr_in( pv->ctx, ycbcr ); - if( job->pass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST ) { unsigned char *buffer; int bytes; diff --git a/libhb/encx264.c b/libhb/encx264.c index 8b39ab0ba..780385d7b 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -123,7 +123,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) /* Some HandBrake-specific defaults; users can override them * using the encoder_options string. */ - if( job->pass == 2 && job->cfr != 1 ) + if( job->pass_id == HB_PASS_ENCODE_2ND && job->cfr != 1 ) { hb_interjob_t * interjob = hb_interjob_get( job->h ); param.i_fps_num = interjob->vrate.num; @@ -268,19 +268,20 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) param.rc.i_rc_method = X264_RC_ABR; param.rc.i_bitrate = job->vbitrate; hb_log( "encx264: encoding at average bitrate %d", param.rc.i_bitrate ); - if( job->pass > 0 && job->pass < 3 ) + if( job->pass_id == HB_PASS_ENCODE_1ST || + job->pass_id == HB_PASS_ENCODE_2ND ) { memset( pv->filename, 0, 1024 ); hb_get_tempory_filename( job->h, pv->filename, "x264.log" ); } - switch( job->pass ) + switch( job->pass_id ) { - case 1: + case HB_PASS_ENCODE_1ST: param.rc.b_stat_read = 0; param.rc.b_stat_write = 1; param.rc.psz_stat_out = pv->filename; break; - case 2: + case HB_PASS_ENCODE_2ND: param.rc.b_stat_read = 1; param.rc.b_stat_write = 0; param.rc.psz_stat_in = pv->filename; @@ -310,7 +311,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) } /* Turbo first pass */ - if( job->pass == 1 && job->fastfirstpass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST && job->fastfirstpass == 1 ) { x264_param_apply_fastfirstpass( ¶m ); } @@ -341,7 +342,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) } free( x264_opts_unparsed ); - hb_deep_log( 2, "encx264: opening libx264 (pass %d)", job->pass ); + hb_deep_log( 2, "encx264: opening libx264 (pass %d)", job->pass_id ); pv->x264 = x264_encoder_open( ¶m ); if ( pv->x264 == NULL ) { diff --git a/libhb/encx265.c b/libhb/encx265.c index d9b4be64e..324c07e5b 100644 --- a/libhb/encx265.c +++ b/libhb/encx265.c @@ -234,18 +234,19 @@ int encx265Init(hb_work_object_t *w, hb_job_t *job) { param->rc.rateControlMode = X265_RC_ABR; param->rc.bitrate = job->vbitrate; - if (job->pass > 0 && job->pass < 3) + if (job->pass_id == HB_PASS_ENCODE_1ST || + job->pass_id == HB_PASS_ENCODE_2ND) { char stats_file[1024] = ""; char pass[2]; - snprintf(pass, sizeof(pass), "%d", job->pass); + snprintf(pass, sizeof(pass), "%d", job->pass_id); hb_get_tempory_filename(job->h, stats_file, "x265.log"); if (param_parse(param, "stats", stats_file) || param_parse(param, "pass", pass)) { goto fail; } - if (job->pass == 1 && job->fastfirstpass == 0 && + if (job->pass_id == HB_PASS_ENCODE_1ST && job->fastfirstpass == 0 && param_parse(param, "slow-firstpass", "1")) { goto fail; diff --git a/libhb/hb.c b/libhb/hb.c index 9514de3ee..84347d768 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -48,8 +48,6 @@ struct hb_handle_s from this one (see work.c) */ hb_list_t * jobs; hb_job_t * current_job; - int job_count; - int job_count_permanent; volatile int work_die; hb_error_code work_error; hb_thread_t * work_thread; @@ -1255,7 +1253,7 @@ hb_job_t * hb_current_job( hb_handle_t * h ) * @param h Handle to hb_handle_t. * @param job Handle to hb_job_t. */ -static void hb_add_internal( hb_handle_t * h, hb_job_t * job ) +static void hb_add_internal( hb_handle_t * h, hb_job_t * job, hb_list_t *list_pass ) { hb_job_t * job_copy; hb_audio_t * audio; @@ -1336,21 +1334,64 @@ static void hb_add_internal( hb_handle_t * h, hb_job_t * job ) job_copy->file = strdup(job->file); job_copy->h = h; - job_copy->pause = h->pause_lock; /* Copy the job filter list */ job_copy->list_filter = hb_filter_list_copy( job->list_filter ); /* Add the job to the list */ - hb_list_add( h->jobs, job_copy ); - h->job_count = hb_count(h); - h->job_count_permanent++; + hb_list_add( list_pass, job_copy ); +} + +hb_job_t* hb_job_copy(hb_job_t * job) +{ + hb_job_t * job_copy; + + /* Copy the job */ + job_copy = calloc( sizeof( hb_job_t ), 1 ); + if (job_copy == NULL) + return NULL; + + if (job->json != NULL) + { + // JSON jobs should only have the json string set. + job_copy->json = strdup(job->json); + return job_copy; + } + memcpy( job_copy, job, sizeof( hb_job_t ) ); + + job_copy->list_subtitle = hb_subtitle_list_copy( job->list_subtitle ); + job_copy->list_chapter = hb_chapter_list_copy( job->list_chapter ); + job_copy->list_audio = hb_audio_list_copy( job->list_audio ); + job_copy->list_attachment = hb_attachment_list_copy( job->list_attachment ); + job_copy->metadata = hb_metadata_copy( job->metadata ); + + if (job->encoder_preset != NULL) + job_copy->encoder_preset = strdup(job->encoder_preset); + if (job->encoder_tune != NULL) + job_copy->encoder_tune = strdup(job->encoder_tune); + if (job->encoder_options != NULL) + job_copy->encoder_options = strdup(job->encoder_options); + if (job->encoder_profile != NULL) + job_copy->encoder_profile = strdup(job->encoder_profile); + if (job->encoder_level != NULL) + job_copy->encoder_level = strdup(job->encoder_level); + if (job->file != NULL) + job_copy->file = strdup(job->file); + + job_copy->list_filter = hb_filter_list_copy( job->list_filter ); + + return job_copy; } void hb_add( hb_handle_t * h, hb_job_t * job ) { - int sub_id = 0; + hb_job_t *job_copy = hb_job_copy(job); + job_copy->h = h; + hb_list_add(h->jobs, job_copy); +} +void hb_job_setup_passes(hb_handle_t * h, hb_job_t * job, hb_list_t * list_pass) +{ if (job->vquality >= 0) { job->twopass = 0; @@ -1358,26 +1399,22 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) if (job->indepth_scan) { hb_deep_log(2, "Adding subtitle scan pass"); - job->pass = -1; - job->sequence_id = (job->sequence_id & 0xFFFFFF) | (sub_id++ << 24); - hb_add_internal(h, job); + job->pass_id = HB_PASS_SUBTITLE; + hb_add_internal(h, job, list_pass); job->indepth_scan = 0; } if (job->twopass) { hb_deep_log(2, "Adding two-pass encode"); - job->pass = 1; - job->sequence_id = (job->sequence_id & 0xFFFFFF) | (sub_id++ << 24); - hb_add_internal(h, job); - job->pass = 2; - job->sequence_id = (job->sequence_id & 0xFFFFFF) | (sub_id++ << 24); - hb_add_internal(h, job); + job->pass_id = HB_PASS_ENCODE_1ST; + hb_add_internal(h, job, list_pass); + job->pass_id = HB_PASS_ENCODE_2ND; + hb_add_internal(h, job, list_pass); } else { - job->pass = 0; - job->sequence_id = (job->sequence_id & 0xFFFFFF) | (sub_id++ << 24); - hb_add_internal(h, job); + job->pass_id = HB_PASS_ENCODE; + hb_add_internal(h, job, list_pass); } } @@ -1389,12 +1426,6 @@ void hb_add( hb_handle_t * h, hb_job_t * job ) void hb_rem( hb_handle_t * h, hb_job_t * job ) { hb_list_rem( h->jobs, job ); - - h->job_count = hb_count(h); - if (h->job_count_permanent) - h->job_count_permanent--; - - /* XXX free everything XXX */ } /** @@ -1405,16 +1436,10 @@ void hb_rem( hb_handle_t * h, hb_job_t * job ) */ void hb_start( hb_handle_t * h ) { - /* XXX Hack */ - h->job_count = hb_list_count( h->jobs ); - h->job_count_permanent = h->job_count; - hb_lock( h->state_lock ); h->state.state = HB_STATE_WORKING; #define p h->state.param.working p.progress = 0.0; - p.job_cur = 1; - p.job_count = h->job_count; p.rate_cur = 0.0; p.rate_avg = 0.0; p.hours = -1; @@ -1477,10 +1502,6 @@ void hb_resume( hb_handle_t * h ) void hb_stop( hb_handle_t * h ) { h->work_die = 1; - - h->job_count = hb_count(h); - h->job_count_permanent = 0; - hb_resume( h ); } @@ -1491,10 +1512,6 @@ void hb_stop( hb_handle_t * h ) void hb_scan_stop( hb_handle_t * h ) { h->scan_die = 1; - - h->job_count = hb_count(h); - h->job_count_permanent = 0; - hb_resume( h ); } @@ -1735,9 +1752,6 @@ static void thread_func( void * _h ) h->state.state = HB_STATE_WORKDONE; h->state.param.workdone.error = h->work_error; - h->job_count = hb_count(h); - if (h->job_count < 1) - h->job_count_permanent = 0; hb_unlock( h->state_lock ); } @@ -1813,14 +1827,6 @@ void hb_set_state( hb_handle_t * h, hb_state_t * s ) if( h->state.state == HB_STATE_WORKING || h->state.state == HB_STATE_SEARCHING ) { - /* XXX Hack */ - if (h->job_count < 1) - h->job_count_permanent = 1; - - h->state.param.working.job_cur = - h->job_count_permanent - hb_list_count( h->jobs ); - h->state.param.working.job_count = h->job_count_permanent; - // Set which job is being worked on if (h->current_job) h->state.param.working.sequence_id = h->current_job->sequence_id & 0xFFFFFF; diff --git a/libhb/hb_json.c b/libhb/hb_json.c index f374dbb50..f4b1bb814 100644 --- a/libhb/hb_json.c +++ b/libhb/hb_json.c @@ -42,12 +42,13 @@ static json_t* hb_state_to_dict( hb_state_t * state) case HB_STATE_PAUSED: case HB_STATE_SEARCHING: dict = json_pack_ex(&error, 0, - "{s:o, s{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}}", + "{s:o, s{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}}", "State", json_integer(state->state), "Working", "Progress", json_real(state->param.working.progress), - "Job", json_integer(state->param.working.job_cur), - "JobCount", json_integer(state->param.working.job_count), + "PassID", json_integer(state->param.working.pass_id), + "Pass", json_integer(state->param.working.pass), + "PassCount", json_integer(state->param.working.pass_count), "Rate", json_real(state->param.working.rate_cur), "RateAvg", json_real(state->param.working.rate_avg), "Hours", json_integer(state->param.working.hours), @@ -217,6 +218,11 @@ static json_t* hb_title_to_dict( const hb_title_t * title ) json_object_set_new(meta_dict, "LongDescription", json_string(title->metadata->long_description)); } + if (title->metadata->release_date != NULL) + { + json_object_set_new(meta_dict, "ReleaseDate", + json_string(title->metadata->release_date)); + } // process chapter list json_t * chapter_list = json_array(); @@ -554,6 +560,11 @@ char* hb_job_to_json( const hb_job_t * job ) json_object_set_new(meta_dict, "LongDescription", json_string(job->metadata->long_description)); } + if (job->metadata->release_date != NULL) + { + json_object_set_new(meta_dict, "ReleaseDate", + json_string(job->metadata->release_date)); + } // process chapter list json_t *chapter_list = json_object_get(dest_dict, "ChapterList"); @@ -641,8 +652,7 @@ char* hb_job_to_json( const hb_job_t * job ) else { subtitle_dict = json_pack_ex(&error, 0, - "{s:o, s:o, s:o, s:o, s:o, s:o}", - "ID", json_integer(subtitle->id), + "{s:o, s:o, s:o, s:o, s:o}", "Track", json_integer(subtitle->track), "Default", json_boolean(subtitle->config.default_track), "Force", json_boolean(subtitle->config.force), @@ -667,6 +677,40 @@ static int * unpack_b(int *b) { return b; } static char** unpack_s(char **s) { return s; } static json_t** unpack_o(json_t** o) { return o; } +void hb_json_job_scan( hb_handle_t * h, const char * json_job ) +{ + json_t * dict; + int result; + json_error_t error; + + dict = json_loads(json_job, 0, NULL); + + int title_index; + char *path = NULL; + + result = json_unpack_ex(dict, &error, 0, "{s:{s:s, s:i}}", + "Source", + "Path", unpack_s(&path), + "Title", unpack_i(&title_index)); + if (result < 0) + { + hb_error("json unpack failure, failed to find title: %s", error.text); + return; + } + + hb_scan(h, path, title_index, 10, 0, 0); + + // Wait for scan to complete + hb_state_t state; + do + { + hb_snooze(50); + hb_get_state2(h, &state); + } while (state.state == HB_STATE_SCANNING); + + json_decref(dict); +} + /** * Convert a json string representation of a job to an hb_job_t * @param h - Pointer to the hb_hanle_t hb instance which contains the @@ -1084,12 +1128,10 @@ char* hb_job_init_json(hb_handle_t *h, int title_index) */ int hb_add_json( hb_handle_t * h, const char * json_job ) { - hb_job_t *job = hb_json_to_job(h, json_job); - if (job == NULL) - return -1; + hb_job_t job; - hb_add(h, job); - hb_job_close(&job); + job.json = json_job; + hb_add(h, &job); return 0; } diff --git a/libhb/hb_json.h b/libhb/hb_json.h index fcd1683ce..b5025a6c2 100644 --- a/libhb/hb_json.h +++ b/libhb/hb_json.h @@ -28,6 +28,7 @@ hb_image_t * hb_json_to_image(char *json_image); char * hb_get_preview_params_json(int title_idx, int preview_idx, int deinterlace, hb_geometry_settings_t *settings); char * hb_get_preview_json(hb_handle_t * h, const char *json_param); +void hb_json_job_scan( hb_handle_t * h, const char * json_job ); #ifdef __cplusplus } diff --git a/libhb/internal.h b/libhb/internal.h index 13d12be29..759f1beb8 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -40,6 +40,7 @@ void hb_title_close( hb_title_t ** ); **********************************************************************/ int hb_get_pid( hb_handle_t * ); void hb_set_state( hb_handle_t *, hb_state_t * ); +void hb_job_setup_passes(hb_handle_t *h, hb_job_t *job, hb_list_t *list_pass); /*********************************************************************** * fifo.c diff --git a/libhb/muxavformat.c b/libhb/muxavformat.c index 44993c27c..fb6326d1d 100644 --- a/libhb/muxavformat.c +++ b/libhb/muxavformat.c @@ -352,7 +352,7 @@ static int avformatInit( hb_mux_object_t * m ) track->st->disposition |= AV_DISPOSITION_DEFAULT; hb_rational_t vrate; - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { hb_interjob_t * interjob = hb_interjob_get( job->h ); vrate = interjob->vrate; diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c index c66bf0012..ca9502e4c 100644 --- a/libhb/muxcommon.c +++ b/libhb/muxcommon.c @@ -373,7 +373,8 @@ static int muxWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_bitvec_set(mux->eof, pv->track); hb_bitvec_set(mux->rdy, pv->track); } - else if ((job->pass != 0 && job->pass != 2) || + else if ((job->pass_id != HB_PASS_ENCODE && + job->pass_id != HB_PASS_ENCODE_2ND) || hb_bitvec_bit(mux->eof, pv->track)) { hb_buffer_close( &buf ); @@ -471,7 +472,8 @@ void muxClose( hb_work_object_t * w ) // 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 ) + if( job->pass_id == HB_PASS_ENCODE || + job->pass_id == HB_PASS_ENCODE_2ND ) { /* Update the UI */ hb_state_t state; @@ -487,7 +489,8 @@ void muxClose( hb_work_object_t * w ) } // we're all done muxing -- print final stats and cleanup. - if( job->pass == 0 || job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE || + job->pass_id == HB_PASS_ENCODE_2ND ) { hb_stat_t sb; uint64_t bytes_total, frames_total; @@ -612,7 +615,7 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job ) mux->pts = mux->interleave; /* Get a real muxer */ - if( job->pass == 0 || job->pass == 2) + if( job->pass_id == HB_PASS_ENCODE || job->pass_id == HB_PASS_ENCODE_2ND ) { switch( job->mux ) { diff --git a/libhb/reader.c b/libhb/reader.c index 80e967959..530196e48 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -751,6 +751,7 @@ static void UpdateState( hb_work_private_t * r, int64_t start) r->st_first = now; } + hb_get_state2(r->job->h, &state); #define p state.param.working if ( !r->job->indepth_scan ) { diff --git a/libhb/scan.c b/libhb/scan.c index 55c9bfc90..32a5c60bb 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -74,7 +74,19 @@ hb_thread_t * hb_scan_init( hb_handle_t * handle, volatile int * die, data->preview_count = preview_count; data->store_previews = store_previews; data->min_title_duration = min_duration; - + + // Initialize scan state + hb_state_t state; +#define p state.param.scanning + state.state = HB_STATE_SCANNING; + p.title_cur = 1; + p.title_count = 1; + p.preview_cur = 0; + p.preview_count = 1; + p.progress = 0.0; +#undef p + hb_set_state(handle, &state); + return hb_thread_init( "scan", ScanFunc, data, HB_NORMAL_PRIORITY ); } @@ -169,7 +181,14 @@ static void ScanFunc( void * _data ) } else { - data->title_index = 1; + // Title index 0 is not a valid title number and means scan all titles. + // So set title index to 1 in this scenario. + // + // Otherwise, set title index in new title to the index that was + // requested. This preserves the original index created in batch + // mode. + if (data->title_index == 0) + data->title_index = 1; hb_title_t * title = hb_title_init( data->path, data->title_index ); if ( (data->stream = hb_stream_open( data->path, title, 1 ) ) != NULL ) { diff --git a/libhb/stream.c b/libhb/stream.c index 81d8da2fc..9d01c1d00 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -1039,7 +1039,6 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream, hb_title_t * title) // 'Barebones Title' title->type = HB_STREAM_TYPE; - title->index = 1; // Copy part of the stream path to the title name char *sep = hb_strr_dir_sep(stream->path); @@ -5428,7 +5427,6 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) // 'Barebones Title' title->type = HB_FF_STREAM_TYPE; - title->index = 1; // Copy part of the stream path to the title name char *sep = hb_strr_dir_sep(stream->path); diff --git a/libhb/sync.c b/libhb/sync.c index 21fe8c2ae..ac826584e 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -155,7 +155,7 @@ hb_work_object_t * hb_sync_init( hb_job_t * job ) pv->common->pts_offset = INT64_MIN; sync->first_frame = 1; - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { /* We already have an accurate frame count from pass 1 */ hb_interjob_t * interjob = hb_interjob_get( job->h ); @@ -263,7 +263,7 @@ void syncVideoClose( hb_work_object_t * w ) pv->common->count_frames, sync->count_frames_max ); /* save data for second pass */ - if( job->pass == 1 ) + if( job->pass_id == HB_PASS_ENCODE_1ST ) { /* Preserve frame count for better accuracy in pass 2 */ hb_interjob_t * interjob = hb_interjob_get( job->h ); @@ -1638,6 +1638,7 @@ static void UpdateState( hb_work_object_t * w ) hb_sync_video_t * sync = &pv->type.video; hb_state_t state; + hb_get_state2( pv->job->h, &state ); if( !pv->common->count_frames ) { sync->st_first = hb_get_date(); diff --git a/libhb/work.c b/libhb/work.c index 4792c42b3..01060c01f 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -58,18 +58,21 @@ hb_thread_t * hb_work_init( hb_list_t * jobs, volatile int * die, hb_error_code return hb_thread_init( "work", work_func, work, HB_LOW_PRIORITY ); } -static void InitWorkState( hb_handle_t * h ) +static void InitWorkState(hb_handle_t *h, int pass_id, int pass, int pass_count) { hb_state_t state; - state.state = HB_STATE_WORKING; + state.state = HB_STATE_WORKING; #define p state.param.working - p.progress = 0.0; - p.rate_cur = 0.0; - p.rate_avg = 0.0; - p.hours = -1; - p.minutes = -1; - p.seconds = -1; + p.pass_id = pass_id; + p.pass = pass; + p.pass_count = pass_count; + p.progress = 0.0; + p.rate_cur = 0.0; + p.rate_avg = 0.0; + p.hours = -1; + p.minutes = -1; + p.seconds = -1; #undef p hb_set_state( h, &state ); @@ -90,12 +93,45 @@ static void work_func( void * _work ) while( !*work->die && ( job = hb_list_item( work->jobs, 0 ) ) ) { hb_list_rem( work->jobs, job ); - job->die = work->die; - job->done_error = work->error; - *(work->current_job) = job; - InitWorkState( job->h ); - do_job( job ); - *(work->current_job) = NULL; + hb_list_t * passes = hb_list_init(); + + // JSON jobs get special treatment. We want to perform the title + // scan for the JSON job automatically. This requires that we delay + // filling the job struct till we have performed the title scan + // because the default values for the job come from the title. + if (job->json != NULL) + { + // Perform title scan for json job + hb_json_job_scan(job->h, job->json); + + // Expand json string to full job struct + hb_job_t *new_job = hb_json_to_job(job->h, job->json); + new_job->h = job->h; + hb_job_close(&job); + job = new_job; + } + hb_job_setup_passes(job->h, job, passes); + hb_job_close(&job); + + int pass_count, pass; + pass_count = hb_list_count(passes); + for (pass = 0; pass < pass_count && !*work->die; pass++) + { + job = hb_list_item(passes, pass); + job->die = work->die; + job->done_error = work->error; + *(work->current_job) = job; + InitWorkState(job->h, job->pass_id, pass + 1, pass_count); + do_job( job ); + *(work->current_job) = NULL; + } + // Clean up any incomplete jobs + for (; pass < pass_count; pass++) + { + job = hb_list_item(passes, pass); + hb_job_close(&job); + } + hb_list_close(&passes); } free( work ); @@ -346,8 +382,8 @@ void hb_display_job_info(hb_job_t *job) } else { - hb_log( " + bitrate: %d kbps, pass: %d", job->vbitrate, job->pass ); - if(job->pass == 1 && job->fastfirstpass == 1 && + hb_log( " + bitrate: %d kbps, pass: %d", job->vbitrate, job->pass_id ); + if(job->pass_id == HB_PASS_ENCODE_1ST && job->fastfirstpass == 1 && (job->vcodec == HB_VCODEC_X264 || job->vcodec == HB_VCODEC_X265)) { hb_log( " + fast first pass" ); @@ -538,7 +574,7 @@ static void do_job(hb_job_t *job) title = job->title; interjob = hb_interjob_get( job->h ); - if( job->pass == 2 ) + if( job->pass_id == HB_PASS_ENCODE_2ND ) { correct_framerate( job ); } @@ -606,7 +642,8 @@ static void do_job(hb_job_t *job) * first burned subtitle (explicitly or after sanitizing) - which should * ensure that it doesn't get dropped. */ interjob->select_subtitle->out_track = 1; - if (job->pass == 0 || job->pass == 2) + if (job->pass_id == HB_PASS_ENCODE || + job->pass_id == HB_PASS_ENCODE_2ND) { // final pass, interjob->select_subtitle is no longer needed hb_list_insert(job->list_subtitle, 0, interjob->select_subtitle); @@ -1463,8 +1500,8 @@ static void do_job(hb_job_t *job) hb_handle_t * h = job->h; hb_state_t state; - hb_get_state( h, &state ); - + hb_get_state2( h, &state ); + hb_log("work: average encoding speed for job is %f fps", state.param.working.rate_avg); job->done = 1; |