📄 lqt_codecinfo.c
字号:
/* also init registry */ lqt_registry_init(); lqt_registry_lock(); ptr = lqt_audio_codecs; while(ptr) { for(j = 0; j < ptr->num_wav_ids; j++) { if(ptr->wav_ids[j] == wav_id) { if((encode && (ptr->direction != LQT_DIRECTION_DECODE)) || (!encode && (ptr->direction != LQT_DIRECTION_ENCODE))) { tmp_ptr = ptr; break; } } } if(tmp_ptr) break; ptr = ptr->next; } if(tmp_ptr) { ret = calloc(2, sizeof(lqt_codec_info_t*)); *ret = copy_codec_info(tmp_ptr); } lqt_registry_unlock(); return ret; }lqt_codec_info_t ** lqt_find_video_codec(char * fourcc, int encode) { int j; lqt_codec_info_t * tmp_ptr = (lqt_codec_info_t*)0; lqt_codec_info_t * ptr; lqt_codec_info_t ** ret = (lqt_codec_info_t **)0; /* also init registry */ lqt_registry_init(); lqt_registry_lock(); ptr = lqt_video_codecs; while(ptr) { for(j = 0; j < ptr->num_fourccs; j++) { if(MATCH_FOURCC(ptr->fourccs[j], fourcc)) { if((encode && (ptr->direction != LQT_DIRECTION_DECODE)) || (!encode && (ptr->direction != LQT_DIRECTION_ENCODE))) { tmp_ptr = ptr; break; } } } if(tmp_ptr) break; ptr = ptr->next; } if(tmp_ptr) { ret = calloc(2, sizeof(lqt_codec_info_t*)); *ret = copy_codec_info(tmp_ptr); } lqt_registry_unlock(); return ret; }/* * Query codec registry */lqt_codec_info_t ** lqt_query_registry(int audio, int video, int encode, int decode) { lqt_codec_info_t ** ret; const lqt_codec_info_t * info; int num_codecs = 0, num_added = 0, i; /* also init registry */ lqt_registry_init(); lqt_registry_lock(); if(audio) { for(i = 0; i < lqt_num_audio_codecs; i++) { info = lqt_get_audio_codec_info(i); if((encode && (info->direction != LQT_DIRECTION_DECODE)) || (decode && (info->direction != LQT_DIRECTION_ENCODE))) num_codecs++; } } if(video) { for(i = 0; i < lqt_num_video_codecs; i++) { info = lqt_get_video_codec_info(i); if((encode && (info->direction != LQT_DIRECTION_DECODE)) || (decode && (info->direction != LQT_DIRECTION_ENCODE))) num_codecs++; } } ret = calloc(num_codecs+1, sizeof(lqt_codec_info_t*)); if(audio) { for(i = 0; i < lqt_num_audio_codecs; i++) { info = lqt_get_audio_codec_info(i); if((encode && (info->direction != LQT_DIRECTION_DECODE)) || (decode && (info->direction != LQT_DIRECTION_ENCODE))) { ret[num_added] = copy_codec_info(info); num_added++; } } } if(video) { for(i = 0; i < lqt_num_video_codecs; i++) { info = lqt_get_video_codec_info(i); if((encode && (info->direction != LQT_DIRECTION_DECODE)) || (decode && (info->direction != LQT_DIRECTION_ENCODE))) { ret[num_added] = copy_codec_info(info); num_added++; } } } lqt_registry_unlock(); return ret; }/* * Find a codec by it's unique (short) name */lqt_codec_info_t ** lqt_find_audio_codec_by_name(const char * name) { const lqt_codec_info_t * info; int i; lqt_codec_info_t ** ret = (lqt_codec_info_t**)0; if(!name) return ret; /* also init registry */ lqt_registry_init(); lqt_registry_lock(); info = lqt_get_audio_codec_info(0); for(i = 0; i < lqt_num_audio_codecs; i++) { if(!strcmp(info->name, name)) { ret = calloc(2, sizeof(lqt_codec_info_t*)); *ret = copy_codec_info(info); break; } else info = info->next; } lqt_registry_unlock(); return ret; }lqt_codec_info_t ** lqt_find_video_codec_by_name(const char * name) { const lqt_codec_info_t * info; int i; lqt_codec_info_t ** ret = (lqt_codec_info_t**)0; if(!name) return ret; /* also init registry */ lqt_registry_init(); lqt_registry_lock(); info = lqt_get_video_codec_info(0); for(i = 0; i < lqt_num_video_codecs; i++) { if(!strcmp(info->name, name)) { ret = calloc(2, sizeof(lqt_codec_info_t*)); *ret = copy_codec_info(info); break; } else info = info->next; } lqt_registry_unlock(); return ret; }/* * Get infos about the Codecs of a file * To be called after quicktime_open() when reading * or quicktime_set_audio()/quicktime_set_video() when writing */lqt_codec_info_t ** lqt_audio_codec_from_file(quicktime_t * file, int track) { char * name = ((quicktime_codec_t*)(file->atracks[track].codec))->codec_name; return lqt_find_audio_codec_by_name(name); }lqt_codec_info_t ** lqt_video_codec_from_file(quicktime_t * file, int track) { char * name = ((quicktime_codec_t*)(file->vtracks[track].codec))->codec_name; return lqt_find_video_codec_by_name(name); }/* * Destroys the codec info structure returned by the functions * above */void lqt_destroy_codec_info(lqt_codec_info_t ** info) { lqt_codec_info_t ** ptr = info; if(!ptr) return; while(*ptr) { destroy_codec_info(*ptr); ptr++; } free(info); }void lqt_set_default_parameter(lqt_codec_type type, int encode, const char * codec_name, const char * parameter_name, lqt_parameter_value_t * val) { int i, imax, parameter_found = 0; lqt_codec_info_t * codec_info; lqt_parameter_info_t * parameter_info; /* also init registry */ lqt_registry_init(); lqt_registry_lock(); if(type == LQT_CODEC_AUDIO) codec_info = lqt_audio_codecs; else codec_info = lqt_video_codecs; /* Search codec */ while(codec_info) { if(!strcmp(codec_name, codec_info->name)) break; codec_info = codec_info->next; } if(!codec_info) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "lqt_set_default_parameter: No %s codec %s found", ((type == LQT_CODEC_AUDIO) ? "audio" : "video"), codec_name); lqt_registry_unlock(); return; } /* Search parameter */ if(encode) { imax = codec_info->num_encoding_parameters; parameter_info = codec_info->encoding_parameters; } else { imax = codec_info->num_decoding_parameters; parameter_info = codec_info->decoding_parameters; } for(i = 0; i < imax; i++) { if(!strcmp(parameter_info[i].name, parameter_name)) { parameter_found = 1; break; } } if(!parameter_found) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "lqt_set_default_parameter: No parameter %s for codec %s found", parameter_name, codec_name); lqt_registry_unlock(); return; } /* Set the value */ switch(parameter_info[i].type) { case LQT_PARAMETER_INT: parameter_info[i].val_default.val_int = val->val_int; break; case LQT_PARAMETER_FLOAT: parameter_info[i].val_default.val_float = val->val_float; break; case LQT_PARAMETER_STRING: case LQT_PARAMETER_STRINGLIST: if(parameter_info[i].val_default.val_string) free(parameter_info[i].val_default.val_string); parameter_info[i].val_default.val_string = __lqt_strdup(val->val_string); break; case LQT_PARAMETER_SECTION: break; } lqt_registry_unlock(); return; }/* * I don't want to depend on one of the 1000s of MIN MAX macros out * there */#define __LQT_MIN(a, b) ((a<b)?a:b)/* * Load the module and restore default parameters. * Parameters are only stored in the return value, * NOT in the registry */void lqt_restore_default_parameters(lqt_codec_info_t * codec_info, int encode, int decode) { lqt_codec_info_t * info_from_module; lqt_codec_info_static_t * (*get_codec_info)(int); void * module; int i, imax; module = dlopen(codec_info->module_filename, RTLD_NOW); if(!module) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "lqt_restore_default_parameters: dlopen failed for %s: %s", codec_info->module_filename, dlerror()); return; } get_codec_info = (lqt_codec_info_static_t*(*)(int))(dlsym(module, "get_codec_info")); if(!get_codec_info) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Symbol %s not found in %s", "get_codec_info", codec_info->module_filename); return; } info_from_module = lqt_create_codec_info(get_codec_info(codec_info->module_index)); if(!info_from_module) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Couldn't get codec info for %s from_module %s", codec_info->long_name, codec_info->module_filename); return; } if(encode) { imax = __LQT_MIN(info_from_module->num_encoding_parameters, codec_info->num_encoding_parameters); for(i = 0; i < imax; i++) { /* Small check prevents evil bugs in ill conditioned applications */ if(!strcmp(codec_info->encoding_parameters[i].name, info_from_module->encoding_parameters[i].name)) { copy_parameter_value(&(codec_info->encoding_parameters[i].val_default), &(info_from_module->encoding_parameters[i].val_default), codec_info->encoding_parameters[i].type); } } } if(decode) { imax = __LQT_MIN(info_from_module->num_decoding_parameters, codec_info->num_decoding_parameters); for(i = 0; i < imax; i++) { if(!strcmp(codec_info->decoding_parameters[i].name, info_from_module->decoding_parameters[i].name)) { copy_parameter_value(&(codec_info->decoding_parameters[i].val_default), &(info_from_module->decoding_parameters[i].val_default), codec_info->decoding_parameters[i].type); } } } if(module) dlclose(module); if(info_from_module) destroy_codec_info(info_from_module); }/* * Sort audio and video codecs *//* * This is the actual sort function: It takes the original chained list * of the codecs and a string containing a comma separated list of the * codecs as arguments. It returns the newly sorted list. * * This string will also be saved in the codec file. */static lqt_codec_info_t *sort_codecs_internal(lqt_codec_info_t * original, char * names) { char * pos; char * end_pos; int len; lqt_codec_info_t * before; lqt_codec_info_t * ptr; lqt_codec_info_t * start = original; lqt_codec_info_t * ret = (lqt_codec_info_t*)0; lqt_codec_info_t * ret_end = (lqt_codec_info_t*)0; pos = names; end_pos = strchr(pos, ','); if(!end_pos) end_pos = pos + strlen(pos); while(1) { /* Seek the codec in the list */ ptr = start; before = ptr; len = end_pos - pos; while(ptr) { if(!strncmp(pos, ptr->name, len)) /* Found the codec */ break; before = ptr; ptr = ptr->next; } if(ptr) { /* Remove codec from the list */ if(ptr == start) start = start->next; else before->next = ptr->next; ptr->next = (lqt_codec_info_t*)0; /* Append it to the returned list */ if(!ret) { ret = ptr; ret_end = ret; } else { ret_end->next = ptr; ret_end = ret_end->next; } } /* Get the next codec name */ pos = end_pos; if(*pos == '\0') break; pos++; end_pos = strchr(pos, ','); if(!end_pos) end_pos = pos + strlen(pos); } /* Append the rest of the list */ if(start) ret_end->next = start; return ret; }static char * create_seek_string(lqt_codec_info_t ** info) { int i; int num_codecs = 0; int string_length = 0; char * ret; while(info[num_codecs]) { string_length += strlen(info[num_codecs]->name) + 1; num_codecs++; } ret = malloc(string_length); *ret = '\0'; for(i = 0; i < num_codecs; i++) { strcat(ret, info[i]->name); if(i != num_codecs - 1) strcat(ret, ","); } return ret; }void lqt_reorder_audio_codecs(lqt_codec_info_t ** info) { char * seek_string = create_seek_string(info); lqt_registry_lock(); lqt_audio_codecs = sort_codecs_internal(lqt_audio_codecs, seek_string); lqt_registry_unlock(); free(seek_string); }void lqt_reorder_video_codecs(lqt_codec_info_t ** info) { char * seek_string = create_seek_string(info); lqt_registry_lock(); lqt_video_codecs = sort_codecs_internal(lqt_video_codecs, seek_string); lqt_registry_unlock(); free(seek_string); }/*************************************************************** * This will hopefully make the destruction for dynamic loading * (Trick comes from a 1995 version of the ELF Howto, so it * should work everywhere now) ***************************************************************/#if defined(__GNUC__)static void __lqt_cleanup_codecinfo() __attribute__ ((destructor));static void __lqt_cleanup_codecinfo() { lqt_registry_destroy(); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -