diff options
-rw-r--r-- | libhb/encavcodec.c | 56 | ||||
-rw-r--r-- | libhb/encx264.c | 67 | ||||
-rw-r--r-- | libhb/hb_dict.c | 172 | ||||
-rw-r--r-- | libhb/hb_dict.h | 43 |
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( ¶m, 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( ¶m, 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; +}; |