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