📄 lqt_codecinfo.c
字号:
/******************************************************************************* lqt_codecinfo.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "lqt_codecinfo_private.h"#define LQT_LIBQUICKTIME#include <quicktime/lqt_codecapi.h>#include <sys/stat.h>#include <pthread.h>#include <dlfcn.h>#include <dirent.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <limits.h>#include <libintl.h>#define LOG_DOMAIN "codecinfo"/* Public function (lqt.h) */int lqt_get_codec_api_version() { return LQT_CODEC_API_VERSION; }/* Forward declaration */static lqt_codec_info_t *sort_codecs_internal(lqt_codec_info_t * original, char * names);/* * Quick and dirty strdup function for the case it's not there */static char * __lqt_strdup(const char * string) { char * ret = malloc(strlen(string)+1); strcpy(ret, string); return ret; }static char * __lqt_fourccdup(const char * fourcc) { char * ret = malloc(5); memcpy(ret, fourcc, 5); return ret; };/* * Codec Registry */int lqt_num_audio_codecs = 0;int lqt_num_video_codecs = 0;lqt_codec_info_t * lqt_audio_codecs = (lqt_codec_info_t*)0;lqt_codec_info_t * lqt_video_codecs = (lqt_codec_info_t*)0;static int registry_init_done = 0;pthread_mutex_t codecs_mutex = PTHREAD_MUTEX_INITIALIZER;/* * Lock and unlock the codec registry */void lqt_registry_lock() { pthread_mutex_lock(&codecs_mutex); }void lqt_registry_unlock() { pthread_mutex_unlock(&codecs_mutex); }/* Free memory of parameter info */static void destroy_parameter_info(lqt_parameter_info_t * p) { int i; if(p->name) free(p->name); if(p->real_name) free(p->real_name); if(p->help_string) free(p->help_string); switch(p->type) { case LQT_PARAMETER_STRING: if(p->val_default.val_string) free(p->val_default.val_string); break; case LQT_PARAMETER_STRINGLIST: if(p->val_default.val_string) free(p->val_default.val_string); if(p->stringlist_options) { for(i = 0; i < p->num_stringlist_options; i++) free(p->stringlist_options[i]); free(p->stringlist_options); } if(p->stringlist_labels) { for(i = 0; i < p->num_stringlist_options; i++) free(p->stringlist_labels[i]); free(p->stringlist_labels); } break; default: /* Keep gcc quiet */ break; } }/* Free memory of codec info (public) */static void destroy_codec_info(lqt_codec_info_t * ptr) { int i; if(ptr->fourccs) { for(i = 0; i < ptr->num_fourccs; i++) free(ptr->fourccs[i]); free(ptr->fourccs); } if(ptr->wav_ids) free(ptr->wav_ids); if(ptr->name) free(ptr->name); /* Name of the codec */ if(ptr->long_name) /* Long name of the codec */ free(ptr->long_name); if(ptr->description) /* Long name of the codec */ free(ptr->description); if(ptr->module_filename) /* Module filename */ free(ptr->module_filename); if(ptr->gettext_domain) free(ptr->gettext_domain); if(ptr->gettext_directory) free(ptr->gettext_directory); if(ptr->encoding_parameters) { for(i = 0; i < ptr->num_encoding_parameters; i++) destroy_parameter_info(&(ptr->encoding_parameters[i])); free(ptr->encoding_parameters); } if(ptr->decoding_parameters) { for(i = 0; i < ptr->num_decoding_parameters; i++) destroy_parameter_info(&(ptr->decoding_parameters[i])); free(ptr->decoding_parameters); } free(ptr); }static void copy_parameter_value(lqt_parameter_value_t * dst, const lqt_parameter_value_t * src, lqt_parameter_type_t type) { switch(type) { case LQT_PARAMETER_INT: dst->val_int = src->val_int; break; case LQT_PARAMETER_FLOAT: dst->val_float = src->val_float; break; case LQT_PARAMETER_STRING: case LQT_PARAMETER_STRINGLIST: /* String with options */ if(dst->val_string) free(dst->val_string); if(src->val_string) dst->val_string = __lqt_strdup(src->val_string); else dst->val_string = (char*)0; break; case LQT_PARAMETER_SECTION: break; } }static voidcopy_parameter_info(lqt_parameter_info_t * ret, const lqt_parameter_info_t * info, const char * gettext_domain) { int i; if(info->name) ret->name = __lqt_strdup(info->name); if(info->real_name) ret->real_name = __lqt_strdup(dgettext(gettext_domain, info->real_name)); if(info->help_string) ret->help_string = __lqt_strdup(dgettext(gettext_domain, info->help_string)); ret->type = info->type; switch(ret->type) { case LQT_PARAMETER_INT: ret->val_min.val_int = info->val_min.val_int; ret->val_max.val_int = info->val_max.val_int; break; case LQT_PARAMETER_FLOAT: ret->val_min.val_float = info->val_min.val_float; ret->val_max.val_float = info->val_max.val_float; ret->num_digits = info->num_digits; break; case LQT_PARAMETER_STRING: break; case LQT_PARAMETER_STRINGLIST: /* String with options */ ret->num_stringlist_options = info->num_stringlist_options; ret->stringlist_options = calloc(ret->num_stringlist_options, sizeof(char*)); ret->stringlist_labels = calloc(ret->num_stringlist_options, sizeof(char*)); for(i = 0; i < ret->num_stringlist_options; i++) { ret->stringlist_options[i] = __lqt_strdup(info->stringlist_options[i]); ret->stringlist_labels[i] = __lqt_strdup(dgettext(gettext_domain, info->stringlist_labels[i])); } break; case LQT_PARAMETER_SECTION: /* String with options */ break; } copy_parameter_value(&(ret->val_default), &(info->val_default), info->type); }/* * Copy codec Info */static lqt_codec_info_t *copy_codec_info(const lqt_codec_info_t * info) { int i; const char * gettext_domain; lqt_codec_info_t * ret = calloc(1, sizeof(lqt_codec_info_t)); if(info->gettext_domain && info->gettext_directory) { bindtextdomain(info->gettext_domain, info->gettext_directory); gettext_domain = info->gettext_domain; } else { lqt_translation_init(); gettext_domain = PACKAGE; } ret->compatibility_flags = info->compatibility_flags; if(info->name) ret->name = __lqt_strdup(info->name); if(info->long_name) ret->long_name = __lqt_strdup(info->long_name); if(info->description) ret->description = __lqt_strdup(info->description); if(info->module_filename) ret->module_filename = __lqt_strdup(info->module_filename); ret->module_index = info->module_index; ret->type = info->type; ret->direction = info->direction; ret->num_fourccs = info->num_fourccs; if(ret->num_fourccs) { ret->fourccs = malloc(ret->num_fourccs * sizeof(char*)); for(i = 0; i < ret->num_fourccs; i++) ret->fourccs[i] = __lqt_fourccdup(info->fourccs[i]); } ret->num_wav_ids = info->num_wav_ids; if(ret->num_wav_ids) { ret->wav_ids = malloc(ret->num_wav_ids * sizeof(int)); for(i = 0; i < ret->num_wav_ids; i++) ret->wav_ids[i] = info->wav_ids[i]; } ret->num_encoding_parameters = info->num_encoding_parameters; if(ret->num_encoding_parameters) { ret->encoding_parameters = calloc(ret->num_encoding_parameters+1, sizeof(lqt_parameter_info_t)); for(i = 0; i < ret->num_encoding_parameters; i++) copy_parameter_info(&(ret->encoding_parameters[i]), &(info->encoding_parameters[i]), gettext_domain); } ret->num_decoding_parameters = info->num_decoding_parameters; if(ret->num_decoding_parameters) { ret->decoding_parameters = calloc(ret->num_decoding_parameters, sizeof(lqt_parameter_info_t)); for(i = 0; i < ret->num_decoding_parameters; i++) copy_parameter_info(&(ret->decoding_parameters[i]), &(info->decoding_parameters[i]), gettext_domain); } return ret; }/* * Seek a codec in the database */static lqt_codec_info_t * find_codec_by_filename(lqt_codec_info_t ** list, const char * filename, uint32_t time) { lqt_codec_info_t * new_list = (lqt_codec_info_t*)0; lqt_codec_info_t * new_list_end = (lqt_codec_info_t*)0; lqt_codec_info_t * ret = (lqt_codec_info_t*)0; lqt_codec_info_t * ret_end = (lqt_codec_info_t*)0; lqt_codec_info_t * tmp_ptr; lqt_codec_info_t * ptr = *list; if(!ptr) return (lqt_codec_info_t*)0; while(ptr) { if(!strcmp(ptr->module_filename, filename)) { /* * File is there, but newer than our database entry * -> Remove from the list */ if(ptr->file_time < time) { tmp_ptr = ptr->next; destroy_codec_info(ptr); ptr = tmp_ptr; } else { if(ret) { ret_end->next = ptr; ret_end = ret_end->next; } else { ret = ptr; ret_end = ptr; } ptr = ptr->next; } } else /* Not our file, return to database */ { if(new_list) { new_list_end->next = ptr; new_list_end = new_list_end->next; } else { new_list = ptr; new_list_end = ptr; } ptr = ptr->next; } } /* Prepare for returning */ if(new_list) { new_list_end->next = (lqt_codec_info_t*)0; } *list = new_list; if(ret_end) ret_end->next = (lqt_codec_info_t*)0; return ret; }static lqt_codec_info_t * load_codec_info_from_plugin(char * plugin_filename, uint32_t time) { void * module; lqt_codec_info_t * ret_end; int i; int num_codecs; int codec_api_version_module; int codec_api_version_us = lqt_get_codec_api_version(); int (*get_num_codecs)(); int (*get_codec_api_version)(); lqt_codec_info_static_t * (*get_codec_info)(int); lqt_codec_info_t * ret = (lqt_codec_info_t*)0; module = dlopen(plugin_filename, RTLD_NOW); if(!module) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "dlopen failed for %s: %s", plugin_filename, dlerror()); return ret; } /* Now, get the codec parameters */ /* Check the api version */ get_codec_api_version = (int (*)())(dlsym(module, "get_codec_api_version")); if(!get_codec_api_version) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Module %s has no API version and is thus terribly old", plugin_filename); dlclose(module); return ret; } codec_api_version_module = get_codec_api_version(); if(codec_api_version_module != codec_api_version_us) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Codec interface version mismatch of module %s: %d [module] != %d [lqt]", plugin_filename, codec_api_version_module, codec_api_version_us); dlclose(module); return ret; } get_num_codecs = (int (*)())(dlsym(module, "get_num_codecs")); if(!get_num_codecs) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "Symbol get_num_codecs not found in %s", plugin_filename); dlclose(module); return ret; } 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 get_codec_info not found in %s", plugin_filename); dlclose(module); return ret; } /* Now, create the structure */ num_codecs = get_num_codecs(); if(!num_codecs) { lqt_log(NULL, LQT_LOG_ERROR, LOG_DOMAIN, "No codecs found in %s", plugin_filename); dlclose(module); return ret; } ret = lqt_create_codec_info(get_codec_info(0)); /* Complete the structure */ ret_end = ret; ret_end->module_index = 0; /* Filename of the module */ ret_end->module_filename = __lqt_strdup(plugin_filename); ret_end->file_time = time; /* File modification time */ for(i = 1; i < num_codecs; i++) { ret_end->next = lqt_create_codec_info(get_codec_info(i)); ret_end = ret_end->next; ret_end->module_index = i; /* Filename of the module */ ret_end->module_filename = __lqt_strdup(plugin_filename); /* File modification time */ ret_end->file_time = time; } ret_end->next = (lqt_codec_info_t*)0; dlclose(module); return ret; }/* * Register all codecs found in list */static void register_codecs(lqt_codec_info_t * list, lqt_codec_info_t ** audio_codecs_end, lqt_codec_info_t ** video_codecs_end) { lqt_codec_info_t * tmp_ptr; while(list) { if(list->type == LQT_CODEC_AUDIO) { if(*audio_codecs_end) { (*audio_codecs_end)->next = list; *audio_codecs_end = (*audio_codecs_end)->next; } else { lqt_audio_codecs = list; (*audio_codecs_end) = lqt_audio_codecs; } lqt_num_audio_codecs++; } if(list->type == LQT_CODEC_VIDEO) { if((*video_codecs_end)) { (*video_codecs_end)->next = list; (*video_codecs_end) = (*video_codecs_end)->next; } else { lqt_video_codecs = list; (*video_codecs_end) = lqt_video_codecs; } lqt_num_video_codecs++; } tmp_ptr = list; list = list->next; tmp_ptr->next = (lqt_codec_info_t*)0; } }static int scan_for_plugins(const char * plugin_dir, lqt_codec_info_t ** database) { char * pos; int ret; char * filename; DIR * directory; struct dirent * directory_entry; struct stat status; lqt_codec_info_t * codecs; lqt_codec_info_t * video_codecs_end; lqt_codec_info_t * audio_codecs_end; filename = malloc(PATH_MAX * sizeof(char));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -