OSDN Git Service

HandBrake 0.7.0
[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 struct hb_work_object_s
14 {
15     HB_WORK_COMMON;
16
17     hb_job_t       * job;
18     x264_t         * x264;
19     x264_picture_t   pic_in;
20     x264_picture_t   pic_out;
21
22     char             filename[1024];
23 };
24
25 /***********************************************************************
26  * Local prototypes
27  **********************************************************************/
28 static int  Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
29                   hb_buffer_t ** buf_out );
30 static void Close( hb_work_object_t ** _w );
31
32 /***********************************************************************
33  * hb_work_encx264_init
34  ***********************************************************************
35  *
36  **********************************************************************/
37 hb_work_object_t * hb_work_encx264_init( hb_job_t * job )
38 {
39     hb_work_object_t * w;
40     x264_param_t       param;
41     x264_nal_t       * nal;
42     int                nal_count;
43
44     w        = calloc( sizeof( hb_work_object_t ), 1 );
45     w->name  = strdup( "AVC encoder (libx264)" );
46     w->work  = Work;
47     w->close = Close;
48
49     w->job = job;
50
51     memset( w->filename, 0, 1024 );
52     hb_get_tempory_filename( job->h, w->filename, "x264.log" );
53
54     x264_param_default( &param );
55
56     param.i_threads    = hb_get_cpu_count();
57     param.i_width      = job->width;
58     param.i_height     = job->height;
59     param.i_fps_num    = job->vrate;
60     param.i_fps_den    = job->vrate_base;
61     param.i_keyint_max = 20 * job->vrate / job->vrate_base;
62     param.i_log_level  = X264_LOG_NONE;
63     if( job->h264_13 )
64     {
65         param.b_cabac     = 0;
66         param.i_level_idc = 13;
67     }
68
69     /* Slightly faster with minimal quality lost */
70     param.analyse.i_subpel_refine = 4;
71
72     if( job->vquality >= 0.0 && job->vquality <= 1.0 )
73     {
74         /* Constant QP */
75         param.rc.i_qp_constant = 51 - job->vquality * 51;
76         hb_log( "encx264: encoding at constant QP %d",
77                 param.rc.i_qp_constant );
78     }
79     else
80     {
81         /* Rate control */
82         param.rc.b_cbr     = 1;
83         param.rc.i_bitrate = job->vbitrate;
84         switch( job->pass )
85         {
86             case 1:
87                 param.rc.b_stat_write  = 1;
88                 param.rc.psz_stat_out = w->filename;
89                 break;
90             case 2:
91                 param.rc.b_stat_read = 1;
92                 param.rc.psz_stat_in = w->filename;
93                 break;
94         }
95     }
96
97     hb_log( "encx264: opening libx264 (pass %d)", job->pass );
98     w->x264 = x264_encoder_open( &param );
99
100 #define c job->config.h264
101     x264_encoder_headers( w->x264, &nal, &nal_count );
102
103     /* Sequence Parameter Set */
104     c.sps_length = 1 + nal[1].i_payload;
105     c.sps        = malloc( c.sps_length);
106     c.sps[0]     = 0x67;
107     memcpy( &c.sps[1], nal[1].p_payload, nal[1].i_payload );
108
109     /* Picture Parameter Set */
110     c.pps_length = 1 + nal[2].i_payload;
111     c.pps        = malloc( c.pps_length );
112     c.pps[0]     = 0x68;
113     memcpy( &c.pps[1], nal[2].p_payload, nal[2].i_payload );
114 #undef c
115
116     x264_picture_alloc( &w->pic_in, X264_CSP_I420,
117                         job->width, job->height );
118
119     return w;
120 }
121
122 static void Close( hb_work_object_t ** _w )
123 {
124     hb_work_object_t * w = *_w;
125
126     x264_encoder_close( w->x264 );
127
128     /* TODO */
129
130     free( w->name );
131     free( w );
132     *_w = NULL;
133 }
134
135 static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
136                  hb_buffer_t ** buf_out )
137 {
138     hb_job_t    * job = w->job;
139     hb_buffer_t * in = *buf_in, * buf;
140     int           i_nal;
141     x264_nal_t  * nal;
142     int i;
143
144     /* XXX avoid this memcpy ? */
145     memcpy( w->pic_in.img.plane[0], in->data, job->width * job->height );
146     if( job->grayscale )
147     {
148         /* XXX x264 has currently no option for grayscale encoding */
149         memset( w->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );
150         memset( w->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );
151     }
152     else
153     {
154         memcpy( w->pic_in.img.plane[1], in->data + job->width * job->height,
155                 job->width * job->height / 4 );
156         memcpy( w->pic_in.img.plane[2], in->data + 5 * job->width *
157                 job->height / 4, job->width * job->height / 4 );
158     }
159
160     w->pic_in.i_type    = X264_TYPE_AUTO;
161     w->pic_in.i_qpplus1 = 0;
162
163     x264_encoder_encode( w->x264, &nal, &i_nal,
164                          &w->pic_in, &w->pic_out );
165
166     /* Should be way too large */
167     buf        = hb_buffer_init( 3 * job->width * job->height / 2 );
168     buf->size  = 0;
169     buf->start = in->start;
170     buf->stop  = in->stop;
171     buf->key   = 0;
172
173     for( i = 0; i < i_nal; i++ )
174     {
175         int size, data;
176
177         data = buf->alloc - buf->size;
178         if( ( size = x264_nal_encode( buf->data + buf->size, &data,
179                                       1, &nal[i] ) ) < 1 )
180         {
181             continue;
182         }
183
184         if( job->mux & HB_MUX_AVI )
185         {
186             if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
187             {
188                 buf->key = 1;
189             }
190             buf->size += size;
191             continue;
192         }
193
194         /* H.264 in .mp4 */
195         switch( buf->data[buf->size+4] & 0x1f )
196         {
197             case 0x7:
198             case 0x8:
199                 /* SPS, PPS */
200                 break;
201
202             default:
203                 /* H.264 in mp4 (stolen from mp4creator) */
204                 buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;
205                 buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;
206                 buf->data[buf->size+2] = ( ( size - 4 ) >>  8 ) & 0xFF;
207                 buf->data[buf->size+3] = ( ( size - 4 ) >>  0 ) & 0xFF;
208                 if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
209                 {
210                     buf->key = 1;
211                 }
212                 buf->size += size;
213         }
214     }
215
216     *buf_out = buf;
217
218     return HB_WORK_OK;
219 }
220
221