Exemplo n.º 1
0
gboolean
gst_core_audio_parse_channel_layout (AudioChannelLayout * layout,
    guint * channels, guint64 * channel_mask, GstAudioChannelPosition * pos)
{
  g_assert (channels != NULL);
  g_assert (channel_mask != NULL);
  g_assert (layout != NULL);

  if (layout->mChannelLayoutTag ==
      kAudioChannelLayoutTag_UseChannelDescriptions) {

    switch (layout->mNumberChannelDescriptions) {
      case 0:
        if (pos)
          pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
        *channels = 0;
        *channel_mask = 0;
        return TRUE;
      case 1:
        if (pos)
          pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
        *channels = 1;
        *channel_mask = 0;
        return TRUE;
      case 2:
        if (pos) {
          pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
          pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
        }
        *channels = 2;
        *channel_mask =
            GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
            GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
        return TRUE;
      default:
        _core_audio_parse_channel_descriptions (layout, channels, channel_mask,
            pos);
        return TRUE;
    }
  } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Mono) {
    if (pos)
      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
    *channels = 1;
    *channel_mask = 0;
    return TRUE;
  } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Stereo ||
      layout->mChannelLayoutTag == kAudioChannelLayoutTag_StereoHeadphones ||
      layout->mChannelLayoutTag == kAudioChannelLayoutTag_Binaural) {
    if (pos) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
    }
    *channels = 2;
    *channel_mask =
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
    return TRUE;
  } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Quadraphonic) {
    if (pos) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      pos[2] = GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT;
      pos[3] = GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT;
    }
    *channels = 4;
    *channel_mask =
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_RIGHT);
    return TRUE;
  } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Pentagonal) {
    if (pos) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      pos[2] = GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT;
      pos[3] = GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT;
      pos[4] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
    }
    *channels = 5;
    *channel_mask =
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER);
    return TRUE;
  } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Cube) {
    if (pos) {
      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
      pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
      pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
      pos[4] = GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT;
      pos[5] = GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT;
      pos[6] = GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT;
      pos[7] = GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT;

    }
    *channels = 8;
    *channel_mask =
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (TOP_FRONT_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (TOP_FRONT_RIGHT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (TOP_REAR_LEFT) |
        GST_AUDIO_CHANNEL_POSITION_MASK (TOP_REAR_RIGHT);
    return TRUE;
  } else {
    GST_WARNING
        ("AudioChannelLayoutTag: %u not yet supported",
        layout->mChannelLayoutTag);
    *channels = 0;
    *channel_mask = 0;
    return FALSE;
  }
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
static gboolean
gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps)
{
  pa_channel_map channel_map;
  const pa_channel_map *m;
  GstStructure *s;
  gboolean need_channel_layout = FALSE;
  GstAudioRingBufferSpec spec;
  const gchar *name;

  s = gst_caps_get_structure (*caps, 0);
  gst_structure_get_int (s, "channels", &spec.info.channels);
  if (!gst_structure_has_field (s, "channel-mask")) {
    if (spec.info.channels == 1) {
      pa_channel_map_init_mono (&channel_map);
    } else if (spec.info.channels == 2) {
      gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
          GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
          GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT), NULL);
      pa_channel_map_init_stereo (&channel_map);
    } else {
      need_channel_layout = TRUE;
      gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
          G_GUINT64_CONSTANT (0), NULL);
    }
  }

  memset (&spec, 0, sizeof (GstAudioRingBufferSpec));
  spec.latency_time = GST_SECOND;
  if (!gst_audio_ring_buffer_parse_caps (&spec, *caps))
    goto invalid_caps;

  /* Keep the refcount of the caps at 1 to make them writable */
  gst_caps_unref (spec.caps);

  if (!need_channel_layout
      && !gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
    need_channel_layout = TRUE;
    gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
        G_GUINT64_CONSTANT (0), NULL);
    memset (spec.info.position, 0xff, sizeof (spec.info.position));
  }

  if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec))
    goto invalid_spec;

  pa_threaded_mainloop_lock (pulsesrc->mainloop);

  if (!pulsesrc->context)
    goto bad_context;

  name = "Record Stream";
  if (pulsesrc->proplist) {
    if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
                name, &pulsesrc->sample_spec,
                (need_channel_layout) ? NULL : &channel_map,
                pulsesrc->proplist)))
      goto create_failed;

  } else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
              name, &pulsesrc->sample_spec,
              (need_channel_layout) ? NULL : &channel_map)))
    goto create_failed;

  m = pa_stream_get_channel_map (pulsesrc->stream);
  gst_pulse_channel_map_to_gst (m, &spec);
  gst_audio_channel_positions_to_valid_order (spec.info.position,
      spec.info.channels);
  gst_caps_unref (*caps);
  *caps = gst_audio_info_to_caps (&spec.info);

  GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);

  pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
      pulsesrc);
  pa_stream_set_read_callback (pulsesrc->stream, gst_pulsesrc_stream_request_cb,
      pulsesrc);
  pa_stream_set_underflow_callback (pulsesrc->stream,
      gst_pulsesrc_stream_underflow_cb, pulsesrc);
  pa_stream_set_overflow_callback (pulsesrc->stream,
      gst_pulsesrc_stream_overflow_cb, pulsesrc);
  pa_stream_set_latency_update_callback (pulsesrc->stream,
      gst_pulsesrc_stream_latency_update_cb, pulsesrc);

  pa_threaded_mainloop_unlock (pulsesrc->mainloop);

  return TRUE;

  /* ERRORS */
invalid_caps:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
        ("Can't parse caps."), (NULL));
    goto fail;
  }
invalid_spec:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
        ("Invalid sample specification."), (NULL));
    goto fail;
  }
bad_context:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Bad context"), (NULL));
    goto unlock_and_fail;
  }
create_failed:
  {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
        ("Failed to create stream: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }
unlock_and_fail:
  {
    gst_pulsesrc_destroy_stream (pulsesrc);

    pa_threaded_mainloop_unlock (pulsesrc->mainloop);

  fail:
    return FALSE;
  }
}
Exemplo n.º 4
0
static GstCaps *
gst_flite_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{
  GstStructure *structure;
  gint channels;

  caps = gst_caps_truncate (caps);
  caps = gst_caps_make_writable (caps);

  structure = gst_caps_get_structure (caps, 0);

  gst_structure_fixate_field_nearest_int (structure, "channels", 2);
  gst_structure_get_int (structure, "channels", &channels);

  if (channels == 1) {
    gst_structure_remove_field (structure, "channel-mask");
  } else {
    guint64 channel_mask = 0;
    gint x = 63;

    if (!gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK,
            &channel_mask, NULL)) {
      switch (channels) {
        case 8:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
              GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) |
              GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_RIGHT);
          break;
        case 7:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
              GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_CENTER);
          break;
        case 6:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) |
              GST_AUDIO_CHANNEL_POSITION_MASK (LFE1);
          break;
        case 5:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER);
          break;
        case 4:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT);
          break;
        case 3:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (LFE1);
          break;
        case 2:
          channel_mask =
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
              GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
          break;
        default:
          channel_mask = 0;
          break;
      }
    }

    while (n_bits_set (channel_mask) > channels) {
      channel_mask &= ~(G_GUINT64_CONSTANT (1) << x);
      x--;
    }

    gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK,
        channel_mask, NULL);
  }

  return GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
}