예제 #1
0
pa_channel_map *
gst_pulse_gst_to_channel_map (pa_channel_map * map,
    const GstRingBufferSpec * spec)
{
  int i;
  GstAudioChannelPosition *pos;

  pa_channel_map_init (map);

  if (!(pos =
          gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps,
                  0)))) {
    return NULL;
  }

  for (i = 0; i < spec->channels; i++) {
    if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) {
      /* no valid mappings for these channels */
      g_free (pos);
      return NULL;
    } else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM)
      map->map[i] = gst_pos_to_pa[pos[i]];
    else
      map->map[i] = PA_CHANNEL_POSITION_INVALID;
  }

  g_free (pos);
  map->channels = spec->channels;

  if (!pa_channel_map_valid (map)) {
    return NULL;
  }

  return map;
}
예제 #2
0
static gboolean
gst_wavpack_enc_sink_set_caps (GstPad * pad, GstCaps * caps)
{
  GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad));
  GstStructure *structure = gst_caps_get_structure (caps, 0);
  GstAudioChannelPosition *pos;

  if (!gst_structure_get_int (structure, "channels", &enc->channels) ||
      !gst_structure_get_int (structure, "rate", &enc->samplerate) ||
      !gst_structure_get_int (structure, "depth", &enc->depth)) {
    GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
        ("got invalid caps: %" GST_PTR_FORMAT, caps));
    gst_object_unref (enc);
    return FALSE;
  }

  pos = gst_audio_get_channel_positions (structure);
  /* If one channel is NONE they'll be all undefined */
  if (pos != NULL && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
    g_free (pos);
    pos = NULL;
  }

  if (pos == NULL) {
    GST_ELEMENT_ERROR (enc, STREAM, FORMAT, (NULL),
        ("input has no valid channel layout"));

    gst_object_unref (enc);
    return FALSE;
  }

  enc->channel_mask =
      gst_wavpack_get_channel_mask_from_positions (pos, enc->channels);
  enc->need_channel_remap =
      gst_wavpack_set_channel_mapping (pos, enc->channels,
      enc->channel_mapping);
  g_free (pos);

  /* set fixed src pad caps now that we know what we will get */
  caps = gst_caps_new_simple ("audio/x-wavpack",
      "channels", G_TYPE_INT, enc->channels,
      "rate", G_TYPE_INT, enc->samplerate,
      "width", G_TYPE_INT, enc->depth, "framed", G_TYPE_BOOLEAN, TRUE, NULL);

  if (!gst_wavpack_set_channel_layout (caps, enc->channel_mask))
    GST_WARNING_OBJECT (enc, "setting channel layout failed");

  if (!gst_pad_set_caps (enc->srcpad, caps)) {
    GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL),
        ("setting caps failed: %" GST_PTR_FORMAT, caps));
    gst_caps_unref (caps);
    gst_object_unref (enc);
    return FALSE;
  }
  gst_pad_use_fixed_caps (enc->srcpad);

  gst_caps_unref (caps);
  gst_object_unref (enc);
  return TRUE;
}
예제 #3
0
GstFlowReturn AudioFileReader::handleBuffer(GstAppSink* sink)
{
    GstBuffer* buffer = gst_app_sink_pull_buffer(sink);
    if (!buffer)
        return GST_FLOW_ERROR;

    GstCaps* caps = gst_buffer_get_caps(buffer);
    GstStructure* structure = gst_caps_get_structure(caps, 0);

    gint channels = 0;
    if (!gst_structure_get_int(structure, "channels", &channels) || !channels) {
        gst_caps_unref(caps);
        gst_buffer_unref(buffer);
        return GST_FLOW_ERROR;
    }

    gint sampleRate = 0;
    if (!gst_structure_get_int(structure, "rate", &sampleRate) || !sampleRate) {
        gst_caps_unref(caps);
        gst_buffer_unref(buffer);
        return GST_FLOW_ERROR;
    }

    gint width = 0;
    if (!gst_structure_get_int(structure, "width", &width) || !width) {
        gst_caps_unref(caps);
        gst_buffer_unref(buffer);
        return GST_FLOW_ERROR;
    }

    GstClockTime duration = (static_cast<guint64>(GST_BUFFER_SIZE(buffer)) * 8 * GST_SECOND) / (sampleRate * channels * width);
    int frames = GST_CLOCK_TIME_TO_FRAMES(duration, sampleRate);

    // Check the first audio channel. The buffer is supposed to store
    // data of a single channel anyway.
    GstAudioChannelPosition* positions = gst_audio_get_channel_positions(structure);
    switch (positions[0]) {
    case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
        gst_buffer_list_iterator_add(m_frontLeftBuffersIterator, buffer);
        m_channelSize += frames;
        break;
    case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
        gst_buffer_list_iterator_add(m_frontRightBuffersIterator, buffer);
        break;
    default:
        gst_buffer_unref(buffer);
        break;
    }

    g_free(positions);
    gst_caps_unref(caps);
    return GST_FLOW_OK;
}
예제 #4
0
static gboolean
gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps)
{
    GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad));
    GstStructure *structure = gst_caps_get_structure (caps, 0);

    /* Check if we can set the caps here already */
    if (gst_structure_get_int (structure, "channels", &dec->channels) &&
            gst_structure_get_int (structure, "rate", &dec->sample_rate) &&
            gst_structure_get_int (structure, "width", &dec->depth)) {
        GstCaps *caps;
        GstAudioChannelPosition *pos;

        caps = gst_caps_new_simple ("audio/x-raw-int",
                                    "rate", G_TYPE_INT, dec->sample_rate,
                                    "channels", G_TYPE_INT, dec->channels,
                                    "depth", G_TYPE_INT, dec->depth,
                                    "width", G_TYPE_INT, 32,
                                    "endianness", G_TYPE_INT, G_BYTE_ORDER,
                                    "signed", G_TYPE_BOOLEAN, TRUE, NULL);

        /* If we already have the channel layout set from upstream
         * take this */
        if (gst_structure_has_field (structure, "channel-positions")) {
            pos = gst_audio_get_channel_positions (structure);
            if (pos != NULL && dec->channels > 2) {
                GstStructure *new_str = gst_caps_get_structure (caps, 0);

                gst_audio_set_channel_positions (new_str, pos);
                dec->channel_mask =
                    gst_wavpack_get_channel_mask_from_positions (pos, dec->channels);
            }

            if (pos != NULL)
                g_free (pos);
        }

        GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);

        /* should always succeed */
        gst_pad_set_caps (dec->srcpad, caps);
        gst_caps_unref (caps);

        /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something
         * is decoded or after the format has changed */
        gst_wavpack_dec_post_tags (dec);
    }

    gst_object_unref (dec);

    return TRUE;
}
예제 #5
0
static gboolean query_data(struct input_handle* ih) {
  GstBuffer *preroll;
  GstCaps *src_caps;
  GstStructure *s;
  int i;

  ih->n_channels = 0;
  ih->sample_rate = 0;
  ih->channel_positions = NULL;

  preroll = gst_app_sink_pull_preroll(GST_APP_SINK(ih->appsink));
  src_caps = gst_buffer_get_caps(preroll);

  s = gst_caps_get_structure(src_caps, 0);
  gst_structure_get_int(s, "rate", &(ih->sample_rate));
  gst_structure_get_int(s, "channels", &(ih->n_channels));
  if (!ih->sample_rate || !ih->n_channels) {
    gst_caps_unref(src_caps);
    gst_buffer_unref(preroll);
    return FALSE;
  }

  ih->channel_positions = gst_audio_get_channel_positions(s);
  if (verbose) {
    if (ih->channel_positions) {
      for (i = 0; i < ih->n_channels; ++i) {
        printf("Channel %d: %d\n", i, ih->channel_positions[i]);
      }
    }
    g_print ("%d channels @ %d Hz\n", ih->n_channels, ih->sample_rate);
  }

  gst_caps_unref(src_caps);
  gst_buffer_unref(preroll);

  return TRUE;
}
예제 #6
0
static gboolean
gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
{
  GstDeinterleave *self;

  GstCaps *srccaps;

  GstStructure *s;

  self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps);

  if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
    gint new_channels, i;

    GstAudioChannelPosition *pos;

    gboolean same_layout = TRUE;

    s = gst_caps_get_structure (caps, 0);

    /* We allow caps changes as long as the number of channels doesn't change
     * and the channel positions stay the same. _getcaps() should've cared
     * for this already but better be safe.
     */
    if (!gst_structure_get_int (s, "channels", &new_channels) ||
        new_channels != self->channels ||
        !gst_deinterleave_set_process_function (self, caps))
      goto cannot_change_caps;

    /* Now check the channel positions. If we had no channel positions
     * and get them or the other way around things have changed.
     * If we had channel positions and get different ones things have
     * changed too of course
     */
    pos = gst_audio_get_channel_positions (s);
    if ((pos && !self->pos) || (!pos && self->pos))
      goto cannot_change_caps;

    if (pos) {
      for (i = 0; i < self->channels; i++) {
        if (self->pos[i] != pos[i]) {
          same_layout = FALSE;
          break;
        }
      }
      g_free (pos);
      if (!same_layout)
        goto cannot_change_caps;
    }

  } else {
    s = gst_caps_get_structure (caps, 0);

    if (!gst_structure_get_int (s, "channels", &self->channels))
      goto no_channels;

    if (!gst_deinterleave_set_process_function (self, caps))
      goto unsupported_caps;

    self->pos = gst_audio_get_channel_positions (s);
  }

  gst_caps_replace (&self->sinkcaps, caps);

  /* Get srcpad caps */
  srccaps = gst_caps_copy (caps);
  s = gst_caps_get_structure (srccaps, 0);
  gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
  gst_structure_remove_field (s, "channel-positions");

  /* If we already have pads, update the caps otherwise
   * add new pads */
  if (self->srcpads) {
    gst_deinterleave_set_pads_caps (self, srccaps);
  } else {
    gst_deinterleave_add_new_pads (self, srccaps);
  }

  gst_caps_unref (srccaps);
  gst_object_unref (self);

  return TRUE;

cannot_change_caps:
  {
    GST_ERROR_OBJECT (self, "can't set new caps: %" GST_PTR_FORMAT, caps);
    gst_object_unref (self);
    return FALSE;
  }
unsupported_caps:
  {
    GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps);
    gst_object_unref (self);
    return FALSE;
  }
no_channels:
  {
    GST_ERROR_OBJECT (self, "invalid caps");
    gst_object_unref (self);
    return FALSE;
  }
}
static gboolean
gst_rtp_g722_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
{
  GstRtpG722Pay *rtpg722pay;
  GstStructure *structure;
  gint rate, channels, clock_rate;
  gboolean res;
  gchar *params;
#if 0
  GstAudioChannelPosition *pos;
  const GstRTPChannelOrder *order;
#endif
  GstRTPBaseAudioPayload *rtpbaseaudiopayload;

  rtpbaseaudiopayload = GST_RTP_BASE_AUDIO_PAYLOAD (basepayload);
  rtpg722pay = GST_RTP_G722_PAY (basepayload);

  structure = gst_caps_get_structure (caps, 0);

  /* first parse input caps */
  if (!gst_structure_get_int (structure, "rate", &rate))
    goto no_rate;

  if (!gst_structure_get_int (structure, "channels", &channels))
    goto no_channels;

  /* FIXME: Do something with the channel positions */
#if 0
  /* get the channel order */
  pos = gst_audio_get_channel_positions (structure);
  if (pos)
    order = gst_rtp_channels_get_by_pos (channels, pos);
  else
    order = NULL;
#endif

  /* Clock rate is always 8000 Hz for G722 according to
   * RFC 3551 although the sampling rate is 16000 Hz */
  clock_rate = 8000;

  gst_rtp_base_payload_set_options (basepayload, "audio",
      basepayload->pt != GST_RTP_PAYLOAD_G722, "G722", clock_rate);
  params = g_strdup_printf ("%d", channels);

#if 0
  if (!order && channels > 2) {
    GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE,
        (NULL), ("Unknown channel order for %d channels", channels));
  }

  if (order && order->name) {
    res = gst_rtp_base_payload_set_outcaps (basepayload,
        "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
        channels, "channel-order", G_TYPE_STRING, order->name, NULL);
  } else {
#endif
    res = gst_rtp_base_payload_set_outcaps (basepayload,
        "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
        channels, NULL);
#if 0
  }
#endif

  g_free (params);
#if 0
  g_free (pos);
#endif

  rtpg722pay->rate = rate;
  rtpg722pay->channels = channels;

  /* bits-per-sample is 4 * channels for G722, but as the RTP clock runs at
   * half speed (8 instead of 16 khz), pretend it's 8 bits per sample
   * channels. */
  gst_rtp_base_audio_payload_set_samplebits_options (rtpbaseaudiopayload,
      8 * rtpg722pay->channels);

  return res;

  /* ERRORS */
no_rate:
  {
    GST_DEBUG_OBJECT (rtpg722pay, "no rate given");
    return FALSE;
  }
no_channels:
  {
    GST_DEBUG_OBJECT (rtpg722pay, "no channels given");
    return FALSE;
  }
}
예제 #8
0
static gboolean
gst_rtp_g722_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
{
    GstRtpG722Pay *rtpg722pay;
    GstStructure *structure;
    gint rate, channels, clock_rate;
    gboolean res;
    gchar *params;
    GstAudioChannelPosition *pos;
    const GstRTPChannelOrder *order;
    GstBaseRTPAudioPayload *basertpaudiopayload;

    basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (basepayload);
    rtpg722pay = GST_RTP_G722_PAY (basepayload);

    structure = gst_caps_get_structure (caps, 0);

    /* first parse input caps */
    if (!gst_structure_get_int (structure, "rate", &rate))
        goto no_rate;

    if (!gst_structure_get_int (structure, "channels", &channels))
        goto no_channels;

    /* get the channel order */
    pos = gst_audio_get_channel_positions (structure);
    if (pos)
        order = gst_rtp_channels_get_by_pos (channels, pos);
    else
        order = NULL;

    /* Clock rate is always 8000 Hz for G722 according to
     * RFC 3551 although the sampling rate is 16000 Hz */
    clock_rate = 8000;

    gst_basertppayload_set_options (basepayload, "audio", TRUE, "G722",
                                    clock_rate);
    params = g_strdup_printf ("%d", channels);

    if (!order && channels > 2) {
        GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE,
                             (NULL), ("Unknown channel order for %d channels", channels));
    }

    if (order && order->name) {
        res = gst_basertppayload_set_outcaps (basepayload,
                                              "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
                                              channels, "channel-order", G_TYPE_STRING, order->name, NULL);
    } else {
        res = gst_basertppayload_set_outcaps (basepayload,
                                              "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
                                              channels, NULL);
    }

    g_free (params);
    g_free (pos);

    rtpg722pay->rate = rate;
    rtpg722pay->channels = channels;

    /* octet-per-sample is 1 * channels for G722 */
    gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload,
            4 * rtpg722pay->channels);

    return res;

    /* ERRORS */
no_rate:
    {
        GST_DEBUG_OBJECT (rtpg722pay, "no rate given");
        return FALSE;
    }
no_channels:
    {
        GST_DEBUG_OBJECT (rtpg722pay, "no channels given");
        return FALSE;
    }
}
예제 #9
0
gboolean
gst_core_audio_set_channels_layout (GstCoreAudio * core_audio,
    gint channels, GstCaps * caps)
{
  /* Configure the output stream and allocate ringbuffer memory */
  AudioChannelLayout *layout = NULL;
  OSStatus status;
  int layoutSize, element, i;
  AudioUnitScope scope;
  GstStructure *structure;
  GstAudioChannelPosition *positions;

  /* Describe channels */
  layoutSize = sizeof (AudioChannelLayout) +
      channels * sizeof (AudioChannelDescription);
  layout = g_malloc (layoutSize);

  structure = gst_caps_get_structure (caps, 0);
  positions = gst_audio_get_channel_positions (structure);

  layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
  layout->mChannelBitmap = 0;   /* Not used */
  layout->mNumberChannelDescriptions = channels;
  for (i = 0; i < channels; i++) {
    if (positions) {
      layout->mChannelDescriptions[i].mChannelLabel =
          gst_audio_channel_position_to_coreaudio_channel_label (positions[i],
          i);
    } else {
      /* Discrete channel numbers are ORed into this */
      layout->mChannelDescriptions[i].mChannelLabel =
          kAudioChannelLabel_Discrete_0 | i;
    }

    /* Others unused */
    layout->mChannelDescriptions[i].mChannelFlags = 0;
    layout->mChannelDescriptions[i].mCoordinates[0] = 0.f;
    layout->mChannelDescriptions[i].mCoordinates[1] = 0.f;
    layout->mChannelDescriptions[i].mCoordinates[2] = 0.f;
  }

  if (positions) {
    g_free (positions);
    positions = NULL;
  }

  scope = core_audio->is_src ? kAudioUnitScope_Output : kAudioUnitScope_Input;
  element = core_audio->is_src ? 1 : 0;

  if (layoutSize) {
    status = AudioUnitSetProperty (core_audio->audiounit,
        kAudioUnitProperty_AudioChannelLayout,
        scope, element, layout, layoutSize);
    if (status) {
      GST_WARNING_OBJECT (core_audio->osxbuf,
          "Failed to set output channel layout: %" GST_FOURCC_FORMAT,
          GST_FOURCC_ARGS (status));
      return FALSE;
    }
  }

  g_free (layout);
  return TRUE;
}