/** * 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 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); }
/** * gst_vaapi_surface_deassociate_subpicture: * @surface: a #GstVaapiSurface * @subpicture: a #GstVaapiSubpicture * * Deassociates @subpicture from @surface. Other associations are kept. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_deassociate_subpicture (GstVaapiSurface * surface, GstVaapiSubpicture * subpicture) { gboolean success; g_return_val_if_fail (surface != NULL, FALSE); g_return_val_if_fail (subpicture != NULL, FALSE); if (!surface->subpictures) return TRUE; /* First, check subpicture was really associated with this surface */ if (!g_ptr_array_remove_fast (surface->subpictures, subpicture)) { GST_DEBUG ("subpicture %" GST_VAAPI_ID_FORMAT " was not bound to " "surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (GST_VAAPI_OBJECT_ID (subpicture)), GST_VAAPI_ID_ARGS (GST_VAAPI_OBJECT_ID (surface))); return TRUE; } success = _gst_vaapi_surface_deassociate_subpicture (surface, subpicture); gst_vaapi_object_unref (subpicture); return success; }
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 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); }
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; }
/** AVCodecContext.get_buffer() implementation */ static int gst_vaapi_decoder_ffmpeg_get_buffer(AVCodecContext *avctx, AVFrame *pic) { GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context; GstVaapiContext *context; GstVaapiSurface *surface; GstVaapiID surface_id; context = get_context(avctx); if (!context) return -1; surface = gst_vaapi_context_get_surface(context); if (!surface) { GST_DEBUG("failed to get a free VA surface"); return -1; } surface_id = GST_VAAPI_OBJECT_ID(surface); GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id)); pic->type = FF_BUFFER_TYPE_USER; pic->age = 1; pic->data[0] = (uint8_t *)surface; pic->data[1] = NULL; pic->data[2] = NULL; pic->data[3] = (uint8_t *)(uintptr_t)surface_id; pic->linesize[0] = 0; pic->linesize[1] = 0; pic->linesize[2] = 0; pic->linesize[3] = 0; pic->pts = vactx->decoder->priv->in_timestamp; return 0; }
static gboolean fill_picture (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture, GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface) { VAEncPictureParameterBufferJPEG *const pic_param = picture->param; memset (pic_param, 0, sizeof (VAEncPictureParameterBufferJPEG)); pic_param->reconstructed_picture = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface); pic_param->picture_width = GST_VAAPI_ENCODER_WIDTH (encoder); pic_param->picture_height = GST_VAAPI_ENCODER_HEIGHT (encoder); pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf); pic_param->pic_flags.bits.profile = 0; /* Profile = Baseline */ pic_param->pic_flags.bits.progressive = 0; /* Sequential encoding */ pic_param->pic_flags.bits.huffman = 1; /* Uses Huffman coding */ pic_param->pic_flags.bits.interleaved = 0; /* Input format is non interleaved (YUV) */ pic_param->pic_flags.bits.differential = 0; /* non-Differential Encoding */ pic_param->sample_bit_depth = 8; pic_param->num_scan = 1; pic_param->num_components = encoder->n_components; pic_param->quality = encoder->quality; 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_subpicture_get_id: * @subpicture: a #GstVaapiSubpicture * * Returns the underlying VASubpictureID of the @subpicture. * * Return value: the underlying VA subpicture id */ GstVaapiID gst_vaapi_subpicture_get_id (GstVaapiSubpicture * subpicture) { g_return_val_if_fail (subpicture != NULL, VA_INVALID_ID); return GST_VAAPI_OBJECT_ID (subpicture); }
/** * gst_vaapi_subpicture_new: * @image: a #GstVaapiImage * @flags: #GstVaapiSubpictureFlags, or zero * * Creates a new #GstVaapiSubpicture with @image as source pixels. The * newly created object holds a reference on @image. * * Return value: the newly allocated #GstVaapiSubpicture object */ GstVaapiSubpicture *gst_vaapi_subpicture_new (GstVaapiImage * image, guint flags) { GstVaapiSubpicture *subpicture; GstVaapiDisplay *display; GstVideoFormat format; guint va_flags; g_return_val_if_fail (image != NULL, NULL); GST_DEBUG ("create from image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (GST_VAAPI_OBJECT_ID (image))); display = GST_VAAPI_OBJECT_DISPLAY (image); format = GST_VAAPI_IMAGE_FORMAT (image); if (!gst_vaapi_display_has_subpicture_format (display, format, &va_flags)) return NULL; if (flags & ~va_flags) return NULL; subpicture = gst_vaapi_object_new (gst_vaapi_subpicture_class (), display); if (!subpicture) return NULL; subpicture->global_alpha = 1.0f; if (!gst_vaapi_subpicture_set_image (subpicture, image)) goto error; return subpicture; error: gst_vaapi_object_unref (subpicture); return NULL; }
/** * gst_vaapi_surface_query_status: * @surface: a #GstVaapiSurface * @pstatus: return location for the #GstVaapiSurfaceStatus * * Finds out any pending operations on the @surface. The * #GstVaapiSurfaceStatus flags are returned into @pstatus. * * Return value: %TRUE on success */ gboolean gst_vaapi_surface_query_status( GstVaapiSurface *surface, GstVaapiSurfaceStatus *pstatus ) { VASurfaceStatus surface_status; VAStatus status; g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE); GST_VAAPI_OBJECT_LOCK_DISPLAY(surface); status = vaQuerySurfaceStatus( GST_VAAPI_OBJECT_VADISPLAY(surface), GST_VAAPI_OBJECT_ID(surface), &surface_status ); GST_VAAPI_OBJECT_UNLOCK_DISPLAY(surface); if (!vaapi_check_status(status, "vaQuerySurfaceStatus()")) return FALSE; if (pstatus) *pstatus = to_GstVaapiSurfaceStatus(surface_status); return TRUE; }
/** * gst_vaapi_object_get_id: * @object: a #GstVaapiObject * * Returns the #GstVaapiID contained in the @object. * * Return value: the #GstVaapiID of the @object */ GstVaapiID gst_vaapi_object_get_id (GstVaapiObject * object) { g_return_val_if_fail (object != NULL, 0); return GST_VAAPI_OBJECT_ID (object); }
/** * 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; }
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_surface_get_id: * @surface: a #GstVaapiSurface * * Returns the underlying VASurfaceID of the @surface. * * Return value: the underlying VA surface id */ GstVaapiID gst_vaapi_surface_get_id (GstVaapiSurface * surface) { g_return_val_if_fail (surface != NULL, VA_INVALID_SURFACE); return GST_VAAPI_OBJECT_ID (surface); }
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; }
/** * gst_vaapi_image_get_id: * @image: a #GstVaapiImage * * Returns the underlying VAImageID of the @image. * * Return value: the underlying VA image id */ GstVaapiID gst_vaapi_image_get_id(GstVaapiImage *image) { g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID); g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID); return GST_VAAPI_OBJECT_ID(image); }
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; }
static void coded_buffer_unmap (GstVaapiCodedBuffer * buf) { if (!buf->segment_list) return; GST_VAAPI_OBJECT_LOCK_DISPLAY (buf); vaapi_unmap_buffer (GST_VAAPI_OBJECT_VADISPLAY (buf), GST_VAAPI_OBJECT_ID (buf), (void **) &buf->segment_list); GST_VAAPI_OBJECT_UNLOCK_DISPLAY (buf); }
static gboolean fill_picture (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture, GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface) { VAEncPictureParameterBufferVP8 *const pic_param = picture->param; int i; memset (pic_param, 0, sizeof (VAEncPictureParameterBufferVP8)); pic_param->reconstructed_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface); pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf); if (picture->type == GST_VAAPI_PICTURE_TYPE_P) { pic_param->pic_flags.bits.frame_type = 1; pic_param->ref_arf_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->alt_ref); pic_param->ref_gf_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->golden_ref); pic_param->ref_last_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->last_ref); pic_param->pic_flags.bits.refresh_last = 1; pic_param->pic_flags.bits.refresh_golden_frame = 0; pic_param->pic_flags.bits.copy_buffer_to_golden = 1; pic_param->pic_flags.bits.refresh_alternate_frame = 0; pic_param->pic_flags.bits.copy_buffer_to_alternate = 2; } else { pic_param->ref_last_frame = VA_INVALID_SURFACE; pic_param->ref_gf_frame = VA_INVALID_SURFACE; pic_param->ref_arf_frame = VA_INVALID_SURFACE; pic_param->pic_flags.bits.refresh_last = 1; pic_param->pic_flags.bits.refresh_golden_frame = 1; pic_param->pic_flags.bits.refresh_alternate_frame = 1; } pic_param->pic_flags.bits.show_frame = 1; if (encoder->loop_filter_level) { pic_param->pic_flags.bits.version = 1; pic_param->pic_flags.bits.loop_filter_type = 1; /* Enable simple loop filter */ /* Disabled segmentation, so what matters is only loop_filter_level[0] */ for (i = 0; i < 4; i++) pic_param->loop_filter_level[i] = encoder->loop_filter_level; } pic_param->sharpness_level = encoder->sharpness_level; /* Used for CBR */ pic_param->clamp_qindex_low = 0; pic_param->clamp_qindex_high = 127; 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; }
static gboolean coded_buffer_map (GstVaapiCodedBuffer * buf) { if (buf->segment_list) return TRUE; GST_VAAPI_OBJECT_LOCK_DISPLAY (buf); buf->segment_list = vaapi_map_buffer (GST_VAAPI_OBJECT_VADISPLAY (buf), GST_VAAPI_OBJECT_ID (buf)); GST_VAAPI_OBJECT_UNLOCK_DISPLAY (buf); return buf->segment_list != NULL; }
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 gst_vaapi_image_create(GstVaapiImage *image) { GstVaapiImagePrivate * const priv = image->priv; GstVaapiImageFormat format = priv->format; const VAImageFormat *va_format; VAImageID image_id; if (!priv->create_image) return (priv->image.image_id != VA_INVALID_ID && priv->image.buf != VA_INVALID_ID); if (!_gst_vaapi_image_create(image, format)) { switch (format) { case GST_VAAPI_IMAGE_I420: format = GST_VAAPI_IMAGE_YV12; break; case GST_VAAPI_IMAGE_YV12: format = GST_VAAPI_IMAGE_I420; break; default: format = 0; break; } if (!format || !_gst_vaapi_image_create(image, format)) return FALSE; } priv->image = priv->internal_image; image_id = priv->image.image_id; if (priv->format != priv->internal_format) { switch (priv->format) { case GST_VAAPI_IMAGE_YV12: case GST_VAAPI_IMAGE_I420: va_format = gst_vaapi_image_format_get_va_format(priv->format); if (!va_format) return FALSE; priv->image.format = *va_format; SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]); SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]); break; default: break; } } priv->is_linear = vaapi_image_is_linear(&priv->image); GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id)); GST_VAAPI_OBJECT_ID(image) = image_id; return TRUE; }
/** * 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; }
/** Ensures VA context is correctly set up for the current FFmpeg context */ static GstVaapiContext * get_context(AVCodecContext *avctx) { GstVaapiContextFfmpeg * const vactx = avctx->hwaccel_context; GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(vactx->decoder); GstVaapiDisplay *display; GstVaapiContext *context; gboolean success; if (!avctx->coded_width || !avctx->coded_height) return NULL; gst_vaapi_decoder_set_framerate( decoder, avctx->time_base.den / avctx->ticks_per_frame, avctx->time_base.num ); gst_vaapi_decoder_set_pixel_aspect_ratio( decoder, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den ); success = gst_vaapi_decoder_ensure_context( decoder, vactx->profile, vactx->entrypoint, avctx->coded_width, avctx->coded_height ); if (!success) { GST_DEBUG("failed to reset VA context:"); GST_DEBUG(" profile 0x%08x", vactx->profile); GST_DEBUG(" entrypoint %d", vactx->entrypoint); GST_DEBUG(" surface size %dx%d", avctx->width, avctx->height); return NULL; } display = GST_VAAPI_DECODER_DISPLAY(decoder); context = GST_VAAPI_DECODER_CONTEXT(decoder); vactx->base.display = GST_VAAPI_DISPLAY_VADISPLAY(display); vactx->base.context_id = GST_VAAPI_OBJECT_ID(context); return context; }
static gboolean do_create_objects_unlocked (GstVaapiWindowEGL * window, guint width, guint height, EglContext * egl_context) { EglWindow *egl_window; EglVTable *egl_vtable; egl_window = egl_window_new (egl_context, GSIZE_TO_POINTER (GST_VAAPI_OBJECT_ID (window->window))); if (!egl_window) return FALSE; window->egl_window = egl_window; egl_vtable = egl_context_get_vtable (egl_window->context, TRUE); if (!egl_vtable) return FALSE; window->egl_vtable = egl_object_ref (egl_vtable); 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; }