#include "gstav.h"
#include "gstavutils.h"
+#include "gstavcfg.h"
#ifdef GST_LIBAV_ENABLE_GPL
#define LICENSE "GPL"
gst_ffmpeg_init_pix_fmt_info ();
+ /* build global ffmpeg param/property info */
+ gst_ffmpeg_cfg_init ();
+
gst_ffmpegaudenc_register (plugin);
gst_ffmpegvidenc_register (plugin);
gst_ffmpegauddec_register (plugin);
#include <errno.h>
#include <libavcodec/avcodec.h>
+#include <libavutil/opt.h>
#include <gst/gst.h>
#include "gstav.h"
+#include "gstavcfg.h"
#include "gstavcodecmap.h"
#include "gstavutils.h"
#include "gstavaudenc.h"
enum
{
PROP_0,
- PROP_BIT_RATE,
- PROP_RTP_PAYLOAD_SIZE,
- PROP_COMPLIANCE,
+ PROP_CFG_BASE,
};
/* A number of function prototypes are given so we can refer to them later. */
gobject_class->set_property = gst_ffmpegaudenc_set_property;
gobject_class->get_property = gst_ffmpegaudenc_get_property;
- /* FIXME: could use -1 for a sensible per-codec defaults */
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE,
- 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));
+ gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
+ PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM);
gobject_class->finalize = gst_ffmpegaudenc_finalize;
/* ffmpeg objects */
ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin);
+ ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
ffmpegaudenc->opened = FALSE;
ffmpegaudenc->frame = av_frame_alloc ();
- ffmpegaudenc->compliance = FFMPEG_DEFAULT_COMPLIANCE;
-
gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
}
av_frame_free (&ffmpegaudenc->frame);
gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
av_free (ffmpegaudenc->context);
+ av_free (ffmpegaudenc->refcontext);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
}
}
- /* if we set it in _getcaps we should set it also in _link */
- 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;
+ gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
/* fetch pix_fmt and so on */
gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
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,
("Codec is experimental, but settings don't allow encoders to "
"produce output of experimental quality"),
{
GstFFMpegAudEnc *ffmpegaudenc;
- /* Get a pointer of the right type. */
ffmpegaudenc = (GstFFMpegAudEnc *) (object);
if (ffmpegaudenc->opened) {
return;
}
- /* Check the argument id to see which argument we're setting. */
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:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
-/* The set function is simply the inverse of the get fuction. */
static void
gst_ffmpegaudenc_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstFFMpegAudEnc *ffmpegaudenc;
- /* It's not null if we got it, but it might not be ours */
ffmpegaudenc = (GstFFMpegAudEnc *) (object);
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:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
GstAudioEncoder parent;
AVCodecContext *context;
+ AVCodecContext *refcontext;
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;
GstAudioChannelPosition ffmpeg_layout[64];
#include <libavutil/opt.h>
static GQuark avoption_quark;
-static GHashTable *venc_overrides = NULL;
+static GHashTable *generic_overrides = NULL;
static void
-make_venc_overrides (void)
+make_generic_overrides (void)
{
- g_assert (!venc_overrides);
- venc_overrides = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_assert (!generic_overrides);
+ generic_overrides = g_hash_table_new_full (g_str_hash, g_str_equal,
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"));
- 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"));
- g_hash_table_insert (venc_overrides, g_strdup ("bt"),
+ g_hash_table_insert (generic_overrides, g_strdup ("bt"),
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_ffmpeg_cfg_init (void)
{
avoption_quark = g_quark_from_static_string ("ffmpeg-cfg-param-spec-data");
- make_venc_overrides ();
+ make_generic_overrides ();
}
static gint
}
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;
AVCodecContext *ctx;
prop_id = base;
g_return_if_fail (base > 0);
- ctx = avcodec_alloc_context3 (klass->in_plugin);
+ ctx = avcodec_alloc_context3 (in_plugin);
if (!ctx)
g_warning ("could not get context");
prop_id =
- install_opts ((GObjectClass *) klass, &klass->in_plugin->priv_class,
- prop_id, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM,
+ install_opts ((GObjectClass *) klass, &in_plugin->priv_class, prop_id, 0,
" (Private codec option)", NULL);
prop_id =
- install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id,
- AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM,
- " (Generic codec option, might have no effect)", venc_overrides);
+ install_opts ((GObjectClass *) klass, &ctx->av_class, prop_id, flags,
+ " (Generic codec option, might have no effect)", generic_overrides);
if (ctx) {
gst_ffmpeg_avcodec_close (ctx);
}
gboolean
-gst_ffmpeg_cfg_set_property (GObject * object,
- const GValue * value, GParamSpec * pspec)
+gst_ffmpeg_cfg_set_property (AVCodecContext * refcontext, const GValue * value,
+ GParamSpec * pspec)
{
- GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
const AVOption *opt;
opt = g_param_spec_get_qdata (pspec, avoption_quark);
if (!opt)
return FALSE;
- return set_option_value (ffmpegenc->refcontext, pspec, value, opt) >= 0;
+ return set_option_value (refcontext, pspec, value, opt) >= 0;
}
gboolean
-gst_ffmpeg_cfg_get_property (GObject * object,
- GValue * value, GParamSpec * pspec)
+gst_ffmpeg_cfg_get_property (AVCodecContext * refcontext, GValue * value,
+ GParamSpec * pspec)
{
- GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) (object);
const AVOption *opt;
opt = g_param_spec_get_qdata (pspec, avoption_quark);
case G_TYPE_INT:
{
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))
g_value_set_int (value, val);
break;
case G_TYPE_INT64:
{
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))
g_value_set_int64 (value, val);
break;
case G_TYPE_UINT64:
{
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))
g_value_set_uint64 (value, val);
break;
case G_TYPE_DOUBLE:
{
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))
g_value_set_double (value, val);
break;
case G_TYPE_FLOAT:
{
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))
g_value_set_float (value, (gfloat) val);
break;
case G_TYPE_STRING:
{
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)) {
g_value_set_string (value, (gchar *) val);
}
case G_TYPE_BOOLEAN:
{
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))
g_value_set_boolean (value, val ? TRUE : FALSE);
break;
if (G_IS_PARAM_SPEC_ENUM (pspec)) {
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))
g_value_set_enum (value, val);
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
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))
g_value_set_flags (value, val);
} else { /* oops, bit lazy we don't cover this case yet */
}
void
-gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc,
- AVCodecContext * context)
+gst_ffmpeg_cfg_fill_context (GObject * object, AVCodecContext * context)
{
GParamSpec **pspecs;
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);
for (i = 0; i < num_props; ++i) {
if (!opt)
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);
}
g_free (pspecs);
}
void
-gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc)
+gst_ffmpeg_cfg_finalize (void)
{
- g_assert (venc_overrides);
- g_hash_table_unref (venc_overrides);
+ GST_ERROR ("Finalizing");
+ g_assert (generic_overrides);
+ g_hash_table_unref (generic_overrides);
}
#ifndef __GST_FFMPEGCFG_H__
#define __GST_FFMPEGCFG_H__
+#include <glib-object.h>
+#include <libavcodec/avcodec.h>
+
G_BEGIN_DECLS
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);
-gboolean gst_ffmpeg_cfg_get_property (GObject * object,
+gboolean gst_ffmpeg_cfg_get_property (AVCodecContext *refcontext,
GValue * value, GParamSpec * pspec);
-void gst_ffmpeg_cfg_fill_context (GstFFMpegVidEnc * ffmpegenc, AVCodecContext * context);
-void gst_ffmpeg_cfg_set_defaults (GstFFMpegVidEnc * ffmpegenc);
-void gst_ffmpeg_cfg_finalize (GstFFMpegVidEnc * ffmpegenc);
+void gst_ffmpeg_cfg_fill_context (GObject *object, AVCodecContext * context);
+void gst_ffmpeg_cfg_finalize (void);
G_END_DECLS
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
/* 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->stop = gst_ffmpegvidenc_stop;
{
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) object;
- gst_ffmpeg_cfg_finalize (ffmpegenc);
-
/* clean up remaining allocated data */
av_frame_free (&ffmpegenc->picture);
gst_ffmpeg_avcodec_close (ffmpegenc->context);
}
/* 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 */
ffmpegenc->context->flags |= ffmpegenc->pass;
ffmpegenc->filename = g_value_dup_string (value);
break;
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);
break;
}
g_value_take_string (value, g_strdup (ffmpegenc->filename));
break;
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);
break;
}
AVCodec *in_plugin;
void *i = 0;
-
GST_LOG ("Registering encoders");
- /* build global ffmpeg param/property info */
- gst_ffmpeg_cfg_init ();
-
while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
gchar *type_name;