OSDN Git Service

Tells x264 to use threads=cpus*1.5 instead of threads=cpus. This is because x264...
[handbrake-jp/handbrake-jp-git.git] / libhb / encx264.c
1 /* $Id: encx264.c,v 1.21 2005/11/04 13:09:41 titer Exp $
2
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. */
6
7 #include <stdarg.h>
8
9 #include "hb.h"
10
11 #include "x264.h"
12
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 * );
16
17 hb_work_object_t hb_encx264 =
18 {
19     WORK_ENCX264,
20     "H.264/AVC encoder (libx264)",
21     encx264Init,
22     encx264Work,
23     encx264Close
24 };
25
26 // 16 is probably overkill but it's also the maximum for h.264 reference frames
27 #define MAX_INFLIGHT_FRAMES 16
28
29 struct hb_work_private_s
30 {
31     hb_job_t       * job;
32     x264_t         * x264;
33     x264_picture_t   pic_in;
34
35     // Internal queue of DTS start/stop values.
36     int64_t        dts_start[MAX_INFLIGHT_FRAMES];
37     int64_t        dts_stop[MAX_INFLIGHT_FRAMES];
38
39     int64_t        dts_write_index;
40     int64_t        dts_read_index;
41
42     char             filename[1024];
43 };
44
45 /***********************************************************************
46  * hb_work_encx264_init
47  ***********************************************************************
48  *
49  **********************************************************************/
50 int encx264Init( hb_work_object_t * w, hb_job_t * job )
51 {
52     x264_param_t       param;
53     x264_nal_t       * nal;
54     int                nal_count;
55
56     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
57     w->private_data = pv;
58
59     pv->job = job;
60
61     memset( pv->filename, 0, 1024 );
62     hb_get_tempory_filename( job->h, pv->filename, "x264.log" );
63
64     x264_param_default( &param );
65
66     param.i_threads    = ( hb_get_cpu_count() * 3 / 2 );
67     param.i_width      = job->width;
68     param.i_height     = job->height;
69     param.i_fps_num    = job->vrate;
70     param.i_fps_den    = job->vrate_base;
71     param.i_keyint_max = 20 * job->vrate / job->vrate_base;
72     param.i_log_level  = X264_LOG_INFO;
73     if( job->h264_level )
74     {
75         param.i_threads   = 1;
76         param.b_cabac     = 0;
77         param.i_level_idc = job->h264_level;
78         hb_log( "encx264: encoding at level %i",
79                 param.i_level_idc );
80     }
81
82     /* Slightly faster with minimal quality lost */
83     param.analyse.i_subpel_refine = 4;
84
85     /*
86         This section passes the string x264opts to libx264 for parsing into 
87         parameter names and values.
88
89         The string is set up like this:
90         option1=value1:option2=value 2
91
92         So, you have to iterate through based on the colons, and then put 
93         the left side of the equals sign in "name" and the right side into
94         "value." Then you hand those strings off to x264 for interpretation.
95
96         This is all based on the universal x264 option handling Loren
97         Merritt implemented in the Mplayer/Mencoder project.
98      */
99
100     char *x264opts = job->x264opts;
101     if( x264opts != NULL && *x264opts != '\0' )
102     {
103         while( *x264opts )
104         {
105             char *name = x264opts;
106             char *value;
107             int ret;
108
109             x264opts += strcspn( x264opts, ":" );
110             if( *x264opts )
111             {
112                 *x264opts = 0;
113                 x264opts++;
114             }
115
116             value = strchr( name, '=' );
117             if( value )
118             {
119                 *value = 0;
120                 value++;
121             }
122
123             /*
124                When B-frames are enabled, the max frame count increments
125                by 1 (regardless of the number of B-frames). If you don't
126                change the duration of the video track when you mux, libmp4
127                barfs.  So, check if the x264opts are using B-frames, and
128                when they are, set the boolean job->areBframes as true.
129              */
130
131             if( !( strcmp( name, "bframes" ) ) )
132             {
133                 if( atoi( value ) > 0 )
134                 {
135                     job->areBframes = 1;
136                 }
137             }
138
139             /* Note b-pyramid here, so the initial delay can be doubled */
140             if( !( strcmp( name, "b-pyramid" ) ) )
141             {
142                 if( value != NULL )
143                 {
144                     if( atoi( value ) > 0 )
145                     {
146                         job->areBframes = 2;
147                     }
148                 }
149                 else
150                 {
151                     job->areBframes = 2;
152                 }
153             }
154
155             /* Here's where the strings are passed to libx264 for parsing. */
156             ret = x264_param_parse( &param, name, value );
157
158             /*  Let x264 sanity check the options for us*/
159             if( ret == X264_PARAM_BAD_NAME )
160                 hb_log( "x264 options: Unknown suboption %s", name );
161             if( ret == X264_PARAM_BAD_VALUE )
162                 hb_log( "x264 options: Bad argument %s=%s", name, value ? value : "(null)" );
163         }
164     }
165
166
167     if( job->pixel_ratio )
168     {
169         param.vui.i_sar_width = job->pixel_aspect_width;
170         param.vui.i_sar_height = job->pixel_aspect_height;
171
172         hb_log( "encx264: encoding with stored aspect %d/%d",
173                 param.vui.i_sar_width, param.vui.i_sar_height );
174     }
175
176
177     if( job->vquality >= 0.0 && job->vquality <= 1.0 )
178     {
179         switch( job->crf )
180         {
181             case 1:
182                 /*Constant RF*/
183                 param.rc.i_rc_method = X264_RC_CRF;
184                 param.rc.f_rf_constant = 51 - job->vquality * 51;
185                 hb_log( "encx264: Encoding at constant RF %f",
186                         param.rc.f_rf_constant );
187                 break;
188
189             case 0:
190                 /*Constant QP*/
191                 param.rc.i_rc_method = X264_RC_CQP;
192                 param.rc.i_qp_constant = 51 - job->vquality * 51;
193                 hb_log( "encx264: encoding at constant QP %d",
194                         param.rc.i_qp_constant );
195                 break;
196         }
197     }
198     else
199     {
200         /* Rate control */
201         param.rc.i_rc_method = X264_RC_ABR;
202         param.rc.i_bitrate = job->vbitrate;
203         switch( job->pass )
204         {
205             case 1:
206                 param.rc.b_stat_write  = 1;
207                 param.rc.psz_stat_out = pv->filename;
208                 break;
209             case 2:
210                 param.rc.b_stat_read = 1;
211                 param.rc.psz_stat_in = pv->filename;
212                 break;
213         }
214     }
215
216     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
217     pv->x264 = x264_encoder_open( &param );
218
219     x264_encoder_headers( pv->x264, &nal, &nal_count );
220
221     /* Sequence Parameter Set */
222     w->config->h264.sps_length = 1 + nal[1].i_payload;
223     w->config->h264.sps[0] = 0x67;
224     memcpy( &w->config->h264.sps[1], nal[1].p_payload, nal[1].i_payload );
225
226     /* Picture Parameter Set */
227     w->config->h264.pps_length = 1 + nal[2].i_payload;
228     w->config->h264.pps[0] = 0x68;
229     memcpy( &w->config->h264.pps[1], nal[2].p_payload, nal[2].i_payload );
230
231     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
232             job->width, job->height );
233
234     pv->dts_write_index = 0;
235     pv->dts_read_index = 0;
236
237     return 0;
238 }
239
240 void encx264Close( hb_work_object_t * w )
241 {
242     hb_work_private_t * pv = w->private_data;
243     x264_picture_clean( &pv->pic_in );
244     x264_encoder_close( pv->x264 );
245     free( pv );
246     w->private_data = NULL;
247
248     /* TODO */
249 }
250
251 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
252                   hb_buffer_t ** buf_out )
253 {
254     hb_work_private_t * pv = w->private_data;
255     hb_job_t    * job = pv->job;
256     hb_buffer_t * in = *buf_in, * buf;
257     x264_picture_t   pic_out;
258     int           i_nal;
259     x264_nal_t  * nal;
260     int i;
261
262     if( in->data )
263     {
264         /* XXX avoid this memcpy ? */
265         memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
266         if( job->grayscale )
267         {
268             /* XXX x264 has currently no option for grayscale encoding */
269             memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
270             memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
271         }
272         else
273         {
274             memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
275                     job->width * job->height / 4 );
276             memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
277                     job->height / 4, job->width * job->height / 4 );
278         }
279
280         pv->pic_in.i_type    = X264_TYPE_AUTO;
281         pv->pic_in.i_qpplus1 = 0;
282
283         // Remember current PTS value, use as DTS later
284         pv->dts_start[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)] = in->start;
285         pv->dts_stop[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)]  = in->stop;
286         pv->dts_write_index++;
287
288         /* Feed the input DTS to x264 so it can figure out proper output PTS */
289         pv->pic_in.i_pts = in->start;
290
291         x264_encoder_encode( pv->x264, &nal, &i_nal,
292                              &pv->pic_in, &pic_out );        
293     }
294     else
295     {
296         x264_encoder_encode( pv->x264, &nal, &i_nal,
297                              NULL, &pic_out );
298         /* No more delayed B frames */
299         if( i_nal == 0 )
300         {
301             *buf_out = NULL;
302             return HB_WORK_DONE;
303         }
304         else
305         {
306         /*  Since we output at least one more frame, drop another empty
307             one onto our input fifo.  We'll keep doing this automatically
308             until we stop getting frames out of the encoder. */
309             hb_fifo_push(w->fifo_in, hb_buffer_init(0));
310         }
311     }
312
313     if( i_nal )
314     {
315         /* Should be way too large */
316         buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
317         buf->size  = 0;
318         buf->start = in->start;
319         buf->stop  = in->stop;
320         buf->key   = 0;
321
322         int64_t dts_start, dts_stop;
323
324         /* Get next DTS value to use */
325         dts_start = pv->dts_start[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];
326         dts_stop  = pv->dts_stop[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];
327         pv->dts_read_index++;
328
329         for( i = 0; i < i_nal; i++ )
330         {
331             int size, data;
332
333             data = buf->alloc - buf->size;
334             if( ( size = x264_nal_encode( buf->data + buf->size, &data,
335                                           1, &nal[i] ) ) < 1 )
336             {
337                 continue;
338             }
339
340             if( job->mux & HB_MUX_AVI )
341             {
342                 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
343                 {
344                     buf->key = 1;
345                 }
346                 buf->size += size;
347                 continue;
348             }
349
350             /* H.264 in .mp4 */
351             switch( buf->data[buf->size+4] & 0x1f )
352             {
353                 case 0x7:
354                 case 0x8:
355                     /* SPS, PPS */
356                     break;
357
358                 default:
359                     /* H.264 in mp4 (stolen from mp4creator) */
360                     buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
361                     buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
362                     buf->data[buf->size+2] = ( ( size - 4 ) >>  8 ) & 0xFF;
363                     buf->data[buf->size+3] = ( ( size - 4 ) >>  0 ) & 0xFF;
364                     switch( pic_out.i_type )
365                     {
366                     /*  For IDR (key frames), buf->key = 1,
367                         and the same for regular I-frames. */
368                         case X264_TYPE_IDR:
369                         case X264_TYPE_I:
370                             buf->key = 1;
371                             break;
372                     /*  For B-frames, buf->key = 2 */
373                         case X264_TYPE_B:
374                             buf->key = 2;
375                             break;
376                     /*  This is for b-pyramid, which has reference b-frames
377                         However, it doesn't seem to ever be used...
378                         They just show up as buf->key == 2 like
379                         regular b-frames. */
380                         case X264_TYPE_BREF:
381                             buf->key = 3;
382                             break;
383                     /*  For P-frames, buf->key = 0 */
384                         default:
385                             buf->key = 0;
386                     }
387
388
389                     /* Store the output presentation time stamp
390                        from x264 for use by muxmp4 in off-setting
391                        b-frames with the CTTS atom.
392                        For now, just add 1000000 to the offset so that the
393                        value is pretty much guaranteed to be positive.  The
394                        muxing code will minimize the renderOffset at the end. */
395
396                     buf->renderOffset = pic_out.i_pts - dts_start + 1000000;
397
398                     /* Send out the next dts values */
399                     buf->start = dts_start;
400                     buf->stop  = dts_stop;
401
402                     buf->size += size;
403             }
404         }
405     }
406
407     else
408         buf = NULL;
409
410     *buf_out = buf;
411
412     return HB_WORK_OK;
413 }
414
415