Remove boost library to parse input args. use a simple struct based approach

This commit is contained in:
jfmcarreira committed 2015-03-20 19:32:09 +00:00
1 parent 0ab7ab29ca
commit 011856bbe2
10 files changed
+1019 -126

No files matched your search

-4
View File
@@ -82,10 +82,6 @@ SET( CMAKE_CXX_FLAGS "" )
# Dependencies
######################################################################################
FIND_PACKAGE(Boost COMPONENTS program_options )
SET_PACKAGE_PROPERTIES(Boost PROPERTIES URL "http://www.boost.org" DESCRIPTION "Boost library support" TYPE REQUIRED)
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
OPTION( USE_OPENCV "Add OpenCV support" ON )
IF( USE_OPENCV )
FIND_PACKAGE( OpenCV )
+2 -1
View File
@@ -11,8 +11,9 @@ set(plaYUver_Lib_SRCS
PlaYUVerFrameStats.cpp
# Stream
PlaYUVerStream.cpp
# Command Line Parser
# Command Parser
PlaYUVerCmdParser.cpp
ProgramOptions.cpp
)
IF( USE_FFMPEG )
+32 -46
View File
@@ -28,6 +28,7 @@
#include <string>
#include <vector>
#include "PlaYUVerCmdParser.h"
#include "ProgramOptions.h"
#include "PlaYUVerFrame.h"
namespace plaYUVer
@@ -35,9 +36,14 @@ namespace plaYUVer
PlaYUVerCmdParser::PlaYUVerCmdParser()
{
m_iArgc = 0;
m_apcArgv = NULL;
m_ParserOptions.add( GetCommandOpts() );
Opts().addOptions()/**/
( "help", "produce help message" )/**/
( "version", "show version and exit" )/**/
( "pel_fmts", "list pixel formats" ) /**/
( "quality_metrics", "list supported quality metrics" )/**/
( "module_list", "list supported modules" ) /**/
( "module_list_full", "detailed list supported modules" );
}
PlaYUVerCmdParser::~PlaYUVerCmdParser()
@@ -45,57 +51,23 @@ PlaYUVerCmdParser::~PlaYUVerCmdParser()
}
Void PlaYUVerCmdParser::Config( Int argc, Char *argv[] )
Options& PlaYUVerCmdParser::Opts()
{
m_iArgc = argc;
m_apcArgv = argv;
return m_cParserOptions;
}
po::options_description PlaYUVerCmdParser::GetCommandOpts()
{
po::options_description inputOpts( "InputOutput" );
inputOpts.add_options()/**/
( "input,i", po::value<std::vector<std::string> >(), "input file" ) /**/
( "output,o", po::value<std::vector<std::string> >(), "output file" ) /**/
( "size,s", po::value<std::string>(), "size (WxH)" ) /**/
( "pel_fmt", po::value<std::string>(), "pixel format" ) /**/
( "pel_fmts", "list pixel formats" ) /**/
( "frames,f", po::value<UInt>(), "number of frames" );
po::options_description commonOpts( "Common" );
commonOpts.add_options()/**/
( "quiet,q", "disable verbose" )/**/
( "help", "produce help message" )/**/
( "version", "show version and exit" );
commonOpts.add( inputOpts );
return commonOpts;
}
Void PlaYUVerCmdParser::addOptions( po::options_description opts )
{
m_ParserOptions.add( opts );
}
Bool PlaYUVerCmdParser::parse()
Bool PlaYUVerCmdParser::parse( Int argc, Char *argv[] )
{
try
{
po::store( po::command_line_parser( m_iArgc, m_apcArgv ).options( m_ParserOptions ).allow_unregistered().run(), m_cOptionsMap );
po::notify( m_cOptionsMap );
// m_cParserOptions.setDefaults();
const std::list<const Char*>& argv_unhandled = scanArgv( m_cParserOptions, argc, ( const Char** )argv );
if( m_cOptionsMap.count( "help" ) )
for( std::list<const Char*>::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++ )
{
std::cout << m_ParserOptions
<< "\n";
return false;
}
if( m_cOptionsMap.count( "version" ) )
{
std::cout << "PlaYUVer version "
<< PLAYUVER_VERSION_STRING
<< "\n";
return false;
fprintf( stderr, "Unhandled argument ignored: `%s'\n", *it );
}
if( checkListingOpts() )
{
return false;
@@ -118,7 +90,21 @@ Bool PlaYUVerCmdParser::parse()
Bool PlaYUVerCmdParser::checkListingOpts()
{
Bool bRet = false;
if( m_cOptionsMap.count( "pel_fmts" ) )
if( m_cParserOptions["help"]->count() )
{
doHelp( std::cout, m_cParserOptions );
bRet |= true;
}
if( m_cParserOptions["version"]->count() )
{
std::cout << "PlaYUVer version "
<< PLAYUVER_VERSION_STRING
<< "\n";
bRet |= true;
}
if( m_cParserOptions["pel_fmts"]->count() )
{
printf( "PlaYUVer supported pixel formats: \n" );
for( UInt i = 0; i < PlaYUVerFrame::supportedPixelFormatListNames().size(); i++ )
+5 -17
View File
@@ -23,8 +23,8 @@
*/
#include "PlaYUVerDefs.h"
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include "ProgramOptions.h"
namespace plaYUVer
{
@@ -35,22 +35,10 @@ public:
PlaYUVerCmdParser();
~PlaYUVerCmdParser();
Void Config( Int argc, Char *argv[] );
Void addOptions( po::options_description );
Bool parse();
po::variables_map getOptionsMap()
{
return m_cOptionsMap;
}
static po::options_description GetCommandOpts();
Bool parse( Int argc, Char *argv[] );
Options& Opts();
private:
Int m_iArgc;
Char** m_apcArgv;
po::options_description m_ParserOptions;
po::variables_map m_cOptionsMap;
Options m_cParserOptions;
Bool checkListingOpts();
};
+550
View File
@@ -0,0 +1,550 @@
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2014, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file ProgramOptions.cpp
* \brief Input args handler
*/
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <map>
#include <algorithm>
#include "ProgramOptions.h"
using namespace std;
namespace plaYUVer
{
Options::~Options()
{
for( Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); it++ )
{
delete *it;
}
}
OptionBase* Options::operator[]( const std::string& optName )
{
return getOption( optName );
}
OptionBase* Options::getOption( const std::string& optName )
{
Options::NamesMap::iterator opt_it;
opt_it = opt_short_map.find( optName );
if( opt_it != opt_short_map.end() )
{
NamesPtrList opt_list = ( *opt_it ).second;
for( Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it )
{
return ( *it )->opt;
}
}
opt_it = opt_long_map.find( optName );
if( opt_it != opt_long_map.end() )
{
NamesPtrList opt_list = ( *opt_it ).second;
for( Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it )
{
return ( *it )->opt;
}
}
return NULL;
}
void Options::addOption( OptionBase *opt )
{
Names* names = new Names();
names->opt = opt;
string& opt_string = opt->opt_string;
size_t opt_start = 0;
for( size_t opt_end = 0; opt_end != string::npos; )
{
opt_end = opt_string.find_first_of( ',', opt_start );
bool force_short = 0;
if( opt_string[opt_start] == '-' )
{
opt_start++;
force_short = 1;
}
string opt_name = opt_string.substr( opt_start, opt_end - opt_start );
if( force_short || opt_name.size() == 1 )
{
names->opt_short.push_back( opt_name );
opt_short_map[opt_name].push_back( names );
}
else
{
names->opt_long.push_back( opt_name );
opt_long_map[opt_name].push_back( names );
}
opt_start += opt_end + 1;
}
opt_list.push_back( names );
}
/* Helper method to initiate adding options to Options */
OptionSpecific Options::addOptions()
{
return OptionSpecific( *this );
}
/* for all options in opts, set their storage to their specified
* default value */
Void Options::setDefaults()
{
// for( Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); it++ )
// {
// ( *it )->opt->setDefault();
// }
}
static void setOptions( Options::NamesPtrList& opt_list, const string& value )
{
/* multiple options may be registered for the same name:
* allow each to parse value */
for( Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it )
{
( *it )->opt->parse( value );
}
}
static const char spaces[41] = " ";
/* format help text for a single option:
* using the formatting: "-x, --long",
* if a short/long option isn't specified, it is not printed
*/
static void doHelpOpt( ostream& out, const Options::Names& entry, unsigned pad_short = 0 )
{
pad_short = min( pad_short, 8u );
if( !entry.opt_short.empty() )
{
unsigned pad = max( ( int )pad_short - ( int )entry.opt_short.front().size(), 0 );
out << "-"
<< entry.opt_short.front();
if( !entry.opt_long.empty() )
{
out << ", ";
}
out << &( spaces[40 - pad] );
}
else
{
out << " ";
out << &( spaces[40 - pad_short] );
}
if( !entry.opt_long.empty() )
{
out << "--"
<< entry.opt_long.front();
}
}
/* format the help text */
void doHelp( ostream& out, Options& opts, unsigned columns )
{
const unsigned pad_short = 3;
/* first pass: work out the longest option name */
unsigned max_width = 0;
for( Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++ )
{
ostringstream line( ios_base::out );
doHelpOpt( line, **it, pad_short );
max_width = max( max_width, ( unsigned )line.tellp() );
}
unsigned opt_width = min( max_width + 2, 28u + pad_short ) + 2;
unsigned desc_width = columns - opt_width;
/* second pass: write out formatted option and help text.
* - align start of help text to start at opt_width
* - if the option text is longer than opt_width, place the help
* text at opt_width on the next line.
*/
for( Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++ )
{
ostringstream line( ios_base::out );
line << " ";
doHelpOpt( line, **it, pad_short );
const string& opt_desc = ( *it )->opt->opt_desc;
if( opt_desc.empty() )
{
/* no help text: output option, skip further processing */
cout << line.str()
<< endl;
continue;
}
size_t currlength = size_t( line.tellp() );
if( currlength > opt_width )
{
/* if option text is too long (and would collide with the
* help text, split onto next line */
line << endl;
currlength = 0;
}
/* split up the help text, taking into account new lines,
* (add opt_width of padding to each new line) */
for( size_t newline_pos = 0, cur_pos = 0; cur_pos != string::npos; currlength = 0 )
{
/* print any required padding space for vertical alignment */
line << &( spaces[40 - opt_width + currlength] );
newline_pos = opt_desc.find_first_of( '\n', newline_pos );
if( newline_pos != string::npos )
{
/* newline found, print substring (newline needn't be stripped) */
newline_pos++;
line << opt_desc.substr( cur_pos, newline_pos - cur_pos );
cur_pos = newline_pos;
continue;
}
if( cur_pos + desc_width > opt_desc.size() )
{
/* no need to wrap text, remainder is less than avaliable width */
line << opt_desc.substr( cur_pos );
break;
}
/* find a suitable point to split text (avoid spliting in middle of word) */
size_t split_pos = opt_desc.find_last_of( ' ', cur_pos + desc_width );
if( split_pos != string::npos )
{
/* eat up multiple space characters */
split_pos = opt_desc.find_last_not_of( ' ', split_pos ) + 1;
}
/* bad split if no suitable space to split at. fall back to width */
bool bad_split = split_pos == string::npos || split_pos <= cur_pos;
if( bad_split )
{
split_pos = cur_pos + desc_width;
}
line << opt_desc.substr( cur_pos, split_pos - cur_pos );
/* eat up any space for the start of the next line */
if( !bad_split )
{
split_pos = opt_desc.find_first_not_of( ' ', split_pos );
}
cur_pos = newline_pos = split_pos;
if( cur_pos >= opt_desc.size() )
{
break;
}
line << endl;
}
cout << line.str()
<< endl;
}
}
bool storePair( Options& opts, bool allow_long, bool allow_short, const string& name, const string& value )
{
bool found = false;
Options::NamesMap::iterator opt_it;
if( allow_long )
{
opt_it = opts.opt_long_map.find( name );
if( opt_it != opts.opt_long_map.end() )
{
found = true;
}
}
/* check for the short list */
if( allow_short && !( found && allow_long ) )
{
opt_it = opts.opt_short_map.find( name );
if( opt_it != opts.opt_short_map.end() )
{
found = true;
}
}
if( !found )
{
/* not found */
cerr << "Unknown option: `"
<< name
<< "' (value:`"
<< value
<< "')"
<< endl;
return false;
}
setOptions( ( *opt_it ).second, value );
return true;
}
bool storePair( Options& opts, const string& name, const string& value )
{
return storePair( opts, true, true, name, value );
}
/**
* returns number of extra arguments consumed
*/
unsigned parseGNU( Options& opts, unsigned argc, const char* argv[] )
{
/* gnu style long options can take the forms:
* --option=arg
* --option arg
*/
string arg( argv[0] );
size_t arg_opt_start = arg.find_first_not_of( '-' );
size_t arg_opt_sep = arg.find_first_of( '=' );
string option = arg.substr( arg_opt_start, arg_opt_sep - arg_opt_start );
unsigned extra_argc_consumed = 0;
if( arg_opt_sep == string::npos )
{
/* no argument found => argument in argv[1] (maybe) */
/* xxx, need to handle case where option isn't required */
#if 0
/* commented out, to return to true GNU style processing
* where longopts have to include an =, otherwise they are
* booleans */
if (argc == 1)
return 0; /* run out of argv for argument */
extra_argc_consumed = 1;
#endif
if( !storePair( opts, true, false, option, "1" ) )
{
return 0;
}
}
else
{
/* argument occurs after option_sep */
string val = arg.substr( arg_opt_sep + 1 );
storePair( opts, true, false, option, val );
}
return extra_argc_consumed;
}
unsigned parseSHORT( Options& opts, unsigned argc, const char* argv[] )
{
/* short options can take the forms:
* --option arg
* -option arg
*/
string arg( argv[0] );
size_t arg_opt_start = arg.find_first_not_of( '-' );
string option = arg.substr( arg_opt_start );
/* lookup option */
/* argument in argv[1] */
/* xxx, need to handle case where option isn't required */
if( argc == 1 )
{
cerr << "Not processing option without argument `"
<< option
<< "'"
<< endl;
return 0; /* run out of argv for argument */
}
storePair( opts, false, true, option, string( argv[1] ) );
return 1;
}
list<const char*> scanArgv( Options& opts, unsigned argc, const char* argv[] )
{
/* a list for anything that didn't get handled as an option */
list<const char*> non_option_arguments;
for( unsigned i = 1; i < argc; i++ )
{
if( argv[i][0] != '-' )
{
non_option_arguments.push_back( argv[i] );
continue;
}
if( argv[i][1] == 0 )
{
/* a lone single dash is an argument (usually signifying stdin) */
non_option_arguments.push_back( argv[i] );
continue;
}
if( argv[i][1] != '-' )
{
/* handle short (single dash) options */
#if 0
i += parsePOSIX(opts, argc - i, &argv[i]);
#else
i += parseSHORT( opts, argc - i, &argv[i] );
#endif
continue;
}
if( argv[i][2] == 0 )
{
/* a lone double dash ends option processing */
while( ++i < argc )
non_option_arguments.push_back( argv[i] );
break;
}
/* handle long (double dash) options */
i += parseGNU( opts, argc - i, &argv[i] );
}
return non_option_arguments;
}
void scanLine( Options& opts, string& line )
{
/* strip any leading whitespace */
size_t start = line.find_first_not_of( " \t\n\r" );
if( start == string::npos )
{
/* blank line */
return;
}
if( line[start] == '#' )
{
/* comment line */
return;
}
/* look for first whitespace or ':' after the option end */
size_t option_end = line.find_first_of( ": \t\n\r", start );
string option = line.substr( start, option_end - start );
/* look for ':', eat up any whitespace first */
start = line.find_first_not_of( " \t\n\r", option_end );
if( start == string::npos )
{
/* error: badly formatted line */
return;
}
if( line[start] != ':' )
{
/* error: badly formatted line */
return;
}
/* look for start of value string -- eat up any leading whitespace */
start = line.find_first_not_of( " \t\n\r", ++start );
if( start == string::npos )
{
/* error: badly formatted line */
return;
}
/* extract the value part, which may contain embedded spaces
* by searching for a word at a time, until we hit a comment or end of line */
size_t value_end = start;
do
{
if( line[value_end] == '#' )
{
/* rest of line is a comment */
value_end--;
break;
}
value_end = line.find_first_of( " \t\n\r", value_end );
/* consume any white space, incase there is another word.
* any trailing whitespace will be removed shortly */
value_end = line.find_first_not_of( " \t\n\r", value_end );
}
while( value_end != string::npos );
/* strip any trailing space from value*/
value_end = line.find_last_not_of( " \t\n\r", value_end );
string value;
if( value_end >= start )
{
value = line.substr( start, value_end + 1 - start );
}
else
{
/* error: no value */
return;
}
/* store the value in option */
storePair( opts, true, false, option, value );
}
void scanFile( Options& opts, istream& in )
{
do
{
string line;
getline( in, line );
scanLine( opts, line );
}
while( !!in );
}
/* for all options in opts, set their storage to their specified
* default value */
void setDefaults( Options& opts )
{
// for( Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++ )
// {
// ( *it )->opt->setDefault();
// }
}
void parseConfigFile( Options& opts, const string& filename )
{
ifstream cfgstream( filename.c_str(), ifstream::in );
if( !cfgstream )
{
cerr << "Failed to open config file: `"
<< filename
<< "'"
<< endl;
exit( EXIT_FAILURE );
}
scanFile( opts, cfgstream );
}
} // NAMESPACE
+348
View File
@@ -0,0 +1,348 @@
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2014, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file ProgramOptions.h
* \brief Input args handler
*/
#ifndef __PROGRAMOPTIONS_H__
#define __PROGRAMOPTIONS_H__
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <map>
#include <vector>
#include "PlaYUVerDefs.h"
namespace plaYUVer
{
struct Options;
struct ParseFailure: public std::exception
{
ParseFailure( std::string arg0, std::string val0 ) throw() :
arg( arg0 ),
val( val0 )
{
}
~ParseFailure() throw()
{
}
;
std::string arg;
std::string val;
const char* what() const throw()
{
return "Option Parse Failure";
}
};
void doHelp( std::ostream& out, Options& opts, unsigned columns = 80 );
unsigned parseGNU( Options& opts, unsigned argc, const char* argv[] );
unsigned parseSHORT( Options& opts, unsigned argc, const char* argv[] );
std::list<const char*> scanArgv( Options& opts, unsigned argc, const char* argv[] );
void scanLine( Options& opts, std::string& line );
void scanFile( Options& opts, std::istream& in );
void setDefaults( Options& opts );
void setDefaults( Options* opts );
void parseConfigFile( Options& opts, const std::string& filename );
bool storePair( Options& opts, const std::string& name, const std::string& value );
/** OptionBase: Virtual base class for storing information relating to a
* specific option This base class describes common elements. Type specific
* information should be stored in a derived class. */
struct OptionBase
{
OptionBase( const std::string& name, const std::string& desc ) :
arg_count( 0 ),
opt_string( name ),
opt_desc( desc )
{
}
;
virtual ~OptionBase()
{
}
/* parse argument arg, to obtain a value for the option */
virtual void parse( const std::string& arg ) = 0;
/* set the argument to the default value */
//virtual void setDefault() = 0;
int count()
{
return arg_count;
}
int arg_count;
std::string opt_string;
std::string opt_desc;
};
/** Type specific option storage */
struct FlagOpt: public OptionBase
{
FlagOpt( const std::string& name, Bool default_val, const std::string& desc ) :
OptionBase( name, desc ),
opt_storage( false ),
opt_default_val( default_val )
{
}
void parse( const std::string& arg )
{
opt_storage = true;
arg_count++;
}
void setDefault()
{
opt_storage = opt_default_val;
}
Bool opt_storage;
Bool opt_default_val;
};
/** Type specific option storage */
template<typename T>
struct Option: public OptionBase
{
Option( const std::string& name, T& storage, const std::string& desc ) :
OptionBase( name, desc ),
opt_storage( storage )
{
}
void parse( const std::string& arg );
// void setDefault()
// {
// opt_storage = opt_default_val;
// }
T& opt_storage;
};
/* Generic parsing */
template<typename T>
inline void Option<T>::parse( const std::string& arg )
{
std::istringstream arg_ss( arg, std::istringstream::in );
arg_ss.exceptions( std::ios::failbit );
try
{
arg_ss >> opt_storage;
}
catch( ... )
{
throw ParseFailure( opt_string, arg );
}
arg_count++;
}
/* string parsing is specialized -- copy the whole string, not just the
* first word */
template<>
inline void Option<std::string>::parse( const std::string& arg )
{
opt_storage = arg;
arg_count++;
}
/* string parsing is specialized -- copy the whole string, not just the
* first word */
template<>
inline void Option<std::vector<std::string> >::parse( const std::string& arg )
{
opt_storage.push_back( arg );
arg_count++;
}
/** Option class for argument handling using a user provided function */
struct OptionFunc: public OptionBase
{
typedef Void (Func)( Options&, const std::string& );
OptionFunc( const std::string& name, Options& parent_, Func *func_, const std::string& desc ) :
OptionBase( name, desc ),
parent( parent_ ),
func( func_ )
{
}
void parse( const std::string& arg )
{
func( parent, arg );
arg_count++;
}
void setDefault()
{
return;
}
private:
Options& parent;
void (*func)( Options&, const std::string& );
};
class OptionSpecific;
struct Options
{
~Options();
OptionSpecific addOptions();
Void setDefaults();
struct Names
{
Names() :
opt( 0 )
{
}
;
~Names()
{
if( opt )
delete opt;
}
std::list<std::string> opt_long;
std::list<std::string> opt_short;
OptionBase* opt;
};
OptionBase* operator[]( const std::string& optName );
OptionBase* getOption( const std::string& optName );
void addOption( OptionBase *opt );
typedef std::list<Names*> NamesPtrList;
NamesPtrList opt_list;
typedef std::map<std::string, NamesPtrList> NamesMap;
NamesMap opt_long_map;
NamesMap opt_short_map;
};
/* Class with templated overloaded operator(), for use by Options::addOptions() */
class OptionSpecific
{
public:
OptionSpecific( Options& parent_ ) :
parent( parent_ )
{
}
/**
* Add option described by name to the parent Options list,
* with storage for the option's value
* with default_val as the default value
* with desc as an optional help description
*/
template<typename T>
OptionSpecific&
operator()( const std::string& name, T& storage, const std::string& desc )
{
parent.addOption( new Option<T>( name, storage, desc ) );
return *this;
}
// /**
// * Add option described by name to the parent Options list,
// * with storage for the option's value
// * with default_val as the default value
// * with desc as an optional help description
// */
// template<typename T>
// OptionSpecific&
// operator()( const std::string& name, T& storage, const std::string& desc )
// {
// parent.addOption( new Option<T>( name, storage, desc ) );
// return *this;
// }
/**
* Add option described by name to the parent Options list,
* with storage for the option's value
* with default_val as the default value
* with desc as an optional help description
*/
OptionSpecific&
operator()( const std::string& name, const std::string& desc )
{
parent.addOption( new FlagOpt( name, false, desc ) );
return *this;
}
/**
* Add option described by name to the parent Options list,
* with storage for the option's value
* with default_val as the default value
* with desc as an optional help description
*/
OptionSpecific&
operator()( const std::string& name, Bool default_val, const std::string& desc )
{
parent.addOption( new FlagOpt( name, default_val, desc ) );
return *this;
}
/**
* Add option described by name to the parent Options list,
* with desc as an optional help description
* instead of storing the value somewhere, a function of type
* OptionFunc::Func is called. It is upto this function to correctly
* handle evaluating the option's value.
*/
OptionSpecific&
operator()( const std::string& name, OptionFunc::Func *func, const std::string& desc )
{
parent.addOption( new OptionFunc( name, parent, func, desc ) );
return *this;
}
private:
Options& parent;
};
} // NAMESPACE
#endif // __PROGRAMOPTIONS_H__
+26 -16
View File
@@ -26,6 +26,7 @@
#include <cstdarg>
#include "CommandLineHandle.h"
#include "lib/PlaYUVerFrame.h"
#include "lib/PlaYUVerStream.h"
#include "modules/PlaYUVerModuleIf.h"
#include "modules/PlaYUVerModuleFactory.h"
@@ -35,6 +36,9 @@ namespace plaYUVer
CommandLineHandle::CommandLineHandle()
{
m_uiLogLevel = 0;
m_bQuiet = false;
m_strPelFmt = std::string( "YUV420p" );
m_iFrames = -1;
}
CommandLineHandle::~CommandLineHandle()
@@ -53,30 +57,36 @@ Void CommandLineHandle::log( UInt level, const char *fmt, ... )
}
}
Int CommandLineHandle::parseToolsArgs()
Int CommandLineHandle::parseToolsArgs( Int argc, Char *argv[] )
{
Int iRet = 0;
po::options_description qualityOpts( "Quality" );
qualityOpts.add_options() /**/
( "quality", po::value<std::string>(), "select a quality metric" ) /**/
( "quality_metrics", "list supported quality metrics" );
Opts().addOptions()/**/
( "quiet,q", m_bQuiet, "disable verbose" );
po::options_description moduleOpts( "Module" );
moduleOpts.add_options() /**/
( "module", po::value<std::string>(), "select a module (use internal name)" ) /**/
( "module_list", "list supported modules" ) /**/
( "module_list_full", "detailed list supported modules" );
Opts().addOptions()/**/
( "input,i", m_apcInputs, "input file" ) /**/
//( "input,i", m_strInput, "input file" ) /**/
( "output,o", m_strOutput, "output file" ) /**/
( "size,s", m_strResolution, "size (WxH)" ) /**/
( "pel_fmt", m_strPelFmt, "pixel format" ) /**/
( "frames,f", m_iFrames, "number of frames to parse" );
addOptions( qualityOpts );
addOptions( moduleOpts );
Opts().addOptions()/**/
( "quality", m_strQualityMetric, "select a quality metric" ) /**/
( "module", m_strModule, "select a module (use internal name)" );
if( !parse() )
if( !parse( argc, argv ) )
{
iRet = 1;
}
if( getOptionsMap().count( "quality_metrics" ) )
if( m_bQuiet )
{
m_uiLogLevel = RESULT;
}
if( Opts()["quality_metrics"]->count() )
{
printf( "PlaYUVer supported quality metrics: \n" );
for( UInt i = 0; i < PlaYUVerFrame::supportedQualityMetricsList().size(); i++ )
@@ -86,7 +96,7 @@ Int CommandLineHandle::parseToolsArgs()
iRet = 1;
}
if( getOptionsMap().count( "module_list" ) || getOptionsMap().count( "module_list_full" ) )
if( Opts()["module_list"]->count() || Opts()["module_list_full"]->count() )
{
listModules();
iRet = 1;
@@ -99,7 +109,7 @@ Void CommandLineHandle::listModules()
{
Bool bDetailed = false;
if( getOptionsMap().count( "module_list_full" ) )
if( Opts()["module_list_full"]->count() )
bDetailed = true;
PlaYUVerModuleIf* pcCurrModuleIf;
+28 -2
View File
@@ -28,12 +28,16 @@
#include "config.h"
#include "lib/PlaYUVerDefs.h"
#include "lib/PlaYUVerCmdParser.h"
#include "lib/ProgramOptions.h"
namespace plaYUVer
{
class PlaYUVerStream;
class CommandLineHandle: public PlaYUVerCmdParser
{
friend class PlaYUVerTools;
public:
CommandLineHandle();
~CommandLineHandle();
@@ -64,11 +68,33 @@ public:
*/
Void log( UInt level, const char *fmt, ... );
Int parseToolsArgs();
Void listModules();
Int parseToolsArgs( Int argc, Char *argv[] );
private:
Options m_cParserOptions;
UInt m_uiLogLevel;
/**
* Command line opts for PlaYUVerTools
*/
Bool m_bShowHelp;
Bool m_bShowVersion;
Bool m_bQuiet;
std::vector<std::string> m_apcInputs;
std::string m_strInput;
std::string m_strOutput;
std::string m_strResolution;
std::string m_strPelFmt;
Bool m_bListPelFmts;
Int m_iFrames;
Bool m_bListQuality;
std::string m_strQualityMetric;
Bool m_bListModules;
std::string m_strModule;
Void listModules();
};
} // NAMESPACE
+28 -39
View File
@@ -22,6 +22,7 @@
* \brief Main definition of the PlaYUVerTools APp
*/
#include <cstring>
#include "PlaYUVerTools.h"
#include "modules/PlaYUVerModuleIf.h"
#include "modules/PlaYUVerModuleFactory.h"
@@ -54,28 +55,23 @@ PlaYUVerTools::~PlaYUVerTools()
Int PlaYUVerTools::openInputs()
{
if( m_cCmdLineHandler.getOptionsMap().count( "quiet" ) )
{
m_bVerbose = false;
m_cCmdLineHandler.setLogLevel( CommandLineHandle::RESULT );
}
/**
* Create input streams
*/
if( m_cCmdLineHandler.getOptionsMap().count( "input" ) )
if( m_cCmdLineHandler.Opts()["input"]->count() )
{
std::string resolutionString( "" );
if( m_cCmdLineHandler.getOptionsMap().count( "size" ) )
if( m_cCmdLineHandler.Opts()["size"]->count() )
{
resolutionString = m_cCmdLineHandler.getOptionsMap()["size"].as<std::string>();
resolutionString = m_cCmdLineHandler.m_strResolution;
}
std::string fmtString( "yuv420p" );
if( m_cCmdLineHandler.getOptionsMap().count( "pel_fmt" ) )
if( m_cCmdLineHandler.Opts()["pel_fmt"]->count() )
{
fmtString = m_cCmdLineHandler.getOptionsMap()["pel_fmt"].as<std::string>();
fmtString = m_cCmdLineHandler.m_strPelFmt;
}
std::vector<std::string> inputFileNames = m_cCmdLineHandler.getOptionsMap()["input"].as<std::vector<std::string> >();
std::vector<std::string> inputFileNames = m_cCmdLineHandler.m_apcInputs;
PlaYUVerStream* pcStream;
for( UInt i = 0; i < inputFileNames.size(); i++ )
@@ -96,30 +92,23 @@ Int PlaYUVerTools::openInputs()
return 2;
}
}
m_uiNumberOfFrames = MAX_UINT;
if( m_cCmdLineHandler.getOptionsMap().count( "frames" ) )
{
m_uiNumberOfFrames = m_cCmdLineHandler.getOptionsMap()["frames"].as<UInt>();
}
m_uiNumberOfComponents = MAX_UINT;
for( UInt i = 0; i < m_apcInputStreams.size(); i++ )
{
if( m_apcInputStreams[i]->getFrameNum() < m_uiNumberOfFrames )
m_uiNumberOfFrames = m_apcInputStreams[i]->getFrameNum();
if( m_apcInputStreams[i]->getCurrFrame()->getNumberChannels() < m_uiNumberOfComponents )
m_uiNumberOfComponents = m_apcInputStreams[i]->getCurrFrame()->getNumberChannels();
}
}
return 0;
}
Int PlaYUVerTools::openOutputs()
{
if( m_cCmdLineHandler.getOptionsMap().count( "output" ) )
m_uiNumberOfFrames = MAX_UINT;
if( m_cCmdLineHandler.Opts()["frames"]->count() )
{
m_uiNumberOfFrames = m_cCmdLineHandler.m_iFrames;
}
m_uiNumberOfComponents = MAX_UINT;
for( UInt i = 0; i < m_apcInputStreams.size(); i++ )
{
if( m_apcInputStreams[i]->getFrameNum() < m_uiNumberOfFrames )
m_uiNumberOfFrames = m_apcInputStreams[i]->getFrameNum();
if( m_apcInputStreams[i]->getCurrFrame()->getNumberChannels() < m_uiNumberOfComponents )
m_uiNumberOfComponents = m_apcInputStreams[i]->getCurrFrame()->getNumberChannels();
}
return 0;
}
@@ -127,8 +116,7 @@ Int PlaYUVerTools::Open( Int argc, Char *argv[] )
{
Int iRet = 0;
m_cCmdLineHandler.Config( argc, argv );
if( ( iRet = m_cCmdLineHandler.parseToolsArgs() ) > 0 )
if( ( iRet = m_cCmdLineHandler.parseToolsArgs( argc, argv ) ) > 0 )
{
return iRet;
}
@@ -141,9 +129,9 @@ Int PlaYUVerTools::Open( Int argc, Char *argv[] )
/**
* Check Quality operation
*/
if( m_cCmdLineHandler.getOptionsMap().count( "quality" ) )
if( m_cCmdLineHandler.Opts()["quality"]->count() )
{
std::string qualityMetric = m_cCmdLineHandler.getOptionsMap()["quality"].as<std::string>();
std::string qualityMetric = m_cCmdLineHandler.m_strQualityMetric;
if( m_apcInputStreams.size() != 2 )
{
m_cCmdLineHandler.log( CommandLineHandle::ERROR, "Invalid number of inputs! " );
@@ -169,9 +157,9 @@ Int PlaYUVerTools::Open( Int argc, Char *argv[] )
/**
* Check Module operation
*/
if( m_cCmdLineHandler.getOptionsMap().count( "module" ) )
if( m_cCmdLineHandler.Opts()["module"]->count() )
{
std::string moduleName = m_cCmdLineHandler.getOptionsMap()["module"].as<std::string>();
std::string moduleName = m_cCmdLineHandler.m_strModule;
PlaYUVerModuleFactoryMap& PlaYUVerModuleFactoryMap = PlaYUVerModuleFactory::Get()->getMap();
PlaYUVerModuleFactoryMap::iterator it = PlaYUVerModuleFactoryMap.begin();
@@ -196,8 +184,9 @@ Int PlaYUVerTools::Open( Int argc, Char *argv[] )
{
// Check outputs
std::vector<std::string> outputFileNames;
if( m_cCmdLineHandler.getOptionsMap().count( "output" ) )
outputFileNames = m_cCmdLineHandler.getOptionsMap()["output"].as<std::vector<std::string> >();
if( m_cCmdLineHandler.Opts()["output"]->count() )
outputFileNames.push_back( m_cCmdLineHandler.m_strOutput );
;
if( outputFileNames.size() == 1 )
{
-1
View File
@@ -64,7 +64,6 @@ private:
std::vector<PlaYUVerStream*> m_apcOutputStreams;
Int openInputs();
Int openOutputs();
typedef Int (PlaYUVerTools::*FpProcess) ();
FpProcess m_fpProcess;