Skip to content
Permalink
Browse files
[GStreamer] webkitwebaudiosrc element needs to emit stream-start, cap…
…s and segment events

https://bugs.webkit.org/show_bug.cgi?id=123015

Reviewed by Martin Robinson.

When the source element starts emitting buffers send along various
events to notify downstream elements.

No new tests, change covered by existing webaudio tests.

* platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp:
(webkit_web_audio_src_init): Initialize segment.
(webKitWebAudioSrcConstructed): Give an explicit name to each
queue added in front of the interleave element.
(webKitWebAudioSrcLoop): Before sending the first buffers push
stream-start, caps and segment events on each queue's sinkpad.

Canonical link: https://commits.webkit.org/143435@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@160216 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
philn committed Dec 6, 2013
1 parent efa3521 commit e21f5d9acbe45b1a6be30408999f70e3b6b83da5
Showing 2 changed files with 60 additions and 2 deletions.
@@ -1,3 +1,22 @@
2013-11-11 Philippe Normand <pnormand@igalia.com>

[GStreamer] webkitwebaudiosrc element needs to emit stream-start, caps and segment events
https://bugs.webkit.org/show_bug.cgi?id=123015

Reviewed by Martin Robinson.

When the source element starts emitting buffers send along various
events to notify downstream elements.

No new tests, change covered by existing webaudio tests.

* platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp:
(webkit_web_audio_src_init): Initialize segment.
(webKitWebAudioSrcConstructed): Give an explicit name to each
queue added in front of the interleave element.
(webKitWebAudioSrcLoop): Before sending the first buffers push
stream-start, caps and segment events on each queue's sinkpad.

2013-12-05 Philippe Normand <pnormand@igalia.com>

[GStreamer] Audio/Video sink management is incoherent
@@ -60,6 +60,9 @@ struct _WebKitWebAudioSourcePrivate {

GSList* pads; // List of queue sink pads. One queue for each planar audio channel.
GstPad* sourcePad; // src pad of the element, interleaved wav data is pushed to it.

bool newStreamEventPending;
GstSegment segment;
};

enum {
@@ -181,6 +184,9 @@ static void webkit_web_audio_src_init(WebKitWebAudioSrc* src)
priv->provider = 0;
priv->bus = 0;

priv->newStreamEventPending = true;
gst_segment_init(&priv->segment, GST_FORMAT_TIME);

g_rec_mutex_init(&priv->mutex);
priv->task = gst_task_new(reinterpret_cast<GstTaskFunction>(webKitWebAudioSrcLoop), src, 0);

@@ -215,7 +221,8 @@ static void webKitWebAudioSrcConstructed(GObject* object)
// For each channel of the bus create a new upstream branch for interleave, like:
// queue ! capsfilter ! audioconvert. which is plugged to a new interleave request sinkpad.
for (unsigned channelIndex = 0; channelIndex < priv->bus->numberOfChannels(); channelIndex++) {
GstElement* queue = gst_element_factory_make("queue", 0);
GOwnPtr<gchar> queueName(g_strdup_printf("webaudioQueue%u", channelIndex));
GstElement* queue = gst_element_factory_make("queue", queueName.get());
GstElement* capsfilter = gst_element_factory_make("capsfilter", 0);
GstElement* audioconvert = gst_element_factory_make("audioconvert", 0);

@@ -334,15 +341,46 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src)

GSList* padsIt = priv->pads;
GSList* buffersIt = channelBufferList;

#if GST_CHECK_VERSION(1, 2, 0)
guint groupId = 0;
if (priv->newStreamEventPending)
groupId = gst_util_group_id_next();
#endif

for (i = 0; padsIt && buffersIt; padsIt = g_slist_next(padsIt), buffersIt = g_slist_next(buffersIt), ++i) {
GstPad* pad = static_cast<GstPad*>(padsIt->data);
GstBuffer* channelBuffer = static_cast<GstBuffer*>(buffersIt->data);

// Send stream-start, segment and caps events downstream, along with the first buffer.
if (priv->newStreamEventPending) {
GRefPtr<GstElement> queue = adoptGRef(gst_pad_get_parent_element(pad));
GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(queue.get(), "sink"));
GOwnPtr<gchar> queueName(gst_element_get_name(queue.get()));
GOwnPtr<gchar> streamId(g_strdup_printf("webaudio/%s", queueName.get()));
GstEvent* streamStartEvent = gst_event_new_stream_start(streamId.get());
#if GST_CHECK_VERSION(1, 2, 0)
gst_event_set_group_id(streamStartEvent, groupId);
#endif
gst_pad_send_event(sinkPad.get(), streamStartEvent);

GRefPtr<GstCaps> monoCaps = adoptGRef(getGStreamerMonoAudioCaps(priv->sampleRate));
GstAudioInfo info;
gst_audio_info_from_caps(&info, monoCaps.get());
GST_AUDIO_INFO_POSITION(&info, 0) = webKitWebAudioGStreamerChannelPosition(i);
GRefPtr<GstCaps> capsWithChannelPosition = adoptGRef(gst_audio_info_to_caps(&info));
gst_pad_send_event(sinkPad.get(), gst_event_new_caps(capsWithChannelPosition.get()));

gst_pad_send_event(sinkPad.get(), gst_event_new_segment(&priv->segment));
}

GstFlowReturn ret = gst_pad_chain(pad, channelBuffer);
if (ret != GST_FLOW_OK)
GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to push buffer on %s:%s", GST_DEBUG_PAD_NAME(pad)));
GST_ELEMENT_ERROR(src, CORE, PAD, ("Internal WebAudioSrc error"), ("Failed to push buffer on %s:%s flow: %s", GST_DEBUG_PAD_NAME(pad), gst_flow_get_name(ret)));
}

priv->newStreamEventPending = false;

g_slist_free(channelBufferList);
}

@@ -381,6 +419,7 @@ static GstStateChangeReturn webKitWebAudioSrcChangeState(GstElement* element, Gs
returnValue = GST_STATE_CHANGE_FAILURE;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
src->priv->newStreamEventPending = true;
GST_DEBUG_OBJECT(src, "PAUSED->READY");
if (!gst_task_join(src->priv->task.get()))
returnValue = GST_STATE_CHANGE_FAILURE;

0 comments on commit e21f5d9

Please sign in to comment.