Esempio n. 1
0
static void
gst_raw_audio_parse_update_config_bpf (GstRawAudioParseConfig * config)
{
  switch (config->format) {
    case GST_RAW_AUDIO_PARSE_FORMAT_PCM:
    {
      GstAudioFormatInfo const *fmt_info =
          gst_audio_format_get_info (config->pcm_format);
      g_assert (fmt_info != NULL);

      config->bpf =
          GST_AUDIO_FORMAT_INFO_WIDTH (fmt_info) * config->num_channels / 8;

      break;
    }

    case GST_RAW_AUDIO_PARSE_FORMAT_ALAW:
    case GST_RAW_AUDIO_PARSE_FORMAT_MULAW:
      /* A-law and mu-law both use 1 byte per sample */
      config->bpf = 1 * config->num_channels;
      break;

    default:
      g_assert_not_reached ();
  }
}
/**
 * gst_audio_info_init:
 * @info: a #GstAudioInfo
 *
 * Initialize @info with default values.
 */
void
gst_audio_info_init (GstAudioInfo * info)
{
  g_return_if_fail (info != NULL);

  memset (info, 0, sizeof (GstAudioInfo));

  info->finfo = gst_audio_format_get_info (GST_AUDIO_FORMAT_UNKNOWN);
}
/**
 * gst_audio_info_set_format:
 * @info: a #GstAudioInfo
 * @format: the format
 * @rate: the samplerate
 * @channels: the number of channels
 * @position: the channel positions
 *
 * Set the default info for the audio info of @format and @rate and @channels.
 *
 * Note: This initializes @info first, no values are preserved.
 */
void
gst_audio_info_set_format (GstAudioInfo * info, GstAudioFormat format,
    gint rate, gint channels, const GstAudioChannelPosition * position)
{
  const GstAudioFormatInfo *finfo;
  gint i;

  g_return_if_fail (info != NULL);
  g_return_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN);
  g_return_if_fail (channels <= 64 || position == NULL);

  gst_audio_info_init (info);

  finfo = gst_audio_format_get_info (format);

  info->flags = 0;
  info->layout = GST_AUDIO_LAYOUT_INTERLEAVED;
  info->finfo = finfo;
  info->rate = rate;
  info->channels = channels;
  info->bpf = (finfo->width * channels) / 8;

  memset (&info->position, 0xff, sizeof (info->position));

  if (!position && channels == 1) {
    info->position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
    return;
  } else if (!position && channels == 2) {
    info->position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
    info->position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
    return;
  } else {
    if (!position
        || !gst_audio_check_valid_channel_positions (position, channels,
            TRUE)) {
      if (position)
        g_warning ("Invalid channel positions");
    } else {
      memcpy (&info->position, position,
          info->channels * sizeof (info->position[0]));
      if (info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE)
        info->flags |= GST_AUDIO_FLAG_UNPOSITIONED;
      return;
    }
  }

  /* Otherwise a NONE layout */
  info->flags |= GST_AUDIO_FLAG_UNPOSITIONED;
  for (i = 0; i < MIN (64, channels); i++)
    info->position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
}
Esempio n. 4
0
static void
do_perfect_stream_test (guint rate, const gchar * format,
    gdouble drop_probability, gdouble inject_probability)
{
  GstElement *pipe, *src, *conv, *filter, *injector, *audiorate, *sink;
  GstMessage *msg;
  GstCaps *caps;
  GstPad *srcpad;
  GList *l, *bufs = NULL;
  GstClockTime next_time = GST_CLOCK_TIME_NONE;
  guint64 next_offset = GST_BUFFER_OFFSET_NONE;
  GstAudioFormat fmt;
  const GstAudioFormatInfo *finfo;
  gint width;

  fmt = gst_audio_format_from_string (format);
  g_assert (format != GST_AUDIO_FORMAT_UNKNOWN);

  finfo = gst_audio_format_get_info (fmt);
  width = GST_AUDIO_FORMAT_INFO_WIDTH (finfo);

  caps = gst_caps_new_simple ("audio/x-raw", "rate", G_TYPE_INT,
      rate, "format", G_TYPE_STRING, format, NULL);

  GST_INFO ("-------- drop=%.0f%% caps = %" GST_PTR_FORMAT " ---------- ",
      drop_probability * 100.0, caps);

  g_assert (drop_probability >= 0.0 && drop_probability <= 1.0);
  g_assert (inject_probability >= 0.0 && inject_probability <= 1.0);

  pipe = gst_pipeline_new ("pipeline");
  fail_unless (pipe != NULL);

  src = gst_element_factory_make ("audiotestsrc", "audiotestsrc");
  fail_unless (src != NULL);

  g_object_set (src, "num-buffers", 10, NULL);

  conv = gst_element_factory_make ("audioconvert", "audioconvert");
  fail_unless (conv != NULL);

  filter = gst_element_factory_make ("capsfilter", "capsfilter");
  fail_unless (filter != NULL);

  g_object_set (filter, "caps", caps, NULL);

  injector_inject_probability = inject_probability;

  injector = GST_ELEMENT (g_object_new (test_injector_get_type (), NULL));

  srcpad = gst_element_get_static_pad (injector, "src");
  fail_unless (srcpad != NULL);
  gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER, probe_cb,
      &drop_probability, NULL);
  gst_object_unref (srcpad);

  audiorate = gst_element_factory_make ("audiorate", "audiorate");
  fail_unless (audiorate != NULL);

  sink = gst_element_factory_make ("fakesink", "fakesink");
  fail_unless (sink != NULL);

  g_object_set (sink, "signal-handoffs", TRUE, NULL);

  g_signal_connect (sink, "handoff", G_CALLBACK (got_buf), &bufs);

  gst_bin_add_many (GST_BIN (pipe), src, conv, filter, injector, audiorate,
      sink, NULL);
  gst_element_link_many (src, conv, filter, injector, audiorate, sink, NULL);

  fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING),
      GST_STATE_CHANGE_ASYNC);

  fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1),
      GST_STATE_CHANGE_SUCCESS);

  msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
      GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
  fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos");

  for (l = bufs; l != NULL; l = l->next) {
    GstBuffer *buf = GST_BUFFER (l->data);
    guint num_samples;

    fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf));
    fail_unless (GST_BUFFER_DURATION_IS_VALID (buf));
    fail_unless (GST_BUFFER_OFFSET_IS_VALID (buf));
    fail_unless (GST_BUFFER_OFFSET_END_IS_VALID (buf));

    GST_LOG ("buffer: ts=%" GST_TIME_FORMAT ", end_ts=%" GST_TIME_FORMAT
        " off=%" G_GINT64_FORMAT ", end_off=%" G_GINT64_FORMAT,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)),
        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));

    if (GST_CLOCK_TIME_IS_VALID (next_time)) {
      fail_unless_equals_uint64 (next_time, GST_BUFFER_TIMESTAMP (buf));
    }
    if (next_offset != GST_BUFFER_OFFSET_NONE) {
      fail_unless_equals_uint64 (next_offset, GST_BUFFER_OFFSET (buf));
    }

    /* check buffer size for sanity */
    fail_unless_equals_int (gst_buffer_get_size (buf) % (width / 8), 0);

    /* check there is actually as much data as there should be */
    num_samples = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf);
    fail_unless_equals_int (gst_buffer_get_size (buf),
        num_samples * (width / 8));

    next_time = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
    next_offset = GST_BUFFER_OFFSET_END (buf);
  }

  gst_message_unref (msg);
  gst_element_set_state (pipe, GST_STATE_NULL);
  gst_object_unref (pipe);

  g_list_foreach (bufs, (GFunc) gst_mini_object_unref, NULL);
  g_list_free (bufs);

  gst_caps_unref (caps);
}
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;
  }
}
/* returns static descriptions and dynamic ones (such as video/x-raw),
 * or NULL if caps aren't known at all */
static gchar *
format_info_get_desc (const FormatInfo * info, const GstCaps * caps)
{
  const GstStructure *s;

  g_assert (info != NULL);

  if (info->desc != NULL)
    return g_strdup (_(info->desc));

  s = gst_caps_get_structure (caps, 0);

  if (strcmp (info->type, "video/x-raw") == 0) {
    gchar *ret = NULL;
    const gchar *str = 0;
    GstVideoFormat format;
    const GstVideoFormatInfo *finfo;

    str = gst_structure_get_string (s, "format");
    if (str == NULL)
      return g_strdup (_("Uncompressed video"));
    format = gst_video_format_from_string (str);
    if (format == GST_VIDEO_FORMAT_UNKNOWN)
      return g_strdup (_("Uncompressed video"));

    finfo = gst_video_format_get_info (format);

    if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
      ret = g_strdup (_("Uncompressed gray"));
    } else if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
      const gchar *subs;
      gint w_sub, h_sub, n_semi;

      w_sub = GST_VIDEO_FORMAT_INFO_W_SUB (finfo, 1);
      h_sub = GST_VIDEO_FORMAT_INFO_H_SUB (finfo, 1);

      if (w_sub == 1 && h_sub == 1) {
        subs = "4:4:4";
      } else if (w_sub == 2 && h_sub == 1) {
        subs = "4:2:2";
      } else if (w_sub == 2 && h_sub == 2) {
        subs = "4:2:0";
      } else if (w_sub == 4 && h_sub == 1) {
        subs = "4:1:1";
      } else {
        subs = "";
      }

      n_semi = GST_VIDEO_FORMAT_INFO_HAS_ALPHA (finfo) ? 3 : 2;

      if (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) == 1) {
        ret = g_strdup_printf (_("Uncompressed packed YUV %s"), subs);
      } else if (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) == n_semi) {
        ret = g_strdup_printf (_("Uncompressed semi-planar YUV %s"), subs);
      } else {
        ret = g_strdup_printf (_("Uncompressed planar YUV %s"), subs);
      }
    } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
      gboolean alpha, palette;
      gint bits;

      alpha = GST_VIDEO_FORMAT_INFO_HAS_ALPHA (finfo);
      palette = GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo);
      bits = GST_VIDEO_FORMAT_INFO_BITS (finfo);

      if (palette) {
        ret = g_strdup_printf (_("Uncompressed palettized %d-bit %s"),
            bits, alpha ? "RGBA" : "RGB");
      } else {
        ret = g_strdup_printf (_("Uncompressed %d-bit %s"),
            bits, alpha ? "RGBA" : "RGB");
      }
    } else {
      ret = g_strdup (_("Uncompressed video"));
    }
    return ret;
  } else if (strcmp (info->type, "video/x-h263") == 0) {
    const gchar *variant, *ret;

    variant = gst_structure_get_string (s, "variant");
    if (variant == NULL)
      ret = "H.263";
    else if (strcmp (variant, "itu") == 0)
      ret = "ITU H.26n";        /* why not ITU H.263? (tpm) */
    else if (strcmp (variant, "lead") == 0)
      ret = "Lead H.263";
    else if (strcmp (variant, "microsoft") == 0)
      ret = "Microsoft H.263";
    else if (strcmp (variant, "vdolive") == 0)
      ret = "VDOLive";
    else if (strcmp (variant, "vivo") == 0)
      ret = "Vivo H.263";
    else if (strcmp (variant, "xirlink") == 0)
      ret = "Xirlink H.263";
    else {
      GST_WARNING ("Unknown H263 variant '%s'", variant);
      ret = "H.263";
    }
    return g_strdup (ret);
  } else if (strcmp (info->type, "video/x-h264") == 0) {
    const gchar *variant, *ret;
    const gchar *profile;

    variant = gst_structure_get_string (s, "variant");
    if (variant == NULL)
      ret = "H.264";
    else if (strcmp (variant, "itu") == 0)
      ret = "ITU H.264";
    else if (strcmp (variant, "videosoft") == 0)
      ret = "Videosoft H.264";
    else if (strcmp (variant, "lead") == 0)
      ret = "Lead H.264";
    else {
      GST_WARNING ("Unknown H264 variant '%s'", variant);
      ret = "H.264";
    }
    /* profile */
    profile = gst_structure_get_string (s, "profile");
    if (profile != NULL)
      profile = pbutils_desc_get_h264_profile_name_from_nick (profile);
    if (profile == NULL)
      return g_strdup (ret);
    return g_strdup_printf ("%s (%s Profile)", ret, profile);
  } else if (strcmp (info->type, "video/x-h265") == 0) {
    const gchar *profile = gst_structure_get_string (s, "profile");

    if (profile != NULL)
      profile = pbutils_desc_get_h265_profile_name_from_nick (profile);
    if (profile != NULL)
      return g_strdup_printf ("H.265 (%s Profile)", profile);

    return g_strdup ("H.265");
  } else if (strcmp (info->type, "video/x-dirac") == 0) {
    const gchar *profile = gst_structure_get_string (s, "profile");
    if (profile == NULL)
      return g_strdup ("Dirac");
    if (strcmp (profile, "vc2-low-delay") == 0)
      return g_strdup_printf ("Dirac (%s)", "VC-2 Low Delay Profile");
    else if (strcmp (profile, "vc2-simple") == 0)
      return g_strdup_printf ("Dirac (%s)", "VC-2 Simple Profile");
    else if (strcmp (profile, "vc2-main") == 0)
      return g_strdup_printf ("Dirac (%s)", "VC-2 Main Profile");
    else
      return g_strdup ("Dirac");
  } else if (strcmp (info->type, "video/x-divx") == 0) {
    gint ver = 0;

    if (!gst_structure_get_int (s, "divxversion", &ver) || ver <= 2) {
      GST_WARNING ("Unexpected DivX version in %" GST_PTR_FORMAT, caps);
      return g_strdup ("DivX MPEG-4");
    }
    return g_strdup_printf (_("DivX MPEG-4 Version %d"), ver);
  } else if (strcmp (info->type, "video/x-msmpeg") == 0) {
    gint ver = 0;

    if (!gst_structure_get_int (s, "msmpegversion", &ver) ||
        ver < 40 || ver > 49) {
      GST_WARNING ("Unexpected msmpegversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("Microsoft MPEG-4 4.x");
    }
    return g_strdup_printf ("Microsoft MPEG-4 4.%d", ver % 10);
  } else if (strcmp (info->type, "video/x-truemotion") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "trueversion", &ver);
    switch (ver) {
      case 1:
        return g_strdup_printf ("Duck TrueMotion 1");
      case 2:
        return g_strdup_printf ("TrueMotion 2.0");
      default:
        GST_WARNING ("Unexpected trueversion in %" GST_PTR_FORMAT, caps);
        break;
    }
    return g_strdup_printf ("TrueMotion");
  } else if (strcmp (info->type, "video/x-xan") == 0) {
    gint ver = 0;

    if (!gst_structure_get_int (s, "wcversion", &ver) || ver < 1) {
      GST_WARNING ("Unexpected wcversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("Xan Wing Commander");
    }
    return g_strdup_printf ("Xan Wing Commander %u", ver);
  } else if (strcmp (info->type, "video/x-indeo") == 0) {
    gint ver = 0;

    if (!gst_structure_get_int (s, "indeoversion", &ver) || ver < 2) {
      GST_WARNING ("Unexpected indeoversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("Intel Indeo");
    }
    return g_strdup_printf ("Intel Indeo %u", ver);
  } else if (strcmp (info->type, "audio/x-wma") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "wmaversion", &ver);
    switch (ver) {
      case 1:
      case 2:
      case 3:
        return g_strdup_printf ("Windows Media Audio %d", ver + 6);
      default:
        break;
    }
    GST_WARNING ("Unexpected wmaversion in %" GST_PTR_FORMAT, caps);
    return g_strdup ("Windows Media Audio");
  } else if (strcmp (info->type, "video/x-wmv") == 0) {
    gint ver = 0;
    const gchar *str;

    gst_structure_get_int (s, "wmvversion", &ver);
    str = gst_structure_get_string (s, "format");

    switch (ver) {
      case 1:
      case 2:
      case 3:
        if (str && strncmp (str, "MSS", 3)) {
          return g_strdup_printf ("Windows Media Video %d Screen", ver + 6);
        } else {
          return g_strdup_printf ("Windows Media Video %d", ver + 6);
        }
      default:
        break;
    }
    GST_WARNING ("Unexpected wmvversion in %" GST_PTR_FORMAT, caps);
    return g_strdup ("Windows Media Video");
  } else if (strcmp (info->type, "audio/x-mace") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "maceversion", &ver);
    if (ver == 3 || ver == 6) {
      return g_strdup_printf ("MACE-%d", ver);
    } else {
      GST_WARNING ("Unexpected maceversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("MACE");
    }
  } else if (strcmp (info->type, "video/x-svq") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "svqversion", &ver);
    if (ver == 1 || ver == 3) {
      return g_strdup_printf ("Sorensen Video %d", ver);
    } else {
      GST_WARNING ("Unexpected svqversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("Sorensen Video");
    }
  } else if (strcmp (info->type, "video/x-asus") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "asusversion", &ver);
    if (ver == 1 || ver == 2) {
      return g_strdup_printf ("Asus Video %d", ver);
    } else {
      GST_WARNING ("Unexpected asusversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("Asus Video");
    }
  } else if (strcmp (info->type, "video/x-ati-vcr") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "vcrversion", &ver);
    if (ver == 1 || ver == 2) {
      return g_strdup_printf ("ATI VCR %d", ver);
    } else {
      GST_WARNING ("Unexpected acrversion in %" GST_PTR_FORMAT, caps);
      return g_strdup ("ATI VCR");
    }
  } else if (strcmp (info->type, "audio/x-adpcm") == 0) {
    const GValue *layout_val;

    layout_val = gst_structure_get_value (s, "layout");
    if (layout_val != NULL && G_VALUE_HOLDS_STRING (layout_val)) {
      const gchar *layout;

      if ((layout = g_value_get_string (layout_val))) {
        gchar *layout_upper, *ret;

        if (strcmp (layout, "swf") == 0)
          return g_strdup ("Shockwave ADPCM");
        if (strcmp (layout, "microsoft") == 0)
          return g_strdup ("Microsoft ADPCM");
        if (strcmp (layout, "quicktime") == 0)
          return g_strdup ("Quicktime ADPCM");
        if (strcmp (layout, "westwood") == 0)
          return g_strdup ("Westwood ADPCM");
        if (strcmp (layout, "yamaha") == 0)
          return g_strdup ("Yamaha ADPCM");
        /* FIXME: other layouts: sbpro2, sbpro3, sbpro4, ct, g726, ea,
         * adx, xa, 4xm, smjpeg, dk4, dk3, dvi */
        layout_upper = g_ascii_strup (layout, -1);
        ret = g_strdup_printf ("%s ADPCM", layout_upper);
        g_free (layout_upper);
        return ret;
      }
    }
    return g_strdup ("ADPCM");
  } else if (strcmp (info->type, "audio/mpeg") == 0) {
    gint ver = 0, layer = 0;

    gst_structure_get_int (s, "mpegversion", &ver);

    switch (ver) {
      case 1:
        gst_structure_get_int (s, "layer", &layer);
        switch (layer) {
          case 1:
          case 2:
          case 3:
            return g_strdup_printf ("MPEG-1 Layer %d (MP%d)", layer, layer);
          default:
            break;
        }
        GST_WARNING ("Unexpected MPEG-1 layer in %" GST_PTR_FORMAT, caps);
        return g_strdup ("MPEG-1 Audio");
      case 2:
        return g_strdup ("MPEG-2 AAC");
      case 4:
        return g_strdup ("MPEG-4 AAC");
      default:
        break;
    }
    GST_WARNING ("Unexpected audio mpegversion in %" GST_PTR_FORMAT, caps);
    return g_strdup ("MPEG Audio");
  } else if (strcmp (info->type, "audio/x-pn-realaudio") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "raversion", &ver);
    switch (ver) {
      case 1:
        return g_strdup ("RealAudio 14k4bps");
      case 2:
        return g_strdup ("RealAudio 28k8bps");
      case 8:
        return g_strdup ("RealAudio G2 (Cook)");
      default:
        break;
    }
    GST_WARNING ("Unexpected raversion in %" GST_PTR_FORMAT, caps);
    return g_strdup ("RealAudio");
  } else if (strcmp (info->type, "video/x-pn-realvideo") == 0) {
    gint ver = 0;

    gst_structure_get_int (s, "rmversion", &ver);
    switch (ver) {
      case 1:
        return g_strdup ("RealVideo 1.0");
      case 2:
        return g_strdup ("RealVideo 2.0");
      case 3:
        return g_strdup ("RealVideo 3.0");
      case 4:
        return g_strdup ("RealVideo 4.0");
      default:
        break;
    }
    GST_WARNING ("Unexpected rmversion in %" GST_PTR_FORMAT, caps);
    return g_strdup ("RealVideo");
  } else if (strcmp (info->type, "video/mpeg") == 0) {
    gboolean sysstream;
    gint ver = 0;

    if (!gst_structure_get_boolean (s, "systemstream", &sysstream)) {
      GST_WARNING ("Missing systemstream field in mpeg video caps "
          "%" GST_PTR_FORMAT, caps);
      sysstream = FALSE;
    }

    if (gst_structure_get_int (s, "mpegversion", &ver) && ver > 0 && ver <= 4) {
      if (sysstream) {
        return g_strdup_printf ("MPEG-%d System Stream", ver);
      } else {
        const gchar *profile = gst_structure_get_string (s, "profile");
        if (profile != NULL) {
          if (ver == 4)
            profile = pbutils_desc_get_mpeg4v_profile_name_from_nick (profile);
          else if (ver == 2)
            profile = pbutils_desc_get_mpeg2v_profile_name_from_nick (profile);
          else
            profile = NULL;
        }
        if (profile != NULL)
          return g_strdup_printf ("MPEG-%d Video (%s Profile)", ver, profile);
        else
          return g_strdup_printf ("MPEG-%d Video", ver);
      }
    }
    GST_WARNING ("Missing mpegversion field in mpeg video caps "
        "%" GST_PTR_FORMAT, caps);
    return g_strdup ("MPEG Video");
  } else if (strcmp (info->type, "audio/x-raw") == 0) {
    gint depth = 0;
    gboolean is_float;
    const gchar *str;
    GstAudioFormat format;
    const GstAudioFormatInfo *finfo;

    str = gst_structure_get_string (s, "format");
    format = gst_audio_format_from_string (str);
    if (format == GST_AUDIO_FORMAT_UNKNOWN)
      return g_strdup (_("Uncompressed audio"));

    finfo = gst_audio_format_get_info (format);
    depth = GST_AUDIO_FORMAT_INFO_DEPTH (finfo);
    is_float = GST_AUDIO_FORMAT_INFO_IS_FLOAT (finfo);

    return g_strdup_printf (_("Raw %d-bit %s audio"), depth,
        is_float ? "floating-point" : "PCM");
  } else if (strcmp (info->type, "video/x-tscc") == 0) {
    gint version;
    gst_structure_get_int (s, "tsccversion", &version);
    switch (version) {
      case 1:
        return g_strdup ("TechSmith Screen Capture 1");
      case 2:
        return g_strdup ("TechSmith Screen Capture 2");
      default:
        break;
    }
    GST_WARNING ("Unexpected version in %" GST_PTR_FORMAT, caps);
    return g_strdup ("TechSmith Screen Capture");
  }
  return NULL;
}
Esempio n. 7
0
static gboolean gst_imx_audio_uniaudio_dec_set_format(GstAudioDecoder *dec, GstCaps *caps)
{
	UniACodecParameter parameter;
	UniACodecMemoryOps memory_ops;
	GstImxAudioUniaudioDec *imx_audio_uniaudio_dec = GST_IMX_AUDIO_UNIAUDIO_DEC(dec);

#define UNIA_SET_PARAMETER(PARAM_ID, DESC) \
	do \
	{ \
		if (imx_audio_uniaudio_dec->codec->set_parameter(imx_audio_uniaudio_dec->handle, (PARAM_ID), &parameter) != ACODEC_SUCCESS) \
		{ \
			GST_ERROR_OBJECT(dec, "setting %s parameter failed: %s", (DESC), imx_audio_uniaudio_dec->codec->get_last_error(imx_audio_uniaudio_dec->handle)); \
			gst_imx_audio_uniaudio_dec_close_handle(imx_audio_uniaudio_dec); \
			return FALSE; \
		} \
	} \
	while (0)

#define UNIA_SET_PARAMETER_EX(PARAM_ID, DESC, VALUE) \
	do \
	{ \
		if (imx_audio_uniaudio_dec->codec->set_parameter(imx_audio_uniaudio_dec->handle, (PARAM_ID), ((UniACodecParameter *)(VALUE))) != ACODEC_SUCCESS) \
		{ \
			GST_ERROR_OBJECT(dec, "setting %s parameter failed: %s", (DESC), imx_audio_uniaudio_dec->codec->get_last_error(imx_audio_uniaudio_dec->handle)); \
			gst_imx_audio_uniaudio_dec_close_handle(imx_audio_uniaudio_dec); \
			return FALSE; \
		} \
	} \
	while (0)

	if (imx_audio_uniaudio_dec->handle != NULL)
	{
		/* drain old decoder handle */
		gst_imx_audio_uniaudio_dec_handle_frame(dec, NULL);
		gst_imx_audio_uniaudio_dec_close_handle(imx_audio_uniaudio_dec);
	}

	if ((imx_audio_uniaudio_dec->codec = gst_imx_audio_uniaudio_codec_table_get_codec(caps)) == NULL)
	{
		GST_ERROR_OBJECT(dec, "found no suitable codec for caps %" GST_PTR_FORMAT, (gpointer)caps);
		return FALSE;
	}

	memory_ops.Calloc  = gst_imx_audio_uniaudio_dec_calloc;
	memory_ops.Malloc  = gst_imx_audio_uniaudio_dec_malloc;
	memory_ops.Free    = gst_imx_audio_uniaudio_dec_free;
	memory_ops.ReAlloc = gst_imx_audio_uniaudio_dec_realloc;

	if ((imx_audio_uniaudio_dec->handle = imx_audio_uniaudio_dec->codec->create_codec(&memory_ops)) == NULL)
	{
		GST_ERROR_OBJECT(dec, "creating codec handle for caps %" GST_PTR_FORMAT " failed", (gpointer)caps);
		return FALSE;
	}

	/* Get configuration parameters from caps */
	{
		int samplerate, channels, bitrate, block_align, wmaversion;
		gchar const *stream_format, *sample_format;
		GValue const *value;
		gboolean framed, is_vorbis;
		GstBuffer *codec_data = NULL;
		GstStructure *structure = gst_caps_get_structure(caps, 0);

		imx_audio_uniaudio_dec->skip_header_counter = 0;

		is_vorbis = (g_strcmp0(gst_structure_get_name(structure), "audio/x-vorbis") == 0);
		parameter.framed = is_vorbis || (gst_structure_get_boolean(structure, "framed", &framed) && framed) || (gst_structure_get_boolean(structure, "parsed", &framed) && framed);
		GST_DEBUG_OBJECT(dec, "input is framed: %d", parameter.framed);
		UNIA_SET_PARAMETER(UNIA_FRAMED, "framed");

		if (gst_structure_get_int(structure, "rate", &samplerate))
		{
			GST_DEBUG_OBJECT(dec, "input caps sample rate: %d Hz", samplerate);
			parameter.samplerate = samplerate;
			UNIA_SET_PARAMETER(UNIA_SAMPLERATE, "sample rate");
		}

		if (gst_structure_get_int(structure, "channels", &channels))
		{
			CHAN_TABLE table;

			GST_DEBUG_OBJECT(dec, "input caps channel count: %d", channels);
			parameter.channels = channels;
			UNIA_SET_PARAMETER(UNIA_CHANNEL, "channel");

			memset(&table, 0, sizeof(table));
			table.size = CHANNEL_MAPS_SIZE;
			memcpy(&table.channel_table, uniaudio_channel_maps, sizeof(uniaudio_channel_maps));
			UNIA_SET_PARAMETER_EX(UNIA_CHAN_MAP_TABLE, "channel map", &table);
		}

		if (gst_structure_get_int(structure, "bitrate", &bitrate))
		{
			GST_DEBUG_OBJECT(dec, "input caps channel count: %d", bitrate);
			parameter.bitrate = bitrate;
			UNIA_SET_PARAMETER(UNIA_BITRATE, "bitrate");
		}

		if (gst_structure_get_int(structure, "block_align", &block_align))
		{
			GST_DEBUG_OBJECT(dec, "block alignment: %d", block_align);
			parameter.blockalign = block_align;
			UNIA_SET_PARAMETER(UNIA_WMA_BlOCKALIGN, "blockalign");
		}

		if (gst_structure_get_int(structure, "wmaversion", &wmaversion))
		{
			GST_DEBUG_OBJECT(dec, "WMA version: %d", wmaversion);
			parameter.version = wmaversion;
			UNIA_SET_PARAMETER(UNIA_WMA_VERSION, "wmaversion");
		}

		if ((stream_format = gst_structure_get_string(structure, "stream-format")) != NULL)
		{
			GST_DEBUG_OBJECT(dec, "input caps stream format: %s", stream_format);
			if (g_strcmp0(stream_format, "raw") == 0)
				parameter.stream_type = STREAM_ADTS;
			if (g_strcmp0(stream_format, "adif") == 0)
				parameter.stream_type = STREAM_ADIF;
			if (g_strcmp0(stream_format, "raw") == 0)
				parameter.stream_type = STREAM_RAW;
			else
				parameter.stream_type = STREAM_UNKNOW;
			UNIA_SET_PARAMETER(UNIA_STREAM_TYPE, "stream type");
		}

		if ((sample_format = gst_structure_get_string(structure, "format")) != NULL)
		{
			GstAudioFormat fmt;
			GstAudioFormatInfo const * fmtinfo;

			GST_DEBUG_OBJECT(dec, "input caps stream sample format: %s", sample_format);
			if ((fmt = gst_audio_format_from_string(sample_format)) == GST_AUDIO_FORMAT_UNKNOWN)
			{
				GST_ERROR_OBJECT(dec, "format is unknown, cannot continue");
				return FALSE;
			}

			fmtinfo = gst_audio_format_get_info(fmt);
			g_assert(fmtinfo != NULL);

			parameter.depth = GST_AUDIO_FORMAT_INFO_DEPTH(fmtinfo);
			UNIA_SET_PARAMETER(UNIA_DEPTH, "depth");
		}

		/* Handle codec data, either directly from a codec_data caps,
		 * or assemble it from a list of buffers specified by the
		 * streamheader caps (typically used by Vorbis audio) */

		/* Cleanup old codec data first */
		if (imx_audio_uniaudio_dec->codec_data != NULL)
		{
			gst_buffer_unref(imx_audio_uniaudio_dec->codec_data);
			imx_audio_uniaudio_dec->codec_data = NULL;
		}

		/* Check if either codec_data or streamheader caps exist */
		if ((value = gst_structure_get_value(structure, "codec_data")) != NULL)
		{
			/* codec_data caps exist - simply make a copy of its buffer
			 * (this makes sure we own that buffer properly) */

			GstBuffer *caps_buffer;
			GST_DEBUG_OBJECT(dec, "reading codec_data value");
			caps_buffer = gst_value_get_buffer(value);
			g_assert(caps_buffer != NULL);
			codec_data = gst_buffer_copy(caps_buffer);
		}
		else if ((value = gst_structure_get_value(structure, "streamheader")) != NULL)
		{
			/* streamheader caps exist, which are a list of buffers
			 * these buffers need to be concatenated and then given as
			 * one consecutive codec data buffer to the decoder */

			guint i, num_buffers = gst_value_array_get_size(value);
			GstAdapter *streamheader_adapter = gst_adapter_new();

			GST_DEBUG_OBJECT(dec, "reading streamheader value (%u headers)", num_buffers);

			imx_audio_uniaudio_dec->num_vorbis_headers = num_buffers;

			/* Use the GstAdapter to stitch these buffers together */
			for (i = 0; i < num_buffers; ++i)
			{
				GValue const *array_value = gst_value_array_get_value(value, i);
				GstBuffer *buf = gst_value_get_buffer(array_value);
				GST_DEBUG_OBJECT(dec, "add streamheader buffer #%u with %" G_GSIZE_FORMAT " byte", i, gst_buffer_get_size(buf));
				gst_adapter_push(streamheader_adapter, gst_buffer_copy(buf));
			}
			codec_data = gst_adapter_take_buffer(streamheader_adapter, gst_adapter_available(streamheader_adapter));

			g_object_unref(G_OBJECT(streamheader_adapter));
		}

		/* At this point, if either codec_data or streamheader caps were found,
		 * the codec_data pointer will refer to a valid non-empty buffer with
		 * codec data inside. This buffer is owned by this audio decoder object,
		 * and must be kept around for as long as the decoder needs to be ran,
		 * since the set_parameter call below does *not* copy the codec data
		 * bytes into some internal buffer. Instead, the uniaudio decoder plugin
		 * expects the caller to keep the buffer valid. */
		if ((codec_data != NULL) && (gst_buffer_get_size(codec_data) != 0))
		{
			GstMapInfo map;
			gst_buffer_map(codec_data, &map, GST_MAP_READ);
			parameter.codecData.size = map.size;
			parameter.codecData.buf = (char *)(map.data);
			UNIA_SET_PARAMETER(UNIA_CODEC_DATA, "codec data");
			gst_buffer_unmap(codec_data, &map);

			imx_audio_uniaudio_dec->codec_data = codec_data;

			GST_DEBUG_OBJECT(dec, "codec data: %" G_GUINT32_FORMAT " byte", (guint32)(parameter.codecData.size));
		}
	}

	GST_DEBUG_OBJECT(dec, "decoder configured");

	imx_audio_uniaudio_dec->has_audioinfo_set = FALSE;

#undef UNIA_SET_PARAMETER

	return TRUE;
}