]> granicus.if.org Git - handbrake/commitdiff
libhb: add basic dictionary implementation.
authorRodeo <tdskywalker@gmail.com>
Wed, 28 Mar 2012 22:56:52 +0000 (22:56 +0000)
committerRodeo <tdskywalker@gmail.com>
Wed, 28 Mar 2012 22:56:52 +0000 (22:56 +0000)
Note: under OS X, this commit may require a full rebuild to work properly.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4550 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/encavcodec.c
libhb/encx264.c
libhb/hb_dict.c [new file with mode: 0644]
libhb/hb_dict.h [new file with mode: 0644]

index 4744712c7a5c19730d68eea759cf641badc0fbfb..5a77ceb4b2ff8ecee60c1ca9693a3bcf155985ff 100644 (file)
@@ -5,6 +5,7 @@
    It may be used under the terms of the GNU General Public License. */
 
 #include "hb.h"
+#include "hb_dict.h"
 #include "hbffmpeg.h"
 
 /*
@@ -156,51 +157,22 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
     context->time_base.num = fps.den;
     context->gop_size  = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 );
 
-    /*
-        This section passes the string advanced_opts to avutil for parsing 
-        into an AVCodecContext.
-
-        The string is set up like this:
-        option1=value1:option2=value2
-
-        So, you have to iterate through based on the colons, and then put
-        the left side of the equals sign in "name" and the right side into
-        "value." Then you hand those strings off to avutil for interpretation.
-     */
-    AVDictionary *av_opts = NULL;
+    /* place job->advanced_opts in an hb_dict_t for convenience */
+    hb_dict_t * lavc_opts = NULL;
     if( job->advanced_opts != NULL && *job->advanced_opts != '\0' )
     {
-        char *opts, *opts_start;
-
-        opts = opts_start = strdup(job->advanced_opts);
-
-        if( opts_start )
-        {
-            while( *opts )
-            {
-                char *name = opts;
-                char *value;
-
-                opts += strcspn( opts, ":" );
-                if( *opts )
-                {
-                    *opts = 0;
-                    opts++;
-                }
-
-                value = strchr( name, '=' );
-                if( value )
-                {
-                    *value = 0;
-                    value++;
-                }
-
-                /* Here's where the strings are passed to avutil for parsing. */
-                av_dict_set( &av_opts, name, value, 0 );
-            }
-        }
-        free(opts_start);
+        lavc_opts = hb_encopts_to_dict( job->advanced_opts );
+    }
+    /* iterate through lavc_opts and have avutil parse the options for us */
+    int ret;
+    AVDictionary * av_opts = NULL;
+    hb_dict_entry_t * entry = NULL;
+    while( ( entry = hb_dict_next( lavc_opts, entry ) ) )
+    {
+        /* Here's where the strings are passed to avutil for parsing. */
+        av_dict_set( &av_opts, entry->key, entry->value, 0 );
     }
+    hb_dict_free( &lavc_opts );
 
     // Now set the things in context that we don't want to allow
     // the user to override.
index 253b95b87f1dd7db167d12b7eaca81b525ccd248..7836b9add6debddfab1984a45f50df8232623de0 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdarg.h>
 
 #include "hb.h"
+#include "hb_dict.h"
 #include "encx264.h"
 
 int  encx264Init( hb_work_object_t *, hb_job_t * );
@@ -161,58 +162,26 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
         param.vui.i_colmatrix = 6;
     }
 
-    /*
-        This section passes the string advanced_opts to libx264 for parsing into
-        parameter names and values.
-
-        The string is set up like this:
-        option1=value1:option2=value 2
-
-        So, you have to iterate through based on the colons, and then put
-        the left side of the equals sign in "name" and the right side into
-        "value." Then you hand those strings off to x264 for interpretation.
-
-        This is all based on the universal x264 option handling Loren
-        Merritt implemented in the Mplayer/Mencoder project.
-     */
-
+    /* place job->advanced_opts in an hb_dict_t for convenience */
+    hb_dict_t * x264_opts = NULL;
     if( job->advanced_opts != NULL && *job->advanced_opts != '\0' )
     {
-        char *x264opts, *x264opts_start;
-
-        x264opts = x264opts_start = strdup(job->advanced_opts);
-
-        while( x264opts_start && *x264opts )
-        {
-            char *name = x264opts;
-            char *value;
-            int ret;
-
-            x264opts += strcspn( x264opts, ":" );
-            if( *x264opts )
-            {
-                *x264opts = 0;
-                x264opts++;
-            }
-
-            value = strchr( name, '=' );
-            if( value )
-            {
-                *value = 0;
-                value++;
-            }
-
-            /* Here's where the strings are passed to libx264 for parsing. */
-            ret = x264_param_parse( &param, name, value );
-
-            /* Let x264 sanity check the options for us*/
-            if( ret == X264_PARAM_BAD_NAME )
-                hb_log( "x264 options: Unknown suboption %s", name );
-            if( ret == X264_PARAM_BAD_VALUE )
-                hb_log( "x264 options: Bad argument %s=%s", name, value ? value : "(null)" );
-        }
-        free(x264opts_start);
+        x264_opts = hb_encopts_to_dict( job->advanced_opts );
+    }
+    /* 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 ) ) )
+    {
+        /* Here's where the strings are passed to libx264 for parsing. */
+        ret = x264_param_parse( &param, entry->key, entry->value );
+        /* 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)" );
     }
+    hb_dict_free( &x264_opts );
 
     /* Reload colorimetry settings in case custom values were set
      * in the advanced_opts string */
diff --git a/libhb/hb_dict.c b/libhb/hb_dict.c
new file mode 100644 (file)
index 0000000..5d54d8b
--- /dev/null
@@ -0,0 +1,172 @@
+/* This file is part of the HandBrake source code.
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include "hb.h"
+#include "hb_dict.h"
+
+hb_dict_t * hb_dict_init( int alloc )
+{
+    hb_dict_t * dict = NULL;
+    dict = malloc( sizeof( hb_dict_t ) );
+    if( !dict )
+    {
+        hb_log( "ERROR: could not allocate hb_dict_t" );
+        return NULL;
+    }
+    dict->count = 0;
+    dict->objects = malloc( alloc * sizeof( hb_dict_entry_t ) );
+    if( !dict->objects )
+    {
+        hb_log( "ERROR: could not allocate hb_dict_t objects" );
+        dict->alloc = 0;
+    }
+    else
+    {
+        dict->alloc = alloc;
+    }
+    return dict;
+}
+
+void hb_dict_free( hb_dict_t ** dict_ptr )
+{
+    hb_dict_t * dict = *dict_ptr;
+    if( dict )
+    {
+        if( dict->objects )
+        {
+            int i;
+            for( i = 0; i < dict->count; i++ )
+            {
+                if( dict->objects[i].key )
+                {
+                    free( dict->objects[i].key );
+                    dict->objects[i].key = NULL;
+                }
+                if( dict->objects[i].value )
+                {
+                    free( dict->objects[i].value );
+                    dict->objects[i].value = NULL;
+                }
+            }
+            free( dict->objects );
+            dict->objects = NULL;
+        }
+        free( *dict_ptr );
+        *dict_ptr = NULL;
+    }
+}
+
+void hb_dict_set( hb_dict_t ** dict_ptr, const char * key, const char * value )
+{
+    hb_dict_t * dict = *dict_ptr;
+    if( !dict )
+    {
+        hb_log( "hb_dict_set: NULL dictionary" );
+        return;
+    }
+    if( !key || !strlen( key ) )
+        return;
+    hb_dict_entry_t * entry = hb_dict_get( dict, key );
+    if( entry )
+    {
+        if( entry->value )
+        {
+            if( value && !strcmp( value, entry->value ) )
+                return;
+            else
+            {
+                free( entry->value );
+                entry->value = NULL;
+            }
+        }
+        if( value && strlen( value ) )
+            entry->value = strdup( value );
+    }
+    else
+    {
+        if( dict->alloc <= dict->count )
+        {
+            hb_dict_entry_t * tmp = NULL;
+            tmp = malloc( ( 2 * dict->alloc ) * sizeof( hb_dict_entry_t ) );
+            if( !tmp )
+            {
+                hb_log( "ERROR: could not realloc hb_dict_t objects" );
+                return;
+            }
+            if( dict->objects )
+            {
+                if( dict->count )
+                    memcpy( tmp, dict->objects, dict->count * sizeof( hb_dict_entry_t ) );
+                free( dict->objects );
+            }
+            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++;
+    }
+}
+
+hb_dict_entry_t * hb_dict_get( hb_dict_t * dict, const char * key )
+{
+    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;
+}
+
+hb_dict_entry_t * hb_dict_next( hb_dict_t * dict, hb_dict_entry_t * previous )
+{
+    if( !dict || !dict->objects )
+        return NULL;
+    if( !previous )
+        return &dict->objects[0];
+    int i;
+    for( i = 0; i+1 < dict->count; i++ )
+        if( &dict->objects[i] == previous )
+            return &dict->objects[i+1];
+    return NULL;
+}
+
+hb_dict_t * hb_encopts_to_dict( const char * encopts )
+{
+    hb_dict_t * dict = NULL;
+    if( encopts && *encopts )
+    {
+        char *cur_opt, *opts_start, *name, *value;
+        dict = hb_dict_init( 10 );
+        if( !dict )
+            return NULL;
+        cur_opt = opts_start = strdup( encopts );
+        if( opts_start )
+        {
+            while( *cur_opt )
+            {
+                name = cur_opt;
+                cur_opt += strcspn( cur_opt, ":" );
+                if( *cur_opt )
+                {
+                    *cur_opt = 0;
+                    cur_opt++;
+                }
+                value = strchr( name, '=' );
+                if( value )
+                {
+                    *value = 0;
+                    value++;
+                }
+                hb_dict_set( &dict, name, value );
+            }
+        }
+        free( opts_start );
+    }
+    return dict;
+}
\ No newline at end of file
diff --git a/libhb/hb_dict.h b/libhb/hb_dict.h
new file mode 100644 (file)
index 0000000..b8ca4c5
--- /dev/null
@@ -0,0 +1,43 @@
+/* This file is part of the HandBrake source code.
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License. */
+
+typedef struct hb_dict_entry_s hb_dict_entry_t;
+typedef struct hb_dict_s       hb_dict_t;
+
+/* Basic 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. */
+
+hb_dict_t * hb_dict_init( int alloc );
+void        hb_dict_free( hb_dict_t ** dict_ptr );
+
+void hb_dict_set(  hb_dict_t ** dict_ptr, const char * key, const char * 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 );
+
+hb_dict_t * hb_encopts_to_dict( const char * encopts );
+
+struct hb_dict_entry_s
+{
+    char * key;
+    char * value;
+};
+
+struct hb_dict_s
+{
+    int alloc;
+    int count;
+    hb_dict_entry_t * objects;
+};