OSDN Git Service

added call to av_log_set_level in hb_init_real based on value of verbose param.
[handbrake-jp/handbrake-jp-git.git] / libmediafork / 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 "mediafork.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_NONE;
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         if( job->pixel_ratio )
77         {
78             param.vui.i_sar_width = job->pixel_aspect_width;
79             param.vui.i_sar_height = job->pixel_aspect_height;
80
81             hb_log( "encx264: encoding with stored aspect %d/%d",
82                     param.vui.i_sar_width, param.vui.i_sar_height );
83         }
84
85
86         if( job->vquality >= 0.0 && job->vquality <= 1.0 )
87         {
88             switch(job->crf)
89                 {
90                         case 1:
91                         /*Constant RF*/
92                         param.rc.i_rc_method = X264_RC_CRF;
93                         param.rc.f_rf_constant = 51 - job->vquality * 51;
94                         hb_log( "encx264: Encoding at constant RF %f",
95                                 param.rc.f_rf_constant );
96                         break;
97
98                         case 0:
99                         /*Constant QP*/
100                         param.rc.i_rc_method = X264_RC_CQP;
101                 param.rc.i_qp_constant = 51 - job->vquality * 51;
102                 hb_log( "encx264: encoding at constant QP %d",
103                     param.rc.i_qp_constant );
104                         break;
105                 }
106         }
107         else
108         {
109         /* Rate control */
110             param.rc.i_rc_method = X264_RC_ABR;
111             param.rc.i_bitrate = job->vbitrate;
112             switch( job->pass )
113             {
114                 case 1:
115                     param.rc.b_stat_write  = 1;
116                     param.rc.psz_stat_out = pv->filename;
117                     break;
118                 case 2:
119                     param.rc.b_stat_read = 1;
120                     param.rc.psz_stat_in = pv->filename;
121                     break;
122             }
123         }
124
125     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
126     pv->x264 = x264_encoder_open( &param );
127
128     x264_encoder_headers( pv->x264, &nal, &nal_count );
129
130     /* Sequence Parameter Set */
131     w->config->h264.sps_length = 1 + nal[1].i_payload;
132     w->config->h264.sps[0] = 0x67;
133     memcpy( &w->config->h264.sps[1], nal[1].p_payload, nal[1].i_payload );
134
135     /* Picture Parameter Set */
136     w->config->h264.pps_length = 1 + nal[2].i_payload;
137     w->config->h264.pps[0] = 0x68;
138     memcpy( &w->config->h264.pps[1], nal[2].p_payload, nal[2].i_payload );
139
140     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
141                         job->width, job->height );
142
143     return 0;
144 }
145
146 void encx264Close( hb_work_object_t * w )
147 {
148     hb_work_private_t * pv = w->private_data;
149     x264_encoder_close( pv->x264 );
150
151     /* TODO */
152 }
153
154 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
155                   hb_buffer_t ** buf_out )
156 {
157     hb_work_private_t * pv = w->private_data;
158     hb_job_t    * job = pv->job;
159     hb_buffer_t * in = *buf_in, * buf;
160     int           i_nal;
161     x264_nal_t  * nal;
162     int i;
163
164     /* XXX avoid this memcpy ? */
165     memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
166     if( job->grayscale )
167     {
168         /* XXX x264 has currently no option for grayscale encoding */
169         memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
170         memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
171     }
172     else
173     {
174         memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
175                 job->width * job->height / 4 );
176         memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
177                 job->height / 4, job->width * job->height / 4 );
178     }
179
180     pv->pic_in.i_type    = X264_TYPE_AUTO;
181     pv->pic_in.i_qpplus1 = 0;
182
183     x264_encoder_encode( pv->x264, &nal, &i_nal,
184                          &pv->pic_in, &pv->pic_out );
185
186     /* Should be way too large */
187     buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
188     buf->size  = 0;
189     buf->start = in->start;
190     buf->stop  = in->stop;
191     buf->key   = 0;
192
193     for( i = 0; i < i_nal; i++ )
194     {
195         int size, data;
196
197         data = buf->alloc - buf->size;
198         if( ( size = x264_nal_encode( buf->data + buf->size, &data,
199                                       1, &nal[i] ) ) < 1 )
200         {
201             continue;
202         }
203
204         if( job->mux & HB_MUX_AVI )
205         {
206             if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
207             {
208                 buf->key = 1;
209             }
210             buf->size += size;
211             continue;
212         }
213
214         /* H.264 in .mp4 */
215         switch( buf->data[buf->size+4] & 0x1f )
216         {
217             case 0x7:
218             case 0x8:
219                 /* SPS, PPS */
220                 break;
221
222             default:
223                 /* H.264 in mp4 (stolen from mp4creator) */
224                 buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
225                 buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
226                 buf->data[buf->size+2] = ( ( size - 4 ) >>  8 ) & 0xFF;
227                 buf->data[buf->size+3] = ( ( size - 4 ) >>  0 ) & 0xFF;
228                 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
229                 {
230                     buf->key = 1;
231                 }
232                 buf->size += size;
233         }
234     }
235
236     *buf_out = buf;
237
238     return HB_WORK_OK;
239 }
240
241