コード例 #1
0
static void
sink_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad,
    gpointer user_data)
{
  gint i;
  GstMapInfo map;
  gfloat *data;
  GstCaps *caps, *ccaps;
  gint n = GPOINTER_TO_INT (user_data);
  guint64 mask;

  fail_unless (GST_IS_BUFFER (buffer));
  gst_buffer_map (buffer, &map, GST_MAP_READ);
  data = (gfloat *) map.data;

  fail_unless_equals_int (map.size, 48000 * 2 * sizeof (gfloat));
  fail_unless_equals_int (GST_BUFFER_DURATION (buffer), GST_SECOND);

  if (n == 0) {
    GstAudioChannelPosition pos[2] =
        { GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE };
    gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask);
  } else if (n == 1) {
    GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
    };
    gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask);
  } else if (n == 2) {
    GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
      GST_AUDIO_CHANNEL_POSITION_REAR_CENTER
    };
    gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask);
  } else {
    g_assert_not_reached ();
  }

  caps = gst_caps_new_simple ("audio/x-raw",
      "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
      "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000,
      "layout", G_TYPE_STRING, "interleaved",
      "channel-mask", GST_TYPE_BITMASK, mask, NULL);

  ccaps = gst_pad_get_current_caps (pad);
  fail_unless (gst_caps_is_equal (caps, ccaps));
  gst_caps_unref (ccaps);
  gst_caps_unref (caps);

#ifdef HAVE_VALGRIND
  if (!(RUNNING_ON_VALGRIND))
#endif
    for (i = 0; i < 48000 * 2; i += 2) {
      fail_unless_equals_float (data[i], -1.0);
      fail_unless_equals_float (data[i + 1], 1.0);
    }
  gst_buffer_unmap (buffer, &map);

  have_data++;
}
コード例 #2
0
static gboolean
gst_interleave_channel_positions_to_mask (GValueArray * positions,
    gint default_ordering_map[64], guint64 * mask)
{
  gint i;
  guint channels;
  GstAudioChannelPosition *pos;
  gboolean ret;

  channels = positions->n_values;
  pos = g_new (GstAudioChannelPosition, channels);

  for (i = 0; i < channels; i++) {
    GValue *val;

    val = g_value_array_get_nth (positions, i);
    pos[i] = g_value_get_enum (val);
  }

  /* sort the default ordering map according to the position order */
  for (i = 0; i < channels; i++) {
    default_ordering_map[i] = i;
  }
  g_qsort_with_data (default_ordering_map, channels,
      sizeof (*default_ordering_map), compare_positions, pos);

  ret = gst_audio_channel_positions_to_mask (pos, channels, FALSE, mask);
  g_free (pos);

  return ret;
}
コード例 #3
0
static GstCaps *
gst_fdkaacenc_get_caps (GstAudioEncoder * enc, GstCaps * filter)
{
  GstCaps *res, *caps;
  gint i;

  caps = gst_caps_new_empty ();

  for (i = 0; i < G_N_ELEMENTS (channel_layouts); i++) {
    guint64 channel_mask;
    GstCaps *tmp =
        gst_caps_make_writable (gst_pad_get_pad_template_caps
        (GST_AUDIO_ENCODER_SINK_PAD (enc)));

    if (channel_layouts[i].channels == 1) {
      gst_caps_set_simple (tmp, "channels", G_TYPE_INT,
          channel_layouts[i].channels, NULL);
    } else {
      gst_audio_channel_positions_to_mask (channel_layouts[i].positions,
          channel_layouts[i].channels, FALSE, &channel_mask);
      gst_caps_set_simple (tmp, "channels", G_TYPE_INT,
          channel_layouts[i].channels, "channel-mask", GST_TYPE_BITMASK,
          channel_mask, NULL);
    }

    gst_caps_append (caps, tmp);
  }

  res = gst_audio_encoder_proxy_getcaps (enc, caps, filter);
  gst_caps_unref (caps);

  return res;
}
コード例 #4
0
static gboolean
gst_interleave_channel_positions_to_mask (GValueArray * positions,
    guint64 * mask)
{
  gint i;
  guint channels;
  GstAudioChannelPosition *pos;
  gboolean ret;

  channels = positions->n_values;
  pos = g_new (GstAudioChannelPosition, channels);

  for (i = 0; i < channels; i++) {
    GValue *val;

    val = g_value_array_get_nth (positions, i);
    pos[i] = g_value_get_enum (val);
  }

  ret = gst_audio_channel_positions_to_mask (pos, channels, FALSE, mask);
  g_free (pos);

  return ret;
}
コード例 #5
0
static GstCaps *
gst_openal_helper_probe_caps (ALCcontext * context)
{
  static const struct
  {
    gint count;
    GstAudioChannelPosition positions[8];
  } chans[] = {
    {
      1, {
      GST_AUDIO_CHANNEL_POSITION_MONO}
    }, {
      2, {
      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
    }, {
      4, {
      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
            GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
            GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}
    }, {
      6, {
      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
            GST_AUDIO_CHANNEL_POSITION_LFE1,
            GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
            GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}
    }, {
      7, {
      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
            GST_AUDIO_CHANNEL_POSITION_LFE1,
            GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
            GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
            GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
    }, {
      8, {
      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
            GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
            GST_AUDIO_CHANNEL_POSITION_LFE1,
            GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
            GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
            GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
            GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
  },};
  GstStructure *structure;
  guint64 channel_mask;
  GstCaps *caps;
  ALCcontext *old;

  old = pushContext (context);

  caps = gst_caps_new_empty ();

  if (alIsExtensionPresent ("AL_EXT_MCFORMATS")) {
    const char *fmt32[] = {
      "AL_FORMAT_MONO_FLOAT32",
      "AL_FORMAT_STEREO_FLOAT32",
      "AL_FORMAT_QUAD32",
      "AL_FORMAT_51CHN32",
      "AL_FORMAT_61CHN32",
      "AL_FORMAT_71CHN32",
      NULL
    }, *fmt16[] = {
    "AL_FORMAT_MONO16",
          "AL_FORMAT_STEREO16",
          "AL_FORMAT_QUAD16",
          "AL_FORMAT_51CHN16",
          "AL_FORMAT_61CHN16", "AL_FORMAT_71CHN16", NULL}, *fmt8[] = {
    "AL_FORMAT_MONO8",
          "AL_FORMAT_STEREO8",
          "AL_FORMAT_QUAD8",
          "AL_FORMAT_51CHN8", "AL_FORMAT_61CHN8", "AL_FORMAT_71CHN8", NULL};
    int i;

    if (alIsExtensionPresent ("AL_EXT_FLOAT32")) {
      for (i = 0; fmt32[i]; i++) {
        ALenum value = alGetEnumValue (fmt32[i]);
        if (checkALError () != AL_NO_ERROR || value == 0 || value == -1)
          continue;

        structure =
            gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
            GST_AUDIO_NE (F32), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
            OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL);
        if (chans[i].count > 2) {
          gst_audio_channel_positions_to_mask (chans[i].positions,
              chans[i].count, FALSE, &channel_mask);
          gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
              channel_mask, NULL);
        }
        gst_caps_append_structure (caps, structure);
      }
    }

    for (i = 0; fmt16[i]; i++) {
      ALenum value = alGetEnumValue (fmt16[i]);
      if (checkALError () != AL_NO_ERROR || value == 0 || value == -1)
        continue;

      structure =
          gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
          GST_AUDIO_NE (S16), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
          OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL);
      if (chans[i].count > 2) {
        gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count,
            FALSE, &channel_mask);
        gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
            channel_mask, NULL);
      }
      gst_caps_append_structure (caps, structure);
    }
    for (i = 0; fmt8[i]; i++) {
      ALenum value = alGetEnumValue (fmt8[i]);
      if (checkALError () != AL_NO_ERROR || value == 0 || value == -1)
        continue;

      structure =
          gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
          G_STRINGIFY (U8), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
          OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL);
      if (chans[i].count > 2) {
        gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count,
            FALSE, &channel_mask);
        gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
            channel_mask, NULL);
      }
      gst_caps_append_structure (caps, structure);
    }
  } else {
    if (alIsExtensionPresent ("AL_EXT_FLOAT32")) {
      structure =
          gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
          GST_AUDIO_NE (F32), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
          OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
      gst_caps_append_structure (caps, structure);
    }

    structure =
        gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
        GST_AUDIO_NE (S16), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
        OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
    gst_caps_append_structure (caps, structure);

    structure =
        gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
        G_STRINGIFY (U8), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
        OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
    gst_caps_append_structure (caps, structure);
  }

  if (alIsExtensionPresent ("AL_EXT_double")) {
    structure =
        gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING,
        GST_AUDIO_NE (F64), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE,
        OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
    gst_caps_append_structure (caps, structure);
  }

  if (alIsExtensionPresent ("AL_EXT_IMA4")) {
    structure =
        gst_structure_new ("audio/x-adpcm", "layout", G_TYPE_STRING, "ima",
        "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE,
        "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
    gst_caps_append_structure (caps, structure);
  }

  if (alIsExtensionPresent ("AL_EXT_ALAW")) {
    structure =
        gst_structure_new ("audio/x-alaw", "rate", GST_TYPE_INT_RANGE,
        OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2,
        NULL);
    gst_caps_append_structure (caps, structure);
  }

  if (alIsExtensionPresent ("AL_EXT_MULAW_MCFORMATS")) {
    const char *fmtmulaw[] = {
      "AL_FORMAT_MONO_MULAW",
      "AL_FORMAT_STEREO_MULAW",
      "AL_FORMAT_QUAD_MULAW",
      "AL_FORMAT_51CHN_MULAW",
      "AL_FORMAT_61CHN_MULAW",
      "AL_FORMAT_71CHN_MULAW",
      NULL
    };
    int i;

    for (i = 0; fmtmulaw[i]; i++) {
      ALenum value = alGetEnumValue (fmtmulaw[i]);
      if (checkALError () != AL_NO_ERROR || value == 0 || value == -1)
        continue;

      structure =
          gst_structure_new ("audio/x-mulaw", "rate", GST_TYPE_INT_RANGE,
          OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", G_TYPE_INT,
          chans[i].count, NULL);
      if (chans[i].count > 2) {
        gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count,
            FALSE, &channel_mask);
        gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
            channel_mask, NULL);
      }
      gst_caps_append_structure (caps, structure);
    }
  } else if (alIsExtensionPresent ("AL_EXT_MULAW")) {
    structure =
        gst_structure_new ("audio/x-mulaw", "rate", GST_TYPE_INT_RANGE,
        OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2,
        NULL);
    gst_caps_append_structure (caps, structure);
  }

  popContext (old, context);

  return caps;
}
コード例 #6
0
static gboolean
gst_fdkaacenc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
{
  GstFdkAacEnc *self = GST_FDKAACENC (enc);
  gboolean ret = FALSE;
  GstCaps *allowed_caps;
  GstCaps *src_caps;
  AACENC_ERROR err;
  gint transmux = 0, aot = AOT_AAC_LC;
  gint mpegversion = 4;
  CHANNEL_MODE channel_mode;
  AACENC_InfoStruct enc_info = { 0 };
  gint bitrate;

  if (self->enc) {
    /* drain */
    gst_fdkaacenc_handle_frame (enc, NULL);
    aacEncClose (&self->enc);
  }

  allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (self));

  GST_DEBUG_OBJECT (self, "allowed caps: %" GST_PTR_FORMAT, allowed_caps);

  if (allowed_caps && gst_caps_get_size (allowed_caps) > 0) {
    GstStructure *s = gst_caps_get_structure (allowed_caps, 0);
    const gchar *str = NULL;

    if ((str = gst_structure_get_string (s, "stream-format"))) {
      if (strcmp (str, "adts") == 0) {
        GST_DEBUG_OBJECT (self, "use ADTS format for output");
        transmux = 2;
      } else if (strcmp (str, "adif") == 0) {
        GST_DEBUG_OBJECT (self, "use ADIF format for output");
        transmux = 1;
      } else if (strcmp (str, "raw") == 0) {
        GST_DEBUG_OBJECT (self, "use RAW format for output");
        transmux = 0;
      }
    }

    gst_structure_get_int (s, "mpegversion", &mpegversion);
  }
  if (allowed_caps)
    gst_caps_unref (allowed_caps);

  err = aacEncOpen (&self->enc, 0, GST_AUDIO_INFO_CHANNELS (info));
  if (err != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to open encoder: %d\n", err);
    return FALSE;
  }

  aot = AOT_AAC_LC;

  if ((err = aacEncoder_SetParam (self->enc, AACENC_AOT, aot)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set AOT %d: %d\n", aot, err);
    return FALSE;
  }

  if ((err = aacEncoder_SetParam (self->enc, AACENC_SAMPLERATE,
              GST_AUDIO_INFO_RATE (info))) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set sample rate %d: %d\n",
        GST_AUDIO_INFO_RATE (info), err);
    return FALSE;
  }

  if (GST_AUDIO_INFO_CHANNELS (info) == 1) {
    channel_mode = MODE_1;
    self->need_reorder = FALSE;
    self->aac_positions = NULL;
  } else {
    guint64 in_channel_mask, out_channel_mask;
    gint i;

    for (i = 0; i < G_N_ELEMENTS (channel_layouts); i++) {
      if (channel_layouts[i].channels != GST_AUDIO_INFO_CHANNELS (info))
        continue;

      gst_audio_channel_positions_to_mask (&GST_AUDIO_INFO_POSITION (info, 0),
          GST_AUDIO_INFO_CHANNELS (info), FALSE, &in_channel_mask);
      gst_audio_channel_positions_to_mask (channel_layouts[i].positions,
          channel_layouts[i].channels, FALSE, &out_channel_mask);
      if (in_channel_mask == out_channel_mask) {
        channel_mode = channel_layouts[i].mode;
        self->need_reorder =
            memcmp (channel_layouts[i].positions,
            &GST_AUDIO_INFO_POSITION (info, 0),
            GST_AUDIO_INFO_CHANNELS (info) *
            sizeof (GstAudioChannelPosition)) != 0;
        self->aac_positions = channel_layouts[i].positions;
        break;
      }
    }

    if (i == G_N_ELEMENTS (channel_layouts)) {
      GST_ERROR_OBJECT (self, "Couldn't find a valid channel layout");
      return FALSE;
    }
  }

  if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELMODE,
              channel_mode)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set channel mode %d: %d", channel_mode,
        err);
    return FALSE;
  }

  /* MPEG channel order */
  if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELORDER,
              0)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set channel order %d: %d", channel_mode,
        err);
    return FALSE;
  }

  bitrate = self->bitrate;
  /* See
   * http://wiki.hydrogenaud.io/index.php?title=Fraunhofer_FDK_AAC#Recommended_Sampling_Rate_and_Bitrate_Combinations
   */
  if (bitrate == 0) {
    if (GST_AUDIO_INFO_CHANNELS (info) == 1) {
      if (GST_AUDIO_INFO_RATE (info) < 16000) {
        bitrate = 8000;
      } else if (GST_AUDIO_INFO_RATE (info) == 16000) {
        bitrate = 16000;
      } else if (GST_AUDIO_INFO_RATE (info) < 32000) {
        bitrate = 24000;
      } else if (GST_AUDIO_INFO_RATE (info) == 32000) {
        bitrate = 32000;
      } else if (GST_AUDIO_INFO_RATE (info) <= 44100) {
        bitrate = 56000;
      } else {
        bitrate = 160000;
      }
    } else if (GST_AUDIO_INFO_CHANNELS (info) == 2) {
      if (GST_AUDIO_INFO_RATE (info) < 16000) {
        bitrate = 16000;
      } else if (GST_AUDIO_INFO_RATE (info) == 16000) {
        bitrate = 24000;
      } else if (GST_AUDIO_INFO_RATE (info) < 22050) {
        bitrate = 32000;
      } else if (GST_AUDIO_INFO_RATE (info) < 32000) {
        bitrate = 40000;
      } else if (GST_AUDIO_INFO_RATE (info) == 32000) {
        bitrate = 96000;
      } else if (GST_AUDIO_INFO_RATE (info) <= 44100) {
        bitrate = 112000;
      } else {
        bitrate = 320000;
      }
    } else {
      /* 5, 5.1 */
      if (GST_AUDIO_INFO_RATE (info) < 32000) {
        bitrate = 160000;
      } else if (GST_AUDIO_INFO_RATE (info) <= 44100) {
        bitrate = 240000;
      } else {
        bitrate = 320000;
      }
    }
  }

  if ((err = aacEncoder_SetParam (self->enc, AACENC_TRANSMUX,
              transmux)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set transmux %d: %d", transmux, err);
    return FALSE;
  }

  if ((err = aacEncoder_SetParam (self->enc, AACENC_BITRATE,
              bitrate)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to set bitrate %d: %d", bitrate, err);
    return FALSE;
  }

  if ((err = aacEncEncode (self->enc, NULL, NULL, NULL, NULL)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to initialize encoder: %d", err);
    return FALSE;
  }

  if ((err = aacEncInfo (self->enc, &enc_info)) != AACENC_OK) {
    GST_ERROR_OBJECT (self, "Unable to get encoder info: %d", err);
    return FALSE;
  }

  gst_audio_encoder_set_frame_max (enc, 1);
  gst_audio_encoder_set_frame_samples_min (enc, enc_info.frameLength);
  gst_audio_encoder_set_frame_samples_max (enc, enc_info.frameLength);
  gst_audio_encoder_set_hard_min (enc, FALSE);
  self->outbuf_size = enc_info.maxOutBufBytes;
  self->samples_per_frame = enc_info.frameLength;

  src_caps = gst_caps_new_simple ("audio/mpeg",
      "mpegversion", G_TYPE_INT, mpegversion,
      "channels", G_TYPE_INT, GST_AUDIO_INFO_CHANNELS (info),
      "framed", G_TYPE_BOOLEAN, TRUE,
      "rate", G_TYPE_INT, GST_AUDIO_INFO_RATE (info), NULL);

  /* raw */
  if (transmux == 0) {
    GstBuffer *codec_data =
        gst_buffer_new_wrapped (g_memdup (enc_info.confBuf, enc_info.confSize),
        enc_info.confSize);
    gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER, codec_data,
        "stream-format", G_TYPE_STRING, "raw", NULL);
    gst_buffer_unref (codec_data);
  } else if (transmux == 1) {
    gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adif",
        NULL);
  } else if (transmux == 2) {
    gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts",
        NULL);
  } else {
    g_assert_not_reached ();
  }

  gst_codec_utils_aac_caps_set_level_and_profile (src_caps, enc_info.confBuf,
      enc_info.confSize);

  ret = gst_audio_encoder_set_output_format (enc, src_caps);
  gst_caps_unref (src_caps);

  return ret;
}
コード例 #7
0
/**
 * gst_audio_info_to_caps:
 * @info: a #GstAudioInfo
 *
 * Convert the values of @info into a #GstCaps.
 *
 * Returns: (transfer full): the new #GstCaps containing the
 *          info of @info.
 */
GstCaps *
gst_audio_info_to_caps (const GstAudioInfo * info)
{
  GstCaps *caps;
  const gchar *format;
  const gchar *layout;
  GstAudioFlags flags;

  g_return_val_if_fail (info != NULL, NULL);
  g_return_val_if_fail (info->finfo != NULL, NULL);
  g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL);

  format = gst_audio_format_to_string (info->finfo->format);
  g_return_val_if_fail (format != NULL, NULL);

  if (info->layout == GST_AUDIO_LAYOUT_INTERLEAVED)
    layout = "interleaved";
  else if (info->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
    layout = "non-interleaved";
  else
    g_return_val_if_reached (NULL);

  flags = info->flags;
  if ((flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1
      && info->position[0] != GST_AUDIO_CHANNEL_POSITION_NONE) {
    flags &= ~GST_AUDIO_FLAG_UNPOSITIONED;
    g_warning ("Unpositioned audio channel position flag set but "
        "channel positions present");
  } else if (!(flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1
      && info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
    flags |= GST_AUDIO_FLAG_UNPOSITIONED;
    g_warning ("Unpositioned audio channel position flag not set "
        "but no channel positions present");
  }

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

  if (info->channels > 1
      || info->position[0] != GST_AUDIO_CHANNEL_POSITION_MONO) {
    guint64 channel_mask = 0;

    if ((flags & GST_AUDIO_FLAG_UNPOSITIONED)) {
      channel_mask = 0;
    } else {
      if (!gst_audio_channel_positions_to_mask (info->position, info->channels,
              TRUE, &channel_mask))
        goto invalid_channel_positions;
    }

    if (info->channels == 1
        && info->position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) {
      /* Default mono special case */
    } else {
      gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask,
          NULL);
    }
  }

  return caps;

invalid_channel_positions:
  {
    GST_ERROR ("Invalid channel positions");
    gst_caps_unref (caps);
    return NULL;
  }
}
コード例 #8
0
static gboolean
gst_osx_audio_sink_allowed_caps (GstOsxAudioSink * osxsink)
{
  gint i, channels;
  gboolean spdif_allowed;
  AudioChannelLayout *layout;
  GstElementClass *element_class;
  GstPadTemplate *pad_template;
  GstCaps *caps, *in_caps;
  guint64 channel_mask = 0;
  GstAudioChannelPosition *pos = osxsink->channel_positions;

  /* First collect info about the HW capabilites and preferences */
  spdif_allowed =
      gst_core_audio_audio_device_is_spdif_avail (osxsink->device_id);
  layout = gst_core_audio_audio_device_get_channel_layout (osxsink->device_id);

  GST_DEBUG_OBJECT (osxsink, "Selected device ID: %u SPDIF allowed: %d",
      (unsigned) osxsink->device_id, spdif_allowed);

  if (layout) {
    channels = MIN (layout->mNumberChannelDescriptions,
        GST_OSX_AUDIO_MAX_CHANNEL);
  } else {
    GST_WARNING_OBJECT (osxsink, "This driver does not support "
        "kAudioDevicePropertyPreferredChannelLayout.");
    channels = 2;
  }

  switch (channels) {
    case 0:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
      break;
    case 1:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
      break;
    case 2:
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT);
      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
      break;
    default:
      channels = MIN (layout->mNumberChannelDescriptions,
          GST_OSX_AUDIO_MAX_CHANNEL);
      for (i = 0; i < channels; i++) {
        switch (layout->mChannelDescriptions[i].mChannelLabel) {
          case kAudioChannelLabel_Left:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
            break;
          case kAudioChannelLabel_Right:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
            break;
          case kAudioChannelLabel_Center:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
            break;
          case kAudioChannelLabel_LFEScreen:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
            break;
          case kAudioChannelLabel_LeftSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
            break;
          case kAudioChannelLabel_RightSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
            break;
          case kAudioChannelLabel_RearSurroundLeft:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
            break;
          case kAudioChannelLabel_RearSurroundRight:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
            break;
          case kAudioChannelLabel_CenterSurround:
            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
            break;
          default:
            GST_WARNING_OBJECT (osxsink, "unrecognized channel: %d",
                (int) layout->mChannelDescriptions[i].mChannelLabel);
            channel_mask = 0;
            channels = 2;
            break;
        }
      }
  }
  g_free (layout);

  /* Recover the template caps */
  element_class = GST_ELEMENT_GET_CLASS (osxsink);
  pad_template = gst_element_class_get_pad_template (element_class, "sink");
  in_caps = gst_pad_template_get_caps (pad_template);

  /* Create the allowed subset  */
  caps = gst_caps_new_empty ();
  for (i = 0; i < gst_caps_get_size (in_caps); i++) {
    GstStructure *in_s, *out_s;

    in_s = gst_caps_get_structure (in_caps, i);

    if (gst_structure_has_name (in_s, "audio/x-ac3") ||
        gst_structure_has_name (in_s, "audio/x-dts")) {
      if (spdif_allowed) {
        gst_caps_append_structure (caps, gst_structure_copy (in_s));
      }
    }
    gst_audio_channel_positions_to_mask (pos, channels, false, &channel_mask);
    out_s = gst_structure_copy (in_s);
    gst_structure_remove_fields (out_s, "channels", "channel-mask", NULL);
    gst_structure_set (out_s, "channels", G_TYPE_INT, channels,
        "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
    gst_caps_append_structure (caps, out_s);
  }

  if (osxsink->cached_caps) {
    gst_caps_unref (osxsink->cached_caps);
  }

  osxsink->cached_caps = caps;
  osxsink->channels = channels;

  return TRUE;
}
コード例 #9
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;
}