OSDN Git Service

- Roll back avpicture_alloc to malloc + avpicture_fill. This fixes the MacGUI preview...
[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.b_cabac     = 0;
76         param.i_level_idc = job->h264_level;
77         hb_log( "encx264: encoding at level %i",
78                 param.i_level_idc );
79     }
80
81     /* Slightly faster with minimal quality lost */
82     param.analyse.i_subpel_refine = 4;
83
84     /*
85         This section passes the string x264opts to libx264 for parsing into 
86         parameter names and values.
87
88         The string is set up like this:
89         option1=value1:option2=value 2
90
91         So, you have to iterate through based on the colons, and then put 
92         the left side of the equals sign in "name" and the right side into
93         "value." Then you hand those strings off to x264 for interpretation.
94
95         This is all based on the universal x264 option handling Loren
96         Merritt implemented in the Mplayer/Mencoder project.
97      */
98
99     char *x264opts = job->x264opts;
100     if( x264opts != NULL && *x264opts != '\0' )
101     {
102         while( *x264opts )
103         {
104             char *name = x264opts;
105             char *value;
106             int ret;
107
108             x264opts += strcspn( x264opts, ":" );
109             if( *x264opts )
110             {
111                 *x264opts = 0;
112                 x264opts++;
113             }
114
115             value = strchr( name, '=' );
116             if( value )
117             {
118                 *value = 0;
119                 value++;
120             }
121
122             /*
123                When B-frames are enabled, the max frame count increments
124                by 1 (regardless of the number of B-frames). If you don't
125                change the duration of the video track when you mux, libmp4
126                barfs.  So, check if the x264opts are using B-frames, and
127                when they are, set the boolean job->areBframes as true.
128              */
129
130             if( !( strcmp( name, "bframes" ) ) )
131             {
132                 if( atoi( value ) > 0 )
133                 {
134                     job->areBframes = 1;
135                 }
136             }
137
138             /* Note b-pyramid here, so the initial delay can be doubled */
139             if( !( strcmp( name, "b-pyramid" ) ) )
140             {
141                 if( value != NULL )
142                 {
143                     if( atoi( value ) > 0 )
144                     {
145                         job->areBframes = 2;
146                     }
147                 }
148                 else
149                 {
150                     job->areBframes = 2;
151                 }
152             }
153
154             /* Here's where the strings are passed to libx264 for parsing. */
155             ret = x264_param_parse( &param, name, value );
156
157             /*  Let x264 sanity check the options for us*/
158             if( ret == X264_PARAM_BAD_NAME )
159                 hb_log( "x264 options: Unknown suboption %s", name );
160             if( ret == X264_PARAM_BAD_VALUE )
161                 hb_log( "x264 options: Bad argument %s=%s", name, value ? value : "(null)" );
162         }
163     }
164
165
166     if( job->pixel_ratio )
167     {
168         param.vui.i_sar_width = job->pixel_aspect_width;
169         param.vui.i_sar_height = job->pixel_aspect_height;
170
171         hb_log( "encx264: encoding with stored aspect %d/%d",
172                 param.vui.i_sar_width, param.vui.i_sar_height );
173     }
174
175
176     if( job->vquality >= 0.0 && job->vquality <= 1.0 )
177     {
178         switch( job->crf )
179         {
180             case 1:
181                 /*Constant RF*/
182                 param.rc.i_rc_method = X264_RC_CRF;
183                 param.rc.f_rf_constant = 51 - job->vquality * 51;
184                 hb_log( "encx264: Encoding at constant RF %f",
185                         param.rc.f_rf_constant );
186                 break;
187
188             case 0:
189                 /*Constant QP*/
190                 param.rc.i_rc_method = X264_RC_CQP;
191                 param.rc.i_qp_constant = 51 - job->vquality * 51;
192                 hb_log( "encx264: encoding at constant QP %d",
193                         param.rc.i_qp_constant );
194                 break;
195         }
196     }
197     else
198     {
199         /* Rate control */
200         param.rc.i_rc_method = X264_RC_ABR;
201         param.rc.i_bitrate = job->vbitrate;
202         switch( job->pass )
203         {
204             case 1:
205                 param.rc.b_stat_write  = 1;
206                 param.rc.psz_stat_out = pv->filename;
207                 break;
208             case 2:
209                 param.rc.b_stat_read = 1;
210                 param.rc.psz_stat_in = pv->filename;
211                 break;
212         }
213     }
214
215     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
216     pv->x264 = x264_encoder_open( &param );
217
218     x264_encoder_headers( pv->x264, &nal, &nal_count );
219
220     /* Sequence Parameter Set */
221     w->config->h264.sps_length = 1 + nal[1].i_payload;
222     w->config->h264.sps[0] = 0x67;
223     memcpy( &w->config->h264.sps[1], nal[1].p_payload, nal[1].i_payload );
224
225     /* Picture Parameter Set */
226     w->config->h264.pps_length = 1 + nal[2].i_payload;
227     w->config->h264.pps[0] = 0x68;
228     memcpy( &w->config->h264.pps[1], nal[2].p_payload, nal[2].i_payload );
229
230     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
231             job->width, job->height );
232
233     pv->dts_write_index = 0;
234     pv->dts_read_index = 0;
235
236     return 0;
237 }
238
239 void encx264Close( hb_work_object_t * w )
240 {
241     hb_work_private_t * pv = w->private_data;
242     x264_picture_clean( &pv->pic_in );
243     x264_encoder_close( pv->x264 );
244     free( pv );
245     w->private_data = NULL;
246
247     /* TODO */
248 }
249
250 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
251                   hb_buffer_t ** buf_out )
252 {
253     hb_work_private_t * pv = w->private_data;
254     hb_job_t    * job = pv->job;
255     hb_buffer_t * in = *buf_in, * buf;
256     x264_picture_t   pic_out;
257     int           i_nal;
258     x264_nal_t  * nal;
259     int i;
260
261     if( in->data )
262     {
263         /* XXX avoid this memcpy ? */
264         memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
265         if( job->grayscale )
266         {
267             /* XXX x264 has currently no option for grayscale encoding */
268             memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
269             memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
270         }
271         else
272         {
273             memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
274                     job->width * job->height / 4 );
275             memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
276                     job->height / 4, job->width * job->height / 4 );
277         }
278
279         pv->pic_in.i_type    = X264_TYPE_AUTO;
280         pv->pic_in.i_qpplus1 = 0;
281
282         // Remember current PTS value, use as DTS later
283         pv->dts_start[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)] = in->start;
284         pv->dts_stop[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)]  = in->stop;
285         pv->dts_write_index++;
286
287         /* Feed the input DTS to x264 so it can figure out proper output PTS */
288         pv->pic_in.i_pts = in->start;
289
290         x264_encoder_encode( pv->x264, &nal, &i_nal,
291                              &pv->pic_in, &pic_out );        
292     }
293     else
294     {
295         x264_encoder_encode( pv->x264, &nal, &i_nal,
296                              NULL, &pic_out );
297         /* No more delayed B frames */
298         if( i_nal == 0 )
299         {
300             *buf_out = NULL;
301             return HB_WORK_DONE;
302         }
303         else
304         {
305         /*  Since we output at least one more frame, drop another empty
306             one onto our input fifo.  We'll keep doing this automatically
307             until we stop getting frames out of the encoder. */
308             hb_fifo_push(w->fifo_in, hb_buffer_init(0));
309         }
310     }
311
312     if( i_nal )
313     {
314         /* Should be way too large */
315         buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
316         buf->size  = 0;
317         buf->start = in->start;
318         buf->stop  = in->stop;
319         buf->frametype   = 0;
320
321         int64_t dts_start, dts_stop;
322
323         /* Get next DTS value to use */
324         dts_start = pv->dts_start[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];
325         dts_stop  = pv->dts_stop[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];
326         pv->dts_read_index++;
327
328         for( i = 0; i < i_nal; i++ )
329         {
330             int size, data;
331
332             data = buf->alloc - buf->size;
333             if( ( size = x264_nal_encode( buf->data + buf->size, &data,
334                                           1, &nal[i] ) ) < 1 )
335             {
336                 continue;
337             }
338
339             if( job->mux & HB_MUX_AVI )
340             {
341                 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
342                 {
343                     buf->frametype = HB_FRAME_KEY;
344                 }
345                 buf->size += size;
346                 continue;
347             }
348
349             /* H.264 in .mp4 */
350             switch( buf->data[buf->size+4] & 0x1f )
351             {
352                 case 0x7:
353                 case 0x8:
354                     /* SPS, PPS */
355                     break;
356
357                 default:
358                     /* H.264 in mp4 (stolen from mp4creator) */
359                     buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
360                     buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
361                     buf->data[buf->size+2] = ( ( size - 4 ) >>  8 ) & 0xFF;
362                     buf->data[buf->size+3] = ( ( size - 4 ) >>  0 ) & 0xFF;
363                     switch( pic_out.i_type )
364                     {
365                     /*  Decide what type of frame we have. */
366                         case X264_TYPE_IDR:
367                             buf->frametype = HB_FRAME_IDR;
368                             break;
369                         case X264_TYPE_I:
370                             buf->frametype = HB_FRAME_I;
371                             break;
372                         case X264_TYPE_P:
373                             buf->frametype = HB_FRAME_P;
374                             break;
375                         case X264_TYPE_B:
376                             buf->frametype = HB_FRAME_B;
377                             break;
378                     /*  This is for b-pyramid, which has reference b-frames
379                         However, it doesn't seem to ever be used... */
380                         case X264_TYPE_BREF:
381                             buf->frametype = HB_FRAME_BREF;
382                             break;
383                     /*  If it isn't the above, what type of frame is it?? */
384                         default:
385                             buf->frametype = 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