Commit 55ae3aa9 authored by philn@webkit.org's avatar philn@webkit.org

[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.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160216 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 0dc4522f
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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment