mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-08 23:42:28 +00:00
encoder: fix subclassing process.
Fix the GstVaapiEncoderClass parent class type. Make sure to validate subclass hooks as early as possible, i.e. in gst_vaapi_encoder_init(), thus avoiding useless run-time checks. Also simplify the subclass initialization process to be less error prone.
This commit is contained in:
parent
0fb7c60508
commit
8ecc35ecf2
6 changed files with 63 additions and 140 deletions
|
@ -261,9 +261,6 @@ gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder,
|
||||||
GstVaapiCodedBufferProxy *coded_buf = NULL;
|
GstVaapiCodedBufferProxy *coded_buf = NULL;
|
||||||
GstVaapiEncoderSyncPic *sync_pic = NULL;
|
GstVaapiEncoderSyncPic *sync_pic = NULL;
|
||||||
|
|
||||||
if (!klass->reordering || !klass->encode)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
picture = NULL;
|
picture = NULL;
|
||||||
sync_pic = NULL;
|
sync_pic = NULL;
|
||||||
|
@ -350,18 +347,9 @@ end:
|
||||||
GstVaapiEncoderStatus
|
GstVaapiEncoderStatus
|
||||||
gst_vaapi_encoder_flush (GstVaapiEncoder * encoder)
|
gst_vaapi_encoder_flush (GstVaapiEncoder * encoder)
|
||||||
{
|
{
|
||||||
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_SUCCESS;
|
|
||||||
GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
||||||
|
|
||||||
if (!klass->flush)
|
return klass->flush (encoder);
|
||||||
goto error;
|
|
||||||
|
|
||||||
ret = klass->flush (encoder);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
error:
|
|
||||||
GST_ERROR ("flush failed");
|
|
||||||
return GST_VAAPI_ENCODER_STATUS_FUNC_PTR_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstVaapiEncoderStatus
|
GstVaapiEncoderStatus
|
||||||
|
@ -390,9 +378,8 @@ gst_vaapi_encoder_ensure_context (GstVaapiEncoder * encoder)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
memset (&info, 0, sizeof (info));
|
memset (&info, 0, sizeof (info));
|
||||||
if (!klass->get_context_info || !klass->get_context_info (encoder, &info)) {
|
if (!klass->get_context_info (encoder, &info))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
context = gst_vaapi_context_new_full (GST_VAAPI_ENCODER_DISPLAY (encoder),
|
context = gst_vaapi_context_new_full (GST_VAAPI_ENCODER_DISPLAY (encoder),
|
||||||
&info);
|
&info);
|
||||||
|
@ -418,9 +405,6 @@ gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder,
|
||||||
}
|
}
|
||||||
GST_VAAPI_ENCODER_VIDEO_INFO (encoder) = in_state->info;
|
GST_VAAPI_ENCODER_VIDEO_INFO (encoder) = in_state->info;
|
||||||
|
|
||||||
if (!klass->set_format)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
out_caps = klass->set_format (encoder, in_state, ref_caps);
|
out_caps = klass->set_format (encoder, in_state, ref_caps);
|
||||||
if (!out_caps)
|
if (!out_caps)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -460,19 +444,28 @@ error:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
|
gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
|
||||||
{
|
{
|
||||||
GstVaapiEncoderClass *kclass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
||||||
|
|
||||||
g_assert (kclass);
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
g_assert (display);
|
|
||||||
|
|
||||||
g_return_val_if_fail (display, FALSE);
|
#define CHECK_VTABLE_HOOK(FUNC) do { \
|
||||||
g_return_val_if_fail (encoder->display == NULL, FALSE);
|
if (!klass->FUNC) \
|
||||||
|
goto error_invalid_vtable; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
CHECK_VTABLE_HOOK (init);
|
||||||
|
CHECK_VTABLE_HOOK (finalize);
|
||||||
|
CHECK_VTABLE_HOOK (encode);
|
||||||
|
CHECK_VTABLE_HOOK (reordering);
|
||||||
|
CHECK_VTABLE_HOOK (flush);
|
||||||
|
CHECK_VTABLE_HOOK (get_context_info);
|
||||||
|
CHECK_VTABLE_HOOK (set_format);
|
||||||
|
|
||||||
|
#undef CHECK_VTABLE_HOOK
|
||||||
|
|
||||||
encoder->display = gst_vaapi_display_ref (display);
|
encoder->display = gst_vaapi_display_ref (display);
|
||||||
encoder->va_display = gst_vaapi_display_get_display (display);
|
encoder->va_display = gst_vaapi_display_get_display (display);
|
||||||
encoder->context = NULL;
|
|
||||||
encoder->va_context = VA_INVALID_ID;
|
encoder->va_context = VA_INVALID_ID;
|
||||||
encoder->caps = NULL;
|
|
||||||
|
|
||||||
gst_video_info_init (&encoder->video_info);
|
gst_video_info_init (&encoder->video_info);
|
||||||
|
|
||||||
|
@ -482,18 +475,22 @@ gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
|
||||||
g_queue_init (&encoder->sync_pictures);
|
g_queue_init (&encoder->sync_pictures);
|
||||||
g_cond_init (&encoder->sync_ready);
|
g_cond_init (&encoder->sync_ready);
|
||||||
|
|
||||||
if (kclass->init)
|
return klass->init (encoder);
|
||||||
return kclass->init (encoder);
|
|
||||||
return TRUE;
|
/* ERRORS */
|
||||||
|
error_invalid_vtable:
|
||||||
|
{
|
||||||
|
GST_ERROR ("invalid subclass hook (internal error)");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gst_vaapi_encoder_destroy (GstVaapiEncoder * encoder)
|
gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder)
|
||||||
{
|
{
|
||||||
GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
|
||||||
|
|
||||||
if (klass->destroy)
|
klass->finalize (encoder);
|
||||||
klass->destroy (encoder);
|
|
||||||
|
|
||||||
gst_vaapi_encoder_free_sync_pictures (encoder);
|
gst_vaapi_encoder_free_sync_pictures (encoder);
|
||||||
gst_vaapi_video_pool_replace (&encoder->codedbuf_pool, NULL);
|
gst_vaapi_video_pool_replace (&encoder->codedbuf_pool, NULL);
|
||||||
|
@ -508,22 +505,6 @@ gst_vaapi_encoder_destroy (GstVaapiEncoder * encoder)
|
||||||
g_cond_clear (&encoder->sync_ready);
|
g_cond_clear (&encoder->sync_ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder)
|
|
||||||
{
|
|
||||||
gst_vaapi_encoder_destroy (encoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gst_vaapi_encoder_class_init (GstVaapiEncoderClass * klass)
|
|
||||||
{
|
|
||||||
GstVaapiMiniObjectClass *const object_class =
|
|
||||||
GST_VAAPI_MINI_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->size = sizeof (GstVaapiEncoder);
|
|
||||||
object_class->finalize = (GDestroyNotify) gst_vaapi_encoder_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
GstVaapiEncoder *
|
GstVaapiEncoder *
|
||||||
gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass,
|
gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass,
|
||||||
GstVaapiDisplay * display)
|
GstVaapiDisplay * display)
|
||||||
|
|
|
@ -1711,10 +1711,10 @@ gst_vaapi_encoder_h264_init (GstVaapiEncoder * base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vaapi_encoder_h264_destroy (GstVaapiEncoder * base)
|
gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base)
|
||||||
{
|
{
|
||||||
/*free private buffers */
|
/*free private buffers */
|
||||||
GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264 (base);
|
GstVaapiEncoderH264 *const encoder = GST_VAAPI_ENCODER_H264 (base);
|
||||||
GstVaapiEncPicture *pic;
|
GstVaapiEncPicture *pic;
|
||||||
GstVaapiEncoderH264Ref *ref;
|
GstVaapiEncoderH264Ref *ref;
|
||||||
|
|
||||||
|
@ -1736,38 +1736,14 @@ gst_vaapi_encoder_h264_destroy (GstVaapiEncoder * base)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_encoder_h264_class_init (GstVaapiEncoderH264Class * klass)
|
|
||||||
{
|
|
||||||
GstVaapiMiniObjectClass *const object_class =
|
|
||||||
GST_VAAPI_MINI_OBJECT_CLASS (klass);
|
|
||||||
GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
|
|
||||||
|
|
||||||
gst_vaapi_encoder_class_init (encoder_class);
|
|
||||||
|
|
||||||
object_class->size = sizeof (GstVaapiEncoderH264);
|
|
||||||
|
|
||||||
encoder_class->init = gst_vaapi_encoder_h264_init;
|
|
||||||
encoder_class->destroy = gst_vaapi_encoder_h264_destroy;
|
|
||||||
encoder_class->set_format = gst_vaapi_encoder_h264_set_format;
|
|
||||||
encoder_class->get_context_info = gst_vaapi_encoder_h264_get_context_info;
|
|
||||||
encoder_class->reordering = gst_vaapi_encoder_h264_reordering;
|
|
||||||
encoder_class->encode = gst_vaapi_encoder_h264_encode;
|
|
||||||
encoder_class->get_codec_data = gst_vaapi_encoder_h264_get_codec_data;
|
|
||||||
encoder_class->flush = gst_vaapi_encoder_h264_flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const GstVaapiEncoderClass *
|
static inline const GstVaapiEncoderClass *
|
||||||
gst_vaapi_encoder_h264_class ()
|
gst_vaapi_encoder_h264_class ()
|
||||||
{
|
{
|
||||||
static GstVaapiEncoderH264Class g_class;
|
static const GstVaapiEncoderClass GstVaapiEncoderH264Class = {
|
||||||
static gsize g_class_init = FALSE;
|
GST_VAAPI_ENCODER_CLASS_INIT (H264, h264),
|
||||||
|
.get_codec_data = gst_vaapi_encoder_h264_get_codec_data
|
||||||
if (g_once_init_enter (&g_class_init)) {
|
};
|
||||||
gst_vaapi_encoder_h264_class_init (&g_class);
|
return &GstVaapiEncoderH264Class;
|
||||||
g_once_init_leave (&g_class_init, TRUE);
|
|
||||||
}
|
|
||||||
return GST_VAAPI_ENCODER_CLASS (&g_class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstVaapiEncoder *
|
GstVaapiEncoder *
|
||||||
|
|
|
@ -33,14 +33,6 @@ G_BEGIN_DECLS
|
||||||
((GstVaapiEncoderH264 *)(encoder))
|
((GstVaapiEncoderH264 *)(encoder))
|
||||||
#define GST_VAAPI_ENCODER_H264_CAST(encoder) \
|
#define GST_VAAPI_ENCODER_H264_CAST(encoder) \
|
||||||
((GstVaapiEncoderH264 *)(encoder))
|
((GstVaapiEncoderH264 *)(encoder))
|
||||||
#define GST_VAAPI_ENCODER_H264_CLASS(klass) \
|
|
||||||
((GstVaapiEncoderH264Class *)(klass))
|
|
||||||
#define GST_IS_VAAPI_ENCODER_H264_CLASS(klass) \
|
|
||||||
((klass) != NULL)
|
|
||||||
#define GST_VAAPI_ENCODER_H264_GET_CLASS(obj) \
|
|
||||||
GST_VAAPI_ENCODER_H264_CLASS(GST_VAAPI_MINI_OBJECT_GET_CLASS(obj))
|
|
||||||
|
|
||||||
typedef struct _GstVaapiEncoderH264Class GstVaapiEncoderH264Class;
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -115,12 +107,6 @@ struct _GstVaapiEncoderH264
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVaapiEncoderH264Class
|
|
||||||
{
|
|
||||||
/*< private > */
|
|
||||||
GstVaapiEncoderClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*GST_VAAPI_ENCODER_H264_PRIV_H */
|
#endif /*GST_VAAPI_ENCODER_H264_PRIV_H */
|
||||||
|
|
|
@ -741,7 +741,7 @@ push_reference (GstVaapiEncoderMpeg2 * encoder, GstVaapiSurfaceProxy * ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vaapi_encoder_mpeg2_destroy (GstVaapiEncoder * base)
|
gst_vaapi_encoder_mpeg2_finalize (GstVaapiEncoder * base)
|
||||||
{
|
{
|
||||||
/*free private buffers */
|
/*free private buffers */
|
||||||
GstVaapiEncoderMpeg2 *encoder = GST_VAAPI_ENCODER_MPEG2 (base);
|
GstVaapiEncoderMpeg2 *encoder = GST_VAAPI_ENCODER_MPEG2 (base);
|
||||||
|
@ -756,37 +756,13 @@ gst_vaapi_encoder_mpeg2_destroy (GstVaapiEncoder * base)
|
||||||
g_queue_clear (&encoder->b_frames);
|
g_queue_clear (&encoder->b_frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_vaapi_encoder_mpeg2_class_init (GstVaapiEncoderMpeg2Class * klass)
|
|
||||||
{
|
|
||||||
GstVaapiMiniObjectClass *const object_class =
|
|
||||||
GST_VAAPI_MINI_OBJECT_CLASS (klass);
|
|
||||||
GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
|
|
||||||
|
|
||||||
gst_vaapi_encoder_class_init (encoder_class);
|
|
||||||
|
|
||||||
object_class->size = sizeof (GstVaapiEncoderMpeg2);
|
|
||||||
|
|
||||||
encoder_class->init = gst_vaapi_encoder_mpeg2_init;
|
|
||||||
encoder_class->destroy = gst_vaapi_encoder_mpeg2_destroy;
|
|
||||||
encoder_class->set_format = gst_vaapi_encoder_mpeg2_set_format;
|
|
||||||
encoder_class->get_context_info = gst_vaapi_encoder_mpeg2_get_context_info;
|
|
||||||
encoder_class->reordering = gst_vaapi_encoder_mpeg2_reordering;
|
|
||||||
encoder_class->encode = gst_vaapi_encoder_mpeg2_encode;
|
|
||||||
encoder_class->flush = gst_vaapi_encoder_mpeg2_flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline const GstVaapiEncoderClass *
|
static inline const GstVaapiEncoderClass *
|
||||||
gst_vaapi_encoder_mpeg2_class ()
|
gst_vaapi_encoder_mpeg2_class ()
|
||||||
{
|
{
|
||||||
static GstVaapiEncoderMpeg2Class g_class;
|
static const GstVaapiEncoderClass GstVaapiEncoderMpeg2Class = {
|
||||||
static gsize g_class_init = FALSE;
|
GST_VAAPI_ENCODER_CLASS_INIT (Mpeg2, mpeg2),
|
||||||
|
};
|
||||||
if (g_once_init_enter (&g_class_init)) {
|
return &GstVaapiEncoderMpeg2Class;
|
||||||
gst_vaapi_encoder_mpeg2_class_init (&g_class);
|
|
||||||
g_once_init_leave (&g_class_init, TRUE);
|
|
||||||
}
|
|
||||||
return GST_VAAPI_ENCODER_CLASS (&g_class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GstVaapiEncoder *
|
GstVaapiEncoder *
|
||||||
|
|
|
@ -32,14 +32,6 @@ G_BEGIN_DECLS
|
||||||
((GstVaapiEncoderMpeg2 *)(encoder))
|
((GstVaapiEncoderMpeg2 *)(encoder))
|
||||||
#define GST_VAAPI_ENCODER_MPEG2_CAST(encoder) \
|
#define GST_VAAPI_ENCODER_MPEG2_CAST(encoder) \
|
||||||
((GstVaapiEncoderMpeg2 *)(encoder))
|
((GstVaapiEncoderMpeg2 *)(encoder))
|
||||||
#define GST_VAAPI_ENCODER_MPEG2_CLASS(klass) \
|
|
||||||
((GstVaapiEncoderMpeg2Class *)(klass))
|
|
||||||
#define GST_IS_VAAPI_ENCODER_MPEG2_CLASS(klass) \
|
|
||||||
((klass) != NULL)
|
|
||||||
#define GST_VAAPI_ENCODER_MPEG2_GET_CLASS(obj) \
|
|
||||||
GST_VAAPI_ENCODER_MPEG2_CLASS(GST_VAAPI_MINI_OBJECT_GET_CLASS(obj))
|
|
||||||
|
|
||||||
typedef struct _GstVaapiEncoderMpeg2Class GstVaapiEncoderMpeg2Class;
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -105,12 +97,6 @@ struct _GstVaapiEncoderMpeg2
|
||||||
guint32 frame_num; /* same value picture header, but it's not mod by 1024 */
|
guint32 frame_num; /* same value picture header, but it's not mod by 1024 */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVaapiEncoderMpeg2Class
|
|
||||||
{
|
|
||||||
/*< private > */
|
|
||||||
GstVaapiEncoderClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* GST_VAAPI_ENCODER_MPEG2_PRIV_H */
|
#endif /* GST_VAAPI_ENCODER_MPEG2_PRIV_H */
|
||||||
|
|
|
@ -105,10 +105,10 @@ struct _GstVaapiEncoder
|
||||||
|
|
||||||
struct _GstVaapiEncoderClass
|
struct _GstVaapiEncoderClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GstVaapiMiniObjectClass parent_class;
|
||||||
|
|
||||||
gboolean (*init) (GstVaapiEncoder * encoder);
|
gboolean (*init) (GstVaapiEncoder * encoder);
|
||||||
void (*destroy) (GstVaapiEncoder * encoder);
|
void (*finalize) (GstVaapiEncoder * encoder);
|
||||||
|
|
||||||
GstCaps * (*set_format) (GstVaapiEncoder * encoder,
|
GstCaps * (*set_format) (GstVaapiEncoder * encoder,
|
||||||
GstVideoCodecState * in_state,
|
GstVideoCodecState * in_state,
|
||||||
|
@ -132,13 +132,31 @@ struct _GstVaapiEncoderClass
|
||||||
GstBuffer ** codec_data);
|
GstBuffer ** codec_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
#define GST_VAAPI_ENCODER_CLASS_HOOK(codec, func) \
|
||||||
gst_vaapi_encoder_class_init (GstVaapiEncoderClass * klass);
|
.func = G_PASTE (G_PASTE (G_PASTE (gst_vaapi_encoder_,codec),_), func)
|
||||||
|
|
||||||
|
#define GST_VAAPI_ENCODER_CLASS_INIT_BASE(CODEC) \
|
||||||
|
.parent_class = { \
|
||||||
|
.size = sizeof (G_PASTE (GstVaapiEncoder, CODEC)), \
|
||||||
|
.finalize = (GDestroyNotify) gst_vaapi_encoder_finalize \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GST_VAAPI_ENCODER_CLASS_INIT(CODEC, codec) \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_INIT_BASE (CODEC), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, init), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, finalize), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_format), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, get_context_info), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, reordering), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, encode), \
|
||||||
|
GST_VAAPI_ENCODER_CLASS_HOOK (codec, flush)
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
GstVaapiEncoder *
|
GstVaapiEncoder *
|
||||||
gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass,
|
gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass,
|
||||||
GstVaapiDisplay * display);
|
GstVaapiDisplay * display);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
void
|
void
|
||||||
gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder);
|
gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue