/**
 * 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);
}
예제 #6
0
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;
}
예제 #12
0
/**
 * 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;
}
예제 #13
0
/**
 * 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;
}
예제 #18
0
/**
 * 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);
}
예제 #21
0
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;
}
예제 #24
0
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;
    }
}
예제 #25
0
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;
}
예제 #26
0
/**
 * 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;
}
예제 #28
0
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;
}
예제 #30
0
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;
}