5 * Copyright (C) <2006> Mark Nauwelaerts <manauw@skynet.be>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library 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 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include "gstavvidenc.h"
34 /* some enums used in property declarations */
36 #define GST_TYPE_FFMPEG_PASS (gst_ffmpeg_pass_get_type ())
38 gst_ffmpeg_pass_get_type (void)
40 static GType ffmpeg_pass_type = 0;
42 if (!ffmpeg_pass_type) {
43 static const GEnumValue ffmpeg_passes[] = {
44 {0, "Constant Bitrate Encoding", "cbr"},
45 {CODEC_FLAG_QSCALE, "Constant Quantizer", "quant"},
46 {CODEC_FLAG_PASS1, "VBR Encoding - Pass 1", "pass1"},
47 {CODEC_FLAG_PASS2, "VBR Encoding - Pass 2", "pass2"},
52 g_enum_register_static ("GstLibAVEncPass", ffmpeg_passes);
55 return ffmpeg_pass_type;
59 /* some do not support 2-pass */
60 #define GST_TYPE_FFMPEG_LIM_PASS (gst_ffmpeg_lim_pass_get_type ())
62 gst_ffmpeg_lim_pass_get_type (void)
64 static GType ffmpeg_lim_pass_type = 0;
66 if (!ffmpeg_lim_pass_type) {
67 static const GEnumValue ffmpeg_lim_passes[] = {
68 {0, "Constant Bitrate Encoding", "cbr"},
69 {CODEC_FLAG_QSCALE, "Constant Quantizer", "quant"},
73 ffmpeg_lim_pass_type =
74 g_enum_register_static ("GstLibAVEncLimPass", ffmpeg_lim_passes);
77 return ffmpeg_lim_pass_type;
81 #define GST_TYPE_FFMPEG_MB_DECISION (gst_ffmpeg_mb_decision_get_type ())
83 gst_ffmpeg_mb_decision_get_type (void)
85 static GType ffmpeg_mb_decision_type = 0;
87 if (!ffmpeg_mb_decision_type) {
88 static const GEnumValue ffmpeg_mb_decisions[] = {
89 {FF_MB_DECISION_SIMPLE, "Use method set by mb-cmp", "simple"},
91 "Chooses the one which needs the fewest bits aka vhq mode", "bits"},
92 {FF_MB_DECISION_RD, "Rate Distortion", "rd"},
96 ffmpeg_mb_decision_type =
97 g_enum_register_static ("GstLibAVEncMBDecision", ffmpeg_mb_decisions);
100 return ffmpeg_mb_decision_type;
103 #define GST_TYPE_FFMPEG_CMP_FUNCTION (gst_ffmpeg_mb_cmp_get_type ())
105 gst_ffmpeg_mb_cmp_get_type (void)
107 static GType ffmpeg_mb_cmp_type = 0;
109 /* TODO fill out remaining values */
110 if (!ffmpeg_mb_cmp_type) {
111 static const GEnumValue ffmpeg_mb_cmps[] = {
112 {FF_CMP_SAD, "Sum of Absolute Differences", "sad"},
113 {FF_CMP_SSE, "Sum of Squared Errors", "sse"},
114 {FF_CMP_SATD, "Sum of Absolute Hadamard Transformed Differences", "satd"},
115 {FF_CMP_DCT, "Sum of Absolute DCT Transformed Differences", "dct"},
116 {FF_CMP_PSNR, "Sum of the Squared Quantization Errors", "psnr"},
117 {FF_CMP_BIT, "Sum of the Bits needed for the block", "bit"},
118 {FF_CMP_RD, "Rate Distortion optimal", "rd"},
119 {FF_CMP_ZERO, "ZERO", "zero"},
120 {FF_CMP_VSAD, "VSAD", "vsad"},
121 {FF_CMP_VSSE, "VSSE", "vsse"},
123 /* economize a bit for now */
124 {FF_CMP_NSSE, "NSSE", "nsse"},
125 {FF_CMP_W53, "W53", "w53"},
126 {FF_CMP_W97, "W97", "w97"},
132 g_enum_register_static ("GstLibAVCMPFunction", ffmpeg_mb_cmps);
135 return ffmpeg_mb_cmp_type;
138 #define GST_TYPE_FFMPEG_DCT_ALGO (gst_ffmpeg_dct_algo_get_type ())
140 gst_ffmpeg_dct_algo_get_type (void)
142 static GType ffmpeg_dct_algo_type = 0;
144 if (!ffmpeg_dct_algo_type) {
145 static const GEnumValue ffmpeg_dct_algos[] = {
146 {FF_DCT_AUTO, "Automatically select a good one", "auto"},
147 {FF_DCT_FASTINT, "Fast Integer", "fastint"},
148 {FF_DCT_INT, "Accurate Integer", "int"},
149 {FF_DCT_MMX, "MMX", "mmx"},
150 {FF_DCT_ALTIVEC, "ALTIVEC", "altivec"},
151 {FF_DCT_FAAN, "FAAN", "faan"},
155 ffmpeg_dct_algo_type =
156 g_enum_register_static ("GstLibAVDCTAlgo", ffmpeg_dct_algos);
159 return ffmpeg_dct_algo_type;
162 #define GST_TYPE_FFMPEG_IDCT_ALGO (gst_ffmpeg_idct_algo_get_type ())
164 gst_ffmpeg_idct_algo_get_type (void)
166 static GType ffmpeg_idct_algo_type = 0;
168 if (!ffmpeg_idct_algo_type) {
169 static const GEnumValue ffmpeg_idct_algos[] = {
170 {FF_IDCT_AUTO, "Automatically select a good one", "auto"},
171 {FF_IDCT_INT, "JPEG reference Integer", "int"},
172 {FF_IDCT_SIMPLE, "Simple", "simple"},
173 {FF_IDCT_SIMPLEMMX, "Simple MMX", "simplemmx"},
174 {FF_IDCT_ARM, "ARM", "arm"},
175 {FF_IDCT_ALTIVEC, "Altivec", "altivec"},
176 {FF_IDCT_SIMPLEARM, "Simple ARM", "simplearm"},
177 {FF_IDCT_XVID, "XVID", "xvid"},
178 {FF_IDCT_SIMPLEARMV5TE, "Simple ARMV5TE", "simplearmv5te"},
179 {FF_IDCT_SIMPLEARMV6, "Simple ARMV6", "simplearmv6"},
180 {FF_IDCT_FAAN, "FAAN", "faan"},
181 {FF_IDCT_SIMPLENEON, "Simple NEON", "simpleneon"},
185 ffmpeg_idct_algo_type =
186 g_enum_register_static ("GstLibAVIDCTAlgo", ffmpeg_idct_algos);
189 return ffmpeg_idct_algo_type;
192 #define GST_TYPE_FFMPEG_QUANT_TYPE (gst_ffmpeg_quant_type_get_type ())
194 gst_ffmpeg_quant_type_get_type (void)
196 static GType ffmpeg_quant_type_type = 0;
198 if (!ffmpeg_quant_type_type) {
199 static const GEnumValue ffmpeg_quant_types[] = {
200 {0, "H263 quantization", "h263"},
201 {1, "MPEG quantization", "mpeg"},
205 ffmpeg_quant_type_type =
206 g_enum_register_static ("GstLibAVEncQuantTypes", ffmpeg_quant_types);
209 return ffmpeg_quant_type_type;
212 #define GST_TYPE_FFMPEG_PRE_ME (gst_ffmpeg_pre_me_get_type ())
214 gst_ffmpeg_pre_me_get_type (void)
216 static GType ffmpeg_pre_me_type = 0;
218 if (!ffmpeg_pre_me_type) {
219 static const GEnumValue ffmpeg_pre_mes[] = {
220 {0, "Disabled", "off"},
221 {1, "Only after I-frames", "key"},
222 {2, "Always", "all"},
227 g_enum_register_static ("GstLibAVEncPreME", ffmpeg_pre_mes);
230 return ffmpeg_pre_me_type;
233 #define GST_TYPE_FFMPEG_PRED_METHOD (gst_ffmpeg_pred_method_get_type ())
235 gst_ffmpeg_pred_method_get_type (void)
237 static GType ffmpeg_pred_method = 0;
239 if (!ffmpeg_pred_method) {
240 static const GEnumValue ffmpeg_pred_methods[] = {
241 {FF_PRED_LEFT, "Left", "left"},
242 {FF_PRED_PLANE, "Plane", "plane"},
243 {FF_PRED_MEDIAN, "Median", "median"},
248 g_enum_register_static ("GstLibAVEncPredMethod", ffmpeg_pred_methods);
251 return ffmpeg_pred_method;
254 #define GST_TYPE_FFMPEG_FLAGS (gst_ffmpeg_flags_get_type())
256 gst_ffmpeg_flags_get_type (void)
258 static GType ffmpeg_flags_type = 0;
260 /* FIXME: This needs some serious resyncing with avcodec.h */
261 if (!ffmpeg_flags_type) {
262 static const GFlagsValue ffmpeg_flags[] = {
263 {CODEC_FLAG_QSCALE, "Use fixed qscale", "qscale"},
264 {CODEC_FLAG_4MV, "Allow 4 MV per MB", "4mv"},
265 {CODEC_FLAG_QPEL, "Quartel Pel Motion Compensation", "qpel"},
266 {CODEC_FLAG_GMC, "GMC", "gmc"},
267 {CODEC_FLAG_MV0, "Always try a MB with MV (0,0)", "mv0"},
268 {CODEC_FLAG_LOOP_FILTER, "Loop filter", "loop-filter"},
269 {CODEC_FLAG_GRAY, "Only decode/encode grayscale", "gray"},
270 {CODEC_FLAG_NORMALIZE_AQP,
271 "Normalize Adaptive Quantization (masking, etc)", "aqp"},
272 {CODEC_FLAG_GLOBAL_HEADER,
273 "Global headers in extradata instead of every keyframe",
275 {CODEC_FLAG_AC_PRED, "H263 Advanced Intra Coding / MPEG4 AC prediction",
277 {CODEC_FLAG_CLOSED_GOP, "Closed GOP", "closedgop"},
281 ffmpeg_flags_type = g_flags_register_static ("GstLibAVFlags", ffmpeg_flags);
284 return ffmpeg_flags_type;
287 /* provides additional info to attach to a property */
289 typedef struct _GParamSpecData GParamSpecData;
291 struct _GParamSpecData
293 /* offset of member in the element struct that stores the property */
296 /* size of the above member */
299 /* if TRUE, try to get the default from lavc and ignore the paramspec default */
300 gboolean lavc_default;
302 /* these lists are arrays terminated by AV_CODEC_ID_NONE entry:
303 * property applies to a codec if it's not in the exclude_list
304 * and in exclude_list (or the latter is NULL) */
309 /* properties whose member offset is higher than the config base
310 * can be copied directly at context configuration time;
311 * and can also retrieve a default value from lavc */
312 #define CONTEXT_CONFIG_OFFSET G_STRUCT_OFFSET (GstFFMpegVidEnc, config)
314 /* additional info is named pointer specified by the quark */
317 /* central configuration store:
318 * list of GParamSpec's with GParamSpecData attached as named pointer */
319 static GList *property_list;
321 /* add the GParamSpec pspec to store with GParamSpecData
322 * constructed from struct_type, member, default and include and exclude */
323 #define gst_ffmpeg_add_pspec_full(pspec, store, struct_type, member, \
324 default, include, exclude) \
326 GParamSpecData *_qdata = g_new0 (GParamSpecData, 1); \
327 GstFFMpegVidEnc _enc; \
328 _qdata->offset = G_STRUCT_OFFSET (struct_type, member); \
329 _qdata->size = sizeof (_enc.member); \
330 _qdata->lavc_default = default; \
331 _qdata->include_list = include; \
332 _qdata->exclude_list = exclude; \
333 g_param_spec_set_qdata_full (pspec, quark, _qdata, g_free); \
334 store = g_list_append (store, pspec); \
337 #define gst_ffmpeg_add_pspec(pspec, member, default, include, exclude) \
338 gst_ffmpeg_add_pspec_full (pspec, property_list, GstFFMpegVidEnc, member, \
339 default, include, exclude)
341 /* ==== BEGIN CONFIGURATION SECTION ==== */
343 /* some typical include and exclude lists; modify and/or add where needed */
345 static gint mpeg[] = {
347 AV_CODEC_ID_MSMPEG4V1,
348 AV_CODEC_ID_MSMPEG4V2,
349 AV_CODEC_ID_MSMPEG4V3,
350 AV_CODEC_ID_MPEG1VIDEO,
351 AV_CODEC_ID_MPEG2VIDEO,
358 static gint huffyuv[] = {
364 /* Properties should be added here for registration into the config store.
365 * Note that some may occur more than once, with different include/exclude lists,
366 * as some may require different defaults for different codecs,
367 * or some may have slightly varying enum-types with more or less options.
368 * The enum-types themselves should be declared above. */
370 gst_ffmpeg_cfg_init (void)
374 /* initialize global config vars */
375 quark = g_quark_from_static_string ("ffmpeg-cfg-param-spec-data");
376 property_list = NULL;
378 /* list properties here */
379 pspec = g_param_spec_enum ("pass", "Encoding pass/type",
380 "Encoding pass/type", GST_TYPE_FFMPEG_PASS, 0,
381 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
382 gst_ffmpeg_add_pspec (pspec, pass, FALSE, mpeg, NULL);
384 pspec = g_param_spec_float ("quantizer", "Constant Quantizer",
385 "Constant Quantizer", 0, 30, 0.01f,
386 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
387 gst_ffmpeg_add_pspec (pspec, quantizer, FALSE, mpeg, NULL);
389 pspec = g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
390 "Filename for multipass cache file", "stats.log",
391 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
392 gst_ffmpeg_add_pspec (pspec, filename, FALSE, mpeg, NULL);
394 pspec = g_param_spec_int ("bitrate-tolerance", "Bitrate Tolerance",
395 "Number of bits the bitstream is allowed to diverge from the reference",
396 0, 100000000, 8000000, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
397 gst_ffmpeg_add_pspec (pspec, config.bit_rate_tolerance, FALSE, mpeg, NULL);
399 pspec = g_param_spec_enum ("mb-decision", "Macroblock Decision",
400 "Macroblok Decision Mode",
401 GST_TYPE_FFMPEG_MB_DECISION, FF_CMP_SAD,
402 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
403 gst_ffmpeg_add_pspec (pspec, config.mb_decision, FALSE, mpeg, NULL);
405 pspec = g_param_spec_enum ("mb-cmp", "Macroblock Compare Function",
406 "Macroblok Compare Function",
407 GST_TYPE_FFMPEG_CMP_FUNCTION, FF_CMP_SAD,
408 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
409 gst_ffmpeg_add_pspec (pspec, config.mb_cmp, FALSE, mpeg, NULL);
412 g_param_spec_enum ("me-pre-cmp",
413 "Motion Estimation Pre Pass Compare Function",
414 "Motion Estimation Pre Pass Compare Function",
415 GST_TYPE_FFMPEG_CMP_FUNCTION, FF_CMP_SAD,
416 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
417 gst_ffmpeg_add_pspec (pspec, config.me_pre_cmp, FALSE, mpeg, NULL);
419 pspec = g_param_spec_enum ("me-cmp", "Motion Estimation Compare Function",
420 "Motion Estimation Compare Function",
421 GST_TYPE_FFMPEG_CMP_FUNCTION, FF_CMP_SAD,
422 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
423 gst_ffmpeg_add_pspec (pspec, config.me_cmp, FALSE, mpeg, NULL);
425 pspec = g_param_spec_enum ("me-sub-cmp",
426 "Subpixel Motion Estimation Compare Function",
427 "Subpixel Motion Estimation Compare Function",
428 GST_TYPE_FFMPEG_CMP_FUNCTION, FF_CMP_SAD,
429 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
430 gst_ffmpeg_add_pspec (pspec, config.me_sub_cmp, FALSE, mpeg, NULL);
432 pspec = g_param_spec_enum ("ildct-cmp", "Interlaced DCT Compare Function",
433 "Interlaced DCT Compare Function",
434 GST_TYPE_FFMPEG_CMP_FUNCTION, FF_CMP_VSAD,
435 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
436 gst_ffmpeg_add_pspec (pspec, config.ildct_cmp, FALSE, mpeg, NULL);
438 pspec = g_param_spec_enum ("dct-algo", "DCT Algorithm",
440 GST_TYPE_FFMPEG_DCT_ALGO, FF_DCT_AUTO,
441 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
442 gst_ffmpeg_add_pspec (pspec, config.dct_algo, FALSE, mpeg, NULL);
444 pspec = g_param_spec_enum ("idct-algo", "IDCT Algorithm",
446 GST_TYPE_FFMPEG_IDCT_ALGO, FF_IDCT_AUTO,
447 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
448 gst_ffmpeg_add_pspec (pspec, config.idct_algo, FALSE, mpeg, NULL);
450 pspec = g_param_spec_enum ("quant-type", "Quantizer Type",
451 "Quantizer Type", GST_TYPE_FFMPEG_QUANT_TYPE, 0,
452 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
453 gst_ffmpeg_add_pspec (pspec, config.mpeg_quant, FALSE, mpeg, NULL);
455 pspec = g_param_spec_int ("qmin", "Minimum Quantizer",
456 "Minimum Quantizer", 1, 31, 2,
457 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
458 gst_ffmpeg_add_pspec (pspec, config.qmin, FALSE, mpeg, NULL);
460 pspec = g_param_spec_int ("qmax", "Maximum Quantizer",
461 "Maximum Quantizer", 1, 31, 31,
462 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
463 gst_ffmpeg_add_pspec (pspec, config.qmax, FALSE, mpeg, NULL);
465 pspec = g_param_spec_int ("max-qdiff", "Maximum Quantizer Difference",
466 "Maximum Quantizer Difference between frames",
467 1, 31, 3, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
468 gst_ffmpeg_add_pspec (pspec, config.max_qdiff, FALSE, mpeg, NULL);
470 pspec = g_param_spec_int ("lmin", "Minimum Lagrange Multiplier",
471 "Minimum Lagrange Multiplier", 1, 31, 2,
472 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
473 gst_ffmpeg_add_pspec (pspec, lmin, FALSE, mpeg, NULL);
475 pspec = g_param_spec_int ("lmax", "Maximum Lagrange Multiplier",
476 "Maximum Lagrange Multiplier", 1, 31, 31,
477 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
478 gst_ffmpeg_add_pspec (pspec, lmax, FALSE, mpeg, NULL);
480 pspec = g_param_spec_float ("qcompress", "Quantizer Change",
481 "Quantizer Change between easy and hard scenes",
482 0, 1.0f, 0.5f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
483 gst_ffmpeg_add_pspec (pspec, config.qcompress, FALSE, mpeg, NULL);
485 pspec = g_param_spec_float ("qblur", "Quantizer Smoothing",
486 "Quantizer Smoothing over time", 0, 1.0f, 0.5f,
487 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
488 gst_ffmpeg_add_pspec (pspec, config.qblur, FALSE, mpeg, NULL);
490 pspec = g_param_spec_float ("rc-qsquish", "Ratecontrol Limiting Method",
491 "0 means limit by clipping, otherwise use nice continuous function",
492 0, 99.0f, 1.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
493 gst_ffmpeg_add_pspec (pspec, config.rc_qsquish, FALSE, mpeg, NULL);
495 pspec = g_param_spec_float ("rc-qmod-amp", "Ratecontrol Mod",
496 "Ratecontrol Mod", 0, 99.0f, 0,
497 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
498 gst_ffmpeg_add_pspec (pspec, config.rc_qmod_amp, FALSE, mpeg, NULL);
500 pspec = g_param_spec_int ("rc-qmod-freq", "Ratecontrol Freq",
501 "Ratecontrol Freq", 0, 0, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
502 gst_ffmpeg_add_pspec (pspec, config.rc_qmod_freq, FALSE, mpeg, NULL);
504 pspec = g_param_spec_int ("rc-buffer-size", "Ratecontrol Buffer Size",
505 "Decoder bitstream buffer size", 0, G_MAXINT, 0,
506 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
507 gst_ffmpeg_add_pspec (pspec, config.rc_buffer_size, FALSE, mpeg, NULL);
510 g_param_spec_float ("rc-buffer-aggressivity",
511 "Ratecontrol Buffer Aggressivity", "Ratecontrol Buffer Aggressivity", 0,
512 99.0f, 1.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
513 gst_ffmpeg_add_pspec (pspec, config.rc_buffer_aggressivity, FALSE, mpeg,
516 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT (57, 3, 0)
517 pspec = g_param_spec_int ("rc-max-rate", "Ratecontrol Maximum Bitrate",
518 "Ratecontrol Maximum Bitrate", 0, G_MAXINT, 0,
519 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
521 pspec = g_param_spec_int64 ("rc-max-rate", "Ratecontrol Maximum Bitrate",
522 "Ratecontrol Maximum Bitrate", 0, G_MAXINT64, 0,
523 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
525 gst_ffmpeg_add_pspec (pspec, config.rc_max_rate, FALSE, mpeg, NULL);
527 pspec = g_param_spec_int64 ("rc-min-rate", "Ratecontrol Minimum Bitrate",
528 "Ratecontrol Minimum Bitrate", 0, G_MAXINT64, 0,
529 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
530 gst_ffmpeg_add_pspec (pspec, config.rc_min_rate, FALSE, mpeg, NULL);
533 g_param_spec_float ("rc-initial-cplx",
534 "Initial Complexity for Pass 1 Ratecontrol",
535 "Initial Complexity for Pass 1 Ratecontrol", 0, 9999999.0f, 0,
536 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
537 gst_ffmpeg_add_pspec (pspec, config.rc_initial_cplx, FALSE, mpeg, NULL);
539 pspec = g_param_spec_string ("rc-eq", "Ratecontrol Equation",
540 "Ratecontrol Equation", "tex^qComp",
541 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
542 gst_ffmpeg_add_pspec (pspec, config.rc_eq, FALSE, mpeg, NULL);
544 pspec = g_param_spec_float ("b-quant-factor", "B-Quantizer Factor",
545 "Factor in B-Frame Quantizer Computation",
546 -31.0f, 31.0f, 1.25f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
547 gst_ffmpeg_add_pspec (pspec, config.b_quant_factor, FALSE, mpeg, NULL);
549 pspec = g_param_spec_float ("b-quant-offset", "B-Quantizer Offset",
550 "Offset in B-Frame Quantizer Computation",
551 0.0f, 31.0f, 1.25f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
552 gst_ffmpeg_add_pspec (pspec, config.b_quant_offset, FALSE, mpeg, NULL);
554 pspec = g_param_spec_float ("i-quant-factor", "I-Quantizer Factor",
555 "Factor in P-Frame Quantizer Computation",
556 -31.0f, 31.0f, 0.8f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
557 gst_ffmpeg_add_pspec (pspec, config.i_quant_factor, FALSE, mpeg, NULL);
559 pspec = g_param_spec_float ("i-quant-offset", "I-Quantizer Offset",
560 "Offset in P-Frame Quantizer Computation",
561 0.0f, 31.0f, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
562 gst_ffmpeg_add_pspec (pspec, config.i_quant_offset, FALSE, mpeg, NULL);
564 /* note overlap with gop-size; 0 means do not override */
565 pspec = g_param_spec_int ("max-key-interval", "Maximum Key Interval",
566 "Maximum number of frames between two keyframes (< 0 is in sec)",
567 -100, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
568 gst_ffmpeg_add_pspec (pspec, max_key_interval, FALSE, mpeg, NULL);
570 pspec = g_param_spec_float ("lumi-masking", "Luminance Masking",
571 "Luminance Masking", -1.0f, 1.0f, 0.0f,
572 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
573 gst_ffmpeg_add_pspec (pspec, config.lumi_masking, FALSE, mpeg, NULL);
575 pspec = g_param_spec_float ("dark-masking", "Darkness Masking",
576 "Darkness Masking", -1.0f, 1.0f, 0.0f,
577 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
578 gst_ffmpeg_add_pspec (pspec, config.dark_masking, FALSE, mpeg, NULL);
580 pspec = g_param_spec_float ("temporal-cplx-masking",
581 "Temporal Complexity Masking",
582 "Temporal Complexity Masking", -1.0f, 1.0f, 0.0f,
583 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
584 gst_ffmpeg_add_pspec (pspec, config.temporal_cplx_masking, FALSE, mpeg, NULL);
586 pspec = g_param_spec_float ("spatial-cplx-masking",
587 "Spatial Complexity Masking",
588 "Spatial Complexity Masking", -1.0f, 1.0f, 0.0f,
589 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
590 gst_ffmpeg_add_pspec (pspec, config.spatial_cplx_masking, FALSE, mpeg, NULL);
592 pspec = g_param_spec_float ("p-masking", "P Block Masking",
593 "P Block Masking", -1.0f, 1.0f, 0.0f,
594 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
595 gst_ffmpeg_add_pspec (pspec, config.p_masking, FALSE, mpeg, NULL);
597 pspec = g_param_spec_int ("dia-size",
598 "Motion Estimation Diamond Size/Shape",
599 "Motion Estimation Diamond Size/Shape",
600 -2000, 2000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
601 gst_ffmpeg_add_pspec (pspec, config.dia_size, FALSE, mpeg, NULL);
603 pspec = g_param_spec_int ("pre-dia-size",
604 "Motion Estimation Pre Pass Diamond Size/Shape",
605 "Motion Estimation Diamond Size/Shape",
606 -2000, 2000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
607 gst_ffmpeg_add_pspec (pspec, config.pre_dia_size, FALSE, mpeg, NULL);
609 pspec = g_param_spec_int ("last-predictor-count",
610 "Last Predictor Count",
611 "Amount of previous Motion Vector predictors",
612 0, 2000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
613 gst_ffmpeg_add_pspec (pspec, config.last_predictor_count, FALSE, mpeg, NULL);
615 pspec = g_param_spec_enum ("pre-me",
616 "Pre Pass for Motion Estimation",
617 "Pre Pass for Motion Estimation",
618 GST_TYPE_FFMPEG_PRE_ME, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
619 gst_ffmpeg_add_pspec (pspec, config.pre_me, FALSE, mpeg, NULL);
621 pspec = g_param_spec_int ("me-subpel-quality",
622 "Motion Estimation Subpixel Quality",
623 "Motion Estimation Subpixel Refinement Quality",
624 0, 8, 8, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
625 gst_ffmpeg_add_pspec (pspec, config.me_subpel_quality, FALSE, mpeg, NULL);
627 pspec = g_param_spec_int ("me-range",
628 "Motion Estimation Range",
629 "Motion Estimation search range in subpel units",
630 0, 16000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
631 gst_ffmpeg_add_pspec (pspec, config.me_range, FALSE, mpeg, NULL);
633 pspec = g_param_spec_int ("intra-quant-bias",
634 "Intra Quantizer Bias",
635 "Intra Quantizer Bias",
636 -1000000, 1000000, FF_DEFAULT_QUANT_BIAS,
637 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
638 gst_ffmpeg_add_pspec (pspec, config.intra_quant_bias, FALSE, mpeg, NULL);
640 pspec = g_param_spec_int ("inter-quant-bias",
641 "Inter Quantizer Bias",
642 "Inter Quantizer Bias",
643 -1000000, 1000000, FF_DEFAULT_QUANT_BIAS,
644 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
645 gst_ffmpeg_add_pspec (pspec, config.inter_quant_bias, FALSE, mpeg, NULL);
647 pspec = g_param_spec_int ("noise-reduction",
649 "Noise Reduction Strength", 0, 1000000, 0,
650 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
651 gst_ffmpeg_add_pspec (pspec, config.noise_reduction, FALSE, mpeg, NULL);
653 pspec = g_param_spec_int ("intra-dc-precision",
654 "Intra DC precision",
655 "Precision of the Intra DC coefficient - 8", 0, 16, 0,
656 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
657 gst_ffmpeg_add_pspec (pspec, config.intra_dc_precision, FALSE, mpeg, NULL);
659 /* TODO skipped coder_type, context_model, inter_threshold, scenechange_threshold */
661 pspec = g_param_spec_flags ("flags", "Flags",
662 "Flags", GST_TYPE_FFMPEG_FLAGS, 0,
663 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
664 gst_ffmpeg_add_pspec (pspec, config.flags, FALSE, mpeg, NULL);
666 pspec = g_param_spec_boolean ("interlaced", "Interlaced Material",
667 "Interlaced Material", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
668 gst_ffmpeg_add_pspec (pspec, interlaced, FALSE, mpeg, NULL);
670 pspec = g_param_spec_int ("max-bframes", "Max B-Frames",
671 "Maximum B-frames in a row", 0, INT_MAX, 0,
672 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
673 gst_ffmpeg_add_pspec (pspec, config.max_b_frames, FALSE, mpeg, NULL);
675 pspec = g_param_spec_enum ("prediction-method", "Prediction Method",
677 GST_TYPE_FFMPEG_PRED_METHOD, FF_PRED_LEFT,
678 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
679 gst_ffmpeg_add_pspec (pspec, config.prediction_method, FALSE, huffyuv, NULL);
680 pspec = g_param_spec_int ("trellis", "Trellis Quantization",
681 "Trellis RD quantization", 0, 1, 1,
682 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
683 gst_ffmpeg_add_pspec (pspec, config.trellis, FALSE, mpeg, NULL);
686 /* ==== END CONFIGURATION SECTION ==== */
689 /* return TRUE if property described by pspec applies to the codec with codec_id */
691 gst_ffmpeg_cfg_codec_has_pspec (enum AVCodecID codec_id, GParamSpec * pspec)
693 GParamSpecData *qdata;
695 gboolean ret = FALSE;
697 qdata = g_param_spec_get_qdata (pspec, quark);
699 /* check if excluded first */
700 if ((codec = qdata->exclude_list)) {
701 for (; *codec != AV_CODEC_ID_NONE; ++codec) {
702 if (*codec == codec_id)
707 /* no include list means it is accepted */
708 if ((codec = qdata->include_list)) {
709 for (; *codec != AV_CODEC_ID_NONE; ++codec) {
710 if (*codec == codec_id)
720 /* install all properties for klass that have been registered in property_list */
722 gst_ffmpeg_cfg_install_property (GstFFMpegVidEncClass * klass, guint base)
730 g_return_if_fail (base > 0);
732 ctx = avcodec_alloc_context3 (klass->in_plugin);
734 g_warning ("could not get context");
736 for (list = property_list; list; list = list->next) {
737 pspec = G_PARAM_SPEC (list->data);
738 if (gst_ffmpeg_cfg_codec_has_pspec (klass->in_plugin->id, pspec)) {
739 /* 'clone' the paramspec for the various codecs,
740 * since a single paramspec cannot be owned by distinct types */
742 const gchar *name = g_param_spec_get_name (pspec);
743 const gchar *nick = g_param_spec_get_nick (pspec);
744 const gchar *blurb = g_param_spec_get_blurb (pspec);
745 GParamSpecData *qdata = g_param_spec_get_qdata (pspec, quark);
747 gboolean lavc_default;
749 /* cannot obtain lavc default if no context */
751 lavc_default = FALSE;
753 ctx_offset = qdata->offset - CONTEXT_CONFIG_OFFSET;
754 /* safety check; is it really member of the avcodec context */
756 lavc_default = FALSE;
758 lavc_default = qdata->lavc_default;
761 switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) {
763 GParamSpecString *pstring = G_PARAM_SPEC_STRING (pspec);
765 pspec = g_param_spec_string (name, nick, blurb,
766 lavc_default ? G_STRUCT_MEMBER (gchar *, ctx, ctx_offset)
767 : pstring->default_value, pspec->flags);
771 GParamSpecInt *pint = G_PARAM_SPEC_INT (pspec);
773 pspec = g_param_spec_int (name, nick, blurb,
774 pint->minimum, pint->maximum,
775 lavc_default ? G_STRUCT_MEMBER (gint, ctx, ctx_offset)
776 : pint->default_value, pspec->flags);
780 GParamSpecInt64 *pint = G_PARAM_SPEC_INT64 (pspec);
782 pspec = g_param_spec_int64 (name, nick, blurb,
783 pint->minimum, pint->maximum,
784 lavc_default ? G_STRUCT_MEMBER (gint64, ctx, ctx_offset)
785 : pint->default_value, pspec->flags);
789 GParamSpecUInt *puint = G_PARAM_SPEC_UINT (pspec);
791 pspec = g_param_spec_uint (name, nick, blurb,
792 puint->minimum, puint->maximum,
793 lavc_default ? G_STRUCT_MEMBER (guint, ctx, ctx_offset)
794 : puint->default_value, pspec->flags);
798 GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (pspec);
800 pspec = g_param_spec_float (name, nick, blurb,
801 pfloat->minimum, pfloat->maximum,
802 lavc_default ? G_STRUCT_MEMBER (gfloat, ctx, ctx_offset)
803 : pfloat->default_value, pspec->flags);
806 case G_TYPE_BOOLEAN:{
807 GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (pspec);
809 pspec = g_param_spec_boolean (name, nick, blurb,
810 lavc_default ? G_STRUCT_MEMBER (gboolean, ctx, ctx_offset)
811 : pboolean->default_value, pspec->flags);
815 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
816 GParamSpecEnum *penum = G_PARAM_SPEC_ENUM (pspec);
818 pspec = g_param_spec_enum (name, nick, blurb,
820 lavc_default ? G_STRUCT_MEMBER (gint, ctx, ctx_offset)
821 : penum->default_value, pspec->flags);
822 } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
823 GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (pspec);
825 pspec = g_param_spec_flags (name, nick, blurb,
827 lavc_default ? G_STRUCT_MEMBER (guint, ctx, ctx_offset)
828 : pflags->default_value, pspec->flags);
830 g_critical ("%s does not yet support type %s", GST_FUNCTION,
831 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
836 g_param_spec_set_qdata (pspec, quark, qdata);
837 g_object_class_install_property (G_OBJECT_CLASS (klass), prop_id, pspec);
843 gst_ffmpeg_avcodec_close (ctx);
848 /* returns TRUE if it is a known property for this config system,
851 gst_ffmpeg_cfg_set_property (GObject * object,
852 const GValue * value, GParamSpec * pspec)
854 GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
855 GParamSpecData *qdata;
857 qdata = g_param_spec_get_qdata (pspec, quark);
859 /* our param specs should have such qdata */
863 /* set the member using the offset, also mild type check based on size */
864 switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) {
866 g_return_val_if_fail (qdata->size == sizeof (gboolean), TRUE);
867 G_STRUCT_MEMBER (gboolean, ffmpegenc, qdata->offset) =
868 g_value_get_boolean (value);
871 g_return_val_if_fail (qdata->size == sizeof (guint), TRUE);
872 G_STRUCT_MEMBER (guint, ffmpegenc, qdata->offset) =
873 g_value_get_uint (value);
876 g_return_val_if_fail (qdata->size == sizeof (gint), TRUE);
877 G_STRUCT_MEMBER (gint, ffmpegenc, qdata->offset) =
878 g_value_get_int (value);
881 g_return_val_if_fail (qdata->size == sizeof (gint64), TRUE);
882 G_STRUCT_MEMBER (gint64, ffmpegenc, qdata->offset) =
883 g_value_get_int64 (value);
886 g_return_val_if_fail (qdata->size == sizeof (gfloat), TRUE);
887 G_STRUCT_MEMBER (gfloat, ffmpegenc, qdata->offset) =
888 g_value_get_float (value);
891 g_return_val_if_fail (qdata->size == sizeof (gchar *), TRUE);
892 g_free (G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset));
893 G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset) =
894 g_value_dup_string (value);
896 default: /* must be enum, given the check above */
897 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
898 g_return_val_if_fail (qdata->size == sizeof (gint), TRUE);
899 G_STRUCT_MEMBER (gint, ffmpegenc, qdata->offset) =
900 g_value_get_enum (value);
901 } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
902 g_return_val_if_fail (qdata->size == sizeof (guint), TRUE);
903 G_STRUCT_MEMBER (guint, ffmpegenc, qdata->offset) =
904 g_value_get_flags (value);
905 } else { /* oops, bit lazy we don't cover this case yet */
906 g_critical ("%s does not yet support type %s", GST_FUNCTION,
907 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
916 /* returns TRUE if it is a known property for this config system,
919 gst_ffmpeg_cfg_get_property (GObject * object,
920 GValue * value, GParamSpec * pspec)
922 GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
923 GParamSpecData *qdata;
925 qdata = g_param_spec_get_qdata (pspec, quark);
927 /* our param specs should have such qdata */
931 /* get the member using the offset, also mild type check based on size */
932 switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) {
934 g_return_val_if_fail (qdata->size == sizeof (gboolean), TRUE);
935 g_value_set_boolean (value,
936 G_STRUCT_MEMBER (gboolean, ffmpegenc, qdata->offset));
939 g_return_val_if_fail (qdata->size == sizeof (guint), TRUE);
940 g_value_set_uint (value,
941 G_STRUCT_MEMBER (guint, ffmpegenc, qdata->offset));
944 g_return_val_if_fail (qdata->size == sizeof (gint), TRUE);
945 g_value_set_int (value, G_STRUCT_MEMBER (gint, ffmpegenc, qdata->offset));
948 g_return_val_if_fail (qdata->size == sizeof (gint64), TRUE);
949 g_value_set_int64 (value, G_STRUCT_MEMBER (gint64, ffmpegenc,
953 g_return_val_if_fail (qdata->size == sizeof (gfloat), TRUE);
954 g_value_set_float (value,
955 G_STRUCT_MEMBER (gfloat, ffmpegenc, qdata->offset));
958 g_return_val_if_fail (qdata->size == sizeof (gchar *), TRUE);
959 g_value_take_string (value,
960 g_strdup (G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset)));
962 default: /* must be enum, given the check above */
963 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
964 g_return_val_if_fail (qdata->size == sizeof (gint), TRUE);
965 g_value_set_enum (value,
966 G_STRUCT_MEMBER (gint, ffmpegenc, qdata->offset));
967 } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
968 g_return_val_if_fail (qdata->size == sizeof (guint), TRUE);
969 g_value_set_flags (value,
970 G_STRUCT_MEMBER (guint, ffmpegenc, qdata->offset));
971 } else { /* oops, bit lazy we don't cover this case yet */
972 g_critical ("%s does not yet support type %s", GST_FUNCTION,
973 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
982 gst_ffmpeg_cfg_set_defaults (GstFFMpegVidEnc * ffmpegenc)
987 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (ffmpegenc),
990 for (i = 0; i < num_props; ++i) {
992 GParamSpec *pspec = pspecs[i];
994 /* only touch those that are really ours; i.e. should have some qdata */
995 if (!g_param_spec_get_qdata (pspec, quark))
997 g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec));
998 g_param_value_set_default (pspec, &val);
999 g_object_set_property (G_OBJECT (ffmpegenc),
1000 g_param_spec_get_name (pspec), &val);
1001 g_value_unset (&val);
1010 gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc,
1011 AVCodecContext * context)
1013 GstFFMpegVidEncClass *klass
1014 = (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
1016 GParamSpecData *qdata;
1019 list = property_list;
1022 gint context_offset;
1024 pspec = G_PARAM_SPEC (list->data);
1025 qdata = g_param_spec_get_qdata (pspec, quark);
1026 context_offset = qdata->offset - CONTEXT_CONFIG_OFFSET;
1027 if (gst_ffmpeg_cfg_codec_has_pspec (klass->in_plugin->id, pspec)
1028 && context_offset >= 0) {
1029 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_STRING) {
1030 /* make a copy for ffmpeg, it will likely free only some,
1031 * but in any case safer than a potential double free */
1032 G_STRUCT_MEMBER (gchar *, context, context_offset) =
1033 av_strdup (G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset));
1035 /* memcpy a bit heavy for a small copy,
1036 * but hardly part of 'inner loop' */
1037 memcpy (G_STRUCT_MEMBER_P (context, context_offset),
1038 G_STRUCT_MEMBER_P (ffmpegenc, qdata->offset), qdata->size);
1046 gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc)
1048 GParamSpec **pspecs;
1051 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (ffmpegenc),
1054 for (i = 0; i < num_props; ++i) {
1055 GParamSpec *pspec = pspecs[i];
1056 GParamSpecData *qdata;
1058 qdata = g_param_spec_get_qdata (pspec, quark);
1060 /* our param specs should have such qdata */
1064 switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) {
1066 if (qdata->size == sizeof (gchar *)) {
1067 g_free (G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset));
1068 G_STRUCT_MEMBER (gchar *, ffmpegenc, qdata->offset) = NULL;