static gboolean
ensure_vpp (GstVaapiDecodeBin * vaapidecbin)
{
  GstVaapiDisplay *display;

  if (vaapidecbin->has_vpp != HAS_VPP_UNKNOWN)
    return TRUE;

  display = GST_VAAPI_PLUGIN_BASE_DISPLAY (vaapidecbin->decoder);
  if (display) {
    GST_INFO_OBJECT (vaapidecbin, "Got display from vaapidecode");
    gst_vaapi_display_ref (display);
  } else {
    GST_INFO_OBJECT (vaapidecbin, "Creating a dummy display to test for vpp");
    display = gst_vaapi_create_test_display ();
  }
  if (!display)
    return FALSE;

  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ?
    HAS_VPP_YES : HAS_VPP_NO;

  gst_vaapi_display_unref (display);

  return TRUE;
}
Пример #2
0
static GstCaps *
gst_vaapidecode_sink_getcaps (GstVideoDecoder * vdec, GstCaps * filter)
{
  GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
  GstCaps *result;

  if (decode->allowed_sinkpad_caps)
    goto bail;

  /* if we haven't a display yet, return our pad's template caps */
  if (!GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))
    goto bail;

  /* if the allowed caps calculation fails, return an empty caps, so
   * the auto-plug can try other decoder */
  if (!gst_vaapidecode_ensure_allowed_sinkpad_caps (decode))
    return gst_caps_new_empty ();

bail:
  result = gst_video_decoder_proxy_getcaps (vdec, decode->allowed_sinkpad_caps,
      filter);

  GST_DEBUG_OBJECT (decode, "Returning sink caps %" GST_PTR_FORMAT, result);

  return result;
}
Пример #3
0
static gboolean
gst_vaapiencode_open (GstVideoEncoder * venc)
{
  GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
  GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (encode);
  gboolean success;

  if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (encode)))
    return FALSE;

  GST_VAAPI_PLUGIN_BASE_DISPLAY (encode) = NULL;
  success = ensure_display (encode);
  if (old_display)
    gst_vaapi_display_unref (old_display);
  return success;
}
Пример #4
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;
}
Пример #5
0
static gboolean
gst_vaapidecode_ensure_allowed_srcpad_caps (GstVaapiDecode * decode)
{
  GstCaps *out_caps, *raw_caps;

  if (decode->allowed_srcpad_caps)
    return TRUE;

  if (!GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))
    return FALSE;

  /* Create VA caps */
  out_caps = gst_caps_from_string (GST_VAAPI_MAKE_SURFACE_CAPS);
  if (!out_caps) {
    GST_WARNING_OBJECT (decode, "failed to create VA/GL source caps");
    return FALSE;
  }
#if (USE_GLX || USE_EGL)
  if (!GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAN_DMABUF (decode) &&
      gst_vaapi_display_has_opengl (GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))) {
    out_caps = gst_caps_make_writable (out_caps);
    gst_caps_append (out_caps,
        gst_caps_from_string (GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS));
  }
#endif
  out_caps = gst_caps_make_writable (out_caps);
  gst_caps_append (out_caps, gst_caps_from_string (GST_VAAPI_MAKE_DMABUF_CAPS));

  raw_caps = gst_vaapi_plugin_base_get_allowed_srcpad_raw_caps
      (GST_VAAPI_PLUGIN_BASE (decode),
      GST_VIDEO_INFO_FORMAT (&decode->decoded_info));
  if (!raw_caps) {
    gst_caps_unref (out_caps);
    GST_WARNING_OBJECT (decode, "failed to create raw sink caps");
    return FALSE;
  }

  out_caps = gst_caps_make_writable (out_caps);
  gst_caps_append (out_caps, gst_caps_copy (raw_caps));
  decode->allowed_srcpad_caps = out_caps;

  GST_INFO_OBJECT (decode, "allowed srcpad caps: %" GST_PTR_FORMAT,
      decode->allowed_srcpad_caps);

  return TRUE;
}
Пример #6
0
static gboolean
gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode)
{
  GstCaps *caps, *allowed_sinkpad_caps;
  GArray *profiles;
  guint i;

  profiles =
      gst_vaapi_display_get_decode_profiles (GST_VAAPI_PLUGIN_BASE_DISPLAY
      (decode));
  if (!profiles)
    goto error_no_profiles;

  allowed_sinkpad_caps = gst_caps_new_empty ();
  if (!allowed_sinkpad_caps)
    goto error_no_memory;

  for (i = 0; i < profiles->len; i++) {
    const GstVaapiProfile profile =
        g_array_index (profiles, GstVaapiProfile, i);
    const gchar *media_type_name;
    const gchar *profile_name;
    GstStructure *structure;

    media_type_name = gst_vaapi_profile_get_media_type_name (profile);
    if (!media_type_name)
      continue;

    caps = gst_caps_from_string (media_type_name);
    if (!caps)
      continue;
    structure = gst_caps_get_structure (caps, 0);

    profile_name = gst_vaapi_profile_get_name (profile);
    if (profile_name)
      gst_structure_set (structure, "profile", G_TYPE_STRING,
          profile_name, NULL);

    allowed_sinkpad_caps = gst_caps_merge (allowed_sinkpad_caps, caps);
  }
  decode->allowed_sinkpad_caps = gst_caps_simplify (allowed_sinkpad_caps);

  g_array_unref (profiles);
  return TRUE;

  /* ERRORS */
error_no_profiles:
  {
    GST_ERROR ("failed to retrieve VA decode profiles");
    return FALSE;
  }
error_no_memory:
  {
    GST_ERROR ("failed to allocate allowed-caps set");
    g_array_unref (profiles);
    return FALSE;
  }
}
Пример #7
0
static gboolean
gst_vaapidecode_start (GstVideoDecoder * vdec)
{
  GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec);
  GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);
  gboolean success;

  /* Let GstVideoContext ask for a proper display to its neighbours */
  /* Note: steal old display that may be allocated from get_caps()
     so that to retain a reference to it, thus avoiding extra
     initialization steps if we turn out to simply re-use the
     existing (cached) VA display */
  GST_VAAPI_PLUGIN_BASE_DISPLAY (decode) = NULL;
  success =
      gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (decode));
  if (old_display)
    gst_vaapi_display_unref (old_display);

  return success;
}
Пример #8
0
static GstCaps *
gst_vaapidecode_get_caps (GstPad * pad)
{
  GstVaapiDecode *const decode = GST_VAAPIDECODE (GST_OBJECT_PARENT (pad));

  if (decode->allowed_caps)
    goto bail;

  /* if we haven't a display yet, return our pad's template caps */
  if (!GST_VAAPI_PLUGIN_BASE_DISPLAY (decode))
    return gst_pad_get_pad_template_caps (pad);

  /* if the allowed caps calculation fails, return an empty caps, so
   * the auto-plug can try other decoder */
  if (!gst_vaapidecode_ensure_allowed_caps (decode))
    return gst_caps_new_empty ();

bail:
  return gst_caps_ref (decode->allowed_caps);
}
Пример #9
0
static gboolean
gst_vaapidecode_create (GstVaapiDecode * decode, GstCaps * caps)
{
  GstVaapiDisplay *dpy;

  if (!gst_vaapidecode_ensure_display (decode))
    return FALSE;
  dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode);

  switch (gst_vaapi_codec_from_caps (caps)) {
    case GST_VAAPI_CODEC_MPEG2:
      decode->decoder = gst_vaapi_decoder_mpeg2_new (dpy, caps);
      break;
    case GST_VAAPI_CODEC_MPEG4:
    case GST_VAAPI_CODEC_H263:
      decode->decoder = gst_vaapi_decoder_mpeg4_new (dpy, caps);
      break;
    case GST_VAAPI_CODEC_H264:
      decode->decoder = gst_vaapi_decoder_h264_new (dpy, caps);

      /* Set the stream buffer alignment for better optimizations */
      if (decode->decoder && caps) {
        GstStructure *const structure = gst_caps_get_structure (caps, 0);
        const gchar *str = NULL;

        if ((str = gst_structure_get_string (structure, "alignment"))) {
          GstVaapiStreamAlignH264 alignment;
          if (g_strcmp0 (str, "au") == 0)
            alignment = GST_VAAPI_STREAM_ALIGN_H264_AU;
          else if (g_strcmp0 (str, "nal") == 0)
            alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU;
          else
            alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE;
          gst_vaapi_decoder_h264_set_alignment (GST_VAAPI_DECODER_H264
              (decode->decoder), alignment);
        }
      }
      break;
#if USE_H265_DECODER
    case GST_VAAPI_CODEC_H265:
      decode->decoder = gst_vaapi_decoder_h265_new (dpy, caps);

      /* Set the stream buffer alignment for better optimizations */
      if (decode->decoder && caps) {
        GstStructure *const structure = gst_caps_get_structure (caps, 0);
        const gchar *str = NULL;

        if ((str = gst_structure_get_string (structure, "alignment"))) {
          GstVaapiStreamAlignH265 alignment;
          if (g_strcmp0 (str, "au") == 0)
            alignment = GST_VAAPI_STREAM_ALIGN_H265_AU;
          else if (g_strcmp0 (str, "nal") == 0)
            alignment = GST_VAAPI_STREAM_ALIGN_H265_NALU;
          else
            alignment = GST_VAAPI_STREAM_ALIGN_H265_NONE;
          gst_vaapi_decoder_h265_set_alignment (GST_VAAPI_DECODER_H265
              (decode->decoder), alignment);
        }
      }
      break;
#endif
    case GST_VAAPI_CODEC_WMV3:
    case GST_VAAPI_CODEC_VC1:
      decode->decoder = gst_vaapi_decoder_vc1_new (dpy, caps);
      break;
#if USE_JPEG_DECODER
    case GST_VAAPI_CODEC_JPEG:
      decode->decoder = gst_vaapi_decoder_jpeg_new (dpy, caps);
      break;
#endif
#if USE_VP8_DECODER
    case GST_VAAPI_CODEC_VP8:
      decode->decoder = gst_vaapi_decoder_vp8_new (dpy, caps);
      break;
#endif
#if USE_VP9_DECODER
    case GST_VAAPI_CODEC_VP9:
      decode->decoder = gst_vaapi_decoder_vp9_new (dpy, caps);
      break;
#endif
    default:
      decode->decoder = NULL;
      break;
  }
  if (!decode->decoder)
    return FALSE;

  gst_vaapi_decoder_set_codec_state_changed_func (decode->decoder,
      gst_vaapi_decoder_state_changed, decode);

  return TRUE;
}
Пример #10
0
static gboolean
gst_vaapidecode_ensure_allowed_sinkpad_caps (GstVaapiDecode * decode)
{
  GstCaps *caps, *allowed_sinkpad_caps;
  GArray *profiles;
  guint i;
  gboolean base_only = FALSE;
  gboolean have_high = FALSE;
  gboolean have_mvc = FALSE;
  gboolean have_svc = FALSE;

  profiles =
      gst_vaapi_display_get_decode_profiles (GST_VAAPI_PLUGIN_BASE_DISPLAY
      (decode));
  if (!profiles)
    goto error_no_profiles;

  allowed_sinkpad_caps = gst_caps_new_empty ();
  if (!allowed_sinkpad_caps)
    goto error_no_memory;

  if (g_object_class_find_property (G_OBJECT_GET_CLASS (decode), "base-only")) {
    g_object_get (decode, "base-only", &base_only, NULL);
  }

  for (i = 0; i < profiles->len; i++) {
    const GstVaapiProfile profile =
        g_array_index (profiles, GstVaapiProfile, i);
    const gchar *media_type_name;
    const gchar *profile_name;
    GstStructure *structure;

    media_type_name = gst_vaapi_profile_get_media_type_name (profile);
    if (!media_type_name)
      continue;

    caps = gst_caps_from_string (media_type_name);
    if (!caps)
      continue;
    structure = gst_caps_get_structure (caps, 0);

    profile_name = gst_vaapi_profile_get_name (profile);
    if (profile_name)
      gst_structure_set (structure, "profile", G_TYPE_STRING,
          profile_name, NULL);

    allowed_sinkpad_caps = gst_caps_merge (allowed_sinkpad_caps, caps);
    have_mvc |= is_mvc_profile (profile);
    have_svc |= is_svc_profile (profile);
    have_high |= profile == GST_VAAPI_PROFILE_H264_HIGH;
  }

  if (have_high) {
    allowed_sinkpad_caps =
        add_h264_profile_in_caps (allowed_sinkpad_caps, "progressive-high");
    allowed_sinkpad_caps =
        add_h264_profile_in_caps (allowed_sinkpad_caps, "constrained-high");
  }

  if (base_only && (!have_mvc || !have_svc) && have_high) {
    if (!have_mvc) {
      GST_DEBUG ("base_only: force adding MVC profiles in caps");

      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps, "multiview-high");
      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps, "stereo-high");
    }

    if (!have_svc) {
      GST_DEBUG ("base_only: force adding SVC profiles in caps");

      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps,
          "scalable-constrained-baseline");
      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps, "scalable-baseline");
      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps,
          "scalable-high-intra");
      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps,
          "scalable-constrained-high");
      allowed_sinkpad_caps =
          add_h264_profile_in_caps (allowed_sinkpad_caps, "scalable-high");
    }
  }
  decode->allowed_sinkpad_caps = gst_caps_simplify (allowed_sinkpad_caps);

  g_array_unref (profiles);
  return TRUE;

  /* ERRORS */
error_no_profiles:
  {
    GST_ERROR ("failed to retrieve VA decode profiles");
    return FALSE;
  }
error_no_memory:
  {
    GST_ERROR ("failed to allocate allowed-caps set");
    g_array_unref (profiles);
    return FALSE;
  }
}