mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
pulsesrc: Handle negotiation events
This makes sure that we: a) Destroy an existing stream if a negotiate() request comes in: this is required when receiving a downstream renegotiation request after a stream has been created. b) Create a new stream on prepare(): this is required since we do a setcaps() in negotiate(), which causes the stream to be dropped by a ringbuffer release() call (this does not happen during first negotiation since the release is only done on a running ringbuffer). The subsequent call to ringbuffer acquire() fails because the stream was lost on release(). https://bugzilla.gnome.org/show_bug.cgi?id=681247
This commit is contained in:
parent
1a8512986a
commit
ef9c81d495
1 changed files with 63 additions and 35 deletions
|
@ -1136,48 +1136,71 @@ server_dead:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps)
|
||||
gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps,
|
||||
GstAudioRingBufferSpec * rspec)
|
||||
{
|
||||
pa_channel_map channel_map;
|
||||
const pa_channel_map *m;
|
||||
GstStructure *s;
|
||||
gboolean need_channel_layout = FALSE;
|
||||
GstAudioRingBufferSpec spec;
|
||||
GstAudioRingBufferSpec new_spec, *spec;
|
||||
const gchar *name;
|
||||
int i;
|
||||
|
||||
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) {
|
||||
pa_channel_map_init_stereo (&channel_map);
|
||||
} else {
|
||||
/* If we already have a stream (renegotiation), free it first */
|
||||
if (pulsesrc->stream)
|
||||
gst_pulsesrc_destroy_stream (pulsesrc);
|
||||
|
||||
if (rspec) {
|
||||
/* Post-negotiation, we already have a ringbuffer spec, so we just need to
|
||||
* use it to create a stream. */
|
||||
spec = rspec;
|
||||
|
||||
/* At this point, we expect the channel-mask to be set in caps, so we just
|
||||
* use that */
|
||||
if (!gst_pulse_gst_to_channel_map (&channel_map, spec))
|
||||
goto invalid_spec;
|
||||
|
||||
} else if (caps) {
|
||||
/* At negotiation time, we get a fixed caps and use it to set up a stream */
|
||||
s = gst_caps_get_structure (*caps, 0);
|
||||
gst_structure_get_int (s, "channels", &new_spec.info.channels);
|
||||
if (!gst_structure_has_field (s, "channel-mask")) {
|
||||
if (new_spec.info.channels == 1) {
|
||||
pa_channel_map_init_mono (&channel_map);
|
||||
} else if (new_spec.info.channels == 2) {
|
||||
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 (&new_spec, 0, sizeof (GstAudioRingBufferSpec));
|
||||
new_spec.latency_time = GST_SECOND;
|
||||
if (!gst_audio_ring_buffer_parse_caps (&new_spec, *caps))
|
||||
goto invalid_caps;
|
||||
|
||||
/* Keep the refcount of the caps at 1 to make them writable */
|
||||
gst_caps_unref (new_spec.caps);
|
||||
|
||||
if (!need_channel_layout
|
||||
&& !gst_pulse_gst_to_channel_map (&channel_map, &new_spec)) {
|
||||
need_channel_layout = TRUE;
|
||||
gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
|
||||
G_GUINT64_CONSTANT (0), NULL);
|
||||
for (i = 0; i < G_N_ELEMENTS (new_spec.info.position); i++)
|
||||
new_spec.info.position[i] = GST_AUDIO_CHANNEL_POSITION_INVALID;
|
||||
}
|
||||
|
||||
spec = &new_spec;
|
||||
} else {
|
||||
/* !rspec && !caps */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
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);
|
||||
for (i = 0; i < G_N_ELEMENTS (spec.info.position); i++)
|
||||
spec.info.position[i] = GST_AUDIO_CHANNEL_POSITION_INVALID;
|
||||
}
|
||||
|
||||
if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec))
|
||||
if (!gst_pulse_fill_sample_spec (spec, &pulsesrc->sample_spec))
|
||||
goto invalid_spec;
|
||||
|
||||
pa_threaded_mainloop_lock (pulsesrc->mainloop);
|
||||
|
@ -1198,12 +1221,14 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps)
|
|||
(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);
|
||||
if (caps) {
|
||||
m = pa_stream_get_channel_map (pulsesrc->stream);
|
||||
gst_pulse_channel_map_to_gst (m, &new_spec);
|
||||
gst_audio_channel_positions_to_valid_order (new_spec.info.position,
|
||||
new_spec.info.channels);
|
||||
gst_caps_unref (*caps);
|
||||
*caps = gst_audio_info_to_caps (&new_spec.info);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
|
||||
|
||||
|
@ -1305,7 +1330,7 @@ gst_pulsesrc_negotiate (GstBaseSrc * basesrc)
|
|||
result = TRUE;
|
||||
} else if (gst_caps_is_fixed (caps)) {
|
||||
/* yay, fixed caps, use those then */
|
||||
result = gst_pulsesrc_create_stream (pulsesrc, &caps);
|
||||
result = gst_pulsesrc_create_stream (pulsesrc, &caps, NULL);
|
||||
if (result)
|
||||
result = gst_base_src_set_caps (basesrc, caps);
|
||||
}
|
||||
|
@ -1335,6 +1360,9 @@ gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
|
|||
|
||||
pa_threaded_mainloop_lock (pulsesrc->mainloop);
|
||||
|
||||
if (!pulsesrc->stream)
|
||||
gst_pulsesrc_create_stream (pulsesrc, NULL, spec);
|
||||
|
||||
{
|
||||
GstAudioRingBufferSpec s = *spec;
|
||||
const pa_channel_map *m;
|
||||
|
|
Loading…
Reference in a new issue