コード例 #1
0
static void
gst_audio_aggregator_reset (GstAudioAggregator * aagg)
{
  GstAggregator *agg = GST_AGGREGATOR (aagg);

  GST_AUDIO_AGGREGATOR_LOCK (aagg);
  GST_OBJECT_LOCK (aagg);
  agg->segment.position = -1;
  aagg->priv->offset = -1;
  gst_audio_info_init (&aagg->info);
  gst_caps_replace (&aagg->current_caps, NULL);
  gst_buffer_replace (&aagg->priv->current_buffer, NULL);
  GST_OBJECT_UNLOCK (aagg);
  GST_AUDIO_AGGREGATOR_UNLOCK (aagg);
}
コード例 #2
0
ファイル: gstavauddec.c プロジェクト: GStreamer/gst-libav
static gboolean
gst_ffmpegauddec_stop (GstAudioDecoder * decoder)
{
  GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder;

  GST_OBJECT_LOCK (ffmpegdec);
  gst_ffmpegauddec_close (ffmpegdec, FALSE);
  g_free (ffmpegdec->padded);
  ffmpegdec->padded = NULL;
  ffmpegdec->padded_size = 0;
  GST_OBJECT_UNLOCK (ffmpegdec);
  gst_audio_info_init (&ffmpegdec->info);
  gst_caps_replace (&ffmpegdec->last_caps, NULL);

  return TRUE;
}
コード例 #3
0
static void
gst_audio_aggregator_pad_init (GstAudioAggregatorPad * pad)
{
  pad->priv =
      G_TYPE_INSTANCE_GET_PRIVATE (pad, GST_TYPE_AUDIO_AGGREGATOR_PAD,
      GstAudioAggregatorPadPrivate);

  gst_audio_info_init (&pad->info);

  pad->priv->buffer = NULL;
  pad->priv->position = 0;
  pad->priv->size = 0;
  pad->priv->output_offset = -1;
  pad->priv->next_offset = -1;
  pad->priv->discont_time = GST_CLOCK_TIME_NONE;
}
コード例 #4
0
ファイル: gstsbcdec.c プロジェクト: 0p1pp1/gst-plugins-bad
static gboolean
gst_sbc_dec_set_format (GstAudioDecoder * audio_dec, GstCaps * caps)
{
  GstSbcDec *dec = GST_SBC_DEC (audio_dec);
  const gchar *channel_mode;
  GstAudioInfo info;
  GstStructure *s;
  gint channels, rate, subbands, blocks, bitpool;

  s = gst_caps_get_structure (caps, 0);
  gst_structure_get_int (s, "channels", &channels);
  gst_structure_get_int (s, "rate", &rate);

  /* save input format */
  channel_mode = gst_structure_get_string (s, "channel-mode");
  if (channel_mode == NULL ||
      !gst_structure_get_int (s, "subbands", &subbands) ||
      !gst_structure_get_int (s, "blocks", &blocks) ||
      !gst_structure_get_int (s, "bitpool", &bitpool))
    return FALSE;

  if (strcmp (channel_mode, "mono") == 0) {
    dec->frame_len = 4 + (subbands * 1) / 2 + ((blocks * 1 * bitpool) + 7) / 8;
  } else if (strcmp (channel_mode, "dual") == 0) {
    dec->frame_len = 4 + (subbands * 2) / 2 + ((blocks * 2 * bitpool) + 7) / 8;
  } else if (strcmp (channel_mode, "stereo") == 0) {
    dec->frame_len = 4 + (subbands * 2) / 2 + ((blocks * bitpool) + 7) / 8;
  } else if (strcmp (channel_mode, "joint") == 0) {
    dec->frame_len =
        4 + (subbands * 2) / 2 + ((subbands + blocks * bitpool) + 7) / 8;
  } else {
    return FALSE;
  }

  dec->samples_per_frame = channels * blocks * subbands;

  GST_INFO_OBJECT (dec, "frame len: %" G_GSIZE_FORMAT ", samples per frame "
      "%" G_GSIZE_FORMAT, dec->frame_len, dec->samples_per_frame);

  /* set up output format */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, rate, channels, NULL);
  gst_audio_decoder_set_output_format (audio_dec, &info);

  return TRUE;
}
コード例 #5
0
ファイル: deinterleave.c プロジェクト: PeterXu/gst-mobile
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);
}
コード例 #6
0
static gboolean
gst_amc_audio_dec_set_src_caps (GstAmcAudioDec * self, GstAmcFormat * format)
{
  gint rate, channels;
  guint32 channel_mask = 0;
  GstAudioChannelPosition to[64];

  if (!gst_amc_format_get_int (format, "sample-rate", &rate) ||
      !gst_amc_format_get_int (format, "channel-count", &channels)) {
    GST_ERROR_OBJECT (self, "Failed to get output format metadata");
    return FALSE;
  }

  if (rate == 0 || channels == 0) {
    GST_ERROR_OBJECT (self, "Rate or channels not set");
    return FALSE;
  }

  /* Not always present */
  if (gst_amc_format_contains_key (format, "channel-mask"))
    gst_amc_format_get_int (format, "channel-mask", (gint *) & channel_mask);

  gst_amc_audio_channel_mask_to_positions (channel_mask, channels,
      self->positions);
  memcpy (to, self->positions, sizeof (to));
  gst_audio_channel_positions_to_valid_order (to, channels);
  self->needs_reorder =
      (memcmp (self->positions, to,
          sizeof (GstAudioChannelPosition) * channels) != 0);
  if (self->needs_reorder)
    gst_audio_get_channel_reorder_map (channels, self->positions, to,
        self->reorder_map);

  gst_audio_info_init (&self->info);
  gst_audio_info_set_format (&self->info, GST_AUDIO_FORMAT_S16, rate, channels,
      to);

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (self),
          &self->info))
    return FALSE;

  self->input_caps_changed = FALSE;

  return TRUE;
}
コード例 #7
0
ファイル: gstopusdec.c プロジェクト: Lachann/gst-plugins-bad
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;
}
コード例 #8
0
static void
gst_audio_aggregator_init (GstAudioAggregator * aagg)
{
  aagg->priv =
      G_TYPE_INSTANCE_GET_PRIVATE (aagg, GST_TYPE_AUDIO_AGGREGATOR,
      GstAudioAggregatorPrivate);

  g_mutex_init (&aagg->priv->mutex);

  aagg->priv->output_buffer_duration = DEFAULT_OUTPUT_BUFFER_DURATION;
  aagg->priv->alignment_threshold = DEFAULT_ALIGNMENT_THRESHOLD;
  aagg->priv->discont_wait = DEFAULT_DISCONT_WAIT;

  aagg->current_caps = NULL;
  gst_audio_info_init (&aagg->info);

  gst_aggregator_set_latency (GST_AGGREGATOR (aagg),
      aagg->priv->output_buffer_duration, aagg->priv->output_buffer_duration);
}
コード例 #9
0
static void
gst_wavpack_dec_negotiate (GstWavpackDec * dec)
{
  GstAudioInfo info;
  GstAudioFormat fmt;
  GstAudioChannelPosition pos[64] = { GST_AUDIO_CHANNEL_POSITION_INVALID, };

  /* arrange for 1, 2 or 4-byte width == depth output */
  dec->width = dec->depth;
  switch (dec->depth) {
    case 8:
      fmt = GST_AUDIO_FORMAT_S8;
      break;
    case 16:
      fmt = _GST_AUDIO_FORMAT_NE (S16);
      break;
    case 24:
    case 32:
      fmt = _GST_AUDIO_FORMAT_NE (S32);
      dec->width = 32;
      break;
    default:
      fmt = GST_AUDIO_FORMAT_UNKNOWN;
      g_assert_not_reached ();
      break;
  }

  g_assert (dec->channel_mask != 0);

  if (!gst_wavpack_get_channel_positions (dec->channels,
          dec->channel_mask, pos))
    GST_WARNING_OBJECT (dec, "Failed to set channel layout");

  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, fmt, dec->sample_rate, dec->channels, pos);

  gst_audio_channel_positions_to_valid_order (info.position, info.channels);
  gst_audio_get_channel_reorder_map (info.channels,
      info.position, pos, dec->channel_reorder_map);

  /* should always succeed */
  gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info);
}
コード例 #10
0
ファイル: gstlevel.c プロジェクト: nnikos123/gst-plugins-good
static void
gst_level_init (GstLevel * filter)
{
  filter->CS = NULL;
  filter->peak = NULL;
  filter->last_peak = NULL;
  filter->decay_peak = NULL;
  filter->decay_peak_base = NULL;
  filter->decay_peak_age = NULL;

  gst_audio_info_init (&filter->info);

  filter->interval = GST_SECOND / 10;
  filter->decay_peak_ttl = GST_SECOND / 10 * 3;
  filter->decay_peak_falloff = 10.0;    /* dB falloff (/sec) */

  filter->post_messages = TRUE;

  filter->process = NULL;

  gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE);
}
コード例 #11
0
static gboolean
gst_audio_segment_clip_set_caps (GstSegmentClip * base, GstCaps * caps)
{
  GstAudioSegmentClip *self = GST_AUDIO_SEGMENT_CLIP (base);
  gboolean ret;
  GstAudioInfo info;
  gint rate, channels, width;

  gst_audio_info_init (&info);
  ret = gst_audio_info_from_caps (&info, caps);

  if (ret) {
    rate = GST_AUDIO_INFO_RATE (&info);
    channels = GST_AUDIO_INFO_CHANNELS (&info);
    width = GST_AUDIO_INFO_WIDTH (&info);

    GST_DEBUG_OBJECT (self, "Configured: rate %d channels %d width %d",
        rate, channels, width);
    self->rate = rate;
    self->framesize = (width / 8) * channels;
  }

  return ret;
}
コード例 #12
0
static gboolean
gst_mulawdec_set_format (GstAudioDecoder * dec, GstCaps * caps)
{
    GstMuLawDec *mulawdec = GST_MULAWDEC (dec);
    GstStructure *structure;
    int rate, channels;
    GstAudioInfo info;

    structure = gst_caps_get_structure (caps, 0);
    if (!structure) {
        GST_ERROR ("failed to get structure from caps");
        goto error_failed_get_structure;
    }

    if (!gst_structure_get_int (structure, "rate", &rate)) {
        GST_ERROR ("failed to find field rate in input caps");
        goto error_failed_find_rate;
    }

    if (!gst_structure_get_int (structure, "channels", &channels)) {
        GST_ERROR ("failed to find field channels in input caps");
        goto error_failed_find_channel;
    }

    gst_audio_info_init (&info);
    gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, rate, channels, NULL);

    GST_DEBUG_OBJECT (mulawdec, "rate=%d, channels=%d", rate, channels);

    return gst_audio_decoder_set_output_format (dec, &info);

error_failed_find_channel:
error_failed_find_rate:
error_failed_get_structure:
    return FALSE;
}
コード例 #13
0
static gboolean
gst_mpg123_audio_dec_set_format (GstAudioDecoder * dec, GstCaps * input_caps)
{
/* Using the parsed information upstream, and the list of allowed caps
 * downstream, this code tries to find a suitable audio info. It is important
 * to keep in mind that the rate and number of channels should never deviate
 * from the one the bitstream has, otherwise mpg123 has to mix channels and/or
 * resample (and as its docs say, its internal resampler is very crude). The
 * sample format, however, can be chosen freely, because the MPEG specs do not
 * mandate any special format. Therefore, rate and number of channels are taken
 * from upstream (which parsed the MPEG frames, so the input_caps contain
 * exactly the rate and number of channels the bitstream actually has), while
 * the sample format is chosen by trying out all caps that are allowed by
 * downstream. This way, the output is adjusted to what the downstream prefers.
 *
 * Also, the new output audio info is not set immediately. Instead, it is
 * considered the "next audioinfo". The code waits for mpg123 to notice the new
 * format (= when mpg123_decode_frame() returns MPG123_AUDIO_DEC_NEW_FORMAT),
 * and then sets the next audioinfo. Otherwise, the next audioinfo is set too
 * soon, which may cause problems with mp3s containing several format headers.
 * One example would be an mp3 with the first 30 seconds using 44.1 kHz, then
 * the next 30 seconds using 32 kHz. Rare, but possible.
 *
 * STEPS:
 *
 * 1. get rate and channels from input_caps
 * 2. get allowed caps from src pad
 * 3. for each structure in allowed caps:
 * 3.1. take format
 * 3.2. if the combination of format with rate and channels is unsupported by
 *      mpg123, go to (3), or exit with error if there are no more structures
 *      to try
 * 3.3. create next audioinfo out of rate,channels,format, and exit
 */


  int rate, channels;
  GstMpg123AudioDec *mpg123_decoder;
  GstCaps *allowed_srccaps;
  guint structure_nr;
  gboolean match_found = FALSE;

  mpg123_decoder = GST_MPG123_AUDIO_DEC (dec);

  g_assert (mpg123_decoder->handle != NULL);

  mpg123_decoder->has_next_audioinfo = FALSE;

  /* Get rate and channels from input_caps */
  {
    GstStructure *structure;
    gboolean err = FALSE;

    /* Only the first structure is used (multiple
     * input caps structures don't make sense */
    structure = gst_caps_get_structure (input_caps, 0);

    if (!gst_structure_get_int (structure, "rate", &rate)) {
      err = TRUE;
      GST_ERROR_OBJECT (dec, "Input caps do not have a rate value");
    }
    if (!gst_structure_get_int (structure, "channels", &channels)) {
      err = TRUE;
      GST_ERROR_OBJECT (dec, "Input caps do not have a channel value");
    }

    if (err)
      return FALSE;
  }

  /* Get the caps that are allowed by downstream */
  {
    GstCaps *allowed_srccaps_unnorm =
        gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
    allowed_srccaps = gst_caps_normalize (allowed_srccaps_unnorm);
  }

  /* Go through all allowed caps, pick the first one that matches */
  for (structure_nr = 0; structure_nr < gst_caps_get_size (allowed_srccaps);
      ++structure_nr) {
    GstStructure *structure;
    gchar const *format_str;
    GstAudioFormat format;
    int encoding;

    structure = gst_caps_get_structure (allowed_srccaps, structure_nr);

    format_str = gst_structure_get_string (structure, "format");
    if (format_str == NULL) {
      GST_DEBUG_OBJECT (dec, "Could not get format from src caps");
      continue;
    }

    format = gst_audio_format_from_string (format_str);
    if (format == GST_AUDIO_FORMAT_UNKNOWN) {
      GST_DEBUG_OBJECT (dec, "Unknown format %s", format_str);
      continue;
    }

    switch (format) {
      case GST_AUDIO_FORMAT_S16:
        encoding = MPG123_ENC_SIGNED_16;
        break;
      case GST_AUDIO_FORMAT_S24:
        encoding = MPG123_ENC_SIGNED_24;
        break;
      case GST_AUDIO_FORMAT_S32:
        encoding = MPG123_ENC_SIGNED_32;
        break;
      case GST_AUDIO_FORMAT_U16:
        encoding = MPG123_ENC_UNSIGNED_16;
        break;
      case GST_AUDIO_FORMAT_U24:
        encoding = MPG123_ENC_UNSIGNED_24;
        break;
      case GST_AUDIO_FORMAT_U32:
        encoding = MPG123_ENC_UNSIGNED_32;
        break;
      case GST_AUDIO_FORMAT_F32:
        encoding = MPG123_ENC_FLOAT_32;
        break;
      default:
        GST_DEBUG_OBJECT (dec,
            "Format %s in srccaps is not supported", format_str);
        continue;
    }

    {
      int err;

      /* Cleanup old formats & set new one */
      mpg123_format_none (mpg123_decoder->handle);
      err = mpg123_format (mpg123_decoder->handle, rate, channels, encoding);
      if (err != MPG123_OK) {
        GST_DEBUG_OBJECT (dec,
            "mpg123 cannot use caps %" GST_PTR_FORMAT
            " because mpg123_format() failed: %s", structure,
            mpg123_strerror (mpg123_decoder->handle));
        continue;
      }
    }

    gst_audio_info_init (&(mpg123_decoder->next_audioinfo));
    gst_audio_info_set_format (&(mpg123_decoder->next_audioinfo), format, rate,
        channels, NULL);
    GST_LOG_OBJECT (dec, "The next audio format is: %s, %u Hz, %u channels",
        format_str, rate, channels);
    mpg123_decoder->has_next_audioinfo = TRUE;

    match_found = TRUE;

    break;
  }

  gst_caps_unref (allowed_srccaps);

  return match_found;
}
コード例 #14
0
static void
gst_omx_audio_dec_loop (GstOMXAudioDec * self)
{
  GstOMXPort *port = self->dec_out_port;
  GstOMXBuffer *buf = NULL;
  GstFlowReturn flow_ret = GST_FLOW_OK;
  GstOMXAcquireBufferReturn acq_return;
  OMX_ERRORTYPE err;

  acq_return = gst_omx_port_acquire_buffer (port, &buf);
  if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
    goto component_error;
  } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
    goto flushing;
  } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
    goto eos;
  }

  if (!gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (self)) ||
      acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
    OMX_PARAM_PORTDEFINITIONTYPE port_def;
    OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
    GstAudioChannelPosition omx_position[OMX_AUDIO_MAXCHANNELS];
    GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
    gint i;

    GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");

    /* Reallocate all buffers */
    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
        && gst_omx_port_is_enabled (port)) {
      err = gst_omx_port_set_enabled (port, FALSE);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_deallocate_buffers (port);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;
    }

    /* Just update caps */
    GST_AUDIO_DECODER_STREAM_LOCK (self);

    gst_omx_port_get_port_definition (port, &port_def);
    g_assert (port_def.format.audio.eEncoding == OMX_AUDIO_CodingPCM);

    GST_OMX_INIT_STRUCT (&pcm_param);
    pcm_param.nPortIndex = self->dec_out_port->index;
    err =
        gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioPcm,
        &pcm_param);
    if (err != OMX_ErrorNone) {
      GST_ERROR_OBJECT (self, "Failed to get PCM parameters: %s (0x%08x)",
          gst_omx_error_to_string (err), err);
      goto caps_failed;
    }

    g_assert (pcm_param.ePCMMode == OMX_AUDIO_PCMModeLinear);
    g_assert (pcm_param.bInterleaved == OMX_TRUE);

    gst_audio_info_init (&self->info);

    for (i = 0; i < pcm_param.nChannels; i++) {
      switch (pcm_param.eChannelMapping[i]) {
        case OMX_AUDIO_ChannelLF:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
          break;
        case OMX_AUDIO_ChannelRF:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
          break;
        case OMX_AUDIO_ChannelCF:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
          break;
        case OMX_AUDIO_ChannelLS:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
          break;
        case OMX_AUDIO_ChannelRS:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
          break;
        case OMX_AUDIO_ChannelLFE:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
          break;
        case OMX_AUDIO_ChannelCS:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
          break;
        case OMX_AUDIO_ChannelLR:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
          break;
        case OMX_AUDIO_ChannelRR:
          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
          break;
        case OMX_AUDIO_ChannelNone:
        default:
          /* This will break the outer loop too as the
           * i == pcm_param.nChannels afterwards */
          for (i = 0; i < pcm_param.nChannels; i++)
            omx_position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
          break;
      }
    }
    if (pcm_param.nChannels == 1
        && omx_position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER)
      omx_position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;

    if (omx_position[0] == GST_AUDIO_CHANNEL_POSITION_NONE
        && klass->get_channel_positions) {
      GST_WARNING_OBJECT (self,
          "Failed to get a valid channel layout, trying fallback");
      klass->get_channel_positions (self, self->dec_out_port, omx_position);
    }

    memcpy (self->position, omx_position, sizeof (omx_position));
    gst_audio_channel_positions_to_valid_order (self->position,
        pcm_param.nChannels);
    self->needs_reorder =
        (memcmp (self->position, omx_position,
            sizeof (GstAudioChannelPosition) * pcm_param.nChannels) != 0);
    if (self->needs_reorder)
      gst_audio_get_channel_reorder_map (pcm_param.nChannels, self->position,
          omx_position, self->reorder_map);

    gst_audio_info_set_format (&self->info,
        gst_audio_format_build_integer (pcm_param.eNumData ==
            OMX_NumericalDataSigned,
            pcm_param.eEndian ==
            OMX_EndianLittle ? G_LITTLE_ENDIAN : G_BIG_ENDIAN,
            pcm_param.nBitPerSample, pcm_param.nBitPerSample),
        pcm_param.nSamplingRate, pcm_param.nChannels, self->position);

    GST_DEBUG_OBJECT (self,
        "Setting output state: format %s, rate %u, channels %u",
        gst_audio_format_to_string (self->info.finfo->format),
        (guint) pcm_param.nSamplingRate, (guint) pcm_param.nChannels);

    if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (self),
            &self->info)
        || !gst_audio_decoder_negotiate (GST_AUDIO_DECODER (self))) {
      if (buf)
        gst_omx_port_release_buffer (port, buf);
      goto caps_failed;
    }

    GST_AUDIO_DECODER_STREAM_UNLOCK (self);

    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
      err = gst_omx_port_set_enabled (port, TRUE);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_allocate_buffers (port);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_populate (port);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;

      err = gst_omx_port_mark_reconfigured (port);
      if (err != OMX_ErrorNone)
        goto reconfigure_error;
    }

    /* Now get a buffer */
    if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
      return;
    }
  }

  g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
  if (!buf) {
    g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
    GST_AUDIO_DECODER_STREAM_LOCK (self);
    goto eos;
  }

  /* This prevents a deadlock between the srcpad stream
   * lock and the audiocodec stream lock, if ::reset()
   * is called at the wrong time
   */
  if (gst_omx_port_is_flushing (port)) {
    GST_DEBUG_OBJECT (self, "Flushing");
    gst_omx_port_release_buffer (port, buf);
    goto flushing;
  }

  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
      (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);

  GST_AUDIO_DECODER_STREAM_LOCK (self);

  if (buf->omx_buf->nFilledLen > 0) {
    GstBuffer *outbuf;
    gint nframes, spf;
    GstMapInfo minfo;
    GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);

    GST_DEBUG_OBJECT (self, "Handling output data");

    if (buf->omx_buf->nFilledLen % self->info.bpf != 0) {
      gst_omx_port_release_buffer (port, buf);
      goto invalid_buffer;
    }

    outbuf =
        gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (self),
        buf->omx_buf->nFilledLen);

    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
    if (self->needs_reorder) {
      gint i, n_samples, c, n_channels;
      gint *reorder_map = self->reorder_map;
      gint16 *dest, *source;

      dest = (gint16 *) minfo.data;
      source = (gint16 *) (buf->omx_buf->pBuffer + buf->omx_buf->nOffset);
      n_samples = buf->omx_buf->nFilledLen / self->info.bpf;
      n_channels = self->info.channels;

      for (i = 0; i < n_samples; i++) {
        for (c = 0; c < n_channels; c++) {
          dest[i * n_channels + reorder_map[c]] = source[i * n_channels + c];
        }
      }
    } else {
      memcpy (minfo.data, buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
          buf->omx_buf->nFilledLen);
    }
    gst_buffer_unmap (outbuf, &minfo);

    nframes = 1;
    spf = klass->get_samples_per_frame (self, self->dec_out_port);
    if (spf != -1) {
      nframes = buf->omx_buf->nFilledLen / self->info.bpf;
      if (nframes % spf != 0)
        GST_WARNING_OBJECT (self, "Output buffer does not contain an integer "
            "number of input frames (frames: %d, spf: %d)", nframes, spf);
      nframes = (nframes + spf - 1) / spf;
    }

    GST_BUFFER_TIMESTAMP (outbuf) =
        gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
        OMX_TICKS_PER_SECOND);
    if (buf->omx_buf->nTickCount != 0)
      GST_BUFFER_DURATION (outbuf) =
          gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND,
          OMX_TICKS_PER_SECOND);

    flow_ret =
        gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
        nframes);
  }

  GST_DEBUG_OBJECT (self, "Read frame from component");

  GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));

  if (buf) {
    err = gst_omx_port_release_buffer (port, buf);
    if (err != OMX_ErrorNone)
      goto release_error;
  }

  self->downstream_flow_ret = flow_ret;

  if (flow_ret != GST_FLOW_OK)
    goto flow_error;

  GST_AUDIO_DECODER_STREAM_UNLOCK (self);

  return;

component_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
        ("OpenMAX component in error state %s (0x%08x)",
            gst_omx_component_get_last_error_string (self->dec),
            gst_omx_component_get_last_error (self->dec)));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    self->started = FALSE;
    return;
  }

flushing:
  {
    GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_FLUSHING;
    self->started = FALSE;
    return;
  }

eos:
  {
    g_mutex_lock (&self->drain_lock);
    if (self->draining) {
      GST_DEBUG_OBJECT (self, "Drained");
      self->draining = FALSE;
      g_cond_broadcast (&self->drain_cond);
      flow_ret = GST_FLOW_OK;
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    } else {
      GST_DEBUG_OBJECT (self, "Component signalled EOS");
      flow_ret = GST_FLOW_EOS;
    }
    g_mutex_unlock (&self->drain_lock);

    GST_AUDIO_DECODER_STREAM_LOCK (self);
    self->downstream_flow_ret = flow_ret;

    /* Here we fallback and pause the task for the EOS case */
    if (flow_ret != GST_FLOW_OK)
      goto flow_error;

    GST_AUDIO_DECODER_STREAM_UNLOCK (self);

    return;
  }

flow_error:
  {
    if (flow_ret == GST_FLOW_EOS) {
      GST_DEBUG_OBJECT (self, "EOS");

      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
          gst_event_new_eos ());
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
      self->started = FALSE;
    } else if (flow_ret < GST_FLOW_EOS) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          ("Internal data stream error."), ("stream stopped, reason %s",
              gst_flow_get_name (flow_ret)));

      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
          gst_event_new_eos ());
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
      self->started = FALSE;
    } else if (flow_ret == GST_FLOW_FLUSHING) {
      GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
      self->started = FALSE;
    }
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

reconfigure_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
        ("Unable to reconfigure output port"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    self->started = FALSE;
    return;
  }

invalid_buffer:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
        ("Invalid sized input buffer"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
    self->started = FALSE;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }

caps_failed:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
    self->started = FALSE;
    return;
  }
release_error:
  {
    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
        ("Failed to relase output buffer to component: %s (0x%08x)",
            gst_omx_error_to_string (err), err));
    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
    self->downstream_flow_ret = GST_FLOW_ERROR;
    self->started = FALSE;
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    return;
  }
}
コード例 #15
0
static gboolean
gst_raw_audio_parse_config_to_caps (GstRawAudioParse * raw_audio_parse,
    GstCaps ** caps, GstRawAudioParseConfig * config)
{
  gboolean ret = TRUE;
  GstAudioChannelPosition *channel_positions;

  g_assert (caps != NULL);

  if (config->bpf == 0) {
    GST_ERROR_OBJECT (raw_audio_parse,
        "cannot convert config to caps - config not filled with valid values");
    *caps = NULL;
    return FALSE;
  }

  channel_positions =
      config->needs_channel_reordering ? &(config->
      reordered_channel_positions[0]) : &(config->channel_positions[0]);

  switch (config->format) {
    case GST_RAW_AUDIO_PARSE_FORMAT_PCM:
    {
      GstAudioInfo info;
      gst_audio_info_init (&info);
      gst_audio_info_set_format (&info,
          config->pcm_format,
          config->sample_rate, config->num_channels, channel_positions);

      *caps = gst_audio_info_to_caps (&info);

      break;
    }

    case GST_RAW_AUDIO_PARSE_FORMAT_ALAW:
    case GST_RAW_AUDIO_PARSE_FORMAT_MULAW:
    {
      guint64 channel_mask;

      if (!gst_audio_channel_positions_to_mask (channel_positions,
              config->num_channels, TRUE, &channel_mask)) {
        GST_ERROR_OBJECT (raw_audio_parse, "invalid channel positions");
        ret = FALSE;
        break;
      }

      *caps = gst_caps_new_simple (
          (config->format ==
              GST_RAW_AUDIO_PARSE_FORMAT_ALAW) ? "audio/x-alaw" :
          "audio/x-mulaw", "rate", G_TYPE_INT, config->sample_rate, "channels",
          G_TYPE_INT, config->num_channels, "channel-mask", GST_TYPE_BITMASK,
          channel_mask, NULL);

      break;
    }

    default:
      g_assert_not_reached ();
      ret = FALSE;
  }

  if (!ret)
    *caps = NULL;

  return ret;
}
コード例 #16
0
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;
}
コード例 #17
0
ファイル: gstdroidadec.c プロジェクト: rss351/gst-droid
static void
gst_droidadec_data_available (void *data, DroidMediaCodecData * encoded)
{
  GstFlowReturn flow_ret;
  GstDroidADec *dec = (GstDroidADec *) data;
  GstAudioDecoder *decoder = GST_AUDIO_DECODER (dec);
  GstBuffer *out;
  GstMapInfo info;

  GST_DEBUG_OBJECT (dec, "data available of size %d", encoded->data.size);

  GST_AUDIO_DECODER_STREAM_LOCK (decoder);

  if (G_UNLIKELY (dec->downstream_flow_ret != GST_FLOW_OK)) {
    GST_DEBUG_OBJECT (dec, "not handling data in error state: %s",
        gst_flow_get_name (dec->downstream_flow_ret));
    flow_ret = dec->downstream_flow_ret;
    gst_audio_decoder_finish_frame (decoder, NULL, 1);
    goto out;
  }

  if (G_UNLIKELY (gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER
              (dec))->finfo->format == GST_AUDIO_FORMAT_UNKNOWN)) {
    DroidMediaCodecMetaData md;
    DroidMediaRect crop;        /* TODO: get rid of that */
    GstAudioInfo info;

    memset (&md, 0x0, sizeof (md));
    droid_media_codec_get_output_info (dec->codec, &md, &crop);
    GST_INFO_OBJECT (dec, "output rate=%d, output channels=%d", md.sample_rate,
        md.channels);

    gst_audio_info_init (&info);
    gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, md.sample_rate,
        md.channels, NULL);

    if (!gst_audio_decoder_set_output_format (decoder, &info)) {
      flow_ret = GST_FLOW_ERROR;
      goto out;
    }

    dec->info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (dec));
  }

  out = gst_audio_decoder_allocate_output_buffer (decoder, encoded->data.size);

  gst_buffer_map (out, &info, GST_MAP_READWRITE);
  orc_memcpy (info.data, encoded->data.data, encoded->data.size);
  gst_buffer_unmap (out, &info);

  //  GST_WARNING_OBJECT (dec, "bpf %d, bps %d", dec->info->bpf, GST_AUDIO_INFO_BPS(dec->info));
  if (dec->spf == -1 || (encoded->data.size == dec->spf * dec->info->bpf
          && gst_adapter_available (dec->adapter) == 0)) {
    /* fast path. no need for anything */
    goto push;
  }

  gst_adapter_push (dec->adapter, out);

  if (gst_adapter_available (dec->adapter) >= dec->spf * dec->info->bpf) {
    out = gst_adapter_take_buffer (dec->adapter, dec->spf * dec->info->bpf);
  } else {
    flow_ret = GST_FLOW_OK;
    goto out;
  }

push:
  GST_DEBUG_OBJECT (dec, "pushing %d bytes out", gst_buffer_get_size (out));

  flow_ret = gst_audio_decoder_finish_frame (decoder, out, 1);

  if (flow_ret == GST_FLOW_OK || flow_ret == GST_FLOW_FLUSHING) {
    goto out;
  } else if (flow_ret == GST_FLOW_EOS) {
    GST_INFO_OBJECT (dec, "eos");
  } else if (flow_ret < GST_FLOW_OK) {
    GST_ELEMENT_ERROR (dec, STREAM, FAILED,
        ("Internal data stream error."), ("stream stopped, reason %s",
            gst_flow_get_name (flow_ret)));
  }

out:
  dec->downstream_flow_ret = flow_ret;
  GST_AUDIO_DECODER_STREAM_UNLOCK (decoder);
}
コード例 #18
0
static GstCaps *
gst_audio_parse_get_caps (GstRawParse * rp)
{
  GstAudioParse *ap = GST_AUDIO_PARSE (rp);
  GstCaps *caps, *ncaps;
  GstAudioInfo info;
  gint fps_n, fps_d;
  const GValue *val;

  if (ap->use_sink_caps) {
    gint rate;
    GstCaps *caps = gst_pad_get_current_caps (rp->sinkpad);
    gst_audio_info_from_caps (&info, caps);

    rate = GST_AUDIO_INFO_RATE (&info);
    gst_raw_parse_set_fps (GST_RAW_PARSE (ap), rate, 1);

    return caps;
  }

  gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
  gst_audio_parse_setup_channel_positions (ap);

  /* yes, even when format not raw */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, ap->raw_format, fps_n, ap->channels,
      ap->channel_order);
  info.layout = ap->interleaved ? GST_AUDIO_LAYOUT_INTERLEAVED :
      GST_AUDIO_LAYOUT_NON_INTERLEAVED;
  caps = gst_audio_info_to_caps (&info);

  switch (ap->format) {
    case GST_AUDIO_PARSE_FORMAT_RAW:
      break;
    case GST_AUDIO_PARSE_FORMAT_ALAW:
      ncaps = gst_caps_new_simple ("audio/x-alaw",
          "rate", G_TYPE_INT, fps_n,
          "channels", G_TYPE_INT, ap->channels, NULL);
      /* pick mask stuff from faked raw format */
      val = gst_structure_get_value (gst_caps_get_structure (caps, 0),
          "channel-mask");
      if (val)
        gst_caps_set_value (ncaps, "channel-mask", val);
      gst_caps_unref (caps);
      caps = ncaps;
      break;
    case GST_AUDIO_PARSE_FORMAT_MULAW:
      ncaps = gst_caps_new_simple ("audio/x-mulaw",
          "rate", G_TYPE_INT, fps_n,
          "channels", G_TYPE_INT, ap->channels, NULL);
      /* pick mask stuff from faked raw format */
      val = gst_structure_get_value (gst_caps_get_structure (caps, 0),
          "channel-mask");
      if (val)
        gst_caps_set_value (ncaps, "channel-mask", val);
      gst_caps_unref (caps);
      caps = ncaps;
      break;
    default:
      caps = gst_caps_new_empty ();
      GST_ERROR_OBJECT (rp, "unexpected format %d", ap->format);
      break;
  }

  return caps;
}
コード例 #19
0
static gboolean
gst_rtp_L16_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstRtpL16Depay *rtpL16depay;
  gint clock_rate, payload;
  gint channels;
  GstCaps *srccaps;
  gboolean res;
  const gchar *channel_order;
  const GstRTPChannelOrder *order;
  GstAudioInfo *info;

  rtpL16depay = GST_RTP_L16_DEPAY (depayload);

  structure = gst_caps_get_structure (caps, 0);

  payload = 96;
  gst_structure_get_int (structure, "payload", &payload);
  switch (payload) {
    case GST_RTP_PAYLOAD_L16_STEREO:
      channels = 2;
      clock_rate = 44100;
      break;
    case GST_RTP_PAYLOAD_L16_MONO:
      channels = 1;
      clock_rate = 44100;
      break;
    default:
      /* no fixed mapping, we need clock-rate */
      channels = 0;
      clock_rate = 0;
      break;
  }

  /* caps can overwrite defaults */
  clock_rate =
      gst_rtp_L16_depay_parse_int (structure, "clock-rate", clock_rate);
  if (clock_rate == 0)
    goto no_clockrate;

  channels =
      gst_rtp_L16_depay_parse_int (structure, "encoding-params", channels);
  if (channels == 0) {
    channels = gst_rtp_L16_depay_parse_int (structure, "channels", channels);
    if (channels == 0) {
      /* channels defaults to 1 otherwise */
      channels = 1;
    }
  }

  depayload->clock_rate = clock_rate;

  info = &rtpL16depay->info;
  gst_audio_info_init (info);
  info->finfo = gst_audio_format_get_info (GST_AUDIO_FORMAT_S16BE);
  info->rate = clock_rate;
  info->channels = channels;
  info->bpf = (info->finfo->width / 8) * channels;

  /* add channel positions */
  channel_order = gst_structure_get_string (structure, "channel-order");

  order = gst_rtp_channels_get_by_order (channels, channel_order);
  rtpL16depay->order = order;
  if (order) {
    memcpy (info->position, order->pos,
        sizeof (GstAudioChannelPosition) * channels);
    gst_audio_channel_positions_to_valid_order (info->position, info->channels);
  } else {
    GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE,
        (NULL), ("Unknown channel order '%s' for %d channels",
            GST_STR_NULL (channel_order), channels));
    /* create default NONE layout */
    gst_rtp_channels_create_default (channels, info->position);
  }

  srccaps = gst_audio_info_to_caps (info);
  res = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return res;

  /* ERRORS */
no_clockrate:
  {
    GST_ERROR_OBJECT (depayload, "no clock-rate specified");
    return FALSE;
  }
}
コード例 #20
0
static GstCaps *
gst_dshowaudiosrc_getcaps_from_streamcaps (GstDshowAudioSrc * src, IPin * pin,
    IAMStreamConfig * streamcaps)
{
  GstCaps *caps = NULL;
  HRESULT hres = S_OK;
  int icount = 0;
  int isize = 0;
  AUDIO_STREAM_CONFIG_CAPS ascc;
  int i = 0;

  if (!streamcaps)
    return NULL;

  streamcaps->GetNumberOfCapabilities (&icount, &isize);

  if (isize != sizeof (ascc))
    return NULL;

  for (; i < icount; i++) {
    GstCapturePinMediaType *pin_mediatype = g_new0 (GstCapturePinMediaType, 1);

    pin->AddRef ();
    pin_mediatype->capture_pin = pin;

    hres = streamcaps->GetStreamCaps (i, &pin_mediatype->mediatype,
        (BYTE *) & ascc);
    if (hres == S_OK && pin_mediatype->mediatype) {
      GstCaps *mediacaps = NULL;

      if (!caps)
        caps = gst_caps_new_empty ();

      if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_PCM,
              FORMAT_WaveFormatEx)) {
	GstAudioFormat format = GST_AUDIO_FORMAT_UNKNOWN;
        WAVEFORMATEX *wavformat =
            (WAVEFORMATEX *) pin_mediatype->mediatype->pbFormat;

	switch (wavformat->wFormatTag) {
            case WAVE_FORMAT_PCM:
	      format = gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, wavformat->wBitsPerSample, wavformat->wBitsPerSample);
	      break;
            default:
	      break;
	}

	if (format != GST_AUDIO_FORMAT_UNKNOWN) {
	  GstAudioInfo info;

	  gst_audio_info_init(&info);
	  gst_audio_info_set_format(&info,
				    format,
				    wavformat->nSamplesPerSec,
				    wavformat->nChannels,
				    NULL);
	  mediacaps = gst_audio_info_to_caps(&info);
	}

        if (mediacaps) {
          src->pins_mediatypes =
              g_list_append (src->pins_mediatypes, pin_mediatype);
          gst_caps_append (caps, mediacaps);
        } else {
          gst_dshow_free_pin_mediatype (pin_mediatype);
        }
      } else {
        gst_dshow_free_pin_mediatype (pin_mediatype);
      }
    } else {
      gst_dshow_free_pin_mediatype (pin_mediatype);
    }
  }

  if (caps && gst_caps_is_empty (caps)) {
    gst_caps_unref (caps);
    caps = NULL;
  }

  return caps;
}
コード例 #21
0
ファイル: gstspeexdec.c プロジェクト: pexip/gst-plugins-good
static GstFlowReturn
gst_speex_dec_parse_header (GstSpeexDec * dec, GstBuffer * buf)
{
  SpeexHeader *header;
  GstMapInfo map;
  GstAudioInfo info;
  static const GstAudioChannelPosition chan_pos[2][2] = {
    {GST_AUDIO_CHANNEL_POSITION_MONO},
    {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
  };

  /* get the header */
  gst_buffer_map (buf, &map, GST_MAP_READ);
  header = speex_packet_to_header ((gchar *) map.data, map.size);
  gst_buffer_unmap (buf, &map);

  if (!header)
    goto no_header;

  if (dec->header) {
    GST_DEBUG_OBJECT (dec, "Replacing speex-header, resetting state");
    gst_speex_dec_reset (dec);
  }
  dec->header = header;

  if (dec->header->mode >= SPEEX_NB_MODES || dec->header->mode < 0)
    goto mode_too_old;

  dec->mode = speex_lib_get_mode (dec->header->mode);

  /* initialize the decoder */
  dec->state = speex_decoder_init (dec->mode);
  if (!dec->state)
    goto init_failed;

  speex_decoder_ctl (dec->state, SPEEX_SET_ENH, &dec->enh);
  speex_decoder_ctl (dec->state, SPEEX_GET_FRAME_SIZE, &dec->frame_size);

  if (dec->header->nb_channels != 1) {
    dec->stereo = speex_stereo_state_init ();
    dec->callback.callback_id = SPEEX_INBAND_STEREO;
    dec->callback.func = speex_std_stereo_request_handler;
    dec->callback.data = dec->stereo;
    speex_decoder_ctl (dec->state, SPEEX_SET_HANDLER, &dec->callback);
  }

  speex_decoder_ctl (dec->state, SPEEX_SET_SAMPLING_RATE, &dec->header->rate);

  dec->frame_duration = gst_util_uint64_scale_int (dec->frame_size,
      GST_SECOND, dec->header->rate);

  speex_bits_init (&dec->bits);

  /* set caps */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info,
      GST_AUDIO_FORMAT_S16,
      dec->header->rate,
      dec->header->nb_channels, chan_pos[dec->header->nb_channels - 1]);

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dec), &info))
    goto nego_failed;

  return GST_FLOW_OK;

  /* ERRORS */
no_header:
  {
    GST_INFO_OBJECT (dec, "couldn't read header");
    return GST_FLOW_NO_HEADER;
  }
mode_too_old:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL),
        ("Mode number %d does not (yet/any longer) exist in this version",
            dec->header->mode));
    return GST_FLOW_ERROR;
  }
init_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't initialize decoder"));
    return GST_FLOW_ERROR;
  }
nego_failed:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("couldn't negotiate format"));
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
コード例 #22
0
ファイル: deinterleave.c プロジェクト: PeterXu/gst-mobile
static gboolean
gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps)
{
  GstCaps *srccaps;
  GstStructure *s;

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

  if (!gst_audio_info_from_caps (&self->audio_info, caps))
    goto invalid_caps;

  if (!gst_deinterleave_set_process_function (self))
    goto unsupported_caps;

  if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
    gint i;
    gboolean same_layout = TRUE;
    gboolean was_unpositioned;
    gboolean is_unpositioned =
        GST_AUDIO_INFO_IS_UNPOSITIONED (&self->audio_info);
    gint new_channels = GST_AUDIO_INFO_CHANNELS (&self->audio_info);
    gint old_channels;
    GstAudioInfo old_info;

    gst_audio_info_init (&old_info);
    gst_audio_info_from_caps (&old_info, self->sinkcaps);
    was_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (&old_info);
    old_channels = GST_AUDIO_INFO_CHANNELS (&old_info);

    /* 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 (new_channels != old_channels ||
        !gst_deinterleave_set_process_function (self))
      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
     */
    if ((!was_unpositioned && is_unpositioned) || (was_unpositioned
            && !is_unpositioned))
      goto cannot_change_caps;

    if (!is_unpositioned) {
      if (GST_AUDIO_INFO_CHANNELS (&old_info) !=
          GST_AUDIO_INFO_CHANNELS (&self->audio_info))
        goto cannot_change_caps;
      for (i = 0; i < GST_AUDIO_INFO_CHANNELS (&old_info); i++) {
        if (self->audio_info.position[i] != old_info.position[i]) {
          same_layout = FALSE;
          break;
        }
      }
      if (!same_layout)
        goto cannot_change_caps;
    }

  }

  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-mask");

  /* 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);

  return TRUE;

cannot_change_caps:
  {
    GST_WARNING_OBJECT (self, "caps change from %" GST_PTR_FORMAT
        " to %" GST_PTR_FORMAT " not supported: channel number or channel "
        "positions change", self->sinkcaps, caps);
    return FALSE;
  }
unsupported_caps:
  {
    GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps);
    return FALSE;
  }
invalid_caps:
  {
    GST_ERROR_OBJECT (self, "invalid caps");
    return FALSE;
  }
}