summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2015-03-09 15:05:47 +0000
committerjstebbins <[email protected]>2015-03-09 15:05:47 +0000
commit9e9e47cd1913a34bd248a3ac5a8da9765e638bdc (patch)
tree8350a5991ef036fe05d6d7903dfd0603a3a05f78 /libhb
parent44eb2602873819fcb35cc92ea53a8f14e5bc7c64 (diff)
libhb: use jansson for hb_dict
This paves the way to doing preset processing in libhb. Initially for the CLI but other frontends may benefit eventually. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6981 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r--libhb/enc_qsv.c22
-rw-r--r--libhb/encavcodec.c13
-rw-r--r--libhb/encx264.c392
-rw-r--r--libhb/encx265.c18
-rw-r--r--libhb/hb_dict.c620
-rw-r--r--libhb/hb_dict.h123
-rw-r--r--libhb/hb_json.c1
-rw-r--r--libhb/hb_json.h2
8 files changed, 814 insertions, 377 deletions
diff --git a/libhb/enc_qsv.c b/libhb/enc_qsv.c
index 8051bd5d0..c4aca79ff 100644
--- a/libhb/enc_qsv.c
+++ b/libhb/enc_qsv.c
@@ -577,27 +577,32 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
if (job->encoder_options != NULL && *job->encoder_options)
{
hb_dict_t *options_list;
- hb_dict_entry_t *option = NULL;
options_list = hb_encopts_to_dict(job->encoder_options, job->vcodec);
- while ((option = hb_dict_next(options_list, option)) != NULL)
+
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(x264_opts);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(x264_opts, iter))
{
- switch (hb_qsv_param_parse(&pv->param, pv->qsv_info,
- option->key, option->value))
+ const char *key = hb_dict_iter_key(iter);
+ hb_value_t *value = hb_dict_iter_value(iter);
+ char *str = hb_value_get_string_xform(value);
+
+ switch (hb_qsv_param_parse(&pv->param, pv->qsv_info, key, str))
{
case HB_QSV_PARAM_OK:
break;
case HB_QSV_PARAM_BAD_NAME:
- hb_log("encqsvInit: hb_qsv_param_parse: bad key %s",
- option->key);
+ hb_log("encqsvInit: hb_qsv_param_parse: bad key %s", key);
break;
case HB_QSV_PARAM_BAD_VALUE:
hb_log("encqsvInit: hb_qsv_param_parse: bad value %s for key %s",
- option->value, option->key);
+ str, key);
break;
case HB_QSV_PARAM_UNSUPPORTED:
hb_log("encqsvInit: hb_qsv_param_parse: unsupported option %s",
- option->key);
+ key);
break;
case HB_QSV_PARAM_ERROR:
@@ -605,6 +610,7 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
hb_log("encqsvInit: hb_qsv_param_parse: unknown error");
break;
}
+ free(str);
}
hb_dict_free(&options_list);
}
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index fe479a393..7b1c01ccc 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -170,11 +170,18 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
}
/* iterate through lavc_opts and have avutil parse the options for us */
AVDictionary * av_opts = NULL;
- hb_dict_entry_t * entry = NULL;
- while( ( entry = hb_dict_next( lavc_opts, entry ) ) )
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(lavc_opts);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(lavc_opts, iter))
{
+ const char *key = hb_dict_iter_key(iter);
+ hb_value_t *value = hb_dict_iter_value(iter);
+ char *str = hb_value_get_string_xform(value);
+
/* Here's where the strings are passed to avutil for parsing. */
- av_dict_set( &av_opts, entry->key, entry->value, 0 );
+ av_dict_set( &av_opts, key, str, 0 );
+ free(str);
}
hb_dict_free( &lavc_opts );
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 780385d7b..d64e56547 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -200,18 +200,27 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
}
/* iterate through x264_opts and have libx264 parse the options for us */
int ret;
- hb_dict_entry_t * entry = NULL;
- while( ( entry = hb_dict_next( x264_opts, entry ) ) )
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(x264_opts);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(x264_opts, iter))
{
+ const char *key = hb_dict_iter_key(iter);
+ hb_value_t *value = hb_dict_iter_value(iter);
+ char *str = hb_value_get_string_xform(value);
+
/* Here's where the strings are passed to libx264 for parsing. */
- ret = x264_param_parse( &param, entry->key, entry->value );
+ ret = x264_param_parse(&param, key, str);
+
/* Let x264 sanity check the options for us */
- if( ret == X264_PARAM_BAD_NAME )
- hb_log( "x264 options: Unknown suboption %s", entry->key );
- if( ret == X264_PARAM_BAD_VALUE )
- hb_log( "x264 options: Bad argument %s=%s", entry->key, entry->value ? entry->value : "(null)" );
+ if (ret == X264_PARAM_BAD_NAME)
+ hb_log( "x264 options: Unknown suboption %s", key );
+ if (ret == X264_PARAM_BAD_VALUE)
+ hb_log( "x264 options: Bad argument %s=%s", key,
+ str ? str : "(null)" );
+ free(str);
}
- hb_dict_free( &x264_opts );
+ hb_dict_free(&x264_opts);
/* Reload colorimetry settings in case custom values were set
* in the encoder_options string */
@@ -1046,15 +1055,21 @@ int hb_apply_h264_level(x264_param_t *param, const char *h264_level,
return ret;
}
+static hb_value_t * value_pair(hb_value_t * v1, hb_value_t * v2)
+{
+ hb_value_t *array = hb_value_array_init();
+ hb_value_array_append(array, v1);
+ hb_value_array_append(array, v2);
+ return array;
+}
+
char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
const char *x264_encopts, const char *h264_profile,
const char *h264_level, int width, int height)
{
int i;
- char buf[32];
char *unparsed_opts;
hb_dict_t *x264_opts;
- hb_dict_entry_t *entry;
x264_param_t defaults, param;
/*
@@ -1077,7 +1092,6 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
/*
* place additional x264 options in a dictionary
*/
- entry = NULL;
x264_opts = hb_encopts_to_dict(x264_encopts, HB_VCODEC_X264);
/*
@@ -1087,22 +1101,30 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
*
* clear them from x264_opts so as to not apply then during unparse.
*/
- hb_dict_unset(&x264_opts, "qp");
- hb_dict_unset(&x264_opts, "qp_constant");
- hb_dict_unset(&x264_opts, "crf");
- hb_dict_unset(&x264_opts, "bitrate");
- hb_dict_unset(&x264_opts, "fps");
- hb_dict_unset(&x264_opts, "force-cfr");
- hb_dict_unset(&x264_opts, "sar");
- hb_dict_unset(&x264_opts, "annexb");
+ hb_dict_remove(x264_opts, "qp");
+ hb_dict_remove(x264_opts, "qp_constant");
+ hb_dict_remove(x264_opts, "crf");
+ hb_dict_remove(x264_opts, "bitrate");
+ hb_dict_remove(x264_opts, "fps");
+ hb_dict_remove(x264_opts, "force-cfr");
+ hb_dict_remove(x264_opts, "sar");
+ hb_dict_remove(x264_opts, "annexb");
/*
* apply the additional x264 options
*/
- while ((entry = hb_dict_next(x264_opts, entry)) != NULL)
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(x264_opts);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(x264_opts, iter))
{
+ const char *key = hb_dict_iter_key(iter);
+ hb_value_t *value = hb_dict_iter_value(iter);
+ char *str = hb_value_get_string_xform(value);
+
// let's not pollute GUI logs with x264_param_parse return codes
- x264_param_parse(&param, entry->key, entry->value);
+ x264_param_parse(&param, key, str);
+ free(str);
}
/*
@@ -1146,19 +1168,19 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
* also, don't bother with forms that aren't allowed by the x264 CLI, such
* as "no-bframes" - there are too many.
*/
- hb_dict_unset(&x264_opts, "no-sliced-threads");
- hb_dict_unset(&x264_opts, "no-scenecut");
- hb_dict_unset(&x264_opts, "no-b-adapt");
- hb_dict_unset(&x264_opts, "no-weightb");
- hb_dict_unset(&x264_opts, "no-cabac");
- hb_dict_unset(&x264_opts, "interlaced"); // we unparse to tff/bff
- hb_dict_unset(&x264_opts, "no-interlaced");
- hb_dict_unset(&x264_opts, "no-8x8dct");
- hb_dict_unset(&x264_opts, "no-mixed-refs");
- hb_dict_unset(&x264_opts, "no-fast-pskip");
- hb_dict_unset(&x264_opts, "no-dct-decimate");
- hb_dict_unset(&x264_opts, "no-psy");
- hb_dict_unset(&x264_opts, "no-mbtree");
+ hb_dict_remove(x264_opts, "no-sliced-threads");
+ hb_dict_remove(x264_opts, "no-scenecut");
+ hb_dict_remove(x264_opts, "no-b-adapt");
+ hb_dict_remove(x264_opts, "no-weightb");
+ hb_dict_remove(x264_opts, "no-cabac");
+ hb_dict_remove(x264_opts, "interlaced"); // we unparse to tff/bff
+ hb_dict_remove(x264_opts, "no-interlaced");
+ hb_dict_remove(x264_opts, "no-8x8dct");
+ hb_dict_remove(x264_opts, "no-mixed-refs");
+ hb_dict_remove(x264_opts, "no-fast-pskip");
+ hb_dict_remove(x264_opts, "no-dct-decimate");
+ hb_dict_remove(x264_opts, "no-psy");
+ hb_dict_remove(x264_opts, "no-mbtree");
/*
* compare defaults to param and unparse to the x264_opts dictionary
@@ -1166,75 +1188,74 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
if (!param.b_sliced_threads != !defaults.b_sliced_threads)
{
// can be modified by: tune zerolatency
- sprintf(buf, "%d", !!param.b_sliced_threads);
- hb_dict_set(&x264_opts, "sliced-threads", buf);
+ hb_dict_set(x264_opts, "sliced-threads",
+ hb_value_bool(!!param.b_sliced_threads));
}
else
{
- hb_dict_unset(&x264_opts, "sliced-threads");
+ hb_dict_remove(x264_opts, "sliced-threads");
}
if (param.i_sync_lookahead != defaults.i_sync_lookahead)
{
// can be modified by: tune zerolatency
- sprintf(buf, "%d", param.i_sync_lookahead);
- hb_dict_set(&x264_opts, "sync-lookahead", buf);
+ hb_dict_set(x264_opts, "sync-lookahead",
+ hb_value_int(param.i_sync_lookahead));
}
else
{
- hb_dict_unset(&x264_opts, "sync-lookahead");
+ hb_dict_remove(x264_opts, "sync-lookahead");
}
if (param.i_level_idc != defaults.i_level_idc)
{
// can be modified by: level
for (i = 0; hb_h264_level_values[i]; i++)
if (param.i_level_idc == hb_h264_level_values[i])
- hb_dict_set(&x264_opts, "level", hb_h264_level_names[i]);
+ hb_dict_set(x264_opts, "level",
+ hb_value_string(hb_h264_level_names[i]));
}
else
{
- hb_dict_unset(&x264_opts, "level");
+ hb_dict_remove(x264_opts, "level");
}
if (param.i_frame_reference != defaults.i_frame_reference)
{
// can be modified by: presets, tunes, level
- sprintf(buf, "%d", param.i_frame_reference);
- hb_dict_set(&x264_opts, "ref", buf);
+ hb_dict_set(x264_opts, "ref", hb_value_int(param.i_frame_reference));
}
else
{
- hb_dict_unset(&x264_opts, "ref");
+ hb_dict_remove(x264_opts, "ref");
}
if (param.i_scenecut_threshold != defaults.i_scenecut_threshold)
{
// can be modified by: preset ultrafast
- sprintf(buf, "%d", param.i_scenecut_threshold);
- hb_dict_set(&x264_opts, "scenecut", buf);
+ hb_dict_set(x264_opts, "scenecut",
+ hb_value_int(param.i_scenecut_threshold));
}
else
{
- hb_dict_unset(&x264_opts, "scenecut");
+ hb_dict_remove(x264_opts, "scenecut");
}
if (param.i_bframe != defaults.i_bframe)
{
// can be modified by: presets, tunes, profile, level
- sprintf(buf, "%d", param.i_bframe);
- hb_dict_set(&x264_opts, "bframes", buf);
+ hb_dict_set(x264_opts, "bframes", hb_value_int(param.i_bframe));
}
else
{
- hb_dict_unset(&x264_opts, "bframes");
+ hb_dict_remove(x264_opts, "bframes");
}
if (param.i_bframe > 0)
{
if (param.i_bframe_adaptive != defaults.i_bframe_adaptive)
{
// can be modified by: presets
- sprintf(buf, "%d", param.i_bframe_adaptive);
- hb_dict_set(&x264_opts, "b-adapt", buf);
+ hb_dict_set(x264_opts, "b-adapt",
+ hb_value_int(param.i_bframe_adaptive));
}
else
{
- hb_dict_unset(&x264_opts, "b-adapt");
+ hb_dict_remove(x264_opts, "b-adapt");
}
if (param.i_bframe > 1 &&
param.i_bframe_pyramid != defaults.i_bframe_pyramid)
@@ -1246,12 +1267,12 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
param.i_bframe_pyramid = X264_B_PYRAMID_NORMAL;
for (i = 0; x264_b_pyramid_names[i] != NULL; i++)
if (param.i_bframe_pyramid == i)
- hb_dict_set(&x264_opts, "b-pyramid",
- x264_b_pyramid_names[i]);
+ hb_dict_set(x264_opts, "b-pyramid",
+ hb_value_string(x264_b_pyramid_names[i]));
}
else
{
- hb_dict_unset(&x264_opts, "b-pyramid");
+ hb_dict_remove(x264_opts, "b-pyramid");
}
if (param.analyse.i_direct_mv_pred != defaults.analyse.i_direct_mv_pred)
{
@@ -1262,109 +1283,108 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
for (i = 0; x264_direct_pred_names[i] != NULL; i++)
if (param.analyse.i_direct_mv_pred == i)
- hb_dict_set(&x264_opts, "direct",
- x264_direct_pred_names[i]);
+ hb_dict_set(x264_opts, "direct",
+ hb_value_string(x264_direct_pred_names[i]));
}
else
{
- hb_dict_unset(&x264_opts, "direct");
+ hb_dict_remove(x264_opts, "direct");
}
if (!param.analyse.b_weighted_bipred !=
!defaults.analyse.b_weighted_bipred)
{
// can be modified by: preset ultrafast, tune fastdecode
- sprintf(buf, "%d", !!param.analyse.b_weighted_bipred);
- hb_dict_set(&x264_opts, "weightb", buf);
+ hb_dict_set(x264_opts, "weightb",
+ hb_value_bool(!!param.analyse.b_weighted_bipred));
}
else
{
- hb_dict_unset(&x264_opts, "weightb");
+ hb_dict_remove(x264_opts, "weightb");
}
}
else
{
// no bframes, these options have no effect
- hb_dict_unset(&x264_opts, "b-adapt");
- hb_dict_unset(&x264_opts, "b-pyramid");
- hb_dict_unset(&x264_opts, "direct");
- hb_dict_unset(&x264_opts, "weightb");
- hb_dict_unset(&x264_opts, "b-bias");
- hb_dict_unset(&x264_opts, "open-gop");
+ hb_dict_remove(x264_opts, "b-adapt");
+ hb_dict_remove(x264_opts, "b-pyramid");
+ hb_dict_remove(x264_opts, "direct");
+ hb_dict_remove(x264_opts, "weightb");
+ hb_dict_remove(x264_opts, "b-bias");
+ hb_dict_remove(x264_opts, "open-gop");
}
if (!param.b_deblocking_filter != !defaults.b_deblocking_filter)
{
// can be modified by: preset ultrafast, tune fastdecode
- sprintf(buf, "%d", !param.b_deblocking_filter);
- hb_dict_set(&x264_opts, "no-deblock", buf);
+ hb_dict_set(x264_opts, "no-deblock",
+ hb_value_bool(!param.b_deblocking_filter));
}
else
{
- hb_dict_unset(&x264_opts, "no-deblock");
+ hb_dict_remove(x264_opts, "no-deblock");
}
if (param.b_deblocking_filter &&
(param.i_deblocking_filter_alphac0 != defaults.i_deblocking_filter_alphac0 ||
param.i_deblocking_filter_beta != defaults.i_deblocking_filter_beta))
{
// can be modified by: tunes
- sprintf(buf, "%d,%d", param.i_deblocking_filter_alphac0,
- param.i_deblocking_filter_beta);
- hb_dict_set(&x264_opts, "deblock", buf);
+ hb_dict_set(x264_opts, "deblock",
+ value_pair(hb_value_int(param.i_deblocking_filter_alphac0),
+ hb_value_int(param.i_deblocking_filter_beta)));
}
else
{
- hb_dict_unset(&x264_opts, "deblock");
+ hb_dict_remove(x264_opts, "deblock");
}
if (!param.b_cabac != !defaults.b_cabac)
{
// can be modified by: preset ultrafast, tune fastdecode, profile
- sprintf(buf, "%d", !!param.b_cabac);
- hb_dict_set(&x264_opts, "cabac", buf);
+ hb_dict_set(x264_opts, "cabac", hb_value_bool(!!param.b_cabac));
}
else
{
- hb_dict_unset(&x264_opts, "cabac");
+ hb_dict_remove(x264_opts, "cabac");
}
if (param.b_interlaced != defaults.b_interlaced)
{
if (param.b_tff)
{
- hb_dict_set(&x264_opts, "tff", "1");
- hb_dict_unset(&x264_opts, "bff");
+ hb_dict_set(x264_opts, "tff", hb_value_bool(1));
+ hb_dict_remove(x264_opts, "bff");
}
else
{
- hb_dict_set(&x264_opts, "bff", "1");
- hb_dict_unset(&x264_opts, "tff");
+ hb_dict_set(x264_opts, "bff", hb_value_bool(1));
+ hb_dict_remove(x264_opts, "tff");
}
- hb_dict_unset(&x264_opts, "fake-interlaced");
+ hb_dict_remove(x264_opts, "fake-interlaced");
}
else if (param.b_fake_interlaced != defaults.b_fake_interlaced)
{
- hb_dict_set(&x264_opts, "fake-interlaced", "1");
- hb_dict_unset(&x264_opts, "tff");
- hb_dict_unset(&x264_opts, "bff");
+ hb_dict_set(x264_opts, "fake-interlaced", hb_value_bool(1));
+ hb_dict_remove(x264_opts, "tff");
+ hb_dict_remove(x264_opts, "bff");
}
else
{
- hb_dict_unset(&x264_opts, "tff");
- hb_dict_unset(&x264_opts, "bff");
- hb_dict_unset(&x264_opts, "fake-interlaced");
+ hb_dict_remove(x264_opts, "tff");
+ hb_dict_remove(x264_opts, "bff");
+ hb_dict_remove(x264_opts, "fake-interlaced");
}
if (param.i_cqm_preset == defaults.i_cqm_preset &&
param.psz_cqm_file == defaults.psz_cqm_file)
{
// can be reset to default by: profile
- hb_dict_unset(&x264_opts, "cqm");
- hb_dict_unset(&x264_opts, "cqm4");
- hb_dict_unset(&x264_opts, "cqm8");
- hb_dict_unset(&x264_opts, "cqm4i");
- hb_dict_unset(&x264_opts, "cqm4p");
- hb_dict_unset(&x264_opts, "cqm8i");
- hb_dict_unset(&x264_opts, "cqm8p");
- hb_dict_unset(&x264_opts, "cqm4iy");
- hb_dict_unset(&x264_opts, "cqm4ic");
- hb_dict_unset(&x264_opts, "cqm4py");
- hb_dict_unset(&x264_opts, "cqm4pc");
+ hb_dict_remove(x264_opts, "cqm");
+ hb_dict_remove(x264_opts, "cqm4");
+ hb_dict_remove(x264_opts, "cqm8");
+ hb_dict_remove(x264_opts, "cqm4i");
+ hb_dict_remove(x264_opts, "cqm4p");
+ hb_dict_remove(x264_opts, "cqm8i");
+ hb_dict_remove(x264_opts, "cqm8p");
+ hb_dict_remove(x264_opts, "cqm4iy");
+ hb_dict_remove(x264_opts, "cqm4ic");
+ hb_dict_remove(x264_opts, "cqm4py");
+ hb_dict_remove(x264_opts, "cqm4pc");
}
/*
* Note: param.analyse.intra can only be modified directly or by using
@@ -1375,7 +1395,7 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
// can be modified by: presets, tune touhou
if (!param.analyse.inter)
{
- hb_dict_set(&x264_opts, "analyse", "none");
+ hb_dict_set(x264_opts, "analyse", hb_value_string("none"));
}
else if ((param.analyse.inter & X264_ANALYSE_I4x4) &&
(param.analyse.inter & X264_ANALYSE_I8x8) &&
@@ -1383,65 +1403,57 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
(param.analyse.inter & X264_ANALYSE_PSUB8x8) &&
(param.analyse.inter & X264_ANALYSE_BSUB16x16))
{
- hb_dict_set(&x264_opts, "analyse", "all");
+ hb_dict_set(x264_opts, "analyse", hb_value_string("all"));
}
else
{
- sprintf(buf, "%s", "");
+ hb_value_t *array = hb_value_array_init();
if (param.analyse.inter & X264_ANALYSE_I4x4)
{
- strcat(buf, "i4x4");
+ hb_value_array_append(array, hb_value_string("i4x4"));
}
if (param.analyse.inter & X264_ANALYSE_I8x8)
{
- if (*buf)
- strcat(buf, ",");
- strcat(buf, "i8x8");
+ hb_value_array_append(array, hb_value_string("i8x8"));
}
if (param.analyse.inter & X264_ANALYSE_PSUB16x16)
{
- if (*buf)
- strcat(buf, ",");
- strcat(buf, "p8x8");
+ hb_value_array_append(array, hb_value_string("p8x8"));
}
if (param.analyse.inter & X264_ANALYSE_PSUB8x8)
{
- if (*buf)
- strcat(buf, ",");
- strcat(buf, "p4x4");
+ hb_value_array_append(array, hb_value_string("p4x4"));
}
if (param.analyse.inter & X264_ANALYSE_BSUB16x16)
{
- if (*buf)
- strcat(buf, ",");
- strcat(buf, "b8x8");
+ hb_value_array_append(array, hb_value_string("b8x8"));
}
- hb_dict_set(&x264_opts, "analyse", buf);
+ hb_dict_set(x264_opts, "analyse", array);
}
}
else
{
- hb_dict_unset(&x264_opts, "analyse");
+ hb_dict_remove(x264_opts, "analyse");
}
if (!param.analyse.b_transform_8x8 != !defaults.analyse.b_transform_8x8)
{
// can be modified by: preset ultrafast, profile
- sprintf(buf, "%d", !!param.analyse.b_transform_8x8);
- hb_dict_set(&x264_opts, "8x8dct", buf);
+ hb_dict_set(x264_opts, "8x8dct",
+ hb_value_bool(!!param.analyse.b_transform_8x8));
}
else
{
- hb_dict_unset(&x264_opts, "8x8dct");
+ hb_dict_remove(x264_opts, "8x8dct");
}
if (param.analyse.i_weighted_pred != defaults.analyse.i_weighted_pred)
{
// can be modified by: presets, tune fastdecode, profile
- sprintf(buf, "%d", param.analyse.i_weighted_pred);
- hb_dict_set(&x264_opts, "weightp", buf);
+ hb_dict_set(x264_opts, "weightp",
+ hb_value_int(param.analyse.i_weighted_pred));
}
else
{
- hb_dict_unset(&x264_opts, "weightp");
+ hb_dict_remove(x264_opts, "weightp");
}
if (param.analyse.i_me_method != defaults.analyse.i_me_method)
{
@@ -1452,31 +1464,32 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
param.analyse.i_me_method = X264_ME_TESA;
for (i = 0; x264_motion_est_names[i] != NULL; i++)
if (param.analyse.i_me_method == i)
- hb_dict_set(&x264_opts, "me", x264_motion_est_names[i]);
+ hb_dict_set(x264_opts, "me",
+ hb_value_string(x264_motion_est_names[i]));
}
else
{
- hb_dict_unset(&x264_opts, "me");
+ hb_dict_remove(x264_opts, "me");
}
if (param.analyse.i_me_range != defaults.analyse.i_me_range)
{
// can be modified by: presets
- sprintf(buf, "%d", param.analyse.i_me_range);
- hb_dict_set(&x264_opts, "merange", buf);
+ hb_dict_set(x264_opts, "merange",
+ hb_value_int(param.analyse.i_me_range));
}
else
{
- hb_dict_unset(&x264_opts, "merange");
+ hb_dict_remove(x264_opts, "merange");
}
if (param.analyse.i_mv_range != defaults.analyse.i_mv_range)
{
// can be modified by: level
- sprintf(buf, "%d", param.analyse.i_mv_range);
- hb_dict_set(&x264_opts, "mvrange", buf);
+ hb_dict_set(x264_opts, "mvrange",
+ hb_value_int(param.analyse.i_mv_range));
}
else
{
- hb_dict_unset(&x264_opts, "mvrange");
+ hb_dict_remove(x264_opts, "mvrange");
}
if (param.analyse.i_subpel_refine > 9 && (param.rc.i_aq_mode == 0 ||
param.analyse.i_trellis < 2))
@@ -1487,76 +1500,75 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
if (param.analyse.i_subpel_refine != defaults.analyse.i_subpel_refine)
{
// can be modified by: presets
- sprintf(buf, "%d", param.analyse.i_subpel_refine);
- hb_dict_set(&x264_opts, "subme", buf);
+ hb_dict_set(x264_opts, "subme",
+ hb_value_int(param.analyse.i_subpel_refine));
}
else
{
- hb_dict_unset(&x264_opts, "subme");
+ hb_dict_remove(x264_opts, "subme");
}
if (!param.analyse.b_mixed_references !=
!defaults.analyse.b_mixed_references)
{
// can be modified by: presets
- sprintf(buf, "%d", !!param.analyse.b_mixed_references);
- hb_dict_set(&x264_opts, "mixed-refs", buf);
+ hb_dict_set(x264_opts, "mixed-refs",
+ hb_value_bool(!!param.analyse.b_mixed_references));
}
else
{
- hb_dict_unset(&x264_opts, "mixed-refs");
+ hb_dict_remove(x264_opts, "mixed-refs");
}
if (param.analyse.i_trellis != defaults.analyse.i_trellis)
{
// can be modified by: presets
- sprintf(buf, "%d", param.analyse.i_trellis);
- hb_dict_set(&x264_opts, "trellis", buf);
+ hb_dict_set(x264_opts, "trellis",
+ hb_value_int(param.analyse.i_trellis));
}
else
{
- hb_dict_unset(&x264_opts, "trellis");
+ hb_dict_remove(x264_opts, "trellis");
}
if (!param.analyse.b_fast_pskip != !defaults.analyse.b_fast_pskip)
{
// can be modified by: preset placebo
- sprintf(buf, "%d", !!param.analyse.b_fast_pskip);
- hb_dict_set(&x264_opts, "fast-pskip", buf);
+ hb_dict_set(x264_opts, "fast-pskip",
+ hb_value_bool(!!param.analyse.b_fast_pskip));
}
else
{
- hb_dict_unset(&x264_opts, "fast-pskip");
+ hb_dict_remove(x264_opts, "fast-pskip");
}
if (!param.analyse.b_dct_decimate != !defaults.analyse.b_dct_decimate)
{
// can be modified by: tune grain
- sprintf(buf, "%d", !!param.analyse.b_dct_decimate);
- hb_dict_set(&x264_opts, "dct-decimate", buf);
+ hb_dict_set(x264_opts, "dct-decimate",
+ hb_value_bool(!!param.analyse.b_dct_decimate));
}
else
{
- hb_dict_unset(&x264_opts, "dct-decimate");
+ hb_dict_remove(x264_opts, "dct-decimate");
}
if (!param.analyse.b_psy != !defaults.analyse.b_psy)
{
// can be modified by: tunes
- sprintf(buf, "%d", !!param.analyse.b_psy);
- hb_dict_set(&x264_opts, "psy", buf);
+ hb_dict_set(x264_opts, "psy", hb_value_bool(!!param.analyse.b_psy));
}
else
{
- hb_dict_unset(&x264_opts, "psy");
+ hb_dict_remove(x264_opts, "psy");
}
if (param.analyse.b_psy &&
(param.analyse.f_psy_rd != defaults.analyse.f_psy_rd ||
param.analyse.f_psy_trellis != defaults.analyse.f_psy_trellis))
{
// can be modified by: tunes
- sprintf(buf, "%.2f,%.2f", param.analyse.f_psy_rd,
- param.analyse.f_psy_trellis);
- hb_dict_set(&x264_opts, "psy-rd", buf);
+ hb_dict_set(x264_opts, "psy-rd",
+ value_pair(hb_value_double(param.analyse.f_psy_rd),
+ hb_value_double(param.analyse.f_psy_trellis)));
}
else
{
- hb_dict_unset(&x264_opts, "psy-rd");
+ hb_dict_remove(x264_opts, "psy-rd");
}
/*
* Note: while deadzone is incompatible with trellis, it still has a slight
@@ -1565,126 +1577,122 @@ char * hb_x264_param_unparse(const char *x264_preset, const char *x264_tune,
if (param.analyse.i_luma_deadzone[0] != defaults.analyse.i_luma_deadzone[0])
{
// can be modified by: tune grain
- sprintf(buf, "%d", param.analyse.i_luma_deadzone[0]);
- hb_dict_set(&x264_opts, "deadzone-inter", buf);
+ hb_dict_set(x264_opts, "deadzone-inter",
+ hb_value_int(param.analyse.i_luma_deadzone[0]));
}
else
{
- hb_dict_unset(&x264_opts, "deadzone-inter");
+ hb_dict_remove(x264_opts, "deadzone-inter");
}
if (param.analyse.i_luma_deadzone[1] != defaults.analyse.i_luma_deadzone[1])
{
// can be modified by: tune grain
- sprintf(buf, "%d", param.analyse.i_luma_deadzone[1]);
- hb_dict_set(&x264_opts, "deadzone-intra", buf);
+ hb_dict_set(x264_opts, "deadzone-intra",
+ hb_value_int(param.analyse.i_luma_deadzone[1]));
}
else
{
- hb_dict_unset(&x264_opts, "deadzone-intra");
+ hb_dict_remove(x264_opts, "deadzone-intra");
}
if (param.rc.i_vbv_buffer_size != defaults.rc.i_vbv_buffer_size)
{
// can be modified by: level
- sprintf(buf, "%d", param.rc.i_vbv_buffer_size);
- hb_dict_set(&x264_opts, "vbv-bufsize", buf);
+ hb_dict_set(x264_opts, "vbv-bufsize",
+ hb_value_int(param.rc.i_vbv_buffer_size));
if (param.rc.i_vbv_max_bitrate != defaults.rc.i_vbv_max_bitrate)
{
// can be modified by: level
- sprintf(buf, "%d", param.rc.i_vbv_max_bitrate);
- hb_dict_set(&x264_opts, "vbv-maxrate", buf);
+ hb_dict_set(x264_opts, "vbv-maxrate",
+ hb_value_int(param.rc.i_vbv_max_bitrate));
}
else
{
- hb_dict_unset(&x264_opts, "vbv-maxrate");
+ hb_dict_remove(x264_opts, "vbv-maxrate");
}
}
else
{
- hb_dict_unset(&x264_opts, "vbv-bufsize");
- hb_dict_unset(&x264_opts, "vbv-maxrate");
+ hb_dict_remove(x264_opts, "vbv-bufsize");
+ hb_dict_remove(x264_opts, "vbv-maxrate");
}
if (param.rc.f_ip_factor != defaults.rc.f_ip_factor)
{
// can be modified by: tune grain
- sprintf(buf, "%.2f", param.rc.f_ip_factor);
- hb_dict_set(&x264_opts, "ipratio", buf);
+ hb_dict_set(x264_opts, "ipratio",
+ hb_value_double(param.rc.f_ip_factor));
}
else
{
- hb_dict_unset(&x264_opts, "ipratio");
+ hb_dict_remove(x264_opts, "ipratio");
}
if (param.i_bframe > 0 && !param.rc.b_mb_tree &&
param.rc.f_pb_factor != defaults.rc.f_pb_factor)
{
// can be modified by: tune grain
- sprintf(buf, "%.2f", param.rc.f_pb_factor);
- hb_dict_set(&x264_opts, "pbratio", buf);
+ hb_dict_set(x264_opts, "pbratio",
+ hb_value_double(param.rc.f_pb_factor));
}
else
{
// pbratio requires bframes and is incomaptible with mbtree
- hb_dict_unset(&x264_opts, "pbratio");
+ hb_dict_remove(x264_opts, "pbratio");
}
if (param.rc.f_qcompress != defaults.rc.f_qcompress)
{
// can be modified by: tune grain
- sprintf(buf, "%.2f", param.rc.f_qcompress);
- hb_dict_set(&x264_opts, "qcomp", buf);
+ hb_dict_set(x264_opts, "qcomp", hb_value_double(param.rc.f_qcompress));
}
else
{
- hb_dict_unset(&x264_opts, "qcomp");
+ hb_dict_remove(x264_opts, "qcomp");
}
if (param.rc.i_aq_mode != defaults.rc.i_aq_mode)
{
// can be modified by: preset ultrafast, tune psnr
- sprintf(buf, "%d", param.rc.i_aq_mode);
- hb_dict_set(&x264_opts, "aq-mode", buf);
+ hb_dict_set(x264_opts, "aq-mode", hb_value_int(param.rc.i_aq_mode));
}
else
{
- hb_dict_unset(&x264_opts, "aq-mode");
+ hb_dict_remove(x264_opts, "aq-mode");
}
if (param.rc.i_aq_mode > 0 &&
param.rc.f_aq_strength != defaults.rc.f_aq_strength)
{
// can be modified by: tunes
- sprintf(buf, "%.2f", param.rc.f_aq_strength);
- hb_dict_set(&x264_opts, "aq-strength", buf);
+ hb_dict_set(x264_opts, "aq-strength",
+ hb_value_double(param.rc.f_aq_strength));
}
else
{
- hb_dict_unset(&x264_opts, "aq-strength");
+ hb_dict_remove(x264_opts, "aq-strength");
}
if (!param.rc.b_mb_tree != !defaults.rc.b_mb_tree)
{
// can be modified by: presets, tune zerolatency
- sprintf(buf, "%d", !!param.rc.b_mb_tree);
- hb_dict_set(&x264_opts, "mbtree", buf);
+ hb_dict_set(x264_opts, "mbtree", hb_value_bool(!!param.rc.b_mb_tree));
}
else
{
- hb_dict_unset(&x264_opts, "mbtree");
+ hb_dict_remove(x264_opts, "mbtree");
}
if (param.rc.i_lookahead != defaults.rc.i_lookahead)
{
// can be modified by: presets, tune zerolatency
- sprintf(buf, "%d", param.rc.i_lookahead);
- hb_dict_set(&x264_opts, "rc-lookahead", buf);
+ hb_dict_set(x264_opts, "rc-lookahead",
+ hb_value_int(param.rc.i_lookahead));
}
else
{
- hb_dict_unset(&x264_opts, "rc-lookahead");
+ hb_dict_remove(x264_opts, "rc-lookahead");
}
if (!param.b_vfr_input != !defaults.b_vfr_input)
{
// can be modified by: tune zerolatency
- sprintf(buf, "%d", !param.b_vfr_input);
- hb_dict_set(&x264_opts, "force-cfr", buf);
+ hb_dict_set(x264_opts, "force-cfr", hb_value_bool(!param.b_vfr_input));
}
else
{
- hb_dict_unset(&x264_opts, "force-cfr");
+ hb_dict_remove(x264_opts, "force-cfr");
}
/* convert the x264_opts dictionary to an encopts string */
diff --git a/libhb/encx265.c b/libhb/encx265.c
index 324c07e5b..8743b8d20 100644
--- a/libhb/encx265.c
+++ b/libhb/encx265.c
@@ -184,16 +184,26 @@ int encx265Init(hb_work_object_t *w, hb_job_t *job)
}
/* iterate through x265_opts and parse the options */
- hb_dict_entry_t *entry = NULL;
- hb_dict_t *x265_opts = hb_encopts_to_dict(job->encoder_options, job->vcodec);
- while ((entry = hb_dict_next(x265_opts, entry)) != NULL)
+ hb_dict_t *x265_opts;
+ x265_opts = hb_encopts_to_dict(job->encoder_options, job->vcodec);
+
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(x265_opts);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(x265_opts, iter))
{
+ const char *key = hb_dict_iter_key(iter);
+ hb_value_t *value = hb_dict_iter_value(iter);
+ char *str = hb_value_get_string_xform(value);
+
// here's where the strings are passed to libx265 for parsing
- if (param_parse(param, entry->key, entry->value))
+ if (param_parse(param, key, str))
{
+ free(str);
hb_dict_free(&x265_opts);
goto fail;
}
+ free(str);
}
hb_dict_free(&x265_opts);
diff --git a/libhb/hb_dict.c b/libhb/hb_dict.c
index 48d5c6a01..d8bbc8713 100644
--- a/libhb/hb_dict.c
+++ b/libhb/hb_dict.c
@@ -10,219 +10,561 @@
#include "hb.h"
#include "hb_dict.h"
-hb_dict_t * hb_dict_init( int alloc )
+hb_value_type_t hb_value_type(const hb_value_t *value)
{
- hb_dict_t * dict = NULL;
- dict = malloc( sizeof( hb_dict_t ) );
- if( !dict )
+ if (value == NULL)
+ return HB_VALUE_TYPE_NULL;
+ hb_value_type_t type = json_typeof(value);
+ if (type == JSON_TRUE || type == JSON_FALSE)
+ return HB_VALUE_TYPE_BOOL;
+ return type;
+}
+
+hb_value_t * hb_value_dup(hb_value_t *value)
+{
+ if (value == NULL) return NULL;
+ return json_deep_copy(value);
+}
+
+void hb_value_incref(hb_value_t *value)
+{
+ if (value == NULL) return;
+ json_incref(value);
+}
+
+void hb_value_decref(hb_value_t *value)
+{
+ if (value == NULL) return;
+ json_decref(value);
+}
+
+void hb_value_free(hb_value_t **_value)
+{
+ hb_value_decref(*_value);
+ *_value = NULL;
+}
+
+hb_value_t * hb_value_string(const char * value)
+{
+ // json_string does not create a value for NULL strings.
+ // So create JSON_NULL in this case
+ if (value == NULL)
+ return json_null();
+ return json_string(value);
+}
+
+hb_value_t * hb_value_int(json_int_t value)
+{
+ return json_integer(value);
+}
+
+hb_value_t * hb_value_double(double value)
+{
+ return json_real(value);
+}
+
+hb_value_t * hb_value_bool(int value)
+{
+ return json_boolean(value);
+}
+
+static hb_value_t* xform_null(hb_value_type_t type)
+{
+ switch (type)
{
- hb_log( "ERROR: could not allocate hb_dict_t" );
- return NULL;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_false();
+ case HB_VALUE_TYPE_INT:
+ return json_integer(0);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(0.0);
+ case HB_VALUE_TYPE_STRING:
+ return json_null();
}
- dict->count = 0;
- dict->objects = malloc( alloc * sizeof( hb_dict_entry_t ) );
- if( !dict->objects )
+}
+
+static hb_value_t* xform_bool(const hb_value_t *value, hb_value_type_t type)
+{
+ json_int_t b = json_is_true(value);
+ switch (type)
{
- hb_log( "ERROR: could not allocate hb_dict_t objects" );
- dict->alloc = 0;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean(b);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(b);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(b);
+ case HB_VALUE_TYPE_STRING:
+ {
+ char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, b);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
+ }
}
- else
+}
+
+static hb_value_t* xform_int(const hb_value_t *value, hb_value_type_t type)
+{
+ json_int_t i = json_integer_value(value);
+ switch (type)
{
- dict->alloc = alloc;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean(i);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(i);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(i);
+ case HB_VALUE_TYPE_STRING:
+ {
+ char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, i);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
+ }
}
- return dict;
}
-void hb_dict_free( hb_dict_t ** dict_ptr )
+static hb_value_t* xform_double(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( dict )
+ double d = json_real_value(value);
+ switch (type)
{
- if( dict->objects )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean((int)d != 0);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(d);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(d);
+ case HB_VALUE_TYPE_STRING:
{
- int i;
- for( i = 0; i < dict->count; i++ )
- {
- if( dict->objects[i].key )
- {
- free( dict->objects[i].key );
- }
- if( dict->objects[i].value )
- {
- free( dict->objects[i].value );
- }
- }
- free( dict->objects );
+ char *s = hb_strdup_printf("%g", d);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
}
- free( *dict_ptr );
- *dict_ptr = NULL;
}
}
-void hb_dict_set( hb_dict_t ** dict_ptr, const char * key, const char * value )
+static hb_value_t* xform_string(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( !dict )
+ const char *s = json_string_value(value);
+ switch (type)
{
- hb_log( "hb_dict_set: NULL dictionary" );
- return;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ {
+ return json_null();
+ }
+ case HB_VALUE_TYPE_BOOL:
+ {
+ if (s != NULL &&
+ (!strcasecmp(s, "true") ||
+ !strcasecmp(s, "yes") ||
+ !strcasecmp(s, "1")))
+ {
+ return json_true();
+ }
+ return json_false();
+ }
+ case HB_VALUE_TYPE_INT:
+ {
+ json_int_t i = 0;
+ if (s != NULL)
+ strtoll(s, NULL, 0);
+ return json_integer(i);
+ }
+ case HB_VALUE_TYPE_DOUBLE:
+ {
+ double d = 0.0;
+ if (s != NULL)
+ d = strtod(s, NULL);
+ return json_real(d);
+ }
+ case HB_VALUE_TYPE_STRING:
+ {
+ return json_string(s);
+ }
}
- if( !key || !strlen( key ) )
- return;
- hb_dict_entry_t * entry = hb_dict_get( dict, key );
- if( entry )
+}
+
+static hb_value_t* xform_array(const hb_value_t *value, hb_value_type_t type)
+{
+ hb_value_t *first = NULL;
+ int count = hb_value_array_len(value);
+
+ if (count > 0)
+ first = hb_value_array_get(value, 0);
+ switch (type)
{
- if( entry->value )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ case HB_VALUE_TYPE_BOOL:
+ case HB_VALUE_TYPE_INT:
+ case HB_VALUE_TYPE_DOUBLE:
+ return hb_value_xform(first, type);
+ case HB_VALUE_TYPE_STRING:
{
- if( value && !strcmp( value, entry->value ) )
- return;
+ char *r = strdup("");
+ int ii;
+ for (ii = 0; ii < count; ii++)
+ {
+ hb_value_t *v = hb_value_array_get(value, ii);
+ hb_value_t *x = hb_value_xform(v, type);
+ const char *s = hb_value_get_string(x);
+ if (s != NULL)
+ {
+ char *tmp = r;
+ r = hb_strdup_printf("%s%s,", tmp, s);
+ free(tmp);
+ }
+ hb_value_free(&x);
+ }
+ int len = strlen(r);
+ hb_value_t *v;
+ if (len > 0)
+ {
+ // Removing trailing ','
+ r[len - 1] = 0;
+ v = json_string(r);
+ }
else
{
- free( entry->value );
- entry->value = NULL;
+ free(r);
+ r = NULL;
+ v = json_null();
}
+ free(r);
+ return v;
}
- if( value && strlen( value ) )
- entry->value = strdup( value );
}
- else
+}
+
+static hb_value_t* xform_dict(const hb_value_t *dict, hb_value_type_t type)
+{
+ hb_value_t *first = NULL;
+ hb_dict_iter_t iter = hb_dict_iter_init(dict);
+
+ if (iter != HB_DICT_ITER_DONE)
+ first = hb_dict_iter_value(iter);
+
+ switch (type)
{
- if( dict->alloc <= dict->count )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ case HB_VALUE_TYPE_BOOL:
+ case HB_VALUE_TYPE_INT:
+ case HB_VALUE_TYPE_DOUBLE:
+ return hb_value_xform(first, type);
+ case HB_VALUE_TYPE_STRING:
{
- hb_dict_entry_t * tmp = NULL;
- tmp = malloc( ( 2 * dict->alloc ) * sizeof( hb_dict_entry_t ) );
- if( !tmp )
+ char *r = strdup("");
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(dict);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(dict, iter))
+ {
+ const char *k = hb_dict_iter_key(iter);
+ hb_value_t *v = hb_dict_iter_value(iter);
+ hb_value_t *x = hb_value_xform(v, type);
+ const char *s = hb_value_get_string(x);
+
+ char *tmp = r;
+ r = hb_strdup_printf("%s%s%s%s:",
+ r,
+ k,
+ s ? "=" : "",
+ s ? s : "");
+ free(tmp);
+ hb_value_free(&x);
+ }
+ int len = strlen(r);
+ hb_value_t *v;
+ if (len > 0)
{
- hb_log( "ERROR: could not realloc hb_dict_t objects" );
- return;
+ // Removing trailing ':'
+ r[len - 1] = 0;
+ v = json_string(r);
}
- if( dict->objects )
+ else
{
- if( dict->count )
- memcpy( tmp, dict->objects, dict->count * sizeof( hb_dict_entry_t ) );
- free( dict->objects );
+ free(r);
+ r = NULL;
+ v = json_null();
}
- dict->objects = tmp;
- dict->alloc *= 2;
- }
- dict->objects[dict->count].key = strdup( key );
- if( value && strlen( value ) )
- dict->objects[dict->count].value = strdup( value );
- else
- dict->objects[dict->count].value = NULL;
- dict->count++;
+ free(r);
+ return v;
+ }
}
}
-void hb_dict_unset( hb_dict_t ** dict_ptr, const char * key )
+hb_value_t* hb_value_xform(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( !dict || !dict->objects || !key || !strlen( key ) )
- return;
- int i;
- for( i = 0; i < dict->count; i++ )
- if( !strcmp( key, dict->objects[i].key ) )
+ hb_value_type_t src_type = hb_value_type(value);
+ if (src_type == type && value != NULL)
+ {
+ json_incref((hb_value_t*)value);
+ return (hb_value_t*)value;
+ }
+ switch (src_type)
+ {
+ default:
+ case HB_VALUE_TYPE_NULL:
+ {
+ return xform_null(type);
+ }
+ case HB_VALUE_TYPE_BOOL:
+ {
+ return xform_bool(value, type);
+ }
+ case HB_VALUE_TYPE_INT:
{
- free( dict->objects[i].key );
- if( dict->objects[i].value )
- free( dict->objects[i].value );
- if( i != --dict->count )
- memmove( &dict->objects[i], &dict->objects[i+1],
- sizeof( hb_dict_entry_t ) * ( dict->count - i ) );
+ return xform_int(value, type);
}
+ case HB_VALUE_TYPE_DOUBLE:
+ {
+ return xform_double(value, type);
+ }
+ case HB_VALUE_TYPE_STRING:
+ {
+ return xform_string(value, type);
+ }
+ case HB_VALUE_TYPE_ARRAY:
+ {
+ return xform_array(value, type);
+ }
+ case HB_VALUE_TYPE_DICT:
+ {
+ return xform_dict(value, type);
+ }
+ }
}
-hb_dict_entry_t * hb_dict_get( hb_dict_t * dict, const char * key )
+const char * hb_value_get_string(const hb_value_t *value)
{
- if( !dict || !dict->objects || !key || !strlen( key ) )
- return NULL;
- int i;
- for( i = 0; i < dict->count; i++ )
- if( !strcmp( key, dict->objects[i].key ) )
- return &dict->objects[i];
- return NULL;
+ if (hb_value_type(value) != HB_VALUE_TYPE_STRING) return NULL;
+ return json_string_value(value);
+}
+
+json_int_t hb_value_get_int(const hb_value_t *value)
+{
+ json_int_t result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_INT);
+ result = json_integer_value(v);
+ json_decref(v);
+ return result;
+}
+
+double hb_value_get_double(const hb_value_t *value)
+{
+ double result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_DOUBLE);
+ result = json_real_value(v);
+ json_decref(v);
+ return result;
}
-hb_dict_entry_t * hb_dict_next( hb_dict_t * dict, hb_dict_entry_t * previous )
+int hb_value_get_bool(const hb_value_t *value)
{
- if( dict == NULL || dict->objects == NULL || !dict->count )
+ int result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_BOOL);
+ result = json_is_true(v);
+ json_decref(v);
+ return result;
+}
+
+char*
+hb_value_get_string_xform(const hb_value_t *value)
+{
+ char *result;
+ if (hb_value_type(value) == HB_VALUE_TYPE_NULL)
+ return NULL;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_STRING);
+ if (hb_value_type(v) == HB_VALUE_TYPE_NULL)
return NULL;
- if( previous == NULL )
- return &dict->objects[0];
- unsigned int prev_index = previous - dict->objects;
- if( prev_index + 1 < dict->count )
- return &dict->objects[prev_index+1];
- return NULL;
+ result = strdup(json_string_value(v));
+ json_decref(v);
+ return result;
+}
+
+void hb_dict_free(hb_dict_t **_dict)
+{
+ hb_value_free(_dict);
+}
+
+hb_dict_t * hb_dict_init()
+{
+ return json_object();
+}
+
+void hb_dict_set(hb_dict_t * dict, const char *key, hb_value_t *value)
+{
+ json_object_set_new(dict, key, value);
+}
+
+int hb_dict_remove(hb_dict_t * dict, const char * key)
+{
+ return json_object_del(dict, key) == 0;
+}
+
+hb_value_t * hb_dict_get(hb_dict_t * dict, const char * key)
+{
+ return json_object_get(dict, key);
+}
+
+hb_dict_iter_t hb_dict_iter_init(const hb_dict_t *dict)
+{
+ if (dict == NULL)
+ return HB_DICT_ITER_DONE;
+ return json_object_iter((hb_dict_t*)dict);
+}
+
+hb_dict_iter_t hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter)
+{
+ return json_object_iter_next((hb_dict_t*)dict, iter);
+}
+
+const char * hb_dict_iter_key(const hb_dict_iter_t iter)
+{
+ return json_object_iter_key(iter);
}
-hb_dict_t * hb_encopts_to_dict( const char * encopts, int encoder )
+hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter)
+{
+ return json_object_iter_value(iter);
+}
+
+hb_value_array_t*
+hb_value_array_init()
+{
+ return json_array();
+}
+
+void
+hb_value_array_clear(hb_value_array_t *array)
+{
+ json_array_clear(array);
+}
+
+hb_value_t*
+hb_value_array_get(const hb_value_array_t *array, int index)
+{
+ return json_array_get(array, index);
+}
+
+void
+hb_value_array_set(hb_value_array_t *array, int index, hb_value_t *value)
+{
+ if (index < 0 || index >= json_array_size(array))
+ {
+ hb_error("hb_value_array_set: invalid index %d size %zu",
+ index, json_array_size(array));
+ return;
+ }
+ json_array_set_new(array, index, value);
+}
+
+void
+hb_value_array_insert(hb_value_array_t *array, int index, hb_value_t *value)
+{
+ json_array_insert_new(array, index, value);
+}
+
+void
+hb_value_array_append(hb_value_array_t *array, hb_value_t *value)
+{
+ json_array_append_new(array, value);
+}
+
+void
+hb_value_array_remove(hb_value_array_t *array, int index)
+{
+ json_array_remove(array, index);
+}
+
+void
+hb_value_array_copy(hb_value_array_t *dst,
+ const hb_value_array_t *src, int count)
+{
+ size_t len;
+ int ii;
+
+ // empty the first array if it is not already empty
+ json_array_clear(dst);
+
+ len = hb_value_array_len(src);
+ count = MIN(count, len);
+ for (ii = 0; ii < count; ii++)
+ hb_value_array_append(dst, hb_value_dup(hb_value_array_get(src, ii)));
+}
+
+size_t
+hb_value_array_len(const hb_value_array_t *array)
+{
+ return json_array_size(array);
+}
+
+hb_dict_t * hb_encopts_to_dict(const char * encopts, int encoder)
{
hb_dict_t * dict = NULL;
- if( encopts && *encopts )
+
+ if (encopts && *encopts)
{
char *cur_opt, *opts_start, *value;
const char *name;
- dict = hb_dict_init( 10 );
+ dict = hb_dict_init();
if( !dict )
return NULL;
- cur_opt = opts_start = strdup( encopts );
- if( opts_start )
+ cur_opt = opts_start = strdup(encopts);
+ if (opts_start)
{
- while( *cur_opt )
+ while (*cur_opt)
{
name = cur_opt;
- cur_opt += strcspn( cur_opt, ":" );
- if( *cur_opt )
+ cur_opt += strcspn(cur_opt, ":");
+ if (*cur_opt)
{
*cur_opt = 0;
cur_opt++;
}
- value = strchr( name, '=' );
- if( value )
+ value = strchr(name, '=');
+ if (value)
{
*value = 0;
value++;
}
// x264 has multiple names for some options
- if( encoder == HB_VCODEC_X264 )
- name = hb_x264_encopt_name( name );
+ if (encoder == HB_VCODEC_X264)
+ name = hb_x264_encopt_name(name);
#ifdef USE_X265
// x265 has multiple names for some options
- if( encoder == HB_VCODEC_X265 )
- name = hb_x265_encopt_name( name );
+ if (encoder == HB_VCODEC_X265)
+ name = hb_x265_encopt_name(name);
#endif
- hb_dict_set( &dict, name, value );
+ if (name != NULL)
+ {
+ hb_dict_set(dict, name, hb_value_string(value));
+ }
}
}
- free( opts_start );
+ free(opts_start);
}
return dict;
}
-char * hb_dict_to_encopts( hb_dict_t * dict )
+char * hb_dict_to_encopts(const hb_dict_t * dict)
{
- int first_opt = 1;
- char *tmp, *encopts_tmp, *encopts = NULL;
- hb_dict_entry_t * entry = NULL;
- while( ( entry = hb_dict_next( dict, entry ) ) )
- {
- tmp = hb_strdup_printf( "%s%s%s%s",
- first_opt ? "" : ":",
- entry->key,
- entry->value ? "=" : "",
- entry->value ? entry->value : "" );
- if( tmp )
- {
- encopts_tmp = hb_strncat_dup( encopts, tmp, strlen( tmp ) );
- if( encopts_tmp )
- {
- if( encopts )
- free( encopts );
- encopts = encopts_tmp;
- }
- first_opt = 0;
- free( tmp );
- }
- }
- return encopts;
+ return hb_value_get_string_xform(dict);
}
diff --git a/libhb/hb_dict.h b/libhb/hb_dict.h
index daa3b39a9..7df1a56fa 100644
--- a/libhb/hb_dict.h
+++ b/libhb/hb_dict.h
@@ -9,46 +9,109 @@
#if !defined(HB_DICT_H)
#define HB_DICT_H
-typedef struct hb_dict_entry_s hb_dict_entry_t;
-typedef struct hb_dict_s hb_dict_t;
+#include <jansson.h>
-/* Basic dictionary implementation.
+#define HB_VALUE_TYPE_DICT JSON_OBJECT
+#define HB_VALUE_TYPE_ARRAY JSON_ARRAY
+#define HB_VALUE_TYPE_STRING JSON_STRING
+#define HB_VALUE_TYPE_INT JSON_INTEGER
+#define HB_VALUE_TYPE_DOUBLE JSON_REAL
+#define HB_VALUE_TYPE_NULL JSON_NULL
+#define HB_VALUE_TYPE_BOOL 0xff
+
+#define HB_DICT_ITER_DONE NULL
+
+typedef int hb_value_type_t;
+typedef json_t hb_value_t;
+typedef hb_value_t hb_dict_t;
+typedef hb_value_t hb_value_array_t;
+typedef void* hb_dict_iter_t;
+
+/* A dictionary implementation.
*
* an hb_dict_t must be initialized with hb_dict_init() before use.
*
* "key" must be a string with non-zero length (NULL and "" are invalid keys).
- * "value" can be NULL (the zero-length string "" is mapped to NULL).
- *
- * hb_dict_next( dict, NULL ) returns the first key in the dictionary.
- * hb_dict_next( dict, previous ) returns key directly following previous, or
- * NULL if the end of the dictionary was reached.
- *
- * hb_encopts_to_dict() converts an op1=val1:opt2=val2:opt3=val3 type string to
- * an hb_dict_t dictionary. */
+ * "value" must be an hb_value_t*
+ */
+hb_dict_t * hb_dict_init();
+/* free dictionary and release references to all values it contains */
+void hb_dict_free(hb_dict_t ** dict_ptr);
+/* add value to dictionary. dictionary takes ownership of value */
+void hb_dict_set(hb_dict_t * dict, const char * key,
+ hb_value_t * value);
+/* remove value from dictionary. releases reference to value */
+int hb_dict_remove(hb_dict_t * dict, const char * key);
+/* get value from dictionary. value has borrowed reference */
+hb_value_t * hb_dict_get(hb_dict_t * dict, const char * key);
+
+/* dict iterator
+ * hb_dict_iter_init(dict) returns an iter to the first key/value in the dict
+ * hb_dict_iter_next(dict, iter) returns an iter to the next key/value
+ * HB_DICT_ITER_DONE if the end of the dictionary was reached.
+ */
+hb_dict_iter_t hb_dict_iter_init(const hb_dict_t *dict);
+hb_dict_iter_t hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter);
+/* get key from iter */
+const char * hb_dict_iter_key(const hb_dict_iter_t iter);
+/* get value from iter. value has borrowed reference */
+hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter);
-hb_dict_t * hb_dict_init( int alloc );
-void hb_dict_free( hb_dict_t ** dict_ptr );
+/* hb_value_array_t */
+hb_value_array_t * hb_value_array_init();
+/* remove all elements of array */
+void hb_value_array_clear(hb_value_array_t *array);
+/* get value from array. value has borrowed reference */
+hb_value_t * hb_value_array_get(const hb_value_array_t *array, int index);
+/* replace value at index in array. array takes ownership of new value */
+void hb_value_array_set(hb_value_array_t *array, int index,
+ hb_value_t *value);
+/* insert value at index in array. values move up.
+ * array takes ownership of new value */
+void hb_value_array_insert(hb_value_array_t *array, int index,
+ hb_value_t *value);
+/* append value to array. array takes ownership of new value */
+void hb_value_array_append(hb_value_array_t *array,
+ hb_value_t *value);
+/* remove value from array. releases reference to value */
+void hb_value_array_remove(hb_value_array_t *array, int index);
+/* clears dst and performs a deep copy */
+void hb_value_array_copy(hb_value_array_t *dst,
+ const hb_value_array_t *src, int count);
+size_t hb_value_array_len(const hb_value_array_t *array);
-void hb_dict_set( hb_dict_t ** dict_ptr, const char * key, const char * value );
-void hb_dict_unset( hb_dict_t ** dict_ptr, const char * key );
+/* hb_value_t */
+int hb_value_type(const hb_value_t *value);
+hb_value_t * hb_value_dup(hb_value_t *value);
+void hb_value_incref(hb_value_t *value);
+void hb_value_decref(hb_value_t *value);
+void hb_value_free(hb_value_t **value);
-hb_dict_entry_t * hb_dict_get( hb_dict_t * dict, const char * key );
-hb_dict_entry_t * hb_dict_next( hb_dict_t * dict, hb_dict_entry_t * previous );
+/* Create new hb_value_t */
+hb_value_t * hb_value_string(const char *value);
+hb_value_t * hb_value_int(json_int_t value);
+hb_value_t * hb_value_double(double value);
+hb_value_t * hb_value_bool(int value);
-hb_dict_t * hb_encopts_to_dict( const char * encopts, int encoder );
-char * hb_dict_to_encopts( hb_dict_t * dict );
+/* Transform hb_value_t from one type to another */
+hb_value_t * hb_value_xform(const hb_value_t *value, int type);
-struct hb_dict_entry_s
-{
- char * key;
- char * value;
-};
+/* Extract values */
+/* hb_value_t must be of type HB_VALUE_TYPE_STRING */
+const char * hb_value_get_string(const hb_value_t *value);
+/* hb_value_t may be of any type, automatic conversion performed */
+json_int_t hb_value_get_int(const hb_value_t *value);
+double hb_value_get_double(const hb_value_t *value);
+int hb_value_get_bool(const hb_value_t *value);
+/* converts value type and returns an allocated string representation.
+ * caller must free the returned string */
+char * hb_value_get_string_xform(const hb_value_t *value);
-struct hb_dict_s
-{
- int alloc;
- int count;
- hb_dict_entry_t * objects;
-};
+/* specialized dict functions */
+/*
+ * hb_encopts_to_dict() converts an op1=val1:opt2=val2:opt3=val3 type string to
+ * an hb_dict_t dictionary. */
+hb_dict_t * hb_encopts_to_dict(const char * encopts, int encoder);
+char * hb_dict_to_encopts(const hb_dict_t * dict);
#endif // !defined(HB_DICT_H)
diff --git a/libhb/hb_json.c b/libhb/hb_json.c
index f4b1bb814..8020221d1 100644
--- a/libhb/hb_json.c
+++ b/libhb/hb_json.c
@@ -8,6 +8,7 @@
*/
#include <jansson.h>
+#include "hb.h"
#include "hb_json.h"
#include "libavutil/base64.h"
diff --git a/libhb/hb_json.h b/libhb/hb_json.h
index b5025a6c2..a6ec311eb 100644
--- a/libhb/hb_json.h
+++ b/libhb/hb_json.h
@@ -14,7 +14,7 @@
extern "C" {
#endif
-#include "hb.h"
+#include "common.h"
char * hb_get_title_set_json(hb_handle_t * h);
char * hb_title_to_json(const hb_title_t * title);