avviddec: Introduce a class for shared properties

Without a parent class,the documentation would need to be duplicated for
every CODECs. This patch adds an abstract class in between GstVideoDecoder
and the element.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3311>
This commit is contained in:
Nicolas Dufresne 2022-11-01 11:13:23 -04:00 committed by GStreamer Marge Bot
parent af05abdb79
commit 99ec53073a
7 changed files with 88 additions and 61 deletions

View file

@ -61,7 +61,7 @@ gst_ffmpeg_avcodec_is_ffmpeg (void)
} }
int int
gst_ffmpeg_avcodec_open (AVCodecContext * avctx, AVCodec * codec) gst_ffmpeg_avcodec_open (AVCodecContext * avctx, const AVCodec * codec)
{ {
int ret; int ret;

View file

@ -44,7 +44,7 @@ extern gboolean gst_ffmpegvidenc_register (GstPlugin * plugin);
extern gboolean gst_ffmpegmux_register (GstPlugin * plugin); extern gboolean gst_ffmpegmux_register (GstPlugin * plugin);
extern gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin); extern gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin);
int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, AVCodec *codec); int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, const AVCodec *codec);
int gst_ffmpeg_avcodec_close (AVCodecContext *avctx); int gst_ffmpeg_avcodec_close (AVCodecContext *avctx);
int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic); int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic);

View file

@ -244,7 +244,7 @@ gst_ffmpeg_video_set_pix_fmts (GstCaps * caps, const enum AVPixelFormat *fmts)
* but I'm too lazy today. Maybe later. * but I'm too lazy today. Maybe later.
*/ */
static GstCaps * static GstCaps *
gst_ff_vid_caps_new (AVCodecContext * context, AVCodec * codec, gst_ff_vid_caps_new (AVCodecContext * context, const AVCodec * codec,
enum AVCodecID codec_id, gboolean encode, const char *mimetype, enum AVCodecID codec_id, gboolean encode, const char *mimetype,
const char *fieldname, ...) const char *fieldname, ...)
{ {
@ -2562,7 +2562,7 @@ gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context,
GstCaps * GstCaps *
gst_ffmpeg_codectype_to_video_caps (AVCodecContext * context, gst_ffmpeg_codectype_to_video_caps (AVCodecContext * context,
enum AVCodecID codec_id, gboolean encode, AVCodec * codec) enum AVCodecID codec_id, gboolean encode, const AVCodec * codec)
{ {
GstCaps *caps; GstCaps *caps;

View file

@ -56,7 +56,7 @@ GstCaps *
gst_ffmpeg_codectype_to_video_caps (AVCodecContext *context, gst_ffmpeg_codectype_to_video_caps (AVCodecContext *context,
enum AVCodecID codec_id, enum AVCodecID codec_id,
gboolean encode, gboolean encode,
AVCodec *codec); const AVCodec *codec);
/* /*
* caps_to_codecid () transforms a GstCaps that belongs to * caps_to_codecid () transforms a GstCaps that belongs to

View file

@ -114,6 +114,11 @@ av_smp_format_depth(enum AVSampleFormat smp_fmt);
GstBuffer * GstBuffer *
new_aligned_buffer (gint size); new_aligned_buffer (gint size);
/**
* GstAvCodecCompliance:
*
* Since: 1.22
*/
typedef enum typedef enum
{ {
GST_AV_CODEC_COMPLIANCE_AUTO = G_MAXINT, GST_AV_CODEC_COMPLIANCE_AUTO = G_MAXINT,

View file

@ -65,9 +65,6 @@ enum
}; };
/* 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. */
static void gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass);
static void gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass);
static void gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec);
static void gst_ffmpegviddec_finalize (GObject * object); static void gst_ffmpegviddec_finalize (GObject * object);
static gboolean gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, static gboolean gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
@ -104,9 +101,10 @@ static gboolean picture_changed (GstFFMpegVidDec * ffmpegdec,
static gboolean context_changed (GstFFMpegVidDec * ffmpegdec, static gboolean context_changed (GstFFMpegVidDec * ffmpegdec,
AVCodecContext * context); AVCodecContext * context);
#define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("avdec-params") G_DEFINE_ABSTRACT_TYPE (GstFFMpegVidDec, gst_ffmpegviddec,
GST_TYPE_VIDEO_DECODER);
static GstElementClass *parent_class = NULL; #define parent_class gst_ffmpegviddec_parent_class
#define GST_FFMPEGVIDDEC_TYPE_LOWRES (gst_ffmpegviddec_lowres_get_type()) #define GST_FFMPEGVIDDEC_TYPE_LOWRES (gst_ffmpegviddec_lowres_get_type())
static GType static GType
@ -189,17 +187,40 @@ dup_caps_with_alternate (GstCaps * caps)
} }
static void static void
gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass) gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_ffmpegviddec_set_property;
gobject_class->get_property = gst_ffmpegviddec_get_property;
/**
* GstFFMpegVidDec:std-compliance:
*
* Specifies standard compliance mode to use
*
* Since: 1.22
*/
g_object_class_install_property (gobject_class, PROP_STD_COMPLIANCE,
g_param_spec_enum ("std-compliance", "Standard Compliance",
"Standard compliance mode to use", GST_TYPE_AV_CODEC_COMPLIANCE,
DEFAULT_STD_COMPLIANCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
gst_ffmpegviddec_subclass_init (GstFFMpegVidDecClass * klass,
gconstpointer class_data)
{
GstVideoDecoderClass *viddec_class = GST_VIDEO_DECODER_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstPadTemplate *sinktempl, *srctempl; GstPadTemplate *sinktempl, *srctempl;
GstCaps *sinkcaps, *srccaps; GstCaps *sinkcaps, *srccaps;
AVCodec *in_plugin; const AVCodec *in_plugin;
gchar *longname, *description; gchar *longname, *description;
int caps;
in_plugin = in_plugin = class_data;
(AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
GST_FFDEC_PARAMS_QDATA);
g_assert (in_plugin != NULL); g_assert (in_plugin != NULL);
/* construct the element details struct */ /* construct the element details struct */
@ -239,16 +260,6 @@ gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass)
gst_caps_unref (srccaps); gst_caps_unref (srccaps);
klass->in_plugin = in_plugin; klass->in_plugin = in_plugin;
}
static void
gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstVideoDecoderClass *viddec_class = GST_VIDEO_DECODER_CLASS (klass);
int caps;
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gst_ffmpegviddec_finalize; gobject_class->finalize = gst_ffmpegviddec_finalize;
@ -295,18 +306,6 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
DEFAULT_THREAD_TYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); DEFAULT_THREAD_TYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
} }
/**
* GstFFMpegVidDec::std-compliance:
*
* Specifies standard compliance mode to use
*
* Since: 1.20
*/
g_object_class_install_property (gobject_class, PROP_STD_COMPLIANCE,
g_param_spec_enum ("std-compliance", "Standard Compliance",
"Standard compliance mode to use", GST_TYPE_AV_CODEC_COMPLIANCE,
DEFAULT_STD_COMPLIANCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
viddec_class->set_format = gst_ffmpegviddec_set_format; viddec_class->set_format = gst_ffmpegviddec_set_format;
viddec_class->handle_frame = gst_ffmpegviddec_handle_frame; viddec_class->handle_frame = gst_ffmpegviddec_handle_frame;
viddec_class->start = gst_ffmpegviddec_start; viddec_class->start = gst_ffmpegviddec_start;
@ -323,10 +322,16 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_SKIPFRAME, 0); gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_SKIPFRAME, 0);
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_THREAD_TYPE, 0); gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_THREAD_TYPE, 0);
gst_type_mark_as_plugin_api (GST_TYPE_AV_CODEC_COMPLIANCE, 0); gst_type_mark_as_plugin_api (GST_TYPE_AV_CODEC_COMPLIANCE, 0);
gst_type_mark_as_plugin_api (GST_TYPE_FFMPEGVIDDEC, 0);
} }
static void static void
gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec) gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec)
{
}
static void
gst_ffmpegviddec_subinit (GstFFMpegVidDec * ffmpegdec)
{ {
GstFFMpegVidDecClass *klass = GstFFMpegVidDecClass *klass =
(GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec); (GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec);
@ -352,7 +357,7 @@ gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec)
static void static void
gst_ffmpegviddec_finalize (GObject * object) gst_ffmpegviddec_finalize (GObject * object)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
av_frame_free (&ffmpegdec->picture); av_frame_free (&ffmpegdec->picture);
avcodec_free_context (&ffmpegdec->context); avcodec_free_context (&ffmpegdec->context);
@ -391,7 +396,7 @@ gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec, gboolean reset)
GstFFMpegVidDecClass *oclass; GstFFMpegVidDecClass *oclass;
guint i; guint i;
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec"); GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec");
@ -425,7 +430,7 @@ gst_ffmpegviddec_open (GstFFMpegVidDec * ffmpegdec)
GstFFMpegVidDecClass *oclass; GstFFMpegVidDecClass *oclass;
guint i; guint i;
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0) if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0)
goto could_not_open; goto could_not_open;
@ -510,8 +515,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
gboolean is_live; gboolean is_live;
GstQuery *query; GstQuery *query;
ffmpegdec = (GstFFMpegVidDec *) decoder; ffmpegdec = GST_FFMPEGVIDDEC (decoder);
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
GST_DEBUG_OBJECT (ffmpegdec, "setcaps called"); GST_DEBUG_OBJECT (ffmpegdec, "setcaps called");
@ -889,7 +894,7 @@ gst_ffmpegviddec_can_direct_render (GstFFMpegVidDec * ffmpegdec)
if (!ffmpegdec->direct_rendering) if (!ffmpegdec->direct_rendering)
return FALSE; return FALSE;
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
return ((oclass->in_plugin->capabilities & AV_CODEC_CAP_DR1) == return ((oclass->in_plugin->capabilities & AV_CODEC_CAP_DR1) ==
AV_CODEC_CAP_DR1); AV_CODEC_CAP_DR1);
} }
@ -907,7 +912,7 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
GstFlowReturn ret; GstFlowReturn ret;
int create_buffer_flags = 0; int create_buffer_flags = 0;
ffmpegdec = (GstFFMpegVidDec *) context->opaque; ffmpegdec = GST_FFMPEGVIDDEC (context->opaque);
GST_DEBUG_OBJECT (ffmpegdec, "getting buffer picture %p", picture); GST_DEBUG_OBJECT (ffmpegdec, "getting buffer picture %p", picture);
@ -2014,7 +2019,7 @@ no_codec:
static GstFlowReturn static GstFlowReturn
gst_ffmpegviddec_drain (GstVideoDecoder * decoder) gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gboolean got_frame = FALSE; gboolean got_frame = FALSE;
@ -2049,7 +2054,7 @@ static GstFlowReturn
gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder, gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame) GstVideoCodecFrame * frame)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
guint8 *data; guint8 *data;
gint size; gint size;
gboolean got_frame; gboolean got_frame;
@ -2156,10 +2161,10 @@ send_packet_failed:
static gboolean static gboolean
gst_ffmpegviddec_start (GstVideoDecoder * decoder) gst_ffmpegviddec_start (GstVideoDecoder * decoder)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
GstFFMpegVidDecClass *oclass; GstFFMpegVidDecClass *oclass;
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); oclass = GST_FFMPEGVIDDEC_GET_CLASS (ffmpegdec);
GST_OBJECT_LOCK (ffmpegdec); GST_OBJECT_LOCK (ffmpegdec);
avcodec_free_context (&ffmpegdec->context); avcodec_free_context (&ffmpegdec->context);
@ -2178,7 +2183,7 @@ gst_ffmpegviddec_start (GstVideoDecoder * decoder)
static gboolean static gboolean
gst_ffmpegviddec_stop (GstVideoDecoder * decoder) gst_ffmpegviddec_stop (GstVideoDecoder * decoder)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
GST_OBJECT_LOCK (ffmpegdec); GST_OBJECT_LOCK (ffmpegdec);
gst_ffmpegviddec_close (ffmpegdec, FALSE); gst_ffmpegviddec_close (ffmpegdec, FALSE);
@ -2233,7 +2238,7 @@ gst_ffmpegviddec_finish (GstVideoDecoder * decoder)
static gboolean static gboolean
gst_ffmpegviddec_flush (GstVideoDecoder * decoder) gst_ffmpegviddec_flush (GstVideoDecoder * decoder)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
if (ffmpegdec->opened) { if (ffmpegdec->opened) {
GST_LOG_OBJECT (decoder, "flushing buffers"); GST_LOG_OBJECT (decoder, "flushing buffers");
@ -2246,7 +2251,7 @@ gst_ffmpegviddec_flush (GstVideoDecoder * decoder)
static gboolean static gboolean
gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) decoder; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (decoder);
GstVideoCodecState *state; GstVideoCodecState *state;
GstBufferPool *pool; GstBufferPool *pool;
guint size, min, max; guint size, min, max;
@ -2418,7 +2423,7 @@ static void
gst_ffmpegviddec_set_property (GObject * object, gst_ffmpegviddec_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec) guint prop_id, const GValue * value, GParamSpec * pspec)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOWRES: case PROP_LOWRES:
@ -2458,7 +2463,7 @@ static void
gst_ffmpegviddec_get_property (GObject * object, gst_ffmpegviddec_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec) guint prop_id, GValue * value, GParamSpec * pspec)
{ {
GstFFMpegVidDec *ffmpegdec = (GstFFMpegVidDec *) object; GstFFMpegVidDec *ffmpegdec = GST_FFMPEGVIDDEC (object);
switch (prop_id) { switch (prop_id) {
case PROP_LOWRES: case PROP_LOWRES:
@ -2498,14 +2503,14 @@ gst_ffmpegviddec_register (GstPlugin * plugin)
{ {
GTypeInfo typeinfo = { GTypeInfo typeinfo = {
sizeof (GstFFMpegVidDecClass), sizeof (GstFFMpegVidDecClass),
(GBaseInitFunc) gst_ffmpegviddec_base_init,
NULL, NULL,
(GClassInitFunc) gst_ffmpegviddec_class_init, NULL,
(GClassInitFunc) gst_ffmpegviddec_subclass_init,
NULL, NULL,
NULL, NULL,
sizeof (GstFFMpegVidDec), sizeof (GstFFMpegVidDec),
0, 0,
(GInstanceInitFunc) gst_ffmpegviddec_init, (GInstanceInitFunc) gst_ffmpegviddec_subinit,
}; };
GType type; GType type;
AVCodec *in_plugin; AVCodec *in_plugin;
@ -2634,10 +2639,10 @@ gst_ffmpegviddec_register (GstPlugin * plugin)
if (!type) { if (!type) {
/* create the gtype now */ /* create the gtype now */
typeinfo.class_data = in_plugin;
type = type =
g_type_register_static (GST_TYPE_VIDEO_DECODER, type_name, &typeinfo, g_type_register_static (GST_TYPE_FFMPEGVIDDEC, type_name, &typeinfo,
0); 0);
g_type_set_qdata (type, GST_FFDEC_PARAMS_QDATA, (gpointer) in_plugin);
} }
/* (Ronald) MPEG-4 gets a higher priority because it has been well- /* (Ronald) MPEG-4 gets a higher priority because it has been well-

View file

@ -25,7 +25,22 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_TYPE_FFMPEGVIDDEC (gst_ffmpegviddec_get_type())
#define GST_FFMPEGVIDDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGVIDDEC,GstFFMpegVidDec))
#define GST_FFMPEGVIDDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGVIDDEC,GstFFMpegVidDecClass))
#define GST_FFMPEGVIDDEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_FFMPEGVIDDEC, GstFFMpegVidDecClass))
#define GST_IS_FFMPEGVIDDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGVIDDEC))
#define GST_IS_FFMPEGVIDDEC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGVIDDEC))
/**
* GstFFMpegVidDec:
*
* The #GstFFMpegVidDec data structure.
*
* Since: 1.22
*/
typedef struct _GstFFMpegVidDec GstFFMpegVidDec; typedef struct _GstFFMpegVidDec GstFFMpegVidDec;
struct _GstFFMpegVidDec struct _GstFFMpegVidDec
{ {
GstVideoDecoder parent; GstVideoDecoder parent;
@ -87,9 +102,11 @@ struct _GstFFMpegVidDecClass
{ {
GstVideoDecoderClass parent_class; GstVideoDecoderClass parent_class;
AVCodec *in_plugin; const AVCodec *in_plugin;
}; };
GType gst_ffmpegviddec_get_type (void);
G_END_DECLS G_END_DECLS
#endif #endif