Esempio n. 1
0
static gboolean
gst_dtmf_src_negotiate (GstBaseSrc * basesrc)
{
  GstDTMFSrc *dtmfsrc = GST_DTMF_SRC (basesrc);
  GstCaps *caps;
  GstStructure *s;
  gboolean ret;

  caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc));

  if (!caps)
    caps =
        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
            (basesrc)));

  if (gst_caps_is_empty (caps))
    return FALSE;

  gst_caps_truncate (caps);
  s = gst_caps_get_structure (caps, 0);

  gst_structure_fixate_field_nearest_int (s, "rate", DEFAULT_SAMPLE_RATE);

  if (!gst_structure_get_int (s, "rate", &dtmfsrc->sample_rate)) {
    GST_ERROR_OBJECT (dtmfsrc, "Could not get rate");
    gst_caps_unref (caps);
    return FALSE;
  }

  ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);

  gst_caps_unref (caps);

  return ret;
}
Esempio n. 2
0
static gboolean
gst_fake_h264_parser_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstElement *self = GST_ELEMENT (gst_pad_get_parent (pad));
  GstPad *otherpad = gst_element_get_static_pad (self, "src");
  GstCaps *accepted_caps;
  GstStructure *s;
  const gchar *stream_format;

  accepted_caps = gst_pad_get_allowed_caps (otherpad);
  accepted_caps = gst_caps_make_writable (accepted_caps);
  gst_caps_truncate (accepted_caps);

  s = gst_caps_get_structure (accepted_caps, 0);
  stream_format = gst_structure_get_string (s, "stream-format");
  if (!stream_format)
    gst_structure_set (s, "stream-format", G_TYPE_STRING, "avc", NULL);

  gst_pad_set_caps (otherpad, accepted_caps);
  gst_caps_unref (accepted_caps);

  gst_object_unref (otherpad);
  gst_object_unref (self);

  return TRUE;
}
Esempio n. 3
0
static gboolean
gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
{
  GstMFCDec *self = GST_MFC_DEC (decoder);
  GstVideoCodecState *state;
  GstCaps *allowed_caps;
  GstVideoFormat format = GST_VIDEO_FORMAT_NV12;

  allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self));
  allowed_caps = gst_caps_truncate (allowed_caps);
  allowed_caps = gst_caps_fixate (allowed_caps);
  if (!gst_caps_is_empty (allowed_caps)) {
    const gchar *format_str;
    GstStructure *s = gst_caps_get_structure (allowed_caps, 0);

    format_str = gst_structure_get_string (s, "format");
    if (format_str)
      format = gst_video_format_from_string (format_str);
  }
  gst_caps_unref (allowed_caps);

  self->format = format;
  state =
      gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
      self->format, self->crop_width, self->crop_height, self->input_state);

  gst_video_codec_state_unref (state);

  return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
}
Esempio n. 4
0
static gboolean
gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstVdpVideoPostProcess *vpp =
      GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
  GstStructure *structure;
  GstCaps *output_caps, *allowed_caps, *src_caps;
  gboolean res;

  /* extract interlaced flag */
  structure = gst_caps_get_structure (caps, 0);
  gst_structure_get_boolean (structure, "interlaced", &vpp->interlaced);

  allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad);
  structure = gst_caps_get_structure (allowed_caps, 0);
  output_caps = gst_vdp_video_to_output_caps (caps);

  src_caps = gst_caps_intersect (output_caps, allowed_caps);
  gst_caps_truncate (src_caps);
  if (gst_caps_is_empty (src_caps))
    goto invalid_caps;

  GST_DEBUG ("output_caps: %" GST_PTR_FORMAT " allowed_caps: %" GST_PTR_FORMAT
      " src_caps: %" GST_PTR_FORMAT, output_caps, allowed_caps, src_caps);

  gst_caps_unref (output_caps);
  gst_caps_unref (allowed_caps);

  if (gst_vdp_vpp_is_interlaced (vpp)) {
    gint fps_n, fps_d;

    structure = gst_caps_get_structure (src_caps, 0);

    if (!gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
      gst_caps_unref (src_caps);
      goto invalid_caps;
    }

    gst_fraction_double (&fps_n, &fps_d);
    gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
        NULL);
    gst_structure_remove_field (structure, "interlaced");

    vpp->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
  }

  res = gst_pad_set_caps (vpp->srcpad, src_caps);

done:
  gst_object_unref (vpp);
  return res;

invalid_caps:
  GST_ERROR_OBJECT (vpp, "invalid caps: %" GST_PTR_FORMAT, caps);
  res = FALSE;
  goto done;
}
static GstCaps* gst_imx_blitter_video_transform_fixate_caps(GstBaseTransform *transform, GstPadDirection direction, GstCaps *caps, GstCaps *othercaps)
{
	othercaps = gst_caps_truncate(othercaps);
	othercaps = gst_caps_make_writable(othercaps);

	GST_DEBUG_OBJECT(transform, "trying to fixate othercaps %" GST_PTR_FORMAT " based on caps %" GST_PTR_FORMAT, (gpointer)othercaps, (gpointer)caps);

	othercaps = gst_imx_blitter_video_transform_fixate_size_caps(transform, direction, caps, othercaps);
	gst_imx_blitter_video_transform_fixate_format_caps(transform, caps, othercaps);

	return othercaps;
}
static gboolean
sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstStructure *structure;
  GstOmxBaseFilter *omx_base;
  GOmxCore *gomx;
  gint rate = 0;

  omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad));
  gomx = (GOmxCore *) omx_base->gomx;

  GST_INFO_OBJECT (omx_base, "setcaps (sink): %" GST_PTR_FORMAT, caps);

  structure = gst_caps_get_structure (caps, 0);

  gst_structure_get_int (structure, "rate", &rate);

  /* Input port configuration. */
  {
    OMX_AUDIO_PARAM_PCMMODETYPE param;

    G_OMX_INIT_PARAM (param);

    param.nPortIndex = omx_base->out_port->port_index;
    OMX_GetParameter (gomx->omx_handle, OMX_IndexParamAudioPcm, &param);

    param.nSamplingRate = rate;

    OMX_SetParameter (gomx->omx_handle, OMX_IndexParamAudioPcm, &param);
  }

  /* set caps on the srcpad */
  {
    GstCaps *tmp_caps;

    tmp_caps = gst_pad_get_allowed_caps (omx_base->srcpad);
    tmp_caps = gst_caps_make_writable (tmp_caps);
    gst_caps_truncate (tmp_caps);

    gst_pad_fixate_caps (omx_base->srcpad, tmp_caps);

    if (gst_caps_is_fixed (tmp_caps)) {
      GST_INFO_OBJECT (omx_base, "fixated to: %" GST_PTR_FORMAT, tmp_caps);
      gst_pad_set_caps (omx_base->srcpad, tmp_caps);
    }

    gst_caps_unref (tmp_caps);
  }

  return gst_pad_set_caps (pad, caps);
}
Esempio n. 7
0
static gboolean
gst_vis_gl_src_negotiate (GstVisualGL * visual)
{
  GstCaps *othercaps, *target;
  GstStructure *structure;
  GstCaps *caps;

  caps = gst_pad_get_caps (visual->srcpad);

  /* see what the peer can do */
  othercaps = gst_pad_peer_get_caps (visual->srcpad);
  if (othercaps) {
    target = gst_caps_intersect (othercaps, caps);
    gst_caps_unref (othercaps);
    gst_caps_unref (caps);

    if (gst_caps_is_empty (target))
      goto no_format;

    gst_caps_truncate (target);
  } else {
    /* need a copy, we'll be modifying it when fixating */
    target = gst_caps_copy (caps);
    gst_caps_unref (caps);
  }

  /* fixate in case something is not fixed. This does nothing if the value is
   * already fixed. For video we always try to fixate to something like
   * 320x240x25 by convention. */
  structure = gst_caps_get_structure (target, 0);
  gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH);
  gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT);
  gst_structure_fixate_field_nearest_fraction (structure, "framerate",
      DEFAULT_FPS_N, DEFAULT_FPS_D);

  gst_pad_set_caps (visual->srcpad, target);
  gst_caps_unref (target);

  return TRUE;

  /* ERRORS */
no_format:
  {
    GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
        ("could not negotiate output format"));
    gst_caps_unref (target);
    return FALSE;
  }
}
Esempio n. 8
0
const gchar *
get_mime_type (GstAnalyzerSink * sink)
{
  GstCaps *caps = NULL;
  GstStructure *structure;
  const gchar *name;

  caps = gst_pad_get_allowed_caps (GST_BASE_SINK_PAD (sink));
  if (caps) {
    caps = gst_caps_truncate (caps);
    structure = gst_caps_get_structure (caps, 0);
    name = g_strdup (gst_structure_get_name (structure));
    gst_caps_unref (caps);
    return name;
  }
  return NULL;
}
Esempio n. 9
0
static void
gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
{
  GstCaps *caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
  GstStructure *s;
  GstAudioInfo info;

  if (caps) {
    caps = gst_caps_truncate (caps);
    caps = gst_caps_make_writable (caps);
    s = gst_caps_get_structure (caps, 0);
    gst_structure_fixate_field_nearest_int (s, "rate", 48000);
    gst_structure_get_int (s, "rate", &dec->sample_rate);
    gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
    gst_structure_get_int (s, "channels", &dec->n_channels);
    gst_caps_unref (caps);
  } else {
    dec->sample_rate = 48000;
  }

  GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
      dec->sample_rate);

  /* pass valid order to audio info */
  if (pos) {
    memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
    gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
  }

  /* set up source format */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16,
      dec->sample_rate, dec->n_channels, pos ? dec->opus_pos : NULL);
  gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info);

  /* but we still need the opus order for later reordering */
  if (pos) {
    memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
    gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
  } else {
    dec->opus_pos[0] = GST_AUDIO_CHANNEL_POSITION_INVALID;
  }

  dec->info = info;
}
Esempio n. 10
0
static void
gst_droid_cam_src_vfsrc_fixatecaps (GstPad * pad, GstCaps * caps)
{
  GstDroidCamSrc *src = GST_DROID_CAM_SRC (GST_OBJECT_PARENT (pad));
  GstStructure *s;

  GST_LOG_OBJECT (src, "fixatecaps %" GST_PTR_FORMAT, caps);

  gst_caps_truncate (caps);

  s = gst_caps_get_structure (caps, 0);

  gst_structure_fixate_field_nearest_int (s, "width", DEFAULT_VF_WIDTH);
  gst_structure_fixate_field_nearest_int (s, "height", DEFAULT_VF_HEIGHT);
  gst_structure_fixate_field_nearest_fraction (s, "framerate", DEFAULT_FPS, 1);

  GST_DEBUG_OBJECT (src, "caps now is %" GST_PTR_FORMAT, caps);
}
Esempio n. 11
0
static GstCaps *
gst_video_rate_fixate_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
{
  GstStructure *s;
  gint num, denom;

  s = gst_caps_get_structure (caps, 0);
  if (G_UNLIKELY (!gst_structure_get_fraction (s, "framerate", &num, &denom)))
    return othercaps;

  othercaps = gst_caps_truncate (othercaps);
  othercaps = gst_caps_make_writable (othercaps);
  s = gst_caps_get_structure (othercaps, 0);
  gst_structure_fixate_field_nearest_fraction (s, "framerate", num, denom);

  return othercaps;
}
static GstCaps *
gst_inter_audio_src_fixate (GstBaseSrc * src, GstCaps * caps)
{
  GstStructure *structure;

  GST_DEBUG_OBJECT (src, "fixate");

  caps = gst_caps_make_writable (caps);
  caps = gst_caps_truncate (caps);

  structure = gst_caps_get_structure (caps, 0);

  gst_structure_fixate_field_string (structure, "format", GST_AUDIO_NE (S16));
  gst_structure_fixate_field_nearest_int (structure, "channels", 2);
  gst_structure_fixate_field_nearest_int (structure, "rate", 48000);
  gst_structure_fixate_field_string (structure, "layout", "interleaved");

  return caps;
}
Esempio n. 13
0
static gboolean
gst_teletextdec_push_preroll_buffer (GstTeletextDec * teletext)
{
  GstFlowReturn ret;
  GstBuffer *buf;
  gboolean res = TRUE;
  GstStructure *structure;
  const gchar *mimetype;
  GstCaps *out_caps, *peer_caps, *pad_caps;

  /* the stream is sparse, we send a dummy buffer for preroll */
  peer_caps = gst_pad_peer_get_caps (teletext->srcpad);
  pad_caps = gst_pad_get_caps (teletext->srcpad);
  out_caps = gst_caps_intersect (pad_caps, peer_caps);

  if (gst_caps_is_empty (out_caps)) {
    res = FALSE;
    goto beach;
  }

  gst_caps_truncate (out_caps);
  structure = gst_caps_get_structure (out_caps, 0);
  mimetype = gst_structure_get_name (structure);
  if (g_strcmp0 (mimetype, "video/x-raw-rgb") == 0) {
    /* omit preroll buffer for this format */
    goto beach;
  }

  buf = gst_buffer_new_and_alloc (1);
  GST_BUFFER_DATA (buf)[0] = 0;
  gst_buffer_set_caps (buf, out_caps);
  ret = gst_pad_push (teletext->srcpad, buf);
  if (ret != GST_FLOW_OK)
    res = FALSE;

beach:
  {
    gst_caps_unref (out_caps);
    gst_caps_unref (pad_caps);
    gst_caps_unref (peer_caps);
    return res;
  }
}
Esempio n. 14
0
static gboolean
gst_vtdec_negotiate_output_format (GstVtdec * vtdec,
    GstVideoCodecState * input_state)
{
  GstCaps *caps = NULL, *peercaps = NULL, *templcaps;
  GstVideoFormat output_format;
  GstVideoCodecState *output_state = NULL;
  GstCapsFeatures *features;
  GstStructure *structure;
  const gchar *s;

  peercaps = gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec), NULL);

  /* Check if output supports GL caps by preference */
  templcaps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec));
  caps =
      gst_caps_intersect_full (templcaps, peercaps, GST_CAPS_INTERSECT_FIRST);

  gst_caps_unref (peercaps);
  gst_caps_unref (templcaps);

  caps = gst_caps_truncate (caps);
  structure = gst_caps_get_structure (caps, 0);
  s = gst_structure_get_string (structure, "format");
  output_format = gst_video_format_from_string (s);
  features = gst_caps_features_copy (gst_caps_get_features (caps, 0));

  gst_caps_unref (caps);

  if (!gst_vtdec_create_session (vtdec, output_format)) {
    gst_caps_features_free (features);
    return FALSE;
  }

  output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (vtdec),
      output_format, vtdec->video_info.width, vtdec->video_info.height,
      input_state);

  output_state->caps = gst_video_info_to_caps (&output_state->info);
  gst_caps_set_features (output_state->caps, 0, features);

  return TRUE;
}
Esempio n. 15
0
static gboolean
gst_goom_src_negotiate (GstGoom * goom)
{
  GstCaps *othercaps, *target;
  GstStructure *structure;
  const GstCaps *templ;

  templ = gst_pad_get_pad_template_caps (goom->srcpad);

  GST_DEBUG_OBJECT (goom, "performing negotiation");

  /* see what the peer can do */
  othercaps = gst_pad_peer_get_caps (goom->srcpad);
  if (othercaps) {
    target = gst_caps_intersect (othercaps, templ);
    gst_caps_unref (othercaps);

    if (gst_caps_is_empty (target))
      goto no_format;

    gst_caps_truncate (target);
  } else {
    target = gst_caps_ref ((GstCaps *) templ);
  }

  structure = gst_caps_get_structure (target, 0);
  gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH);
  gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT);
  gst_structure_fixate_field_nearest_fraction (structure, "framerate",
      DEFAULT_FPS_N, DEFAULT_FPS_D);

  gst_pad_set_caps (goom->srcpad, target);
  gst_caps_unref (target);

  return TRUE;

no_format:
  {
    gst_caps_unref (target);
    return FALSE;
  }
}
static GstCaps *
gst_opus_dec_negotiate (GstOpusDec * dec)
{
  GstCaps *caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
  GstStructure *s;

  caps = gst_caps_make_writable (caps);
  gst_caps_truncate (caps);

  s = gst_caps_get_structure (caps, 0);
  gst_structure_fixate_field_nearest_int (s, "rate", 48000);
  gst_structure_get_int (s, "rate", &dec->sample_rate);
  gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
  gst_structure_get_int (s, "channels", &dec->n_channels);

  GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
      dec->sample_rate);

  return caps;
}
Esempio n. 17
0
static gboolean
gst_monoscope_src_negotiate (GstMonoscope * monoscope)
{
  GstCaps *othercaps, *target;
  GstStructure *structure;
  const GstCaps *templ;

  templ = gst_pad_get_pad_template_caps (monoscope->srcpad);

  GST_DEBUG_OBJECT (monoscope, "performing negotiation");

  /* see what the peer can do */
  othercaps = gst_pad_peer_get_caps (monoscope->srcpad);
  if (othercaps) {
    target = gst_caps_intersect (othercaps, templ);
    gst_caps_unref (othercaps);

    if (gst_caps_is_empty (target))
      goto no_format;

    gst_caps_truncate (target);
  } else {
    target = gst_caps_ref ((GstCaps *) templ);
  }

  structure = gst_caps_get_structure (target, 0);
  gst_structure_fixate_field_nearest_int (structure, "width", 320);
  gst_structure_fixate_field_nearest_int (structure, "height", 240);
  gst_structure_fixate_field_nearest_fraction (structure, "framerate", 25, 1);

  gst_pad_set_caps (monoscope->srcpad, target);
  gst_caps_unref (target);

  return TRUE;

no_format:
  {
    gst_caps_unref (target);
    return FALSE;
  }
}
Esempio n. 18
0
static GstCaps *
gst_smpte_alpha_transform_caps (GstBaseTransform * trans,
    GstPadDirection direction, GstCaps * from)
{
  GstCaps *to = gst_caps_copy (from);
  GstStructure *s;

  gst_caps_truncate (to);
  s = gst_caps_get_structure (to, 0);

  if (gst_structure_has_name (s, "video/x-raw-yuv")) {
    GValue list = { 0, };
    GValue val = { 0, };

    gst_structure_remove_field (s, "format");

    g_value_init (&list, GST_TYPE_LIST);
    g_value_init (&val, GST_TYPE_FOURCC);
    gst_value_set_fourcc (&val, GST_STR_FOURCC ("AYUV"));
    gst_value_list_append_value (&list, &val);
    g_value_reset (&val);
    gst_value_set_fourcc (&val, GST_STR_FOURCC ("I420"));
    gst_value_list_append_value (&list, &val);
    g_value_reset (&val);
    gst_value_set_fourcc (&val, GST_STR_FOURCC ("YV12"));
    gst_value_list_append_value (&list, &val);
    g_value_unset (&val);
    gst_structure_set_value (s, "format", &list);
    g_value_unset (&list);
  } else if (!gst_structure_has_name (s, "video/x-raw-rgb")) {
    gst_caps_unref (to);
    to = gst_caps_new_empty ();
  }

  return to;
}
Esempio n. 19
0
static gboolean
gst_fake_h264_parser_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstElement *self = GST_ELEMENT (parent);
  GstPad *otherpad = gst_element_get_static_pad (self, "src");
  GstCaps *accepted_caps;
  GstStructure *s;
  const gchar *stream_format;
  gboolean ret = TRUE;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
      accepted_caps = gst_pad_get_allowed_caps (otherpad);
      accepted_caps = gst_caps_truncate (accepted_caps);

      s = gst_caps_get_structure (accepted_caps, 0);
      stream_format = gst_structure_get_string (s, "stream-format");
      if (!stream_format)
        gst_structure_set (s, "stream-format", G_TYPE_STRING, "avc", NULL);

      gst_pad_set_caps (otherpad, accepted_caps);
      gst_caps_unref (accepted_caps);
      gst_event_unref (event);
      event = NULL;
      break;
    default:
      break;
  }

  if (event)
    ret = gst_pad_push_event (otherpad, event);
  gst_object_unref (otherpad);

  return ret;
}
Esempio n. 20
0
/**
 * gst_rtp_base_payload_set_outcaps:
 * @payload: a #GstRTPBasePayload
 * @fieldname: the first field name or %NULL
 * @...: field values
 *
 * Configure the output caps with the optional parameters.
 *
 * Variable arguments should be in the form field name, field type
 * (as a GType), value(s).  The last variable argument should be NULL.
 *
 * Returns: %TRUE if the caps could be set.
 */
gboolean
gst_rtp_base_payload_set_outcaps (GstRTPBasePayload * payload,
    const gchar * fieldname, ...)
{
  GstCaps *srccaps, *peercaps;
  gboolean res;

  /* fill in the defaults, their properties cannot be negotiated. */
  srccaps = gst_caps_new_simple ("application/x-rtp",
      "media", G_TYPE_STRING, payload->media,
      "clock-rate", G_TYPE_INT, payload->clock_rate,
      "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL);

  GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps);

  if (fieldname) {
    va_list varargs;

    /* override with custom properties */
    va_start (varargs, fieldname);
    gst_caps_set_simple_valist (srccaps, fieldname, varargs);
    va_end (varargs);

    GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps);
  }

  payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME;
  payload->ptime = 0;

  /* the peer caps can override some of the defaults */
  peercaps = gst_pad_peer_query_caps (payload->srcpad, srccaps);
  if (peercaps == NULL) {
    /* no peer caps, just add the other properties */
    gst_caps_set_simple (srccaps,
        "payload", G_TYPE_INT, GST_RTP_BASE_PAYLOAD_PT (payload),
        "ssrc", G_TYPE_UINT, payload->current_ssrc,
        "timestamp-offset", G_TYPE_UINT, payload->ts_base,
        "seqnum-offset", G_TYPE_UINT, payload->seqnum_base, NULL);

    GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps);
  } else {
    GstCaps *temp;
    GstStructure *s, *d;
    const GValue *value;
    gint pt;
    guint max_ptime, ptime;

    /* peer provides caps we can use to fixate. They are already intersected
     * with our srccaps, just make them writable */
    temp = gst_caps_make_writable (peercaps);
    gst_caps_unref (srccaps);

    if (gst_caps_is_empty (temp)) {
      gst_caps_unref (temp);
      return FALSE;
    }

    /* now fixate, start by taking the first caps */
    temp = gst_caps_truncate (temp);

    /* get first structure */
    s = gst_caps_get_structure (temp, 0);

    if (gst_structure_get_uint (s, "maxptime", &max_ptime))
      payload->priv->caps_max_ptime = max_ptime * GST_MSECOND;

    if (gst_structure_get_uint (s, "ptime", &ptime))
      payload->ptime = ptime * GST_MSECOND;

    if (gst_structure_get_int (s, "payload", &pt)) {
      /* use peer pt */
      GST_RTP_BASE_PAYLOAD_PT (payload) = pt;
      GST_LOG_OBJECT (payload, "using peer pt %d", pt);
    } else {
      if (gst_structure_has_field (s, "payload")) {
        /* can only fixate if there is a field */
        gst_structure_fixate_field_nearest_int (s, "payload",
            GST_RTP_BASE_PAYLOAD_PT (payload));
        gst_structure_get_int (s, "payload", &pt);
        GST_LOG_OBJECT (payload, "using peer pt %d", pt);
      } else {
        /* no pt field, use the internal pt */
        pt = GST_RTP_BASE_PAYLOAD_PT (payload);
        gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
        GST_LOG_OBJECT (payload, "using internal pt %d", pt);
      }
    }

    if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "ssrc");
      payload->current_ssrc = g_value_get_uint (value);
      GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL);
      GST_LOG_OBJECT (payload, "using internal ssrc %08x",
          payload->current_ssrc);
    }

    if (gst_structure_has_field_typed (s, "timestamp-offset", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "timestamp-offset");
      payload->ts_base = g_value_get_uint (value);
      GST_LOG_OBJECT (payload, "using peer timestamp-offset %u",
          payload->ts_base);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "timestamp-offset", G_TYPE_UINT, payload->ts_base,
          NULL);
      GST_LOG_OBJECT (payload, "using internal timestamp-offset %u",
          payload->ts_base);
    }
    if (gst_structure_has_field_typed (s, "seqnum-offset", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "seqnum-offset");
      payload->seqnum_base = g_value_get_uint (value);
      GST_LOG_OBJECT (payload, "using peer seqnum-offset %u",
          payload->seqnum_base);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "seqnum-offset", G_TYPE_UINT, payload->seqnum_base,
          NULL);
      GST_LOG_OBJECT (payload, "using internal seqnum-offset %u",
          payload->seqnum_base);
    }

    /* make the target caps by copying over all the fixed caps, removing the
     * unfixed caps. */
    srccaps = gst_caps_new_empty_simple (gst_structure_get_name (s));
    d = gst_caps_get_structure (srccaps, 0);

    gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d);

    gst_caps_unref (temp);

    GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps);
  }

  update_max_ptime (payload);

  res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
  gst_caps_unref (srccaps);

  return res;
}
static GstCaps *
gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
                             GstCaps * caps, GstCaps * othercaps)
{
    GstStructure *ins, *outs;
    const GValue *from_par, *to_par;
    GValue fpar = { 0, }, tpar = {
        0,
    };

    othercaps = gst_caps_truncate (othercaps);
    othercaps = gst_caps_make_writable (othercaps);

    GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
                      " based on caps %" GST_PTR_FORMAT, othercaps, caps);

    ins = gst_caps_get_structure (caps, 0);
    outs = gst_caps_get_structure (othercaps, 0);

    from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
    to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");

    /* If we're fixating from the sinkpad we always set the PAR and
     * assume that missing PAR on the sinkpad means 1/1 and
     * missing PAR on the srcpad means undefined
     */
    if (direction == GST_PAD_SINK) {
        if (!from_par) {
            g_value_init (&fpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&fpar, 1, 1);
            from_par = &fpar;
        }
        if (!to_par) {
            g_value_init (&tpar, GST_TYPE_FRACTION_RANGE);
            gst_value_set_fraction_range_full (&tpar, 1, G_MAXINT, G_MAXINT, 1);
            to_par = &tpar;
        }
    } else {
        if (!to_par) {
            g_value_init (&tpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&tpar, 1, 1);
            to_par = &tpar;

            gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
                               NULL);
        }
        if (!from_par) {
            g_value_init (&fpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&fpar, 1, 1);
            from_par = &fpar;
        }
    }

    /* we have both PAR but they might not be fixated */
    {
        gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
        gint w = 0, h = 0;
        gint from_dar_n, from_dar_d;
        gint num, den;

        /* from_par should be fixed */
        g_return_val_if_fail (gst_value_is_fixed (from_par), othercaps);

        from_par_n = gst_value_get_fraction_numerator (from_par);
        from_par_d = gst_value_get_fraction_denominator (from_par);

        gst_structure_get_int (ins, "width", &from_w);
        gst_structure_get_int (ins, "height", &from_h);

        gst_structure_get_int (outs, "width", &w);
        gst_structure_get_int (outs, "height", &h);

        /* if both width and height are already fixed, we can't do anything
         * about it anymore */
        if (w && h) {
            guint n, d;

            GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
                              w, h);
            if (!gst_value_is_fixed (to_par)) {
                if (gst_video_calculate_display_ratio (&n, &d, from_w, from_h,
                                                       from_par_n, from_par_d, w, h)) {
                    GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", n, d);
                    if (gst_structure_has_field (outs, "pixel-aspect-ratio"))
                        gst_structure_fixate_field_nearest_fraction (outs,
                                "pixel-aspect-ratio", n, d);
                    else if (n != d)
                        gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                           n, d, NULL);
                }
            }
            goto done;
        }

        /* Calculate input DAR */
        if (!gst_util_fraction_multiply (from_w, from_h, from_par_n, from_par_d,
                                         &from_dar_n, &from_dar_d)) {
            GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                               ("Error calculating the output scaled size - integer overflow"));
            goto done;
        }

        GST_DEBUG_OBJECT (base, "Input DAR is %d/%d", from_dar_n, from_dar_d);

        /* If either width or height are fixed there's not much we
         * can do either except choosing a height or width and PAR
         * that matches the DAR as good as possible
         */
        if (h) {
            GstStructure *tmp;
            gint set_w, set_par_n, set_par_d;

            GST_DEBUG_OBJECT (base, "height is fixed (%d)", h);

            /* If the PAR is fixed too, there's not much to do
             * except choosing the width that is nearest to the
             * width with the same DAR */
            if (gst_value_is_fixed (to_par)) {
                to_par_n = gst_value_get_fraction_numerator (to_par);
                to_par_d = gst_value_get_fraction_denominator (to_par);

                GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);

                if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
                                                 to_par_n, &num, &den)) {
                    GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                       ("Error calculating the output scaled size - integer overflow"));
                    goto done;
                }

                w = (guint) gst_util_uint64_scale_int (h, num, den);
                gst_structure_fixate_field_nearest_int (outs, "width", w);

                goto done;
            }

            /* The PAR is not fixed and it's quite likely that we can set
             * an arbitrary PAR. */

            /* Check if we can keep the input width */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            /* Might have failed but try to keep the DAR nonetheless by
             * adjusting the PAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }

            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            /* Check if the adjusted PAR is accepted */
            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "width", G_TYPE_INT, set_w,
                                       "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
                                       NULL);
                goto done;
            }

            /* Otherwise scale the width to the new PAR and check if the
             * adjusted with is accepted. If all that fails we can't keep
             * the DAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            w = (guint) gst_util_uint64_scale_int (h, num, den);
            gst_structure_fixate_field_nearest_int (outs, "width", w);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);

            goto done;
        } else if (w) {
            GstStructure *tmp;
            gint set_h, set_par_n, set_par_d;

            GST_DEBUG_OBJECT (base, "width is fixed (%d)", w);

            /* If the PAR is fixed too, there's not much to do
             * except choosing the height that is nearest to the
             * height with the same DAR */
            if (gst_value_is_fixed (to_par)) {
                to_par_n = gst_value_get_fraction_numerator (to_par);
                to_par_d = gst_value_get_fraction_denominator (to_par);

                GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);

                if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
                                                 to_par_n, &num, &den)) {
                    GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                       ("Error calculating the output scaled size - integer overflow"));
                    goto done;
                }

                h = (guint) gst_util_uint64_scale_int (w, den, num);
                gst_structure_fixate_field_nearest_int (outs, "height", h);

                goto done;
            }

            /* The PAR is not fixed and it's quite likely that we can set
             * an arbitrary PAR. */

            /* Check if we can keep the input height */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);

            /* Might have failed but try to keep the DAR nonetheless by
             * adjusting the PAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }
            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            /* Check if the adjusted PAR is accepted */
            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "height", G_TYPE_INT, set_h,
                                       "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
                                       NULL);
                goto done;
            }

            /* Otherwise scale the height to the new PAR and check if the
             * adjusted with is accepted. If all that fails we can't keep
             * the DAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            h = (guint) gst_util_uint64_scale_int (w, den, num);
            gst_structure_fixate_field_nearest_int (outs, "height", h);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);

            goto done;
        } else if (gst_value_is_fixed (to_par)) {
            GstStructure *tmp;
            gint set_h, set_w, f_h, f_w;

            to_par_n = gst_value_get_fraction_numerator (to_par);
            to_par_d = gst_value_get_fraction_denominator (to_par);

            /* Calculate scale factor for the PAR change */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n,
                                             to_par_d, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            /* Try to keep the input height (because of interlacing) */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);

            /* This might have failed but try to scale the width
             * to keep the DAR nonetheless */
            w = (guint) gst_util_uint64_scale_int (set_h, num, den);
            gst_structure_fixate_field_nearest_int (tmp, "width", w);
            gst_structure_get_int (tmp, "width", &set_w);
            gst_structure_free (tmp);

            /* We kept the DAR and the height is nearest to the original height */
            if (set_w == w) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);
                goto done;
            }

            f_h = set_h;
            f_w = set_w;

            /* If the former failed, try to keep the input width at least */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            /* This might have failed but try to scale the width
             * to keep the DAR nonetheless */
            h = (guint) gst_util_uint64_scale_int (set_w, den, num);
            gst_structure_fixate_field_nearest_int (tmp, "height", h);
            gst_structure_get_int (tmp, "height", &set_h);
            gst_structure_free (tmp);

            /* We kept the DAR and the width is nearest to the original width */
            if (set_h == h) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);
                goto done;
            }

            /* If all this failed, keep the height that was nearest to the orignal
             * height and the nearest possible width. This changes the DAR but
             * there's not much else to do here.
             */
            gst_structure_set (outs, "width", G_TYPE_INT, f_w, "height", G_TYPE_INT,
                               f_h, NULL);
            goto done;
        } else {
            GstStructure *tmp;
            gint set_h, set_w, set_par_n, set_par_d, tmp2;

            /* width, height and PAR are not fixed but passthrough is not possible */

            /* First try to keep the height and width as good as possible
             * and scale PAR */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }

            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);

                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* Otherwise try to scale width to keep the DAR with the set
             * PAR and height */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            w = (guint) gst_util_uint64_scale_int (set_h, num, den);
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", w);
            gst_structure_get_int (tmp, "width", &tmp2);
            gst_structure_free (tmp);

            if (tmp2 == w) {
                gst_structure_set (outs, "width", G_TYPE_INT, tmp2, "height",
                                   G_TYPE_INT, set_h, NULL);
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* ... or try the same with the height */
            h = (guint) gst_util_uint64_scale_int (set_w, den, num);
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", h);
            gst_structure_get_int (tmp, "height", &tmp2);
            gst_structure_free (tmp);

            if (tmp2 == h) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, tmp2, NULL);
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* If all fails we can't keep the DAR and take the nearest values
             * for everything from the first try */
            gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                               G_TYPE_INT, set_h, NULL);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);
        }
    }

done:
    GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);

    if (from_par == &fpar)
        g_value_unset (&fpar);
    if (to_par == &tpar)
        g_value_unset (&tpar);

    return othercaps;
}
Esempio n. 22
0
static gboolean
gst_rtp_opus_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
{
  gboolean res;
  GstCaps *src_caps;
  GstStructure *s;
  char *encoding_name;
  gint channels, rate;
  const char *sprop_stereo = NULL;
  char *sprop_maxcapturerate = NULL;

  src_caps = gst_pad_get_allowed_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
  if (src_caps) {
    src_caps = gst_caps_make_writable (src_caps);
    src_caps = gst_caps_truncate (src_caps);
    s = gst_caps_get_structure (src_caps, 0);
    gst_structure_fixate_field_string (s, "encoding-name", "OPUS");
    encoding_name = g_strdup (gst_structure_get_string (s, "encoding-name"));
    gst_caps_unref (src_caps);
  } else {
    encoding_name = g_strdup ("X-GST-OPUS-DRAFT-SPITTKA-00");
  }

  s = gst_caps_get_structure (caps, 0);
  if (gst_structure_get_int (s, "channels", &channels)) {
    if (channels > 2) {
      GST_ERROR_OBJECT (payload,
          "More than 2 channels with channel-mapping-family=0 is invalid");
      return FALSE;
    } else if (channels == 2) {
      sprop_stereo = "1";
    } else {
      sprop_stereo = "0";
    }
  }

  if (gst_structure_get_int (s, "rate", &rate)) {
    sprop_maxcapturerate = g_strdup_printf ("%d", rate);
  }

  gst_rtp_base_payload_set_options (payload, "audio", FALSE,
      encoding_name, 48000);
  g_free (encoding_name);

  if (sprop_maxcapturerate && sprop_stereo) {
    res =
        gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate",
        G_TYPE_STRING, sprop_maxcapturerate, "sprop-stereo", G_TYPE_STRING,
        sprop_stereo, NULL);
  } else if (sprop_maxcapturerate) {
    res =
        gst_rtp_base_payload_set_outcaps (payload, "sprop-maxcapturerate",
        G_TYPE_STRING, sprop_maxcapturerate, NULL);
  } else if (sprop_stereo) {
    res =
        gst_rtp_base_payload_set_outcaps (payload, "sprop-stereo",
        G_TYPE_STRING, sprop_stereo, NULL);
  } else {
    res = gst_rtp_base_payload_set_outcaps (payload, NULL);
  }

  g_free (sprop_maxcapturerate);

  return res;
}
static gboolean
gst_monoscope_src_negotiate (GstMonoscope * monoscope)
{
  GstCaps *othercaps, *target;
  GstStructure *structure;
  GstCaps *templ;
  GstQuery *query;
  GstBufferPool *pool;
  GstStructure *config;
  guint size, min, max;

  templ = gst_pad_get_pad_template_caps (monoscope->srcpad);

  GST_DEBUG_OBJECT (monoscope, "performing negotiation");

  /* see what the peer can do */
  othercaps = gst_pad_peer_query_caps (monoscope->srcpad, NULL);
  if (othercaps) {
    target = gst_caps_intersect (othercaps, templ);
    gst_caps_unref (othercaps);
    gst_caps_unref (templ);

    if (gst_caps_is_empty (target))
      goto no_format;

    target = gst_caps_truncate (target);
  } else {
    target = templ;
  }

  target = gst_caps_make_writable (target);
  structure = gst_caps_get_structure (target, 0);
  gst_structure_fixate_field_nearest_int (structure, "width", 320);
  gst_structure_fixate_field_nearest_int (structure, "height", 240);
  gst_structure_fixate_field_nearest_fraction (structure, "framerate", 25, 1);

  gst_monoscope_src_setcaps (monoscope, target);

  /* try to get a bufferpool now */
  /* find a pool for the negotiated caps now */
  query = gst_query_new_allocation (target, TRUE);

  if (!gst_pad_peer_query (monoscope->srcpad, query)) {
  }

  if (gst_query_get_n_allocation_pools (query) > 0) {
    /* we got configuration from our peer, parse them */
    gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
  } else {
    pool = NULL;
    size = monoscope->outsize;
    min = max = 0;
  }

  if (pool == NULL) {
    /* we did not get a pool, make one ourselves then */
    pool = gst_buffer_pool_new ();
  }

  config = gst_buffer_pool_get_config (pool);
  gst_buffer_pool_config_set_params (config, target, size, min, max);
  gst_buffer_pool_set_config (pool, config);

  if (monoscope->pool) {
    gst_buffer_pool_set_active (monoscope->pool, TRUE);
    gst_object_unref (monoscope->pool);
  }
  monoscope->pool = pool;

  /* and activate */
  gst_buffer_pool_set_active (pool, TRUE);

  gst_caps_unref (target);

  return TRUE;

no_format:
  {
    gst_caps_unref (target);
    return FALSE;
  }
}
Esempio n. 24
0
static gboolean
gst_openjpeg_enc_set_format (GstVideoEncoder * encoder,
    GstVideoCodecState * state)
{
  GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder);
  GstCaps *allowed_caps, *caps;
  GstStructure *s;
  const gchar *colorspace;
  gint ncomps;

  GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);

  if (self->input_state)
    gst_video_codec_state_unref (self->input_state);
  self->input_state = gst_video_codec_state_ref (state);

  allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
  allowed_caps = gst_caps_truncate (allowed_caps);
  s = gst_caps_get_structure (allowed_caps, 0);
  if (gst_structure_has_name (s, "image/jp2")) {
    self->codec_format = OPJ_CODEC_JP2;
    self->is_jp2c = FALSE;
  } else if (gst_structure_has_name (s, "image/x-j2c")) {
    self->codec_format = OPJ_CODEC_J2K;
    self->is_jp2c = TRUE;
  } else if (gst_structure_has_name (s, "image/x-jpc")) {
    self->codec_format = OPJ_CODEC_J2K;
    self->is_jp2c = FALSE;
  } else {
    g_return_val_if_reached (FALSE);
  }

  switch (state->info.finfo->format) {
    case GST_VIDEO_FORMAT_ARGB64:
      self->fill_image = fill_image_packed16_4;
      ncomps = 4;
      break;
    case GST_VIDEO_FORMAT_ARGB:
      self->fill_image = fill_image_packed8_4;
      ncomps = 4;
      break;
    case GST_VIDEO_FORMAT_xRGB:
      self->fill_image = fill_image_packed8_3;
      ncomps = 3;
      break;
    case GST_VIDEO_FORMAT_AYUV64:
      self->fill_image = fill_image_packed16_4;
      ncomps = 4;
      break;
    case GST_VIDEO_FORMAT_Y444_10LE:
    case GST_VIDEO_FORMAT_Y444_10BE:
    case GST_VIDEO_FORMAT_I422_10LE:
    case GST_VIDEO_FORMAT_I422_10BE:
    case GST_VIDEO_FORMAT_I420_10LE:
    case GST_VIDEO_FORMAT_I420_10BE:
      self->fill_image = fill_image_planar16_3;
      ncomps = 3;
      break;
    case GST_VIDEO_FORMAT_AYUV:
      self->fill_image = fill_image_packed8_3;
      ncomps = 3;
      break;
    case GST_VIDEO_FORMAT_Y444:
    case GST_VIDEO_FORMAT_Y42B:
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_Y41B:
    case GST_VIDEO_FORMAT_YUV9:
      self->fill_image = fill_image_planar8_3;
      ncomps = 3;
      break;
    case GST_VIDEO_FORMAT_GRAY8:
      self->fill_image = fill_image_planar8_1;
      ncomps = 1;
      break;
    case GST_VIDEO_FORMAT_GRAY16_LE:
    case GST_VIDEO_FORMAT_GRAY16_BE:
      self->fill_image = fill_image_planar16_1;
      ncomps = 1;
      break;
    default:
      g_assert_not_reached ();
  }

  if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_YUV))
    colorspace = "sYUV";
  else if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB))
    colorspace = "sRGB";
  else if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_GRAY))
    colorspace = "GRAY";
  else
    g_return_val_if_reached (FALSE);

  caps = gst_caps_new_simple (gst_structure_get_name (s),
      "colorspace", G_TYPE_STRING, colorspace,
      "num-components", G_TYPE_INT, ncomps, NULL);
  gst_caps_unref (allowed_caps);

  if (self->output_state)
    gst_video_codec_state_unref (self->output_state);
  self->output_state =
      gst_video_encoder_set_output_state (encoder, caps, state);

  gst_video_encoder_negotiate (GST_VIDEO_ENCODER (encoder));

  return TRUE;
}
Esempio n. 25
0
static gboolean
gst_rtp_dtmf_src_negotiate (GstBaseSrc * basesrc)
{
  GstCaps *srccaps, *peercaps;
  GstRTPDTMFSrc *dtmfsrc = GST_RTP_DTMF_SRC (basesrc);
  gboolean ret;

  /* fill in the defaults, there properties cannot be negotiated. */
  srccaps = gst_caps_new_simple ("application/x-rtp",
      "media", G_TYPE_STRING, "audio",
      "encoding-name", G_TYPE_STRING, "TELEPHONE-EVENT", NULL);

  /* the peer caps can override some of the defaults */
  peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
  if (peercaps == NULL) {
    /* no peer caps, just add the other properties */
    gst_caps_set_simple (srccaps,
        "payload", G_TYPE_INT, dtmfsrc->pt,
        "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc,
        "timestamp-offset", G_TYPE_UINT, dtmfsrc->ts_base,
        "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate,
        "seqnum-offset", G_TYPE_UINT, dtmfsrc->seqnum_base, NULL);

    GST_DEBUG_OBJECT (dtmfsrc, "no peer caps: %" GST_PTR_FORMAT, srccaps);
  } else {
    GstCaps *temp;
    GstStructure *s;
    const GValue *value;
    gint pt;
    gint clock_rate;

    /* peer provides caps we can use to fixate, intersect. This always returns a
     * writable caps. */
    temp = gst_caps_intersect (srccaps, peercaps);
    gst_caps_unref (srccaps);
    gst_caps_unref (peercaps);

    if (!temp) {
      GST_DEBUG_OBJECT (dtmfsrc, "Could not get intersection with peer caps");
      return FALSE;
    }

    if (gst_caps_is_empty (temp)) {
      GST_DEBUG_OBJECT (dtmfsrc, "Intersection with peer caps is empty");
      gst_caps_unref (temp);
      return FALSE;
    }

    /* now fixate, start by taking the first caps */
    temp = gst_caps_truncate (temp);
    temp = gst_caps_make_writable (temp);
    srccaps = temp;

    /* get first structure */
    s = gst_caps_get_structure (srccaps, 0);

    if (gst_structure_get_int (s, "payload", &pt)) {
      /* use peer pt */
      dtmfsrc->pt = pt;
      GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
    } else {
      if (gst_structure_has_field (s, "payload")) {
        /* can only fixate if there is a field */
        gst_structure_fixate_field_nearest_int (s, "payload", dtmfsrc->pt);
        gst_structure_get_int (s, "payload", &pt);
        GST_LOG_OBJECT (dtmfsrc, "using peer pt %d", pt);
      } else {
        /* no pt field, use the internal pt */
        pt = dtmfsrc->pt;
        gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
        GST_LOG_OBJECT (dtmfsrc, "using internal pt %d", pt);
      }
    }

    if (gst_structure_get_int (s, "clock-rate", &clock_rate)) {
      dtmfsrc->clock_rate = clock_rate;
      GST_LOG_OBJECT (dtmfsrc, "using clock-rate from caps %d",
          dtmfsrc->clock_rate);
    } else {
      GST_LOG_OBJECT (dtmfsrc, "using existing clock-rate %d",
          dtmfsrc->clock_rate);
    }
    gst_structure_set (s, "clock-rate", G_TYPE_INT, dtmfsrc->clock_rate, NULL);


    if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "ssrc");
      dtmfsrc->current_ssrc = g_value_get_uint (value);
      GST_LOG_OBJECT (dtmfsrc, "using peer ssrc %08x", dtmfsrc->current_ssrc);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "ssrc", G_TYPE_UINT, dtmfsrc->current_ssrc, NULL);
      GST_LOG_OBJECT (dtmfsrc, "using internal ssrc %08x",
          dtmfsrc->current_ssrc);
    }

    if (gst_structure_has_field_typed (s, "timestamp-offset", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "timestamp-offset");
      dtmfsrc->ts_base = g_value_get_uint (value);
      GST_LOG_OBJECT (dtmfsrc, "using peer timestamp-offset %u",
          dtmfsrc->ts_base);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "timestamp-offset", G_TYPE_UINT, dtmfsrc->ts_base,
          NULL);
      GST_LOG_OBJECT (dtmfsrc, "using internal timestamp-offset %u",
          dtmfsrc->ts_base);
    }
    if (gst_structure_has_field_typed (s, "seqnum-offset", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "seqnum-offset");
      dtmfsrc->seqnum_base = g_value_get_uint (value);
      GST_LOG_OBJECT (dtmfsrc, "using peer seqnum-offset %u",
          dtmfsrc->seqnum_base);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "seqnum-offset", G_TYPE_UINT, dtmfsrc->seqnum_base,
          NULL);
      GST_LOG_OBJECT (dtmfsrc, "using internal seqnum-offset %u",
          dtmfsrc->seqnum_base);
    }

    if (gst_structure_has_field_typed (s, "ptime", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "ptime");
      dtmfsrc->ptime = g_value_get_uint (value);
      GST_LOG_OBJECT (dtmfsrc, "using peer ptime %u", dtmfsrc->ptime);
    } else if (gst_structure_has_field_typed (s, "maxptime", G_TYPE_UINT)) {
      value = gst_structure_get_value (s, "maxptime");
      dtmfsrc->ptime = g_value_get_uint (value);
      GST_LOG_OBJECT (dtmfsrc, "using peer maxptime as ptime %u",
          dtmfsrc->ptime);
    } else {
      /* FIXME, fixate_nearest_uint would be even better */
      gst_structure_set (s, "ptime", G_TYPE_UINT, dtmfsrc->ptime, NULL);
      GST_LOG_OBJECT (dtmfsrc, "using internal ptime %u", dtmfsrc->ptime);
    }


    GST_DEBUG_OBJECT (dtmfsrc, "with peer caps: %" GST_PTR_FORMAT, srccaps);
  }

  ret = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), srccaps);
  gst_caps_unref (srccaps);

  dtmfsrc->dirty = FALSE;

  return ret;

}
Esempio n. 26
0
static gboolean
gst_vtdec_negotiate (GstVideoDecoder * decoder)
{
  GstVideoCodecState *output_state = NULL;
  GstCaps *peercaps = NULL, *caps = NULL, *templcaps = NULL, *prevcaps = NULL;
  GstVideoFormat format;
  GstStructure *structure;
  const gchar *s;
  GstVtdec *vtdec;
  OSStatus err = noErr;
  GstCapsFeatures *features = NULL;
  gboolean output_textures;

  vtdec = GST_VTDEC (decoder);
  if (vtdec->session)
    gst_vtdec_push_frames_if_needed (vtdec, TRUE, FALSE);

  output_state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (vtdec));
  if (output_state) {
    prevcaps = gst_caps_ref (output_state->caps);
    gst_video_codec_state_unref (output_state);
  }

  peercaps = gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec), NULL);
  if (prevcaps && gst_caps_can_intersect (prevcaps, peercaps)) {
    /* The hardware decoder can become (temporarily) unavailable across
     * VTDecompressionSessionCreate/Destroy calls. So if the currently configured
     * caps are still accepted by downstream we keep them so we don't have to
     * destroy and recreate the session.
     */
    GST_INFO_OBJECT (vtdec,
        "current and peer caps are compatible, keeping current caps");
    caps = gst_caps_ref (prevcaps);
  } else {
    templcaps =
        gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (decoder));
    caps =
        gst_caps_intersect_full (peercaps, templcaps, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (templcaps);
  }
  gst_caps_unref (peercaps);

  caps = gst_caps_truncate (gst_caps_make_writable (caps));
  structure = gst_caps_get_structure (caps, 0);
  s = gst_structure_get_string (structure, "format");
  format = gst_video_format_from_string (s);
  features = gst_caps_get_features (caps, 0);
  if (features)
    features = gst_caps_features_copy (features);

  output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (vtdec),
      format, vtdec->video_info.width, vtdec->video_info.height,
      vtdec->input_state);
  output_state->caps = gst_video_info_to_caps (&output_state->info);
  if (features) {
    gst_caps_set_features (output_state->caps, 0, features);
    output_textures =
        gst_caps_features_contains (features,
        GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
    if (output_textures)
      gst_caps_set_simple (output_state->caps, "texture-target", G_TYPE_STRING,
#if !HAVE_IOS
          GST_GL_TEXTURE_TARGET_RECTANGLE_STR,
#else
          GST_GL_TEXTURE_TARGET_2D_STR,
#endif
          NULL);
  }
  gst_caps_unref (caps);

  if (!prevcaps || !gst_caps_is_equal (prevcaps, output_state->caps)) {
    gboolean renegotiating = vtdec->session != NULL;

    GST_INFO_OBJECT (vtdec,
        "negotiated output format %" GST_PTR_FORMAT " previous %"
        GST_PTR_FORMAT, output_state->caps, prevcaps);

    if (vtdec->session)
      gst_vtdec_invalidate_session (vtdec);

    err = gst_vtdec_create_session (vtdec, format, TRUE);
    if (err == noErr) {
      GST_INFO_OBJECT (vtdec, "using hardware decoder");
    } else if (err == kVTVideoDecoderNotAvailableNowErr && renegotiating) {
      GST_WARNING_OBJECT (vtdec, "hw decoder not available anymore");
      err = gst_vtdec_create_session (vtdec, format, FALSE);
    }

    if (err != noErr) {
      GST_ELEMENT_ERROR (vtdec, RESOURCE, FAILED, (NULL),
          ("VTDecompressionSessionCreate returned %d", (int) err));
    }
  }

  if (vtdec->texture_cache != NULL && !output_textures) {
    gst_video_texture_cache_free (vtdec->texture_cache);
    vtdec->texture_cache = NULL;
  }

  if (err == noErr && output_textures) {
    /* call this regardless of whether caps have changed or not since a new
     * local context could have become available
     */
    gst_gl_context_helper_ensure_context (vtdec->ctxh);

    GST_INFO_OBJECT (vtdec, "pushing textures, context %p old context %p",
        vtdec->ctxh->context,
        vtdec->texture_cache ? vtdec->texture_cache->ctx : NULL);

    if (vtdec->texture_cache
        && vtdec->texture_cache->ctx != vtdec->ctxh->context) {
      gst_video_texture_cache_free (vtdec->texture_cache);
      vtdec->texture_cache = NULL;
    }
    if (!vtdec->texture_cache)
      setup_texture_cache (vtdec, vtdec->ctxh->context);
  }

  if (prevcaps)
    gst_caps_unref (prevcaps);

  if (err != noErr)
    return FALSE;

  return GST_VIDEO_DECODER_CLASS (gst_vtdec_parent_class)->negotiate (decoder);
}
Esempio n. 27
0
static gboolean
gst_v4l2src_negotiate (GstBaseSrc * basesrc)
{
  GstV4l2Src *v4l2src;
  GstV4l2Object *obj;
  GstCaps *thiscaps;
  GstCaps *caps = NULL;
  GstCaps *peercaps = NULL;
  gboolean result = FALSE;

  v4l2src = GST_V4L2SRC (basesrc);
  obj = v4l2src->v4l2object;

  /* We don't allow renegotiation, just return TRUE in that case */
  if (GST_V4L2_IS_ACTIVE (obj))
    return TRUE;

  /* first see what is possible on our source pad */
  thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
  GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
  LOG_CAPS (basesrc, thiscaps);

  /* nothing or anything is allowed, we're done */
  if (thiscaps == NULL || gst_caps_is_any (thiscaps))
    goto no_nego_needed;

  /* get the peer caps without a filter as we'll filter ourselves later on */
  peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
  GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
  LOG_CAPS (basesrc, peercaps);
  if (peercaps && !gst_caps_is_any (peercaps)) {
    GstCaps *icaps = NULL;
    int i;

    /* Prefer the first caps we are compatible with that the peer proposed */
    for (i = 0; i < gst_caps_get_size (peercaps); i++) {
      /* get intersection */
      GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);

      GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
      LOG_CAPS (basesrc, ipcaps);

      icaps = gst_caps_intersect (thiscaps, ipcaps);
      gst_caps_unref (ipcaps);

      if (!gst_caps_is_empty (icaps))
        break;

      gst_caps_unref (icaps);
      icaps = NULL;
    }

    GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
    LOG_CAPS (basesrc, icaps);
    if (icaps) {
      /* If there are multiple intersections pick the one with the smallest
       * resolution strictly bigger then the first peer caps */
      if (gst_caps_get_size (icaps) > 1) {
        GstStructure *s = gst_caps_get_structure (peercaps, 0);
        int best = 0;
        int twidth, theight;
        int width = G_MAXINT, height = G_MAXINT;

        if (gst_structure_get_int (s, "width", &twidth)
            && gst_structure_get_int (s, "height", &theight)) {

          /* Walk the structure backwards to get the first entry of the
           * smallest resolution bigger (or equal to) the preferred resolution)
           */
          for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
            GstStructure *is = gst_caps_get_structure (icaps, i);
            int w, h;

            if (gst_structure_get_int (is, "width", &w)
                && gst_structure_get_int (is, "height", &h)) {
              if (w >= twidth && w <= width && h >= theight && h <= height) {
                width = w;
                height = h;
                best = i;
              }
            }
          }
        }

        caps = gst_caps_copy_nth (icaps, best);
        gst_caps_unref (icaps);
      } else {
        caps = icaps;
      }
    }
    gst_caps_unref (thiscaps);
  } else {
    /* no peer or peer have ANY caps, work with our own caps then */
    caps = thiscaps;
  }
  if (peercaps)
    gst_caps_unref (peercaps);
  if (caps) {
    caps = gst_caps_truncate (caps);

    /* now fixate */
    if (!gst_caps_is_empty (caps)) {
      caps = gst_v4l2src_fixate (basesrc, caps);
      GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
      LOG_CAPS (basesrc, caps);

      if (gst_caps_is_any (caps)) {
        /* hmm, still anything, so element can do anything and
         * nego is not needed */
        result = TRUE;
      } else if (gst_caps_is_fixed (caps)) {
        /* yay, fixed caps, use those then */
        result = gst_base_src_set_caps (basesrc, caps);
      }
    }
    gst_caps_unref (caps);
  }
  return result;

no_nego_needed:
  {
    GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
    if (thiscaps)
      gst_caps_unref (thiscaps);
    return TRUE;
  }
}
Esempio n. 28
0
static GstFlowReturn
gst_rsvg_decode_image (GstRsvgDec * rsvg, const guint8 * data, guint size,
    GstBuffer ** buffer)
{
  GstFlowReturn ret = GST_FLOW_OK;
  cairo_t *cr;
  cairo_surface_t *surface;
  RsvgHandle *handle;
  GError *error = NULL;
  RsvgDimensionData dimension;
  gdouble scalex, scaley;

  GST_LOG_OBJECT (rsvg, "parsing svg");

  handle = rsvg_handle_new_from_data (data, size, &error);
  if (!handle) {
    GST_ERROR_OBJECT (rsvg, "Failed to parse SVG image: %s", error->message);
    g_error_free (error);
    return GST_FLOW_ERROR;
  }

  rsvg_handle_get_dimensions (handle, &dimension);
  if (rsvg->width != dimension.width || rsvg->height != dimension.height) {
    GstCaps *caps1, *caps2, *caps3;
    GstStructure *s;

    GST_LOG_OBJECT (rsvg, "resolution changed, updating caps");

    caps1 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad));
    caps2 = gst_pad_peer_get_caps (rsvg->srcpad);
    if (caps2) {
      caps3 = gst_caps_intersect (caps1, caps2);
      gst_caps_unref (caps1);
      gst_caps_unref (caps2);
      caps1 = caps3;
      caps3 = NULL;
    }

    if (gst_caps_is_empty (caps1)) {
      GST_ERROR_OBJECT (rsvg, "Unable to negotiate a format");
      gst_caps_unref (caps1);
      g_object_unref (handle);
      return GST_FLOW_NOT_NEGOTIATED;
    }

    caps2 = gst_caps_copy (gst_pad_get_pad_template_caps (rsvg->srcpad));
    s = gst_caps_get_structure (caps2, 0);
    gst_structure_set (s, "width", G_TYPE_INT, dimension.width, "height",
        G_TYPE_INT, dimension.height, "framerate", GST_TYPE_FRACTION, 0, 1,
        NULL);
    caps3 = gst_caps_intersect (caps1, caps2);
    if (!gst_caps_is_empty (caps3)) {
      gst_caps_truncate (caps3);
      gst_pad_set_caps (rsvg->srcpad, caps3);
      gst_caps_unref (caps1);
      gst_caps_unref (caps2);
      gst_caps_unref (caps3);
      rsvg->width = dimension.width;
      rsvg->height = dimension.height;
    } else {
      gst_caps_unref (caps2);
      gst_caps_unref (caps3);
      gst_caps_truncate (caps1);

      s = gst_caps_get_structure (caps1, 0);
      gst_structure_set (s, "framerate", GST_TYPE_FRACTION, 0, 1, NULL);

      if (!gst_caps_is_fixed (caps1)
          && (!gst_structure_fixate_field_nearest_int (s, "width",
                  dimension.width)
              || !gst_structure_fixate_field_nearest_int (s, "height",
                  dimension.height))) {
        g_object_unref (handle);
        GST_ERROR_OBJECT (rsvg, "Failed to fixate caps");
        return GST_FLOW_NOT_NEGOTIATED;
      }
      gst_pad_set_caps (rsvg->srcpad, caps1);
      gst_structure_get_int (s, "width", &rsvg->width);
      gst_structure_get_int (s, "height", &rsvg->height);
      gst_caps_unref (caps1);
    }
  }

  if ((ret = gst_pad_alloc_buffer_and_set_caps (rsvg->srcpad,
              GST_BUFFER_OFFSET_NONE,
              rsvg->width * rsvg->height * 4,
              GST_PAD_CAPS (rsvg->srcpad), buffer)) != GST_FLOW_OK) {
    g_object_unref (handle);
    GST_ERROR_OBJECT (rsvg, "Buffer allocation failed %s",
        gst_flow_get_name (ret));
    return ret;
  }

  GST_LOG_OBJECT (rsvg, "render image at %d x %d", rsvg->height, rsvg->width);

  surface =
      cairo_image_surface_create_for_data (GST_BUFFER_DATA (*buffer),
      CAIRO_FORMAT_ARGB32, rsvg->width, rsvg->height, rsvg->width * 4);

  cr = cairo_create (surface);
  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
  cairo_paint (cr);
  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);

  scalex = scaley = 1.0;
  if (rsvg->width != dimension.width) {
    scalex = ((gdouble) rsvg->width) / ((gdouble) dimension.width);
  }
  if (rsvg->height != dimension.height) {
    scaley = ((gdouble) rsvg->height) / ((gdouble) dimension.height);
  }
  cairo_scale (cr, scalex, scaley);
  rsvg_handle_render_cairo (handle, cr);

  g_object_unref (handle);
  cairo_destroy (cr);
  cairo_surface_destroy (surface);

  /* Now unpremultiply Cairo's ARGB to match GStreamer's */
  gst_rsvg_decode_unpremultiply (GST_BUFFER_DATA (*buffer), rsvg->width,
      rsvg->height);

  return ret;
}
static gboolean
gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
{
  GstCaps *caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
  GstStructure *s;
  GstAudioInfo info;

  if (caps) {
    gint rate = dec->sample_rate, channels = dec->n_channels;
    GstCaps *constraint, *inter;

    constraint = gst_caps_from_string ("audio/x-raw");
    if (dec->n_channels <= 2) { /* including 0 */
      gst_caps_set_simple (constraint, "channels", GST_TYPE_INT_RANGE, 1, 2,
          NULL);
    } else {
      gst_caps_set_simple (constraint, "channels", G_TYPE_INT, dec->n_channels,
          NULL);
    }

    inter = gst_caps_intersect (caps, constraint);
    gst_caps_unref (constraint);

    if (gst_caps_is_empty (inter)) {
      GST_DEBUG_OBJECT (dec, "Empty intersection, failed to negotiate");
      gst_caps_unref (inter);
      gst_caps_unref (caps);
      return FALSE;
    }

    inter = gst_caps_truncate (inter);
    s = gst_caps_get_structure (inter, 0);
    rate = dec->sample_rate > 0 ? dec->sample_rate : 48000;
    gst_structure_fixate_field_nearest_int (s, "rate", dec->sample_rate);
    gst_structure_get_int (s, "rate", &rate);
    channels = dec->n_channels > 0 ? dec->n_channels : 2;
    gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
    gst_structure_get_int (s, "channels", &channels);

    gst_caps_unref (inter);

    dec->sample_rate = rate;
    dec->n_channels = channels;
    gst_caps_unref (caps);
  }

  if (dec->n_channels == 0) {
    GST_DEBUG_OBJECT (dec, "Using a default of 2 channels");
    dec->n_channels = 2;
    pos = NULL;
  }

  if (dec->sample_rate == 0) {
    GST_DEBUG_OBJECT (dec, "Using a default of 48kHz sample rate");
    dec->sample_rate = 48000;
  }

  GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
      dec->sample_rate);

  /* pass valid order to audio info */
  if (pos) {
    memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
    gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
  }

  /* set up source format */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16,
      dec->sample_rate, dec->n_channels, pos ? dec->opus_pos : NULL);
  gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info);

  /* but we still need the opus order for later reordering */
  if (pos) {
    memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
  } else {
    dec->opus_pos[0] = GST_AUDIO_CHANNEL_POSITION_INVALID;
  }

  dec->info = info;

  return TRUE;
}
Esempio n. 30
0
static gboolean
gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
{
  GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
  GstCaps *other_caps;
  GstCaps *allowed_caps;
  GstCaps *icaps;
  gsize frame_size;
  GstFFMpegAudEncClass *oclass =
      (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);

  /* close old session */
  if (ffmpegaudenc->opened) {
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    ffmpegaudenc->opened = FALSE;
  }

  /* if we set it in _getcaps we should set it also in _link */
  ffmpegaudenc->context->strict_std_compliance = -1;

  /* user defined properties */
  if (ffmpegaudenc->bitrate > 0) {
    GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d",
        ffmpegaudenc->bitrate);
    ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate;
    ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate;
  } else {
    GST_INFO_OBJECT (ffmpegaudenc, "Using avcontext default bitrate %d",
        ffmpegaudenc->context->bit_rate);
  }

  /* RTP payload used for GOB production (for Asterisk) */
  if (ffmpegaudenc->rtp_payload_size) {
    ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size;
  }

  /* some other defaults */
  ffmpegaudenc->context->rc_strategy = 2;
  ffmpegaudenc->context->b_frame_strategy = 0;
  ffmpegaudenc->context->coder_type = 0;
  ffmpegaudenc->context->context_model = 0;
  ffmpegaudenc->context->scenechange_threshold = 0;
  ffmpegaudenc->context->inter_threshold = 0;

  /* fetch pix_fmt and so on */
  gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
  if (!ffmpegaudenc->context->time_base.den) {
    ffmpegaudenc->context->time_base.den = GST_AUDIO_INFO_RATE (info);
    ffmpegaudenc->context->time_base.num = 1;
    ffmpegaudenc->context->ticks_per_frame = 1;
  }

  if (ffmpegaudenc->context->channel_layout) {
    gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout,
        ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout);
    ffmpegaudenc->needs_reorder =
        (memcmp (ffmpegaudenc->ffmpeg_layout, info->position,
            sizeof (GstAudioChannelPosition) *
            ffmpegaudenc->context->channels) != 0);
  }

  /* open codec */
  if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
    if (ffmpegaudenc->context->priv_data)
      gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
        oclass->in_plugin->name);
    return FALSE;
  }

  /* some codecs support more than one format, first auto-choose one */
  GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ...");
  allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
  if (!allowed_caps) {
    GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps");
    /* we need to copy because get_allowed_caps returns a ref, and
     * get_pad_template_caps doesn't */
    allowed_caps =
        gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
  }
  GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
  gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
      oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context);

  /* try to set this caps on the other side */
  other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id,
      ffmpegaudenc->context, TRUE);

  if (!other_caps) {
    gst_caps_unref (allowed_caps);
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    GST_DEBUG ("Unsupported codec - no caps found");
    return FALSE;
  }

  icaps = gst_caps_intersect (allowed_caps, other_caps);
  gst_caps_unref (allowed_caps);
  gst_caps_unref (other_caps);
  if (gst_caps_is_empty (icaps)) {
    gst_caps_unref (icaps);
    return FALSE;
  }
  icaps = gst_caps_truncate (icaps);

  if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
          icaps)) {
    gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
    gst_caps_unref (icaps);
    return FALSE;
  }
  gst_caps_unref (icaps);

  frame_size = ffmpegaudenc->context->frame_size;
  if (frame_size > 1) {
    gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
        frame_size);
    gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
        frame_size);
    gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1);
  } else {
    gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
        0);
    gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
        0);
    gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0);
  }

  /* success! */
  ffmpegaudenc->opened = TRUE;

  return TRUE;
}