OSDN Git Service

HandBrake 0.7.1a1
[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     int i, size;
47         
48     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
49     w->private_data = pv;
50         
51     pv->job = job;
52         
53     memset( pv->filename, 0, 1024 );
54     hb_get_tempory_filename( job->h, pv->filename, "x264.log" );
55         
56     x264_param_default( &param );
57         
58     param.i_threads    = hb_get_cpu_count();
59     param.i_width      = job->width;
60     param.i_height     = job->height;
61     param.i_fps_num    = job->vrate;
62     param.i_fps_den    = job->vrate_base;
63     param.i_keyint_max = 20 * job->vrate / job->vrate_base;
64     param.i_log_level  = X264_LOG_NONE;
65         
66     if( job->h264_level )
67     {
68         param.i_threads   = 1;
69         param.b_cabac     = 0;
70         param.i_level_idc = job->h264_level;
71         hb_log( "encx264: encoding at level %i",
72                 param.i_level_idc );
73     }
74         
75     /* Slightly faster with minimal quality lost */
76     param.analyse.i_subpel_refine = 4;
77         
78     if( job->vquality >= 0.0 && job->vquality <= 1.0 )
79     {
80         /* Constant QP */
81         param.rc.i_qp_constant = 51 - job->vquality * 51;
82         hb_log( "encx264: encoding at constant QP %d",
83                 param.rc.i_qp_constant );
84     }
85     else
86     {
87
88                 /* Rate control */
89                 /* no longer in x264 - see rc.i_rc_method in x264.h */
90         /* param.rc.b_cbr     = 1; */
91                 
92                 /* these were the only settings I could use to get accurate ending video bitrate */
93                 param.rc.i_rc_method    =  X264_RC_CRF;
94                 param.rc.i_vbv_max_bitrate = job->vbitrate;
95         param.rc.i_vbv_buffer_size = 224;
96                 param.rc.i_rf_constant = 1;
97                 
98         param.rc.i_bitrate = job->vbitrate;
99         switch( job->pass )
100         {
101             case 1:
102                                 param.rc.i_rc_method    =  X264_RC_ABR;
103                 param.rc.b_stat_write  = 1;
104                 param.rc.psz_stat_out = pv->filename;
105                 break;
106             case 2:
107                                 param.rc.i_rc_method    =  X264_RC_ABR;
108                 param.rc.b_stat_read = 1;
109                 param.rc.psz_stat_in = pv->filename;
110                 break;
111         }
112     }
113         
114     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
115     pv->x264 = x264_encoder_open( &param );
116         
117     w->config->mpeg4.length = 0;
118         
119     x264_encoder_headers( pv->x264, &nal, &nal_count );
120         
121     for( i = 0; i < nal_count; i++ )
122     {
123         size = sizeof( w->config->mpeg4.bytes ) - w->config->mpeg4.length;
124         x264_nal_encode( &w->config->mpeg4.bytes[w->config->mpeg4.length],
125                          &size, 1, &nal[i] );
126         w->config->mpeg4.length += size;
127     }
128         
129     x264_picture_alloc( &pv->pic_in, X264_CSP_I420,
130                         job->width, job->height );
131         
132     return 0;
133 }
134
135 void encx264Close( hb_work_object_t * w )
136 {
137     hb_work_private_t * pv = w->private_data;
138     x264_encoder_close( pv->x264 );
139         
140     /* TODO */
141 }
142
143 int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
144                                  hb_buffer_t ** buf_out )
145 {
146     hb_work_private_t * pv = w->private_data;
147     hb_job_t    * job = pv->job;
148     hb_buffer_t * in = *buf_in, * buf;
149     int           i_nal;
150     x264_nal_t  * nal;
151     int i;
152         
153     /* XXX avoid this memcpy ? */
154     memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );
155     if( job->grayscale )
156     {
157         /* XXX x264 has currently no option for grayscale encoding */
158         memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
159         memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
160     }
161     else
162     {
163         memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,
164                 job->width * job->height / 4 );
165         memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *
166                 job->height / 4, job->width * job->height / 4 );
167     }
168         
169     pv->pic_in.i_type    = X264_TYPE_AUTO;
170     pv->pic_in.i_qpplus1 = 0;
171         
172     x264_encoder_encode( pv->x264, &nal, &i_nal,
173                          &pv->pic_in, &pv->pic_out );
174         
175         
176         
177     /* Should be way too large */
178     buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
179     buf->start = in->start;
180     buf->stop  = in->stop;
181     buf->key   = ( pv->pic_out.i_type == X264_TYPE_IDR );
182         
183         
184     buf->size  = 0;
185     for( i = 0; i < i_nal; i++ )
186     {
187         int size, data;
188         data = buf->alloc - buf->size;
189         if( ( size = x264_nal_encode( &buf->data[buf->size], &data,
190                                       1, &nal[i] ) ) > 0 )
191         {
192             buf->size += size;
193         }
194     }
195         
196     *buf_out = buf;
197         
198     return HB_WORK_OK;
199 }
200
201