/**
 * gst_vaapi_object_new:
 * @klass: The object class
 * @display: The #GstVaapiDisplay
 *
 * Creates a new #GstVaapiObject. The @klass argument shall not be
 * %NULL, and it must reference a statically allocated descriptor.
 *
 * This function zero-initializes the derived object data. Also note
 * that this is an internal function that shall not be used outside of
 * libgstvaapi libraries.
 *
 * Returns: The newly allocated #GstVaapiObject
 */
gpointer
gst_vaapi_object_new (const GstVaapiObjectClass * klass,
    GstVaapiDisplay * display)
{
  const GstVaapiMiniObjectClass *const object_class =
      GST_VAAPI_MINI_OBJECT_CLASS (klass);
  GstVaapiObject *object;
  guint sub_size;

  g_return_val_if_fail (klass != NULL, NULL);
  g_return_val_if_fail (display != NULL, NULL);

  object = (GstVaapiObject *) gst_vaapi_mini_object_new (object_class);
  if (!object)
    return NULL;

  object->display = gst_object_ref (display);
  object->object_id = VA_INVALID_ID;

  sub_size = object_class->size - sizeof (*object);
  if (sub_size > 0)
    memset (((guchar *) object) + sizeof (*object), 0, sub_size);

  if (klass->init)
    klass->init (object);
  return object;
}
GstVaapiDecoder *
gst_vaapi_decoder_new (const GstVaapiDecoderClass * klass,
    GstVaapiDisplay * display, GstCaps * caps)
{
  GstVaapiDecoder *decoder;

  g_return_val_if_fail (display != NULL, NULL);
  g_return_val_if_fail (GST_IS_CAPS (caps), NULL);

  decoder = (GstVaapiDecoder *)
      gst_vaapi_mini_object_new (GST_VAAPI_MINI_OBJECT_CLASS (klass));
  if (!decoder)
    return NULL;

  if (!gst_vaapi_decoder_init (decoder, display, caps))
    goto error;
  return decoder;

  /* ERRORS */
error:
  {
    gst_vaapi_decoder_unref (decoder);
    return NULL;
  }
}
void
gst_vaapi_object_class_init (GstVaapiObjectClass * klass, guint size)
{
  GstVaapiMiniObjectClass *const object_class =
      GST_VAAPI_MINI_OBJECT_CLASS (klass);

  object_class->size = size;
  object_class->finalize = (GDestroyNotify) gst_vaapi_object_finalize;
}
static void
gst_vaapi_display_glx_class_init (GstVaapiDisplayGLXClass * klass)
{
  GstVaapiMiniObjectClass *const object_class =
      GST_VAAPI_MINI_OBJECT_CLASS (klass);
  GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);

  gst_vaapi_display_x11_class_init (&klass->parent_class);

  object_class->size = sizeof (GstVaapiDisplayGLX);
  dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
  dpy_class->create_window = gst_vaapi_display_glx_create_window;
  dpy_class->create_texture = gst_vaapi_display_glx_create_texture;
}
static void
gst_vaapi_decoder_jpeg_class_init(GstVaapiDecoderJpegClass *klass)
{
    GstVaapiMiniObjectClass * const object_class =
        GST_VAAPI_MINI_OBJECT_CLASS(klass);
    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);

    object_class->size          = sizeof(GstVaapiDecoderJpeg);
    object_class->finalize      = (GDestroyNotify)gst_vaapi_decoder_finalize;

    decoder_class->create       = gst_vaapi_decoder_jpeg_create;
    decoder_class->destroy      = gst_vaapi_decoder_jpeg_destroy;
    decoder_class->parse        = gst_vaapi_decoder_jpeg_parse;
    decoder_class->decode       = gst_vaapi_decoder_jpeg_decode;
    decoder_class->start_frame  = gst_vaapi_decoder_jpeg_start_frame;
    decoder_class->end_frame    = gst_vaapi_decoder_jpeg_end_frame;
}
/* Helper function to create new GstVaapiEncoder instances (internal) */
GstVaapiEncoder *
gst_vaapi_encoder_new (const GstVaapiEncoderClass * klass,
    GstVaapiDisplay * display)
{
  GstVaapiEncoder *encoder;

  encoder = (GstVaapiEncoder *)
      gst_vaapi_mini_object_new0 (GST_VAAPI_MINI_OBJECT_CLASS (klass));
  if (!encoder)
    return NULL;

  if (!gst_vaapi_encoder_init (encoder, display))
    goto error;
  return encoder;

error:
  gst_vaapi_encoder_unref (encoder);
  return NULL;
}
static gboolean
gst_vaapi_decoder_init (GstVaapiDecoder * decoder, GstVaapiDisplay * display,
    GstCaps * caps)
{
  const GstVaapiDecoderClass *const klass =
      GST_VAAPI_DECODER_GET_CLASS (decoder);
  GstVideoCodecState *codec_state;
  guint sub_size;

  parser_state_init (&decoder->parser_state);

  codec_state = g_slice_new0 (GstVideoCodecState);
  codec_state->ref_count = 1;
  gst_video_info_init (&codec_state->info);

  decoder->user_data = NULL;
  decoder->display = gst_vaapi_display_ref (display);
  decoder->va_display = GST_VAAPI_DISPLAY_VADISPLAY (display);
  decoder->context = NULL;
  decoder->va_context = VA_INVALID_ID;
  decoder->codec = 0;
  decoder->codec_state = codec_state;
  decoder->codec_state_changed_func = NULL;
  decoder->codec_state_changed_data = NULL;

  decoder->buffers = g_async_queue_new_full ((GDestroyNotify) gst_buffer_unref);
  decoder->frames = g_async_queue_new_full ((GDestroyNotify)
      gst_video_codec_frame_unref);

  if (!set_caps (decoder, caps))
    return FALSE;

  sub_size = GST_VAAPI_MINI_OBJECT_CLASS (klass)->size - sizeof (*decoder);
  if (sub_size > 0)
    memset (((guchar *) decoder) + sizeof (*decoder), 0, sub_size);

  if (klass->create && !klass->create (decoder))
    return FALSE;
  return TRUE;
}
static inline gpointer
egl_object_new0 (const EglObjectClass * klass)
{
  return gst_vaapi_mini_object_new0 (GST_VAAPI_MINI_OBJECT_CLASS (klass));
}