1 /* $Id: encx264.c,v 1.21 2005/11/04 13:09:41 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
13 int encx264Init( hb_work_object_t *, hb_job_t * );
14 int encx264Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
15 void encx264Close( hb_work_object_t * );
17 hb_work_object_t hb_encx264 =
20 "H.264/AVC encoder (libx264)",
26 struct hb_work_private_s
30 x264_picture_t pic_in;
31 x264_picture_t pic_out;
36 /***********************************************************************
37 * hb_work_encx264_init
38 ***********************************************************************
40 **********************************************************************/
41 int encx264Init( hb_work_object_t * w, hb_job_t * job )
48 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
53 memset( pv->filename, 0, 1024 );
54 hb_get_tempory_filename( job->h, pv->filename, "x264.log" );
56 x264_param_default( ¶m );
58 param.i_threads = hb_get_cpu_count();
59 param.i_width = job->width;
60 param.i_height = job->height;
61 param.i_fps_num = job->vrate;
62 param.i_fps_den = job->vrate_base;
63 param.i_keyint_max = 20 * job->vrate / job->vrate_base;
64 param.i_log_level = X264_LOG_NONE;
70 param.i_level_idc = job->h264_level;
71 hb_log( "encx264: encoding at level %i",
75 /* Slightly faster with minimal quality lost */
76 param.analyse.i_subpel_refine = 4;
78 if( job->vquality >= 0.0 && job->vquality <= 1.0 )
81 param.rc.i_qp_constant = 51 - job->vquality * 51;
82 hb_log( "encx264: encoding at constant QP %d",
83 param.rc.i_qp_constant );
89 /* no longer in x264 - see rc.i_rc_method in x264.h */
90 /* param.rc.b_cbr = 1; */
92 /* these were the only settings I could use to get accurate ending video bitrate */
93 param.rc.i_rc_method = X264_RC_CRF;
94 param.rc.i_vbv_max_bitrate = job->vbitrate;
95 param.rc.i_vbv_buffer_size = 224;
96 param.rc.i_rf_constant = 1;
98 param.rc.i_bitrate = job->vbitrate;
102 param.rc.i_rc_method = X264_RC_ABR;
103 param.rc.b_stat_write = 1;
104 param.rc.psz_stat_out = pv->filename;
107 param.rc.i_rc_method = X264_RC_ABR;
108 param.rc.b_stat_read = 1;
109 param.rc.psz_stat_in = pv->filename;
114 hb_log( "encx264: opening libx264 (pass %d)", job->pass );
115 pv->x264 = x264_encoder_open( ¶m );
117 w->config->mpeg4.length = 0;
119 x264_encoder_headers( pv->x264, &nal, &nal_count );
121 for( i = 0; i < nal_count; i++ )
123 size = sizeof( w->config->mpeg4.bytes ) - w->config->mpeg4.length;
124 x264_nal_encode( &w->config->mpeg4.bytes[w->config->mpeg4.length],
126 w->config->mpeg4.length += size;
129 x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
130 job->width, job->height );
135 void encx264Close( hb_work_object_t * w )
137 hb_work_private_t * pv = w->private_data;
138 x264_encoder_close( pv->x264 );
143 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
144 hb_buffer_t ** buf_out )
146 hb_work_private_t * pv = w->private_data;
147 hb_job_t * job = pv->job;
148 hb_buffer_t * in = *buf_in, * buf;
153 /* XXX avoid this memcpy ? */
154 memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
157 /* XXX x264 has currently no option for grayscale encoding */
158 memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
159 memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
163 memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
164 job->width * job->height / 4 );
165 memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
166 job->height / 4, job->width * job->height / 4 );
169 pv->pic_in.i_type = X264_TYPE_AUTO;
170 pv->pic_in.i_qpplus1 = 0;
172 x264_encoder_encode( pv->x264, &nal, &i_nal,
173 &pv->pic_in, &pv->pic_out );
177 /* Should be way too large */
178 buf = hb_buffer_init( 3 * job->width * job->height / 2 );
179 buf->start = in->start;
180 buf->stop = in->stop;
181 buf->key = ( pv->pic_out.i_type == X264_TYPE_IDR );
185 for( i = 0; i < i_nal; i++ )
188 data = buf->alloc - buf->size;
189 if( ( size = x264_nal_encode( &buf->data[buf->size], &data,