]> granicus.if.org Git - handbrake/commitdiff
libhb: use jansson for hb_dict
authorjstebbins <jstebbins.hb@gmail.com>
Mon, 9 Mar 2015 15:05:47 +0000 (15:05 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Mon, 9 Mar 2015 15:05:47 +0000 (15:05 +0000)
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

libhb/enc_qsv.c
libhb/encavcodec.c
libhb/encx264.c
libhb/encx265.c
libhb/hb_dict.c
libhb/hb_dict.h
libhb/hb_json.c
libhb/hb_json.h

index 8051bd5d06f2ebac854b2244dfc7bd258a2affcb..c4aca79ff9885041d61c4c3ca411951e7cddf262 100644 (file)
@@ -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);
     }
index fe479a3935958fc8d2034f6de53366a2883e205b..7b1c01ccca82f305f797590912692a7b3eb4bec8 100644 (file)
@@ -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 );
 
index 780385d7b8e6042eadf33d826be81548ee184b5f..d64e56547444e4fefb7e30117cf7a948c0c73418 100644 (file)
@@ -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 */
index 324c07e5ba48a95d45067f92e5350c000aee3d31..8743b8d201c780673e74b4af61a002c9daf0eea5 100644 (file)
@@ -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);
 
index 48d5c6a0148f9333e2d5f5c7421d21af49379d67..d8bbc8713ad0173645f84333071058a1dc5302fe 100644 (file)
 #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);
 }
index daa3b39a9fcbb213d169676506509754153edb20..7df1a56fac57df133ee3669a78998ceed3922134 100644 (file)
 #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)
index f4b1bb81467bf379df0b8ab22bbdd729a2cd7609..8020221d10bdb87e89dfcc4f3bc12115ee9c10ac 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <jansson.h>
+#include "hb.h"
 #include "hb_json.h"
 #include "libavutil/base64.h"
 
index b5025a6c28dcac58ed108bab53fe14e58fda035b..a6ec311ebd2834366f897134760d7857cb8f0cfa 100644 (file)
@@ -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);