Example #1
0
/**
 * gst_gl_context_new:
 * @display: a #GstGLDisplay
 *
 * Create a new #GstGLContext with the specified @display
 *
 * Returns: a new #GstGLContext
 *
 * Since: 1.4
 */
GstGLContext *
gst_gl_context_new (GstGLDisplay * display)
{
  GstGLContext *context = NULL;
  const gchar *user_choice;

  _init_debug ();

  user_choice = g_getenv ("GST_GL_PLATFORM");
  GST_INFO ("creating a context for display %" GST_PTR_FORMAT
      ", user choice:%s", display, user_choice);
#if GST_GL_HAVE_PLATFORM_CGL
  if (!context && (!user_choice || g_strstr_len (user_choice, 5, "cgl")))
    context = GST_GL_CONTEXT (gst_gl_context_cocoa_new ());
#endif
#if GST_GL_HAVE_PLATFORM_GLX
  if (!context && (!user_choice || g_strstr_len (user_choice, 3, "glx")))
    context = GST_GL_CONTEXT (gst_gl_context_glx_new ());
#endif
#if GST_GL_HAVE_PLATFORM_EGL
  if (!context && (!user_choice || g_strstr_len (user_choice, 7, "egl")))
    context = GST_GL_CONTEXT (gst_gl_context_egl_new ());
#endif
#if GST_GL_HAVE_PLATFORM_WGL
  if (!context && (!user_choice || g_strstr_len (user_choice, 3, "wgl"))) {
    context = GST_GL_CONTEXT (gst_gl_context_wgl_new ());
  }
#endif
#if GST_GL_HAVE_PLATFORM_EAGL
  if (!context && (!user_choice || g_strstr_len (user_choice, 5, "eagl")))
    context = GST_GL_CONTEXT (gst_gl_context_eagl_new ());
#endif

  if (!context) {
    /* subclass returned a NULL context */
    GST_WARNING ("Could not create context. user specified %s",
        user_choice ? user_choice : "(null)");

    return NULL;
  }

  context->priv->display = gst_object_ref (display);

  GST_DEBUG_OBJECT (context,
      "Done creating context for display %" GST_PTR_FORMAT " (user_choice:%s)",
      display, user_choice);

  return context;
}
/**
 * gst_vaapi_plugin_base_set_gl_context:
 * @plugin: a #GstVaapiPluginBase
 * @object: the new GL context from downstream
 *
 * Registers the new GL context. The change is effective at the next
 * call to gst_vaapi_plugin_base_ensure_display(), where the
 * underlying display object could be re-allocated to fit the GL
 * context needs
 */
void
gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
    GstObject * object)
{
#if USE_GST_GL_HELPERS
  GstGLContext *const gl_context = GST_GL_CONTEXT (object);
  GstVaapiDisplayType display_type;

  gst_object_replace (&plugin->gl_context, object);

  switch (gst_gl_context_get_gl_platform (gl_context)) {
#if USE_GLX
    case GST_GL_PLATFORM_GLX:
      display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
      break;
#endif
#if USE_EGL
    case GST_GL_PLATFORM_EGL:
      display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
      break;
#endif
    default:
      display_type = plugin->display_type;
      break;
  }
  gst_vaapi_plugin_base_set_display_type (plugin, display_type);
#endif
}
static void
gst_gl_context_gpu_process_finalize (GObject * object)
{
  GstGLContext *context = GST_GL_CONTEXT (object);

  if (context->window)
    GST_GL_WINDOW_GET_CLASS (context->window)->close (context->window);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
Example #4
0
static void
_gst_egl_image_free (GstMiniObject * object)
{
  GstEGLImage *image = GST_EGL_IMAGE (object);

  if (image->context) {
    gst_gl_context_thread_add (GST_GL_CONTEXT (image->context),
        (GstGLContextThreadFunc) _gst_egl_image_free_thread, image);
    gst_object_unref (image->context);
  }
}
Example #5
0
static void
gst_gl_context_finalize (GObject * object)
{
  GstGLContext *context = GST_GL_CONTEXT (object);

  if (context->window) {
    gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL);
    gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL);

    if (context->priv->alive) {
      g_mutex_lock (&context->priv->render_lock);
      GST_INFO_OBJECT (context, "send quit gl window loop");
      gst_gl_window_quit (context->window);
      while (context->priv->alive) {
        g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock);
      }
      g_mutex_unlock (&context->priv->render_lock);
    }

    gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL);

    if (context->priv->gl_thread) {
      gpointer ret = g_thread_join (context->priv->gl_thread);
      GST_INFO_OBJECT (context, "gl thread joined");
      if (ret != NULL)
        GST_ERROR_OBJECT (context, "gl thread returned a non-null pointer");
      context->priv->gl_thread = NULL;
    }

    gst_object_unref (context->window);
  }

  gst_object_unref (context->display);

  if (context->gl_vtable) {
    g_slice_free (GstGLFuncs, context->gl_vtable);
    context->gl_vtable = NULL;
  }

  g_mutex_clear (&context->priv->render_lock);

  g_cond_clear (&context->priv->destroy_cond);
  g_cond_clear (&context->priv->create_cond);

  g_free (context->priv->gl_exts);
  g_weak_ref_clear (&context->priv->other_context_ref);

  GST_DEBUG_OBJECT (context, "End of finalize");
  G_OBJECT_CLASS (gst_gl_context_parent_class)->finalize (object);
}
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);
  GstGLDisplayType gl_display_type;
  GstGLPlatform gl_platform;
  gpointer native_display;
  GstVaapiDisplay *display = NULL;
  GstVaapiDisplayType display_type;

  /* Get display type and the native hanler */
  gl_display_type = gst_gl_display_get_handle_type (gl_display);
  gl_platform = gst_gl_context_get_gl_platform (gl_context);
  display_type =
      gst_vaapi_get_display_type_from_gl (gl_display_type, gl_platform);

  native_display = GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display));

  if (display_type == GST_VAAPI_DISPLAY_TYPE_ANY) {
    /* derive type and native_display from the active window */
    GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context);
    if (gl_window)
      native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window));
    display_type = gst_vaapi_get_display_type_from_gl_env ();
  }

  if (gl_platform == GST_GL_PLATFORM_EGL) {
    display = gst_vaapi_create_display_from_egl (gl_display, gl_context,
        display_type, native_display);
  }

  /* Non-EGL and fallback */
  if (!display) {
    display =
        gst_vaapi_create_display_from_handle (display_type, native_display);
  }

  gst_object_unref (gl_display);

  return display;
#endif
  GST_ERROR ("No GstGL support");
  return NULL;
}
Example #7
0
static gboolean
_gl_mem_create (GstGLMemoryEGL * gl_mem, GError ** error)
{
    GstGLContext *context = gl_mem->mem.mem.context;
    GstGLContextEGL *ctx_egl = GST_GL_CONTEXT_EGL (context);
    const GstGLFuncs *gl = context->gl_vtable;
    GstGLBaseMemoryAllocatorClass *alloc_class;

    if (!gst_gl_context_check_feature (GST_GL_CONTEXT (context),
                                       "EGL_KHR_image_base")) {
        g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
                     "EGL_KHR_image_base is not supported");
        return FALSE;
    }

    alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_CLASS (parent_class);
    if (!alloc_class->create ((GstGLBaseMemory *) gl_mem, error))
        return FALSE;

    if (gl_mem->image == NULL) {
        EGLImageKHR image = ctx_egl->eglCreateImageKHR (ctx_egl->egl_display,
                            ctx_egl->egl_context, EGL_GL_TEXTURE_2D_KHR,
                            (EGLClientBuffer) (guintptr) gl_mem->mem.tex_id, NULL);

        GST_TRACE ("Generating EGLImage handle:%p from a texture:%u",
                   gl_mem->image, gl_mem->mem.tex_id);

        if (eglGetError () != EGL_SUCCESS) {
            g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
                         "Failed to create EGLImage");
            return FALSE;
        }

        gl_mem->image = gst_egl_image_new_wrapped (context, image, 0, 0,
                        NULL, (GstEGLImageDestroyNotify) _destroy_egl_image);
    } else {
        gl->ActiveTexture (GL_TEXTURE0 + gl_mem->mem.plane);
        gl->BindTexture (GL_TEXTURE_2D, gl_mem->mem.tex_id);
        gl->EGLImageTargetTexture2D (GL_TEXTURE_2D,
                                     gst_egl_image_get_image (GST_EGL_IMAGE (gl_mem->image)));
    }

    return TRUE;
}
GstGLContext *
gst_gl_context_gpu_process_new (GstGLDisplay * display,
    GstGLAPI gl_api, GstGLProcAddrFunc proc_addr)
{
  GstGLContext *context = NULL;
  GstGLContextGPUProcess *gpu_context = NULL;
  GstGLContextClass *context_class = NULL;
  GstGLWindow *window = NULL;
  GError *error = NULL;
  g_return_val_if_fail ((gst_gl_display_get_gl_api (display) & gl_api) !=
      GST_GL_API_NONE, NULL);

  gpu_context = g_object_new (GST_GL_TYPE_CONTEXT_GPU_PROCESS, NULL);
  gpu_context->priv->gl_api = gl_api;

  context = GST_GL_CONTEXT (gpu_context);

  context->display = display;
  gst_gl_display_add_context (display, context);

  context_class = GST_GL_CONTEXT_GET_CLASS (context);

  context_class->get_current_context = NULL;
  context_class->get_proc_address = GST_DEBUG_FUNCPTR (proc_addr);

  gst_gl_context_activate (context, TRUE);
  gst_gl_context_fill_info (context, &error);

  if (error) {
    GST_ERROR_OBJECT (context, "Failed to create gpu process context: %s",
        error->message);
    g_error_free (error);
    gst_object_unref (context);
    return NULL;
  }

  window = GST_GL_WINDOW (gst_gl_window_gpu_process_new (display));
  gst_gl_context_set_window (context, window);
  GST_GL_WINDOW_GET_CLASS (window)->open (window, NULL);
  gst_object_unref (window);

  return context;
}
static gboolean
gst_eglimage_to_gl_texture_upload_meta (GstVideoGLTextureUploadMeta *
    meta, guint texture_id[4])
{
  gint i = 0;
  gint n = 0;

  g_return_val_if_fail (meta != NULL, FALSE);
  g_return_val_if_fail (texture_id != NULL, FALSE);

  GST_DEBUG ("Uploading for meta with textures %i,%i,%i,%i", texture_id[0],
      texture_id[1], texture_id[2], texture_id[3]);

  n = gst_buffer_n_memory (meta->buffer);

  for (i = 0; i < n; i++) {
    GstMemory *mem = gst_buffer_peek_memory (meta->buffer, i);
    const GstGLFuncs *gl = NULL;

    if (!gst_is_egl_image_memory (mem)) {
      GST_WARNING ("memory %p does not hold an EGLImage", mem);
      return FALSE;
    }

    gl = GST_GL_CONTEXT (GST_EGL_IMAGE_MEMORY (mem)->context)->gl_vtable;

    gl->ActiveTexture (GL_TEXTURE0 + i);
    gl->BindTexture (GL_TEXTURE_2D, texture_id[i]);
    gl->EGLImageTargetTexture2D (GL_TEXTURE_2D,
        gst_egl_image_memory_get_image (mem));
  }

  if (GST_IS_GL_BUFFER_POOL (meta->buffer->pool))
    gst_gl_buffer_pool_replace_last_buffer (GST_GL_BUFFER_POOL (meta->
            buffer->pool), meta->buffer);


  return TRUE;
}
/**
 * gst_vaapi_plugin_base_set_gl_context:
 * @plugin: a #GstVaapiPluginBase
 * @object: the new GL context from downstream
 *
 * Registers the new GL context. The change is effective at the next
 * call to gst_vaapi_plugin_base_ensure_display(), where the
 * underlying display object could be re-allocated to fit the GL
 * context needs
 */
void
gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
    GstObject * object)
{
#if USE_GST_GL_HELPERS
  GstGLContext *const gl_context = GST_GL_CONTEXT (object);
  GstVaapiDisplayType display_type;

  if (plugin->gl_context == object)
    return;

  gst_object_replace (&plugin->gl_context, object);

  switch (gst_gl_context_get_gl_platform (gl_context)) {
#if USE_GLX
    case GST_GL_PLATFORM_GLX:
      display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
      break;
#endif
    case GST_GL_PLATFORM_EGL:
#if VA_CHECK_VERSION (0,36,0) && USE_GST_GL_HELPERS
      plugin->srcpad_can_dmabuf =
          (!(gst_gl_context_get_gl_api (gl_context) & GST_GL_API_GLES1)
          && gst_gl_context_check_feature (gl_context,
              "EGL_EXT_image_dma_buf_import"));
#endif
#if USE_EGL
      display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
      break;
#endif
    default:
      display_type = plugin->display_type;
      break;
  }
  GST_INFO_OBJECT (plugin, "GL context: %" GST_PTR_FORMAT, plugin->gl_context);
  gst_vaapi_plugin_base_set_display_type (plugin, display_type);
#endif
}
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;
}
gboolean
gst_egl_image_memory_setup_buffer (GstGLContext * ctx, GstVideoInfo * info,
    GstBuffer * buffer)
{
  gint i = 0;
  gint stride[3];
  gsize offset[3];
  GstMemory *mem[3] = { NULL, NULL, NULL };
  guint n_mem = 0;
  GstMemoryFlags flags = 0;
  EGLImageKHR image = EGL_NO_IMAGE_KHR;
  EGLClientBuffer client_buffer_tex[3] = { 0, 0, 0 };
  GstVideoGLTextureType texture_types[] = { 0, 0, 0, 0 };
  GstEGLImageAllocator *allocator = gst_egl_image_allocator_obtain ();
  GstGLContextEGL *context = GST_GL_CONTEXT_EGL (ctx);

  g_return_val_if_fail (ctx, FALSE);
  g_return_val_if_fail (info, FALSE);
  g_return_val_if_fail (buffer, FALSE);
  g_return_val_if_fail (gst_gl_context_check_feature (ctx,
          "EGL_KHR_image_base"), FALSE);

  memset (stride, 0, sizeof (stride));
  memset (offset, 0, sizeof (offset));

  flags |= GST_MEMORY_FLAG_NOT_MAPPABLE;
  flags |= GST_MEMORY_FLAG_NO_SHARE;

  switch (GST_VIDEO_INFO_FORMAT (info)) {
    case GST_VIDEO_FORMAT_RGB:
    case GST_VIDEO_FORMAT_BGR:
    case GST_VIDEO_FORMAT_RGB16:
    case GST_VIDEO_FORMAT_RGBA:
    case GST_VIDEO_FORMAT_BGRA:
    case GST_VIDEO_FORMAT_ARGB:
    case GST_VIDEO_FORMAT_ABGR:
    case GST_VIDEO_FORMAT_RGBx:
    case GST_VIDEO_FORMAT_BGRx:
    case GST_VIDEO_FORMAT_xRGB:
    case GST_VIDEO_FORMAT_xBGR:
    case GST_VIDEO_FORMAT_AYUV:
    {
      gsize size = 0;

      switch (GST_VIDEO_INFO_FORMAT (info)) {
        case GST_VIDEO_FORMAT_RGB:
        case GST_VIDEO_FORMAT_BGR:
        case GST_VIDEO_FORMAT_RGB16:
        {
          texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGB;
          break;
        }
        case GST_VIDEO_FORMAT_RGBA:
        case GST_VIDEO_FORMAT_BGRA:
        case GST_VIDEO_FORMAT_ARGB:
        case GST_VIDEO_FORMAT_ABGR:
        case GST_VIDEO_FORMAT_RGBx:
        case GST_VIDEO_FORMAT_BGRx:
        case GST_VIDEO_FORMAT_xRGB:
        case GST_VIDEO_FORMAT_xBGR:
        case GST_VIDEO_FORMAT_AYUV:
        {
          texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
          break;
        }
        default:
          g_assert_not_reached ();
          break;
      }
#if 0
      mem[0] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[0], GST_VIDEO_INFO_WIDTH (info),
          GST_VIDEO_INFO_HEIGHT (info), size);
      if (mem[0]) {
        stride[0] = size / GST_VIDEO_INFO_HEIGHT (info);
        n_mem = 1;
        GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
      } else
#endif
      {
        gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, 0, stride,
            offset, &size, (GLuint *) & client_buffer_tex[0]);

        image = context->eglCreateImage (context->egl_display,
            context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[0],
            NULL);
        if (eglGetError () != EGL_SUCCESS)
          goto mem_error;

        mem[0] =
            gst_egl_image_allocator_wrap (allocator, context,
            image, texture_types[0], flags, size, client_buffer_tex[0],
            (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture);
        n_mem = 1;
      }
      break;
    }

    case GST_VIDEO_FORMAT_NV12:
    case GST_VIDEO_FORMAT_NV21:
    {
      gsize size[2];

      texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
      texture_types[1] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA;
#if 0
      mem[0] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[0], GST_VIDEO_INFO_COMP_WIDTH (info,
              0), GST_VIDEO_INFO_COMP_HEIGHT (info, 0), size[0]);
      mem[1] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[1],
          GST_VIDEO_INFO_COMP_WIDTH (info, 1),
          GST_VIDEO_INFO_COMP_HEIGHT (info, 1), size[1]);

      if (mem[0] && mem[1]) {
        stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (info);
        offset[1] = size[0];
        stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (info);
        n_mem = 2;
        GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
        GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE);
      } else {
        if (mem[0])
          gst_memory_unref (mem[0]);
        if (mem[1])
          gst_memory_unref (mem[1]);
        mem[0] = mem[1] = NULL;
      }
#endif
      {
        for (i = 0; i < 2; i++) {
          gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, 0,
              stride, offset, size, (GLuint *) & client_buffer_tex[i]);

          image = context->eglCreateImage (context->egl_display,
              context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[i],
              NULL);
          if (eglGetError () != EGL_SUCCESS)
            goto mem_error;

          mem[i] =
              gst_egl_image_allocator_wrap (allocator, context,
              image, texture_types[i], flags, size[i], client_buffer_tex[i],
              (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture);
        }

        n_mem = 2;
      }
      break;
    }
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_YV12:
    case GST_VIDEO_FORMAT_Y444:
    case GST_VIDEO_FORMAT_Y42B:
    case GST_VIDEO_FORMAT_Y41B:
    {
      gsize size[3];

      texture_types[0] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
      texture_types[1] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
      texture_types[2] = GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
#if 0
      mem[0] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[0], GST_VIDEO_INFO_COMP_WIDTH (info,
              0), GST_VIDEO_INFO_COMP_HEIGHT (info, 0), size[0]);
      mem[1] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[1], GST_VIDEO_INFO_COMP_WIDTH (info,
              1), GST_VIDEO_INFO_COMP_HEIGHT (info, 1), size[1]);
      mem[2] =
          gst_egl_image_allocator_alloc (allocator, context,
          texture_types[2], GST_VIDEO_INFO_COMP_WIDTH (info,
              2), GST_VIDEO_INFO_COMP_HEIGHT (info, 2), size[2]);

      if (mem[0] && mem[1] && mem[2]) {
        stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (info);
        offset[1] = size[0];
        stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (info);
        offset[2] = size[1];
        stride[2] = size[2] / GST_VIDEO_INFO_HEIGHT (info);
        n_mem = 3;
        GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE);
        GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE);
        GST_MINI_OBJECT_FLAG_SET (mem[2], GST_MEMORY_FLAG_NO_SHARE);
      } else {
        if (mem[0])
          gst_memory_unref (mem[0]);
        if (mem[1])
          gst_memory_unref (mem[1]);
        if (mem[2])
          gst_memory_unref (mem[2]);
        mem[0] = mem[1] = mem[2] = NULL;
      }
#endif
      {
        for (i = 0; i < 3; i++) {
          gst_gl_generate_texture_full (GST_GL_CONTEXT (context), info, i,
              stride, offset, size, (GLuint *) & client_buffer_tex[i]);

          image = context->eglCreateImage (context->egl_display,
              context->egl_context, EGL_GL_TEXTURE_2D_KHR, client_buffer_tex[i],
              NULL);
          if (eglGetError () != EGL_SUCCESS)
            goto mem_error;

          mem[i] =
              gst_egl_image_allocator_wrap (allocator, context,
              image, texture_types[i], flags, size[i], client_buffer_tex[i],
              (GstEGLImageDestroyNotify) gst_egl_image_memory_del_gl_texture);
        }

        n_mem = 3;
      }
      break;
    }
    default:
      g_assert_not_reached ();
      break;
  }

  gst_buffer_add_video_meta_full (buffer, 0, GST_VIDEO_INFO_FORMAT (info),
      GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info),
      GST_VIDEO_INFO_N_PLANES (info), offset, stride);

  gst_buffer_add_video_gl_texture_upload_meta (buffer,
      gst_egl_image_memory_get_orientation (mem[0]), n_mem, texture_types,
      gst_eglimage_to_gl_texture_upload_meta, NULL, NULL, NULL);

  for (i = 0; i < n_mem; i++)
    gst_buffer_append_memory (buffer, mem[i]);

  return TRUE;

mem_error:
  {
    GST_CAT_ERROR (GST_CAT_DEFAULT, "Failed to create EGLImage");

    for (i = 0; i < 3; i++) {
      if (client_buffer_tex[i])
        gst_gl_context_del_texture (ctx, (GLuint *) & client_buffer_tex[i]);
      if (mem[i])
        gst_memory_unref (mem[i]);
    }

    return FALSE;
  }
}