// Pour commencer on fait ceci: // Usage: testf0r [options] // // Un jour on aura ca: // Usage: testf0r [options] [args] // // Subcommands: // help [SUBCOMMAND...] // create [options] // run [options] // info // #include "frei0r.h" #include #include #include #include #include #include #include #include #include #define N_COMMANDLINE_REQUIRED_HELP 1 #define N_COMMANDLINE_REQUIRED_CREATE 5 #define N_COMMANDLINE_REQUIRED_RUN 2 #define N_COMMANDLINE_REQUIRED_INFO 1 #define MAX_N_COMMANDLINE_ARGUMENTS 64 #define BUFFER_SIZE 1024 using namespace std; void printHelp(const string subcommand = ""); void error(const string& errormsg); void assertError(bool assert, const string& errormsg = ""); //void assertHelp(bool assert, const string subcommand = "") { assertError(assert, "", true, subcommand); } const string nextString(int& idx, int argc, char **argv); int nextInt(int& idx, int argc, char **argv, bool *is_int = 0); double nextDouble(int& idx, int argc, char **argv, bool *is_double = 0); void readFrame(uint32_t *inframe, const string& filename, const string& format, int width, int height); void writeFrame(const uint32_t *outframe, const string& filename, const string& format, int width, int height); void printInfo(f0r_plugin_info_t plugin_info, const vector& param_infos); void writeTestFile(int width, int height, const string& outfile, int opt_argc, char **opt_argv, const string& testfile); void readTestFile(int& width, int& height, string& outfile, int& opt_argc, char**& opt_argv, const string& testfile); int main(int argc, char **argv) { // Arguments from the commandline. vector param_infos; map param_infos_map; string libfile, outfile, testfile; string outrunfile = ""; // Arguments for the call. f0r_instance_t instance; f0r_plugin_info_t plugin_info; int width = 0; int height = 0; double time = 0.0; uint32_t *inframe1; uint32_t *inframe2; uint32_t *inframe3; uint32_t *outframe; string infile1, infile2, infile3; string file_format = "JPEG"; // Used in the validation process (nextInt(), nextDouble() calls). bool type_ok; // If true, f0r_update2 does exists (and thus has to be used). bool update2_exists; // Handle on the .so plugin. void *handle = 0; // Interface function pointers. int (*f0r_init)(); void (*f0r_get_plugin_info)(f0r_plugin_info_t* pluginInfo); void (*f0r_get_param_info)(f0r_param_info_t* info, int param_index); f0r_instance_t (*f0r_construct)(unsigned int width, unsigned int height); void (*f0r_destruct)(f0r_instance_t instance); void (*f0r_set_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index); void (*f0r_get_param_value)(f0r_instance_t instance, f0r_param_t param, int param_index); void (*f0r_update)(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe); void (*f0r_update2)(f0r_instance_t instance, double time, const uint32_t* inframe1, const uint32_t* inframe2, const uint32_t* inframe3, uint32_t* outframe); // Main switch (subcommand) ////////////////////////////////////////////////////////////////////////// assertError(argc > 1, "Too few argument."); int arg = 1; const string subcommand = nextString(arg, argc, argv); // Subcommand : help ///////////////////////////////////////////////////////////////////////////////// if (subcommand == "help") { if (arg == argc) // finished (just asking for general help) printHelp(); else // needs help on a specific subcommand printHelp(nextString(arg, argc, argv)); } // Subcommand : info ///////////////////////////////////////////////////////////////////////////////// else if (subcommand == "info") { // Read required. libfile = nextString(arg, argc, argv); // Create dynamic handle to the library file. handle = dlopen(libfile.c_str(), RTLD_LAZY); assertError(handle); // Get interface function pointers *(void**) (&f0r_init) = dlsym(handle, "f0r_init"); *(void**) (&f0r_get_plugin_info) = dlsym(handle, "f0r_get_plugin_info"); *(void**) (&f0r_get_param_info) = dlsym(handle, "f0r_get_param_info"); // Get infos. (*f0r_get_plugin_info)(&plugin_info); // Get the list of params. param_infos.resize(plugin_info.num_params); for (int i=0; i= 0); // Read required. arg = n_option_args + 2; width = nextInt(arg, argc, argv, &type_ok); assertError(type_ok); height = nextInt(arg, argc, argv, &type_ok); assertError(type_ok); libfile = nextString(arg, argc, argv); testfile = nextString(arg, argc, argv); outfile = nextString(arg, argc, argv); // Set option count/pointer. opt_argc = n_option_args; opt_argv = argv + 2; // Save options to test file. writeTestFile(width, height, outfile, opt_argc, opt_argv, testfile); } else // subcommand == "run" { // Number of arguments that are options (i.e. non required). int n_option_args = argc - N_COMMANDLINE_REQUIRED_RUN - 2; assertError(n_option_args >= 0); // Read options arg = 2; if (n_option_args > 0) { const string option_name = nextString(arg, argc, argv); if (option_name == "-o") outrunfile = nextString(arg, argc, argv); else error("Unknown option: " + option_name); } // Read required. libfile = nextString(arg, argc, argv); testfile = nextString(arg, argc, argv); // Read test file options. opt_argv = (char**)malloc(MAX_N_COMMANDLINE_ARGUMENTS*sizeof(char*)); for (int i=0; i::const_iterator it = param_infos_map.find(param_name); assert (it != param_infos_map.end()); // not found param_index = it->second; } // We've got the info. param_info = param_infos[param_index]; // Set parameter. switch (param_info.type) { case F0R_PARAM_BOOL: { double value = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); (*f0r_set_param_value)(instance, new f0r_param_bool(value), param_index); } break; case F0R_PARAM_DOUBLE: { double value = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); (*f0r_set_param_value)(instance, new f0r_param_double(value), param_index); } break; case F0R_PARAM_COLOR: { f0r_param_color *color = new f0r_param_color; color->r = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); color->g = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); color->b = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); (*f0r_set_param_value)(instance, color, param_index); } break; case F0R_PARAM_POSITION: { f0r_param_position *position = new f0r_param_position; position->x = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); position->y = nextDouble(arg, opt_argc, opt_argv, &type_ok); assertError(type_ok); (*f0r_set_param_value)(instance, position, param_index); } break; default: error("Unrecognized info type."); } } // Input file. else if (option_name == "-i1") infile1 = nextString(arg, opt_argc, opt_argv); else if (option_name == "-i2") infile2 = nextString(arg, opt_argc, opt_argv); else if (option_name == "-i3") infile3 = nextString(arg, opt_argc, opt_argv); else if (option_name == "-format") file_format = nextString(arg, opt_argc, opt_argv); else error("Unknown option: " + option_name + "."); } // Read input frames. if (!infile1.empty()) readFrame(inframe1, infile1, file_format, width, height); if (!infile2.empty()) readFrame(inframe2, infile2, file_format, width, height); if (!infile3.empty()) readFrame(inframe3, infile3, file_format, width, height); // Perform update. if (update2_exists) (*f0r_update2)(instance, time, inframe1, inframe2, inframe3, outframe); else (*f0r_update)(instance, time, inframe1, outframe); if (subcommand == "create") { // Write output to file. writeFrame(outframe, outfile, file_format, width, height); } else // subcommand == "run" { // Compare output with that from file. uint32_t *testframe = (uint32_t*)malloc(width*height*sizeof(uint32_t)); readFrame(testframe, outfile, file_format, width, height); // Compare frames pixel by pixel. double sum = 0.0; for (int i=0; i]" << endl; cout << " Displays a help notice." << endl; printSubCommands(); } else if (subcommand == "create") { cout << prefix << "create [options] " << endl; cout << " Creates a new test." << endl; cout << " Options: " << endl; cout << " -p (|) Sets a boolean or a double param to some value." << endl; cout << " -p (|) Sets a color param to some value." << endl; cout << " -p (|) Sets a position param to some value." << endl; cout << " -i1,-i2,-i3 Loads input 1, 2 or 3 from a file." << endl; cout << " -format Sets the image format of the input/output files." << endl; } else if (subcommand == "run") { cout << prefix << "run [options] " << endl; cout << " Performs a previously created test." << endl; cout << " Options: " << endl; cout << " -o Generates an output image." << endl; } else if (subcommand == "info") { cout << prefix << "info " << endl; cout << " Displays informations about a plugin." << endl; } else { cout << prefix << " [options] [args]" << endl; printSubCommands(); } } const string nextString(int& idx, int argc, char **argv) { assertError(0 <= idx && idx < argc, "Parsing error."); return argv[idx++]; } int nextInt(int& idx, int argc, char **argv, bool *is_int) { assertError(0 <= idx && idx < argc, "Parsing error."); char *endptr; // char *endptr = (char*)malloc(BUFFER_SIZE*sizeof(char)); int k = (int)strtol(argv[idx], &endptr, 10); if (is_int) { if (argv[idx][0] != '\0' && endptr[0] != '\0') *is_int = false; else { *is_int = true; idx++; } } else // we don't care idx++; return k; } double nextDouble(int& idx, int argc, char **argv, bool *is_double) { assertError(0 <= idx && idx < argc, "Parsing error."); // char *endptr = (char*)malloc(BUFFER_SIZE*sizeof(char)); char *endptr; double k = (double)strtod(argv[idx], &endptr); if (is_double) { if (argv[idx][0] != '\0' && endptr[0] != '\0') *is_double = false; else { *is_double = true; idx++; } } else // we don't care idx++; return k; } void printInfo(f0r_plugin_info_t plugin_info, const vector& param_infos) { // cout << "# Plugin info ############" << endl; cout << "Name : " << plugin_info.name << endl; cout << "Author : " << plugin_info.author << endl; cout << plugin_info.explanation << endl; cout << "Parameters [" << plugin_info.num_params << " total]" << endl; for (int i=0; i> width; f >> height; f >> outfile; f >> opt_argc; string tmp; for (int i=0; i> tmp; strcpy(opt_argv[i], tmp.c_str()); } }