2014-01-24 10:37:15 +00:00
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder .
2014-02-21 13:00:20 +00:00
*
2015-02-23 11:18:48 +00:00
* Copyright ( C ) 2013 - 2015 Tampere University of Technology and others ( see
2014-01-24 10:37:15 +00:00
* COPYING file ) .
*
2015-02-23 11:18:48 +00:00
* Kvazaar 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 .
2014-01-24 10:37:15 +00:00
*
2015-02-23 11:18:48 +00:00
* 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 Lesser General Public License for
* more details .
2014-01-24 10:37:15 +00:00
*
2015-02-23 11:18:48 +00:00
* You should have received a copy of the GNU General Public License along
* with Kvazaar . If not , see < http : //www.gnu.org/licenses/>.
2014-01-24 10:37:15 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* \ file
2012-05-30 12:10:23 +00:00
*/
2013-09-18 09:16:03 +00:00
# include "config.h"
2012-05-30 12:10:23 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2015-08-26 08:50:27 +00:00
kvz_config * kvz_config_alloc ( void )
2012-05-30 12:10:23 +00:00
{
2015-06-30 08:03:26 +00:00
kvz_config * cfg = ( kvz_config * ) malloc ( sizeof ( kvz_config ) ) ;
2014-01-31 15:30:27 +00:00
if ( ! cfg ) {
fprintf ( stderr , " Failed to allocate a config object! \n " ) ;
return cfg ;
}
2015-02-13 09:56:55 +00:00
FILL ( * cfg , 0 ) ;
2012-05-30 12:10:23 +00:00
return cfg ;
}
2015-08-26 08:50:27 +00:00
int kvz_config_init ( kvz_config * cfg )
2014-02-21 13:00:20 +00:00
{
2014-03-10 13:53:23 +00:00
cfg - > width = 0 ;
cfg - > height = 0 ;
2015-03-13 14:31:00 +00:00
cfg - > framerate = 25 ;
2014-02-06 19:45:37 +00:00
cfg - > qp = 32 ;
cfg - > intra_period = 0 ;
2015-02-18 11:41:03 +00:00
cfg - > vps_period = 0 ;
2014-02-06 19:45:37 +00:00
cfg - > deblock_enable = 1 ;
cfg - > deblock_beta = 0 ;
cfg - > deblock_tc = 0 ;
cfg - > sao_enable = 1 ;
2014-03-05 14:56:00 +00:00
cfg - > rdoq_enable = 1 ;
2015-01-24 18:10:21 +00:00
cfg - > signhide_enable = true ;
2015-12-15 05:57:38 +00:00
cfg - > smp_enable = false ;
2015-12-01 12:37:58 +00:00
cfg - > amp_enable = false ;
2014-04-07 11:36:01 +00:00
cfg - > rdo = 1 ;
2015-11-05 11:59:30 +00:00
cfg - > mv_rdo = 0 ;
2014-06-17 12:32:05 +00:00
cfg - > full_intra_search = 0 ;
2014-04-02 11:41:40 +00:00
cfg - > trskip_enable = 1 ;
2014-05-30 14:19:41 +00:00
cfg - > tr_depth_intra = 0 ;
2015-03-19 16:48:10 +00:00
cfg - > ime_algorithm = 0 ; /* hexbs */
2014-11-20 12:59:04 +00:00
cfg - > fme_level = 1 ;
2015-08-13 09:53:14 +00:00
cfg - > source_scan_type = 0 ; /* progressive */
2014-02-06 19:45:37 +00:00
cfg - > vui . sar_width = 0 ;
cfg - > vui . sar_height = 0 ;
cfg - > vui . overscan = 0 ; /* undef */
cfg - > vui . videoformat = 5 ; /* undef */
cfg - > vui . fullrange = 0 ; /* limited range */
cfg - > vui . colorprim = 2 ; /* undef */
cfg - > vui . transfer = 2 ; /* undef */
cfg - > vui . colormatrix = 2 ; /* undef */
cfg - > vui . chroma_loc = 0 ; /* left center */
2014-02-06 22:35:15 +00:00
cfg - > aud_enable = 0 ;
config: Add --cqmfile to use custom quantization matrices from a file.
The coefficients in a matrix are stored in up-right diagonal order.
The following indicates the default matrices specified in the spec.
INTRA4X4_LUMA
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTRA4X4_CHROMAU
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTRA4X4_CHROMAV
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTER4X4_LUMA
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTER4X4_CHROMAU
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTER4X4_CHROMAV
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16,
16, 16, 16, 16
INTRA8X8_LUMA
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTRA8X8_CHROMAU
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTRA8X8_CHROMAV
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTER8X8_LUMA
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTER8X8_CHROMAU
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTER8X8_CHROMAV
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTRA16X16_LUMA
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTRA16X16_CHROMAU
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTRA16X16_CHROMAV
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTER16X16_LUMA
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTER16X16_CHROMAU
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTER16X16_CHROMAV
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTRA32X32_LUMA
16, 16, 16, 16, 17, 18, 21, 24,
16, 16, 16, 16, 17, 19, 22, 25,
16, 16, 17, 18, 20, 22, 25, 29,
16, 16, 18, 21, 24, 27, 31, 36,
17, 17, 20, 24, 30, 35, 41, 47,
18, 19, 22, 27, 35, 44, 54, 65,
21, 22, 25, 31, 41, 54, 70, 88,
24, 25, 29, 36, 47, 65, 88, 115
INTER32X32_LUMA
16, 16, 16, 16, 17, 18, 20, 24,
16, 16, 16, 17, 18, 20, 24, 25,
16, 16, 17, 18, 20, 24, 25, 28,
16, 17, 18, 20, 24, 25, 28, 33,
17, 18, 20, 24, 25, 28, 33, 41,
18, 20, 24, 25, 28, 33, 41, 54,
20, 24, 25, 28, 33, 41, 54, 71,
24, 25, 28, 33, 41, 54, 71, 91
INTRA16X16_LUMA_DC
16
INTRA16X16_CHROMAU_DC
16
INTRA16X16_CHROMAV_DC
16
INTER16X16_LUMA_DC
16
INTER16X16_CHROMAU_DC
16
INTER16X16_CHROMAV_DC
16
INTRA32X32_LUMA_DC
16
INTER32X32_LUMA_DC
16
2014-02-11 10:55:21 +00:00
cfg - > cqmfile = NULL ;
2014-02-19 13:09:17 +00:00
cfg - > ref_frames = DEFAULT_REF_PIC_COUNT ;
2015-03-30 06:54:22 +00:00
cfg - > gop_len = 0 ;
2015-04-21 11:18:34 +00:00
cfg - > bipred = 0 ;
2015-03-13 14:31:00 +00:00
cfg - > target_bitrate = 0 ;
2012-05-30 12:10:23 +00:00
2014-04-02 08:38:03 +00:00
cfg - > tiles_width_count = 0 ;
cfg - > tiles_height_count = 0 ;
cfg - > tiles_width_split = NULL ;
cfg - > tiles_height_split = NULL ;
2014-05-05 13:17:22 +00:00
cfg - > wpp = 0 ;
2014-12-05 13:21:46 +00:00
cfg - > owf = - 1 ;
2014-05-05 13:17:22 +00:00
cfg - > slice_count = 1 ;
cfg - > slice_addresses_in_ts = MALLOC ( int32_t , 1 ) ;
cfg - > slice_addresses_in_ts [ 0 ] = 0 ;
2014-05-13 09:52:10 +00:00
cfg - > threads = 0 ;
2014-10-14 09:01:56 +00:00
cfg - > cpuid = 1 ;
2014-04-02 08:38:03 +00:00
2015-01-09 10:04:23 +00:00
// Defaults for what sizes of PUs are tried.
cfg - > pu_depth_inter . min = 0 ; // 0-3
cfg - > pu_depth_inter . max = 3 ; // 0-3
cfg - > pu_depth_intra . min = 1 ; // 0-4
cfg - > pu_depth_intra . max = 4 ; // 0-4
2015-04-16 14:17:17 +00:00
cfg - > add_encoder_info = true ;
2012-05-30 12:10:23 +00:00
return 1 ;
}
2015-08-26 08:50:27 +00:00
int kvz_config_destroy ( kvz_config * cfg )
2012-05-30 12:10:23 +00:00
{
2015-08-25 09:46:19 +00:00
if ( cfg ) {
FREE_POINTER ( cfg - > cqmfile ) ;
FREE_POINTER ( cfg - > tiles_width_split ) ;
FREE_POINTER ( cfg - > tiles_height_split ) ;
FREE_POINTER ( cfg - > slice_addresses_in_ts ) ;
}
2012-05-30 12:10:23 +00:00
free ( cfg ) ;
return 1 ;
}
2014-02-03 22:16:42 +00:00
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 ;
}
2014-02-06 19:45:37 +00:00
static int parse_enum ( const char * arg , const char * const * names , int8_t * dst )
{
2014-02-21 13:15:59 +00:00
int8_t i ;
for ( i = 0 ; names [ i ] ; i + + ) {
2014-02-06 19:45:37 +00:00
if ( ! strcmp ( arg , names [ i ] ) ) {
* dst = i ;
return 1 ;
}
2014-02-21 13:15:59 +00:00
}
2014-02-06 19:45:37 +00:00
return 0 ;
}
2014-04-02 08:38:03 +00:00
static int parse_tiles_specification ( const char * const arg , int32_t * const ntiles , int32_t * * const array ) {
const char * current_arg = NULL ;
int32_t current_value ;
2014-05-05 13:17:52 +00:00
int32_t values [ MAX_TILES_PER_DIM ] ;
2014-04-02 08:38:03 +00:00
int i ;
//Free pointer in any case
if ( * array ) {
FREE_POINTER ( * array ) ;
}
//If the arg starts with u, we want an uniform split
if ( arg [ 0 ] = = ' u ' ) {
* ntiles = atoi ( arg + 1 ) - 1 ;
2015-09-29 13:28:00 +00:00
if ( MAX_TILES_PER_DIM < = * ntiles | | 0 > * ntiles ) {
2014-04-02 08:38:03 +00:00
fprintf ( stderr , " Invalid number of tiles (0 < %d <= %d = MAX_TILES_PER_DIM)! \n " , * ntiles + 1 , MAX_TILES_PER_DIM ) ;
return 0 ;
}
//Done with parsing
return 1 ;
}
//We have a comma-separated list of int for the split...
current_arg = arg ;
* ntiles = 0 ;
do {
int ret = sscanf ( current_arg , " %d " , & current_value ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " Could not parse integer \" %s \" ! \n " , current_arg ) ;
return 0 ;
}
current_arg = strchr ( current_arg , ' , ' ) ;
//Skip the , if we found one
if ( current_arg ) + + current_arg ;
values [ * ntiles ] = current_value ;
+ + ( * ntiles ) ;
2014-05-05 13:17:52 +00:00
if ( MAX_TILES_PER_DIM < = * ntiles ) break ;
2014-04-02 08:38:03 +00:00
} while ( current_arg ) ;
if ( MAX_TILES_PER_DIM < = * ntiles | | 0 > = * ntiles ) {
fprintf ( stderr , " Invalid number of tiles (0 < %d <= %d = MAX_TILES_PER_DIM)! \n " , * ntiles + 1 , MAX_TILES_PER_DIM ) ;
return 0 ;
}
* array = MALLOC ( int32_t , * ntiles ) ;
if ( ! * array ) {
fprintf ( stderr , " Could not allocate array for tiles \n " ) ;
return 0 ;
}
//TODO: memcpy?
for ( i = 0 ; i < * ntiles ; + + i ) {
( * array ) [ i ] = values [ i ] ;
}
return 1 ;
}
2014-05-05 13:17:22 +00:00
static int parse_slice_specification ( const char * const arg , int32_t * const nslices , int32_t * * const array ) {
const char * current_arg = NULL ;
int32_t current_value ;
int32_t values [ MAX_SLICES ] ;
int i ;
//Free pointer in any case
if ( * array ) {
FREE_POINTER ( * array ) ;
}
//If the arg starts with u, we want an uniform split
if ( arg [ 0 ] = = ' u ' ) {
* nslices = atoi ( arg + 1 ) ;
if ( MAX_SLICES < = * nslices | | 0 > = * nslices ) {
fprintf ( stderr , " Invalid number of tiles (0 < %d <= %d = MAX_SLICES)! \n " , * nslices + 1 , MAX_SLICES ) ;
return 0 ;
}
//Done with parsing
return 1 ;
}
//We have a comma-separated list of int for the split...
current_arg = arg ;
//We always have a slice starting at 0
values [ 0 ] = 0 ;
* nslices = 1 ;
do {
int ret = sscanf ( current_arg , " %d " , & current_value ) ;
if ( ret ! = 1 ) {
fprintf ( stderr , " Could not parse integer \" %s \" ! \n " , current_arg ) ;
return 0 ;
}
current_arg = strchr ( current_arg , ' , ' ) ;
//Skip the , if we found one
if ( current_arg ) + + current_arg ;
values [ * nslices ] = current_value ;
+ + ( * nslices ) ;
if ( MAX_SLICES < = * nslices ) break ;
} while ( current_arg ) ;
if ( MAX_SLICES < = * nslices | | 0 > = * nslices ) {
fprintf ( stderr , " Invalid number of slices (0 < %d <= %d = MAX_SLICES)! \n " , * nslices , MAX_SLICES ) ;
return 0 ;
}
* array = MALLOC ( int32_t , * nslices ) ;
if ( ! * array ) {
fprintf ( stderr , " Could not allocate array for slices \n " ) ;
return 0 ;
}
//TODO: memcpy?
for ( i = 0 ; i < * nslices ; + + i ) {
( * array ) [ i ] = values [ i ] ;
}
return 1 ;
}
2015-08-26 08:50:27 +00:00
int kvz_config_parse ( kvz_config * cfg , const char * name , const char * value )
2014-02-03 20:58:23 +00:00
{
2015-03-19 16:48:10 +00:00
static const char * const me_names [ ] = { " hexbs " , " tz " , NULL } ;
2015-08-13 09:53:14 +00:00
static const char * const source_scan_type_names [ ] = { " progressive " , " tff " , " bff " , NULL } ;
2015-03-19 16:48:10 +00:00
2014-02-06 19:45:37 +00:00
static const char * const overscan_names [ ] = { " undef " , " show " , " crop " , NULL } ;
static const char * const videoformat_names [ ] = { " component " , " pal " , " ntsc " , " secam " , " mac " , " undef " , NULL } ;
2014-02-08 02:29:50 +00:00
static const char * const range_names [ ] = { " tv " , " pc " , NULL } ;
2014-02-06 19:45:37 +00:00
static const char * const colorprim_names [ ] = { " " , " bt709 " , " undef " , " " , " bt470m " , " bt470bg " , " smpte170m " ,
" smpte240m " , " film " , " bt2020 " , NULL } ;
static const char * const transfer_names [ ] = { " " , " bt709 " , " undef " , " " , " bt470m " , " bt470bg " , " smpte170m " ,
" smpte240m " , " linear " , " log100 " , " log316 " , " iec61966-2-4 " ,
" bt1361e " , " iec61966-2-1 " , " bt2020-10 " , " bt2020-12 " , NULL } ;
static const char * const colormatrix_names [ ] = { " GBR " , " bt709 " , " undef " , " " , " fcc " , " bt470bg " , " smpte170m " ,
" smpte240m " , " YCgCo " , " bt2020nc " , " bt2020c " , NULL } ;
2015-11-05 11:59:30 +00:00
static const char * const preset_values [ 11 ] [ 28 ] = {
2015-11-03 13:26:34 +00:00
{
" ultrafast " ,
" pu-depth-intra " , " 2-3 " ,
" pu-depth-inter " , " 1-3 " ,
" rd " , " 0 " ,
" me " , " hexbs " ,
" ref " , " 1 " ,
" deblock " , " 0 " ,
" signhide " , " 0 " ,
" subme " , " 0 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" superfast " ,
" pu-depth-intra " , " 1-3 " ,
" pu-depth-inter " , " 1-3 " ,
" rd " , " 1 " ,
" me " , " hexbs " ,
" ref " , " 1 " ,
" deblock " , " 0 " ,
" signhide " , " 0 " ,
" subme " , " 0 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" veryfast " ,
" pu-depth-intra " , " 1-3 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 1 " ,
" me " , " hexbs " ,
" ref " , " 2 " ,
" deblock " , " 1 " ,
" signhide " , " 0 " ,
" subme " , " 0 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" faster " ,
" pu-depth-intra " , " 1-3 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 1 " ,
" me " , " hexbs " ,
" ref " , " 2 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 0 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" fast " ,
" pu-depth-intra " , " 1-3 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 1 " ,
" me " , " hexbs " ,
" ref " , " 2 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" medium " ,
" pu-depth-intra " , " 1-4 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 1 " ,
" me " , " hexbs " ,
" ref " , " 3 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 0 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" slow " ,
" pu-depth-intra " , " 1-4 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 2 " ,
" me " , " hexbs " ,
" ref " , " 3 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 1 " ,
" rdoq " , " 0 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" slower " ,
" pu-depth-intra " , " 1-4 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 2 " ,
" me " , " tz " ,
" ref " , " 4 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 1 " ,
" rdoq " , " 1 " ,
" transform-skip " , " 0 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 0 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" veryslow " ,
" pu-depth-intra " , " 1-4 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 2 " ,
" me " , " tz " ,
" ref " , " 4 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 1 " ,
" rdoq " , " 1 " ,
" transform-skip " , " 1 " ,
" full-intra-search " , " 0 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 1 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
{
" placebo " ,
" pu-depth-intra " , " 0-4 " ,
" pu-depth-inter " , " 0-3 " ,
" rd " , " 3 " ,
" me " , " tz " ,
" ref " , " 6 " ,
" deblock " , " 1 " ,
" signhide " , " 1 " ,
" subme " , " 1 " ,
" sao " , " 1 " ,
" rdoq " , " 1 " ,
" transform-skip " , " 1 " ,
" full-intra-search " , " 1 " ,
2015-11-05 11:59:30 +00:00
" mv-rdo " , " 1 " ,
2015-11-03 13:26:34 +00:00
NULL
} ,
2015-11-03 10:04:22 +00:00
{ NULL }
} ;
2014-02-03 20:58:23 +00:00
if ( ! name )
return 0 ;
2015-06-29 12:50:15 +00:00
2014-02-03 22:16:42 +00:00
if ( ! value )
value = " true " ;
2014-04-04 08:39:25 +00:00
// Treat "--no-param" as --param 0
if ( ( ! strncmp ( name , " no- " , 3 ) ) ) {
name + = 3 ;
2014-02-03 22:16:42 +00:00
value = atobool ( value ) ? " false " : " true " ;
}
2014-02-03 20:58:23 +00:00
2014-04-04 09:20:17 +00:00
# define OPT(STR) (!strcmp(name, STR))
2015-07-03 12:04:36 +00:00
if OPT ( " width " )
2014-02-03 20:58:23 +00:00
cfg - > width = atoi ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " height " )
2014-02-03 20:58:23 +00:00
cfg - > height = atoi ( value ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " input-res " )
2015-07-29 16:07:27 +00:00
if ( ! strcmp ( value , " auto " ) ) {
return 1 ;
} else {
return ( sscanf ( value , " %dx%d " , & cfg - > width , & cfg - > height ) = = 2 ) ;
}
2015-06-29 12:50:15 +00:00
else if OPT ( " input-fps " )
2015-03-13 14:31:00 +00:00
cfg - > framerate = atof ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " qp " )
2014-02-03 20:58:23 +00:00
cfg - > qp = atoi ( value ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " period " )
2014-02-03 20:58:23 +00:00
cfg - > intra_period = atoi ( value ) ;
2015-02-18 11:41:03 +00:00
else if OPT ( " vps-period " )
cfg - > vps_period = atoi ( value ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " ref " )
2014-02-18 15:45:54 +00:00
cfg - > ref_frames = atoi ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " deblock " ) {
2014-02-03 22:31:24 +00:00
int beta , tc ;
if ( 2 = = sscanf ( value , " %d:%d " , & beta , & tc ) ) {
cfg - > deblock_enable = 1 ;
cfg - > deblock_beta = beta ;
cfg - > deblock_tc = tc ;
2015-06-29 12:50:15 +00:00
} else {
2014-02-03 22:31:24 +00:00
cfg - > deblock_enable = atobool ( value ) ;
2014-02-06 12:32:30 +00:00
}
2014-02-03 22:31:24 +00:00
}
2014-04-04 09:20:17 +00:00
else if OPT ( " sao " )
2014-02-03 22:55:51 +00:00
cfg - > sao_enable = atobool ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " rdoq " )
2014-03-05 14:56:00 +00:00
cfg - > rdoq_enable = atobool ( value ) ;
2015-01-24 18:10:21 +00:00
else if OPT ( " signhide " )
cfg - > signhide_enable = ( bool ) atobool ( value ) ;
2015-12-15 05:57:38 +00:00
else if OPT ( " smp " )
cfg - > smp_enable = ( bool ) atobool ( value ) ;
2015-12-01 12:37:58 +00:00
else if OPT ( " amp " )
cfg - > amp_enable = ( bool ) atobool ( value ) ;
2014-06-17 12:32:05 +00:00
else if OPT ( " rd " )
2015-06-29 12:50:15 +00:00
cfg - > rdo = atoi ( value ) ;
2014-06-17 12:32:05 +00:00
else if OPT ( " full-intra-search " )
cfg - > full_intra_search = atobool ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " transform-skip " )
2014-04-02 11:41:40 +00:00
cfg - > trskip_enable = atobool ( value ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " tr-depth-intra " )
2014-05-30 14:19:41 +00:00
cfg - > tr_depth_intra = atoi ( value ) ;
2015-07-06 06:47:18 +00:00
else if OPT ( " me " ) {
int8_t ime_algorithm = 0 ;
if ( ! parse_enum ( value , me_names , & ime_algorithm ) ) return 0 ;
cfg - > ime_algorithm = ime_algorithm ;
}
2015-06-29 12:50:15 +00:00
else if OPT ( " subme " )
2014-11-20 12:59:04 +00:00
cfg - > fme_level = atoi ( value ) ;
2015-08-13 09:53:14 +00:00
else if OPT ( " source-scan-type " )
return parse_enum ( value , source_scan_type_names , & cfg - > source_scan_type ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " sar " )
return sscanf ( value , " %d:%d " , & cfg - > vui . sar_width , & cfg - > vui . sar_height ) = = 2 ;
2014-04-04 09:20:17 +00:00
else if OPT ( " overscan " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , overscan_names , & cfg - > vui . overscan ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " videoformat " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , videoformat_names , & cfg - > vui . videoformat ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " range " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , range_names , & cfg - > vui . fullrange ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " colorprim " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , colorprim_names , & cfg - > vui . colorprim ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " transfer " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , transfer_names , & cfg - > vui . transfer ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " colormatrix " )
2015-06-29 12:50:15 +00:00
return parse_enum ( value , colormatrix_names , & cfg - > vui . colormatrix ) ;
else if OPT ( " chromaloc " )
cfg - > vui . chroma_loc = atoi ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " aud " )
2014-02-06 22:35:15 +00:00
cfg - > aud_enable = atobool ( value ) ;
2014-04-04 09:20:17 +00:00
else if OPT ( " cqmfile " )
2015-07-03 12:04:36 +00:00
cfg - > cqmfile = strdup ( value ) ;
2014-04-02 08:38:03 +00:00
else if OPT ( " tiles-width-split " )
2015-06-29 12:50:15 +00:00
return parse_tiles_specification ( value , & cfg - > tiles_width_count , & cfg - > tiles_width_split ) ;
2014-04-02 08:38:03 +00:00
else if OPT ( " tiles-height-split " )
2015-06-29 12:50:15 +00:00
return parse_tiles_specification ( value , & cfg - > tiles_height_count , & cfg - > tiles_height_split ) ;
2014-05-05 13:17:22 +00:00
else if OPT ( " wpp " )
cfg - > wpp = atobool ( value ) ;
2014-06-16 06:26:24 +00:00
else if OPT ( " owf " ) {
cfg - > owf = atoi ( value ) ;
2015-06-29 12:50:15 +00:00
if ( cfg - > owf = = 0 & & ! strcmp ( value , " auto " ) ) {
// -1 means automatic selection
2014-11-17 00:19:25 +00:00
cfg - > owf = - 1 ;
2014-06-16 06:26:24 +00:00
}
}
2014-05-05 13:17:22 +00:00
else if OPT ( " slice-addresses " )
2015-06-29 12:50:15 +00:00
return parse_slice_specification ( value , & cfg - > slice_count , & cfg - > slice_addresses_in_ts ) ;
2014-05-13 09:52:10 +00:00
else if OPT ( " threads " )
cfg - > threads = atoi ( value ) ;
2014-10-14 09:01:56 +00:00
else if OPT ( " cpuid " )
cfg - > cpuid = atoi ( value ) ;
2015-01-09 10:04:23 +00:00
else if OPT ( " pu-depth-inter " )
2015-06-29 12:50:15 +00:00
return sscanf ( value , " %d-%d " , & cfg - > pu_depth_inter . min , & cfg - > pu_depth_inter . max ) = = 2 ;
2015-01-09 10:04:23 +00:00
else if OPT ( " pu-depth-intra " )
2015-06-29 12:50:15 +00:00
return sscanf ( value , " %d-%d " , & cfg - > pu_depth_intra . min , & cfg - > pu_depth_intra . max ) = = 2 ;
2015-04-16 14:17:17 +00:00
else if OPT ( " info " )
cfg - > add_encoder_info = atobool ( value ) ;
2015-03-30 06:54:22 +00:00
else if OPT ( " gop " ) {
2015-11-13 16:19:13 +00:00
if ( ! strncmp ( value , " lp- " , 3 ) ) { // Handle GOPs starting with "lp-".
struct {
unsigned g ; // length
unsigned d ; // depth
unsigned r ; // references
unsigned t ; // temporal
} gop = { 0 } ;
if ( sscanf ( value , " lp-g%ud%ur%ut%u " , & gop . g , & gop . d , & gop . r , & gop . t ) ! = 4 ) {
fprintf ( stderr , " Error in GOP syntax. Example: lp-g8d4r2t2 \n " ) ;
return 0 ;
}
if ( gop . g < 1 | | gop . g > 32 ) {
fprintf ( stderr , " gop.g must be between 1 and 32. \n " ) ;
}
if ( gop . d < 1 | | gop . d > 8 ) {
fprintf ( stderr , " gop.d must be between 1 and 8. \n " ) ;
}
if ( gop . r < 1 | | gop . r > 15 ) {
fprintf ( stderr , " gop.d must be between 1 and 15. \n " ) ;
}
if ( gop . t < 1 | | gop . t > 15 ) {
fprintf ( stderr , " gop.t must be between 1 and 32. \n " ) ;
}
// Initialize modulos for testing depth.
// The picture belong to the lowest depth in which (poc % modulo) == 0.
unsigned depth_modulos [ 8 ] = { 0 } ;
for ( int d = 0 ; d < gop . d ; + + d ) {
depth_modulos [ gop . d - 1 - d ] = 1 < < d ;
}
depth_modulos [ 0 ] = gop . g ;
cfg - > gop_lowdelay = 1 ;
cfg - > gop_len = gop . g ;
for ( int g = 1 ; g < = gop . g ; + + g ) {
kvz_gop_config * gop_pic = & cfg - > gop [ g - 1 ] ;
// Find gop depth for picture.
int gop_layer = 0 ;
while ( gop_layer < gop . d & & ( g % depth_modulos [ gop_layer ] ) ) {
+ + gop_layer ;
}
gop_pic - > poc_offset = g ;
gop_pic - > layer = gop_layer + 1 ;
gop_pic - > qp_offset = gop_layer + 1 ;
gop_pic - > ref_pos_count = 0 ;
gop_pic - > ref_neg_count = gop . r ;
gop_pic - > is_ref = 0 ;
// Set first ref to point to previous frame, and the rest to previous
// key-frames.
// If gop.t > 1, have (poc % gop.t) == 0 point gop.t frames away,
// instead of the previous frame. Set the frames in between to
// point to the nearest frame with a lower gop-depth.
if ( gop . t > 1 ) {
if ( gop_pic - > poc_offset % gop . t = = 0 ) {
gop_pic - > ref_neg [ 0 ] = gop . t ;
} else {
int r = gop_pic - > poc_offset - 1 ;
while ( r > 0 ) {
if ( cfg - > gop [ r ] . layer < gop_pic - > layer ) break ;
- - r ;
}
// Var r is now 0 or index of the pic with layer < depth.
if ( cfg - > gop [ r ] . layer < gop_pic - > layer ) {
gop_pic - > ref_neg [ 0 ] = gop_pic - > poc_offset - cfg - > gop [ r ] . poc_offset ;
cfg - > gop [ r ] . is_ref = 1 ;
} else {
// No ref was found, just refer to the previous key-frame.
gop_pic - > ref_neg [ 0 ] = gop_pic - > poc_offset % gop . g ;
}
}
} else {
gop_pic - > ref_neg [ 0 ] = 1 ;
if ( gop_pic - > poc_offset > = 2 ) {
cfg - > gop [ gop_pic - > poc_offset - 2 ] . is_ref = 1 ;
}
}
2015-11-16 09:21:34 +00:00
int keyframe = gop_pic - > poc_offset ;
2015-11-13 16:19:13 +00:00
for ( int i = 1 ; i < gop_pic - > ref_neg_count ; + + i ) {
while ( keyframe = = gop_pic - > ref_neg [ i - 1 ] ) {
keyframe + = gop . g ;
}
gop_pic - > ref_neg [ i ] = keyframe ;
}
gop_pic - > qp_factor = 0.4624 ; // from HM
}
for ( int g = 0 ; g < gop . g ; + + g ) {
kvz_gop_config * gop_pic = & cfg - > gop [ g ] ;
if ( ! gop_pic - > is_ref ) {
gop_pic - > qp_factor = 0.68 * 1.31 ; // derived from HM
}
}
// Key-frame is always a reference.
cfg - > gop [ gop . g - 1 ] . is_ref = 1 ;
cfg - > gop [ gop . g - 1 ] . qp_factor = 0.578 ; // from HM
} else if ( atoi ( value ) = = 8 ) {
2015-11-02 10:22:25 +00:00
cfg - > gop_lowdelay = 0 ;
2015-03-30 06:54:22 +00:00
// GOP
cfg - > gop_len = 8 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 0 ] . poc_offset = 8 ; cfg - > gop [ 0 ] . qp_offset = 1 ; cfg - > gop [ 0 ] . layer = 1 ; cfg - > gop [ 0 ] . qp_factor = 0.442 ; cfg - > gop [ 0 ] . is_ref = 1 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 0 ] . ref_pos_count = 0 ;
cfg - > gop [ 0 ] . ref_neg_count = 3 ; cfg - > gop [ 0 ] . ref_neg [ 0 ] = 8 ; cfg - > gop [ 0 ] . ref_neg [ 1 ] = 12 ; cfg - > gop [ 0 ] . ref_neg [ 2 ] = 16 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 1 ] . poc_offset = 4 ; cfg - > gop [ 1 ] . qp_offset = 2 ; cfg - > gop [ 1 ] . layer = 2 ; cfg - > gop [ 1 ] . qp_factor = 0.3536 ; cfg - > gop [ 1 ] . is_ref = 1 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 1 ] . ref_neg_count = 2 ; cfg - > gop [ 1 ] . ref_neg [ 0 ] = 4 ; cfg - > gop [ 1 ] . ref_neg [ 1 ] = 8 ;
cfg - > gop [ 1 ] . ref_pos_count = 1 ; cfg - > gop [ 1 ] . ref_pos [ 0 ] = 4 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 2 ] . poc_offset = 2 ; cfg - > gop [ 2 ] . qp_offset = 3 ; cfg - > gop [ 2 ] . layer = 3 ; cfg - > gop [ 2 ] . qp_factor = 0.3536 ; cfg - > gop [ 2 ] . is_ref = 1 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 2 ] . ref_neg_count = 2 ; cfg - > gop [ 2 ] . ref_neg [ 0 ] = 2 ; cfg - > gop [ 2 ] . ref_neg [ 1 ] = 6 ;
cfg - > gop [ 2 ] . ref_pos_count = 2 ; cfg - > gop [ 2 ] . ref_pos [ 0 ] = 2 ; cfg - > gop [ 2 ] . ref_pos [ 1 ] = 6 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 3 ] . poc_offset = 1 ; cfg - > gop [ 3 ] . qp_offset = 4 ; cfg - > gop [ 3 ] . layer = 4 ; cfg - > gop [ 3 ] . qp_factor = 0.68 ; cfg - > gop [ 3 ] . is_ref = 0 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 3 ] . ref_neg_count = 1 ; cfg - > gop [ 3 ] . ref_neg [ 0 ] = 1 ;
cfg - > gop [ 3 ] . ref_pos_count = 3 ; cfg - > gop [ 3 ] . ref_pos [ 0 ] = 1 ; cfg - > gop [ 3 ] . ref_pos [ 1 ] = 3 ; cfg - > gop [ 3 ] . ref_pos [ 2 ] = 7 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 4 ] . poc_offset = 3 ; cfg - > gop [ 4 ] . qp_offset = 4 ; cfg - > gop [ 4 ] . layer = 4 ; cfg - > gop [ 4 ] . qp_factor = 0.68 ; cfg - > gop [ 4 ] . is_ref = 0 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 4 ] . ref_neg_count = 2 ; cfg - > gop [ 4 ] . ref_neg [ 0 ] = 1 ; cfg - > gop [ 4 ] . ref_neg [ 1 ] = 3 ;
cfg - > gop [ 4 ] . ref_pos_count = 2 ; cfg - > gop [ 4 ] . ref_pos [ 0 ] = 1 ; cfg - > gop [ 4 ] . ref_pos [ 1 ] = 5 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 5 ] . poc_offset = 6 ; cfg - > gop [ 5 ] . qp_offset = 3 ; cfg - > gop [ 5 ] . layer = 3 ; cfg - > gop [ 5 ] . qp_factor = 0.3536 ; cfg - > gop [ 5 ] . is_ref = 1 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 5 ] . ref_neg_count = 2 ; cfg - > gop [ 5 ] . ref_neg [ 0 ] = 2 ; cfg - > gop [ 5 ] . ref_neg [ 1 ] = 6 ;
cfg - > gop [ 5 ] . ref_pos_count = 1 ; cfg - > gop [ 5 ] . ref_pos [ 0 ] = 2 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 6 ] . poc_offset = 5 ; cfg - > gop [ 6 ] . qp_offset = 4 ; cfg - > gop [ 6 ] . layer = 4 ; cfg - > gop [ 6 ] . qp_factor = 0.68 ; cfg - > gop [ 6 ] . is_ref = 0 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 6 ] . ref_neg_count = 2 ; cfg - > gop [ 6 ] . ref_neg [ 0 ] = 1 ; cfg - > gop [ 6 ] . ref_neg [ 1 ] = 5 ;
cfg - > gop [ 6 ] . ref_pos_count = 2 ; cfg - > gop [ 6 ] . ref_pos [ 0 ] = 1 ; cfg - > gop [ 6 ] . ref_pos [ 1 ] = 3 ;
2015-05-29 11:00:51 +00:00
cfg - > gop [ 7 ] . poc_offset = 7 ; cfg - > gop [ 7 ] . qp_offset = 4 ; cfg - > gop [ 7 ] . layer = 4 ; cfg - > gop [ 7 ] . qp_factor = 0.68 ; cfg - > gop [ 7 ] . is_ref = 0 ;
2015-03-30 06:54:22 +00:00
cfg - > gop [ 7 ] . ref_neg_count = 3 ; cfg - > gop [ 7 ] . ref_neg [ 0 ] = 1 ; cfg - > gop [ 7 ] . ref_neg [ 1 ] = 3 ; cfg - > gop [ 7 ] . ref_neg [ 2 ] = 7 ;
cfg - > gop [ 7 ] . ref_pos_count = 1 ; cfg - > gop [ 7 ] . ref_pos [ 0 ] = 1 ;
2015-06-29 12:50:15 +00:00
} else if ( atoi ( value ) ) {
fprintf ( stderr , " Input error: unsupported gop length, must be 0 or 8 \n " ) ;
2015-03-30 06:54:22 +00:00
return 0 ;
}
}
2015-04-21 11:18:34 +00:00
else if OPT ( " bipred " )
cfg - > bipred = atobool ( value ) ;
2015-06-29 12:50:15 +00:00
else if OPT ( " bitrate " )
2015-03-13 14:31:00 +00:00
cfg - > target_bitrate = atoi ( value ) ;
2015-11-03 10:04:22 +00:00
else if OPT ( " preset " ) {
int preset_line = 0 ;
2015-11-03 13:46:23 +00:00
// Accept numbers from 0 to 9.
if ( ( atoi ( value ) = = 0 & & ! strcmp ( value , " 0 " ) ) | | ( atoi ( value ) > = 1 & & atoi ( value ) < = 9 ) ) {
preset_line = atoi ( value ) ;
} else {
// Find the selected preset from the list
while ( preset_values [ preset_line ] [ 0 ] ! = NULL ) {
if ( ! strcmp ( value , preset_values [ preset_line ] [ 0 ] ) ) {
break ;
2015-11-03 10:04:22 +00:00
}
2015-11-03 13:46:23 +00:00
preset_line + + ;
2015-11-03 10:04:22 +00:00
}
}
2015-11-03 13:46:23 +00:00
if ( preset_values [ preset_line ] [ 0 ] ! = NULL ) {
fprintf ( stderr , " Using preset %s: " , value ) ;
// Loop all the name and value pairs and push to the config parser
for ( int preset_value = 1 ; preset_values [ preset_line ] [ preset_value ] ! = NULL ; preset_value + = 2 ) {
fprintf ( stderr , " --%s=%s " , preset_values [ preset_line ] [ preset_value ] , preset_values [ preset_line ] [ preset_value + 1 ] ) ;
kvz_config_parse ( cfg , preset_values [ preset_line ] [ preset_value ] , preset_values [ preset_line ] [ preset_value + 1 ] ) ;
}
fprintf ( stderr , " \n " ) ;
} else {
2015-11-03 10:04:22 +00:00
fprintf ( stderr , " Input error: unknown preset \" %s \" \n " , value ) ;
return 0 ;
}
}
2015-11-05 11:59:30 +00:00
else if OPT ( " mv-rdo " )
cfg - > mv_rdo = atobool ( value ) ;
2014-02-03 20:58:23 +00:00
else
return 0 ;
# undef OPT
2015-06-29 12:50:15 +00:00
return 1 ;
2014-02-03 20:58:23 +00:00
}
2014-03-10 13:53:23 +00:00
/**
2015-06-29 12:50:15 +00:00
* \ brief Check that configuration is sensible .
2014-03-10 13:53:23 +00:00
*
2015-06-29 12:50:15 +00:00
* \ param cfg config to check
* \ return 1 if the config is ok , otherwise 1
2014-03-10 13:53:23 +00:00
*/
2015-08-26 08:50:27 +00:00
int kvz_config_validate ( const kvz_config * const cfg )
2014-03-10 13:53:23 +00:00
{
2015-06-29 12:50:15 +00:00
int error = 0 ;
if ( cfg - > width < = 0 ) {
2015-07-15 08:37:37 +00:00
fprintf ( stderr , " Input error: width must be positive \n " ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
}
2015-07-15 08:37:37 +00:00
if ( cfg - > height < = 0 ) {
fprintf ( stderr , " Input error: height must be positive \n " ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
}
2015-07-15 08:37:37 +00:00
if ( cfg - > width % 2 ! = 0 ) {
fprintf ( stderr , " Input error: width must be a multiple of two \n " ) ;
error = 1 ;
}
if ( cfg - > height % 2 ! = 0 ) {
fprintf ( stderr , " Input error: height must be a multiple of two \n " ) ;
error = 1 ;
}
if ( cfg - > framerate < = 0.0 ) {
fprintf ( stderr , " Input error: --input-fps must be positive \n " ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
}
if ( cfg - > gop_len & &
cfg - > intra_period & &
cfg - > intra_period % cfg - > gop_len ! = 0 ) {
fprintf ( stderr ,
" Input error: intra period (%d) not a multiple of gop length (%d) \n " ,
cfg - > intra_period ,
cfg - > gop_len ) ;
error = 1 ;
}
if ( cfg - > ref_frames < 1 | | cfg - > ref_frames > = MAX_REF_PIC_COUNT ) {
fprintf ( stderr , " Input error: --ref out of range [1..%d] \n " , MAX_REF_PIC_COUNT - 1 ) ;
error = 1 ;
}
if ( cfg - > deblock_beta < - 6 | | cfg - > deblock_beta > 6 ) {
fprintf ( stderr , " Input error: deblock beta parameter out of range [-6..6] \n " ) ;
error = 1 ;
}
if ( cfg - > deblock_tc < - 6 | | cfg - > deblock_tc > 6 ) {
fprintf ( stderr , " Input error: deblock tc parameter out of range [-6..6] \n " ) ;
error = 1 ;
}
2015-10-04 23:28:10 +00:00
if ( cfg - > rdo < 0 | | cfg - > rdo > 3 ) {
fprintf ( stderr , " Input error: --rd parameter out of range [0..3] \n " ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
}
if ( cfg - > tr_depth_intra < 0 | | cfg - > tr_depth_intra > 4 ) {
// range is 0 .. CtbLog2SizeY - Log2MinTrafoSize
fprintf ( stderr , " Input error: --tr-depth-intra is out of range [0..4] \n " ) ;
error = 1 ;
}
if ( cfg - > fme_level ! = 0 & & cfg - > fme_level ! = 1 ) {
fprintf ( stderr , " Input error: invalid --subme parameter (must be 0 or 1) \n " ) ;
error = 1 ;
}
if ( cfg - > vui . chroma_loc < 0 | | cfg - > vui . chroma_loc > 5 ) {
fprintf ( stderr , " Input error: --chromaloc parameter out of range [0..5] \n " ) ;
error = 1 ;
}
if ( cfg - > owf < - 1 ) {
fprintf ( stderr , " Input error: --owf must be nonnegative or -1 \n " ) ;
error = 1 ;
}
if ( cfg - > target_bitrate < 0 ) {
fprintf ( stderr , " Input error: --bitrate must be nonnegative \n " ) ;
error = 1 ;
}
if ( ! WITHIN ( cfg - > pu_depth_inter . min , PU_DEPTH_INTER_MIN , PU_DEPTH_INTER_MAX ) | |
! WITHIN ( cfg - > pu_depth_inter . max , PU_DEPTH_INTER_MIN , PU_DEPTH_INTER_MAX ) )
{
fprintf ( stderr , " Input error: illegal value for --pu-depth-inter (%d-%d) \n " ,
cfg - > pu_depth_inter . min , cfg - > pu_depth_inter . max ) ;
error = 1 ;
} else if ( cfg - > pu_depth_inter . min > cfg - > pu_depth_inter . max ) {
fprintf ( stderr , " Input error: Inter PU depth min (%d) > max (%d) \n " ,
cfg - > pu_depth_inter . min , cfg - > pu_depth_inter . max ) ;
error = 1 ;
}
if ( ! WITHIN ( cfg - > pu_depth_intra . min , PU_DEPTH_INTRA_MIN , PU_DEPTH_INTRA_MAX ) | |
! WITHIN ( cfg - > pu_depth_intra . max , PU_DEPTH_INTRA_MIN , PU_DEPTH_INTRA_MAX ) )
{
fprintf ( stderr , " Input error: illegal value for --pu-depth-intra (%d-%d) \n " ,
cfg - > pu_depth_intra . min , cfg - > pu_depth_intra . max ) ;
error = 1 ;
} else if ( cfg - > pu_depth_intra . min > cfg - > pu_depth_intra . max ) {
fprintf ( stderr , " Input error: Intra PU depth min (%d) > max (%d) \n " ,
cfg - > pu_depth_intra . min , cfg - > pu_depth_intra . max ) ;
error = 1 ;
2014-03-10 13:53:23 +00:00
}
2015-06-29 12:50:15 +00:00
// Tile separation should be at round position in terms of LCU, should be monotonic, and should not start by 0
2014-04-02 08:38:03 +00:00
if ( cfg - > tiles_width_split ) {
int i ;
int32_t prev_tile_split = 0 ;
for ( i = 0 ; i < cfg - > tiles_width_count ; + + i ) {
if ( cfg - > tiles_width_split [ i ] < = prev_tile_split ) {
fprintf ( stderr , " Input error: tile separations in width should be strictly monotonic (%d <= %d) \n " , cfg - > tiles_width_split [ i ] , prev_tile_split ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
break ;
2014-04-02 08:38:03 +00:00
}
if ( ( cfg - > tiles_width_split [ i ] % LCU_WIDTH ) ! = 0 ) {
fprintf ( stderr , " Input error: tile separation in width %d (at %d) is not at a multiple of LCU_WIDTH (%d) \n " , i , cfg - > tiles_width_split [ i ] , LCU_WIDTH ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
break ;
2014-04-02 08:38:03 +00:00
}
prev_tile_split = cfg - > tiles_width_split [ i ] ;
}
if ( cfg - > tiles_width_split [ cfg - > tiles_width_count - 1 ] > = cfg - > width ) {
fprintf ( stderr , " Input error: last x tile separation in width (%d) should smaller than image width (%d) \n " , cfg - > tiles_width_split [ cfg - > tiles_width_count - 1 ] , cfg - > width ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
2014-04-02 08:38:03 +00:00
}
}
2015-06-29 12:50:15 +00:00
2014-04-02 08:38:03 +00:00
if ( cfg - > tiles_height_split ) {
int i ;
int32_t prev_tile_split = 0 ;
for ( i = 0 ; i < cfg - > tiles_height_count ; + + i ) {
if ( cfg - > tiles_height_split [ i ] < = prev_tile_split ) {
fprintf ( stderr , " Input error: tile separations in height should be strictly monotonic (%d <= %d) \n " , cfg - > tiles_height_split [ i ] , prev_tile_split ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
break ;
2014-04-02 08:38:03 +00:00
}
if ( ( cfg - > tiles_height_split [ i ] % LCU_WIDTH ) ! = 0 ) {
fprintf ( stderr , " Input error: tile separation in height %d (at %d) is not at a multiple of LCU_WIDTH (%d) \n " , i , cfg - > tiles_height_split [ i ] , LCU_WIDTH ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
break ;
2014-04-02 08:38:03 +00:00
}
prev_tile_split = cfg - > tiles_height_split [ i ] ;
}
2015-06-29 12:50:15 +00:00
2014-04-02 08:38:03 +00:00
if ( cfg - > tiles_height_split [ cfg - > tiles_height_count - 1 ] > = cfg - > height ) {
fprintf ( stderr , " Input error: last tile separation in height (%d) should smaller than image height (%d) \n " , cfg - > tiles_height_split [ cfg - > tiles_height_count - 1 ] , cfg - > height ) ;
2015-06-29 12:50:15 +00:00
error = 1 ;
2014-04-02 08:38:03 +00:00
}
}
2015-06-29 12:50:15 +00:00
return ! error ;
2014-03-10 13:53:23 +00:00
}