7332
|
1 #define HAVE_XVID_VBR
|
5550
|
2 #include <stdio.h>
|
|
3 #include <stdlib.h>
|
|
4 #include <string.h>
|
|
5
|
|
6 #include "../config.h"
|
|
7 #include "../mp_msg.h"
|
|
8
|
|
9 #ifdef HAVE_DIVX4ENCORE
|
|
10
|
|
11 #include "codec-cfg.h"
|
|
12 #include "stream.h"
|
|
13 #include "demuxer.h"
|
|
14 #include "stheader.h"
|
|
15
|
|
16 #include "aviwrite.h"
|
|
17
|
5607
|
18 #include "img_format.h"
|
|
19 #include "mp_image.h"
|
5550
|
20 #include "vf.h"
|
|
21
|
7332
|
22 /* About XviD VBR Library, Edouard Gomez (GomGom) said:
|
|
23 <GomGom> header bytes == frame header bytes :-)
|
|
24 <GomGom> total bytes = frame bytes == texture + header
|
|
25 <GomGom> quant = quant returned by xvidcore
|
|
26 <GomGom> it's possible that xvid lowers or increases the passed quant because of lumimasking
|
|
27 <GomGom> kblks = blocks coded as intra blocks
|
|
28 <GomGom> mblks = blocks coded as predicted blocks
|
|
29 <GomGom> ublks = skipped blocks
|
|
30 <GomGom> at the moemnt le vbr lib uses total bytes, and quant
|
|
31 <GomGom> so it's easy to use it with divx5 (wo bframes)
|
|
32 <klOUg> bframes breaks what assumptions?
|
|
33 <GomGom> quant estimation for next frame
|
|
34 <GomGom> because of the bframe quant multiplier given to divx5
|
|
35 <GomGom> that the vbr lib does not "know"
|
|
36 */
|
|
37
|
5550
|
38 //===========================================================================//
|
|
39
|
|
40 #include "divx4_vbr.h"
|
7332
|
41 #ifdef HAVE_XVID_VBR
|
|
42 #include "xvid_vbr.h"
|
|
43 #endif
|
5550
|
44
|
|
45 extern int pass;
|
|
46 extern char* passtmpfile;
|
7127
|
47 extern void mencoder_write_chunk(aviwrite_stream_t *s,int len,unsigned int flags);
|
5550
|
48
|
|
49 #include <encore2.h>
|
|
50
|
5854
|
51 #ifndef ENCORE_MAJOR_VERSION
|
|
52 #define ENCORE_MAJOR_VERSION 4000
|
|
53 #endif
|
|
54
|
5550
|
55 ENC_PARAM divx4_param;
|
|
56 int divx4_crispness;
|
7332
|
57 #ifdef HAVE_XVID_VBR
|
|
58 static int vbrpass = -1;
|
|
59 static int vbrdebug = 0;
|
|
60 #endif
|
5550
|
61
|
|
62 #include "cfgparser.h"
|
|
63
|
|
64 struct config divx4opts_conf[]={
|
|
65 {"br", &divx4_param.bitrate, CONF_TYPE_INT, CONF_RANGE, 4, 24000000, NULL},
|
|
66 {"rc_period", &divx4_param.rc_period, CONF_TYPE_INT, 0,0,0, NULL},
|
|
67 {"rc_reaction_period", &divx4_param.rc_reaction_period, CONF_TYPE_INT, 0,0,0, NULL},
|
|
68 {"rc_reaction_ratio", &divx4_param.rc_reaction_ratio, CONF_TYPE_INT, 0,0,0, NULL},
|
|
69 {"min_quant", &divx4_param.min_quantizer, CONF_TYPE_INT, CONF_RANGE,0,32, NULL},
|
|
70 {"max_quant", &divx4_param.max_quantizer, CONF_TYPE_INT, CONF_RANGE,0,32, NULL},
|
|
71 {"key", &divx4_param.max_key_interval, CONF_TYPE_INT, CONF_MIN,0,0, NULL},
|
|
72 {"deinterlace", &divx4_param.deinterlace, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
73 {"q", &divx4_param.quality, CONF_TYPE_INT, CONF_RANGE, 1, 5, NULL},
|
|
74 {"crispness", &divx4_crispness, CONF_TYPE_INT, CONF_RANGE,0,100, NULL},
|
5854
|
75 #if ENCORE_MAJOR_VERSION >= 5010
|
|
76 {"bidirect", &divx4_param.extensions.use_bidirect, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
77 {"obmc", &divx4_param.extensions.obmc, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
78 {"data_partitioning", &divx4_param.extensions.data_partitioning, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
79 {"qpel", &divx4_param.extensions.quarter_pel, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
80 {"intra_frame_threshold", &divx4_param.extensions.intra_frame_threshold, CONF_TYPE_INT, CONF_RANGE,1,100, NULL},
|
|
81 {"psychovisual", &divx4_param.extensions.psychovisual, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
82 {"testing_param", &divx4_param.extensions.testing_param, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
83 {"gmc", &divx4_param.extensions.use_gmc, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
84 {"interlace_mode", &divx4_param.extensions.interlace_mode, CONF_TYPE_INT, CONF_RANGE,0,2, NULL},
|
|
85 {"temporal", &divx4_param.extensions.temporal_enable, CONF_TYPE_FLAG, 0,0,1, NULL},
|
|
86 {"spatial", &divx4_param.extensions.spatial_passes, CONF_TYPE_INT, 0,0,1, NULL},
|
|
87 {"mv_file", &divx4_param.extensions.mv_file, CONF_TYPE_STRING, 0,0,1, NULL},
|
|
88 #endif
|
7332
|
89 #ifdef HAVE_XVID_VBR
|
|
90 {"vbrpass", &vbrpass, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL},
|
|
91 {"vbrdebug", &vbrdebug, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL},
|
|
92 #endif
|
5550
|
93 {"help", "TODO: divx4opts help!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
|
|
94 {NULL, NULL, 0, 0, 0, 0, NULL}
|
|
95 };
|
|
96
|
|
97 struct vf_priv_s {
|
|
98 aviwrite_stream_t* mux;
|
|
99 ENC_RESULT enc_result;
|
|
100 ENC_FRAME enc_frame;
|
|
101 void* enc_handle;
|
7332
|
102 #ifdef HAVE_XVID_VBR
|
|
103 vbr_control_t vbr_state;
|
|
104 #endif
|
5550
|
105 };
|
|
106
|
|
107 #define mux_v (vf->priv->mux)
|
|
108
|
|
109 static int config(struct vf_instance_s* vf,
|
|
110 int width, int height, int d_width, int d_height,
|
|
111 unsigned int flags, unsigned int outfmt){
|
|
112
|
|
113 mux_v->bih->biWidth=width;
|
|
114 mux_v->bih->biHeight=height;
|
|
115
|
|
116 divx4_param.x_dim=width;
|
|
117 divx4_param.y_dim=height;
|
|
118 divx4_param.framerate=(float)mux_v->h.dwRate/mux_v->h.dwScale;
|
|
119 mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*3;
|
|
120
|
|
121 if(!divx4_param.bitrate) divx4_param.bitrate=800000;
|
|
122 else if(divx4_param.bitrate<=16000) divx4_param.bitrate*=1000;
|
|
123 if(!divx4_param.quality) divx4_param.quality=5; // the quality of compression ( 1 - fastest, 5 - best )
|
|
124
|
5551
|
125 // set some usefull defaults:
|
|
126 if(!divx4_param.min_quantizer) divx4_param.min_quantizer=2;
|
|
127 if(!divx4_param.max_quantizer) divx4_param.max_quantizer=31;
|
|
128 if(!divx4_param.rc_period) divx4_param.rc_period=2000;
|
|
129 if(!divx4_param.rc_reaction_period) divx4_param.rc_reaction_period=10;
|
|
130 if(!divx4_param.rc_reaction_ratio) divx4_param.rc_reaction_ratio=20;
|
|
131
|
7332
|
132 #ifdef HAVE_XVID_VBR
|
|
133 if (vbrpass >= 0) {
|
|
134 vbrSetDefaults(&vf->priv->vbr_state);
|
|
135 vf->priv->vbr_state.desired_bitrate = divx4_param.bitrate;
|
|
136 switch (vbrpass) {
|
|
137 case 0:
|
|
138 vf->priv->vbr_state.mode = VBR_MODE_1PASS;
|
|
139 break;
|
|
140 case 1:
|
|
141 vf->priv->vbr_state.mode = VBR_MODE_2PASS_1;
|
|
142 break;
|
|
143 case 2:
|
|
144 vf->priv->vbr_state.mode = VBR_MODE_2PASS_2;
|
|
145 break;
|
|
146 default:
|
|
147 abort();
|
|
148 }
|
|
149 vf->priv->vbr_state.debug = vbrdebug;
|
|
150 if (vbrInit(&vf->priv->vbr_state) == -1)
|
|
151 abort();
|
|
152 /* XXX - kludge to workaround some DivX encoder limitations */
|
|
153 if (vf->priv->vbr_state.mode != VBR_MODE_2PASS_2)
|
|
154 divx4_param.min_quantizer = divx4_param.max_quantizer = vbrGetQuant(&vf->priv->vbr_state);
|
|
155 }
|
|
156 #endif
|
|
157
|
5550
|
158 divx4_param.handle=NULL;
|
|
159 encore(NULL,ENC_OPT_INIT,&divx4_param,NULL);
|
|
160 vf->priv->enc_handle=divx4_param.handle;
|
|
161 switch(outfmt){
|
|
162 case IMGFMT_YV12: vf->priv->enc_frame.colorspace=ENC_CSP_YV12; break;
|
|
163 case IMGFMT_IYUV:
|
|
164 case IMGFMT_I420: vf->priv->enc_frame.colorspace=ENC_CSP_I420; break;
|
|
165 case IMGFMT_YUY2: vf->priv->enc_frame.colorspace=ENC_CSP_YUY2; break;
|
|
166 case IMGFMT_UYVY: vf->priv->enc_frame.colorspace=ENC_CSP_UYVY; break;
|
|
167 case IMGFMT_RGB24:
|
|
168 case IMGFMT_BGR24:
|
|
169 vf->priv->enc_frame.colorspace=ENC_CSP_RGB24; break;
|
|
170 default:
|
|
171 mp_msg(MSGT_MENCODER,MSGL_ERR,"divx4: unsupported picture format (%s)!\n",
|
|
172 vo_format_name(outfmt));
|
|
173 return 0;
|
|
174 }
|
|
175
|
|
176 switch(pass){
|
|
177 case 1:
|
|
178 if (VbrControl_init_2pass_vbr_analysis(passtmpfile, divx4_param.quality) == -1){
|
|
179 mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
|
|
180 pass=0;
|
|
181 }
|
|
182 break;
|
|
183 case 2:
|
|
184 if (VbrControl_init_2pass_vbr_encoding(passtmpfile,
|
|
185 divx4_param.bitrate,
|
|
186 divx4_param.framerate,
|
|
187 divx4_crispness,
|
|
188 divx4_param.quality) == -1){
|
|
189 mp_msg(MSGT_MENCODER,MSGL_ERR,"2pass failed: filename=%s\n", passtmpfile);
|
|
190 pass=0;
|
|
191 }
|
|
192 break;
|
|
193 }
|
|
194
|
|
195 return 1;
|
|
196 }
|
|
197
|
7332
|
198 #ifdef HAVE_XVID_VBR
|
|
199 static void uninit(struct vf_instance_s* vf){
|
|
200 if (vbrpass >= 0 && vbrFinish(&vf->priv->vbr_state) == -1)
|
|
201 abort();
|
|
202 }
|
|
203 #endif
|
|
204
|
5550
|
205 static int control(struct vf_instance_s* vf, int request, void* data){
|
|
206
|
|
207 return CONTROL_UNKNOWN;
|
|
208 }
|
|
209
|
|
210 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
|
|
211 switch(fmt){
|
|
212 case IMGFMT_YV12:
|
|
213 case IMGFMT_IYUV:
|
|
214 case IMGFMT_I420:
|
|
215 return 3; // no conversion
|
|
216 case IMGFMT_YUY2:
|
|
217 case IMGFMT_UYVY:
|
5706
|
218 return 1; // conversion
|
5550
|
219 case IMGFMT_RGB24:
|
|
220 case IMGFMT_BGR24:
|
5706
|
221 return 1 | VFCAP_FLIPPED; // conversion+flipped
|
5550
|
222 }
|
|
223 return 0;
|
|
224 }
|
|
225
|
|
226 static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
|
|
227 ENC_RESULT enc_result;
|
|
228 vf->priv->enc_frame.image=mpi->planes[0];
|
|
229 vf->priv->enc_frame.bitstream=mux_v->buffer;
|
|
230 vf->priv->enc_frame.length=mux_v->buffer_size;
|
|
231 vf->priv->enc_frame.mvs=NULL;
|
7332
|
232 #ifdef HAVE_XVID_VBR
|
|
233 if (vbrpass >= 0) {
|
|
234 int quant = vbrGetQuant(&vf->priv->vbr_state);
|
|
235 int intra = vbrGetIntra(&vf->priv->vbr_state);
|
|
236 vf->priv->enc_frame.quant = quant ? quant : 1;
|
|
237 vf->priv->enc_frame.intra = intra;
|
|
238 /* XXX - kludge to workaround some DivX encoder limitations:
|
|
239 only pass 2 needs to call encore with VBR, and then it does
|
|
240 not report quantizer and intra*/
|
|
241 if (vf->priv->vbr_state.mode != VBR_MODE_2PASS_2)
|
|
242 encore(vf->priv->enc_handle, ENC_OPT_ENCODE, &vf->priv->enc_frame, &enc_result);
|
|
243 else {
|
|
244 encore(vf->priv->enc_handle, ENC_OPT_ENCODE_VBR, &vf->priv->enc_frame, &enc_result);
|
|
245 enc_result.quantizer = quant;
|
|
246 if (intra >= 0)
|
|
247 enc_result.is_key_frame = intra;
|
|
248 }
|
|
249 if (vbrUpdate(&vf->priv->vbr_state, enc_result.quantizer, enc_result.is_key_frame,
|
|
250 (enc_result.total_bits - enc_result.texture_bits) / 8, enc_result.total_bits / 8,
|
|
251 0, 0, 0) == -1)
|
|
252 abort();
|
|
253 }
|
|
254 else
|
|
255 #endif
|
5550
|
256 if(pass==2){ // handle 2-pass:
|
|
257 vf->priv->enc_frame.quant = VbrControl_get_quant();
|
|
258 vf->priv->enc_frame.intra = VbrControl_get_intra();
|
|
259 encore(vf->priv->enc_handle,ENC_OPT_ENCODE_VBR,&vf->priv->enc_frame,&enc_result);
|
|
260 VbrControl_update_2pass_vbr_encoding(enc_result.motion_bits,
|
|
261 enc_result.texture_bits,
|
|
262 enc_result.total_bits);
|
|
263 } else {
|
|
264 vf->priv->enc_frame.quant=0;
|
|
265 vf->priv->enc_frame.intra=0;
|
|
266 encore(vf->priv->enc_handle,ENC_OPT_ENCODE,&vf->priv->enc_frame,&enc_result);
|
|
267 if(pass==1){
|
|
268 VbrControl_update_2pass_vbr_analysis(enc_result.is_key_frame,
|
|
269 enc_result.motion_bits,
|
|
270 enc_result.texture_bits,
|
|
271 enc_result.total_bits,
|
|
272 enc_result.quantizer);
|
|
273 }
|
|
274 }
|
5551
|
275 mencoder_write_chunk(mux_v,vf->priv->enc_frame.length,enc_result.is_key_frame?0x10:0);
|
5550
|
276 }
|
|
277
|
|
278 //===========================================================================//
|
|
279
|
|
280 static int vf_open(vf_instance_t *vf, char* args){
|
|
281 vf->config=config;
|
|
282 vf->control=control;
|
|
283 vf->query_format=query_format;
|
|
284 vf->put_image=put_image;
|
7332
|
285 #ifdef HAVE_XVID_VBR
|
|
286 vf->uninit = uninit;
|
|
287 #endif
|
5550
|
288 vf->priv=malloc(sizeof(struct vf_priv_s));
|
|
289 memset(vf->priv,0,sizeof(struct vf_priv_s));
|
7127
|
290 vf->priv->mux=(aviwrite_stream_t*)args;
|
5550
|
291
|
|
292 mux_v->bih=malloc(sizeof(BITMAPINFOHEADER));
|
|
293 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
|
|
294 mux_v->bih->biWidth=0;
|
|
295 mux_v->bih->biHeight=0;
|
|
296 mux_v->bih->biPlanes=1;
|
|
297 mux_v->bih->biBitCount=24;
|
5854
|
298 #if ENCORE_MAJOR_VERSION >= 5010
|
|
299 mux_v->bih->biCompression=mmioFOURCC('D','X','5','0');
|
|
300 #else
|
5550
|
301 mux_v->bih->biCompression=mmioFOURCC('d','i','v','x');
|
5854
|
302 #endif
|
5550
|
303
|
|
304 return 1;
|
|
305 }
|
|
306
|
|
307 vf_info_t ve_info_divx4 = {
|
|
308 "divx4 encoder",
|
|
309 "divx4",
|
|
310 "A'rpi",
|
|
311 "for internal use by mencoder",
|
|
312 vf_open
|
|
313 };
|
|
314
|
|
315 //===========================================================================//
|
|
316 #endif
|