hb_job_t * job;
x264_t * x264;
x264_picture_t pic_in;
- uint8_t *x264_allocated_pic;
+ uint8_t * grey_data;
uint32_t frames_in;
uint32_t frames_out;
x264_param_default( ¶m );
- /* Default weightp to off for baseline,
- overridable through x264 option strings. */
- if( job->x264opts != NULL && *job->x264opts != '\0' )
- {
- char *x264opts, *x264opts_start;
-
- x264opts = x264opts_start = strdup(job->x264opts);
-
- while( x264opts_start && *x264opts )
- {
- char *name = x264opts;
- char *value;
-
- x264opts += strcspn( x264opts, ":" );
- if( *x264opts )
- {
- *x264opts = 0;
- x264opts++;
- }
-
- value = strchr( name, '=' );
- if( value )
- {
- *value = 0;
- value++;
- }
-
- if( !( strcmp( name, "bframes" ) ) )
- {
- if( atoi( value ) == 0 )
- {
- param.analyse.i_weighted_pred = X264_WEIGHTP_NONE;
- hb_log("encx264: no bframes, disabling weight-p unless told otherwise");
- }
- }
- }
- }
-
- /* Temporary hack to use old b-pyramid default */
- param.i_bframe_pyramid = 0;
-
/* Enable metrics */
param.analyse.b_psnr = 1;
param.analyse.b_ssim = 1;
+
+ /* QuickTime has trouble with very low QPs (resulting in visual artifacts).
+ * Known to affect QuickTime 7, QuickTime X and iTunes.
+ * Testing shows that a qpmin of 3 works.
+ */
+ param.rc.i_qp_min = 3;
param.i_threads = ( hb_get_cpu_count() * 3 / 2 );
param.i_width = job->width;
param.i_height = job->height;
param.i_fps_num = job->vrate;
param.i_fps_den = job->vrate_base;
- param.i_timebase_num = 1;
- param.i_timebase_den = 90000;
+ if ( job->cfr == 1 )
+ {
+ param.i_timebase_num = 0;
+ param.i_timebase_den = 0;
+ param.b_vfr_input = 0;
+ }
+ else
+ {
+ param.i_timebase_num = 1;
+ param.i_timebase_den = 90000;
+ }
/* Disable annexb. Inserts size into nal header instead of start code */
param.b_annexb = 0;
we still want the same keyframe intervals as the 1st pass,
so the 1st pass stats won't conflict on frame decisions. */
hb_interjob_t * interjob = hb_interjob_get( job->h );
- param.i_keyint_min = ( ( (double)interjob->vrate / (double)interjob->vrate_base ) + 0.5 );
- param.i_keyint_max = ( ( 10 * (double)interjob->vrate / (double)interjob->vrate_base ) + 0.5 );
+ param.i_keyint_max = 10 * (int)( (double)interjob->vrate / (double)interjob->vrate_base + 0.5 );
}
else
{
/* adjust +0.5 for when fps has remainder to bump
{ 23.976, 29.976, 59.94 } to { 24, 30, 60 } */
- param.i_keyint_min = ( ( (double)job->vrate / (double)job->vrate_base ) + 0.5 );
- param.i_keyint_max = ( ( 10 * (double)job->vrate / (double)job->vrate_base ) + 0.5 );
+ param.i_keyint_max = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 );
}
}
param.i_log_level = X264_LOG_INFO;
- if( job->h264_level )
- {
- param.b_cabac = 0;
- param.i_level_idc = job->h264_level;
- hb_log( "encx264: encoding at level %i",
- param.i_level_idc );
- }
/*
This section passes the string x264opts to libx264 for parsing into
value++;
}
- if( !( strcmp( name, "b-pyramid" ) ) )
- {
- if( value == NULL || !strcmp( value, "1" ) )
- {
- value = "normal";
- }
- else if( !strcmp( value, "0" ) )
- {
- value = "none";
- }
- }
-
/* Here's where the strings are passed to libx264 for parsing. */
ret = x264_param_parse( ¶m, name, value );
job->areBframes = 0;
}
- if( param.i_keyint_min != 25 || param.i_keyint_max != 250 )
- hb_log("encx264: keyint-min: %i, keyint-max: %i", param.i_keyint_min, param.i_keyint_max);
+ if( param.i_keyint_min != X264_KEYINT_MIN_AUTO || param.i_keyint_max != 250 )
+ {
+ int min_auto;
+
+ if ( param.i_fps_num / param.i_fps_den < param.i_keyint_max / 10 )
+ min_auto = param.i_fps_num / param.i_fps_den;
+ else
+ min_auto = param.i_keyint_max / 10;
+
+ char min[40], max[40];
+ param.i_keyint_min == X264_KEYINT_MIN_AUTO ?
+ snprintf( min, 40, "auto (%d)", min_auto ) :
+ snprintf( min, 40, "%d", param.i_keyint_min );
+
+ param.i_keyint_max == X264_KEYINT_MAX_INFINITE ?
+ snprintf( max, 40, "infinite" ) :
+ snprintf( max, 40, "%d", param.i_keyint_max );
+
+ hb_log( "encx264: min-keyint: %s, keyint: %s", min, max );
+ }
/* set up the VUI color model & gamma to match what the COLR atom
* set in muxmp4.c says. See libhb/muxmp4.c for notes. */
memcpy(w->config->h264.pps, nal[1].p_payload + 4, nal[1].i_payload - 4);
w->config->h264.pps_length = nal[1].i_payload - 4;
- x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
- job->width, job->height );
+ x264_picture_init( &pv->pic_in );
+ pv->pic_in.img.i_csp = X264_CSP_I420;
+ pv->pic_in.img.i_plane = 3;
+ pv->pic_in.img.i_stride[0] = job->width;
pv->pic_in.img.i_stride[2] = pv->pic_in.img.i_stride[1] = ( ( job->width + 1 ) >> 1 );
- pv->x264_allocated_pic = pv->pic_in.img.plane[0];
+
+ if( job->grayscale )
+ {
+ int uvsize = ( (job->width + 1) >> 1 ) * ( (job->height + 1) >> 1 );
+ pv->grey_data = malloc( uvsize );
+ memset( pv->grey_data, 0x80, uvsize );
+ pv->pic_in.img.plane[1] = pv->pic_in.img.plane[2] = pv->grey_data;
+ }
return 0;
}
hb_log( "encx264: %u frames had to be split (%u in, %u out)",
pv->frames_split, pv->frames_in, pv->frames_out );
}
- /*
- * Patch the x264 allocated data back in so that x264 can free it
- * we have been using our own buffers during the encode to avoid copying.
- */
- pv->pic_in.img.plane[0] = pv->x264_allocated_pic;
- x264_picture_clean( &pv->pic_in );
+ free( pv->grey_data );
x264_encoder_close( pv->x264 );
free( pv );
w->private_data = NULL;
continue;
}
- if( job->mux & HB_MUX_AVI )
- {
- if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
- {
- buf->frametype = HB_FRAME_KEY;
- }
- buf->size += size;
- continue;
- }
-
/* H.264 in .mp4 or .mkv */
switch( nal[i].i_type )
{
pv->pic_in.img.plane[0] = in->data;
int uvsize = ( (job->width + 1) >> 1 ) * ( (job->height + 1) >> 1 );
- if( job->grayscale )
- {
- /* XXX x264 has currently no option for grayscale encoding */
- memset( pv->pic_in.img.plane[1], 0x80, uvsize );
- memset( pv->pic_in.img.plane[2], 0x80, uvsize );
- }
- else
+ if( !job->grayscale )
{
/* Point x264 at our buffers (Y)UV data */
pv->pic_in.img.plane[1] = in->data + job->width * job->height;
{
pv->pic_in.i_type = X264_TYPE_AUTO;
}
- pv->pic_in.i_qpplus1 = 0;
/* XXX this is temporary debugging code to check that the upstream
* modules (render & sync) have generated a continuous, self-consistent
x264_nal_t *nal;
hb_buffer_t *last_buf = NULL;
- while (1)
+ while ( x264_encoder_delayed_frames( pv->x264 ) )
{
x264_encoder_encode( pv->x264, &nal, &i_nal, NULL, &pic_out );
- if ( i_nal <= 0 )
+ if ( i_nal == 0 )
+ continue;
+ if ( i_nal < 0 )
break;
hb_buffer_t *buf = nal_encode( w, &pic_out, i_nal, nal );