예제 #1
0
static gboolean
gst_dtsdec_renegotiate (GstDtsDec * dts)
{
  gint channels;
  gboolean result = FALSE;
  GstAudioChannelPosition from[6], to[6];
  GstAudioInfo info;

  channels = gst_dtsdec_channels (dts->using_channels, from);

  if (!channels)
    goto done;

  GST_INFO_OBJECT (dts, "dtsdec renegotiate, channels=%d, rate=%d",
      channels, dts->sample_rate);

  memcpy (to, from, sizeof (GstAudioChannelPosition) * channels);
  gst_audio_channel_positions_to_valid_order (to, channels);
  gst_audio_get_channel_reorder_map (channels, from, to,
      dts->channel_reorder_map);


  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info,
      SAMPLE_TYPE, dts->sample_rate, channels, (channels > 1 ? to : NULL));

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dts), &info))
    goto done;

  result = TRUE;

done:
  return result;
}
예제 #2
0
static gboolean
adpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * in_caps)
{
  ADPCMDec *dec = (ADPCMDec *) (bdec);
  GstStructure *structure = gst_caps_get_structure (in_caps, 0);
  const gchar *layout;
  GstAudioInfo info;

  layout = gst_structure_get_string (structure, "layout");
  if (!layout)
    return FALSE;

  if (g_str_equal (layout, "microsoft"))
    dec->layout = LAYOUT_ADPCM_MICROSOFT;
  else if (g_str_equal (layout, "dvi"))
    dec->layout = LAYOUT_ADPCM_DVI;
  else
    return FALSE;

  if (!gst_structure_get_int (structure, "block_align", &dec->blocksize))
    dec->blocksize = -1;        /* Not provided */

  if (!gst_structure_get_int (structure, "rate", &dec->rate))
    return FALSE;
  if (!gst_structure_get_int (structure, "channels", &dec->channels))
    return FALSE;

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

  gst_audio_decoder_set_output_format (bdec, &info);
  return TRUE;
}
예제 #3
0
static gboolean
gst_siren_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
{
  GstAudioInfo info;

  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16LE, 16000, 1, NULL);
  return gst_audio_decoder_set_output_format (bdec, &info);
}
예제 #4
0
static gboolean
gst_gsmdec_set_format (GstAudioDecoder * dec, GstCaps * caps)
{
  GstGSMDec *gsmdec;
  GstStructure *s;
  gboolean ret = FALSE;
  gint rate;
  GstAudioInfo info;

  gsmdec = GST_GSMDEC (dec);

  s = gst_caps_get_structure (caps, 0);
  if (s == NULL)
    goto wrong_caps;

  /* figure out if we deal with plain or MSGSM */
  if (gst_structure_has_name (s, "audio/x-gsm"))
    gsmdec->use_wav49 = 0;
  else if (gst_structure_has_name (s, "audio/ms-gsm"))
    gsmdec->use_wav49 = 1;
  else
    goto wrong_caps;

  gsmdec->needed = 33;

  if (!gst_structure_get_int (s, "rate", &rate)) {
    GST_WARNING_OBJECT (gsmdec, "missing sample rate parameter from sink caps");
    goto beach;
  }

  /* MSGSM needs different framing */
  gsm_option (gsmdec->state, GSM_OPT_WAV49, &gsmdec->use_wav49);

  /* Setting up src caps based on the input sample rate. */
  gst_audio_info_init (&info);
  gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, rate, 1, NULL);

  ret = gst_audio_decoder_set_output_format (dec, &info);

  return ret;

  /* ERRORS */
wrong_caps:

  GST_ERROR_OBJECT (gsmdec, "invalid caps received");

beach:

  return ret;
}
예제 #5
0
static gboolean
gst_amc_audio_dec_set_src_caps (GstAmcAudioDec * self, GstAmcFormat * format)
{
  gint rate, channels;
  guint32 channel_mask = 0;
  GstAudioChannelPosition to[64];
  GError *err = NULL;

  if (!gst_amc_format_get_int (format, "sample-rate", &rate, &err) ||
      !gst_amc_format_get_int (format, "channel-count", &channels, &err)) {
    GST_ERROR_OBJECT (self, "Failed to get output format metadata: %s",
        err->message);
    g_clear_error (&err);
    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", NULL))
    gst_amc_format_get_int (format, "channel-mask", (gint *) & channel_mask,
        NULL);

  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;
}
예제 #6
0
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;
}
예제 #7
0
static GstFlowReturn
gst_audio_decoder_tester_handle_frame (GstAudioDecoder * dec,
    GstBuffer * buffer)
{
  GstAudioDecoderTester *tester = (GstAudioDecoderTester *) dec;
  guint8 *data;
  gint size;
  GstMapInfo map;
  GstBuffer *output_buffer;

  if (buffer == NULL)
    return GST_FLOW_OK;

  if (tester->setoutputformat_on_decoding) {
    GstCaps *caps;
    GstAudioInfo info;

    caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S32LE",
        "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100,
        "layout", G_TYPE_STRING, "interleaved", NULL);
    gst_audio_info_from_caps (&info, caps);
    gst_caps_unref (caps);

    gst_audio_decoder_set_output_format (dec, &info);
  }

  gst_buffer_map (buffer, &map, GST_MAP_READ);

  /* the output is SE32LE stereo 44100 Hz */
  size = 2 * 4;
  g_assert (size == sizeof (guint64));
  data = g_malloc0 (size);

  memcpy (data, map.data, sizeof (guint64));

  output_buffer = gst_buffer_new_wrapped (data, size);

  gst_buffer_unmap (buffer, &map);

  if (tester->output_too_many_frames) {
    return gst_audio_decoder_finish_frame (dec, output_buffer, 2);
  } else {
    return gst_audio_decoder_finish_frame (dec, output_buffer, 1);
  }
}
예제 #8
0
static void
gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
{
  GstCaps *caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
  GstStructure *s;
  GstAudioInfo info;

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

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

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

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

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

  dec->info = info;
}
예제 #9
0
static GstFlowReturn
vorbis_handle_identification_packet (GstVorbisDec * vd)
{
  GstAudioInfo info;

  switch (vd->vi.channels) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    {
      const GstAudioChannelPosition *pos;

      pos = gst_vorbis_default_channel_positions[vd->vi.channels - 1];
      gst_audio_info_set_format (&info, GST_VORBIS_AUDIO_FORMAT, vd->vi.rate,
          vd->vi.channels, pos);
      break;
    }
    default:{
      GstAudioChannelPosition position[64];
      gint i, max_pos = MAX (vd->vi.channels, 64);

      GST_ELEMENT_WARNING (vd, STREAM, DECODE,
          (NULL), ("Using NONE channel layout for more than 8 channels"));
      for (i = 0; i < max_pos; i++)
        position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
      gst_audio_info_set_format (&info, GST_VORBIS_AUDIO_FORMAT, vd->vi.rate,
          vd->vi.channels, position);
      break;
    }
  }

  gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (vd), &info);

  vd->info = info;
  /* select a copy_samples function, this way we can have specialized versions
   * for mono/stereo and avoid the depth switch in tremor case */
  vd->copy_samples = gst_vorbis_get_copy_sample_func (info.channels);

  return GST_FLOW_OK;
}
예제 #10
0
static gboolean
gst_audio_decoder_tester_set_format (GstAudioDecoder * dec, GstCaps * caps)
{
  GstAudioDecoderTester *tester = (GstAudioDecoderTester *) dec;
  GstAudioInfo info;
  gst_caps_unref (caps);

  if (!tester->setoutputformat_on_decoding) {
    caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S32LE",
        "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100,
        "layout", G_TYPE_STRING, "interleaved", NULL);
    gst_audio_info_from_caps (&info, caps);
    gst_caps_unref (caps);

    gst_audio_decoder_set_output_format (dec, &info);
  }
  return TRUE;
}
예제 #11
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);
}
예제 #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
파일: atdec.c 프로젝트: PeterXu/gst-mobile
static gboolean
gst_atdec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
{
  OSStatus status;
  AudioStreamBasicDescription input_format = { 0 };
  AudioStreamBasicDescription output_format = { 0 };
  GstAudioInfo output_info = { 0 };
  AudioChannelLayout output_layout = { 0 };
  GstCaps *output_caps;
  GstATDec *atdec = GST_ATDEC (decoder);

  GST_DEBUG_OBJECT (atdec, "set_format");

  if (atdec->queue)
    gst_atdec_destroy_queue (atdec, TRUE);

  /* configure input_format from caps */
  gst_caps_to_at_format (caps, &input_format);

  /* negotiate output caps */
  output_caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (atdec));
  if (!output_caps)
    output_caps =
        gst_pad_get_pad_template_caps (GST_AUDIO_DECODER_SRC_PAD (atdec));
  output_caps = gst_caps_fixate (output_caps);

  gst_caps_set_simple (output_caps,
      "rate", G_TYPE_INT, (int) input_format.mSampleRate,
      "channels", G_TYPE_INT, input_format.mChannelsPerFrame, NULL);

  /* configure output_format from caps */
  gst_caps_to_at_format (output_caps, &output_format);

  /* set the format we want to negotiate downstream */
  gst_audio_info_from_caps (&output_info, output_caps);
  gst_audio_info_set_format (&output_info,
      output_format.mFormatFlags & kLinearPCMFormatFlagIsSignedInteger ?
      GST_AUDIO_FORMAT_S16LE : GST_AUDIO_FORMAT_F32LE,
      output_format.mSampleRate, output_format.mChannelsPerFrame, NULL);
  gst_audio_decoder_set_output_format (decoder, &output_info);
  gst_caps_unref (output_caps);

  status = AudioQueueNewOutput (&input_format, gst_atdec_buffer_emptied,
      atdec, NULL, NULL, 0, &atdec->queue);
  if (status)
    goto create_queue_error;

  /* FIXME: figure out how to map this properly */
  if (output_format.mChannelsPerFrame == 1)
    output_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
  else
    output_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

  status = AudioQueueSetOfflineRenderFormat (atdec->queue,
      &output_format, &output_layout);
  if (status)
    goto set_format_error;

  status = AudioQueueStart (atdec->queue, NULL);
  if (status)
    goto start_error;

  return TRUE;

create_queue_error:
  GST_ELEMENT_ERROR (atdec, STREAM, FORMAT, (NULL),
      ("AudioQueueNewOutput returned error: %d", status));
  return FALSE;

set_format_error:
  GST_ELEMENT_ERROR (atdec, STREAM, FORMAT, (NULL),
      ("AudioQueueSetOfflineRenderFormat returned error: %d", status));
  gst_atdec_destroy_queue (atdec, FALSE);
  return FALSE;

start_error:
  GST_ELEMENT_ERROR (atdec, STREAM, FORMAT, (NULL),
      ("AudioQueueStart returned error: %d", status));
  gst_atdec_destroy_queue (atdec, FALSE);
  return FALSE;
}
예제 #14
0
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);
}
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;
  }
}
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
static GstFlowReturn
gst_mpg123_audio_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
{
  GstMpg123AudioDec *mpg123_decoder;
  int decode_error;
  unsigned char *decoded_bytes;
  size_t num_decoded_bytes;

  if (G_UNLIKELY (!buffer))
    return GST_FLOW_OK;

  mpg123_decoder = GST_MPG123_AUDIO_DEC (dec);

  if (G_UNLIKELY (mpg123_decoder->handle == NULL)) {
    GstElement *element = GST_ELEMENT (dec);
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("mpg123 handle is NULL"));
    return GST_FLOW_ERROR;
  }

  /* The actual decoding */
  {
    unsigned char const *inmemory;
    size_t inmemsize;
    GstMemory *memory;
    GstMapInfo info;

    memory = gst_buffer_get_all_memory (buffer);
    if (memory == NULL)
      return GST_FLOW_ERROR;

    if (!gst_memory_map (memory, &info, GST_MAP_READ)) {
      gst_memory_unref (memory);
      return GST_FLOW_ERROR;
    }

    inmemory = info.data;
    inmemsize = info.size;

    mpg123_feed (mpg123_decoder->handle, inmemory, inmemsize);
    decoded_bytes = NULL;
    num_decoded_bytes = 0;
    decode_error = mpg123_decode_frame (mpg123_decoder->handle,
        &mpg123_decoder->frame_offset, &decoded_bytes, &num_decoded_bytes);

    gst_memory_unmap (memory, &info);
    gst_memory_unref (memory);
  }

  switch (decode_error) {
    case MPG123_NEW_FORMAT:
      /*
         As mentioned in gst_mpg123_audio_dec_set_format(), the next audioinfo is not set immediately;
         instead, the code waits for mpg123 to take note of the new format, and then sets the audioinfo
         This fixes glitches with mp3s containing several format headers (for example, first half using 44.1kHz, second half 32 kHz)
       */

      GST_DEBUG_OBJECT (dec,
          "mpg123 reported a new format -> setting next srccaps");

      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);

      /*
         If there is a next audioinfo, use it, then set has_next_audioinfo to FALSE, to make sure
         gst_audio_decoder_set_output_format() isn't called again until set_format is called by the base class
       */
      if (mpg123_decoder->has_next_audioinfo) {
        if (!gst_audio_decoder_set_output_format (dec,
                &(mpg123_decoder->next_audioinfo))) {
          GstElement *element = GST_ELEMENT (dec);
          GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
              ("Unable to set output format"));
        }
        mpg123_decoder->has_next_audioinfo = FALSE;
      }

      break;

    case MPG123_NEED_MORE:
    case MPG123_OK:
      return gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder,
          decoded_bytes, num_decoded_bytes);

      /* If this happens, then the upstream parser somehow missed the ending of the bitstream */
    case MPG123_DONE:
      GST_DEBUG_OBJECT (dec, "mpg123 is done decoding");
      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);
      return GST_FLOW_EOS;

      /* Anything else is considered an error */
    default:
    {
      GstElement *element = GST_ELEMENT (dec);
      GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), ("Decoding error: %s",
              mpg123_plain_strerror (decode_error)));

      return GST_FLOW_ERROR;
    }
  }

  return GST_FLOW_OK;
}
예제 #18
0
static gboolean
gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force)
{
  GstFFMpegAudDecClass *oclass;
  gint depth;
  GstAudioFormat format;
  GstAudioChannelPosition pos[64] = { 0, };

  oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));

  depth = av_smp_format_depth (ffmpegdec->context->sample_fmt) * 8;
  format = gst_ffmpeg_smpfmt_to_audioformat (ffmpegdec->context->sample_fmt);
  if (format == GST_AUDIO_FORMAT_UNKNOWN)
    goto no_caps;

  if (!force && ffmpegdec->info.rate ==
      ffmpegdec->context->sample_rate &&
      ffmpegdec->info.channels == ffmpegdec->context->channels &&
      ffmpegdec->info.finfo->depth == depth)
    return TRUE;

  GST_DEBUG_OBJECT (ffmpegdec,
      "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
      ffmpegdec->info.rate, ffmpegdec->info.channels,
      ffmpegdec->info.finfo->depth,
      ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth);

  gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context->channel_layout,
      ffmpegdec->context->channels, pos);
  memcpy (ffmpegdec->ffmpeg_layout, pos,
      sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels);

  /* Get GStreamer channel layout */
  gst_audio_channel_positions_to_valid_order (pos,
      ffmpegdec->context->channels);
  ffmpegdec->needs_reorder =
      memcmp (pos, ffmpegdec->ffmpeg_layout,
      sizeof (pos[0]) * ffmpegdec->context->channels) != 0;
  gst_audio_info_set_format (&ffmpegdec->info, format,
      ffmpegdec->context->sample_rate, ffmpegdec->context->channels, pos);

  if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec),
          &ffmpegdec->info))
    goto caps_failed;

  return TRUE;

  /* ERRORS */
no_caps:
  {
#ifdef HAVE_LIBAV_UNINSTALLED
    /* using internal ffmpeg snapshot */
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
        ("Could not find GStreamer caps mapping for libav codec '%s'.",
            oclass->in_plugin->name), (NULL));
#else
    /* using external ffmpeg */
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
        ("Could not find GStreamer caps mapping for libav codec '%s', and "
            "you are using an external libavcodec. This is most likely due to "
            "a packaging problem and/or libavcodec having been upgraded to a "
            "version that is not compatible with this version of "
            "gstreamer-libav. Make sure your gstreamer-libav and libavcodec "
            "packages come from the same source/repository.",
            oclass->in_plugin->name), (NULL));
#endif
    return FALSE;
  }
caps_failed:
  {
    GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
        ("Could not set caps for libav decoder (%s), not fixed?",
            oclass->in_plugin->name));

    return FALSE;
  }
}
예제 #19
0
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;
  }
}
예제 #20
0
static GstFlowReturn
gst_mpg123_audio_dec_handle_frame (GstAudioDecoder * dec,
    GstBuffer * input_buffer)
{
  GstMpg123AudioDec *mpg123_decoder;
  int decode_error;
  unsigned char *decoded_bytes;
  size_t num_decoded_bytes;
  GstFlowReturn retval;

  mpg123_decoder = GST_MPG123_AUDIO_DEC (dec);

  g_assert (mpg123_decoder->handle != NULL);

  /* The actual decoding */
  {
    /* feed input data (if there is any) */
    if (G_LIKELY (input_buffer != NULL)) {
      GstMapInfo info;

      if (gst_buffer_map (input_buffer, &info, GST_MAP_READ)) {
        mpg123_feed (mpg123_decoder->handle, info.data, info.size);
        gst_buffer_unmap (input_buffer, &info);
      } else {
        GST_ERROR_OBJECT (mpg123_decoder, "gst_memory_map() failed");
        return GST_FLOW_ERROR;
      }
    }

    /* Try to decode a frame */
    decoded_bytes = NULL;
    num_decoded_bytes = 0;
    decode_error = mpg123_decode_frame (mpg123_decoder->handle,
        &mpg123_decoder->frame_offset, &decoded_bytes, &num_decoded_bytes);
  }

  retval = GST_FLOW_OK;

  switch (decode_error) {
    case MPG123_NEW_FORMAT:
      /* As mentioned in gst_mpg123_audio_dec_set_format(), the next audioinfo
       * is not set immediately; instead, the code waits for mpg123 to take
       * note of the new format, and then sets the audioinfo. This fixes glitches
       * with mp3s containing several format headers (for example, first half
       * using 44.1kHz, second half 32 kHz) */

      GST_LOG_OBJECT (dec,
          "mpg123 reported a new format -> setting next srccaps");

      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);

      /* If there is a next audioinfo, use it, then set has_next_audioinfo to
       * FALSE, to make sure gst_audio_decoder_set_output_format() isn't called
       * again until set_format is called by the base class */
      if (mpg123_decoder->has_next_audioinfo) {
        if (!gst_audio_decoder_set_output_format (dec,
                &(mpg123_decoder->next_audioinfo))) {
          GST_WARNING_OBJECT (dec, "Unable to set output format");
          retval = GST_FLOW_NOT_NEGOTIATED;
        }
        mpg123_decoder->has_next_audioinfo = FALSE;
      }

      break;

    case MPG123_NEED_MORE:
    case MPG123_OK:
      retval = gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder,
          decoded_bytes, num_decoded_bytes);
      break;

    case MPG123_DONE:
      /* If this happens, then the upstream parser somehow missed the ending
       * of the bitstream */
      GST_LOG_OBJECT (dec, "mpg123 is done decoding");
      gst_mpg123_audio_dec_push_decoded_bytes (mpg123_decoder, decoded_bytes,
          num_decoded_bytes);
      retval = GST_FLOW_EOS;
      break;

    default:
    {
      /* Anything else is considered an error */
      int errcode;
      switch (decode_error) {
        case MPG123_ERR:
          errcode = mpg123_errcode (mpg123_decoder->handle);
          break;
        default:
          errcode = decode_error;
      }
      switch (errcode) {
        case MPG123_BAD_OUTFORMAT:{
          GstCaps *input_caps =
              gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (dec));
          GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL),
              ("Output sample format could not be used when trying to decode frame. "
                  "This is typically caused when the input caps (often the sample "
                  "rate) do not match the actual format of the audio data. "
                  "Input caps: %" GST_PTR_FORMAT, input_caps)
              );
          gst_caps_unref (input_caps);
          break;
        }
        default:{
          char const *errmsg = mpg123_plain_strerror (errcode);
          GST_ERROR_OBJECT (dec, "Reported error: %s", errmsg);
        }
      }

      retval = GST_FLOW_ERROR;
    }
  }

  return retval;
}
예제 #21
0
static FLAC__StreamDecoderWriteStatus
gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
    const FLAC__int32 * const buffer[])
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *outbuf;
  guint depth = frame->header.bits_per_sample;
  guint width, gdepth;
  guint sample_rate = frame->header.sample_rate;
  guint channels = frame->header.channels;
  guint samples = frame->header.blocksize;
  guint j, i;
  GstMapInfo map;
  gboolean caps_changed;

  GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);

  if (depth == 0) {
    if (flacdec->depth < 4 || flacdec->depth > 32) {
      GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
          flacdec->depth);
      ret = GST_FLOW_ERROR;
      goto done;
    }

    depth = flacdec->depth;
  }

  switch (depth) {
    case 8:
      gdepth = width = 8;
      break;
    case 12:
    case 16:
      gdepth = width = 16;
      break;
    case 20:
    case 24:
      gdepth = 24;
      width = 32;
      break;
    case 32:
      gdepth = width = 32;
      break;
    default:
      GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
      ret = GST_FLOW_ERROR;
      goto done;
  }

  if (sample_rate == 0) {
    if (flacdec->info.rate != 0) {
      sample_rate = flacdec->info.rate;
    } else {
      GST_ERROR_OBJECT (flacdec, "unknown sample rate");
      ret = GST_FLOW_ERROR;
      goto done;
    }
  }

  caps_changed = (sample_rate != GST_AUDIO_INFO_RATE (&flacdec->info))
      || (width != GST_AUDIO_INFO_WIDTH (&flacdec->info))
      || (gdepth != GST_AUDIO_INFO_DEPTH (&flacdec->info))
      || (channels != GST_AUDIO_INFO_CHANNELS (&flacdec->info));

  if (caps_changed
      || !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) {
    GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate,
        channels);

    gst_audio_info_set_format (&flacdec->info,
        gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth),
        sample_rate, channels, NULL);

    memcpy (flacdec->info.position,
        channel_positions[flacdec->info.channels - 1],
        sizeof (GstAudioChannelPosition) * flacdec->info.channels);
    gst_audio_channel_positions_to_valid_order (flacdec->info.position,
        flacdec->info.channels);
    /* Note: we create the inverse reordering map here */
    gst_audio_get_channel_reorder_map (flacdec->info.channels,
        flacdec->info.position, channel_positions[flacdec->info.channels - 1],
        flacdec->channel_reorder_map);

    flacdec->depth = depth;

    gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec),
        &flacdec->info);
  }

  outbuf =
      gst_buffer_new_allocate (NULL, samples * channels * (width / 8), NULL);

  gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
  if (width == 8) {
    gint8 *outbuffer = (gint8 *) map.data;
    gint *reorder_map = flacdec->channel_reorder_map;

    if (gdepth != depth) {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ =
              (gint8) (buffer[reorder_map[j]][i] << (gdepth - depth));
        }
      }
    } else {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ = (gint8) buffer[reorder_map[j]][i];
        }
      }
    }
  } else if (width == 16) {
    gint16 *outbuffer = (gint16 *) map.data;
    gint *reorder_map = flacdec->channel_reorder_map;

    if (gdepth != depth) {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ =
              (gint16) (buffer[reorder_map[j]][i] << (gdepth - depth));
        }
      }
    } else {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ = (gint16) buffer[reorder_map[j]][i];
        }
      }
    }
  } else if (width == 32) {
    gint32 *outbuffer = (gint32 *) map.data;
    gint *reorder_map = flacdec->channel_reorder_map;

    if (gdepth != depth) {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ =
              (gint32) (buffer[reorder_map[j]][i] << (gdepth - depth));
        }
      }
    } else {
      for (i = 0; i < samples; i++) {
        for (j = 0; j < channels; j++) {
          *outbuffer++ = (gint32) buffer[reorder_map[j]][i];
        }
      }
    }
  } else {
    g_assert_not_reached ();
  }
  gst_buffer_unmap (outbuf, &map);

  GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
  if (flacdec->error_count)
    flacdec->error_count--;

  ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);

  if (G_UNLIKELY (ret != GST_FLOW_OK)) {
    GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret));
  }

done:

  /* we act on the flow return value later in the handle_frame function, as we
   * don't want to mess up the internal decoder state by returning ABORT when
   * the error is in fact non-fatal (like a pad in flushing mode) and we want
   * to continue later. So just pretend everything's dandy and act later. */
  flacdec->last_flow = ret;

  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
예제 #22
0
static GstFlowReturn gst_imx_audio_uniaudio_dec_handle_frame(GstAudioDecoder *dec, GstBuffer *buffer)
{
	GstMapInfo in_map;
	GstBuffer *out_buffer;
	gsize avail_out_size;
	GstImxAudioUniaudioDec *imx_audio_uniaudio_dec = GST_IMX_AUDIO_UNIAUDIO_DEC(dec);
	int32 dec_ret;
	uint32 offset = 0;
	uint8 *in_buf = NULL;
	uint32 in_size = 0;
	gboolean dec_loop = TRUE, flow_error = FALSE;

	/* With some formats such as Vorbis, the first few buffers are actually redundant,
	 * since they contain codec data that was already specified in codec_data or
	 * streamheader caps earlier. If this is the case, skip these buffers. */
	if (imx_audio_uniaudio_dec->skip_header_counter < imx_audio_uniaudio_dec->num_vorbis_headers)
	{
		GST_TRACE_OBJECT(dec, "skipping header buffer #%u", imx_audio_uniaudio_dec->skip_header_counter);
		++imx_audio_uniaudio_dec->skip_header_counter;
		return gst_audio_decoder_finish_frame(dec, NULL, 1);
	}

	if (buffer != NULL)
	{
		gst_buffer_map(buffer, &in_map, GST_MAP_READ);
		in_buf = in_map.data;
		in_size = in_map.size;
	}

	while (dec_loop)
	{
		GstBuffer *tmp_buf;
		uint8 *out_buf = NULL;
		uint32 out_size = 0;

		if (buffer != NULL)
			GST_TRACE_OBJECT(dec, "feeding %" G_GUINT32_FORMAT " bytes to the decoder", (guint32)in_size);
		else
			GST_TRACE_OBJECT(dec, "draining decoder");

		dec_ret = imx_audio_uniaudio_dec->codec->decode_frame(
			imx_audio_uniaudio_dec->handle,
			in_buf, in_size,
			&offset,
			&out_buf, &out_size
		);

		GST_TRACE_OBJECT(dec, "decode_frame:  return 0x%x  offset %" G_GUINT32_FORMAT "  out_size %" G_GUINT32_FORMAT, (unsigned int)dec_ret, (guint32)offset, (guint32)out_size);

		if ((out_buf != NULL) && (out_size > 0))
		{
			tmp_buf = gst_audio_decoder_allocate_output_buffer(dec, out_size);
			tmp_buf = gst_buffer_make_writable(tmp_buf);
			gst_buffer_fill(tmp_buf, 0, out_buf, out_size);
			gst_adapter_push(imx_audio_uniaudio_dec->out_adapter, tmp_buf);
		}

		if (out_buf != NULL)
		{
			gst_imx_audio_uniaudio_dec_free(out_buf);
		}

		if ((buffer != NULL) && (offset == in_map.size))
		{
			dec_loop = FALSE;
		}

		switch (dec_ret)
		{
			case ACODEC_SUCCESS:
				break;
			case ACODEC_END_OF_STREAM:
				dec_loop = FALSE;
				break;
			case ACODEC_NOT_ENOUGH_DATA:
				break;
			case ACODEC_CAPIBILITY_CHANGE:
				break;
			default:
			{
				dec_loop = FALSE;
				flow_error = TRUE;
				GST_ELEMENT_ERROR(dec, STREAM, DECODE, ("could not decode"), ("error message: %s", imx_audio_uniaudio_dec->codec->get_last_error(imx_audio_uniaudio_dec->handle)));
			}
		}
	}

	if (buffer != NULL)
		gst_buffer_unmap(buffer, &in_map);

	if (flow_error)
		return GST_FLOW_ERROR;

	if (!(imx_audio_uniaudio_dec->has_audioinfo_set))
	{
		UniACodecParameter parameter;
		GstAudioFormat pcm_fmt;
		GstAudioInfo audio_info;

		imx_audio_uniaudio_dec->codec->get_parameter(imx_audio_uniaudio_dec->handle, UNIA_OUTPUT_PCM_FORMAT, &parameter);

		if ((parameter.outputFormat.width == 0) || (parameter.outputFormat.depth == 0))
		{
			GST_DEBUG_OBJECT(imx_audio_uniaudio_dec, "no output format available yet");
			return gst_audio_decoder_finish_frame(dec, NULL, 1);
		}

		GST_DEBUG_OBJECT(imx_audio_uniaudio_dec, "output sample width: %" G_GUINT32_FORMAT "  depth: %" G_GUINT32_FORMAT, (guint32)(parameter.outputFormat.width), (guint32)(parameter.outputFormat.depth));
		pcm_fmt = gst_audio_format_build_integer(TRUE, G_BYTE_ORDER, parameter.outputFormat.width, parameter.outputFormat.depth);

		GST_DEBUG_OBJECT(imx_audio_uniaudio_dec, "setting output format to: %s  %d Hz  %d channels", gst_audio_format_to_string(pcm_fmt), (gint)(parameter.outputFormat.samplerate), (gint)(parameter.outputFormat.channels));

		gst_imx_audio_uniaudio_dec_clear_channel_positions(imx_audio_uniaudio_dec);
		gst_imx_audio_uniaudio_dec_fill_channel_positions(imx_audio_uniaudio_dec, parameter.outputFormat.layout, parameter.outputFormat.channels);

		imx_audio_uniaudio_dec->pcm_format = pcm_fmt;
		imx_audio_uniaudio_dec->num_channels = parameter.outputFormat.channels;

		gst_audio_info_set_format(
			&audio_info,
			pcm_fmt,
			parameter.outputFormat.samplerate,
			parameter.outputFormat.channels,
			imx_audio_uniaudio_dec->reordered_channel_positions
		);
		gst_audio_decoder_set_output_format(dec, &audio_info);

		imx_audio_uniaudio_dec->has_audioinfo_set = TRUE;
	}


	avail_out_size = gst_adapter_available(imx_audio_uniaudio_dec->out_adapter);

	if (avail_out_size > 0)
	{
		out_buffer = gst_adapter_take_buffer(imx_audio_uniaudio_dec->out_adapter, avail_out_size);
		if (imx_audio_uniaudio_dec->original_channel_positions != imx_audio_uniaudio_dec->reordered_channel_positions)
		{
			gst_audio_buffer_reorder_channels(
				out_buffer,
				imx_audio_uniaudio_dec->pcm_format,
				imx_audio_uniaudio_dec->num_channels,
				imx_audio_uniaudio_dec->original_channel_positions,
				imx_audio_uniaudio_dec->reordered_channel_positions
			);
		}
		return gst_audio_decoder_finish_frame(dec, out_buffer, 1);
	}
	else
	{
		return gst_audio_decoder_finish_frame(dec, NULL, 1);
	}
}