Commit | Line | Data |
---|---|---|
1ddadfa9 AT |
1 | /* |
2 | * Interface to xvidcore for mpeg4 encoding | |
3 | * Copyright (c) 2004 Adam Thayer <krevnik@comcast.net> | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | */ | |
19 | ||
20 | /** | |
21 | * @file xvidmpeg4.c | |
22 | * Interface to xvidcore for MPEG-4 compliant encoding. | |
23 | * @author Adam Thayer (krevnik@comcast.net) | |
24 | */ | |
25 | ||
26 | #include <xvid.h> | |
27 | #include <unistd.h> | |
28 | #include "common.h" | |
29 | #include "avcodec.h" | |
77b85488 MN |
30 | #ifdef CONFIG_WIN32 |
31 | #include <fcntl.h> | |
32 | #endif | |
1ddadfa9 AT |
33 | |
34 | /** | |
35 | * Buffer management macros. | |
36 | */ | |
37 | #define BUFFER_SIZE 1024 | |
38 | #define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x)) | |
39 | #define BUFFER_CAT(x) (&((x)[strlen(x)])) | |
40 | ||
41 | /* For PPC Use */ | |
42 | #if HAVE_ALTIVEC==1 | |
43 | extern int has_altivec(void); | |
44 | #endif | |
45 | ||
46 | /** | |
47 | * Structure for the private XviD context. | |
48 | * This stores all the private context for the codec. | |
49 | */ | |
50 | typedef struct xvid_context { | |
51 | void *encoder_handle; /** Handle for XviD Encoder */ | |
52 | int xsize, ysize; /** Frame size */ | |
53 | int vop_flags; /** VOP flags for XviD Encoder */ | |
54 | int vol_flags; /** VOL flags for XviD Encoder */ | |
55 | int me_flags; /** Motion Estimation flags */ | |
56 | int qscale; /** Do we use constant scale? */ | |
57 | int quicktime_format; /** Are we in a QT-based format? */ | |
58 | AVFrame encoded_picture; /** Encoded frame information */ | |
59 | char *twopassbuffer; /** Character buffer for two-pass */ | |
60 | char *old_twopassbuffer; /** Old character buffer (two-pass) */ | |
61 | char *twopassfile; /** second pass temp file name */ | |
62 | unsigned char *intra_matrix; /** P-Frame Quant Matrix */ | |
63 | unsigned char *inter_matrix; /** I-Frame Quant Matrix */ | |
64 | } xvid_context_t; | |
65 | ||
66 | /** | |
67 | * Structure for the private first-pass plugin. | |
68 | */ | |
69 | typedef struct xvid_ff_pass1 { | |
70 | int version; /** XviD version */ | |
71 | xvid_context_t *context; /** Pointer to private context */ | |
72 | } xvid_ff_pass1_t; | |
73 | ||
74 | /* Prototypes - See function implementation for details */ | |
75 | int xvid_strip_vol_header(AVCodecContext *avctx, unsigned char *frame, unsigned int header_len, unsigned int frame_len); | |
76 | int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2); | |
77 | void xvid_correct_framerate(AVCodecContext *avctx); | |
78 | ||
79 | /** | |
80 | * Creates the private context for the encoder. | |
81 | * All buffers are allocated, settings are loaded from the user, | |
82 | * and the encoder context created. | |
83 | * | |
84 | * @param avctx AVCodecContext pointer to context | |
85 | * @return Returns 0 on success, -1 on failure | |
86 | */ | |
87 | int ff_xvid_encode_init(AVCodecContext *avctx) { | |
88 | int xerr, i; | |
89 | int xvid_flags = avctx->flags; | |
90 | xvid_context_t *x = avctx->priv_data; | |
91 | uint16_t *intra, *inter; | |
92 | int fd; | |
93 | ||
94 | xvid_plugin_single_t single; | |
95 | xvid_ff_pass1_t rc2pass1; | |
96 | xvid_plugin_2pass2_t rc2pass2; | |
97 | xvid_gbl_init_t xvid_gbl_init; | |
98 | xvid_enc_create_t xvid_enc_create; | |
99 | xvid_enc_plugin_t plugins[7]; | |
100 | ||
101 | /* Bring in VOP flags from ffmpeg command-line */ | |
102 | x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */ | |
103 | if( xvid_flags & CODEC_FLAG_4MV ) | |
104 | x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */ | |
105 | if( xvid_flags & CODEC_FLAG_TRELLIS_QUANT) | |
106 | x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */ | |
107 | if( xvid_flags & CODEC_FLAG_AC_PRED ) | |
108 | x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */ | |
109 | if( xvid_flags & CODEC_FLAG_GRAY ) | |
110 | x->vop_flags |= XVID_VOP_GREYSCALE; | |
111 | ||
112 | /* Decide which ME quality setting to use */ | |
113 | x->me_flags = 0; | |
114 | switch( avctx->me_method ) { | |
115 | case ME_FULL: /* Quality 6 */ | |
116 | x->me_flags |= XVID_ME_EXTSEARCH16 | |
117 | | XVID_ME_EXTSEARCH8; | |
118 | ||
119 | case ME_EPZS: /* Quality 4 */ | |
120 | x->me_flags |= XVID_ME_ADVANCEDDIAMOND8 | |
121 | | XVID_ME_HALFPELREFINE8 | |
122 | | XVID_ME_CHROMA_PVOP | |
123 | | XVID_ME_CHROMA_BVOP; | |
124 | ||
125 | case ME_LOG: /* Quality 2 */ | |
126 | case ME_PHODS: | |
127 | case ME_X1: | |
128 | x->me_flags |= XVID_ME_ADVANCEDDIAMOND16 | |
129 | | XVID_ME_HALFPELREFINE16; | |
130 | ||
131 | case ME_ZERO: /* Quality 0 */ | |
132 | default: | |
133 | break; | |
134 | } | |
135 | ||
136 | /* Decide how we should decide blocks */ | |
137 | switch( avctx->mb_decision ) { | |
138 | case 2: | |
139 | x->vop_flags |= XVID_VOP_MODEDECISION_RD; | |
140 | x->me_flags |= XVID_ME_HALFPELREFINE8_RD | |
141 | | XVID_ME_QUARTERPELREFINE8_RD | |
142 | | XVID_ME_EXTSEARCH_RD | |
143 | | XVID_ME_CHECKPREDICTION_RD; | |
144 | case 1: | |
145 | if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) ) | |
146 | x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD; | |
147 | x->me_flags |= XVID_ME_HALFPELREFINE16_RD | |
148 | | XVID_ME_QUARTERPELREFINE16_RD; | |
149 | ||
150 | default: | |
151 | break; | |
152 | } | |
153 | ||
154 | /* Bring in VOL flags from ffmpeg command-line */ | |
155 | x->vol_flags = 0; | |
156 | if( xvid_flags & CODEC_FLAG_GMC ) { | |
157 | x->vol_flags |= XVID_VOL_GMC; | |
158 | x->me_flags |= XVID_ME_GME_REFINE; | |
159 | } | |
160 | if( xvid_flags & CODEC_FLAG_QPEL ) { | |
161 | x->vol_flags |= XVID_VOL_QUARTERPEL; | |
162 | x->me_flags |= XVID_ME_QUARTERPELREFINE16; | |
163 | if( x->vop_flags & XVID_VOP_INTER4V ) | |
164 | x->me_flags |= XVID_ME_QUARTERPELREFINE8; | |
165 | } | |
166 | ||
167 | memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init)); | |
168 | xvid_gbl_init.version = XVID_VERSION; | |
169 | xvid_gbl_init.debug = 0; | |
170 | ||
171 | #ifdef ARCH_POWERPC | |
172 | /* XviD's PPC support is borked, use libavcodec to detect */ | |
173 | #if HAVE_ALTIVEC==1 | |
174 | if( has_altivec() ) { | |
175 | xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC; | |
176 | } else | |
177 | #endif | |
178 | xvid_gbl_init.cpu_flags = XVID_CPU_FORCE; | |
179 | #else | |
180 | /* XviD can detect on x86 */ | |
181 | xvid_gbl_init.cpu_flags = 0; | |
182 | #endif | |
183 | ||
184 | /* Initialize */ | |
185 | xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL); | |
186 | ||
187 | /* Create the encoder reference */ | |
188 | memset(&xvid_enc_create, 0, sizeof(xvid_enc_create)); | |
189 | xvid_enc_create.version = XVID_VERSION; | |
190 | ||
191 | /* Store the desired frame size */ | |
192 | xvid_enc_create.width = x->xsize = avctx->width; | |
193 | xvid_enc_create.height = x->ysize = avctx->height; | |
194 | ||
195 | /* XviD can determine the proper profile to use */ | |
196 | /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */ | |
197 | ||
198 | /* We don't use zones or threads */ | |
199 | xvid_enc_create.zones = NULL; | |
200 | xvid_enc_create.num_zones = 0; | |
201 | xvid_enc_create.num_threads = 0; | |
202 | ||
203 | xvid_enc_create.plugins = plugins; | |
204 | xvid_enc_create.num_plugins = 0; | |
205 | ||
206 | /* Initialize Buffers */ | |
207 | x->twopassbuffer = NULL; | |
208 | x->old_twopassbuffer = NULL; | |
209 | x->twopassfile = NULL; | |
210 | ||
211 | if( xvid_flags & CODEC_FLAG_PASS1 ) { | |
212 | memset(&rc2pass1, 0, sizeof(xvid_ff_pass1_t)); | |
213 | rc2pass1.version = XVID_VERSION; | |
214 | rc2pass1.context = x; | |
215 | x->twopassbuffer = av_malloc(BUFFER_SIZE); | |
216 | x->old_twopassbuffer = av_malloc(BUFFER_SIZE); | |
217 | if( x->twopassbuffer == NULL || x->old_twopassbuffer == NULL ) { | |
218 | av_log(avctx, AV_LOG_ERROR, | |
219 | "XviD: Cannot allocate 2-pass log buffers\n"); | |
220 | return -1; | |
221 | } | |
222 | x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0; | |
223 | ||
224 | plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass; | |
225 | plugins[xvid_enc_create.num_plugins].param = &rc2pass1; | |
226 | xvid_enc_create.num_plugins++; | |
227 | } else if( xvid_flags & CODEC_FLAG_PASS2 ) { | |
228 | memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t)); | |
229 | rc2pass2.version = XVID_VERSION; | |
230 | rc2pass2.bitrate = avctx->bit_rate; | |
231 | ||
77b85488 MN |
232 | #ifdef CONFIG_WIN32 /* Ugly work around */ |
233 | { | |
234 | char *tempname; | |
235 | ||
236 | tempname = tempnam(".", "xvidff"); | |
237 | fd = -1; | |
238 | if( tempname && | |
239 | (fd = open(tempname, _O_RDWR | _O_BINARY)) != -1 ) { | |
240 | x->twopassfile = av_strdup(tempname); | |
241 | #undef free | |
242 | free(tempname); | |
243 | #define free please_use_av_free | |
244 | if( x->twopassfile == NULL ) { | |
245 | av_log(avctx, AV_LOG_ERROR, | |
246 | "XviD: Cannot allocate 2-pass buffer\n"); | |
247 | return -1; | |
248 | } | |
249 | } | |
250 | } | |
251 | #else | |
1ddadfa9 AT |
252 | x->twopassfile = av_malloc(BUFFER_SIZE); |
253 | if( x->twopassfile == NULL ) { | |
254 | av_log(avctx, AV_LOG_ERROR, | |
255 | "XviD: Cannot allocate 2-pass buffer\n"); | |
256 | return -1; | |
257 | } | |
258 | strcpy(x->twopassfile, "/tmp/xvidff.XXXXXX"); | |
259 | fd = mkstemp(x->twopassfile); | |
3ed4046f MN |
260 | if(fd < 0){ |
261 | strcpy(x->twopassfile, "./xvidff.XXXXXX"); | |
262 | fd = mkstemp(x->twopassfile); | |
263 | } | |
77b85488 | 264 | #endif |
1ddadfa9 AT |
265 | if( fd == -1 ) { |
266 | av_log(avctx, AV_LOG_ERROR, | |
267 | "XviD: Cannot write 2-pass pipe\n"); | |
268 | return -1; | |
269 | } | |
270 | ||
271 | if( avctx->stats_in == NULL ) { | |
272 | av_log(avctx, AV_LOG_ERROR, | |
273 | "XviD: No 2-pass information loaded for second pass\n"); | |
274 | return -1; | |
275 | } | |
276 | ||
277 | if( strlen(avctx->stats_in) > | |
278 | write(fd, avctx->stats_in, strlen(avctx->stats_in)) ) { | |
279 | close(fd); | |
280 | av_log(avctx, AV_LOG_ERROR, | |
281 | "XviD: Cannot write to 2-pass pipe\n"); | |
282 | return -1; | |
283 | } | |
284 | ||
285 | close(fd); | |
286 | rc2pass2.filename = x->twopassfile; | |
287 | plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2; | |
288 | plugins[xvid_enc_create.num_plugins].param = &rc2pass2; | |
289 | xvid_enc_create.num_plugins++; | |
290 | } else if( !(xvid_flags & CODEC_FLAG_QSCALE) ) { | |
291 | /* Single Pass Bitrate Control! */ | |
292 | memset(&single, 0, sizeof(xvid_plugin_single_t)); | |
293 | single.version = XVID_VERSION; | |
294 | single.bitrate = avctx->bit_rate; | |
295 | ||
296 | plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single; | |
297 | plugins[xvid_enc_create.num_plugins].param = &single; | |
298 | xvid_enc_create.num_plugins++; | |
299 | } | |
300 | ||
301 | /* Luminance Masking */ | |
302 | if( 0.0 != avctx->lumi_masking ) { | |
303 | plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking; | |
304 | plugins[xvid_enc_create.num_plugins].param = NULL; | |
305 | xvid_enc_create.num_plugins++; | |
306 | } | |
307 | ||
308 | /* Frame Rate and Key Frames */ | |
309 | xvid_correct_framerate(avctx); | |
c0df9d75 MN |
310 | xvid_enc_create.fincr = avctx->time_base.num; |
311 | xvid_enc_create.fbase = avctx->time_base.den; | |
1ddadfa9 AT |
312 | if( avctx->gop_size > 0 ) |
313 | xvid_enc_create.max_key_interval = avctx->gop_size; | |
314 | else | |
315 | xvid_enc_create.max_key_interval = 240; /* XviD's best default */ | |
316 | ||
317 | /* Quants */ | |
318 | if( xvid_flags & CODEC_FLAG_QSCALE ) x->qscale = 1; | |
319 | else x->qscale = 0; | |
320 | ||
321 | xvid_enc_create.min_quant[0] = avctx->qmin; | |
322 | xvid_enc_create.min_quant[1] = avctx->qmin; | |
323 | xvid_enc_create.min_quant[2] = avctx->qmin; | |
324 | xvid_enc_create.max_quant[0] = avctx->qmax; | |
325 | xvid_enc_create.max_quant[1] = avctx->qmax; | |
326 | xvid_enc_create.max_quant[2] = avctx->qmax; | |
327 | ||
328 | /* Quant Matrices */ | |
329 | x->intra_matrix = x->inter_matrix = NULL; | |
330 | if( avctx->mpeg_quant ) | |
331 | x->vol_flags |= XVID_VOL_MPEGQUANT; | |
332 | if( (avctx->intra_matrix || avctx->inter_matrix) ) { | |
333 | x->vol_flags |= XVID_VOL_MPEGQUANT; | |
334 | ||
335 | if( avctx->intra_matrix ) { | |
336 | intra = avctx->intra_matrix; | |
337 | x->intra_matrix = av_malloc(sizeof(unsigned char) * 64); | |
338 | } else | |
339 | intra = NULL; | |
340 | if( avctx->inter_matrix ) { | |
341 | inter = avctx->inter_matrix; | |
342 | x->inter_matrix = av_malloc(sizeof(unsigned char) * 64); | |
343 | } else | |
344 | inter = NULL; | |
345 | ||
346 | for( i = 0; i < 64; i++ ) { | |
347 | if( intra ) | |
348 | x->intra_matrix[i] = (unsigned char)intra[i]; | |
349 | if( inter ) | |
350 | x->inter_matrix[i] = (unsigned char)inter[i]; | |
351 | } | |
352 | } | |
353 | ||
354 | /* Misc Settings */ | |
355 | xvid_enc_create.frame_drop_ratio = 0; | |
356 | xvid_enc_create.global = 0; | |
357 | if( xvid_flags & CODEC_FLAG_CLOSED_GOP ) | |
358 | xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP; | |
359 | ||
360 | /* Determines which codec mode we are operating in */ | |
361 | avctx->extradata = NULL; | |
362 | avctx->extradata_size = 0; | |
363 | if( xvid_flags & CODEC_FLAG_GLOBAL_HEADER ) { | |
364 | /* In this case, we are claiming to be MPEG4 */ | |
365 | x->quicktime_format = 1; | |
366 | avctx->codec_id = CODEC_ID_MPEG4; | |
367 | } else { | |
368 | /* We are claiming to be XviD */ | |
369 | x->quicktime_format = 0; | |
370 | avctx->codec_tag = ff_get_fourcc("xvid"); | |
371 | } | |
372 | ||
373 | /* Bframes */ | |
374 | xvid_enc_create.max_bframes = avctx->max_b_frames; | |
375 | xvid_enc_create.bquant_offset = avctx->b_quant_offset; | |
376 | xvid_enc_create.bquant_ratio = 100 * avctx->b_quant_factor; | |
377 | if( avctx->max_b_frames > 0 && !x->quicktime_format ) xvid_enc_create.global |= XVID_GLOBAL_PACKED; | |
378 | ||
379 | /* Create encoder context */ | |
380 | xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); | |
381 | if( xerr ) { | |
382 | av_log(avctx, AV_LOG_ERROR, "XviD: Could not create encoder reference\n"); | |
383 | return -1; | |
384 | } | |
385 | ||
386 | x->encoder_handle = xvid_enc_create.handle; | |
387 | avctx->coded_frame = &x->encoded_picture; | |
388 | ||
389 | return 0; | |
390 | } | |
391 | ||
392 | /** | |
393 | * Encodes a single frame. | |
394 | * | |
395 | * @param avctx AVCodecContext pointer to context | |
396 | * @param frame Pointer to encoded frame buffer | |
397 | * @param buf_size Size of encoded frame buffer | |
398 | * @param data Pointer to AVFrame of unencoded frame | |
399 | * @return Returns 0 on success, -1 on failure | |
400 | */ | |
401 | int ff_xvid_encode_frame(AVCodecContext *avctx, | |
402 | unsigned char *frame, int buf_size, void *data) { | |
403 | int xerr, i; | |
404 | char *tmp; | |
405 | xvid_context_t *x = avctx->priv_data; | |
406 | AVFrame *picture = data; | |
407 | AVFrame *p = &(x->encoded_picture); | |
408 | ||
409 | xvid_enc_frame_t xvid_enc_frame; | |
410 | xvid_enc_stats_t xvid_enc_stats; | |
411 | ||
412 | /* Start setting up the frame */ | |
413 | memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame)); | |
414 | xvid_enc_frame.version = XVID_VERSION; | |
415 | memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats)); | |
416 | xvid_enc_stats.version = XVID_VERSION; | |
417 | *p = *picture; | |
418 | ||
419 | /* Let XviD know where to put the frame. */ | |
420 | xvid_enc_frame.bitstream = frame; | |
421 | xvid_enc_frame.length = buf_size; | |
422 | ||
423 | /* Initialize input image fields */ | |
424 | if( avctx->pix_fmt != PIX_FMT_YUV420P ) { | |
425 | av_log(avctx, AV_LOG_ERROR, "XviD: Color spaces other than 420p not supported\n"); | |
426 | return -1; | |
427 | } | |
428 | ||
429 | xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */ | |
430 | ||
431 | for( i = 0; i < 4; i++ ) { | |
432 | xvid_enc_frame.input.plane[i] = picture->data[i]; | |
433 | xvid_enc_frame.input.stride[i] = picture->linesize[i]; | |
434 | } | |
435 | ||
436 | /* Encoder Flags */ | |
437 | xvid_enc_frame.vop_flags = x->vop_flags; | |
438 | xvid_enc_frame.vol_flags = x->vol_flags; | |
439 | xvid_enc_frame.motion = x->me_flags; | |
440 | xvid_enc_frame.type = XVID_TYPE_AUTO; | |
441 | ||
442 | /* Quant Setting */ | |
443 | if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA; | |
444 | else xvid_enc_frame.quant = 0; | |
445 | ||
446 | /* Matrices */ | |
447 | xvid_enc_frame.quant_intra_matrix = x->intra_matrix; | |
448 | xvid_enc_frame.quant_inter_matrix = x->inter_matrix; | |
449 | ||
450 | /* Encode */ | |
451 | xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE, | |
452 | &xvid_enc_frame, &xvid_enc_stats); | |
453 | ||
454 | /* Two-pass log buffer swapping */ | |
455 | avctx->stats_out = NULL; | |
456 | if( x->twopassbuffer ) { | |
457 | tmp = x->old_twopassbuffer; | |
458 | x->old_twopassbuffer = x->twopassbuffer; | |
459 | x->twopassbuffer = tmp; | |
460 | x->twopassbuffer[0] = 0; | |
461 | if( x->old_twopassbuffer[0] != 0 ) { | |
462 | avctx->stats_out = x->old_twopassbuffer; | |
463 | } | |
464 | } | |
465 | ||
466 | if( 0 <= xerr ) { | |
467 | p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; | |
468 | if( xvid_enc_stats.type == XVID_TYPE_PVOP ) | |
469 | p->pict_type = FF_P_TYPE; | |
470 | else if( xvid_enc_stats.type == XVID_TYPE_BVOP ) | |
471 | p->pict_type = FF_B_TYPE; | |
472 | else if( xvid_enc_stats.type == XVID_TYPE_SVOP ) | |
9b21f056 | 473 | p->pict_type = FF_S_TYPE; |
1ddadfa9 AT |
474 | else |
475 | p->pict_type = FF_I_TYPE; | |
476 | if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) { | |
477 | p->key_frame = 1; | |
478 | if( x->quicktime_format ) | |
479 | return xvid_strip_vol_header(avctx, frame, | |
480 | xvid_enc_stats.hlength, xerr); | |
481 | } else | |
482 | p->key_frame = 0; | |
483 | ||
484 | return xerr; | |
485 | } else { | |
486 | av_log(avctx, AV_LOG_ERROR, "XviD: Encoding Error Occurred: %i\n", xerr); | |
487 | return -1; | |
488 | } | |
489 | } | |
490 | ||
491 | /** | |
492 | * Destroys the private context for the encoder. | |
493 | * All buffers are freed, and the XviD encoder context is destroyed. | |
494 | * | |
495 | * @param avctx AVCodecContext pointer to context | |
496 | * @return Returns 0, success guaranteed | |
497 | */ | |
498 | int ff_xvid_encode_close(AVCodecContext *avctx) { | |
499 | xvid_context_t *x = avctx->priv_data; | |
500 | ||
501 | xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); | |
502 | ||
503 | if( avctx->extradata != NULL ) | |
504 | av_free(avctx->extradata); | |
505 | if( x->twopassbuffer != NULL ) { | |
506 | av_free(x->twopassbuffer); | |
507 | av_free(x->old_twopassbuffer); | |
508 | } | |
509 | if( x->twopassfile != NULL ) | |
510 | av_free(x->twopassfile); | |
511 | if( x->intra_matrix != NULL ) | |
512 | av_free(x->intra_matrix); | |
513 | if( x->inter_matrix != NULL ) | |
514 | av_free(x->inter_matrix); | |
515 | ||
516 | return 0; | |
517 | } | |
518 | ||
519 | /** | |
520 | * Routine to create a global VO/VOL header for MP4 container. | |
521 | * What we do here is extract the header from the XviD bitstream | |
522 | * as it is encoded. We also strip the repeated headers from the | |
523 | * bitstream when a global header is requested for MPEG-4 ISO | |
524 | * compliance. | |
525 | * | |
526 | * @param avctx AVCodecContext pointer to context | |
527 | * @param frame Pointer to encoded frame data | |
528 | * @param header_len Length of header to search | |
529 | * @param frame_len Length of encoded frame data | |
530 | * @return Returns new length of frame data | |
531 | */ | |
532 | int xvid_strip_vol_header(AVCodecContext *avctx, | |
533 | unsigned char *frame, | |
534 | unsigned int header_len, | |
535 | unsigned int frame_len) { | |
536 | int vo_len = 0, i; | |
537 | ||
538 | for( i = 0; i < header_len - 3; i++ ) { | |
539 | if( frame[i] == 0x00 && | |
540 | frame[i+1] == 0x00 && | |
541 | frame[i+2] == 0x01 && | |
542 | frame[i+3] == 0xB6 ) { | |
543 | vo_len = i; | |
544 | break; | |
545 | } | |
546 | } | |
547 | ||
548 | if( vo_len > 0 ) { | |
549 | /* We need to store the header, so extract it */ | |
550 | if( avctx->extradata == NULL ) { | |
551 | avctx->extradata = av_malloc(vo_len); | |
552 | memcpy(avctx->extradata, frame, vo_len); | |
553 | avctx->extradata_size = vo_len; | |
554 | } | |
555 | /* Less dangerous now, memmove properly copies the two | |
556 | chunks of overlapping data */ | |
557 | memmove(frame, &(frame[vo_len]), frame_len - vo_len); | |
558 | return frame_len - vo_len; | |
559 | } else | |
560 | return frame_len; | |
561 | } | |
562 | ||
563 | /** | |
564 | * Routine to correct a possibly erroneous framerate being fed to us. | |
565 | * XviD currently chokes on framerates where the ticks per frame is | |
566 | * extremely large. This function works to correct problems in this area | |
567 | * by estimating a new framerate and taking the simpler fraction of | |
568 | * the two presented. | |
569 | * | |
570 | * @param avctx Context that contains the framerate to correct. | |
571 | */ | |
572 | void xvid_correct_framerate(AVCodecContext *avctx) { | |
573 | int frate, fbase; | |
574 | int est_frate, est_fbase; | |
575 | int gcd; | |
576 | float est_fps, fps; | |
577 | ||
c0df9d75 MN |
578 | frate = avctx->time_base.den; |
579 | fbase = avctx->time_base.num; | |
1ddadfa9 AT |
580 | |
581 | gcd = ff_gcd(frate, fbase); | |
582 | if( gcd > 1 ) { | |
583 | frate /= gcd; | |
584 | fbase /= gcd; | |
585 | } | |
586 | ||
587 | if( frate <= 65000 && fbase <= 65000 ) { | |
c0df9d75 MN |
588 | avctx->time_base.den = frate; |
589 | avctx->time_base.num = fbase; | |
1ddadfa9 AT |
590 | return; |
591 | } | |
592 | ||
593 | fps = (float)frate / (float)fbase; | |
594 | est_fps = roundf(fps * 1000.0) / 1000.0; | |
595 | ||
596 | est_frate = (int)est_fps; | |
597 | if( est_fps > (int)est_fps ) { | |
598 | est_frate = (est_frate + 1) * 1000; | |
599 | est_fbase = (int)roundf((float)est_frate / est_fps); | |
600 | } else | |
601 | est_fbase = 1; | |
602 | ||
603 | gcd = ff_gcd(est_frate, est_fbase); | |
604 | if( gcd > 1 ) { | |
605 | est_frate /= gcd; | |
606 | est_fbase /= gcd; | |
607 | } | |
608 | ||
609 | if( fbase > est_fbase ) { | |
c0df9d75 MN |
610 | avctx->time_base.den = est_frate; |
611 | avctx->time_base.num = est_fbase; | |
1ddadfa9 AT |
612 | av_log(avctx, AV_LOG_DEBUG, |
613 | "XviD: framerate re-estimated: %.2f, %.3f%% correction\n", | |
614 | est_fps, (((est_fps - fps)/fps) * 100.0)); | |
615 | } else { | |
c0df9d75 MN |
616 | avctx->time_base.den = frate; |
617 | avctx->time_base.num = fbase; | |
1ddadfa9 AT |
618 | } |
619 | } | |
620 | ||
621 | /* | |
622 | * XviD 2-Pass Kludge Section | |
623 | * | |
624 | * XviD's default 2-pass doesn't allow us to create data as we need to, so | |
625 | * this section spends time replacing the first pass plugin so we can write | |
626 | * statistic information as libavcodec requests in. We have another kludge | |
627 | * that allows us to pass data to the second pass in XviD without a custom | |
628 | * rate-control plugin. | |
629 | */ | |
630 | ||
631 | /** | |
632 | * Initializes the two-pass plugin and context. | |
633 | * | |
634 | * @param param Input construction parameter structure | |
635 | * @param handle Private context handle | |
636 | * @return Returns XVID_ERR_xxxx on failure, or 0 on success. | |
637 | */ | |
638 | static int xvid_ff_2pass_create(xvid_plg_create_t * param, | |
639 | void ** handle) { | |
640 | xvid_ff_pass1_t *x = (xvid_ff_pass1_t *)param->param; | |
641 | char *log = x->context->twopassbuffer; | |
642 | ||
643 | /* Do a quick bounds check */ | |
644 | if( log == NULL ) | |
645 | return XVID_ERR_FAIL; | |
646 | ||
647 | /* We use snprintf() */ | |
648 | /* This is because we can safely prevent a buffer overflow */ | |
649 | log[0] = 0; | |
650 | snprintf(log, BUFFER_REMAINING(log), | |
651 | "# ffmpeg 2-pass log file, using xvid codec\n"); | |
652 | snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), | |
653 | "# Do not modify. libxvidcore version: %d.%d.%d\n\n", | |
654 | XVID_VERSION_MAJOR(XVID_VERSION), | |
655 | XVID_VERSION_MINOR(XVID_VERSION), | |
656 | XVID_VERSION_PATCH(XVID_VERSION)); | |
657 | ||
658 | *handle = x->context; | |
659 | return 0; | |
660 | } | |
661 | ||
662 | /** | |
663 | * Destroys the two-pass plugin context. | |
664 | * | |
665 | * @param ref Context pointer for the plugin | |
666 | * @param param Destrooy context | |
667 | * @return Returns 0, success guaranteed | |
668 | */ | |
669 | static int xvid_ff_2pass_destroy(xvid_context_t *ref, | |
670 | xvid_plg_destroy_t *param) { | |
671 | /* Currently cannot think of anything to do on destruction */ | |
672 | /* Still, the framework should be here for reference/use */ | |
673 | if( ref->twopassbuffer != NULL ) | |
674 | ref->twopassbuffer[0] = 0; | |
675 | return 0; | |
676 | } | |
677 | ||
678 | /** | |
679 | * Enables fast encode mode during the first pass. | |
680 | * | |
681 | * @param ref Context pointer for the plugin | |
682 | * @param param Frame data | |
683 | * @return Returns 0, success guaranteed | |
684 | */ | |
685 | static int xvid_ff_2pass_before(xvid_context_t *ref, | |
686 | xvid_plg_data_t *param) { | |
687 | int motion_remove; | |
688 | int motion_replacements; | |
689 | int vop_remove; | |
690 | ||
691 | /* Nothing to do here, result is changed too much */ | |
692 | if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) | |
693 | return 0; | |
694 | ||
695 | /* We can implement a 'turbo' first pass mode here */ | |
696 | param->quant = 2; | |
697 | ||
698 | /* Init values */ | |
699 | motion_remove = ~XVID_ME_CHROMA_PVOP & | |
700 | ~XVID_ME_CHROMA_BVOP & | |
701 | ~XVID_ME_EXTSEARCH16 & | |
702 | ~XVID_ME_ADVANCEDDIAMOND16; | |
703 | motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | | |
704 | XVID_ME_SKIP_DELTASEARCH | | |
705 | XVID_ME_FASTREFINE16 | | |
706 | XVID_ME_BFRAME_EARLYSTOP; | |
707 | vop_remove = ~XVID_VOP_MODEDECISION_RD & | |
708 | ~XVID_VOP_FAST_MODEDECISION_RD & | |
709 | ~XVID_VOP_TRELLISQUANT & | |
710 | ~XVID_VOP_INTER4V & | |
711 | ~XVID_VOP_HQACPRED; | |
712 | ||
713 | param->vol_flags &= ~XVID_VOL_GMC; | |
714 | param->vop_flags &= vop_remove; | |
715 | param->motion_flags &= motion_remove; | |
716 | param->motion_flags |= motion_replacements; | |
717 | ||
718 | return 0; | |
719 | } | |
720 | ||
721 | /** | |
722 | * Captures statistic data and writes it during first pass. | |
723 | * | |
724 | * @param ref Context pointer for the plugin | |
725 | * @param param Statistic data | |
726 | * @return Returns XVID_ERR_xxxx on failure, or 0 on success | |
727 | */ | |
728 | static int xvid_ff_2pass_after(xvid_context_t *ref, | |
729 | xvid_plg_data_t *param) { | |
730 | char *log = ref->twopassbuffer; | |
731 | char *frame_types = " ipbs"; | |
732 | char frame_type; | |
733 | ||
734 | /* Quick bounds check */ | |
735 | if( log == NULL ) | |
736 | return XVID_ERR_FAIL; | |
737 | ||
738 | /* Convert the type given to us into a character */ | |
739 | if( param->type < 5 && param->type > 0 ) { | |
740 | frame_type = frame_types[param->type]; | |
741 | } else { | |
742 | return XVID_ERR_FAIL; | |
743 | } | |
744 | ||
745 | snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), | |
746 | "%c %d %d %d %d %d %d\n", | |
747 | frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, | |
748 | param->stats.ublks, param->stats.length, param->stats.hlength); | |
749 | ||
750 | return 0; | |
751 | } | |
752 | ||
753 | /** | |
754 | * Dispatch function for our custom plugin. | |
755 | * This handles the dispatch for the XviD plugin. It passes data | |
756 | * on to other functions for actual processing. | |
757 | * | |
758 | * @param ref Context pointer for the plugin | |
759 | * @param cmd The task given for us to complete | |
760 | * @param p1 First parameter (varies) | |
761 | * @param p2 Second parameter (varies) | |
762 | * @return Returns XVID_ERR_xxxx on failure, or 0 on success | |
763 | */ | |
764 | int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) { | |
765 | switch( cmd ) { | |
766 | case XVID_PLG_INFO: | |
767 | case XVID_PLG_FRAME: | |
768 | return 0; | |
769 | ||
770 | case XVID_PLG_BEFORE: | |
771 | return xvid_ff_2pass_before(ref, p1); | |
772 | ||
773 | case XVID_PLG_CREATE: | |
774 | return xvid_ff_2pass_create(p1, p2); | |
775 | ||
776 | case XVID_PLG_AFTER: | |
777 | return xvid_ff_2pass_after(ref, p1); | |
778 | ||
779 | case XVID_PLG_DESTROY: | |
780 | return xvid_ff_2pass_destroy(ref, p1); | |
781 | ||
782 | default: | |
783 | return XVID_ERR_FAIL; | |
784 | } | |
785 | } | |
786 | ||
787 | /** | |
788 | * XviD codec definition for libavcodec. | |
789 | */ | |
790 | AVCodec xvid_encoder = { | |
791 | "xvid", | |
792 | CODEC_TYPE_VIDEO, | |
793 | CODEC_ID_XVID, | |
794 | sizeof(xvid_context_t), | |
795 | ff_xvid_encode_init, | |
796 | ff_xvid_encode_frame, | |
797 | ff_xvid_encode_close | |
798 | }; |