示例#1
0
static MsdkSurface *
get_surface_from_pool (GstMsdkVPP * thiz, GstBufferPool * pool,
    GstBufferPoolAcquireParams * params)
{
  GstBuffer *new_buffer;
  mfxFrameSurface1 *new_surface;
  MsdkSurface *msdk_surface;

  if (!gst_buffer_pool_is_active (pool) &&
      !gst_buffer_pool_set_active (pool, TRUE)) {
    GST_ERROR_OBJECT (pool, "failed to activate buffer pool");
    return NULL;
  }

  if (gst_buffer_pool_acquire_buffer (pool, &new_buffer, params) != GST_FLOW_OK) {
    GST_ERROR_OBJECT (pool, "failed to acquire a buffer from pool");
    return NULL;
  }

  if (gst_msdk_is_msdk_buffer (new_buffer))
    new_surface = gst_msdk_get_surface_from_buffer (new_buffer);
  else {
    GST_ERROR_OBJECT (pool, "the acquired memory is not MSDK memory");
    return NULL;
  }

  msdk_surface = g_slice_new0 (MsdkSurface);
  msdk_surface->surface = new_surface;
  msdk_surface->buf = new_buffer;

  return msdk_surface;
}
示例#2
0
static MsdkSurface *
get_surface (GstMsdkDec * thiz, GstBuffer * buffer)
{
  MsdkSurface *i;

  i = g_slice_new0 (MsdkSurface);

  if (gst_msdk_is_msdk_buffer (buffer)) {
    i->surface = gst_msdk_get_surface_from_buffer (buffer);
    i->buf = buffer;
  } else {
    /* Confirm to activate the side pool */
    if (!gst_buffer_pool_is_active (thiz->pool) &&
        !gst_buffer_pool_set_active (thiz->pool, TRUE)) {
      g_slice_free (MsdkSurface, i);
      return NULL;
    }

    if (!gst_video_frame_map (&i->copy, &thiz->non_msdk_pool_info, buffer,
            GST_MAP_WRITE))
      goto failed_unref_buffer;

    if (gst_buffer_pool_acquire_buffer (thiz->pool, &buffer,
            NULL) != GST_FLOW_OK)
      goto failed_unmap_copy;

    i->surface = gst_msdk_get_surface_from_buffer (buffer);
    i->buf = buffer;

    if (!gst_video_frame_map (&i->data, &thiz->output_info, buffer,
            GST_MAP_READWRITE))
      goto failed_unref_buffer2;
  }

  thiz->decoded_msdk_surfaces = g_list_append (thiz->decoded_msdk_surfaces, i);
  return i;

failed_unref_buffer2:
  gst_buffer_unref (buffer);
  buffer = i->data.buffer;
failed_unmap_copy:
  gst_video_frame_unmap (&i->copy);
failed_unref_buffer:
  gst_buffer_unref (buffer);
  g_slice_free (MsdkSurface, i);

  GST_ERROR_OBJECT (thiz, "failed to handle buffer");
  return NULL;
}
示例#3
0
static GstFlowReturn
gst_msdkvpp_transform (GstBaseTransform * trans, GstBuffer * inbuf,
    GstBuffer * outbuf)
{
  GstMsdkVPP *thiz = GST_MSDKVPP (trans);
  GstClockTime timestamp;
  GstFlowReturn ret = GST_FLOW_OK;
  mfxSession session;
  mfxSyncPoint sync_point = NULL;
  mfxStatus status;
  MsdkSurface *in_surface = NULL;
  MsdkSurface *out_surface = NULL;

  timestamp = GST_BUFFER_TIMESTAMP (inbuf);

  in_surface = get_msdk_surface_from_input_buffer (thiz, inbuf);
  if (!in_surface)
    return GST_FLOW_ERROR;

  if (gst_msdk_is_msdk_buffer (outbuf)) {
    out_surface = g_slice_new0 (MsdkSurface);
    out_surface->surface = gst_msdk_get_surface_from_buffer (outbuf);
  } else {
    GST_ERROR ("Failed to get msdk outsurface!");
    return GST_FLOW_ERROR;
  }

  session = gst_msdk_context_get_session (thiz->context);

  /* outer loop is for handling FrameRate Control and deinterlace use cases */
  do {
    for (;;) {
      status =
          MFXVideoVPP_RunFrameVPPAsync (session, in_surface->surface,
          out_surface->surface, NULL, &sync_point);
      if (status != MFX_WRN_DEVICE_BUSY)
        break;
      /* If device is busy, wait 1ms and retry, as per MSDK's recommendation */
      g_usleep (1000);
    };

    if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA
        && status != MFX_ERR_MORE_SURFACE)
      goto vpp_error;

    /* No output generated */
    if (status == MFX_ERR_MORE_DATA)
      goto error_more_data;

    if (sync_point)
      MFXVideoCORE_SyncOperation (session, sync_point, 10000);

    /* More than one output buffers are generated */
    if (status == MFX_ERR_MORE_SURFACE) {
      GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
      GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration;
      timestamp += thiz->buffer_duration;
      ret = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (trans), outbuf);
      if (ret != GST_FLOW_OK)
        goto error_push_buffer;
      outbuf = create_output_buffer (thiz);
    } else {
      GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
      GST_BUFFER_DURATION (outbuf) = thiz->buffer_duration;
    }
  } while (status == MFX_ERR_MORE_SURFACE);

  free_msdk_surface (in_surface);
  return ret;

vpp_error:
  GST_ERROR_OBJECT (thiz, "MSDK Failed to do VPP");
  free_msdk_surface (in_surface);
  free_msdk_surface (out_surface);
  return GST_FLOW_ERROR;

error_more_data:
  GST_WARNING_OBJECT (thiz,
      "MSDK Requries additional input for processing, "
      "Retruning FLOW_DROPPED since no output buffer was generated");
  free_msdk_surface (in_surface);
  return GST_BASE_TRANSFORM_FLOW_DROPPED;

error_push_buffer:
  {
    free_msdk_surface (in_surface);
    free_msdk_surface (out_surface);
    GST_DEBUG_OBJECT (thiz, "failed to push output buffer: %s",
        gst_flow_get_name (ret));
    return ret;
  }
}
示例#4
0
static MsdkSurface *
get_msdk_surface_from_input_buffer (GstMsdkVPP * thiz, GstBuffer * inbuf)
{
  GstVideoFrame src_frame, out_frame;
  MsdkSurface *msdk_surface;
  GstMemory *mem = NULL;

  if (gst_msdk_is_msdk_buffer (inbuf)) {
    msdk_surface = g_slice_new0 (MsdkSurface);
    msdk_surface->surface = gst_msdk_get_surface_from_buffer (inbuf);
    msdk_surface->buf = gst_buffer_ref (inbuf);
    return msdk_surface;
  }

  /* If upstream hasn't accpeted the proposed msdk bufferpool,
   * just copy frame (if not dmabuf backed) to msdk buffer and
   * take a surface from it.   */
  if (!(msdk_surface =
          get_surface_from_pool (thiz, thiz->sinkpad_buffer_pool, NULL)))
    goto error;

#ifndef _WIN32
  /************ dmabuf-import ************* */
  /* if upstream provided a dmabuf backed memory, but not an msdk
   * buffer, we could export the dmabuf to underlined vasurface */
  mem = gst_buffer_peek_memory (inbuf, 0);
  if (gst_is_dmabuf_memory (mem)) {
    if (import_dmabuf_to_msdk_surface (thiz, inbuf, msdk_surface))
      return msdk_surface;
    else
      GST_INFO_OBJECT (thiz, "Upstream dmabuf-backed memory is not imported"
          "to the msdk surface, fall back to the copy input frame method");
  }
#endif

  if (!gst_video_frame_map (&src_frame, &thiz->sinkpad_info, inbuf,
          GST_MAP_READ)) {
    GST_ERROR_OBJECT (thiz, "failed to map the frame for source");
    goto error;
  }

  if (!gst_video_frame_map (&out_frame, &thiz->sinkpad_buffer_pool_info,
          msdk_surface->buf, GST_MAP_WRITE)) {
    GST_ERROR_OBJECT (thiz, "failed to map the frame for destination");
    gst_video_frame_unmap (&src_frame);
    goto error;
  }

  if (!gst_video_frame_copy (&out_frame, &src_frame)) {
    GST_ERROR_OBJECT (thiz, "failed to copy frame");
    gst_video_frame_unmap (&out_frame);
    gst_video_frame_unmap (&src_frame);
    goto error;
  }

  gst_video_frame_unmap (&out_frame);
  gst_video_frame_unmap (&src_frame);

  return msdk_surface;

error:
  return NULL;
}