summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/encavcodec.c56
-rw-r--r--libhb/encx264.c67
-rw-r--r--libhb/hb_dict.c172
-rw-r--r--libhb/hb_dict.h43
4 files changed, 247 insertions, 91 deletions
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index 4744712c7..5a77ceb4b 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -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.
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 253b95b87..7836b9add 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -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
index 000000000..5d54d8b4e
--- /dev/null
+++ b/libhb/hb_dict.c
@@ -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
index 000000000..b8ca4c562
--- /dev/null
+++ b/libhb/hb_dict.h
@@ -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;
+};