OSDN Git Service

Another minor step on the way back to Solaris compiles - not linking as yet.
[handbrake-jp/handbrake-jp-git.git] / libhb / encxvid.c
1 /* $Id: encxvid.c,v 1.10 2005/03/09 23:28:39 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8
9 #include "xvid.h"
10
11 int  encxvidInit( hb_work_object_t *, hb_job_t * );
12 int  encxvidWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
13 void encxvidClose( hb_work_object_t * );
14
15 hb_work_object_t hb_encxvid =
16 {
17     WORK_ENCXVID,
18     "MPEG-4 encoder (libxvidcore)",
19     encxvidInit,
20     encxvidWork,
21     encxvidClose
22 };
23
24 struct hb_work_private_s
25 {
26     hb_job_t * job;
27     void     * xvid;
28     char       filename[1024];
29     int        quant;
30     int        configDone;
31 };
32
33 int encxvidInit( hb_work_object_t * w, hb_job_t * job )
34 {
35     xvid_gbl_init_t xvid_gbl_init;
36     xvid_enc_create_t create;
37     xvid_plugin_single_t single;
38     xvid_plugin_2pass1_t rc2pass1;
39     xvid_plugin_2pass2_t rc2pass2;
40     xvid_enc_plugin_t plugins[1];
41
42     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
43     w->private_data = pv;
44
45     pv->job = job;
46
47     memset( pv->filename, 0, 1024 );
48     hb_get_tempory_filename( job->h, pv->filename, "xvid.log" );
49
50     memset( &xvid_gbl_init, 0, sizeof( xvid_gbl_init ) );
51     xvid_gbl_init.version = XVID_VERSION;
52     xvid_global( NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL );
53
54     memset( &create, 0, sizeof( create ) );
55     create.version   = XVID_VERSION;
56     create.width     = job->width;
57     create.height    = job->height;
58     create.zones     = NULL;
59     create.num_zones = 0;
60
61     switch( job->pass )
62     {
63         case 0:
64             memset( &single, 0, sizeof( single ) );
65             single.version   = XVID_VERSION;
66             if( job->vquality < 0.0 )
67             {
68                 /* Rate control */
69                 single.bitrate = 1000 * job->vbitrate;
70                 pv->quant = 0;
71             }
72             else
73             {
74                 if( job->vquality > 0 && job->vquality < 1 )
75                 {
76                     /* Constant quantizer */
77                     pv->quant = 31 - job->vquality * 30;
78                 }
79                 else
80                 {
81                     pv->quant = job->vquality;
82                 }
83                 
84                 hb_log( "encxvid: encoding at constant quantizer %d",
85                         pv->quant );
86             }
87             plugins[0].func  = xvid_plugin_single;
88             plugins[0].param = &single;
89             break;
90
91         case 1:
92             memset( &rc2pass1, 0, sizeof( rc2pass1 ) );
93             rc2pass1.version  = XVID_VERSION;
94             rc2pass1.filename = pv->filename;
95             plugins[0].func   = xvid_plugin_2pass1;
96             plugins[0].param  = &rc2pass1;
97             break;
98
99         case 2:
100             memset( &rc2pass2, 0, sizeof( rc2pass2 ) );
101             rc2pass2.version  = XVID_VERSION;
102             rc2pass2.filename = pv->filename;
103             rc2pass2.bitrate  = 1000 * job->vbitrate;
104             plugins[0].func   = xvid_plugin_2pass2;
105             plugins[0].param  = &rc2pass2;
106             break;
107     }
108
109     create.plugins     = plugins;
110     create.num_plugins = 1;
111
112     create.num_threads      = 0;
113     create.fincr            = job->vrate_base;
114     create.fbase            = job->vrate;
115     create.max_key_interval = 10 * job->vrate / job->vrate_base;
116     create.max_bframes      = 0;
117     create.bquant_ratio     = 150;
118     create.bquant_offset    = 100;
119     create.frame_drop_ratio = 0;
120     create.global           = 0;
121
122     xvid_encore( NULL, XVID_ENC_CREATE, &create, NULL );
123     pv->xvid = create.handle;
124
125     return 0;
126 }
127
128 /***********************************************************************
129  * Close
130  ***********************************************************************
131  *
132  **********************************************************************/
133 void encxvidClose( hb_work_object_t * w )
134 {
135     hb_work_private_t * pv = w->private_data;
136
137     if( pv->xvid )
138     {
139         hb_deep_log( 2, "encxvid: closing libxvidcore" );
140         xvid_encore( pv->xvid, XVID_ENC_DESTROY, NULL, NULL);
141     }
142
143     free( pv );
144     w->private_data = NULL;
145 }
146
147 /***********************************************************************
148  * Work
149  ***********************************************************************
150  *
151  **********************************************************************/
152 int encxvidWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
153                  hb_buffer_t ** buf_out )
154 {
155     hb_work_private_t * pv = w->private_data;
156     hb_job_t * job = pv->job;
157     xvid_enc_frame_t frame;
158     hb_buffer_t * in = *buf_in, * buf;
159
160     if ( in->size <= 0 )
161     {
162         /* EOF on input - send it downstream & say we're done */
163         *buf_out = in;
164         *buf_in = NULL;
165        return HB_WORK_DONE;
166     }
167
168     /* Should be way too large */
169     buf = hb_video_buffer_init( job->width, job->height );
170     buf->start = in->start;
171     buf->stop  = in->stop;
172
173     memset( &frame, 0, sizeof( frame ) );
174
175     frame.version = XVID_VERSION;
176     frame.bitstream = buf->data;
177     frame.length = -1;
178     frame.input.plane[0] = in->data;
179     frame.input.csp = XVID_CSP_I420;
180     frame.input.stride[0] = job->width;
181     frame.vol_flags = 0;
182     frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
183                       XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED;
184     if( job->anamorphic.mode )
185     {
186         frame.par = XVID_PAR_EXT;
187         frame.par_width  = job->anamorphic.par_width;
188         frame.par_height = job->anamorphic.par_height;
189     }
190
191     if( job->grayscale )
192     {
193         frame.vop_flags |= XVID_VOP_GREYSCALE;
194     }
195     frame.type = XVID_TYPE_AUTO;
196     frame.quant = pv->quant;
197     frame.motion = XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
198                    XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 |
199                    XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
200                    XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP;
201     frame.quant_intra_matrix = NULL;
202     frame.quant_inter_matrix = NULL;
203
204     buf->size = xvid_encore( pv->xvid, XVID_ENC_ENCODE, &frame, NULL );
205     buf->frametype = ( frame.out_flags & XVID_KEYFRAME ) ? HB_FRAME_KEY : HB_FRAME_REF;
206
207     if( !pv->configDone )
208     {
209         int vol_start, vop_start;
210         for( vol_start = 0; ; vol_start++ )
211         {
212             if( buf->data[vol_start]   == 0x0 &&
213                 buf->data[vol_start+1] == 0x0 &&
214                 buf->data[vol_start+2] == 0x1 &&
215                 buf->data[vol_start+3] == 0x20 )
216             {
217                 break;
218             }
219         }
220         for( vop_start = vol_start + 4; ; vop_start++ )
221         {
222             if( buf->data[vop_start]   == 0x0 &&
223                 buf->data[vop_start+1] == 0x0 &&
224                 buf->data[vop_start+2] == 0x1 &&
225                 buf->data[vop_start+3] == 0xB6 )
226             {
227                 break;
228             }
229         }
230
231         hb_deep_log( 2, "encxvid: VOL size is %d bytes", vop_start - vol_start );
232         job->config.mpeg4.length = vop_start - vol_start;
233         memcpy( job->config.mpeg4.bytes, &buf->data[vol_start],
234                 job->config.mpeg4.length );
235         pv->configDone = 1;
236     }
237
238     *buf_out = buf;
239
240     return HB_WORK_OK;
241 }
242