Added arg_parse function to bwccmdl tool

This commit is contained in:
Patrick Vogler 2024-10-18 11:13:29 +02:00
parent 750f4639ce
commit 4ca342d69e
Signed by: Patrick Vogler
GPG key ID: 5536B08CE82E8509

View file

@ -48,6 +48,7 @@
#include <argp.h> #include <argp.h>
#include <assert.h> #include <assert.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -309,7 +310,7 @@ static char doc[] = "\n"\
" Compression: bwc -c [INPUT] [OPTIONS]\n"\ " Compression: bwc -c [INPUT] [OPTIONS]\n"\
" Decompression: bwc -d [INPUT] [OPTIONS]\n"\ " Decompression: bwc -d [INPUT] [OPTIONS]\n"\
" Analysis: bwc -a [INPUT] -r [REFERENCE]\n"\ " Analysis: bwc -a [INPUT] -r [REFERENCE]\n"\
" Information: bwc -h [INPUT]\n"\ " Information: bwc -i [INPUT]\n"\
"\n"\ "\n"\
"Valid Option Values:\n"\ "Valid Option Values:\n"\
"\n" "\n"
@ -328,7 +329,7 @@ static char doc[] = "\n"\
" <sarr> One or more strings seperated by commas: sarr = *,*,...\n" " <sarr> One or more strings seperated by commas: sarr = *,*,...\n"
" <sdir> Strings that can be specified globally or for all\n" " <sdir> Strings that can be specified globally or for all\n"
" spacial and temporal directions individually:\n" " spacial and temporal directions individually:\n"
" sdir = * or sdir = x/y/z/ts.\n"*/ " sdir = * or sdir = x,y,z,ts.\n"*/
//=================================================================================================| //=================================================================================================|
/** /**
@ -370,9 +371,6 @@ static struct argp_option options[] = {
"for error resilient decoding of" "for error resilient decoding of"
" compressed dataset.\n", 2}, " compressed dataset.\n", 2},
//--------------------|-----|------------|--------------------|--------------------------------|---| //--------------------|-----|------------|--------------------|--------------------------------|---|
{"stream", 's', 0, OPTION_HIDDEN, "Stream data to and from <input>"
"/<output>.", 2},
//--------------------|-----|------------|--------------------|--------------------------------|---|
{"verbose", 'v', 0, 0, "Display compression statistics " {"verbose", 'v', 0, 0, "Display compression statistics "
"and applied compression " "and applied compression "
"parameters.", 2}, "parameters.", 2},
@ -459,11 +457,11 @@ static struct argp_option options[] = {
/*=====================================================|==========================================*/ /*=====================================================|==========================================*/
typedef enum typedef enum
{ {
cli_err, //!< Command-line interface error cli_ini, //!< Undefined command line mode
cli_cmp, //!< Compression run cli_cmp, //!< Compression run
cli_dcp, //!< Decompression run cli_dcp, //!< Decompression run
cli_anl, //!< Analyse distortion of reconstr. file cli_anl, //!< Analyse distortion of reconstr. file
cli_hdr, //!< Display header information cli_inf, //!< Display BWC Header Information
} cli_mode; } cli_mode;
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*\ /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*\
@ -481,13 +479,32 @@ typedef struct
{ {
cli_mode mode; //!< Current state of the cli tool cli_mode mode; //!< Current state of the cli tool
FILE *fpIn, *fpOut; //!< Pointer to input/output file FILE *fpIn, *fpOut,*fpRef; //!< Pointer to in/out/ref file
char* *in, *out; //!< Name of the input/output files char *nIn, *nOut, *nRef; //!< Name of the in/out/ref file
void *in, *out, *ref; //!< In/Ou/Ref buffer
float bitrate[10]; //!< Quality layers defined by bitrate. bool erresilience; //!< Flag signalling error resilience
bool verbose; //!< Flag signalling verbose output
bwc_stream *stream; //!< Structure defining the BigWhoop I/O uint64_t tileSize[4]; //!< Spatial/Temporal tile size
bwc_codec *codec; //!< Structure defining the BigWhoop codec uint8_t precSize[4]; //!< Spatial/Temporal precinct size
uint8_t cblkSize[4]; //!< Spatial/Temporal codeblock size
//bwc_dwt_filter dwtKernel[4]; //!< Spatial/Temporal wavelet kernels
float bitrate[10]; //!< Quality layers defined by bitrate
uint16_t compRatio[10]; //!< Quality layers defined by c. ratio
uint8_t decompLevel[4]; //!< N.o. Spatiaö/temporal dwt decompositions
double qt_step_size; //!< Global qunatization step size
uint8_t Qm; //!< Q number format range (m)
uint8_t useLayer; //!< Quality layer used for decompression
uint64_t nThreads; //!< Number of OpenMP threads
//bwc_quant_st quantization_style; //!< Quantization style
//bwc_prog_ord progression; //!< Packet progression order
} cli_arguments; } cli_arguments;
@ -518,24 +535,25 @@ parse_opt(int key,
/*-----------------------*\ /*-----------------------*\
! DEFINE INT VARIABLES: ! ! DEFINE INT VARIABLES: !
\*-----------------------*/ \*-----------------------*/
//uint64_t buff_LL; int64_t buff;
//uint64_t multiplier; //uint64_t multiplier;
//uint16_t buffI;
uint8_t i; uint8_t i;
//uint8_t length, shift;
/*-----------------------*\ /*-----------------------*\
! DEFINE REAL VARIABLES: ! ! DEFINE REAL VARIABLES: !
\*-----------------------*/ \*-----------------------*/
double compRatio;
double qt_step_size;
float bitrate; float bitrate;
/*-----------------------*\ /*-----------------------*\
! DEFINE REAL VARIABLES: ! ! DEFINE CHAR VARIABLES: !
\*-----------------------*/ \*-----------------------*/
char *end; char *end;
char *token, *ptr;
/*-----------------------*\ /*-----------------------*\
! DEFINE STRUCTS: ! ! DEFINE STRUCTS: !
@ -554,8 +572,6 @@ parse_opt(int key,
! variables to make the code more readable. ! ! variables to make the code more readable. !
\*--------------------------------------------------------*/ \*--------------------------------------------------------*/
arguments = state->input; arguments = state->input;
codec = arguments->codec;
stream = arguments->stream;
/*--------------------------------------------------------*\ /*--------------------------------------------------------*\
! Parse the cli arguments according to the supplied opt. ! ! Parse the cli arguments according to the supplied opt. !
@ -564,52 +580,69 @@ parse_opt(int key,
{ {
case 'c': case 'c':
{ {
arguments->mode = bwc_cmp; if(arguments->mode == cli_ini)
printf("Compress\n");
if(arg[0] == '-')
{ {
argp_error(state, "No input specified\n"); arguments->mode = cli_cmp;
arguments->nIn = arg;
} }
else else
{ {
arguments->input = ; argp_error(state, "Arguments define multiple use cases.\n");
} }
break; break;
} }
case 'd': case 'd':
{
if(arguments->mode != cli_ini)
{ {
arguments->mode = bwc_dcp; arguments->mode = bwc_dcp;
printf("Decompress\n"); arguments->nIn = arg;
}
else
{
argp_error(state, "Arguments define multiple use cases.\n");
}
break; break;
} }
case 'a': case 'a':
{ {
//arguments->analysis = arg; if(arguments->mode != cli_ini)
{
arguments->mode = cli_anl;
arguments->nIn = arg;
}
else
{
argp_error(state, "Arguments define multiple use cases.\n");
}
break; break;
} }
case 'h': case 'i':
{ {
//arguments->header = arg; if(arguments->mode != cli_ini)
{
arguments->mode = cli_inf;
arguments->nIn = arg;
}
else
{
argp_error(state, "Arguments define multiple use cases.\n");
}
break; break;
} }
case 'o': case 'o':
{ {
//arguments->output = arg; arguments->nOut = arg;
break; break;
} }
case 'r': case 'r':
{ {
//arguments->reference = arg; arguments->nRef = arg;
break;
}
case 's':
{
//arguments->stream = 1;
break; break;
} }
case 'v': case 'v':
{ {
//arguments->stream = 1; arguments->verbose = true;
break; break;
} }
case 'b': case 'b':
@ -627,154 +660,272 @@ parse_opt(int key,
} }
else else
{ {
errno = 0;
argp_error(state, "The specified bitrate (%f) is " argp_error(state, "The specified bitrate (%f) is "
"out of the supported range.\n", bitrate); "out of the supported range.\n", bitrate);
arguments->mode = cli_err;
errno = 0;
break;
} }
} }
break; break;
} }
case 'B': case 'B':
{ {
// remove_deliminator(arg, end, '/'); remove_deliminator(arg, end, '/');
// for(buff_LL = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4;
// buff_LL = strtoll(arg, &end, 10), i++) buff = strtoll(arg, &end, 10), i++)
// {
// arg = end;
// if (errno == ERANGE)
// {
// printf("range error, got ");
// errno = 0;
// }
// if(buff_LL > 1 && buff_LL < 10)
// {
// arguments->codeblock[i] = (uint8_t) buff_LL;
// }
// else
// {
// argp_error(state, "The specified codeblock size (%ld) "
// "is out of the supported range.\n", buff_LL);
// }
// }
// if(i == 1)
// {
// arguments->codeblock[1] =
// arguments->codeblock[2] =
// arguments->codeblock[3] = arguments->codeblock[0];
// }
// else if(i != 4)
// {
// argp_error(state, "The codeblock argument expects either a "
// "single global or 4 dirctional values\n");
// }
// if(((arguments->codeblock[0] + arguments->codeblock[1] +
// arguments->codeblock[2] + arguments->codeblock[3]) < 4) ||
// ((arguments->codeblock[0] + arguments->codeblock[1] +
// arguments->codeblock[2] + arguments->codeblock[3]) > 20))
// {
// argp_error(state, "The sum of the specified codeblock sizes "
// "is outside of the supported range\n");
// }
break;
}
case 'R':
{
// arguments->compratio = (uint8_t)strtoll(arg, &end, 10);
// printf("%d\n", arguments->compratio);
break;
}
case 'D':
{
/* remove_deliminator(arg, end, '/');
for(buff_LL = strtoll(arg, &end, 10), i = 0; arg != end && i < 4;
buff_LL = strtoll(arg, &end, 10), i++)
{ {
arg = end; arg = end;
if (errno == ERANGE)
{
printf("range error, got ");
errno = 0;
}
if(buff_LL >= 1 && buff_LL <= 63) if(buff > 1 && buff < 10 && errno != ERANGE)
{ {
arguments->codeblock[i] = (uint8_t) buff_LL; arguments->cblkSize[i] = (uint8_t) buff;
} }
else else
{ {
errno = 0;
argp_error(state, "The specified codeblock size (%ld) " argp_error(state, "The specified codeblock size (%ld) "
"is out of the supported range.\n", buff_LL); "is out of the supported range.\n", buff);
break;
} }
} }
if(i == 1) if(i == 1)
{ {
arguments->codeblock[1] = arguments->cblkSize[1] =
arguments->codeblock[2] = arguments->cblkSize[2] =
arguments->codeblock[3] = arguments->codeblock[0]; arguments->cblkSize[3] = arguments->cblkSize[0];
} }
else if(i != 4) else if(i != 4)
{ {
argp_error(state, "The codeblock argument expects either a " argp_error(state, "The codeblock argument expects either a "
"single global or 4 directional values\n"); "single global or 4 directional values\n");
}*/ }
break;
}
case 'R':
{
remove_deliminator(arg, end, ',');
for(compRatio = strtod(arg, &end), i = 0; arg != end && i < 10;
compRatio = strtod(arg, &end), i++)
{
arg = end;
if(compRatio > 0 && compRatio < 65536 && errno != ERANGE)
{
arguments->compRatio[i] = (uint16_t) compRatio;
}
else
{
errno = 0;
argp_error(state, "The specified bitrate (%d) is "
"out of the supported range.\n", compRatio);
}
}
break;
}
case 'D':
{
remove_deliminator(arg, end, '/');
for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4;
buff = strtoll(arg, &end, 10), i++)
{
arg = end;
if(buff > 0 && buff <= 64 && errno != ERANGE)
{
arguments->decompLevel[i] = (uint8_t) buff;
}
else
{
errno = 0;
argp_error(state, "The specified decomposition level (%ld) "
"is out of the supported range.\n", buff);
break;
}
}
if(i == 1)
{
arguments->decompLevel[1] =
arguments->decompLevel[2] =
arguments->decompLevel[3] = arguments->decompLevel[0];
}
else if(i != 4)
{
argp_error(state, "The decomposition level argument expects either a "
"single global or 4 directional values\n");
}
break; break;
} }
case 'n': case 'n':
{ {
// buff_LL = strtoll(arg, &end, 10); buff = strtoll(arg, &end, 10);
// if((buff_LL < 1) || (buff_LL > 255))
// { if (errno == ERANGE)
// argp_error(state, "The number of OpenMP threads specified" {
// "is out of the supported range.\n"); errno = 0;
// } argp_error(state, "The specified number of OpenMP threads (%ld) "
// else "is out of the supported range.\n", buff);
// { }
// arguments->nthreads = (uint8_t)buff_LL; else
// } {
arguments->nThreads = (uint64_t) buff;
}
break; break;
} }
case 'l': case 'l':
{ {
printf("l\n"); buff = strtoll(arg, &end, 10);
break;
} if (buff > 0 && buff <= 255 && errno != ERANGE)
case 'k':
{ {
printf("k\n"); errno = 0;
argp_error(state, "The specified quality layer (%ld) "
"is out of the supported range.\n", buff);
}
else
{
arguments->useLayer = (uint8_t) buff;
}
break; break;
} }
/*case 'k':
{
for(token = strtok_r(str, ",", &ptr), i = 0;
token != NULL, i < 4;
token = strtok_r(NULL, ",", &ptr), i++)
{
if(strcasecmp(token, "leGall") == 0)
arguments->dwtKernel[i] = bwc_dwt_5_3;
else if (strcasecmp(token, "CDF") == 0)
arguments->dwtKernel[i] = bwc_dwt_9_7;
else if (strcasecmp(token, "Haar") == 0)
arguments->dwtKernel[i] = bwc_dwt_haar;
else
argp_error(state, "Waveket kernel %s is unknown "
"to the library.\n", token);
}
if(i == 1)
{
arguments->dwtKernel[1] =
arguments->dwtKernel[2] =
arguments->dwtKernel[3] = arguments->dwtKernel[0];
}
else if(i != 4)
{
argp_error(state, "The wavelet kernel argument expects either a "
"single global or 4 directional values\n");
}
break;
}*/
case 'q': case 'q':
{ {
printf("q\n"); qt_step_size = strtod(arg, &end);
if(qt_step_size > 0 && qt_step_size < 2 && errno != ERANGE)
{
arguments->qt_step_size = (double) qt_step_size;
}
else
{
errno = 0;
argp_error(state, "The specified quantization step size (%f) is "
"out of the supported range.\n", qt_step_size);
}
break; break;
} }
case 'Q': case 'Q':
{ {
printf("Q\n"); buff = strtoll(arg, &end, 10);
if(buff > 0 && buff < 63 && errno != ERANGE)
{
arguments->Qm = (uint8_t) buff;
}
else
{
errno = 0;
argp_error(state, "The specified Q number format range (%ld) "
"is out of the supported range.\n", buff);
}
break; break;
} }
case 'e': case 'e':
{ {
printf("e\n"); arguments->erresilience = true;
break; break;
} }
case 't': case 't':
{ {
printf("t\n"); remove_deliminator(arg, end, '/');
for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4;
buff = strtoll(arg, &end, 10), i++)
{
arg = end;
if(buff > 16 && errno != ERANGE)
{
arguments->tileSize[i] = (uint64_t) buff;
}
else
{
errno = 0;
argp_error(state, "The specified tile size (%ld) "
"is out of the supported range.\n", buff);
break;
}
}
if(i == 1)
{
arguments->tileSize[1] =
arguments->tileSize[2] =
arguments->tileSize[3] = arguments->tileSize[0];
}
else if(i != 4)
{
argp_error(state, "The tile argument expects either a "
"single global or 4 directional values\n");
}
break; break;
} }
case 'p': case 'p':
{ {
printf("p\n"); remove_deliminator(arg, end, '/');
for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4;
buff = strtoll(arg, &end, 10), i++)
{
arg = end;
if(buff >= 1 && buff <= 15 && errno != ERANGE)
{
arguments->precSize[i] = (uint8_t) buff;
}
else
{
errno = 0;
argp_error(state, "The specified precinct size (%ld) "
"is out of the supported range.\n", buff);
break;
}
}
if(i == 1)
{
arguments->precSize[1] =
arguments->precSize[2] =
arguments->precSize[3] = arguments->precSize[0];
}
else if(i != 4)
{
argp_error(state, "The precinct argument expects either a "
"single global or 4 directional values\n");
}
break; break;
} }
@ -784,38 +935,19 @@ parse_opt(int key,
break; break;
} }
case ARGP_KEY_ARG:
// Too many arguments.
if(state->arg_num > 1)
argp_usage(state);
break;
case ARGP_KEY_END: case ARGP_KEY_END:
/*if(!((arguments->analysis != NULL) && (arguments->comp == NULL) {
&& (arguments->decomp == NULL) if((arguments->mode == cli_ini) ||
&& (arguments->header == NULL) ((arguments->mode == cli_cmp ||
&& (arguments->output == NULL) arguments->mode == cli_dcp ||
&& (arguments->reference != NULL)) && arguments->mode == cli_inf) && arguments->nIn == NULL) ||
!((arguments->comp != NULL) && (arguments->analysis == NULL) (arguments->mode == cli_anl) && (arguments->nIn == NULL || arguments->nRef == NULL))
&& (arguments->decomp == NULL)
&& (arguments->header == NULL)
&& (arguments->reference == NULL)) &&
!((arguments->decomp != NULL) && (arguments->analysis == NULL)
&& (arguments->comp == NULL)
&& (arguments->header == NULL)
&& (arguments->reference == NULL)) &&
!((arguments->header != NULL) && (arguments->analysis == NULL)
&& (arguments->comp == NULL)
&& (arguments->decomp == NULL)
&& (arguments->output == NULL)
&& (arguments->reference == NULL)))
{ {
argp_error(state, "The User supplied options do not fit the " argp_error(state, "The User supplied options do not fit the "
"supported use cases.\n"); "supported use cases.\n");
}*/ }
break; break;
}
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
@ -845,24 +977,10 @@ int main(int argc, char *argv[])
\*-----------------------*/ \*-----------------------*/
cli_arguments arguments = {0}; cli_arguments arguments = {0};
/*--------------------------------------------------------*\
! Initialize the arguments structure. !
\*--------------------------------------------------------*/
arguments.stream = calloc(1, sizeof(bwc_stream));
arguments.codec = calloc(1, sizeof(bwc_codec));
if((arguments.stream == NULL) ||
(arguments.codec == NULL))
{
// memory allocation error
fprintf(stderr, MEMERROR);
return EXIT_FAILURE;
}
/*--------------------------------------------------------*\ /*--------------------------------------------------------*\
! Parse the cli arguments. ! ! Parse the cli arguments. !
\*--------------------------------------------------------*/ \*--------------------------------------------------------*/
argp_parse(&argp, argc, argv, 0, 0, &arguments); if(argp_parse(&argp, argc, argv, 0, 0, &arguments) == EXIT_FAILURE)
if(arguments.mode == cli_err)
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }