예제 #1
0
gboolean
gst_vaapiencode_init_properties (GstVaapiEncode * encode)
{
  GPtrArray *const props = get_properties (GST_VAAPIENCODE_GET_CLASS (encode));
  guint i;

  /* XXX: use base_init()/base_finalize() to avoid multiple initializations */
  if (!props)
    return FALSE;

  encode->prop_values =
      g_ptr_array_new_full (props->len, (GDestroyNotify) prop_value_free);
  if (!encode->prop_values) {
    g_ptr_array_unref (props);
    return FALSE;
  }

  for (i = 0; i < props->len; i++) {
    PropValue *const prop_value = prop_value_new ((GstVaapiEncoderPropInfo *)
        g_ptr_array_index (props, i));
    if (!prop_value)
      return FALSE;
    g_ptr_array_add (encode->prop_values, prop_value);
  }
  return TRUE;
}
예제 #2
0
static gboolean
ensure_encoder (GstVaapiEncode * encode)
{
  GstVaapiEncodeClass *klass = GST_VAAPIENCODE_GET_CLASS (encode);
  GstVaapiEncoderStatus status;
  GPtrArray *const prop_values = encode->prop_values;
  guint i;

  g_return_val_if_fail (klass->alloc_encoder, FALSE);

  if (encode->encoder)
    return FALSE;

  encode->encoder = klass->alloc_encoder (encode,
      GST_VAAPI_PLUGIN_BASE_DISPLAY (encode));
  if (!encode->encoder)
    return FALSE;

  if (prop_values) {
    for (i = 0; i < prop_values->len; i++) {
      PropValue *const prop_value = g_ptr_array_index (prop_values, i);
      status = gst_vaapi_encoder_set_property (encode->encoder, prop_value->id,
          &prop_value->value);
      if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
        return FALSE;
    }
  }
  return TRUE;
}
예제 #3
0
static gboolean
ensure_output_state (GstVaapiEncode * encode)
{
  GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode);
  GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode);
  GstVaapiEncoderStatus status;
  GstCaps *out_caps;

  if (!encode->input_state_changed)
    return TRUE;

  out_caps = klass->get_caps (encode);
  if (!out_caps)
    return FALSE;

  if (encode->output_state)
    gst_video_codec_state_unref (encode->output_state);
  encode->output_state = gst_video_encoder_set_output_state (venc, out_caps,
      encode->input_state);

  if (encode->need_codec_data) {
    status = gst_vaapi_encoder_get_codec_data (encode->encoder,
        &encode->output_state->codec_data);
    if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
      return FALSE;
  }

  if (!gst_video_encoder_negotiate (venc))
    return FALSE;

  encode->input_state_changed = FALSE;
  return TRUE;
}
static void
gst_vaapiencode_mpeg2_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{
  GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
  GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (object);

  switch (prop_id) {
    default:
      if (!encode_class->set_property (base_encode, prop_id, value))
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
예제 #5
0
static gboolean
set_codec_state (GstVaapiEncode * encode, GstVideoCodecState * state)
{
  GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode);
  GstVaapiEncoderStatus status;

  g_return_val_if_fail (encode->encoder, FALSE);

  /* Initialize codec specific parameters */
  if (klass->set_config && !klass->set_config (encode))
    return FALSE;

  status = gst_vaapi_encoder_set_codec_state (encode->encoder, state);
  if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
    return FALSE;
  return TRUE;
}
예제 #6
0
static gboolean
ensure_allowed_sinkpad_caps (GstVaapiEncode * encode)
{
  GstVaapiEncodeClass *klass = GST_VAAPIENCODE_GET_CLASS (encode);
  GstCaps *out_caps, *raw_caps = NULL;
  GArray *formats = NULL;
  gboolean ret = FALSE;
  GstVaapiProfile profile = GST_VAAPI_PROFILE_UNKNOWN;

  if (encode->allowed_sinkpad_caps)
    return TRUE;
  if (!encode->encoder)
    return TRUE;

  out_caps = gst_caps_from_string (GST_VAAPI_MAKE_SURFACE_CAPS);
  if (!out_caps)
    goto failed_create_va_caps;

  if (klass->get_profile) {
    GstCaps *allowed =
        gst_pad_get_allowed_caps (GST_VAAPI_PLUGIN_BASE_SRC_PAD (encode));
    if (allowed) {
      if (!gst_caps_is_empty (allowed) && !gst_caps_is_any (allowed))
        profile = klass->get_profile (allowed);
      gst_caps_unref (allowed);
    }
  }

  formats = gst_vaapi_encoder_get_surface_formats (encode->encoder, profile);
  if (!formats)
    goto failed_get_formats;

  raw_caps = gst_vaapi_video_format_new_template_caps_from_list (formats);
  if (!raw_caps)
    goto failed_create_raw_caps;

  out_caps = gst_caps_make_writable (out_caps);
  gst_caps_append (out_caps, gst_caps_copy (raw_caps));
  gst_caps_replace (&encode->allowed_sinkpad_caps, out_caps);
  GST_INFO_OBJECT (encode, "Allowed sink caps %" GST_PTR_FORMAT,
      encode->allowed_sinkpad_caps);

  ret = TRUE;

bail:
  if (out_caps)
    gst_caps_unref (out_caps);
  if (raw_caps)
    gst_caps_unref (raw_caps);
  if (formats)
    g_array_unref (formats);
  return ret;

failed_create_va_caps:
  {
    GST_WARNING_OBJECT (encode, "failed to create VA/GL sink caps");
    return FALSE;
  }
failed_get_formats:
  {
    GST_WARNING_OBJECT (encode, "failed to get allowed surface formats");
    goto bail;
  }
failed_create_raw_caps:
  {
    GST_WARNING_OBJECT (encode, "failed to create raw sink caps");
    goto bail;
  }
}
예제 #7
0
static GstFlowReturn
gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout)
{
  GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode);
  GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode);
  GstVideoCodecFrame *out_frame;
  GstVaapiCodedBufferProxy *codedbuf_proxy = NULL;
  GstVaapiEncoderStatus status;
  GstBuffer *out_buffer;
  GstFlowReturn ret;

  status = gst_vaapi_encoder_get_buffer_with_timeout (encode->encoder,
      &codedbuf_proxy, timeout);
  if (status == GST_VAAPI_ENCODER_STATUS_NO_BUFFER)
    return GST_VAAPI_ENCODE_FLOW_TIMEOUT;
  if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
    goto error_get_buffer;

  out_frame = gst_vaapi_coded_buffer_proxy_get_user_data (codedbuf_proxy);
  if (!out_frame)
    goto error_get_buffer;
  gst_video_codec_frame_ref (out_frame);
  gst_video_codec_frame_set_user_data (out_frame, NULL, NULL);

  /* Update output state */
  GST_VIDEO_ENCODER_STREAM_LOCK (encode);
  if (!ensure_output_state (encode))
    goto error_output_state;
  GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);

  /* Allocate and copy buffer into system memory */
  out_buffer = NULL;
  ret = klass->alloc_buffer (encode,
      GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy), &out_buffer);
  gst_vaapi_coded_buffer_proxy_replace (&codedbuf_proxy, NULL);
  if (ret != GST_FLOW_OK)
    goto error_allocate_buffer;

  gst_buffer_replace (&out_frame->output_buffer, out_buffer);
  gst_buffer_unref (out_buffer);

  GST_TRACE_OBJECT (encode, "output:%" GST_TIME_FORMAT ", size:%zu",
      GST_TIME_ARGS (out_frame->pts), gst_buffer_get_size (out_buffer));

  return gst_video_encoder_finish_frame (venc, out_frame);

  /* ERRORS */
error_get_buffer:
  {
    GST_ERROR ("failed to get encoded buffer (status %d)", status);
    if (codedbuf_proxy)
      gst_vaapi_coded_buffer_proxy_unref (codedbuf_proxy);
    return GST_FLOW_ERROR;
  }
error_allocate_buffer:
  {
    GST_ERROR ("failed to allocate encoded buffer in system memory");
    if (out_buffer)
      gst_buffer_unref (out_buffer);
    gst_video_codec_frame_unref (out_frame);
    return ret;
  }
error_output_state:
  {
    GST_ERROR ("failed to negotiate output state (status %d)", status);
    GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);
    gst_video_codec_frame_unref (out_frame);
    return GST_FLOW_NOT_NEGOTIATED;
  }
}