avaudenc: install options generically

https://bugzilla.gnome.org/show_bug.cgi?id=792900
This commit is contained in:
Mathieu Duponchelle 2018-06-30 23:27:06 +02:00
parent 965cd81603
commit 59b9e66542
6 changed files with 70 additions and 130 deletions

View file

@ -30,6 +30,7 @@
#include "gstav.h" #include "gstav.h"
#include "gstavutils.h" #include "gstavutils.h"
#include "gstavcfg.h"
#ifdef GST_LIBAV_ENABLE_GPL #ifdef GST_LIBAV_ENABLE_GPL
#define LICENSE "GPL" #define LICENSE "GPL"
@ -153,6 +154,9 @@ plugin_init (GstPlugin * plugin)
gst_ffmpeg_init_pix_fmt_info (); gst_ffmpeg_init_pix_fmt_info ();
/* build global ffmpeg param/property info */
gst_ffmpeg_cfg_init ();
gst_ffmpegaudenc_register (plugin); gst_ffmpegaudenc_register (plugin);
gst_ffmpegvidenc_register (plugin); gst_ffmpegvidenc_register (plugin);
gst_ffmpegauddec_register (plugin); gst_ffmpegauddec_register (plugin);

View file

@ -31,10 +31,12 @@
#include <errno.h> #include <errno.h>
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <gst/gst.h> #include <gst/gst.h>
#include "gstav.h" #include "gstav.h"
#include "gstavcfg.h"
#include "gstavcodecmap.h" #include "gstavcodecmap.h"
#include "gstavutils.h" #include "gstavutils.h"
#include "gstavaudenc.h" #include "gstavaudenc.h"
@ -50,9 +52,7 @@ enum
enum enum
{ {
PROP_0, PROP_0,
PROP_BIT_RATE, PROP_CFG_BASE,
PROP_RTP_PAYLOAD_SIZE,
PROP_COMPLIANCE,
}; };
/* A number of function prototypes are given so we can refer to them later. */ /* A number of function prototypes are given so we can refer to them later. */
@ -148,16 +148,8 @@ gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass)
gobject_class->set_property = gst_ffmpegaudenc_set_property; gobject_class->set_property = gst_ffmpegaudenc_set_property;
gobject_class->get_property = gst_ffmpegaudenc_get_property; gobject_class->get_property = gst_ffmpegaudenc_get_property;
/* FIXME: could use -1 for a sensible per-codec defaults */ gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE, PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM);
g_param_spec_int ("bitrate", "Bit Rate",
"Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COMPLIANCE,
g_param_spec_enum ("compliance", "Compliance",
"Adherence of the encoder to the specifications",
GST_TYPE_FFMPEG_COMPLIANCE, FFMPEG_DEFAULT_COMPLIANCE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gobject_class->finalize = gst_ffmpegaudenc_finalize; gobject_class->finalize = gst_ffmpegaudenc_finalize;
@ -180,11 +172,10 @@ gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc)
/* ffmpeg objects */ /* ffmpeg objects */
ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin); ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin);
ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
ffmpegaudenc->opened = FALSE; ffmpegaudenc->opened = FALSE;
ffmpegaudenc->frame = av_frame_alloc (); ffmpegaudenc->frame = av_frame_alloc ();
ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE;
gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE); gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
} }
@ -197,6 +188,7 @@ gst_ffmpegaudenc_finalize (GObject * object)
av_frame_free (&ffmpegaudenc->frame); av_frame_free (&ffmpegaudenc->frame);
gst_ffmpeg_avcodec_close (ffmpegaudenc->context); gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
av_free (ffmpegaudenc->context); av_free (ffmpegaudenc->context);
av_free (ffmpegaudenc->refcontext);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -262,31 +254,7 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
} }
} }
/* if we set it in _getcaps we should set it also in _link */ gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
ffmpegaudenc->context->strict_std_compliance = ffmpegaudenc->compliance;
/* user defined properties */
if (ffmpegaudenc->bitrate > 0) {
GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d",
ffmpegaudenc->bitrate);
ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate;
ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate;
} else {
GST_INFO_OBJECT (ffmpegaudenc,
"Using avcontext default bitrate %" G_GINT64_FORMAT,
(gint64) ffmpegaudenc->context->bit_rate);
}
/* RTP payload used for GOB production (for Asterisk) */
if (ffmpegaudenc->rtp_payload_size) {
ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size;
}
/* some other defaults */
ffmpegaudenc->context->b_frame_strategy = 0;
ffmpegaudenc->context->coder_type = 0;
ffmpegaudenc->context->context_model = 0;
ffmpegaudenc->context->scenechange_threshold = 0;
/* fetch pix_fmt and so on */ /* fetch pix_fmt and so on */
gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context); gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
@ -330,7 +298,8 @@ gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults"); GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
ffmpegaudenc->compliance != GST_FFMPEG_EXPERIMENTAL) { ffmpegaudenc->context->strict_std_compliance !=
GST_FFMPEG_EXPERIMENTAL) {
GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS, GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS,
("Codec is experimental, but settings don't allow encoders to " ("Codec is experimental, but settings don't allow encoders to "
"produce output of experimental quality"), "produce output of experimental quality"),
@ -703,7 +672,6 @@ gst_ffmpegaudenc_set_property (GObject * object,
{ {
GstFFMpegAudEnc *ffmpegaudenc; GstFFMpegAudEnc *ffmpegaudenc;
/* Get a pointer of the right type. */
ffmpegaudenc = (GstFFMpegAudEnc *) (object); ffmpegaudenc = (GstFFMpegAudEnc *) (object);
if (ffmpegaudenc->opened) { if (ffmpegaudenc->opened) {
@ -712,45 +680,25 @@ gst_ffmpegaudenc_set_property (GObject * object,
return; return;
} }
/* Check the argument id to see which argument we're setting. */
switch (prop_id) { switch (prop_id) {
case PROP_BIT_RATE:
ffmpegaudenc->bitrate = g_value_get_int (value);
break;
case PROP_RTP_PAYLOAD_SIZE:
ffmpegaudenc->rtp_payload_size = g_value_get_int (value);
break;
case PROP_COMPLIANCE:
ffmpegaudenc->compliance = g_value_get_enum (value);
break;
default: default:
if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
/* The set function is simply the inverse of the get fuction. */
static void static void
gst_ffmpegaudenc_get_property (GObject * object, gst_ffmpegaudenc_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec) guint prop_id, GValue * value, GParamSpec * pspec)
{ {
GstFFMpegAudEnc *ffmpegaudenc; GstFFMpegAudEnc *ffmpegaudenc;
/* It's not null if we got it, but it might not be ours */
ffmpegaudenc = (GstFFMpegAudEnc *) (object); ffmpegaudenc = (GstFFMpegAudEnc *) (object);
switch (prop_id) { switch (prop_id) {
case PROP_BIT_RATE:
g_value_set_int (value, ffmpegaudenc->bitrate);
break;
break;
case PROP_RTP_PAYLOAD_SIZE:
g_value_set_int (value, ffmpegaudenc->rtp_payload_size);
break;
case PROP_COMPLIANCE:
g_value_set_enum (value, ffmpegaudenc->compliance);
break;
default: default:
if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }

View file

@ -37,17 +37,9 @@ struct _GstFFMpegAudEnc
GstAudioEncoder parent; GstAudioEncoder parent;
AVCodecContext *context; AVCodecContext *context;
AVCodecContext *refcontext;
gboolean opened; gboolean opened;
/* cache */
gint bitrate;
gint rtp_payload_size;
gint compliance;
/* other settings are copied over straight,
* include a context here, rather than copy-and-past it from avcodec.h */
AVCodecContext config;
AVFrame *frame; AVFrame *frame;
GstAudioChannelPosition ffmpeg_layout[64]; GstAudioChannelPosition ffmpeg_layout[64];

View file

@ -33,22 +33,24 @@
#include <libavutil/opt.h> #include <libavutil/opt.h>
static GQuark avoption_quark; static GQuark avoption_quark;
static GHashTable *venc_overrides = NULL; static GHashTable *generic_overrides = NULL;
static void static void
make_venc_overrides (void) make_generic_overrides (void)
{ {
g_assert (!venc_overrides); g_assert (!generic_overrides);
venc_overrides = g_hash_table_new_full (g_str_hash, g_str_equal, generic_overrides = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) gst_structure_free); g_free, (GDestroyNotify) gst_structure_free);
g_hash_table_insert (venc_overrides, g_strdup ("b"), g_hash_table_insert (generic_overrides, g_strdup ("b"),
gst_structure_new_empty ("bitrate")); gst_structure_new_empty ("bitrate"));
g_hash_table_insert (venc_overrides, g_strdup ("g"), g_hash_table_insert (generic_overrides, g_strdup ("ab"),
gst_structure_new_empty ("bitrate"));
g_hash_table_insert (generic_overrides, g_strdup ("g"),
gst_structure_new_empty ("gop-size")); gst_structure_new_empty ("gop-size"));
g_hash_table_insert (venc_overrides, g_strdup ("bt"), g_hash_table_insert (generic_overrides, g_strdup ("bt"),
gst_structure_new_empty ("bitrate-tolerance")); gst_structure_new_empty ("bitrate-tolerance"));
g_hash_table_insert (venc_overrides, g_strdup ("bf"), g_hash_table_insert (generic_overrides, g_strdup ("bf"),
gst_structure_new_empty ("max-bframes")); gst_structure_new_empty ("max-bframes"));
} }
@ -56,7 +58,7 @@ void
gst_ffmpeg_cfg_init (void) gst_ffmpeg_cfg_init (void)
{ {
avoption_quark = g_quark_from_static_string ("ffmpeg-cfg-param-spec-data"); avoption_quark = g_quark_from_static_string ("ffmpeg-cfg-param-spec-data");
make_venc_overrides (); make_generic_overrides ();
} }
static gint static gint
@ -335,7 +337,8 @@ install_opts (GObjectClass * gobject_class, const AVClass ** obj, guint prop_id,
} }
void void
gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base) gst_ffmpeg_cfg_install_properties (GObjectClass * klass, AVCodec * in_plugin,
guint base, gint flags)
{ {
gint prop_id; gint prop_id;
AVCodecContext *ctx; AVCodecContext *ctx;
@ -343,18 +346,16 @@ gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base)
prop_id = base; prop_id = base;
g_return_if_fail (base > 0); g_return_if_fail (base > 0);
ctx = avcodec_alloc_context3 (klass->in_plugin); ctx = avcodec_alloc_context3 (in_plugin);
if (!ctx) if (!ctx)
g_warning ("could not get context"); g_warning ("could not get context");
prop_id = prop_id =
install_opts ((GObjectClass *) klass, &klass->in_plugin->priv_class, install_opts ((GObjectClass *) klass, &in_plugin->priv_class, prop_id, 0,
prop_id, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM,
" (Private codec option)", NULL); " (Private codec option)", NULL);
prop_id = prop_id =
install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, flags,
AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM, " (Generic codec option, might have no effect)", generic_overrides);
" (Generic codec option, might have no effect)", venc_overrides);
if (ctx) { if (ctx) {
gst_ffmpeg_avcodec_close (ctx); gst_ffmpeg_avcodec_close (ctx);
@ -421,10 +422,9 @@ set_option_value (AVCodecContext * ctx, GParamSpec * pspec,
} }
gboolean gboolean
gst_ffmpeg_cfg_set_property (GObject * object, gst_ffmpeg_cfg_set_property (AVCodecContext * refcontext, const GValue * value,
const GValue * value, GParamSpec * pspec) GParamSpec * pspec)
{ {
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
const AVOption *opt; const AVOption *opt;
opt = g_param_spec_get_qdata (pspec, avoption_quark); opt = g_param_spec_get_qdata (pspec, avoption_quark);
@ -432,14 +432,13 @@ gst_ffmpeg_cfg_set_property (GObject * object,
if (!opt) if (!opt)
return FALSE; return FALSE;
return set_option_value (ffmpegenc->refcontext, pspec, value, opt) >= 0; return set_option_value (refcontext, pspec, value, opt) >= 0;
} }
gboolean gboolean
gst_ffmpeg_cfg_get_property (GObject * object, gst_ffmpeg_cfg_get_property (AVCodecContext * refcontext, GValue * value,
GValue * value, GParamSpec * pspec) GParamSpec * pspec)
{ {
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
const AVOption *opt; const AVOption *opt;
opt = g_param_spec_get_qdata (pspec, avoption_quark); opt = g_param_spec_get_qdata (pspec, avoption_quark);
@ -455,7 +454,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_INT: case G_TYPE_INT:
{ {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_int (value, val); g_value_set_int (value, val);
break; break;
@ -463,7 +462,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_INT64: case G_TYPE_INT64:
{ {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_int64 (value, val); g_value_set_int64 (value, val);
break; break;
@ -471,7 +470,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_UINT64: case G_TYPE_UINT64:
{ {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_uint64 (value, val); g_value_set_uint64 (value, val);
break; break;
@ -479,7 +478,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_DOUBLE: case G_TYPE_DOUBLE:
{ {
gdouble val; gdouble val;
if ((res = av_opt_get_double (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_double (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_double (value, val); g_value_set_double (value, val);
break; break;
@ -487,7 +486,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_FLOAT: case G_TYPE_FLOAT:
{ {
gdouble val; gdouble val;
if ((res = av_opt_get_double (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_double (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_float (value, (gfloat) val); g_value_set_float (value, (gfloat) val);
break; break;
@ -495,7 +494,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_STRING: case G_TYPE_STRING:
{ {
uint8_t *val; uint8_t *val;
if ((res = av_opt_get (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &val) >= 0)) { AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &val) >= 0)) {
g_value_set_string (value, (gchar *) val); g_value_set_string (value, (gchar *) val);
} }
@ -504,7 +503,7 @@ gst_ffmpeg_cfg_get_property (GObject * object,
case G_TYPE_BOOLEAN: case G_TYPE_BOOLEAN:
{ {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_boolean (value, val ? TRUE : FALSE); g_value_set_boolean (value, val ? TRUE : FALSE);
break; break;
@ -513,13 +512,13 @@ gst_ffmpeg_cfg_get_property (GObject * object,
if (G_IS_PARAM_SPEC_ENUM (pspec)) { if (G_IS_PARAM_SPEC_ENUM (pspec)) {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_enum (value, val); g_value_set_enum (value, val);
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) { } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
int64_t val; int64_t val;
if ((res = av_opt_get_int (ffmpegenc->refcontext, opt->name, if ((res = av_opt_get_int (refcontext, opt->name,
AV_OPT_SEARCH_CHILDREN, &val) >= 0)) AV_OPT_SEARCH_CHILDREN, &val) >= 0))
g_value_set_flags (value, val); g_value_set_flags (value, val);
} else { /* oops, bit lazy we don't cover this case yet */ } else { /* oops, bit lazy we don't cover this case yet */
@ -534,13 +533,12 @@ gst_ffmpeg_cfg_get_property (GObject * object,
} }
void void
gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, gst_ffmpeg_cfg_fill_context (GObject * object, AVCodecContext * context)
AVCodecContext * context)
{ {
GParamSpec **pspecs; GParamSpec **pspecs;
guint num_props, i; guint num_props, i;
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (ffmpegenc), pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object),
&num_props); &num_props);
for (i = 0; i < num_props; ++i) { for (i = 0; i < num_props; ++i) {
@ -553,15 +551,16 @@ gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc,
if (!opt) if (!opt)
continue; continue;
g_object_getv (G_OBJECT (ffmpegenc), 1, &pspec->name, &value); g_object_getv (object, 1, &pspec->name, &value);
set_option_value (context, pspec, &value, opt); set_option_value (context, pspec, &value, opt);
} }
g_free (pspecs); g_free (pspecs);
} }
void void
gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc) gst_ffmpeg_cfg_finalize (void)
{ {
g_assert (venc_overrides); GST_ERROR ("Finalizing");
g_hash_table_unref (venc_overrides); g_assert (generic_overrides);
g_hash_table_unref (generic_overrides);
} }

View file

@ -21,21 +21,23 @@
#ifndef __GST_FFMPEGCFG_H__ #ifndef __GST_FFMPEGCFG_H__
#define __GST_FFMPEGCFG_H__ #define __GST_FFMPEGCFG_H__
#include <glib-object.h>
#include <libavcodec/avcodec.h>
G_BEGIN_DECLS G_BEGIN_DECLS
void gst_ffmpeg_cfg_init (void); void gst_ffmpeg_cfg_init (void);
void gst_ffmpeg_cfg_install_properties (GstFFMpegVidEncClass * klass, guint base); void gst_ffmpeg_cfg_install_properties (GObjectClass * klass, AVCodec *in_plugin, guint base, gint flags);
gboolean gst_ffmpeg_cfg_set_property (GObject * object, gboolean gst_ffmpeg_cfg_set_property (AVCodecContext *refcontext,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
gboolean gst_ffmpeg_cfg_get_property (GObject * object, gboolean gst_ffmpeg_cfg_get_property (AVCodecContext *refcontext,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
void gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, AVCodecContext * context); void gst_ffmpeg_cfg_fill_context (GObject *object, AVCodecContext * context);
void gst_ffmpeg_cfg_set_defaults (GstFFMpegVidEnc * ffmpegenc); void gst_ffmpeg_cfg_finalize (void);
void gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc);
G_END_DECLS G_END_DECLS

View file

@ -184,7 +184,8 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
/* register additional properties, possibly dependent on the exact CODEC */ /* register additional properties, possibly dependent on the exact CODEC */
gst_ffmpeg_cfg_install_properties (klass, PROP_CFG_BASE); gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM);
venc_class->start = gst_ffmpegvidenc_start; venc_class->start = gst_ffmpegvidenc_start;
venc_class->stop = gst_ffmpegvidenc_stop; venc_class->stop = gst_ffmpegvidenc_stop;
@ -217,8 +218,6 @@ gst_ffmpegvidenc_finalize (GObject * object)
{ {
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) object; GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) object;
gst_ffmpeg_cfg_finalize (ffmpegenc);
/* clean up remaining allocated data */ /* clean up remaining allocated data */
av_frame_free (&ffmpegenc->picture); av_frame_free (&ffmpegenc->picture);
gst_ffmpeg_avcodec_close (ffmpegenc->context); gst_ffmpeg_avcodec_close (ffmpegenc->context);
@ -253,7 +252,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
} }
/* additional avcodec settings */ /* additional avcodec settings */
gst_ffmpeg_cfg_fill_context (ffmpegenc, ffmpegenc->context); gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegenc), ffmpegenc->context);
/* and last but not least the pass; CBR, 2-pass, etc */ /* and last but not least the pass; CBR, 2-pass, etc */
ffmpegenc->context->flags |= ffmpegenc->pass; ffmpegenc->context->flags |= ffmpegenc->pass;
@ -737,7 +736,7 @@ gst_ffmpegvidenc_set_property (GObject * object,
ffmpegenc->filename = g_value_dup_string (value); ffmpegenc->filename = g_value_dup_string (value);
break; break;
default: default:
if (!gst_ffmpeg_cfg_set_property (object, value, pspec)) if (!gst_ffmpeg_cfg_set_property (ffmpegenc->refcontext, value, pspec))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
@ -762,7 +761,7 @@ gst_ffmpegvidenc_get_property (GObject * object,
g_value_take_string (value, g_strdup (ffmpegenc->filename)); g_value_take_string (value, g_strdup (ffmpegenc->filename));
break; break;
default: default:
if (!gst_ffmpeg_cfg_get_property (object, value, pspec)) if (!gst_ffmpeg_cfg_get_property (ffmpegenc->refcontext, value, pspec))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
@ -839,12 +838,8 @@ gst_ffmpegvidenc_register (GstPlugin * plugin)
AVCodec *in_plugin; AVCodec *in_plugin;
void *i = 0; void *i = 0;
GST_LOG ("Registering encoders"); GST_LOG ("Registering encoders");
/* build global ffmpeg param/property info */
gst_ffmpeg_cfg_init ();
while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) { while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
gchar *type_name; gchar *type_name;