/**
 * gst_audio_info_is_equal:
 * @info: a #GstAudioInfo
 * @other: a #GstAudioInfo
 *
 * Compares two #GstAudioInfo and returns whether they are equal or not
 *
 * Returns: %TRUE if @info and @other are equal, else %FALSE.
 *
 * Since: 1.2
 *
 */
gboolean
gst_audio_info_is_equal (const GstAudioInfo * info, const GstAudioInfo * other)
{
  if (info == other)
    return TRUE;
  if (info->finfo == NULL || other->finfo == NULL)
    return FALSE;
  if (GST_AUDIO_INFO_FORMAT (info) != GST_AUDIO_INFO_FORMAT (other))
    return FALSE;
  if (GST_AUDIO_INFO_FLAGS (info) != GST_AUDIO_INFO_FLAGS (other))
    return FALSE;
  if (GST_AUDIO_INFO_LAYOUT (info) != GST_AUDIO_INFO_LAYOUT (other))
    return FALSE;
  if (GST_AUDIO_INFO_RATE (info) != GST_AUDIO_INFO_RATE (other))
    return FALSE;
  if (GST_AUDIO_INFO_CHANNELS (info) != GST_AUDIO_INFO_CHANNELS (other))
    return FALSE;
  if (GST_AUDIO_INFO_CHANNELS (info) > 64)
    return TRUE;
  if (memcmp (info->position, other->position,
          GST_AUDIO_INFO_CHANNELS (info) * sizeof (GstAudioChannelPosition)) !=
      0)
    return FALSE;

  return TRUE;
}
예제 #2
0
static gboolean
gst_openal_src_prepare (GstAudioSrc * audiosrc, GstAudioRingBufferSpec * spec)
{
  GstOpenalSrc *openalsrc = GST_OPENAL_SRC (audiosrc);

  gst_openal_src_parse_spec (openalsrc, spec);
  if (openalsrc->format == AL_NONE) {
    GST_ELEMENT_ERROR (openalsrc, RESOURCE, SETTINGS, (NULL),
        ("Unable to get type %d, format %d, and %d channels", spec->type,
            GST_AUDIO_INFO_FORMAT (&spec->info),
            GST_AUDIO_INFO_CHANNELS (&spec->info)));
    return FALSE;
  }

  openalsrc->device =
      alcCaptureOpenDevice (openalsrc->default_device, openalsrc->rate,
      openalsrc->format, openalsrc->buffer_length);

  if (!openalsrc->device) {
    GST_ELEMENT_ERROR (openalsrc, RESOURCE, OPEN_READ,
        ("Could not open device."), GST_ALC_ERROR (openalsrc->device));
    return FALSE;
  }

  openalsrc->default_device_name =
      g_strdup (alcGetString (openalsrc->device, ALC_DEVICE_SPECIFIER));

  alcCaptureStart (openalsrc->device);

  return TRUE;
}
/* get notified of caps and plug in the correct process function */
static gboolean
gst_audio_fx_base_fir_filter_setup (GstAudioFilter * base,
    const GstAudioInfo * info)
{
  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (base);

  g_mutex_lock (&self->lock);
  if (self->buffer) {
    gst_audio_fx_base_fir_filter_push_residue (self);
    g_free (self->buffer);
    self->buffer = NULL;
    self->buffer_fill = 0;
    self->buffer_length = 0;
    self->start_ts = GST_CLOCK_TIME_NONE;
    self->start_off = GST_BUFFER_OFFSET_NONE;
    self->nsamples_out = 0;
    self->nsamples_in = 0;
  }

  gst_audio_fx_base_fir_filter_select_process_function (self,
      GST_AUDIO_INFO_FORMAT (info), GST_AUDIO_INFO_CHANNELS (info));
  g_mutex_unlock (&self->lock);

  return (self->process != NULL);
}
static gboolean
gst_audio_panorama_set_caps (GstBaseTransform * base, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstAudioPanorama *filter = GST_AUDIO_PANORAMA (base);
  GstAudioInfo info;

  /*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */
  if (!gst_audio_info_from_caps (&info, incaps))
    goto no_format;

  GST_DEBUG ("try to process %d input with %d channels",
      GST_AUDIO_INFO_FORMAT (&info), GST_AUDIO_INFO_CHANNELS (&info));

  if (!gst_audio_panorama_set_process_function (filter, &info))
    goto no_format;

  filter->info = info;

  return TRUE;

no_format:
  {
    GST_DEBUG ("invalid caps");
    return FALSE;
  }
}
예제 #5
0
static gboolean
gst_audio_filter_template_setup (GstAudioFilter * filter,
    const GstAudioInfo * info)
{
  GstAudioFilterTemplate *filter_template;
  GstAudioFormat fmt;
  gint chans, rate;

  filter_template = GST_AUDIO_FILTER_TEMPLATE (filter);

  rate = GST_AUDIO_INFO_RATE (info);
  chans = GST_AUDIO_INFO_CHANNELS (info);
  fmt = GST_AUDIO_INFO_FORMAT (info);

  GST_INFO_OBJECT (filter_template, "format %d (%s), rate %d, %d channels",
      fmt, GST_AUDIO_INFO_NAME (info), rate, chans);

  /* if any setup needs to be done (like memory allocated), do it here */

  /* The audio filter base class also saves the audio info in
   * GST_AUDIO_FILTER_INFO(filter) so it's automatically available
   * later from there as well */

  return TRUE;
}
예제 #6
0
static gboolean
gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
{
  GstLevel *filter = GST_LEVEL (trans);
  GstAudioInfo info;
  gint i, channels;

  if (!gst_audio_info_from_caps (&info, in))
    return FALSE;

  switch (GST_AUDIO_INFO_FORMAT (&info)) {
    case GST_AUDIO_FORMAT_S8:
      filter->process = gst_level_calculate_gint8;
      break;
    case GST_AUDIO_FORMAT_S16:
      filter->process = gst_level_calculate_gint16;
      break;
    case GST_AUDIO_FORMAT_S32:
      filter->process = gst_level_calculate_gint32;
      break;
    case GST_AUDIO_FORMAT_F32:
      filter->process = gst_level_calculate_gfloat;
      break;
    case GST_AUDIO_FORMAT_F64:
      filter->process = gst_level_calculate_gdouble;
      break;
    default:
      filter->process = NULL;
      break;
  }

  filter->info = info;

  channels = GST_AUDIO_INFO_CHANNELS (&info);

  /* allocate channel variable arrays */
  g_free (filter->CS);
  g_free (filter->peak);
  g_free (filter->last_peak);
  g_free (filter->decay_peak);
  g_free (filter->decay_peak_base);
  g_free (filter->decay_peak_age);
  filter->CS = g_new (gdouble, channels);
  filter->peak = g_new (gdouble, channels);
  filter->last_peak = g_new (gdouble, channels);
  filter->decay_peak = g_new (gdouble, channels);
  filter->decay_peak_base = g_new (gdouble, channels);

  filter->decay_peak_age = g_new (GstClockTime, channels);

  for (i = 0; i < channels; ++i) {
    filter->CS[i] = filter->peak[i] = filter->last_peak[i] =
        filter->decay_peak[i] = filter->decay_peak_base[i] = 0.0;
    filter->decay_peak_age[i] = G_GUINT64_CONSTANT (0);
  }

  gst_level_recalc_interval_frames (filter);

  return TRUE;
}
예제 #7
0
static gboolean
gst_audio_echo_setup (GstAudioFilter * base, const GstAudioInfo * info)
{
  GstAudioEcho *self = GST_AUDIO_ECHO (base);
  gboolean ret = TRUE;

  switch (GST_AUDIO_INFO_FORMAT (info)) {
    case GST_AUDIO_FORMAT_F32:
      self->process = (GstAudioEchoProcessFunc)
          gst_audio_echo_transform_float;
      break;
    case GST_AUDIO_FORMAT_F64:
      self->process = (GstAudioEchoProcessFunc)
          gst_audio_echo_transform_double;
      break;
    default:
      ret = FALSE;
      break;
  }

  g_free (self->buffer);
  self->buffer = NULL;
  self->buffer_pos = 0;
  self->buffer_size = 0;
  self->buffer_size_frames = 0;

  return ret;
}
예제 #8
0
static gboolean
gst_iir_equalizer_setup (GstAudioFilter * audio, const GstAudioInfo * info)
{
    GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio);

    switch (GST_AUDIO_INFO_FORMAT (info)) {
    case GST_AUDIO_FORMAT_S16:
        equ->history_size = history_size_gint16;
        equ->process = gst_iir_equ_process_gint16;
        break;
    case GST_AUDIO_FORMAT_F32:
        equ->history_size = history_size_gfloat;
        equ->process = gst_iir_equ_process_gfloat;
        break;
    case GST_AUDIO_FORMAT_F64:
        equ->history_size = history_size_gdouble;
        equ->process = gst_iir_equ_process_gdouble;
        break;
    default:
        return FALSE;
    }

    alloc_history (equ, info);
    return TRUE;
}
예제 #9
0
static gboolean
gst_fastspectrum_setup (GstAudioFilter * base, const GstAudioInfo * info)
{
  GstFastSpectrum *spectrum = GST_FASTSPECTRUM (base);
  GstFastSpectrumInputData input_data = NULL;

  g_mutex_lock (&spectrum->lock);
  switch (GST_AUDIO_INFO_FORMAT (info)) {
    case GST_AUDIO_FORMAT_S16:
      input_data = input_data_mixed_int16_max;
      break;
    case GST_AUDIO_FORMAT_S24:
      input_data = input_data_mixed_int24_max;
      break;
    case GST_AUDIO_FORMAT_S32:
      input_data = input_data_mixed_int32_max;
      break;
    case GST_AUDIO_FORMAT_F32:
      input_data = input_data_mixed_float;
      break;
    case GST_AUDIO_FORMAT_F64:
      input_data = input_data_mixed_double;
      break;
    default:
      g_assert_not_reached ();
      break;
  }
  spectrum->input_data = input_data;

  gst_fastspectrum_reset_state (spectrum);
  g_mutex_unlock (&spectrum->lock);

  return TRUE;
}
static gboolean
gst_freeverb_set_caps (GstBaseTransform * base, GstCaps * incaps,
                       GstCaps * outcaps)
{
    GstFreeverb *filter = GST_FREEVERB (base);
    GstAudioInfo info;

    /*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */
    if (!gst_audio_info_from_caps (&info, incaps))
        goto no_format;

    GST_DEBUG ("try to process %d input with %d channels",
               GST_AUDIO_INFO_FORMAT (&info), GST_AUDIO_INFO_CHANNELS (&info));

    if (!gst_freeverb_set_process_function (filter, &info))
        goto no_format;

    filter->info = info;

    gst_freeverb_init_rev_model (filter);
    filter->drained = FALSE;
    GST_INFO_OBJECT (base, "model configured");

    return TRUE;

no_format:
    {
        GST_DEBUG ("invalid caps");
        return FALSE;
    }
}
예제 #11
0
gboolean
gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f,
    guint * channels)
{
  pa_format_info *format;
  pa_sample_format_t sf = PA_SAMPLE_INVALID;
  GstAudioInfo *ainfo = &spec->info;

  format = pa_format_info_new ();

  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW
      && GST_AUDIO_INFO_WIDTH (ainfo) == 8) {
    format->encoding = PA_ENCODING_PCM;
    sf = PA_SAMPLE_ULAW;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW
      && GST_AUDIO_INFO_WIDTH (ainfo) == 8) {
    format->encoding = PA_ENCODING_PCM;
    sf = PA_SAMPLE_ALAW;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
    format->encoding = PA_ENCODING_PCM;
    if (!gstaudioformat_to_pasampleformat (GST_AUDIO_INFO_FORMAT (ainfo), &sf))
      goto fail;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3) {
    format->encoding = PA_ENCODING_AC3_IEC61937;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3) {
    format->encoding = PA_ENCODING_EAC3_IEC61937;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS) {
    format->encoding = PA_ENCODING_DTS_IEC61937;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG) {
    format->encoding = PA_ENCODING_MPEG_IEC61937;
  } else {
    goto fail;
  }

  if (format->encoding == PA_ENCODING_PCM) {
    pa_format_info_set_sample_format (format, sf);
    pa_format_info_set_channels (format, GST_AUDIO_INFO_CHANNELS (ainfo));
  }

  pa_format_info_set_rate (format, GST_AUDIO_INFO_RATE (ainfo));

  if (!pa_format_info_valid (format))
    goto fail;

  *f = format;
  *channels = GST_AUDIO_INFO_CHANNELS (ainfo);

  return TRUE;

fail:
  if (format)
    pa_format_info_free (format);
  return FALSE;
}
static gboolean
gst_audio_fx_base_iir_filter_setup (GstAudioFilter * base,
    const GstAudioInfo * info)
{
  GstAudioFXBaseIIRFilter *filter = GST_AUDIO_FX_BASE_IIR_FILTER (base);
  gboolean ret = TRUE;
  gint channels;

  g_mutex_lock (&filter->lock);
  switch (GST_AUDIO_INFO_FORMAT (info)) {
    case GST_AUDIO_FORMAT_F32:
      filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
          process_32;
      break;
    case GST_AUDIO_FORMAT_F64:
      filter->process = (GstAudioFXBaseIIRFilterProcessFunc)
          process_64;
      break;
    default:
      ret = FALSE;
      break;
  }

  channels = GST_AUDIO_INFO_CHANNELS (info);

  if (channels != filter->nchannels) {
    guint i;
    GstAudioFXBaseIIRFilterChannelCtx *ctx;

    if (filter->channels) {
      for (i = 0; i < filter->nchannels; i++) {
        ctx = &filter->channels[i];

        g_free (ctx->x);
        g_free (ctx->y);
      }
      g_free (filter->channels);
    }

    filter->channels = g_new0 (GstAudioFXBaseIIRFilterChannelCtx, channels);
    for (i = 0; i < channels; i++) {
      ctx = &filter->channels[i];

      ctx->x = g_new0 (gdouble, filter->nb);
      ctx->y = g_new0 (gdouble, filter->na);
    }
    filter->nchannels = channels;
  }
  g_mutex_unlock (&filter->lock);

  return ret;
}
static void
gst_audio_dynamic_set_process_function (GstAudioDynamic * filter,
    const GstAudioInfo * info)
{
  gint func_index;

  func_index = (filter->mode == MODE_COMPRESSOR) ? 0 : 4;
  func_index += (filter->characteristics == CHARACTERISTICS_HARD_KNEE) ? 0 : 2;
  func_index += (GST_AUDIO_INFO_FORMAT (info) == GST_AUDIO_FORMAT_F32) ? 1 : 0;

  g_assert (func_index >= 0 && func_index < G_N_ELEMENTS (process_functions));

  filter->process = process_functions[func_index];
}
예제 #14
0
static void
pcm_config_from_spec (struct pcm_config *config,
    const GstAudioRingBufferSpec * spec)
{
  gint64 frames;

  config->format = pcm_format_from_gst (GST_AUDIO_INFO_FORMAT (&spec->info));
  config->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
  config->rate = GST_AUDIO_INFO_RATE (&spec->info);

  gst_audio_info_convert (&spec->info,
      GST_FORMAT_TIME, spec->latency_time * GST_USECOND,
      GST_FORMAT_DEFAULT /* frames */ , &frames);

  config->period_size = frames;
  config->period_count = spec->buffer_time / spec->latency_time;
}
예제 #15
0
static void
gst_deinterleave_add_new_pads (GstDeinterleave * self, GstCaps * caps)
{
  GstPad *pad;
  guint i;

  for (i = 0; i < GST_AUDIO_INFO_CHANNELS (&self->audio_info); i++) {
    gchar *name = g_strdup_printf ("src_%u", i);
    GstCaps *srccaps;
    GstAudioInfo info;
    GstAudioFormat format = GST_AUDIO_INFO_FORMAT (&self->audio_info);
    gint rate = GST_AUDIO_INFO_RATE (&self->audio_info);
    GstAudioChannelPosition position = GST_AUDIO_CHANNEL_POSITION_MONO;
    CopyStickyEventsData data;

    /* Set channel position if we know it */
    if (self->keep_positions)
      position = GST_AUDIO_INFO_POSITION (&self->audio_info, i);

    gst_audio_info_init (&info);
    gst_audio_info_set_format (&info, format, rate, 1, &position);

    srccaps = gst_audio_info_to_caps (&info);

    pad = gst_pad_new_from_static_template (&src_template, name);
    g_free (name);

    gst_pad_use_fixed_caps (pad);
    gst_pad_set_query_function (pad,
        GST_DEBUG_FUNCPTR (gst_deinterleave_src_query));
    gst_pad_set_active (pad, TRUE);

    data.pad = pad;
    data.caps = srccaps;
    gst_pad_sticky_events_foreach (self->sink, copy_sticky_events, &data);
    if (data.caps)
      gst_pad_set_caps (pad, data.caps);
    gst_element_add_pad (GST_ELEMENT (self), pad);
    self->srcpads = g_list_prepend (self->srcpads, gst_object_ref (pad));

    gst_caps_unref (srccaps);
  }

  gst_element_no_more_pads (GST_ELEMENT (self));
  self->srcpads = g_list_reverse (self->srcpads);
}
static gboolean
gst_audio_invert_setup (GstAudioFilter * base, const GstAudioInfo * info)
{
  GstAudioInvert *filter = GST_AUDIO_INVERT (base);
  gboolean ret = TRUE;

  switch (GST_AUDIO_INFO_FORMAT (info)) {
    case GST_AUDIO_FORMAT_S16:
      filter->process = (GstAudioInvertProcessFunc)
          gst_audio_invert_transform_int;
      break;
    case GST_AUDIO_FORMAT_F32:
      filter->process = (GstAudioInvertProcessFunc)
          gst_audio_invert_transform_float;
      break;
    default:
      ret = FALSE;
      break;
  }
  return ret;
}
예제 #17
0
gboolean
gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec, pa_sample_spec * ss)
{
  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
    if (!gstaudioformat_to_pasampleformat (GST_AUDIO_INFO_FORMAT (&spec->info),
            &ss->format))
      return FALSE;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW) {
    ss->format = PA_SAMPLE_ULAW;
  } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW) {
    ss->format = PA_SAMPLE_ALAW;
  } else
    return FALSE;

  ss->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
  ss->rate = GST_AUDIO_INFO_RATE (&spec->info);

  if (!pa_sample_spec_valid (ss))
    return FALSE;

  return TRUE;
}
void
gst_audio_fx_base_fir_filter_set_kernel (GstAudioFXBaseFIRFilter * self,
    gdouble * kernel, guint kernel_length, guint64 latency,
    const GstAudioInfo * info)
{
  gboolean latency_changed;
  GstAudioFormat format;
  gint channels;

  g_return_if_fail (kernel != NULL);
  g_return_if_fail (self != NULL);

  g_mutex_lock (&self->lock);

  latency_changed = (self->latency != latency
      || (!self->low_latency && self->kernel_length < FFT_THRESHOLD
          && kernel_length >= FFT_THRESHOLD)
      || (!self->low_latency && self->kernel_length >= FFT_THRESHOLD
          && kernel_length < FFT_THRESHOLD));

  /* FIXME: If the latency changes, the buffer size changes too and we
   * have to drain in any case until this is fixed in the future */
  if (self->buffer && (!self->drain_on_changes || latency_changed)) {
    gst_audio_fx_base_fir_filter_push_residue (self);
    self->start_ts = GST_CLOCK_TIME_NONE;
    self->start_off = GST_BUFFER_OFFSET_NONE;
    self->nsamples_out = 0;
    self->nsamples_in = 0;
    self->buffer_fill = 0;
  }

  g_free (self->kernel);
  if (!self->drain_on_changes || latency_changed) {
    g_free (self->buffer);
    self->buffer = NULL;
    self->buffer_fill = 0;
    self->buffer_length = 0;
  }

  self->kernel = kernel;
  self->kernel_length = kernel_length;

  if (info) {
    format = GST_AUDIO_INFO_FORMAT (info);
    channels = GST_AUDIO_INFO_CHANNELS (info);
  } else {
    format = GST_AUDIO_FILTER_FORMAT (self);
    channels = GST_AUDIO_FILTER_CHANNELS (self);
  }

  gst_audio_fx_base_fir_filter_calculate_frequency_response (self);
  gst_audio_fx_base_fir_filter_select_process_function (self, format, channels);

  if (latency_changed) {
    self->latency = latency;
    gst_element_post_message (GST_ELEMENT (self),
        gst_message_new_latency (GST_OBJECT (self)));
  }

  g_mutex_unlock (&self->lock);
}
예제 #19
0
static GstFlowReturn
gst_fdkaacenc_handle_frame (GstAudioEncoder * enc, GstBuffer * inbuf)
{
  GstFdkAacEnc *self = GST_FDKAACENC (enc);
  GstFlowReturn ret = GST_FLOW_OK;
  GstAudioInfo *info;
  GstMapInfo imap, omap;
  GstBuffer *outbuf;
  AACENC_BufDesc in_desc = { 0 };
  AACENC_BufDesc out_desc = { 0 };
  AACENC_InArgs in_args = { 0 };
  AACENC_OutArgs out_args = { 0 };
  gint in_id = IN_AUDIO_DATA, out_id = OUT_BITSTREAM_DATA;
  gint in_sizes, out_sizes;
  gint in_el_sizes, out_el_sizes;
  AACENC_ERROR err;

  info = gst_audio_encoder_get_audio_info (enc);

  if (inbuf) {
    if (self->need_reorder) {
      inbuf = gst_buffer_copy (inbuf);
      gst_buffer_map (inbuf, &imap, GST_MAP_READWRITE);
      gst_audio_reorder_channels (imap.data, imap.size,
          GST_AUDIO_INFO_FORMAT (info), GST_AUDIO_INFO_CHANNELS (info),
          &GST_AUDIO_INFO_POSITION (info, 0), self->aac_positions);
    } else {
      gst_buffer_map (inbuf, &imap, GST_MAP_READ);
    }

    in_args.numInSamples = imap.size / GST_AUDIO_INFO_BPS (info);

    in_sizes = imap.size;
    in_el_sizes = GST_AUDIO_INFO_BPS (info);
    in_desc.numBufs = 1;
  } else {
    in_args.numInSamples = -1;

    in_sizes = 0;
    in_el_sizes = 0;
    in_desc.numBufs = 0;
  }

  in_desc.bufferIdentifiers = &in_id;
  in_desc.bufs = (void *) &imap.data;
  in_desc.bufSizes = &in_sizes;
  in_desc.bufElSizes = &in_el_sizes;

  outbuf = gst_audio_encoder_allocate_output_buffer (enc, self->outbuf_size);
  if (!outbuf) {
    ret = GST_FLOW_ERROR;
    goto out;
  }

  gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);
  out_sizes = omap.size;
  out_el_sizes = 1;
  out_desc.bufferIdentifiers = &out_id;
  out_desc.numBufs = 1;
  out_desc.bufs = (void *) &omap.data;
  out_desc.bufSizes = &out_sizes;
  out_desc.bufElSizes = &out_el_sizes;

  err = aacEncEncode (self->enc, &in_desc, &out_desc, &in_args, &out_args);
  if (err == AACENC_ENCODE_EOF && !inbuf)
    goto out;
  else if (err != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Failed to encode data: %d", err);
    ret = GST_FLOW_ERROR;
    goto out;
  }

  if (inbuf) {
    gst_buffer_unmap (inbuf, &imap);
    if (self->need_reorder)
      gst_buffer_unref (inbuf);
    inbuf = NULL;
  }

  if (!out_args.numOutBytes)
    goto out;

  gst_buffer_unmap (outbuf, &omap);
  gst_buffer_set_size (outbuf, out_args.numOutBytes);

  ret = gst_audio_encoder_finish_frame (enc, outbuf, self->samples_per_frame);
  outbuf = NULL;

out:
  if (outbuf) {
    gst_buffer_unmap (outbuf, &omap);
    gst_buffer_unref (outbuf);
  }
  if (inbuf) {
    gst_buffer_unmap (inbuf, &imap);
    if (self->need_reorder)
      gst_buffer_unref (inbuf);
  }

  return ret;
}
static gboolean
gst_videoframe_audiolevel_asink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstVideoFrameAudioLevel *self = GST_VIDEOFRAME_AUDIOLEVEL (parent);
  GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
      self->first_time = GST_CLOCK_TIME_NONE;
      self->total_frames = 0;
      gst_adapter_clear (self->adapter);
      gst_event_copy_segment (event, &self->asegment);
      if (self->asegment.format != GST_FORMAT_TIME)
        return FALSE;
      break;
    case GST_EVENT_FLUSH_START:
      g_mutex_lock (&self->mutex);
      self->audio_flush_flag = TRUE;
      g_cond_signal (&self->cond);
      g_mutex_unlock (&self->mutex);
      break;
    case GST_EVENT_FLUSH_STOP:
      self->audio_flush_flag = FALSE;
      self->total_frames = 0;
      self->first_time = GST_CLOCK_TIME_NONE;
      gst_adapter_clear (self->adapter);
      gst_segment_init (&self->asegment, GST_FORMAT_UNDEFINED);
      break;
    case GST_EVENT_CAPS:{
      GstCaps *caps;
      gint channels;
      gst_event_parse_caps (event, &caps);
      GST_DEBUG_OBJECT (self, "Got caps %" GST_PTR_FORMAT, caps);
      if (!gst_audio_info_from_caps (&self->ainfo, caps))
        return FALSE;
      switch (GST_AUDIO_INFO_FORMAT (&self->ainfo)) {
        case GST_AUDIO_FORMAT_S8:
          self->process = gst_videoframe_audiolevel_calculate_gint8;
          break;
        case GST_AUDIO_FORMAT_S16:
          self->process = gst_videoframe_audiolevel_calculate_gint16;
          break;
        case GST_AUDIO_FORMAT_S32:
          self->process = gst_videoframe_audiolevel_calculate_gint32;
          break;
        case GST_AUDIO_FORMAT_F32:
          self->process = gst_videoframe_audiolevel_calculate_gfloat;
          break;
        case GST_AUDIO_FORMAT_F64:
          self->process = gst_videoframe_audiolevel_calculate_gdouble;
          break;
        default:
          self->process = NULL;
          break;
      }
      gst_adapter_clear (self->adapter);
      channels = GST_AUDIO_INFO_CHANNELS (&self->ainfo);
      self->first_time = GST_CLOCK_TIME_NONE;
      self->total_frames = 0;
      if (self->CS)
        g_free (self->CS);
      self->CS = g_new0 (gdouble, channels);
      break;
    }
    default:
      break;
  }

  return gst_pad_event_default (pad, parent, event);
}
예제 #21
0
static gboolean
gst_rg_analysis_set_caps (GstBaseTransform * base, GstCaps * in_caps,
    GstCaps * out_caps)
{
  GstRgAnalysis *filter = GST_RG_ANALYSIS (base);
  GstAudioInfo info;
  gint rate, channels;

  g_return_val_if_fail (filter->ctx != NULL, FALSE);

  GST_DEBUG_OBJECT (filter,
      "set_caps in %" GST_PTR_FORMAT " out %" GST_PTR_FORMAT,
      in_caps, out_caps);

  if (!gst_audio_info_from_caps (&info, in_caps))
    goto invalid_format;

  rate = GST_AUDIO_INFO_RATE (&info);

  if (!rg_analysis_set_sample_rate (filter->ctx, rate))
    goto invalid_format;

  channels = GST_AUDIO_INFO_CHANNELS (&info);

  if (channels < 1 || channels > 2)
    goto invalid_format;

  switch (GST_AUDIO_INFO_FORMAT (&info)) {
    case GST_AUDIO_FORMAT_F32:
      /* The depth is not variable for float formats of course.  It just
       * makes the transform function nice and simple if the
       * rg_analysis_analyze_* functions have a common signature. */
      filter->depth = sizeof (gfloat) * 8;

      if (channels == 1)
        filter->analyze = rg_analysis_analyze_mono_float;
      else
        filter->analyze = rg_analysis_analyze_stereo_float;

      break;
    case GST_AUDIO_FORMAT_S16:
      filter->depth = sizeof (gint16) * 8;

      if (channels == 1)
        filter->analyze = rg_analysis_analyze_mono_int16;
      else
        filter->analyze = rg_analysis_analyze_stereo_int16;
      break;
    default:
      goto invalid_format;
  }

  return TRUE;

  /* Errors. */
invalid_format:
  {
    filter->analyze = NULL;
    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION,
        ("Invalid incoming caps: %" GST_PTR_FORMAT, in_caps), (NULL));
    return FALSE;
  }
}
예제 #22
0
static void
gst_openal_sink_parse_spec (GstOpenALSink * sink,
    const GstAudioRingBufferSpec * spec)
{
  ALuint format = AL_NONE;

  GST_DEBUG_OBJECT (sink,
      "looking up format for type %d, gst-format %d, and %d channels",
      spec->type, GST_AUDIO_INFO_FORMAT (&spec->info),
      GST_AUDIO_INFO_CHANNELS (&spec->info));

  /* Don't need to verify supported formats, since the probed caps will only
   * report what was detected and we shouldn't get anything different */
  switch (spec->type) {
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
        case GST_AUDIO_FORMAT_U8:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO8;
              break;
            case 2:
              format = AL_FORMAT_STEREO8;
              break;
            case 4:
              format = AL_FORMAT_QUAD8;
              break;
            case 6:
              format = AL_FORMAT_51CHN8;
              break;
            case 7:
              format = AL_FORMAT_61CHN8;
              break;
            case 8:
              format = AL_FORMAT_71CHN8;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_S16:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO16;
              break;
            case 2:
              format = AL_FORMAT_STEREO16;
              break;
            case 4:
              format = AL_FORMAT_QUAD16;
              break;
            case 6:
              format = AL_FORMAT_51CHN16;
              break;
            case 7:
              format = AL_FORMAT_61CHN16;
              break;
            case 8:
              format = AL_FORMAT_71CHN16;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_F32:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO_FLOAT32;
              break;
            case 2:
              format = AL_FORMAT_STEREO_FLOAT32;
              break;
            case 4:
              format = AL_FORMAT_QUAD32;
              break;
            case 6:
              format = AL_FORMAT_51CHN32;
              break;
            case 7:
              format = AL_FORMAT_61CHN32;
              break;
            case 8:
              format = AL_FORMAT_71CHN32;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_F64:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO_DOUBLE_EXT;
              break;
            case 2:
              format = AL_FORMAT_STEREO_DOUBLE_EXT;
              break;
            default:
              break;
          }
          break;
        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IMA_ADPCM:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_IMA4;
          break;
        case 2:
          format = AL_FORMAT_STEREO_IMA4;
          break;
        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_ALAW_EXT;
          break;
        case 2:
          format = AL_FORMAT_STEREO_ALAW_EXT;
          break;
        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_MULAW;
          break;
        case 2:
          format = AL_FORMAT_STEREO_MULAW;
          break;
        case 4:
          format = AL_FORMAT_QUAD_MULAW;
          break;
        case 6:
          format = AL_FORMAT_51CHN_MULAW;
          break;
        case 7:
          format = AL_FORMAT_61CHN_MULAW;
          break;
        case 8:
          format = AL_FORMAT_71CHN_MULAW;
          break;
        default:
          break;
      }
      break;

    default:
      break;
  }

  sink->bytes_per_sample = GST_AUDIO_INFO_BPS (&spec->info);
  sink->rate = GST_AUDIO_INFO_RATE (&spec->info);
  sink->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
  sink->format = format;
  sink->buffer_count = spec->segtotal;
  sink->buffer_length = spec->segsize;
}
예제 #23
0
static gboolean
gst_openal_sink_prepare (GstAudioSink * audiosink,
    GstAudioRingBufferSpec * spec)
{
  GstOpenALSink *sink = GST_OPENAL_SINK (audiosink);
  ALCcontext *context, *old;

  if (sink->default_context && !gst_openal_sink_unprepare (audiosink))
    return FALSE;

  if (sink->user_context)
    context = sink->user_context;
  else {
    ALCint attribs[3] = { 0, 0, 0 };

    /* Don't try to change the playback frequency of an app's device */
    if (!sink->user_device) {
      attribs[0] = ALC_FREQUENCY;
      attribs[1] = GST_AUDIO_INFO_RATE (&spec->info);
      attribs[2] = 0;
    }

    context = alcCreateContext (sink->default_device, attribs);
    if (!context) {
      GST_ELEMENT_ERROR (sink, RESOURCE, FAILED,
          ("Unable to prepare device."), GST_ALC_ERROR (sink->default_device));
      return FALSE;
    }
  }

  old = pushContext (context);

  if (sink->user_source) {
    if (!sink->user_context || !alIsSource (sink->user_source)) {
      GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
          ("Invalid source specified for context"));
      goto fail;
    }
    sink->default_source = sink->user_source;
  } else {
    ALuint source;

    alGenSources (1, &source);
    if (checkALError () != AL_NO_ERROR) {
      GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL),
          ("Unable to generate source"));
      goto fail;
    }
    sink->default_source = source;
  }

  gst_openal_sink_parse_spec (sink, spec);
  if (sink->format == AL_NONE) {
    GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
        ("Unable to get type %d, format %d, and %d channels", spec->type,
            GST_AUDIO_INFO_FORMAT (&spec->info),
            GST_AUDIO_INFO_CHANNELS (&spec->info)));
    goto fail;
  }

  sink->buffers = g_malloc (sink->buffer_count * sizeof (*sink->buffers));
  if (!sink->buffers) {
    GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, ("Out of memory."),
        ("Unable to allocate buffers"));
    goto fail;
  }

  alGenBuffers (sink->buffer_count, sink->buffers);
  if (checkALError () != AL_NO_ERROR) {
    GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL),
        ("Unable to generate %d buffers", sink->buffer_count));
    goto fail;
  }
  sink->buffer_idx = 0;

  popContext (old, context);
  sink->default_context = context;
  return TRUE;

fail:
  if (!sink->user_source && sink->default_source)
    alDeleteSources (1, &sink->default_source);
  sink->default_source = 0;

  g_free (sink->buffers);
  sink->buffers = NULL;
  sink->buffer_count = 0;
  sink->buffer_length = 0;

  popContext (old, context);
  if (!sink->user_context)
    alcDestroyContext (context);
  return FALSE;
}
예제 #24
0
static gboolean
alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
{
  switch (spec->type) {
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
        case GST_AUDIO_FORMAT_U8:
          alsa->format = SND_PCM_FORMAT_U8;
          break;
        case GST_AUDIO_FORMAT_S8:
          alsa->format = SND_PCM_FORMAT_S8;
          break;
        case GST_AUDIO_FORMAT_S16LE:
          alsa->format = SND_PCM_FORMAT_S16_LE;
          break;
        case GST_AUDIO_FORMAT_S16BE:
          alsa->format = SND_PCM_FORMAT_S16_BE;
          break;
        case GST_AUDIO_FORMAT_U16LE:
          alsa->format = SND_PCM_FORMAT_U16_LE;
          break;
        case GST_AUDIO_FORMAT_U16BE:
          alsa->format = SND_PCM_FORMAT_U16_BE;
          break;
        case GST_AUDIO_FORMAT_S24_32LE:
          alsa->format = SND_PCM_FORMAT_S24_LE;
          break;
        case GST_AUDIO_FORMAT_S24_32BE:
          alsa->format = SND_PCM_FORMAT_S24_BE;
          break;
        case GST_AUDIO_FORMAT_U24_32LE:
          alsa->format = SND_PCM_FORMAT_U24_LE;
          break;
        case GST_AUDIO_FORMAT_U24_32BE:
          alsa->format = SND_PCM_FORMAT_U24_BE;
          break;
        case GST_AUDIO_FORMAT_S32LE:
          alsa->format = SND_PCM_FORMAT_S32_LE;
          break;
        case GST_AUDIO_FORMAT_S32BE:
          alsa->format = SND_PCM_FORMAT_S32_BE;
          break;
        case GST_AUDIO_FORMAT_U32LE:
          alsa->format = SND_PCM_FORMAT_U32_LE;
          break;
        case GST_AUDIO_FORMAT_U32BE:
          alsa->format = SND_PCM_FORMAT_U32_BE;
          break;
        case GST_AUDIO_FORMAT_S24LE:
          alsa->format = SND_PCM_FORMAT_S24_3LE;
          break;
        case GST_AUDIO_FORMAT_S24BE:
          alsa->format = SND_PCM_FORMAT_S24_3BE;
          break;
        case GST_AUDIO_FORMAT_U24LE:
          alsa->format = SND_PCM_FORMAT_U24_3LE;
          break;
        case GST_AUDIO_FORMAT_U24BE:
          alsa->format = SND_PCM_FORMAT_U24_3BE;
          break;
        case GST_AUDIO_FORMAT_S20LE:
          alsa->format = SND_PCM_FORMAT_S20_3LE;
          break;
        case GST_AUDIO_FORMAT_S20BE:
          alsa->format = SND_PCM_FORMAT_S20_3BE;
          break;
        case GST_AUDIO_FORMAT_U20LE:
          alsa->format = SND_PCM_FORMAT_U20_3LE;
          break;
        case GST_AUDIO_FORMAT_U20BE:
          alsa->format = SND_PCM_FORMAT_U20_3BE;
          break;
        case GST_AUDIO_FORMAT_S18LE:
          alsa->format = SND_PCM_FORMAT_S18_3LE;
          break;
        case GST_AUDIO_FORMAT_S18BE:
          alsa->format = SND_PCM_FORMAT_S18_3BE;
          break;
        case GST_AUDIO_FORMAT_U18LE:
          alsa->format = SND_PCM_FORMAT_U18_3LE;
          break;
        case GST_AUDIO_FORMAT_U18BE:
          alsa->format = SND_PCM_FORMAT_U18_3BE;
          break;
        case GST_AUDIO_FORMAT_F32LE:
          alsa->format = SND_PCM_FORMAT_FLOAT_LE;
          break;
        case GST_AUDIO_FORMAT_F32BE:
          alsa->format = SND_PCM_FORMAT_FLOAT_BE;
          break;
        case GST_AUDIO_FORMAT_F64LE:
          alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
          break;
        case GST_AUDIO_FORMAT_F64BE:
          alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
          break;
        default:
          goto error;
      }
      break;
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
      alsa->format = SND_PCM_FORMAT_A_LAW;
      break;
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
      alsa->format = SND_PCM_FORMAT_MU_LAW;
      break;
    default:
      goto error;

  }
  alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
  alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
  alsa->buffer_time = spec->buffer_time;
  alsa->period_time = spec->latency_time;
  alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;

  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
        (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);

  return TRUE;

  /* ERRORS */
error:
  {
    return FALSE;
  }
}
예제 #25
0
static GstFlowReturn
gst_cutter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstCutter *filter;
  GstMapInfo map;
  gint16 *in_data;
  gint bpf, rate;
  gsize in_size;
  guint num_samples;
  gdouble NCS = 0.0;            /* Normalized Cumulative Square of buffer */
  gdouble RMS = 0.0;            /* RMS of signal in buffer */
  gdouble NMS = 0.0;            /* Normalized Mean Square of buffer */
  GstBuffer *prebuf;            /* pointer to a prebuffer element */
  GstClockTime duration;

  filter = GST_CUTTER (parent);

  if (GST_AUDIO_INFO_FORMAT (&filter->info) == GST_AUDIO_FORMAT_UNKNOWN)
    goto not_negotiated;

  bpf = GST_AUDIO_INFO_BPF (&filter->info);
  rate = GST_AUDIO_INFO_RATE (&filter->info);

  gst_buffer_map (buf, &map, GST_MAP_READ);
  in_data = (gint16 *) map.data;
  in_size = map.size;

  GST_LOG_OBJECT (filter, "length of prerec buffer: %" GST_TIME_FORMAT,
      GST_TIME_ARGS (filter->pre_run_length));

  /* calculate mean square value on buffer */
  switch (GST_AUDIO_INFO_FORMAT (&filter->info)) {
    case GST_AUDIO_FORMAT_S16:
      num_samples = in_size / 2;
      gst_cutter_calculate_gint16 (in_data, num_samples, &NCS);
      NMS = NCS / num_samples;
      break;
    case GST_AUDIO_FORMAT_S8:
      num_samples = in_size;
      gst_cutter_calculate_gint8 ((gint8 *) in_data, num_samples, &NCS);
      NMS = NCS / num_samples;
      break;
    default:
      /* this shouldn't happen */
      g_warning ("no mean square function for format");
      break;
  }

  gst_buffer_unmap (buf, &map);

  filter->silent_prev = filter->silent;

  duration = gst_util_uint64_scale (in_size / bpf, GST_SECOND, rate);

  RMS = sqrt (NMS);
  /* if RMS below threshold, add buffer length to silent run length count
   * if not, reset
   */
  GST_LOG_OBJECT (filter, "buffer stats: NMS %f, RMS %f, audio length %f", NMS,
      RMS, gst_guint64_to_gdouble (duration));

  if (RMS < filter->threshold_level)
    filter->silent_run_length += gst_guint64_to_gdouble (duration);
  else {
    filter->silent_run_length = 0 * GST_SECOND;
    filter->silent = FALSE;
  }

  if (filter->silent_run_length > filter->threshold_length)
    /* it has been silent long enough, flag it */
    filter->silent = TRUE;

  /* has the silent status changed ? if so, send right signal
   * and, if from silent -> not silent, flush pre_record buffer
   */
  if (filter->silent != filter->silent_prev) {
    if (filter->silent) {
      GstMessage *m =
          gst_cutter_message_new (filter, FALSE, GST_BUFFER_TIMESTAMP (buf));
      GST_DEBUG_OBJECT (filter, "signaling CUT_STOP");
      gst_element_post_message (GST_ELEMENT (filter), m);
    } else {
      gint count = 0;
      GstMessage *m =
          gst_cutter_message_new (filter, TRUE, GST_BUFFER_TIMESTAMP (buf));

      GST_DEBUG_OBJECT (filter, "signaling CUT_START");
      gst_element_post_message (GST_ELEMENT (filter), m);
      /* first of all, flush current buffer */
      GST_DEBUG_OBJECT (filter, "flushing buffer of length %" GST_TIME_FORMAT,
          GST_TIME_ARGS (filter->pre_run_length));

      while (filter->pre_buffer) {
        prebuf = (g_list_first (filter->pre_buffer))->data;
        filter->pre_buffer = g_list_remove (filter->pre_buffer, prebuf);
        gst_pad_push (filter->srcpad, prebuf);
        ++count;
      }
      GST_DEBUG_OBJECT (filter, "flushed %d buffers", count);
      filter->pre_run_length = 0 * GST_SECOND;
    }
  }
  /* now check if we have to send the new buffer to the internal buffer cache
   * or to the srcpad */
  if (filter->silent) {
    filter->pre_buffer = g_list_append (filter->pre_buffer, buf);
    filter->pre_run_length += gst_guint64_to_gdouble (duration);

    while (filter->pre_run_length > filter->pre_length) {
      GstClockTime pduration;
      gsize psize;

      prebuf = (g_list_first (filter->pre_buffer))->data;
      g_assert (GST_IS_BUFFER (prebuf));

      psize = gst_buffer_get_size (prebuf);
      pduration = gst_util_uint64_scale (psize / bpf, GST_SECOND, rate);

      filter->pre_buffer = g_list_remove (filter->pre_buffer, prebuf);
      filter->pre_run_length -= gst_guint64_to_gdouble (pduration);

      /* only pass buffers if we don't leak */
      if (!filter->leaky)
        ret = gst_pad_push (filter->srcpad, prebuf);
      else
        gst_buffer_unref (prebuf);
    }
  } else
    ret = gst_pad_push (filter->srcpad, buf);

  return ret;

  /* ERRORS */
not_negotiated:
  {
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
예제 #26
0
static void
gst_openal_src_parse_spec (GstOpenalSrc * openalsrc,
    const GstAudioRingBufferSpec * spec)
{
  ALuint format = AL_NONE;

  GST_DEBUG_OBJECT (openalsrc,
      "looking up format for type %d, gst-format %d, and %d channels",
      spec->type, GST_AUDIO_INFO_FORMAT (&spec->info),
      GST_AUDIO_INFO_CHANNELS (&spec->info));

  switch (spec->type) {
    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
        case GST_AUDIO_FORMAT_U8:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO8;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_U16:
        case GST_AUDIO_FORMAT_S16:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO16;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_F32:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO_FLOAT32;
              break;
            default:
              break;
          }
          break;

        case GST_AUDIO_FORMAT_F64:
          switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
            case 1:
              format = AL_FORMAT_MONO_DOUBLE_EXT;
              break;
            default:
              break;
          }
          break;

        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_IMA_ADPCM:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_IMA4;
          break;
        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_ALAW_EXT;
          break;
        default:
          break;
      }
      break;

    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW:
      switch (GST_AUDIO_INFO_CHANNELS (&spec->info)) {
        case 1:
          format = AL_FORMAT_MONO_MULAW;
          break;
        default:
          break;
      }
      break;

    default:
      break;
  }

  openalsrc->bytes_per_sample = GST_AUDIO_INFO_BPS (&spec->info);
  openalsrc->rate = GST_AUDIO_INFO_RATE (&spec->info);
  openalsrc->buffer_length = spec->segsize;
  openalsrc->format = format;
}
예제 #27
0
gboolean
gst_sndio_prepare (struct gstsndio *sio, GstAudioRingBufferSpec *spec)
{
  struct sio_par par, retpar;
  unsigned nchannels;

  GST_DEBUG_OBJECT (sio, "prepare");

  if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE,
	("Only raw buffer format supported by sndio"), (NULL));
      return FALSE;
  }
  if (!GST_AUDIO_INFO_IS_INTEGER(&spec->info)) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE,
	("Only integer format supported"), (NULL));
      return FALSE;
  }
  if (GST_AUDIO_INFO_DEPTH(&spec->info) % 8) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE,
	("Only depths multiple of 8 are supported"), (NULL));
      return FALSE;
  }

  sio_initpar (&par);
  switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
  case GST_AUDIO_FORMAT_S8:
  case GST_AUDIO_FORMAT_U8:
  case GST_AUDIO_FORMAT_S16LE:
  case GST_AUDIO_FORMAT_S16BE:
  case GST_AUDIO_FORMAT_U16LE:
  case GST_AUDIO_FORMAT_U16BE:
  case GST_AUDIO_FORMAT_S32LE:
  case GST_AUDIO_FORMAT_S32BE:
  case GST_AUDIO_FORMAT_U32LE:
  case GST_AUDIO_FORMAT_U32BE:
  case GST_AUDIO_FORMAT_S24_32LE:
  case GST_AUDIO_FORMAT_S24_32BE:
  case GST_AUDIO_FORMAT_U24_32LE:
  case GST_AUDIO_FORMAT_U24_32BE:
  case GST_AUDIO_FORMAT_S24LE:
  case GST_AUDIO_FORMAT_S24BE:
  case GST_AUDIO_FORMAT_U24LE:
  case GST_AUDIO_FORMAT_U24BE:
      break;
  default:
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE,
	  ("Unsupported audio format"),
	  ("format = %d", GST_AUDIO_INFO_FORMAT (&spec->info)));
      return FALSE;
  }
  par.sig = GST_AUDIO_INFO_IS_SIGNED(&spec->info);
  par.bits = GST_AUDIO_INFO_WIDTH(&spec->info);
  par.bps = GST_AUDIO_INFO_DEPTH(&spec->info) / 8;
  if (par.bps > 1)
      par.le = GST_AUDIO_INFO_IS_LITTLE_ENDIAN(&spec->info);
  if (par.bits < par.bps * 8)
      par.msb = 0;
  par.rate = GST_AUDIO_INFO_RATE(&spec->info);
  if (sio->mode == SIO_PLAY)
      par.pchan = GST_AUDIO_INFO_CHANNELS(&spec->info);
  else
      par.rchan = GST_AUDIO_INFO_CHANNELS(&spec->info);
  par.round = par.rate / 1000000. * spec->latency_time;
  par.appbufsz = par.rate / 1000000. * spec->buffer_time;

  if (!sio_setpar (sio->hdl, &par)) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE,
	("Unsupported audio encoding"), (NULL));
      return FALSE;
  }
  if (!sio_getpar (sio->hdl, &retpar)) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE,
	("Couldn't get audio device parameters"), (NULL));
      return FALSE;
  }
#if 0
  fprintf(stderr, "format = %s, "
         "requested: sig = %d, bits = %d, bps = %d, le = %d, msb = %d, "
	 "rate = %d, pchan = %d, round = %d, appbufsz = %d; "
	 "returned: sig = %d, bits = %d, bps = %d, le = %d, msb = %d, "
	 "rate = %d, pchan = %d, round = %d, appbufsz = %d, bufsz = %d\n",
	 GST_AUDIO_INFO_NAME(&spec->info),
	 par.sig, par.bits, par.bps, par.le, par.msb,
	 par.rate, par.pchan, par.round, par.appbufsz,
	 retpar.sig, retpar.bits, retpar.bps, retpar.le, retpar.msb,
	 retpar.rate, retpar.pchan, retpar.round, retpar.appbufsz, retpar.bufsz);
#endif
  if (par.bits != retpar.bits ||
      par.bps != retpar.bps ||
      par.rate != retpar.rate ||
      (sio->mode == SIO_PLAY && par.pchan != retpar.pchan) ||
      (sio->mode == SIO_REC && par.rchan != retpar.rchan) ||
      (par.bps > 1 && par.le != retpar.le) ||
      (par.bits < par.bps * 8 && par.msb != retpar.msb)) {
      GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE,
	("Audio device refused requested parameters"), (NULL));
      return FALSE;
  }

  nchannels = (sio->mode == SIO_PLAY) ? retpar.pchan : retpar.rchan;
  spec->segsize = retpar.round * retpar.bps * nchannels;
  spec->segtotal = retpar.bufsz / retpar.round;
  sio->bpf = retpar.bps * nchannels;
  sio->delay = 0;
  sio_onmove (sio->hdl, gst_sndio_cb, sio);

  if (!sio_start (sio->hdl)) {
    GST_ELEMENT_ERROR (sio->obj, RESOURCE, OPEN_READ_WRITE,
      ("Could not start sndio"), (NULL));
    return FALSE;
  }
  return TRUE;
}
예제 #28
0
static gboolean
gst_raw_audio_parse_caps_to_config (GstRawAudioParse * raw_audio_parse,
    GstCaps * caps, GstRawAudioParseConfig * config)
{
  gboolean ret = FALSE;
  GstStructure *structure;

  /* Caps might get copied, and the copy needs to be unref'd.
   * Also, the caller retains ownership over the original caps.
   * So, to make this mechanism also work with cases where the
   * caps are *not* copied, ref the original caps here first. */
  gst_caps_ref (caps);

  structure = gst_caps_get_structure (caps, 0);

  /* For unaligned raw data, the output caps stay the same,
   * except that audio/x-unaligned-raw becomes audio/x-raw,
   * since the parser aligns the sample data */
  if (gst_structure_has_name (structure, "audio/x-unaligned-raw")) {
    /* Copy the caps to be able to modify them */
    GstCaps *new_caps = gst_caps_copy (caps);
    gst_caps_unref (caps);
    caps = new_caps;

    /* Change the media type to audio/x-raw , otherwise
     * gst_audio_info_from_caps() won't work */
    structure = gst_caps_get_structure (caps, 0);
    gst_structure_set_name (structure, "audio/x-raw");
  }

  if (gst_structure_has_name (structure, "audio/x-raw")) {
    guint num_channels;
    GstAudioInfo info;
    if (!gst_audio_info_from_caps (&info, caps)) {
      GST_ERROR_OBJECT (raw_audio_parse,
          "failed to parse caps %" GST_PTR_FORMAT, (gpointer) caps);
      goto done;
    }

    num_channels = GST_AUDIO_INFO_CHANNELS (&info);

    config->format = GST_RAW_AUDIO_PARSE_FORMAT_PCM;
    config->pcm_format = GST_AUDIO_INFO_FORMAT (&info);
    config->bpf = GST_AUDIO_INFO_BPF (&info);
    config->sample_rate = GST_AUDIO_INFO_RATE (&info);
    config->interleaved =
        (GST_AUDIO_INFO_LAYOUT (&info) == GST_AUDIO_LAYOUT_INTERLEAVED);

    gst_raw_audio_parse_set_config_channels (config, num_channels, 0, FALSE);
    memcpy (config->channel_positions, &(GST_AUDIO_INFO_POSITION (&info, 0)),
        sizeof (GstAudioChannelPosition) * num_channels);
  } else if (gst_structure_has_name (structure, "audio/x-alaw")
      || gst_structure_has_name (structure, "audio/x-mulaw")) {
    gint i;
    guint64 channel_mask;
    guint num_channels;

    config->format =
        gst_structure_has_name (structure,
        "audio/x-alaw") ? GST_RAW_AUDIO_PARSE_FORMAT_ALAW :
        GST_RAW_AUDIO_PARSE_FORMAT_MULAW;

    if (!gst_structure_get_int (structure, "rate", &i)) {
      GST_ERROR_OBJECT (raw_audio_parse,
          "missing rate value in caps %" GST_PTR_FORMAT, (gpointer) caps);
      goto done;
    }
    config->sample_rate = i;

    if (!gst_structure_get_int (structure, "channels", &i)) {
      GST_ERROR_OBJECT (raw_audio_parse,
          "missing channels value in caps %" GST_PTR_FORMAT, (gpointer) caps);
      goto done;
    }
    num_channels = i;

    if (!gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK,
            &channel_mask, NULL)) {
      channel_mask = gst_audio_channel_get_fallback_mask (num_channels);
      GST_DEBUG_OBJECT (raw_audio_parse,
          "input caps have no channel mask - using fallback mask %#"
          G_GINT64_MODIFIER "x for %u channels", channel_mask, num_channels);
    }

    if (!gst_raw_audio_parse_set_config_channels (config, num_channels,
            channel_mask, TRUE)) {
      GST_ERROR_OBJECT (raw_audio_parse,
          "could not use channel mask %#" G_GINT64_MODIFIER
          "x for channel positions", channel_mask);
      goto done;
    }

    /* A-law and mu-law both use 1 byte per sample */
    config->bpf = 1 * num_channels;
  } else {
    GST_ERROR_OBJECT (raw_audio_parse,
        "caps %" GST_PTR_FORMAT " have an unsupported media type",
        (gpointer) caps);
    goto done;
  }

  ret = TRUE;

done:
  gst_caps_unref (caps);
  if (ret)
    config->ready = TRUE;
  return ret;
}