mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 08:08:22 +00:00
avaudenc: install options generically
https://bugzilla.gnome.org/show_bug.cgi?id=792900
This commit is contained in:
parent
965cd81603
commit
59b9e66542
6 changed files with 70 additions and 130 deletions
|
@ -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);
|
||||||
|
|
|
@ -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,46 +680,26 @@ 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:
|
||||||
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;
|
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:
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue