/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2014 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Kvazaar 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kvazaar. If not, see .
****************************************************************************/
/*
* \file
*/
#include "config.h"
#include
#include
#include
#include "extras/getopt.h"
/**
* \brief Allocate memory for config object
* \return pointer to allocated memory
*/
config *config_alloc()
{
config *cfg = (config *)malloc(sizeof(config));
if (!cfg) {
fprintf(stderr, "Failed to allocate a config object!\n");
return cfg;
}
memset(cfg, 0, sizeof(config));
return cfg;
}
/**
* \brief Initialize config structure
* \param cfg config object
* \return 1 on success, 0 on failure
*/
int config_init(config *cfg)
{
cfg->input = NULL;
cfg->output = NULL;
cfg->debug = NULL;
cfg->frames = 0;
cfg->width = 320;
cfg->height = 240;
cfg->qp = 32;
cfg->intra_period = 0;
cfg->deblock_enable = 1;
cfg->deblock_beta = 0;
cfg->deblock_tc = 0;
cfg->sao_enable = 1;
return 1;
}
/**
* \brief Free memory allocated to the config
* \param cfg config object
* \return 1 on success, 0 on failure
*/
int config_destroy(config *cfg)
{
FREE_POINTER(cfg->input);
FREE_POINTER(cfg->output);
free(cfg);
return 1;
}
/**
* \brief Allocates memory space for a string, and copies it
* \param char * string to copy
* \return a pointer to the copied string on success, null on failure
*/
char *copy_string(const char *string)
{
// Allocate +1 for \0
char *allocated_string = (char *)malloc(strlen(string) + 1);
if (!allocated_string) {
fprintf(stderr, "Failed to allocate a string!\n");
return allocated_string;
}
// Copy the string to the new buffer
memcpy(allocated_string, string, strlen(string) + 1);
return allocated_string;
}
static int atobool(const char *str)
{
if (!strcmp(str, "1") ||
!strcmp(str, "true") ||
!strcmp(str, "yes"))
return 1;
if (!strcmp(str, "0") ||
!strcmp(str, "false") ||
!strcmp(str, "no"))
return 0;
return 0;
}
static int config_parse(config *cfg, const char *name, const char *value)
{
int i;
if (!name)
return 0;
if (!value)
value = "true";
if ((!strncmp(name, "no-", 3) && (i = 3))) {
name += i;
value = atobool(value) ? "false" : "true";
}
#define OPT(STR) else if (!strcmp(name, STR))
if (0);
OPT("input")
cfg->input = copy_string(value);
OPT("output")
cfg->output = copy_string(value);
OPT("debug")
cfg->debug = copy_string(value);
OPT("width")
cfg->width = atoi(value);
OPT("height")
cfg->height = atoi(value);
OPT("frames")
cfg->frames = atoi(value);
OPT("qp")
cfg->qp = atoi(value);
OPT("period")
cfg->intra_period = atoi(value);
OPT("deblock") {
int beta, tc;
if (2 == sscanf(value, "%d:%d", &beta, &tc)) {
cfg->deblock_enable = 1;
cfg->deblock_beta = beta;
cfg->deblock_tc = tc;
} else if (sscanf(value, "%d", &beta)) {
cfg->deblock_enable = 1;
cfg->deblock_beta = beta;
cfg->deblock_tc = cfg->deblock_beta;
} else
cfg->deblock_enable = atobool(value);
if (cfg->deblock_beta < -6 || cfg->deblock_beta > 6) {
fprintf(stderr, "--deblock beta parameter out of range [-6..6], set to 0\n");
cfg->deblock_beta = 0;
}
if (cfg->deblock_tc < -6 || cfg->deblock_tc > 6) {
fprintf(stderr, "--deblock tc parameter out of range [-6..6], set to 0\n");
cfg->deblock_tc = 0;
}
}
OPT("sao")
cfg->sao_enable = atobool(value);
else
return 0;
#undef OPT
return 1;
}
/**
* \brief Read configuration options from argv to the config struct
* \param cfg config object
* \param argc argument count
* \param argv argument list
* \return 1 on success, 0 on failure
*/
int config_read(config *cfg,int argc, char *argv[])
{
uint32_t pos = 0;
int arg = 1;
char option = 0;
static char short_options[] = "i:o:d:w:h:n:q:p:";
static struct option long_options[] =
{
{ "input", required_argument, NULL, 'i' },
{ "output", required_argument, NULL, 'o' },
{ "debug", required_argument, NULL, 'd' },
{ "width", required_argument, NULL, 'w' },
{ "height", required_argument, NULL, 'h' },
{ "frames", required_argument, NULL, 'n' },
{ "qp", required_argument, NULL, 'q' },
{ "period", required_argument, NULL, 'p' },
{ "no-deblock", no_argument, NULL, 0 },
{ "deblock", required_argument, NULL, 0 },
{ "no-sao", no_argument, NULL, 0 },
{0, 0, 0, 0}
};
// Parse command line options
for (optind = 0;;) {
int long_options_index = -1;
int c = getopt_long(argc, argv, short_options, long_options, &long_options_index);
if (c == -1)
break;
if (long_options_index < 0) {
int i;
for (i = 0; long_options[i].name; i++)
if (long_options[i].val == c) {
long_options_index = i;
break;
}
if (long_options_index < 0) {
// getopt_long already printed an error message
return 0;
}
}
if (!config_parse(cfg, long_options[long_options_index].name, optarg)) {
const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2];
fprintf(stderr, "invalid argument: %s = %s\r\n", name, optarg );
return 0;
}
}
// Check that the required files were defined
if(cfg->input == NULL || cfg->output == NULL) return 0;
return 1;
}