/**
 * 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_vaapi_display_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 && klass->init)
    klass->init (object);
  return object;
}
/**
 * gst_vaapi_video_meta_copy:
 * @meta: a #GstVaapiVideoMeta
 *
 * Creates a copy of #GstVaapiVideoMeta object @meta. The original
 * @meta object shall not contain any VA objects created from a
 * #GstVaapiVideoPool.
 *
 * Return value: the newly allocated #GstVaapiVideoMeta, or %NULL on error
 */
GstVaapiVideoMeta *
gst_vaapi_video_meta_copy (GstVaapiVideoMeta * meta)
{
  GstVaapiVideoMeta *copy;

  g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);

  if (meta->image_pool)
    return NULL;

  copy = _gst_vaapi_video_meta_create ();
  if (!copy)
    return NULL;

  copy->buffer = NULL;
  copy->ref_count = 1;
  copy->display = gst_vaapi_display_ref (meta->display);
  copy->image_pool = NULL;
  copy->image = meta->image ? gst_vaapi_object_ref (meta->image) : NULL;
  copy->proxy = meta->proxy ? gst_vaapi_surface_proxy_copy (meta->proxy) : NULL;
  copy->converter = meta->converter;
  copy->render_flags = meta->render_flags;

  copy->has_render_rect = meta->has_render_rect;
  if (copy->has_render_rect)
    copy->render_rect = meta->render_rect;
  return copy;
}
static gboolean
ensure_vpp (GstVaapiDecodeBin * vaapidecbin)
{
  GstVaapiDisplay *display;

  if (vaapidecbin->has_vpp != HAS_VPP_UNKNOWN)
    return TRUE;

  display = GST_VAAPI_PLUGIN_BASE_DISPLAY (vaapidecbin->decoder);
  if (display) {
    GST_INFO_OBJECT (vaapidecbin, "Got display from vaapidecode");
    gst_vaapi_display_ref (display);
  } else {
    GST_INFO_OBJECT (vaapidecbin, "Creating a dummy display to test for vpp");
    display = gst_vaapi_create_test_display ();
  }
  if (!display)
    return FALSE;

  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ?
    HAS_VPP_YES : HAS_VPP_NO;

  gst_vaapi_display_unref (display);

  return TRUE;
}
void
gst_vaapi_video_pool_init (GstVaapiVideoPool * pool, GstVaapiDisplay * display,
    GstVaapiVideoPoolObjectType object_type)
{
  pool->object_type = object_type;
  pool->display = gst_vaapi_display_ref (display);
  pool->used_objects = NULL;
  pool->used_count = 0;
  pool->capacity = 0;

  g_queue_init (&pool->free_objects);
  g_mutex_init (&pool->mutex);
}
/* Base encoder initialization (internal) */
static gboolean
gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
{
  GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);

  g_return_val_if_fail (display != NULL, FALSE);

#define CHECK_VTABLE_HOOK(FUNC) do {            \
    if (!klass->FUNC)                           \
      goto error_invalid_vtable;                \
  } while (0)

  CHECK_VTABLE_HOOK (init);
  CHECK_VTABLE_HOOK (finalize);
  CHECK_VTABLE_HOOK (get_default_properties);
  CHECK_VTABLE_HOOK (reconfigure);
  CHECK_VTABLE_HOOK (encode);
  CHECK_VTABLE_HOOK (reordering);
  CHECK_VTABLE_HOOK (flush);

#undef CHECK_VTABLE_HOOK

  encoder->display = gst_vaapi_display_ref (display);
  encoder->va_display = gst_vaapi_display_get_display (display);
  encoder->va_context = VA_INVALID_ID;

  gst_video_info_init (&encoder->video_info);

  g_mutex_init (&encoder->mutex);
  g_cond_init (&encoder->surface_free);
  g_cond_init (&encoder->codedbuf_free);

  encoder->codedbuf_queue = g_async_queue_new_full ((GDestroyNotify)
      gst_vaapi_coded_buffer_proxy_unref);
  if (!encoder->codedbuf_queue)
    return FALSE;

  if (!klass->init (encoder))
    return FALSE;
  if (!gst_vaapi_encoder_init_properties (encoder))
    return FALSE;
  return TRUE;

  /* ERRORS */
error_invalid_vtable:
  {
    GST_ERROR ("invalid subclass hook (internal error)");
    return FALSE;
  }
}
static void
gst_vaapi_video_buffer_pool_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstVaapiVideoBufferPoolPrivate *const priv =
      GST_VAAPI_VIDEO_BUFFER_POOL (object)->priv;

  switch (prop_id) {
    case PROP_DISPLAY:
      priv->display = gst_vaapi_display_ref (g_value_get_pointer (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
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;
}
Esempio n. 8
0
static gboolean
ensure_allowed_raw_caps (GstVaapiPluginBase * plugin)
{
  GArray *formats, *out_formats;
  GstVaapiSurface *surface;
  GstVaapiDisplay *display;
  guint i;
  GstCaps *out_caps;
  gboolean ret = FALSE;

  if (plugin->allowed_raw_caps)
    return TRUE;

  out_formats = formats = NULL;
  surface = NULL;

  display = gst_vaapi_display_ref (plugin->display);
  formats = gst_vaapi_display_get_image_formats (display);
  if (!formats)
    goto bail;

  out_formats =
      g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), formats->len);
  if (!out_formats)
    goto bail;

  surface =
      gst_vaapi_surface_new (display, GST_VAAPI_CHROMA_TYPE_YUV420, 64, 64);
  if (!surface)
    goto bail;

  for (i = 0; i < formats->len; i++) {
    const GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
    GstVaapiImage *image;

    if (format == GST_VIDEO_FORMAT_UNKNOWN)
      continue;
    image = gst_vaapi_image_new (display, format, 64, 64);
    if (!image)
      continue;
    if (gst_vaapi_surface_put_image (surface, image))
      g_array_append_val (out_formats, format);
    gst_vaapi_object_unref (image);
  }

  out_caps = gst_vaapi_video_format_new_template_caps_from_list (out_formats);
  if (!out_caps)
    goto bail;

  gst_caps_replace (&plugin->allowed_raw_caps, out_caps);
  gst_caps_unref (out_caps);
  ret = TRUE;

bail:
  if (formats)
    g_array_unref (formats);
  if (out_formats)
    g_array_unref (out_formats);
  if (surface)
    gst_vaapi_object_unref (surface);
  gst_vaapi_display_unref (display);

  return ret;
}
static GstVaapiDisplay *
gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object)
{
#if USE_GST_GL_HELPERS
  GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object);
  GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context);
  gpointer native_display =
      GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display));
  GstVaapiDisplay *display, *out_display;
  GstVaapiDisplayType display_type;

  switch (gst_gl_display_get_handle_type (gl_display)) {
#if USE_X11
    case GST_GL_DISPLAY_TYPE_X11:
      display_type = GST_VAAPI_DISPLAY_TYPE_X11;
      break;
#endif
#if USE_WAYLAND
    case GST_GL_DISPLAY_TYPE_WAYLAND:
      display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
      break;
#endif
    case GST_GL_DISPLAY_TYPE_ANY:{
      /* Derive from the active window */
      GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context);
      const gchar *const gl_window_type = g_getenv ("GST_GL_WINDOW");

      display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
      if (!gl_window)
        break;
      native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window));

      if (gl_window_type) {
#if USE_X11
        if (!display_type && g_strcmp0 (gl_window_type, "x11") == 0)
          display_type = GST_VAAPI_DISPLAY_TYPE_X11;
#endif
#if USE_WAYLAND
        if (!display_type && g_strcmp0 (gl_window_type, "wayland") == 0)
          display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
#endif
      } else {
#if USE_X11
        if (!display_type && GST_GL_HAVE_WINDOW_X11)
          display_type = GST_VAAPI_DISPLAY_TYPE_X11;
#endif
#if USE_WAYLAND
        if (!display_type && GST_GL_HAVE_WINDOW_WAYLAND)
          display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
#endif
      }
      break;
    }
    default:
      display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
      break;
  }
  if (!display_type)
    return NULL;

  display = gst_vaapi_create_display_from_handle (display_type, native_display);
  if (!display)
    return NULL;

  switch (gst_gl_context_get_gl_platform (gl_context)) {
#if USE_EGL
    case GST_GL_PLATFORM_EGL:{
      guint gles_version;

      switch (gst_gl_context_get_gl_api (gl_context)) {
        case GST_GL_API_GLES1:
          gles_version = 1;
          goto create_egl_display;
        case GST_GL_API_GLES2:
          gles_version = 2;
          goto create_egl_display;
        case GST_GL_API_OPENGL:
        case GST_GL_API_OPENGL3:
          gles_version = 0;
        create_egl_display:
          out_display = gst_vaapi_display_egl_new (display, gles_version);
          break;
        default:
          out_display = NULL;
          break;
      }
      if (!out_display)
        return NULL;
      gst_vaapi_display_egl_set_gl_context (GST_VAAPI_DISPLAY_EGL (out_display),
          GSIZE_TO_POINTER (gst_gl_context_get_gl_context (gl_context)));
      break;
    }
#endif
    default:
      out_display = gst_vaapi_display_ref (display);
      break;
  }
  gst_vaapi_display_unref (display);
  return out_display;
#endif
  GST_ERROR ("unsupported GStreamer version %s", GST_API_VERSION_S);
  return NULL;
}