gboolean _gst_vaapi_surface_deassociate_subpicture (GstVaapiSurface * surface, GstVaapiSubpicture * subpicture) { GstVaapiDisplay *display; VASurfaceID surface_id; VAStatus status; display = GST_VAAPI_OBJECT_DISPLAY (surface); if (!display) return FALSE; surface_id = GST_VAAPI_OBJECT_ID (surface); if (surface_id == VA_INVALID_SURFACE) return FALSE; GST_VAAPI_DISPLAY_LOCK (display); status = vaDeassociateSubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (subpicture), &surface_id, 1); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaDeassociateSubpicture()")) return FALSE; return TRUE; }
static gboolean gst_vaapi_surface_create (GstVaapiSurface * surface, GstVaapiChromaType chroma_type, guint width, guint height) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface); VASurfaceID surface_id; VAStatus status; guint va_chroma_format; va_chroma_format = from_GstVaapiChromaType (chroma_type); if (!va_chroma_format) goto error_unsupported_chroma_type; GST_VAAPI_DISPLAY_LOCK (display); status = vaCreateSurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display), width, height, va_chroma_format, 1, &surface_id); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaCreateSurfaces()")) return FALSE; surface->format = GST_VIDEO_FORMAT_UNKNOWN; surface->chroma_type = chroma_type; surface->width = width; surface->height = height; GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)); GST_VAAPI_OBJECT_ID (surface) = surface_id; return TRUE; /* ERRORS */ error_unsupported_chroma_type: GST_ERROR ("unsupported chroma-type %u", chroma_type); return FALSE; }
static void gst_vaapi_subpicture_destroy (GstVaapiSubpicture * subpicture) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (subpicture); VASubpictureID subpicture_id; VAStatus status; subpicture_id = GST_VAAPI_OBJECT_ID (subpicture); GST_DEBUG ("subpicture %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (subpicture_id)); if (subpicture_id != VA_INVALID_ID) { if (display) { GST_VAAPI_DISPLAY_LOCK (display); status = vaDestroySubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display), subpicture_id); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaDestroySubpicture()")) g_warning ("failed to destroy subpicture %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (subpicture_id)); } GST_VAAPI_OBJECT_ID (subpicture) = VA_INVALID_ID; } gst_vaapi_object_replace (&subpicture->image, NULL); }
/** * gst_vaapi_surface_derive_image: * @surface: a #GstVaapiSurface * * Derives a #GstVaapiImage from the @surface. This image buffer can * then be mapped/unmapped for direct CPU access. This operation is * only possible if the underlying implementation supports direct * rendering capabilities and internal surface formats that can be * represented with a #GstVaapiImage. * * When the operation is not possible, the function returns %NULL and * the user should then fallback to using gst_vaapi_surface_get_image() * or gst_vaapi_surface_put_image() to accomplish the same task in an * indirect manner (additional copy). * * An image created with gst_vaapi_surface_derive_image() should be * unreferenced when it's no longer needed. The image and image buffer * data structures will be destroyed. However, the surface contents * will remain unchanged until destroyed through the last call to * gst_vaapi_object_unref(). * * Return value: the newly allocated #GstVaapiImage object, or %NULL * on failure */ GstVaapiImage * gst_vaapi_surface_derive_image (GstVaapiSurface * surface) { GstVaapiDisplay *display; VAImage va_image; VAStatus status; GstVaapiImage *image; g_return_val_if_fail (surface != NULL, NULL); display = GST_VAAPI_OBJECT_DISPLAY (surface); va_image.image_id = VA_INVALID_ID; va_image.buf = VA_INVALID_ID; GST_VAAPI_DISPLAY_LOCK (display); status = vaDeriveImage (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (surface), &va_image); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaDeriveImage()")) return NULL; if (va_image.image_id == VA_INVALID_ID || va_image.buf == VA_INVALID_ID) return NULL; image = gst_vaapi_image_new_with_image (display, &va_image); if (!image) vaDestroyImage (GST_VAAPI_DISPLAY_VADISPLAY (display), va_image.image_id); return image; }
gboolean _gst_vaapi_image_unmap(GstVaapiImage *image) { GstVaapiDisplay *display; VAStatus status; if (!_gst_vaapi_image_is_mapped(image)) return FALSE; display = GST_VAAPI_OBJECT_DISPLAY(image); if (!display) return FALSE; GST_VAAPI_DISPLAY_LOCK(display); status = vaUnmapBuffer( GST_VAAPI_DISPLAY_VADISPLAY(display), image->priv->image.buf ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaUnmapBuffer()")) return FALSE; image->priv->image_data = NULL; return TRUE; }
/** * gst_vaapi_subpicture_set_global_alpha: * @subpicture: a #GstVaapiSubpicture * @global_alpha: value for global-alpha (range: 0.0 to 1.0, inclusive) * * Sets the global_alpha value of @subpicture. This function calls * vaSetSubpictureGlobalAlpha() if the format of @subpicture, i.e. * the current VA driver supports it. * * Return value: %TRUE if global_alpha could be set, %FALSE otherwise */ gboolean gst_vaapi_subpicture_set_global_alpha (GstVaapiSubpicture * subpicture, gfloat global_alpha) { GstVaapiDisplay *display; VAStatus status; g_return_val_if_fail (subpicture != NULL, FALSE); if (!(subpicture->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA)) return FALSE; if (subpicture->global_alpha == global_alpha) return TRUE; display = GST_VAAPI_OBJECT_DISPLAY (subpicture); GST_VAAPI_DISPLAY_LOCK (display); status = vaSetSubpictureGlobalAlpha (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (subpicture), global_alpha); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaSetSubpictureGlobalAlpha()")) return FALSE; subpicture->global_alpha = global_alpha; return TRUE; }
/** * gst_vaapi_surface_put_image: * @surface: a #GstVaapiSurface * @image: a #GstVaapiImage * * Copies data from a #GstVaapiImage into a @surface. The @image must * have a format supported by the @surface. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_put_image (GstVaapiSurface * surface, GstVaapiImage * image) { GstVaapiDisplay *display; VAImageID image_id; VAStatus status; guint width, height; g_return_val_if_fail (surface != NULL, FALSE); g_return_val_if_fail (image != NULL, FALSE); display = GST_VAAPI_OBJECT_DISPLAY (surface); if (!display) return FALSE; width = GST_VAAPI_IMAGE_WIDTH (image); height = GST_VAAPI_IMAGE_HEIGHT (image); if (width != surface->width || height != surface->height) return FALSE; image_id = GST_VAAPI_OBJECT_ID (image); if (image_id == VA_INVALID_ID) return FALSE; GST_VAAPI_DISPLAY_LOCK (display); status = vaPutImage (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (surface), image_id, 0, 0, width, height, 0, 0, width, height); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaPutImage()")) return FALSE; return TRUE; }
static gboolean _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format) { GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image); GstVaapiImagePrivate * const priv = image->priv; const VAImageFormat *va_format; VAStatus status; if (!gst_vaapi_display_has_image_format(display, format)) return FALSE; va_format = gst_vaapi_image_format_get_va_format(format); if (!va_format) return FALSE; GST_VAAPI_DISPLAY_LOCK(display); status = vaCreateImage( GST_VAAPI_DISPLAY_VADISPLAY(display), (VAImageFormat *)va_format, priv->width, priv->height, &priv->internal_image ); GST_VAAPI_DISPLAY_UNLOCK(display); if (status != VA_STATUS_SUCCESS || priv->internal_image.format.fourcc != va_format->fourcc) return FALSE; priv->internal_format = format; return TRUE; }
static void gst_vaapi_surface_destroy (GstVaapiSurface * surface) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface); VASurfaceID surface_id; VAStatus status; surface_id = GST_VAAPI_OBJECT_ID (surface); GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)); gst_vaapi_surface_destroy_subpictures (surface); gst_vaapi_surface_set_parent_context (surface, NULL); if (surface_id != VA_INVALID_SURFACE) { GST_VAAPI_DISPLAY_LOCK (display); status = vaDestroySurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display), &surface_id, 1); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaDestroySurfaces()")) g_warning ("failed to destroy surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)); GST_VAAPI_OBJECT_ID (surface) = VA_INVALID_SURFACE; } gst_vaapi_buffer_proxy_replace (&surface->extbuf_proxy, NULL); }
gboolean _gst_vaapi_surface_associate_subpicture( GstVaapiSurface *surface, GstVaapiSubpicture *subpicture, const GstVaapiRectangle *src_rect, const GstVaapiRectangle *dst_rect ) { GstVaapiDisplay *display; GstVaapiRectangle src_rect_default, dst_rect_default; GstVaapiImage *image; VASurfaceID surface_id; VAStatus status; display = GST_VAAPI_OBJECT_DISPLAY(surface); if (!display) return FALSE; surface_id = GST_VAAPI_OBJECT_ID(surface); if (surface_id == VA_INVALID_SURFACE) return FALSE; if (!src_rect) { image = gst_vaapi_subpicture_get_image(subpicture); if (!image) return FALSE; src_rect = &src_rect_default; src_rect_default.x = 0; src_rect_default.y = 0; gst_vaapi_image_get_size( image, &src_rect_default.width, &src_rect_default.height ); } if (!dst_rect) { dst_rect = &dst_rect_default; dst_rect_default.x = 0; dst_rect_default.y = 0; dst_rect_default.width = surface->priv->width; dst_rect_default.height = surface->priv->height; } GST_VAAPI_DISPLAY_LOCK(display); status = vaAssociateSubpicture( GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_OBJECT_ID(subpicture), &surface_id, 1, src_rect->x, src_rect->y, src_rect->width, src_rect->height, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height, 0 ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaAssociateSubpicture()")) return FALSE; return TRUE; }
static void gst_vaapi_display_x11_flush (GstVaapiDisplay * display) { GstVaapiDisplayX11Private *const priv = GST_VAAPI_DISPLAY_X11_PRIVATE (display); if (priv->x11_display) { GST_VAAPI_DISPLAY_LOCK (display); XFlush (priv->x11_display); GST_VAAPI_DISPLAY_UNLOCK (display); } }
static void gst_vaapi_display_x11_sync(GstVaapiDisplay *display) { GstVaapiDisplayX11Private * const priv = GST_VAAPI_DISPLAY_X11(display)->priv; if (priv->x11_display) { GST_VAAPI_DISPLAY_LOCK(display); XSync(priv->x11_display, False); GST_VAAPI_DISPLAY_UNLOCK(display); } }
/* Set synchronous behavious on the underlying X11 display */ static void set_synchronous (GstVaapiDisplayX11 * display, gboolean synchronous) { GstVaapiDisplayX11Private *const priv = display->priv; if (priv->synchronous != synchronous) { priv->synchronous = synchronous; if (priv->x11_display) { GST_VAAPI_DISPLAY_LOCK (display); XSynchronize (priv->x11_display, synchronous); GST_VAAPI_DISPLAY_UNLOCK (display); } } }
static void coded_buffer_destroy (GstVaapiCodedBuffer * buf) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf); VABufferID buf_id; buf_id = GST_VAAPI_OBJECT_ID (buf); GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id)); if (buf_id != VA_INVALID_ID) { GST_VAAPI_DISPLAY_LOCK (display); vaapi_destroy_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), &buf_id); GST_VAAPI_DISPLAY_UNLOCK (display); GST_VAAPI_OBJECT_ID (buf) = VA_INVALID_ID; } }
/** * gst_vaapi_texture_glx_new_wrapped: * @display: a #GstVaapiDisplay * @texture_id: the foreign GL texture name to use * @target: the target to which the texture is bound * @format: the format of the pixel data * * Creates a texture from an existing GL texture, with the specified * @target and @format. Note that only GL_TEXTURE_2D @target and * GL_RGBA or GL_BGRA formats are supported at this time. The * dimensions will be retrieved from the @texture_id. * * The application shall maintain the live GL context itself. That is, * gst_vaapi_window_glx_make_current() must be called beforehand, or * any other function like glXMakeCurrent() if the context is managed * outside of this library. * * Return value: the newly created #GstVaapiTexture object */ GstVaapiTexture * gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display, guint texture_id, guint target, guint format) { guint width, height, border_width = 0; GLTextureState ts = { 0, }; gboolean success; GstVaapiGLApi gl_api; g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); g_return_val_if_fail (texture_id != GL_NONE, NULL); g_return_val_if_fail (target == GL_TEXTURE_2D, NULL); g_return_val_if_fail (format == GL_RGBA || format == GL_BGRA, NULL); gl_api = gl_get_curent_api_once (); if (gl_api != GST_VAAPI_GL_API_OPENGL && gl_api != GST_VAAPI_GL_API_OPENGL3) return NULL; /* Check texture dimensions */ GST_VAAPI_DISPLAY_LOCK (display); if (gl_api == GST_VAAPI_GL_API_OPENGL) success = gl_bind_texture (&ts, target, texture_id); else success = gl3_bind_texture_2d (&ts, target, texture_id); if (success) { if (!gl_get_texture_param (target, GL_TEXTURE_WIDTH, &width) || !gl_get_texture_param (target, GL_TEXTURE_HEIGHT, &height)) success = FALSE; if (success && gl_api == GST_VAAPI_GL_API_OPENGL) success = gl_get_texture_param (target, GL_TEXTURE_BORDER, &border_width); gl_unbind_texture (&ts); } GST_VAAPI_DISPLAY_UNLOCK (display); if (!success) return NULL; width -= 2 * border_width; height -= 2 * border_width; g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (height > 0, NULL); return gst_vaapi_texture_new_internal (GST_VAAPI_TEXTURE_CLASS (gst_vaapi_texture_glx_class ()), display, texture_id, target, format, width, height); }
static gboolean coded_buffer_create (GstVaapiCodedBuffer * buf, guint buf_size, GstVaapiContext * context) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf); VABufferID buf_id; gboolean success; GST_VAAPI_DISPLAY_LOCK (display); success = vaapi_create_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (context), VAEncCodedBufferType, buf_size, NULL, &buf_id, NULL); GST_VAAPI_DISPLAY_UNLOCK (display); if (!success) return FALSE; GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id)); GST_VAAPI_OBJECT_ID (buf) = buf_id; return TRUE; }
gboolean _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image) { GstVaapiImagePrivate * const priv = image->priv; GstVaapiDisplay *display; void *image_data; VAStatus status; guint i; if (_gst_vaapi_image_is_mapped(image)) return TRUE; display = GST_VAAPI_OBJECT_DISPLAY(image); if (!display) return FALSE; GST_VAAPI_DISPLAY_LOCK(display); status = vaMapBuffer( GST_VAAPI_DISPLAY_VADISPLAY(display), image->priv->image.buf, &image_data ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaMapBuffer()")) return FALSE; image->priv->image_data = image_data; if (raw_image) { const VAImage * const va_image = &priv->image; raw_image->format = priv->format; raw_image->width = va_image->width; raw_image->height = va_image->height; raw_image->num_planes = va_image->num_planes; for (i = 0; i < raw_image->num_planes; i++) { raw_image->pixels[i] = (guchar *)image_data + va_image->offsets[i]; raw_image->stride[i] = va_image->pitches[i]; } } return TRUE; }
static gboolean gst_vaapi_subpicture_create (GstVaapiSubpicture * subpicture, GstVaapiImage * image) { GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (subpicture); VASubpictureID subpicture_id; VAStatus status; GST_VAAPI_DISPLAY_LOCK (display); status = vaCreateSubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (image), &subpicture_id); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaCreateSubpicture()")) return FALSE; GST_DEBUG ("subpicture %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (subpicture_id)); GST_VAAPI_OBJECT_ID (subpicture) = subpicture_id; subpicture->image = gst_vaapi_object_ref (image); return TRUE; }
/** * gst_vaapi_surface_sync: * @surface: a #GstVaapiSurface * * Blocks until all pending operations on the @surface have been * completed. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_sync (GstVaapiSurface * surface) { GstVaapiDisplay *display; VAStatus status; g_return_val_if_fail (surface != NULL, FALSE); display = GST_VAAPI_OBJECT_DISPLAY (surface); if (!display) return FALSE; GST_VAAPI_DISPLAY_LOCK (display); status = vaSyncSurface (GST_VAAPI_DISPLAY_VADISPLAY (display), GST_VAAPI_OBJECT_ID (surface)); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaSyncSurface()")) return FALSE; return TRUE; }
static gboolean gst_vaapi_surface_create(GstVaapiSurface *surface) { GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface); GstVaapiSurfacePrivate * const priv = surface->priv; VASurfaceID surface_id; VAStatus status; guint format; switch (priv->chroma_type) { case GST_VAAPI_CHROMA_TYPE_YUV420: format = VA_RT_FORMAT_YUV420; break; case GST_VAAPI_CHROMA_TYPE_YUV422: format = VA_RT_FORMAT_YUV422; break; case GST_VAAPI_CHROMA_TYPE_YUV444: format = VA_RT_FORMAT_YUV444; break; default: GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type); return FALSE; } GST_VAAPI_DISPLAY_LOCK(display); status = vaCreateSurfaces( GST_VAAPI_DISPLAY_VADISPLAY(display), priv->width, priv->height, format, 1, &surface_id ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaCreateSurfaces()")) return FALSE; GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id)); GST_VAAPI_OBJECT_ID(surface) = surface_id; return TRUE; }
static void gst_vaapi_image_destroy(GstVaapiImage *image) { GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image); VAImageID image_id; VAStatus status; _gst_vaapi_image_unmap(image); image_id = GST_VAAPI_OBJECT_ID(image); GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id)); if (image_id != VA_INVALID_ID) { GST_VAAPI_DISPLAY_LOCK(display); status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaDestroyImage()")) g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id)); GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID; } }
static gboolean ensure_pix_fmts (GstVaapiDisplayX11 * display) { GstVaapiDisplayX11Private *const priv = GST_VAAPI_DISPLAY_X11_PRIVATE (display); XPixmapFormatValues *pix_fmts; int i, n, num_pix_fmts; if (priv->pixmap_formats) return TRUE; GST_VAAPI_DISPLAY_LOCK (display); pix_fmts = XListPixmapFormats (GST_VAAPI_DISPLAY_XDISPLAY (display), &num_pix_fmts); GST_VAAPI_DISPLAY_UNLOCK (display); if (!pix_fmts) return FALSE; priv->pixmap_formats = g_array_sized_new (FALSE, FALSE, sizeof (GstVaapiPixmapFormatX11), num_pix_fmts); if (!priv->pixmap_formats) { XFree (pix_fmts); return FALSE; } for (i = 0, n = 0; i < num_pix_fmts; i++) { GstVaapiPixmapFormatX11 *const pix_fmt = &g_array_index (priv->pixmap_formats, GstVaapiPixmapFormatX11, n); pix_fmt->depth = pix_fmts[i].depth; pix_fmt->bpp = pix_fmts[i].bits_per_pixel; pix_fmt->format = pix_fmt_to_video_format (pix_fmt->depth, pix_fmt->bpp); if (pix_fmt->format != GST_VIDEO_FORMAT_UNKNOWN) n++; } priv->pixmap_formats->len = n; return TRUE; }
/** * gst_vaapi_get_config_attribute: * @display: a #GstVaapiDisplay * @profile: a VA profile * @entrypoint: a VA entrypoint * @type: a VA config attribute type * @out_value_ptr: return location for the config attribute value * * Determines the value for the VA config attribute @type and the * given @profile/@entrypoint pair. If @out_value_ptr is %NULL, then * this functions acts as a way to query whether the underlying VA * driver supports the specified attribute @type, no matter the * returned value. * * Note: this function only returns success if the VA driver does * actually know about this config attribute type and that it returned * a valid value for it. * * Return value: %TRUE if the VA driver knows about the requested * config attribute and returned a valid value, %FALSE otherwise */ gboolean gst_vaapi_get_config_attribute (GstVaapiDisplay * display, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttribType type, guint * out_value_ptr) { VAConfigAttrib attrib; VAStatus status; g_return_val_if_fail (display != NULL, FALSE); GST_VAAPI_DISPLAY_LOCK (display); attrib.type = type; status = vaGetConfigAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display), profile, entrypoint, &attrib, 1); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaGetConfigAttributes()")) return FALSE; if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) return FALSE; if (out_value_ptr) *out_value_ptr = attrib.value; return TRUE; }
static GstVaapiDecoderStatus decode_frame(GstVaapiDecoderFfmpeg *ffdecoder, guchar *buf, guint buf_size) { GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv; GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(ffdecoder); GstVaapiSurface *surface; int bytes_read, got_picture = 0; AVPacket avpkt; GST_VAAPI_DISPLAY_LOCK(display); av_init_packet(&avpkt); avpkt.data = buf; avpkt.size = buf_size; bytes_read = avcodec_decode_video2( priv->avctx, priv->frame, &got_picture, &avpkt ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!got_picture) return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA; if (bytes_read < 0) return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; surface = gst_vaapi_context_find_surface_by_id( GST_VAAPI_DECODER_CONTEXT(ffdecoder), GPOINTER_TO_UINT(priv->frame->data[3]) ); if (!surface) return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE; if (!gst_vaapi_decoder_push_surface(GST_VAAPI_DECODER_CAST(ffdecoder), surface, priv->frame->pts)) return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; return GST_VAAPI_DECODER_STATUS_SUCCESS; }
/** * gst_vaapi_surface_get_image * @surface: a #GstVaapiSurface * @image: a #GstVaapiImage * * Retrieves surface data into a #GstVaapiImage. The @image must have * a format supported by the @surface. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image) { GstVaapiDisplay *display; VAImageID image_id; VAStatus status; guint width, height; g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE); g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); display = GST_VAAPI_OBJECT_DISPLAY(surface); if (!display) return FALSE; gst_vaapi_image_get_size(image, &width, &height); if (width != surface->priv->width || height != surface->priv->height) return FALSE; image_id = GST_VAAPI_OBJECT_ID(image); if (image_id == VA_INVALID_ID) return FALSE; GST_VAAPI_DISPLAY_LOCK(display); status = vaGetImage( GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_OBJECT_ID(surface), 0, 0, width, height, image_id ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaGetImage()")) return FALSE; return TRUE; }
static gboolean gst_vaapi_decoder_ffmpeg_open(GstVaapiDecoderFfmpeg *ffdecoder, GstBuffer *buffer) { GstVaapiDecoderFfmpegPrivate * const priv = ffdecoder->priv; GstVaapiDisplay * const display = GST_VAAPI_DECODER_DISPLAY(ffdecoder); GstBuffer * const codec_data = GST_VAAPI_DECODER_CODEC_DATA(ffdecoder); GstVaapiCodec codec = GST_VAAPI_DECODER_CODEC(ffdecoder); enum CodecID codec_id; AVCodec *ffcodec; gboolean try_parser, need_parser; int ret; gst_vaapi_decoder_ffmpeg_close(ffdecoder); if (codec_data) { const guchar *data = GST_BUFFER_DATA(codec_data); const guint size = GST_BUFFER_SIZE(codec_data); if (!set_codec_data(priv->avctx, data, size)) return FALSE; } codec_id = get_codec_id_from_codec(codec); if (codec_id == CODEC_ID_NONE) return FALSE; ffcodec = avcodec_find_decoder(codec_id); if (!ffcodec) return FALSE; switch (codec_id) { case CODEC_ID_H264: /* For AVC1 formats, sequence headers are in extradata and input encoded buffers represent the whole NAL unit */ try_parser = priv->avctx->extradata_size == 0; need_parser = try_parser; break; case CODEC_ID_WMV3: /* There is no WMV3 parser in FFmpeg */ try_parser = FALSE; need_parser = FALSE; break; case CODEC_ID_VC1: /* For VC-1, sequence headers ae in extradata and input encoded buffers represent the whole slice */ try_parser = priv->avctx->extradata_size == 0; need_parser = FALSE; break; default: try_parser = TRUE; need_parser = TRUE; break; } if (try_parser) { priv->pctx = av_parser_init(codec_id); if (!priv->pctx && need_parser) return FALSE; } /* XXX: av_find_stream_info() does this and some codecs really want hard an extradata buffer for initialization (e.g. VC-1) */ if (!priv->avctx->extradata && priv->pctx && priv->pctx->parser->split) { const guchar *buf = GST_BUFFER_DATA(buffer); guint buf_size = GST_BUFFER_SIZE(buffer); buf_size = priv->pctx->parser->split(priv->avctx, buf, buf_size); if (buf_size > 0 && !set_codec_data(priv->avctx, buf, buf_size)) return FALSE; } if (priv->pctx && !need_parser) { av_parser_close(priv->pctx); priv->pctx = NULL; } /* Use size information from the demuxer, whenever available */ priv->avctx->coded_width = GST_VAAPI_DECODER_WIDTH(ffdecoder); priv->avctx->coded_height = GST_VAAPI_DECODER_HEIGHT(ffdecoder); GST_VAAPI_DISPLAY_LOCK(display); ret = avcodec_open(priv->avctx, ffcodec); GST_VAAPI_DISPLAY_UNLOCK(display); if (ret < 0) return FALSE; return TRUE; }
/** * gst_vaapi_get_surface_formats: * @display: a #GstVaapiDisplay * @config: a #VAConfigID * * Gets surface formats for the supplied config. * * This function will query for all the supported formats for the * supplied VA @config. * * Return value: (transfer full): a #GArray of #GstVideoFormats or %NULL */ GArray * gst_vaapi_get_surface_formats (GstVaapiDisplay * display, VAConfigID config) { VASurfaceAttrib *surface_attribs = NULL; guint i, num_surface_attribs = 0; VAStatus va_status; GArray *formats; if (config == VA_INVALID_ID) return NULL; GST_VAAPI_DISPLAY_LOCK (display); va_status = vaQuerySurfaceAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display), config, NULL, &num_surface_attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (va_status, "vaQuerySurfaceAttributes()")) return NULL; surface_attribs = g_malloc (num_surface_attribs * sizeof (*surface_attribs)); if (!surface_attribs) return NULL; GST_VAAPI_DISPLAY_LOCK (display); va_status = vaQuerySurfaceAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display), config, surface_attribs, &num_surface_attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (va_status, "vaQuerySurfaceAttributes()")) return NULL; formats = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), num_surface_attribs); if (!formats) goto error; for (i = 0; i < num_surface_attribs; i++) { const VASurfaceAttrib *const attrib = &surface_attribs[i]; GstVideoFormat fmt; if (attrib->type != VASurfaceAttribPixelFormat) continue; if (!(attrib->flags & VA_SURFACE_ATTRIB_SETTABLE)) continue; fmt = gst_vaapi_video_format_from_va_fourcc (attrib->value.value.i); if (fmt == GST_VIDEO_FORMAT_UNKNOWN) continue; g_array_append_val (formats, fmt); } if (formats->len == 0) { g_array_unref (formats); formats = NULL; } g_free (surface_attribs); return formats; /* ERRORS */ error: { g_free (surface_attribs); } return NULL; }
static gboolean gst_vaapi_surface_create_full (GstVaapiSurface * surface, const GstVideoInfo * vip, guint flags) { #if VA_CHECK_VERSION(0,34,0) GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface); const GstVideoFormat format = GST_VIDEO_INFO_FORMAT (vip); VASurfaceID surface_id; VAStatus status; guint chroma_type, va_chroma_format, i; const VAImageFormat *va_format; VASurfaceAttrib attribs[3], *attrib; VASurfaceAttribExternalBuffers extbuf; gboolean extbuf_needed = FALSE; va_format = gst_vaapi_video_format_to_va_format (format); if (!va_format) goto error_unsupported_format; chroma_type = gst_vaapi_video_format_get_chroma_type (format); if (!chroma_type) goto error_unsupported_format; va_chroma_format = from_GstVaapiChromaType (chroma_type); if (!va_chroma_format) goto error_unsupported_format; memset (&extbuf, 0, sizeof (extbuf)); extbuf.pixel_format = va_format->fourcc; extbuf.width = GST_VIDEO_INFO_WIDTH (vip); extbuf.height = GST_VIDEO_INFO_HEIGHT (vip); extbuf_needed = ! !(flags & GST_VAAPI_SURFACE_ALLOC_FLAG_LINEAR_STORAGE); extbuf.num_planes = GST_VIDEO_INFO_N_PLANES (vip); if (flags & GST_VAAPI_SURFACE_ALLOC_FLAG_FIXED_STRIDES) { for (i = 0; i < extbuf.num_planes; i++) extbuf.pitches[i] = GST_VIDEO_INFO_PLANE_STRIDE (vip, i); extbuf_needed = TRUE; } if (flags & GST_VAAPI_SURFACE_ALLOC_FLAG_FIXED_OFFSETS) { for (i = 0; i < extbuf.num_planes; i++) extbuf.offsets[i] = GST_VIDEO_INFO_PLANE_OFFSET (vip, i); extbuf_needed = TRUE; } attrib = attribs; attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; attrib->type = VASurfaceAttribPixelFormat; attrib->value.type = VAGenericValueTypeInteger; attrib->value.value.i = va_format->fourcc; attrib++; if (extbuf_needed) { attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; attrib->type = VASurfaceAttribMemoryType; attrib->value.type = VAGenericValueTypeInteger; attrib->value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA; attrib++; attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; attrib->type = VASurfaceAttribExternalBufferDescriptor; attrib->value.type = VAGenericValueTypePointer; attrib->value.value.p = &extbuf; attrib++; } GST_VAAPI_DISPLAY_LOCK (display); status = vaCreateSurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display), va_chroma_format, extbuf.width, extbuf.height, &surface_id, 1, attribs, attrib - attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaCreateSurfaces()")) return FALSE; surface->format = format; surface->chroma_type = chroma_type; surface->width = extbuf.width; surface->height = extbuf.height; GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)); GST_VAAPI_OBJECT_ID (surface) = surface_id; return TRUE; /* ERRORS */ error_unsupported_format: GST_ERROR ("unsupported format %s", gst_vaapi_video_format_to_string (format)); return FALSE; #else return FALSE; #endif }
static gboolean gst_vaapi_surface_create_from_buffer_proxy (GstVaapiSurface * surface, GstVaapiBufferProxy * proxy, const GstVideoInfo * vip) { #if VA_CHECK_VERSION (0,36,0) GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface); GstVideoFormat format; VASurfaceID surface_id; VAStatus status; guint chroma_type, va_chroma_format; const VAImageFormat *va_format; VASurfaceAttrib attribs[2], *attrib; VASurfaceAttribExternalBuffers extbuf; unsigned long extbuf_handle; guint i, width, height; format = GST_VIDEO_INFO_FORMAT (vip); width = GST_VIDEO_INFO_WIDTH (vip); height = GST_VIDEO_INFO_HEIGHT (vip); gst_vaapi_buffer_proxy_replace (&surface->extbuf_proxy, proxy); va_format = gst_vaapi_video_format_to_va_format (format); if (!va_format) goto error_unsupported_format; chroma_type = gst_vaapi_video_format_get_chroma_type (format); if (!chroma_type) goto error_unsupported_format; va_chroma_format = from_GstVaapiChromaType (chroma_type); if (!va_chroma_format) goto error_unsupported_format; extbuf_handle = GST_VAAPI_BUFFER_PROXY_HANDLE (proxy); extbuf.pixel_format = va_format->fourcc; extbuf.width = width; extbuf.height = height; extbuf.data_size = GST_VAAPI_BUFFER_PROXY_SIZE (proxy); extbuf.num_planes = GST_VIDEO_INFO_N_PLANES (vip); for (i = 0; i < extbuf.num_planes; i++) { extbuf.pitches[i] = GST_VIDEO_INFO_PLANE_STRIDE (vip, i); extbuf.offsets[i] = GST_VIDEO_INFO_PLANE_OFFSET (vip, i); } extbuf.buffers = &extbuf_handle; extbuf.num_buffers = 1; extbuf.flags = 0; extbuf.private_data = NULL; attrib = attribs; attrib->type = VASurfaceAttribExternalBufferDescriptor; attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; attrib->value.type = VAGenericValueTypePointer; attrib->value.value.p = &extbuf; attrib++; attrib->type = VASurfaceAttribMemoryType; attrib->flags = VA_SURFACE_ATTRIB_SETTABLE; attrib->value.type = VAGenericValueTypeInteger; attrib->value.value.i = from_GstVaapiBufferMemoryType (GST_VAAPI_BUFFER_PROXY_TYPE (proxy)); attrib++; GST_VAAPI_DISPLAY_LOCK (display); status = vaCreateSurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display), va_chroma_format, width, height, &surface_id, 1, attribs, attrib - attribs); GST_VAAPI_DISPLAY_UNLOCK (display); if (!vaapi_check_status (status, "vaCreateSurfaces()")) return FALSE; surface->format = format; surface->chroma_type = chroma_type; surface->width = width; surface->height = height; GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id)); GST_VAAPI_OBJECT_ID (surface) = surface_id; return TRUE; /* ERRORS */ error_unsupported_format: GST_ERROR ("unsupported format %s", gst_vaapi_video_format_to_string (format)); return FALSE; #else return FALSE; #endif }