common.c 29.2 KB
Newer Older
Laurent Aimar's avatar
Laurent Aimar committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*****************************************************************************
 * common.c: h264 library
 *****************************************************************************
 * Copyright (C) 2003 Laurent Aimar
 * $Id: common.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
26
#include <stdarg.h>
Laurent Aimar's avatar
Laurent Aimar committed
27 28 29 30 31 32 33 34

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#include "common.h"
#include "cpu.h"

35 36
static void x264_log_default( void *, int, const char *, va_list );

Laurent Aimar's avatar
Laurent Aimar committed
37 38 39 40 41 42 43 44 45 46
/****************************************************************************
 * x264_param_default:
 ****************************************************************************/
void    x264_param_default( x264_param_t *param )
{
    /* */
    memset( param, 0, sizeof( x264_param_t ) );

    /* CPU autodetect */
    param->cpu = x264_cpu_detect();
Loren Merritt's avatar
Loren Merritt committed
47
    param->i_threads = 1;
Loren Merritt's avatar
Loren Merritt committed
48
    param->b_deterministic = 1;
Laurent Aimar's avatar
Laurent Aimar committed
49 50 51 52 53 54 55

    /* Video properties */
    param->i_csp           = X264_CSP_I420;
    param->i_width         = 0;
    param->i_height        = 0;
    param->vui.i_sar_width = 0;
    param->vui.i_sar_height= 0;
56 57 58 59 60 61 62
    param->vui.i_overscan  = 0;  /* undef */
    param->vui.i_vidformat = 5;  /* undef */
    param->vui.b_fullrange = 0;  /* off */
    param->vui.i_colorprim = 2;  /* undef */
    param->vui.i_transfer  = 2;  /* undef */
    param->vui.i_colmatrix = 2;  /* undef */
    param->vui.i_chroma_loc= 0;  /* left center */
Måns Rullgård's avatar
Måns Rullgård committed
63 64
    param->i_fps_num       = 25;
    param->i_fps_den       = 1;
Loren Merritt's avatar
Loren Merritt committed
65
    param->i_level_idc     = 51; /* as close to "unrestricted" as we can get */
Laurent Aimar's avatar
Laurent Aimar committed
66 67 68

    /* Encoder parameters */
    param->i_frame_reference = 1;
69
    param->i_keyint_max = 250;
70
    param->i_keyint_min = 25;
Laurent Aimar's avatar
Laurent Aimar committed
71
    param->i_bframe = 0;
72
    param->i_scenecut_threshold = 40;
73 74
    param->b_bframe_adaptive = 1;
    param->i_bframe_bias = 0;
75
    param->b_bframe_pyramid = 0;
Laurent Aimar's avatar
Laurent Aimar committed
76 77 78 79 80

    param->b_deblocking_filter = 1;
    param->i_deblocking_filter_alphac0 = 0;
    param->i_deblocking_filter_beta = 0;

81
    param->b_cabac = 1;
82
    param->i_cabac_init_idc = 0;
Laurent Aimar's avatar
Laurent Aimar committed
83

84
    param->rc.i_rc_method = X264_RC_CQP;
85
    param->rc.i_bitrate = 0;
Loren Merritt's avatar
Loren Merritt committed
86 87 88 89
    param->rc.f_rate_tolerance = 1.0;
    param->rc.i_vbv_max_bitrate = 0;
    param->rc.i_vbv_buffer_size = 0;
    param->rc.f_vbv_buffer_init = 0.9;
90
    param->rc.i_qp_constant = 26;
Loren Merritt's avatar
Loren Merritt committed
91
    param->rc.f_rf_constant = 0;
Loren Merritt's avatar
Loren Merritt committed
92
    param->rc.i_qp_min = 10;
93 94
    param->rc.i_qp_max = 51;
    param->rc.i_qp_step = 4;
Loren Merritt's avatar
Loren Merritt committed
95
    param->rc.f_ip_factor = 1.4;
96
    param->rc.f_pb_factor = 1.3;
97 98 99 100 101

    param->rc.b_stat_write = 0;
    param->rc.psz_stat_out = "x264_2pass.log";
    param->rc.b_stat_read = 0;
    param->rc.psz_stat_in = "x264_2pass.log";
102
    param->rc.psz_rc_eq = "blurCplx^(1-qComp)";
103 104
    param->rc.f_qcompress = 0.6;
    param->rc.f_qblur = 0.5;
Loren Merritt's avatar
Loren Merritt committed
105
    param->rc.f_complexity_blur = 20;
Loren Merritt's avatar
Loren Merritt committed
106
    param->rc.i_zones = 0;
Laurent Aimar's avatar
Laurent Aimar committed
107

108 109 110
    /* Log */
    param->pf_log = x264_log_default;
    param->p_log_private = NULL;
111
    param->i_log_level = X264_LOG_INFO;
112 113

    /* */
114
    param->analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8;
115 116
    param->analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8
                         | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_BSUB16x16;
117
    param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
118 119
    param->analyse.i_me_method = X264_ME_HEX;
    param->analyse.i_me_range = 16;
120
    param->analyse.i_subpel_refine = 5;
Loren Merritt's avatar
Loren Merritt committed
121
    param->analyse.b_chroma_me = 1;
Loren Merritt's avatar
Loren Merritt committed
122
    param->analyse.i_mv_range_thread = -1;
123
    param->analyse.i_mv_range = -1; // set from level_idc
124
    param->analyse.i_direct_8x8_inference = -1; // set from level_idc
125
    param->analyse.i_chroma_qp_offset = 0;
Loren Merritt's avatar
Loren Merritt committed
126
    param->analyse.b_fast_pskip = 1;
127
    param->analyse.b_dct_decimate = 1;
128 129
    param->analyse.i_luma_deadzone[0] = 21;
    param->analyse.i_luma_deadzone[1] = 11;
130
    param->analyse.b_psnr = 1;
131
    param->analyse.b_ssim = 1;
132

Loren Merritt's avatar
Loren Merritt committed
133 134 135 136 137 138 139 140
    param->i_cqm_preset = X264_CQM_FLAT;
    memset( param->cqm_4iy, 16, 16 );
    memset( param->cqm_4ic, 16, 16 );
    memset( param->cqm_4py, 16, 16 );
    memset( param->cqm_4pc, 16, 16 );
    memset( param->cqm_8iy, 16, 64 );
    memset( param->cqm_8py, 16, 64 );

141
    param->b_repeat_headers = 1;
142
    param->b_aud = 0;
Laurent Aimar's avatar
Laurent Aimar committed
143 144
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
static int parse_enum( const char *arg, const char * const *names, int *dst )
{
    int i;
    for( i = 0; names[i]; i++ )
        if( !strcmp( arg, names[i] ) )
        {
            *dst = i;
            return 0;
        }
    return -1;
}

static int parse_cqm( const char *str, uint8_t *cqm, int length )
{
    int i = 0;
    do {
        int coef;
        if( !sscanf( str, "%d", &coef ) || coef < 1 || coef > 255 )
            return -1;
        cqm[i++] = coef;
    } while( i < length && (str = strchr( str, ',' )) && str++ );
    return (i == length) ? 0 : -1;
}

169
static int x264_atobool( const char *str, int *b_error )
170 171 172 173 174 175 176 177 178
{
    if( !strcmp(str, "1") || 
        !strcmp(str, "true") || 
        !strcmp(str, "yes") )
        return 1;
    if( !strcmp(str, "0") || 
        !strcmp(str, "false") || 
        !strcmp(str, "no") )
        return 0;
179 180 181 182 183 184 185 186 187 188 189
    *b_error = 1;
    return 0;
}

static int x264_atoi( const char *str, int *b_error )
{
    char *end;
    int v = strtol( str, &end, 0 );
    if( end == str || *end != '\0' )
        *b_error = 1;
    return v;
190 191
}

192 193 194 195 196 197 198 199 200 201 202 203
static double x264_atof( const char *str, int *b_error )
{
    char *end;
    double v = strtod( str, &end );
    if( end == str || *end != '\0' )
        *b_error = 1;
    return v;
}

#define atobool(str) ( name_was_bool = 1, x264_atobool( str, &b_error ) )
#define atoi(str) x264_atoi( str, &b_error )
#define atof(str) x264_atof( str, &b_error )
204 205 206

int x264_param_parse( x264_param_t *p, const char *name, const char *value )
{
207
    char *name_buf = NULL;
208
    int b_error = 0;
209 210
    int name_was_bool;
    int value_was_null = !value;
211 212 213 214 215
    int i;

    if( !name )
        return X264_PARAM_BAD_NAME;
    if( !value )
216
        value = "true";
217 218 219 220

    if( value[0] == '=' )
        value++;

221 222 223 224 225 226 227 228 229
    if( strchr( name, '_' ) ) // s/_/-/g
    {
        char *p;
        name_buf = strdup(name);
        while( (p = strchr( name_buf, '_' )) )
            *p = '-';
        name = name_buf;
    }

230 231 232 233 234 235
    if( (!strncmp( name, "no-", 3 ) && (i = 3)) ||
        (!strncmp( name, "no", 2 ) && (i = 2)) )
    {
        name += i;
        value = atobool(value) ? "false" : "true";
    }
236
    name_was_bool = 0;
237 238

#define OPT(STR) else if( !strcmp( name, STR ) )
239
#define OPT2(STR0, STR1) else if( !strcmp( name, STR0 ) || !strcmp( name, STR1 ) )
240 241 242 243
    if(0);
    OPT("asm")
        p->cpu = atobool(value) ? x264_cpu_detect() : 0;
    OPT("threads")
244 245 246 247 248 249
    {
        if( !strcmp(value, "auto") )
            p->i_threads = 0;
        else
            p->i_threads = atoi(value);
    }
Loren Merritt's avatar
Loren Merritt committed
250 251
    OPT2("deterministic", "n-deterministic")
        p->b_deterministic = atobool(value);
252
    OPT2("level", "level-idc")
253 254 255 256 257 258 259 260 261 262 263 264 265
    {
        if( atof(value) < 6 )
            p->i_level_idc = (int)(10*atof(value)+.5);
        else
            p->i_level_idc = atoi(value);
    }
    OPT("sar")
    {
        b_error = ( 2 != sscanf( value, "%d:%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) &&
                    2 != sscanf( value, "%d/%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) );
    }
    OPT("overscan")
        b_error |= parse_enum( value, x264_overscan_names, &p->vui.i_overscan );
266
    OPT("videoformat")
267 268 269
        b_error |= parse_enum( value, x264_vidformat_names, &p->vui.i_vidformat );
    OPT("fullrange")
        b_error |= parse_enum( value, x264_fullrange_names, &p->vui.b_fullrange );
270
    OPT("colorprim")
271 272 273
        b_error |= parse_enum( value, x264_colorprim_names, &p->vui.i_colorprim );
    OPT("transfer")
        b_error |= parse_enum( value, x264_transfer_names, &p->vui.i_transfer );
274
    OPT("colormatrix")
275 276 277 278 279 280 281 282 283 284
        b_error |= parse_enum( value, x264_colmatrix_names, &p->vui.i_colmatrix );
    OPT("chromaloc")
    {
        p->vui.i_chroma_loc = atoi(value);
        b_error = ( p->vui.i_chroma_loc < 0 || p->vui.i_chroma_loc > 5 );
    }
    OPT("fps")
    {
        if( sscanf( value, "%d/%d", &p->i_fps_num, &p->i_fps_den ) == 2 )
            ;
285
        else
286
        {
287
            float fps = atof(value);
288 289 290 291
            p->i_fps_num = (int)(fps * 1000 + .5);
            p->i_fps_den = 1000;
        }
    }
292
    OPT2("ref", "frameref")
293 294 295 296 297 298 299
        p->i_frame_reference = atoi(value);
    OPT("keyint")
    {
        p->i_keyint_max = atoi(value);
        if( p->i_keyint_min > p->i_keyint_max )
            p->i_keyint_min = p->i_keyint_max;
    }
300
    OPT2("min-keyint", "keyint-min")
301 302 303 304 305 306 307
    {
        p->i_keyint_min = atoi(value);
        if( p->i_keyint_max < p->i_keyint_min )
            p->i_keyint_max = p->i_keyint_min;
    }
    OPT("scenecut")
        p->i_scenecut_threshold = atoi(value);
Loren Merritt's avatar
Loren Merritt committed
308 309
    OPT("pre-scenecut")
        p->b_pre_scenecut = atobool(value);
310 311 312 313 314 315 316 317 318
    OPT("bframes")
        p->i_bframe = atoi(value);
    OPT("b-adapt")
        p->b_bframe_adaptive = atobool(value);
    OPT("b-bias")
        p->i_bframe_bias = atoi(value);
    OPT("b-pyramid")
        p->b_bframe_pyramid = atobool(value);
    OPT("nf")
319
        p->b_deblocking_filter = !atobool(value);
320
    OPT2("filter", "deblock")
321
    {
322 323
        if( 2 == sscanf( value, "%d:%d", &p->i_deblocking_filter_alphac0, &p->i_deblocking_filter_beta ) ||
            2 == sscanf( value, "%d,%d", &p->i_deblocking_filter_alphac0, &p->i_deblocking_filter_beta ) )
324 325
        {
            p->b_deblocking_filter = 1;
326 327 328 329 330
        }
        else if( sscanf( value, "%d", &p->i_deblocking_filter_alphac0 ) )
        {
            p->b_deblocking_filter = 1;
            p->i_deblocking_filter_beta = p->i_deblocking_filter_alphac0;
331 332 333 334 335 336 337 338
        }
        else
            p->b_deblocking_filter = atobool(value);
    }
    OPT("cabac")
        p->b_cabac = atobool(value);
    OPT("cabac-idc")
        p->i_cabac_init_idc = atoi(value);
339 340
    OPT("interlaced")
        p->b_interlaced = atobool(value);
341 342 343 344 345 346 347
    OPT("cqm")
    {
        if( strstr( value, "flat" ) )
            p->i_cqm_preset = X264_CQM_FLAT;
        else if( strstr( value, "jvt" ) )
            p->i_cqm_preset = X264_CQM_JVT;
        else
348
            p->psz_cqm_file = strdup(value);
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    }
    OPT("cqmfile")
        p->psz_cqm_file = strdup(value);
    OPT("cqm4")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4iy, 16 );
        b_error |= parse_cqm( value, p->cqm_4ic, 16 );
        b_error |= parse_cqm( value, p->cqm_4py, 16 );
        b_error |= parse_cqm( value, p->cqm_4pc, 16 );
    }
    OPT("cqm8")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_8iy, 64 );
        b_error |= parse_cqm( value, p->cqm_8py, 64 );
    }
    OPT("cqm4i")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4iy, 16 );
        b_error |= parse_cqm( value, p->cqm_4ic, 16 );
    }
    OPT("cqm4p")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4py, 16 );
        b_error |= parse_cqm( value, p->cqm_4pc, 16 );
    }
    OPT("cqm4iy")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4iy, 16 );
    }
    OPT("cqm4ic")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4ic, 16 );
    }
    OPT("cqm4py")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4py, 16 );
    }
    OPT("cqm4pc")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_4pc, 16 );
    }
    OPT("cqm8i")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_8iy, 64 );
    }
    OPT("cqm8p")
    {
        p->i_cqm_preset = X264_CQM_CUSTOM;
        b_error |= parse_cqm( value, p->cqm_8py, 64 );
    }
    OPT("log")
        p->i_log_level = atoi(value);
410 411 412 413 414
#ifdef VISUALIZE
    OPT("visualize")
        p->b_visualize = atobool(value);
#endif
    OPT2("analyse", "partitions")
415 416 417 418 419 420 421 422 423 424 425 426 427
    {
        p->analyse.inter = 0;
        if( strstr( value, "none" ) )  p->analyse.inter =  0;
        if( strstr( value, "all" ) )   p->analyse.inter = ~0;

        if( strstr( value, "i4x4" ) )  p->analyse.inter |= X264_ANALYSE_I4x4;
        if( strstr( value, "i8x8" ) )  p->analyse.inter |= X264_ANALYSE_I8x8;
        if( strstr( value, "p8x8" ) )  p->analyse.inter |= X264_ANALYSE_PSUB16x16;
        if( strstr( value, "p4x4" ) )  p->analyse.inter |= X264_ANALYSE_PSUB8x8;
        if( strstr( value, "b8x8" ) )  p->analyse.inter |= X264_ANALYSE_BSUB16x16;
    }
    OPT("8x8dct")
        p->analyse.b_transform_8x8 = atobool(value);
428
    OPT2("weightb", "weight-b")
429
        p->analyse.b_weighted_bipred = atobool(value);
430
    OPT2("direct", "direct-pred")
431
        b_error |= parse_enum( value, x264_direct_pred_names, &p->analyse.i_direct_mv_pred );
432 433
    OPT("direct-8x8")
        p->analyse.i_direct_8x8_inference = atoi(value);
434 435 436 437
    OPT("chroma-qp-offset")
        p->analyse.i_chroma_qp_offset = atoi(value);
    OPT("me")
        b_error |= parse_enum( value, x264_motion_est_names, &p->analyse.i_me_method );
438
    OPT2("merange", "me-range")
439
        p->analyse.i_me_range = atoi(value);
Loren Merritt's avatar
Loren Merritt committed
440
    OPT2("mvrange", "mv-range")
441
        p->analyse.i_mv_range = atoi(value);
Loren Merritt's avatar
Loren Merritt committed
442 443
    OPT2("mvrange-thread", "mv-range-thread")
        p->analyse.i_mv_range_thread = atoi(value);
444
    OPT2("subme", "subq")
445 446 447 448 449
        p->analyse.i_subpel_refine = atoi(value);
    OPT("bime")
        p->analyse.b_bidir_me = atobool(value);
    OPT("chroma-me")
        p->analyse.b_chroma_me = atobool(value);
450
    OPT2("b-rdo", "brdo")
451 452 453 454 455 456 457 458 459
        p->analyse.b_bframe_rdo = atobool(value);
    OPT("mixed-refs")
        p->analyse.b_mixed_references = atobool(value);
    OPT("trellis")
        p->analyse.i_trellis = atoi(value);
    OPT("fast-pskip")
        p->analyse.b_fast_pskip = atobool(value);
    OPT("dct-decimate")
        p->analyse.b_dct_decimate = atobool(value);
460 461 462 463
    OPT("deadzone-inter")
        p->analyse.i_luma_deadzone[0] = atoi(value);
    OPT("deadzone-intra")
        p->analyse.i_luma_deadzone[1] = atoi(value);
464 465 466 467 468 469 470
    OPT("nr")
        p->analyse.i_noise_reduction = atoi(value);
    OPT("bitrate")
    {
        p->rc.i_bitrate = atoi(value);
        p->rc.i_rc_method = X264_RC_ABR;
    }
471
    OPT2("qp", "qp_constant")
472 473 474 475 476 477
    {
        p->rc.i_qp_constant = atoi(value);
        p->rc.i_rc_method = X264_RC_CQP;
    }
    OPT("crf")
    {
Loren Merritt's avatar
Loren Merritt committed
478
        p->rc.f_rf_constant = atof(value);
479 480
        p->rc.i_rc_method = X264_RC_CRF;
    }
481
    OPT2("qpmin", "qp-min")
482
        p->rc.i_qp_min = atoi(value);
483
    OPT2("qpmax", "qp-max")
484
        p->rc.i_qp_max = atoi(value);
485
    OPT2("qpstep", "qp-step")
486 487 488 489 490 491 492 493 494
        p->rc.i_qp_step = atoi(value);
    OPT("ratetol")
        p->rc.f_rate_tolerance = !strncmp("inf", value, 3) ? 1e9 : atof(value);
    OPT("vbv-maxrate")
        p->rc.i_vbv_max_bitrate = atoi(value);
    OPT("vbv-bufsize")
        p->rc.i_vbv_buffer_size = atoi(value);
    OPT("vbv-init")
        p->rc.f_vbv_buffer_init = atof(value);
495
    OPT2("ipratio", "ip-factor")
496
        p->rc.f_ip_factor = atof(value);
497
    OPT2("pbratio", "pb-factor")
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
        p->rc.f_pb_factor = atof(value);
    OPT("pass")
    {
        int i = x264_clip3( atoi(value), 0, 3 );
        p->rc.b_stat_write = i & 1;
        p->rc.b_stat_read = i & 2;
    }
    OPT("stats")
    {
        p->rc.psz_stat_in = strdup(value);
        p->rc.psz_stat_out = strdup(value);
    }
    OPT("rceq")
        p->rc.psz_rc_eq = strdup(value);
    OPT("qcomp")
        p->rc.f_qcompress = atof(value);
    OPT("qblur")
        p->rc.f_qblur = atof(value);
516
    OPT2("cplxblur", "cplx-blur")
517 518 519 520 521
        p->rc.f_complexity_blur = atof(value);
    OPT("zones")
        p->rc.psz_zones = strdup(value);
    OPT("psnr")
        p->analyse.b_psnr = atobool(value);
522 523
    OPT("ssim")
        p->analyse.b_ssim = atobool(value);
524 525 526 527
    OPT("aud")
        p->b_aud = atobool(value);
    OPT("sps-id")
        p->i_sps_id = atoi(value);
528 529
    OPT("global-header")
        p->b_repeat_headers = !atobool(value);
530 531 532 533 534
    OPT("repeat-headers")
        p->b_repeat_headers = atobool(value);
    else
        return X264_PARAM_BAD_NAME;
#undef OPT
535
#undef OPT2
536
#undef atobool
537 538 539 540 541
#undef atoi
#undef atof

    if( name_buf )
        free( name_buf );
542

543
    b_error |= value_was_null && !name_was_bool;
544 545 546
    return b_error ? X264_PARAM_BAD_VALUE : 0;
}

547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
/****************************************************************************
 * x264_log:
 ****************************************************************************/
void x264_log( x264_t *h, int i_level, const char *psz_fmt, ... )
{
    if( i_level <= h->param.i_log_level )
    {
        va_list arg;
        va_start( arg, psz_fmt );
        h->param.pf_log( h->param.p_log_private, i_level, psz_fmt, arg );
        va_end( arg );
    }
}

static void x264_log_default( void *p_unused, int i_level, const char *psz_fmt, va_list arg )
{
    char *psz_prefix;
    switch( i_level )
    {
        case X264_LOG_ERROR:
            psz_prefix = "error";
            break;
        case X264_LOG_WARNING:
            psz_prefix = "warning";
            break;
        case X264_LOG_INFO:
            psz_prefix = "info";
            break;
        case X264_LOG_DEBUG:
            psz_prefix = "debug";
            break;
        default:
            psz_prefix = "unknown";
            break;
    }
    fprintf( stderr, "x264 [%s]: ", psz_prefix );
    vfprintf( stderr, psz_fmt, arg );
}

Laurent Aimar's avatar
Laurent Aimar committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
/****************************************************************************
 * x264_picture_alloc:
 ****************************************************************************/
void x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height )
{
    pic->i_type = X264_TYPE_AUTO;
    pic->i_qpplus1 = 0;
    pic->img.i_csp = i_csp;
    switch( i_csp & X264_CSP_MASK )
    {
        case X264_CSP_I420:
        case X264_CSP_YV12:
            pic->img.i_plane = 3;
            pic->img.plane[0] = x264_malloc( 3 * i_width * i_height / 2 );
            pic->img.plane[1] = pic->img.plane[0] + i_width * i_height;
            pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 4;
            pic->img.i_stride[0] = i_width;
            pic->img.i_stride[1] = i_width / 2;
            pic->img.i_stride[2] = i_width / 2;
            break;

        case X264_CSP_I422:
            pic->img.i_plane = 3;
            pic->img.plane[0] = x264_malloc( 2 * i_width * i_height );
            pic->img.plane[1] = pic->img.plane[0] + i_width * i_height;
            pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 2;
            pic->img.i_stride[0] = i_width;
            pic->img.i_stride[1] = i_width / 2;
            pic->img.i_stride[2] = i_width / 2;
            break;

        case X264_CSP_I444:
            pic->img.i_plane = 3;
            pic->img.plane[0] = x264_malloc( 3 * i_width * i_height );
            pic->img.plane[1] = pic->img.plane[0] + i_width * i_height;
            pic->img.plane[2] = pic->img.plane[1] + i_width * i_height;
            pic->img.i_stride[0] = i_width;
            pic->img.i_stride[1] = i_width;
            pic->img.i_stride[2] = i_width;
            break;

        case X264_CSP_YUYV:
            pic->img.i_plane = 1;
            pic->img.plane[0] = x264_malloc( 2 * i_width * i_height );
            pic->img.i_stride[0] = 2 * i_width;
            break;

        case X264_CSP_RGB:
        case X264_CSP_BGR:
            pic->img.i_plane = 1;
            pic->img.plane[0] = x264_malloc( 3 * i_width * i_height );
            pic->img.i_stride[0] = 3 * i_width;
            break;

        case X264_CSP_BGRA:
            pic->img.i_plane = 1;
            pic->img.plane[0] = x264_malloc( 4 * i_width * i_height );
            pic->img.i_stride[0] = 4 * i_width;
            break;

        default:
            fprintf( stderr, "invalid CSP\n" );
            pic->img.i_plane = 0;
            break;
    }
}

/****************************************************************************
 * x264_picture_clean:
 ****************************************************************************/
void x264_picture_clean( x264_picture_t *pic )
{
    x264_free( pic->img.plane[0] );

    /* just to be safe */
    memset( pic, 0, sizeof( x264_picture_t ) );
}

/****************************************************************************
 * x264_nal_encode:
 ****************************************************************************/
int x264_nal_encode( void *p_data, int *pi_data, int b_annexeb, x264_nal_t *nal )
{
    uint8_t *dst = p_data;
    uint8_t *src = nal->p_payload;
    uint8_t *end = &nal->p_payload[nal->i_payload];

    int i_count = 0;

    /* FIXME this code doesn't check overflow */

    if( b_annexeb )
    {
        /* long nal start code (we always use long ones)*/
        *dst++ = 0x00;
        *dst++ = 0x00;
        *dst++ = 0x00;
        *dst++ = 0x01;
    }

    /* nal header */
    *dst++ = ( 0x00 << 7 ) | ( nal->i_ref_idc << 5 ) | nal->i_type;

    while( src < end )
    {
        if( i_count == 2 && *src <= 0x03 )
        {
            *dst++ = 0x03;
            i_count = 0;
        }
        if( *src == 0 )
        {
            i_count++;
        }
        else
        {
            i_count = 0;
        }
        *dst++ = *src++;
    }
    *pi_data = dst - (uint8_t*)p_data;

    return *pi_data;
}

/****************************************************************************
 * x264_nal_decode:
 ****************************************************************************/
int x264_nal_decode( x264_nal_t *nal, void *p_data, int i_data )
{
    uint8_t *src = p_data;
    uint8_t *end = &src[i_data];
    uint8_t *dst = nal->p_payload;

    nal->i_type    = src[0]&0x1f;
    nal->i_ref_idc = (src[0] >> 5)&0x03;

    src++;

    while( src < end )
    {
        if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00  && src[2] == 0x03 )
        {
            *dst++ = 0x00;
            *dst++ = 0x00;

            src += 3;
            continue;
        }
        *dst++ = *src++;
    }

    nal->i_payload = dst - (uint8_t*)p_data;
    return 0;
}



/****************************************************************************
 * x264_malloc:
 ****************************************************************************/
void *x264_malloc( int i_size )
{
749 750 751 752
#ifdef SYS_MACOSX
    /* Mac OS X always returns 16 bytes aligned memory */
    return malloc( i_size );
#elif defined( HAVE_MALLOC_H )
Laurent Aimar's avatar
Laurent Aimar committed
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
    return memalign( 16, i_size );
#else
    uint8_t * buf;
    uint8_t * align_buf;
    buf = (uint8_t *) malloc( i_size + 15 + sizeof( void ** ) +
              sizeof( int ) );
    align_buf = buf + 15 + sizeof( void ** ) + sizeof( int );
    align_buf -= (long) align_buf & 15;
    *( (void **) ( align_buf - sizeof( void ** ) ) ) = buf;
    *( (int *) ( align_buf - sizeof( void ** ) - sizeof( int ) ) ) = i_size;
    return align_buf;
#endif
}

/****************************************************************************
 * x264_free:
 ****************************************************************************/
void x264_free( void *p )
{
    if( p )
    {
774
#if defined( HAVE_MALLOC_H ) || defined( SYS_MACOSX )
Laurent Aimar's avatar
Laurent Aimar committed
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
        free( p );
#else
        free( *( ( ( void **) p ) - 1 ) );
#endif
    }
}

/****************************************************************************
 * x264_realloc:
 ****************************************************************************/
void *x264_realloc( void *p, int i_size )
{
#ifdef HAVE_MALLOC_H
    return realloc( p, i_size );
#else
    int       i_old_size = 0;
    uint8_t * p_new;
    if( p )
    {
        i_old_size = *( (int*) ( (uint8_t*) p ) - sizeof( void ** ) -
                         sizeof( int ) );
    }
    p_new = x264_malloc( i_size );
    if( i_old_size > 0 && i_size > 0 )
    {
        memcpy( p_new, p, ( i_old_size < i_size ) ? i_old_size : i_size );
    }
    x264_free( p );
    return p_new;
#endif
}

Loren Merritt's avatar
Loren Merritt committed
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
/****************************************************************************
 * x264_reduce_fraction:
 ****************************************************************************/
void x264_reduce_fraction( int *n, int *d )
{
    int a = *n;
    int b = *d;
    int c;
    if( !a || !b )
        return;
    c = a % b;
    while(c)
    {
	a = b;
	b = c;
	c = a % b;
    }
    *n /= b;
    *d /= b;
}

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
/****************************************************************************
 * x264_slurp_file:
 ****************************************************************************/
char *x264_slurp_file( const char *filename )
{
    int b_error = 0;
    int i_size;
    char *buf;
    FILE *fh = fopen( filename, "rb" );
    if( !fh )
        return NULL;
    b_error |= fseek( fh, 0, SEEK_END ) < 0;
    b_error |= ( i_size = ftell( fh ) ) <= 0;
    b_error |= fseek( fh, 0, SEEK_SET ) < 0;
    if( b_error )
        return NULL;
    buf = x264_malloc( i_size+2 );
    if( buf == NULL )
        return NULL;
    b_error |= fread( buf, 1, i_size, fh ) != i_size;
    if( buf[i_size-1] != '\n' )
        buf[i_size++] = '\n';
    buf[i_size] = 0;
    fclose( fh );
    if( b_error )
    {
        x264_free( buf );
        return NULL;
    }
    return buf;
}
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887

/****************************************************************************
 * x264_param2string:
 ****************************************************************************/
char *x264_param2string( x264_param_t *p, int b_res )
{
    char *buf = x264_malloc( 1000 );
    char *s = buf;

    if( b_res )
    {
        s += sprintf( s, "%dx%d ", p->i_width, p->i_height );
        s += sprintf( s, "fps=%d/%d ", p->i_fps_num, p->i_fps_den );
    }

    s += sprintf( s, "cabac=%d", p->b_cabac );
    s += sprintf( s, " ref=%d", p->i_frame_reference );
    s += sprintf( s, " deblock=%d:%d:%d", p->b_deblocking_filter,
                  p->i_deblocking_filter_alphac0, p->i_deblocking_filter_beta );
    s += sprintf( s, " analyse=%#x:%#x", p->analyse.intra, p->analyse.inter );
    s += sprintf( s, " me=%s", x264_motion_est_names[ p->analyse.i_me_method ] );
    s += sprintf( s, " subme=%d", p->analyse.i_subpel_refine );
    s += sprintf( s, " brdo=%d", p->analyse.b_bframe_rdo );
    s += sprintf( s, " mixed_ref=%d", p->analyse.b_mixed_references );
    s += sprintf( s, " me_range=%d", p->analyse.i_me_range );
    s += sprintf( s, " chroma_me=%d", p->analyse.b_chroma_me );
    s += sprintf( s, " trellis=%d", p->analyse.i_trellis );
    s += sprintf( s, " 8x8dct=%d", p->analyse.b_transform_8x8 );
    s += sprintf( s, " cqm=%d", p->i_cqm_preset );
888
    s += sprintf( s, " deadzone=%d,%d", p->analyse.i_luma_deadzone[0], p->analyse.i_luma_deadzone[1] );
889
    s += sprintf( s, " chroma_qp_offset=%d", p->analyse.i_chroma_qp_offset );
Loren Merritt's avatar
Loren Merritt committed
890
    s += sprintf( s, " threads=%d", p->i_threads );
891
    s += sprintf( s, " nr=%d", p->analyse.i_noise_reduction );
892
    s += sprintf( s, " decimate=%d", p->analyse.b_dct_decimate );
893
    s += sprintf( s, " mbaff=%d", p->b_interlaced );
894 895 896 897

    s += sprintf( s, " bframes=%d", p->i_bframe );
    if( p->i_bframe )
    {
898
        s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d bime=%d",
899
                      p->b_bframe_pyramid, p->b_bframe_adaptive, p->i_bframe_bias,
900 901
                      p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred,
                      p->analyse.b_bidir_me );
902 903
    }

Loren Merritt's avatar
Loren Merritt committed
904 905 906
    s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d%s",
                  p->i_keyint_max, p->i_keyint_min, p->i_scenecut_threshold,
                  p->b_pre_scenecut ? "(pre)" : "" );
907

908 909 910 911
    s += sprintf( s, " rc=%s", p->rc.i_rc_method == X264_RC_ABR ?
                               ( p->rc.b_stat_read ? "2pass" : p->rc.i_vbv_buffer_size ? "cbr" : "abr" )
                               : p->rc.i_rc_method == X264_RC_CRF ? "crf" : "cqp" );
    if( p->rc.i_rc_method == X264_RC_ABR || p->rc.i_rc_method == X264_RC_CRF )
912
    {
913
        if( p->rc.i_rc_method == X264_RC_CRF )
Loren Merritt's avatar
Loren Merritt committed
914
            s += sprintf( s, " crf=%.1f", p->rc.f_rf_constant );
915 916 917 918 919 920 921 922 923
        else
            s += sprintf( s, " bitrate=%d ratetol=%.1f",
                          p->rc.i_bitrate, p->rc.f_rate_tolerance );
        s += sprintf( s, " rceq='%s' qcomp=%.2f qpmin=%d qpmax=%d qpstep=%d",
                      p->rc.psz_rc_eq, p->rc.f_qcompress,
                      p->rc.i_qp_min, p->rc.i_qp_max, p->rc.i_qp_step );
        if( p->rc.b_stat_read )
            s += sprintf( s, " cplxblur=%.1f qblur=%.1f",
                          p->rc.f_complexity_blur, p->rc.f_qblur );
924
        if( p->rc.i_vbv_buffer_size )
925 926 927
            s += sprintf( s, " vbv_maxrate=%d vbv_bufsize=%d",
                          p->rc.i_vbv_max_bitrate, p->rc.i_vbv_buffer_size );
    }
928
    else if( p->rc.i_rc_method == X264_RC_CQP )
929
        s += sprintf( s, " qp=%d", p->rc.i_qp_constant );
930
    if( !(p->rc.i_rc_method == X264_RC_CQP && p->rc.i_qp_constant == 0) )
931 932 933 934 935 936 937 938 939 940 941
    {
        s += sprintf( s, " ip_ratio=%.2f", p->rc.f_ip_factor );
        if( p->i_bframe )
            s += sprintf( s, " pb_ratio=%.2f", p->rc.f_pb_factor );
        if( p->rc.i_zones )
            s += sprintf( s, " zones" );
    }

    return buf;
}