OSDN Git Service

69739635b8aa9b3c072690e55b5731b651187a56
[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 struct hb_work_private_s
27 {
28     hb_job_t       * job;
29     x264_t         * x264;
30     x264_picture_t   pic_in;
31     x264_picture_t   pic_out;
32
33     char             filename[1024];
34 };
35
36 /***********************************************************************
37  * hb_work_encx264_init
38  ***********************************************************************
39  *
40  **********************************************************************/
41 int encx264Init( hb_work_object_t * w, hb_job_t * job )
42 {
43     x264_param_t       param;
44     x264_nal_t       * nal;
45     int                nal_count;
46
47     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
48     w->private_data = pv;
49
50     pv->job = job;
51
52     memset( pv->filename, 0, 1024 );
53     hb_get_tempory_filename( job->h, pv->filename, "x264.log" );
54
55     x264_param_default( &param );
56
57     param.i_threads    = hb_get_cpu_count();
58     param.i_width      = job->width;
59     param.i_height     = job->height;
60     param.i_fps_num    = job->vrate;
61     param.i_fps_den    = job->vrate_base;
62     param.i_keyint_max = 20 * job->vrate / job->vrate_base;
63     param.i_log_level  = X264_LOG_INFO;
64         if( job->h264_level )
65         {
66         param.i_threads   = 1;
67         param.b_cabac     = 0;
68         param.i_level_idc = job->h264_level;
69         hb_log( "encx264: encoding at level %i",
70                 param.i_level_idc );
71         }
72
73         /* Slightly faster with minimal quality lost */
74         param.analyse.i_subpel_refine = 4;
75
76         /*      This section passes the string x264opts to libx264 for parsing into parameter names and values.
77
78         The string is set up like this:
79         option1=value1:option2=value 2
80
81         So, you have to iterate through based on the colons, and then put the left side of the equals sign in "name"
82         and the right side into "value." Then you hand those strings off to x264 for interpretation.
83
84         This is all based on the universal x264 option handling Loren Merritt implemented in the Mplayer/Mencoder project.
85         */
86  
87         char *x264opts = job->x264opts;
88         if(x264opts != NULL && *x264opts != '\0')
89         {
90                 while(*x264opts)
91                 {
92                 char *name = x264opts;
93                 char *value;
94                 int ret;
95
96                 x264opts += strcspn(x264opts, ":");
97                 if(*x264opts)
98                         {
99                         *x264opts = 0;
100                         x264opts++;
101                         }
102
103                 value = strchr( name, '=' );
104                 if(value)
105                         {
106                         *value = 0;
107                         value++;
108                         }
109                 
110                         /*
111                                 When B-frames are enabled, the max frame count increments by 1 (regardless of the number of B-frames).
112                                 If you don't change the duration of the video track when you mux, libmp4 barfs.
113                                 So, check if the x264opts are using B-frames, and when they are, set the boolean job->areBframes as true.
114                         */
115
116                         if (!(strcmp(name, "bframes")))
117                         {
118                                 if (atoi(value) > 0)
119                                 {
120                                         job->areBframes = 1;
121                                 }
122                         }
123
124                         /*      Here's where the strings are passed to libx264 for parsing. */
125                 ret = x264_param_parse(&param, name, value);
126         
127                         /*      Let x264 sanity check the options for us*/
128                 if(ret == X264_PARAM_BAD_NAME)
129                         printf("x264 options: Unknown suboption %s\n", name);
130                 if(ret == X264_PARAM_BAD_VALUE)
131                         printf("x264 options: Bad argument %s=%s\n", name, value ? value : "(null)");
132                 }
133         }
134
135
136         if( job->pixel_ratio )
137         {
138             param.vui.i_sar_width = job->pixel_aspect_width;
139             param.vui.i_sar_height = job->pixel_aspect_height;
140
141             hb_log( "encx264: encoding with stored aspect %d/%d",
142                     param.vui.i_sar_width, param.vui.i_sar_height );
143         }
144
145
146         if( job->vquality >= 0.0 && job->vquality <= 1.0 )
147         {
148             switch(job->crf)
149                 {
150                         case 1:
151                         /*Constant RF*/
152                         param.rc.i_rc_method = X264_RC_CRF;
153                         param.rc.f_rf_constant = 51 - job->vquality * 51;
154                         hb_log( "encx264: Encoding at constant RF %f",
155                                 param.rc.f_rf_constant );
156                         break;
157
158                         case 0:
159                         /*Constant QP*/
160                         param.rc.i_rc_method = X264_RC_CQP;
161                 param.rc.i_qp_constant = 51 - job->vquality * 51;
162                 hb_log( "encx264: encoding at constant QP %d",
163                     param.rc.i_qp_constant );
164                         break;
165                 }
166         }
167         else
168         {
169         /* Rate control */
170             param.rc.i_rc_method = X264_RC_ABR;
171             param.rc.i_bitrate = job->vbitrate;
172             switch( job->pass )
173             {
174                 case 1:
175                     param.rc.b_stat_write  = 1;
176                     param.rc.psz_stat_out = pv->filename;
177                     break;
178                 case 2:
179                     param.rc.b_stat_read = 1;
180                     param.rc.psz_stat_in = pv->filename;
181                     break;
182             }
183         }
184
185     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
186     pv->x264 = x264_encoder_open( &param );
187
188     x264_encoder_headers( pv->x264, &nal, &nal_count );
189
190     /* Sequence Parameter Set */
191     w->config->h264.sps_length = 1 + nal[1].i_payload;
192     w->config->h264.sps[0] = 0x67;
193     memcpy( &w->config->h264.sps[1], nal[1].p_payload, nal[1].i_payload );
194
195     /* Picture Parameter Set */
196     w->config->h264.pps_length = 1 + nal[2].i_payload;
197     w->config->h264.pps[0] = 0x68;
198     memcpy( &w->config->h264.pps[1], nal[2].p_payload, nal[2].i_payload );
199
200     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
201                         job->width, job->height );
202
203     return 0;
204 }
205
206 void encx264Close( hb_work_object_t * w )
207 {
208     hb_work_private_t * pv = w->private_data;
209     x264_encoder_close( pv->x264 );
210
211     /* TODO */
212 }
213
214 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
215                   hb_buffer_t ** buf_out )
216 {
217     hb_work_private_t * pv = w->private_data;
218     hb_job_t    * job = pv->job;
219     hb_buffer_t * in = *buf_in, * buf;
220     int           i_nal;
221     x264_nal_t  * nal;
222     int i;
223
224     /* XXX avoid this memcpy ? */
225     memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
226     if( job->grayscale )
227     {
228         /* XXX x264 has currently no option for grayscale encoding */
229         memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
230         memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
231     }
232     else
233     {
234         memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
235                 job->width * job->height / 4 );
236         memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
237                 job->height / 4, job->width * job->height / 4 );
238     }
239
240     pv->pic_in.i_type    = X264_TYPE_AUTO;
241     pv->pic_in.i_qpplus1 = 0;
242
243     x264_encoder_encode( pv->x264, &nal, &i_nal,
244                          &pv->pic_in, &pv->pic_out );
245
246     /* Should be way too large */
247     buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
248     buf->size  = 0;
249     buf->start = in->start;
250     buf->stop  = in->stop;
251     buf->key   = 0;
252
253     for( i = 0; i < i_nal; i++ )
254     {
255         int size, data;
256
257         data = buf->alloc - buf->size;
258         if( ( size = x264_nal_encode( buf->data + buf->size, &data,
259                                       1, &nal[i] ) ) < 1 )
260         {
261             continue;
262         }
263
264         if( job->mux & HB_MUX_AVI )
265         {
266             if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
267             {
268                 buf->key = 1;
269             }
270             buf->size += size;
271             continue;
272         }
273
274         /* H.264 in .mp4 */
275         switch( buf->data[buf->size+4] & 0x1f )
276         {
277             case 0x7:
278             case 0x8:
279                 /* SPS, PPS */
280                 break;
281
282             default:
283                 /* H.264 in mp4 (stolen from mp4creator) */
284                 buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
285                 buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
286                 buf->data[buf->size+2] = ( ( size - 4 ) >>  8 ) & 0xFF;
287                 buf->data[buf->size+3] = ( ( size - 4 ) >>  0 ) & 0xFF;
288                 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
289                 {
290                     buf->key = 1;
291                 }
292                 buf->size += size;
293         }
294     }
295
296     *buf_out = buf;
297
298     return HB_WORK_OK;
299 }
300
301