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 struct hb_work_object_s
19 x264_picture_t pic_in;
20 x264_picture_t pic_out;
25 /***********************************************************************
27 **********************************************************************/
28 static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
29 hb_buffer_t ** buf_out );
30 static void Close( hb_work_object_t ** _w );
32 /***********************************************************************
33 * hb_work_encx264_init
34 ***********************************************************************
36 **********************************************************************/
37 hb_work_object_t * hb_work_encx264_init( hb_job_t * job )
44 w = calloc( sizeof( hb_work_object_t ), 1 );
45 w->name = strdup( "AVC encoder (libx264)" );
51 memset( w->filename, 0, 1024 );
52 hb_get_tempory_filename( job->h, w->filename, "x264.log" );
54 x264_param_default( ¶m );
56 param.i_threads = hb_get_cpu_count();
57 param.i_width = job->width;
58 param.i_height = job->height;
59 param.i_fps_num = job->vrate;
60 param.i_fps_den = job->vrate_base;
61 param.i_keyint_max = 20 * job->vrate / job->vrate_base;
62 param.i_log_level = X264_LOG_NONE;
66 param.i_level_idc = 13;
69 /* Slightly faster with minimal quality lost */
70 param.analyse.i_subpel_refine = 4;
72 if( job->vquality >= 0.0 && job->vquality <= 1.0 )
75 param.rc.i_qp_constant = 51 - job->vquality * 51;
76 hb_log( "encx264: encoding at constant QP %d",
77 param.rc.i_qp_constant );
83 param.rc.i_bitrate = job->vbitrate;
87 param.rc.b_stat_write = 1;
88 param.rc.psz_stat_out = w->filename;
91 param.rc.b_stat_read = 1;
92 param.rc.psz_stat_in = w->filename;
97 hb_log( "encx264: opening libx264 (pass %d)", job->pass );
98 w->x264 = x264_encoder_open( ¶m );
100 #define c job->config.h264
101 x264_encoder_headers( w->x264, &nal, &nal_count );
103 /* Sequence Parameter Set */
104 c.sps_length = 1 + nal[1].i_payload;
105 c.sps = malloc( c.sps_length);
107 memcpy( &c.sps[1], nal[1].p_payload, nal[1].i_payload );
109 /* Picture Parameter Set */
110 c.pps_length = 1 + nal[2].i_payload;
111 c.pps = malloc( c.pps_length );
113 memcpy( &c.pps[1], nal[2].p_payload, nal[2].i_payload );
116 x264_picture_alloc( &w->pic_in, X264_CSP_I420,
117 job->width, job->height );
122 static void Close( hb_work_object_t ** _w )
124 hb_work_object_t * w = *_w;
126 x264_encoder_close( w->x264 );
135 static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
136 hb_buffer_t ** buf_out )
138 hb_job_t * job = w->job;
139 hb_buffer_t * in = *buf_in, * buf;
144 /* XXX avoid this memcpy ? */
145 memcpy( w->pic_in.img.plane[0], in->data, job->width * job->height );
148 /* XXX x264 has currently no option for grayscale encoding */
149 memset( w->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
150 memset( w->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
154 memcpy( w->pic_in.img.plane[1], in->data + job->width * job->height,
155 job->width * job->height / 4 );
156 memcpy( w->pic_in.img.plane[2], in->data + 5 * job->width *
157 job->height / 4, job->width * job->height / 4 );
160 w->pic_in.i_type = X264_TYPE_AUTO;
161 w->pic_in.i_qpplus1 = 0;
163 x264_encoder_encode( w->x264, &nal, &i_nal,
164 &w->pic_in, &w->pic_out );
166 /* Should be way too large */
167 buf = hb_buffer_init( 3 * job->width * job->height / 2 );
169 buf->start = in->start;
170 buf->stop = in->stop;
173 for( i = 0; i < i_nal; i++ )
177 data = buf->alloc - buf->size;
178 if( ( size = x264_nal_encode( buf->data + buf->size, &data,
184 if( job->mux & HB_MUX_AVI )
186 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
195 switch( buf->data[buf->size+4] & 0x1f )
203 /* H.264 in mp4 (stolen from mp4creator) */
204 buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
205 buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
206 buf->data[buf->size+2] = ( ( size - 4 ) >> 8 ) & 0xFF;
207 buf->data[buf->size+3] = ( ( size - 4 ) >> 0 ) & 0xFF;
208 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )