From a401d8c96df59d68e71cb166a571dd500c076db2 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 21 Jan 2016 12:45:13 +0100 Subject: [PATCH 01/14] [GStreamer][MSE] m_bus as AppendPipeline attribute --- .../gstreamer/MediaPlayerPrivateGStreamerMSE.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 51014bce808fa..62e91b4c51d36 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -142,6 +142,7 @@ class AppendPipeline : public ThreadSafeRefCounted { GstFlowReturn m_flowReturn; GstElement* m_pipeline; + GRefPtr m_bus; GstElement* m_appsrc; GstElement* m_typefind; GstElement* m_qtdemux; @@ -1223,11 +1224,11 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo // The track name is still unknown at this time, though. m_pipeline = gst_pipeline_new(NULL); - GRefPtr bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline))); - gst_bus_add_signal_watch(bus.get()); - gst_bus_enable_sync_message_emission(bus.get()); + m_bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline))); + gst_bus_add_signal_watch(m_bus.get()); + gst_bus_enable_sync_message_emission(m_bus.get()); - g_signal_connect(bus.get(), "sync-message::element", G_CALLBACK(appendPipelineElementMessageCallback), this); + g_signal_connect(m_bus.get(), "sync-message::element", G_CALLBACK(appendPipelineElementMessageCallback), this); g_mutex_init(&m_newSampleMutex); g_cond_init(&m_newSampleCondition); @@ -1292,10 +1293,9 @@ AppendPipeline::~AppendPipeline() cancelLastSampleTimer(); if (m_pipeline) { - GRefPtr bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline))); - ASSERT(bus); - g_signal_handlers_disconnect_by_func(bus.get(), reinterpret_cast(appendPipelineElementMessageCallback), this); - gst_bus_disable_sync_message_emission(bus.get()); + ASSERT(m_bus); + g_signal_handlers_disconnect_by_func(m_bus.get(), reinterpret_cast(appendPipelineElementMessageCallback), this); + gst_bus_disable_sync_message_emission(m_bus.get()); gst_element_set_state (m_pipeline, GST_STATE_NULL); gst_object_unref(m_pipeline); From 242dee832fa909fd607f594e70d6e9d1df1974c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Oca=C3=B1a=20Gonz=C3=A1lez?= Date: Wed, 30 Dec 2015 11:41:28 +0000 Subject: [PATCH 02/14] [GStreamer][MSE] Detect append end using events For this we use custom events. Signed-off-by: Xabier Rodriguez Calvar --- .../MediaPlayerPrivateGStreamerMSE.cpp | 120 +++++++++++++++++- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 62e91b4c51d36..24696a3e0e1a6 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -125,8 +125,12 @@ class AppendPipeline : public ThreadSafeRefCounted { void scheduleLastSampleTimer(); void cancelLastSampleTimer(); + void setAppendIdReceivedInSink(guint64 id); + void receiveEndOfAppendData(); + private: void resetPipeline(); + void markEndOfAppendData(); // TODO: Hide everything and use getters/setters. private: @@ -161,6 +165,18 @@ class AppendPipeline : public ThreadSafeRefCounted { GstCaps* m_demuxerSrcPadCaps; FloatSize m_presentationSize; + // Unique id of the current append operation. Used to mark + // custom events, detect them in the sink and trigger lastSampleTimeout + // ahead of time. + + // This is the last id marked right after appending to appsrc + guint64 m_appendIdMarkedInSrc; + + // This is the last id received by the probe in the appsink sink pad + guint64 m_appendIdReceivedInSink; + + gulong m_endOfDataProbeId; + // Some appended data are only headers and don't generate any // useful stream data for decoding. This is detected with a // timeout and reported to the upper layers, so update/updateend @@ -1191,6 +1207,8 @@ static void appendPipelineDemuxerPadRemoved(GstElement*, GstPad*, AppendPipeline static gboolean appendPipelineDemuxerConnectToAppSinkMainThread(PadInfo*); static gboolean appendPipelineDemuxerDisconnectFromAppSinkMainThread(PadInfo*); static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeline*); +static gboolean receiveEndOfAppendDataFromMainThread(gpointer); +static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *pad, GstPadProbeInfo *info, AppendPipeline* ap); static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); static void appendPipelineAppSinkEOS(GstElement*, AppendPipeline*); @@ -1210,6 +1228,8 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo , m_id(0) , m_appSinkCaps(NULL) , m_demuxerSrcPadCaps(NULL) + , m_appendIdMarkedInSrc(0) + , m_appendIdReceivedInSink(0) , m_dataStarvedTimeoutTag(0) , m_lastSampleTimeoutTag(0) , m_appendStage(NotStarted) @@ -1254,6 +1274,8 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo GRefPtr appSinkPad = adoptGRef(gst_element_get_static_pad(m_appsink, "sink")); g_signal_connect(appSinkPad.get(), "notify::caps", G_CALLBACK(appendPipelineAppSinkCapsChanged), this); + m_endOfDataProbeId = gst_pad_add_probe(appSinkPad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast(appendPipelineAppSinkEvent), this, nullptr); + // These signals won't be connected outside of the lifetime of "this". g_signal_connect(m_qtdemux, "pad-added", G_CALLBACK(appendPipelineDemuxerPadAdded), this); g_signal_connect(m_qtdemux, "pad-removed", G_CALLBACK(appendPipelineDemuxerPadRemoved), this); @@ -1330,6 +1352,8 @@ AppendPipeline::~AppendPipeline() g_signal_handlers_disconnect_by_func(m_appsink, (gpointer)appendPipelineAppSinkNewSample, this); g_signal_handlers_disconnect_by_func(m_appsink, (gpointer)appendPipelineAppSinkEOS, this); + gst_pad_remove_probe(appSinkPad.get(), m_endOfDataProbeId); + gst_object_unref(m_appsink); m_appsink = NULL; } @@ -1490,6 +1514,7 @@ void AppendPipeline::setAppendStage(AppendStage newAppendStage) ok = true; if (m_pendingBuffer) { gst_app_src_push_buffer(GST_APP_SRC(appsrc()), m_pendingBuffer.leakRef()); + markEndOfAppendData(); nextAppendStage = Ongoing; } break; @@ -1753,6 +1778,25 @@ void AppendPipeline::appSinkCapsChanged() gst_caps_unref(caps); } +void AppendPipeline::receiveEndOfAppendData() +{ + ASSERT(WTF::isMainThread()); + + switch (m_appendStage) { + case Ongoing: + TRACE_MEDIA_MESSAGE("DataStarve"); + setAppendStage(DataStarve); + break; + case Sampling: + TRACE_MEDIA_MESSAGE("LastSample"); + setAppendStage(LastSample); + break; + default: + ERROR_MEDIA_MESSAGE("Unexpected"); + break; + } +} + void AppendPipeline::appSinkNewSample(GstSample* sample) { ASSERT(WTF::isMainThread()); @@ -1799,6 +1843,14 @@ void AppendPipeline::appSinkNewSample(GstSample* sample) m_flowReturn = GST_FLOW_OK; g_cond_signal(&m_newSampleCondition); g_mutex_unlock(&m_newSampleMutex); + + TRACE_MEDIA_MESSAGE("m_appendIdMarkedInSrc=%" G_GUINT64_FORMAT ", m_appendIdReceivedInSink=%" G_GUINT64_FORMAT, m_appendIdMarkedInSrc, m_appendIdReceivedInSink); + + if (m_appendIdReceivedInSink && m_appendIdMarkedInSrc == m_appendIdReceivedInSink) { + LOG_MEDIA_MESSAGE("Marked and received append ids match, this must be the LastSample of the batch"); + m_appendIdReceivedInSink = 0; + receiveEndOfAppendData(); + } } void AppendPipeline::appSinkEOS() @@ -1904,12 +1956,44 @@ void AppendPipeline::abort() GstFlowReturn AppendPipeline::pushNewBuffer(GstBuffer* buffer) { + GstFlowReturn result; + if (m_abortPending) { m_pendingBuffer = adoptGRef(buffer); - return GST_FLOW_OK; + result = GST_FLOW_OK; + } else { + setAppendStage(AppendPipeline::Ongoing); + result = gst_app_src_push_buffer(GST_APP_SRC(appsrc()), buffer); + markEndOfAppendData(); + } + + return result; +} + +void AppendPipeline::markEndOfAppendData() +{ + GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data")); + m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); + + gst_element_send_event(m_appsrc, event); + + GstBuffer* emptyBuffer = gst_buffer_new_and_alloc(0); + gst_buffer_fill(emptyBuffer, 0, nullptr, 0); + gst_app_src_push_buffer(GST_APP_SRC(appsrc()), emptyBuffer); +} + +void AppendPipeline::setAppendIdReceivedInSink(guint64 id) +{ + m_appendIdReceivedInSink = id; + + if (m_appendStage == Ongoing) { + if (WTF::isMainThread()) { + receiveEndOfAppendData(); + } else { + ref(); + g_timeout_add(0, receiveEndOfAppendDataFromMainThread, this); + } } - setAppendStage(AppendPipeline::Ongoing); - return gst_app_src_push_buffer(GST_APP_SRC(appsrc()), buffer); } GstFlowReturn AppendPipeline::handleNewSample(GstElement* appsink) @@ -2066,6 +2150,9 @@ void AppendPipeline::connectToAppSink(GstPad* demuxerSrcPad) break; } + // The previous mark has probably been lost because appsink was disconnected. Mark again. + markEndOfAppendData(); + g_cond_signal(&m_padAddRemoveCondition); } @@ -2129,6 +2216,33 @@ static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeli g_timeout_add(0, appSinkCapsChangedFromMainThread, ap); } +static gboolean receiveEndOfAppendDataFromMainThread(gpointer data) +{ + AppendPipeline* ap = reinterpret_cast(data); + ap->receiveEndOfAppendData(); + ap->deref(); + return G_SOURCE_REMOVE; +} + +static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *info, AppendPipeline* ap) +{ + GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); + if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) + return GST_PAD_PROBE_OK; + + const GstStructure* structure = gst_event_get_structure(event); + if (!gst_structure_has_name(structure, "end-of-append-data")) + return GST_PAD_PROBE_OK; + + guint64 id = guint64(gst_event_get_seqnum(event)); + + TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); + + ap->setAppendIdReceivedInSink(id); + + return GST_PAD_PROBE_OK; +} + static void appendPipelineDemuxerPadAdded(GstElement*, GstPad* demuxerSrcPad, AppendPipeline* ap) { ap->connectToAppSinkFromAnyThread(demuxerSrcPad); From 549b4e14d87946bd81a65a2d02c9dc96e42a338c Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Wed, 20 Jan 2016 16:42:27 +0100 Subject: [PATCH 03/14] [GStreamer][MSE] Disable timeouts They only assert if reached. --- .../MediaPlayerPrivateGStreamerMSE.cpp | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 24696a3e0e1a6..8d795492538a2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -1213,8 +1213,8 @@ static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline* static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); static void appendPipelineAppSinkEOS(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkEOSMainThread(AppendPipeline* ap); -static gboolean appendPipelineDataStarveTimeout(AppendPipeline* ap); -static gboolean appendPipelineLastSampleTimeout(AppendPipeline* ap); +static gboolean appendPipelineDataStarveTimeout(gpointer); +static gboolean appendPipelineLastSampleTimeout(gpointer); static void appendPipelineElementMessageCallback(GstBus*, GstMessage* message, AppendPipeline* ap) { @@ -1453,7 +1453,7 @@ gint AppendPipeline::id() void AppendPipeline::scheduleDataStarveTimer() { LOG_MEDIA_MESSAGE("Scheduling data starve timer"); - m_dataStarvedTimeoutTag = g_timeout_add(s_dataStarvedTimeoutMsec, GSourceFunc(appendPipelineDataStarveTimeout), this); + m_dataStarvedTimeoutTag = g_timeout_add(s_dataStarvedTimeoutMsec, appendPipelineDataStarveTimeout, this); } void AppendPipeline::cancelDataStarveTimer() @@ -1470,7 +1470,7 @@ void AppendPipeline::scheduleLastSampleTimer() { if (m_lastSampleTimeoutTag) cancelLastSampleTimer(); - m_lastSampleTimeoutTag = g_timeout_add(s_lastSampleTimeoutMsec, GSourceFunc(appendPipelineLastSampleTimeout), this); + m_lastSampleTimeoutTag = g_timeout_add(s_lastSampleTimeoutMsec, appendPipelineLastSampleTimeout, this); } void AppendPipeline::cancelLastSampleTimer() @@ -2299,23 +2299,17 @@ static gboolean appendPipelineAppSinkEOSMainThread(AppendPipeline* ap) return G_SOURCE_REMOVE; } -static gboolean appendPipelineDataStarveTimeout(AppendPipeline* ap) +static gboolean appendPipelineDataStarveTimeout(gpointer) { - LOG_MEDIA_MESSAGE("data starve timer fired"); - if (ap->appendStage()==AppendPipeline::AppendStage::Invalid) - return G_SOURCE_REMOVE; - - ap->setAppendStage(AppendPipeline::DataStarve); + ERROR_MEDIA_MESSAGE("data starve timer fired"); + ASSERT_NOT_REACHED(); return G_SOURCE_REMOVE; } -static gboolean appendPipelineLastSampleTimeout(AppendPipeline* ap) +static gboolean appendPipelineLastSampleTimeout(gpointer) { - TRACE_MEDIA_MESSAGE("last sample timer fired"); - if (ap->appendStage()==AppendPipeline::AppendStage::Invalid) - return G_SOURCE_REMOVE; - - ap->setAppendStage(AppendPipeline::LastSample); + ERROR_MEDIA_MESSAGE("last sample timer fired"); + ASSERT_NOT_REACHED(); return G_SOURCE_REMOVE; } From 04b9503dd053f6e09aad665513349188f71ec2a0 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Fri, 5 Feb 2016 12:53:43 +0100 Subject: [PATCH 04/14] [GStreamer][MSE] Handle last sample thru the bus Instead of deferring to the main thread with timeouts, we always put the message through the bus as an application message. We get the message and move the state if we are in Sampling instead of Ongoing. --- .../MediaPlayerPrivateGStreamerMSE.cpp | 65 ++++++++++++------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 8d795492538a2..4e92e862d1595 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -88,6 +88,7 @@ class AppendPipeline : public ThreadSafeRefCounted { virtual ~AppendPipeline(); void handleElementMessage(GstMessage*); + void handleApplicationMessage(GstMessage*); gint id(); AppendStage appendStage() { return m_appendStage; } @@ -125,12 +126,13 @@ class AppendPipeline : public ThreadSafeRefCounted { void scheduleLastSampleTimer(); void cancelLastSampleTimer(); - void setAppendIdReceivedInSink(guint64 id); + void reportEndOfAppendDataMarkReceived(guint64 id); void receiveEndOfAppendData(); private: void resetPipeline(); void markEndOfAppendData(); + void handleEndOfAppendDataMarkReceived(const GstStructure*); // TODO: Hide everything and use getters/setters. private: @@ -1207,7 +1209,6 @@ static void appendPipelineDemuxerPadRemoved(GstElement*, GstPad*, AppendPipeline static gboolean appendPipelineDemuxerConnectToAppSinkMainThread(PadInfo*); static gboolean appendPipelineDemuxerDisconnectFromAppSinkMainThread(PadInfo*); static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeline*); -static gboolean receiveEndOfAppendDataFromMainThread(gpointer); static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *pad, GstPadProbeInfo *info, AppendPipeline* ap); static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); @@ -1221,6 +1222,11 @@ static void appendPipelineElementMessageCallback(GstBus*, GstMessage* message, A ap->handleElementMessage(message); } +static void appendPipelineApplicationMessageCallback(GstBus*, GstMessage* message, AppendPipeline* appendPipeline) +{ + appendPipeline->handleApplicationMessage(message); +} + AppendPipeline::AppendPipeline(PassRefPtr mediaSourceClient, PassRefPtr sourceBufferPrivate, MediaPlayerPrivateGStreamerMSE* playerPrivate) : m_mediaSourceClient(mediaSourceClient) , m_sourceBufferPrivate(sourceBufferPrivate) @@ -1249,6 +1255,7 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo gst_bus_enable_sync_message_emission(m_bus.get()); g_signal_connect(m_bus.get(), "sync-message::element", G_CALLBACK(appendPipelineElementMessageCallback), this); + g_signal_connect(m_bus.get(), "message::application", G_CALLBACK(appendPipelineApplicationMessageCallback), this); g_mutex_init(&m_newSampleMutex); g_cond_init(&m_newSampleCondition); @@ -1413,6 +1420,30 @@ void AppendPipeline::handleElementMessage(GstMessage* message) m_playerPrivate->handleSyncMessage(message); } +void AppendPipeline::handleApplicationMessage(GstMessage* message) +{ + ASSERT(WTF::isMainThread()); + + const GstStructure* structure = gst_message_get_structure(message); + + if (gst_structure_has_name(structure, "end-of-append-data-mark-received")) { + handleEndOfAppendDataMarkReceived(structure); + return; + } + + ASSERT_NOT_REACHED(); +} + +void AppendPipeline::handleEndOfAppendDataMarkReceived(const GstStructure* structure) +{ + gst_structure_get(structure, "id", G_TYPE_UINT64, &m_appendIdReceivedInSink, NULL); + ASSERT(m_appendIdReceivedInSink); + + TRACE_MEDIA_MESSAGE("received end of append id %" G_GUINT64_FORMAT " in the sink", m_appendIdReceivedInSink); + if (m_appendStage == Sampling) + receiveEndOfAppendData(); +} + gint AppendPipeline::id() { ASSERT(WTF::isMainThread()); @@ -1972,7 +2003,7 @@ GstFlowReturn AppendPipeline::pushNewBuffer(GstBuffer* buffer) void AppendPipeline::markEndOfAppendData() { - GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data")); + GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data-mark")); m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); gst_element_send_event(m_appsrc, event); @@ -1982,18 +2013,12 @@ void AppendPipeline::markEndOfAppendData() gst_app_src_push_buffer(GST_APP_SRC(appsrc()), emptyBuffer); } -void AppendPipeline::setAppendIdReceivedInSink(guint64 id) +void AppendPipeline::reportEndOfAppendDataMarkReceived(guint64 id) { - m_appendIdReceivedInSink = id; - - if (m_appendStage == Ongoing) { - if (WTF::isMainThread()) { - receiveEndOfAppendData(); - } else { - ref(); - g_timeout_add(0, receiveEndOfAppendDataFromMainThread, this); - } - } + GstStructure* structure = gst_structure_new("end-of-append-data-mark-received", "id", G_TYPE_UINT64, id, NULL); + GstMessage* message = gst_message_new_application(GST_OBJECT(m_appsink), structure); + gst_bus_post(m_bus.get(), message); + TRACE_MEDIA_MESSAGE("received message with id %" G_GUINT64_FORMAT ", re-posted to bus", id); } GstFlowReturn AppendPipeline::handleNewSample(GstElement* appsink) @@ -2216,14 +2241,6 @@ static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeli g_timeout_add(0, appSinkCapsChangedFromMainThread, ap); } -static gboolean receiveEndOfAppendDataFromMainThread(gpointer data) -{ - AppendPipeline* ap = reinterpret_cast(data); - ap->receiveEndOfAppendData(); - ap->deref(); - return G_SOURCE_REMOVE; -} - static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *info, AppendPipeline* ap) { GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); @@ -2231,14 +2248,14 @@ static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *i return GST_PAD_PROBE_OK; const GstStructure* structure = gst_event_get_structure(event); - if (!gst_structure_has_name(structure, "end-of-append-data")) + if (!gst_structure_has_name(structure, "end-of-append-data-mark")) return GST_PAD_PROBE_OK; guint64 id = guint64(gst_event_get_seqnum(event)); TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); - ap->setAppendIdReceivedInSink(id); + ap->reportEndOfAppendDataMarkReceived(id); return GST_PAD_PROBE_OK; } From d81ed733e9e0c27a84192bb0f8298a019c0e4a8d Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Tue, 2 Feb 2016 15:56:41 +0100 Subject: [PATCH 05/14] [GStreamer][MSE] Add more traces --- .../graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 4e92e862d1595..ddb5f05f87daf 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -1544,6 +1544,7 @@ void AppendPipeline::setAppendStage(AppendStage newAppendStage) case NotStarted: ok = true; if (m_pendingBuffer) { + TRACE_MEDIA_MESSAGE("pushing pending buffer %p", m_pendingBuffer.get()); gst_app_src_push_buffer(GST_APP_SRC(appsrc()), m_pendingBuffer.leakRef()); markEndOfAppendData(); nextAppendStage = Ongoing; @@ -1813,6 +1814,8 @@ void AppendPipeline::receiveEndOfAppendData() { ASSERT(WTF::isMainThread()); + TRACE_MEDIA_MESSAGE("end of append data mark was received"); + switch (m_appendStage) { case Ongoing: TRACE_MEDIA_MESSAGE("DataStarve"); @@ -1994,6 +1997,7 @@ GstFlowReturn AppendPipeline::pushNewBuffer(GstBuffer* buffer) result = GST_FLOW_OK; } else { setAppendStage(AppendPipeline::Ongoing); + TRACE_MEDIA_MESSAGE("pushing new buffer %p", buffer); result = gst_app_src_push_buffer(GST_APP_SRC(appsrc()), buffer); markEndOfAppendData(); } @@ -2006,6 +2010,8 @@ void AppendPipeline::markEndOfAppendData() GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data-mark")); m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); + TRACE_MEDIA_MESSAGE("marking end of append with id %" G_GUINT64_FORMAT, m_appendIdMarkedInSrc); + gst_element_send_event(m_appsrc, event); GstBuffer* emptyBuffer = gst_buffer_new_and_alloc(0); @@ -2176,6 +2182,7 @@ void AppendPipeline::connectToAppSink(GstPad* demuxerSrcPad) } // The previous mark has probably been lost because appsink was disconnected. Mark again. + TRACE_MEDIA_MESSAGE("previous append end mark lost, reinsterting"); markEndOfAppendData(); g_cond_signal(&m_padAddRemoveCondition); From 73041defae2c74af2013f34b2d1ba954f342743a Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Tue, 2 Feb 2016 16:07:50 +0100 Subject: [PATCH 06/14] [GStreamer][MSE] Rework checking for end of append This method does not blindly declares the end of the append operation, it does the checks that were done in some cases before calling that method. Also, we reset to 0 the mark received at the sink when it was dealt with. --- .../MediaPlayerPrivateGStreamerMSE.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index ddb5f05f87daf..3eacb184707f0 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -127,10 +127,10 @@ class AppendPipeline : public ThreadSafeRefCounted { void cancelLastSampleTimer(); void reportEndOfAppendDataMarkReceived(guint64 id); - void receiveEndOfAppendData(); private: void resetPipeline(); + void checkEndOfAppendDataMarkReceived(); void markEndOfAppendData(); void handleEndOfAppendDataMarkReceived(const GstStructure*); @@ -1441,7 +1441,7 @@ void AppendPipeline::handleEndOfAppendDataMarkReceived(const GstStructure* struc TRACE_MEDIA_MESSAGE("received end of append id %" G_GUINT64_FORMAT " in the sink", m_appendIdReceivedInSink); if (m_appendStage == Sampling) - receiveEndOfAppendData(); + checkEndOfAppendDataMarkReceived(); } gint AppendPipeline::id() @@ -1810,19 +1810,24 @@ void AppendPipeline::appSinkCapsChanged() gst_caps_unref(caps); } -void AppendPipeline::receiveEndOfAppendData() +void AppendPipeline::checkEndOfAppendDataMarkReceived() { ASSERT(WTF::isMainThread()); + if (!m_appendIdReceivedInSink || m_appendIdMarkedInSrc != m_appendIdReceivedInSink) + return; + TRACE_MEDIA_MESSAGE("end of append data mark was received"); switch (m_appendStage) { case Ongoing: TRACE_MEDIA_MESSAGE("DataStarve"); + m_appendIdReceivedInSink = 0; setAppendStage(DataStarve); break; case Sampling: TRACE_MEDIA_MESSAGE("LastSample"); + m_appendIdReceivedInSink = 0; setAppendStage(LastSample); break; default: @@ -1878,13 +1883,7 @@ void AppendPipeline::appSinkNewSample(GstSample* sample) g_cond_signal(&m_newSampleCondition); g_mutex_unlock(&m_newSampleMutex); - TRACE_MEDIA_MESSAGE("m_appendIdMarkedInSrc=%" G_GUINT64_FORMAT ", m_appendIdReceivedInSink=%" G_GUINT64_FORMAT, m_appendIdMarkedInSrc, m_appendIdReceivedInSink); - - if (m_appendIdReceivedInSink && m_appendIdMarkedInSrc == m_appendIdReceivedInSink) { - LOG_MEDIA_MESSAGE("Marked and received append ids match, this must be the LastSample of the batch"); - m_appendIdReceivedInSink = 0; - receiveEndOfAppendData(); - } + checkEndOfAppendDataMarkReceived(); } void AppendPipeline::appSinkEOS() @@ -2009,6 +2008,7 @@ void AppendPipeline::markEndOfAppendData() { GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data-mark")); m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); + m_appendIdReceivedInSink = 0; TRACE_MEDIA_MESSAGE("marking end of append with id %" G_GUINT64_FORMAT, m_appendIdMarkedInSrc); From 8873e57463b210b3ac23abd432e2befdf8e25686 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Fri, 5 Feb 2016 13:22:38 +0100 Subject: [PATCH 07/14] [GStreamer][MSE] Rework marking end of append In some cases current custom events can go thru the appsrc src pad before the buffer itself, causing that the buffer is not processed. Now we send a probe for buffers in the appsrc src pad and when a buffer goes thru, we engage the process of marking the end of the append. The end of the append is done at the main thread by sending an application message thru the bus. --- .../MediaPlayerPrivateGStreamerMSE.cpp | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 3eacb184707f0..7aec2c8733ac4 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -126,12 +126,13 @@ class AppendPipeline : public ThreadSafeRefCounted { void scheduleLastSampleTimer(); void cancelLastSampleTimer(); + void reportEndOfAppendDataMarkNeeded(); void reportEndOfAppendDataMarkReceived(guint64 id); private: void resetPipeline(); void checkEndOfAppendDataMarkReceived(); - void markEndOfAppendData(); + void handleEndOfAppendDataMarkNeeded(); void handleEndOfAppendDataMarkReceived(const GstStructure*); // TODO: Hide everything and use getters/setters. @@ -178,6 +179,7 @@ class AppendPipeline : public ThreadSafeRefCounted { guint64 m_appendIdReceivedInSink; gulong m_endOfDataProbeId; + gulong m_appsrcDataLeavingProbeId; // Some appended data are only headers and don't generate any // useful stream data for decoding. This is detected with a @@ -1210,6 +1212,7 @@ static gboolean appendPipelineDemuxerConnectToAppSinkMainThread(PadInfo*); static gboolean appendPipelineDemuxerDisconnectFromAppSinkMainThread(PadInfo*); static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeline*); static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *pad, GstPadProbeInfo *info, AppendPipeline* ap); +static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInfo*, AppendPipeline*); static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); static void appendPipelineAppSinkEOS(GstElement*, AppendPipeline*); @@ -1283,6 +1286,9 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo m_endOfDataProbeId = gst_pad_add_probe(appSinkPad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast(appendPipelineAppSinkEvent), this, nullptr); + GRefPtr appsrcPad = adoptGRef(gst_element_get_static_pad(m_appsrc, "src")); + m_appsrcDataLeavingProbeId = gst_pad_add_probe(appsrcPad.get(), GST_PAD_PROBE_TYPE_BUFFER, reinterpret_cast(appendPipelineAppsrcDataLeaving), this, nullptr); + // These signals won't be connected outside of the lifetime of "this". g_signal_connect(m_qtdemux, "pad-added", G_CALLBACK(appendPipelineDemuxerPadAdded), this); g_signal_connect(m_qtdemux, "pad-removed", G_CALLBACK(appendPipelineDemuxerPadRemoved), this); @@ -1332,6 +1338,8 @@ AppendPipeline::~AppendPipeline() } if (m_appsrc) { + GRefPtr appsrcPad = adoptGRef(gst_element_get_static_pad(m_appsrc, "src")); + gst_pad_remove_probe(appsrcPad.get(), m_appsrcDataLeavingProbeId); gst_object_unref(m_appsrc); m_appsrc = NULL; } @@ -1431,6 +1439,11 @@ void AppendPipeline::handleApplicationMessage(GstMessage* message) return; } + if (gst_structure_has_name(structure, "end-of-append-data-mark-needed")) { + handleEndOfAppendDataMarkNeeded(); + return; + } + ASSERT_NOT_REACHED(); } @@ -1546,7 +1559,6 @@ void AppendPipeline::setAppendStage(AppendStage newAppendStage) if (m_pendingBuffer) { TRACE_MEDIA_MESSAGE("pushing pending buffer %p", m_pendingBuffer.get()); gst_app_src_push_buffer(GST_APP_SRC(appsrc()), m_pendingBuffer.leakRef()); - markEndOfAppendData(); nextAppendStage = Ongoing; } break; @@ -1998,13 +2010,12 @@ GstFlowReturn AppendPipeline::pushNewBuffer(GstBuffer* buffer) setAppendStage(AppendPipeline::Ongoing); TRACE_MEDIA_MESSAGE("pushing new buffer %p", buffer); result = gst_app_src_push_buffer(GST_APP_SRC(appsrc()), buffer); - markEndOfAppendData(); } return result; } -void AppendPipeline::markEndOfAppendData() +void AppendPipeline::handleEndOfAppendDataMarkNeeded() { GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data-mark")); m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); @@ -2027,6 +2038,14 @@ void AppendPipeline::reportEndOfAppendDataMarkReceived(guint64 id) TRACE_MEDIA_MESSAGE("received message with id %" G_GUINT64_FORMAT ", re-posted to bus", id); } +void AppendPipeline::reportEndOfAppendDataMarkNeeded() +{ + GstStructure* structure = gst_structure_new_empty("end-of-append-data-mark-needed"); + GstMessage* message = gst_message_new_application(GST_OBJECT(m_appsrc), structure); + gst_bus_post(m_bus.get(), message); + TRACE_MEDIA_MESSAGE("received buffer going thru, re-posted to bus"); +} + GstFlowReturn AppendPipeline::handleNewSample(GstElement* appsink) { ASSERT(!WTF::isMainThread()); @@ -2183,7 +2202,7 @@ void AppendPipeline::connectToAppSink(GstPad* demuxerSrcPad) // The previous mark has probably been lost because appsink was disconnected. Mark again. TRACE_MEDIA_MESSAGE("previous append end mark lost, reinsterting"); - markEndOfAppendData(); + handleEndOfAppendDataMarkNeeded(); g_cond_signal(&m_padAddRemoveCondition); } @@ -2248,6 +2267,17 @@ static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeli g_timeout_add(0, appSinkCapsChangedFromMainThread, ap); } +static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInfo* info, AppendPipeline* appendPipeline) +{ + TRACE_MEDIA_MESSAGE("buffer going thru"); + + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + if (gst_buffer_get_size(buffer) > 0) + appendPipeline->reportEndOfAppendDataMarkNeeded(); + + return GST_PAD_PROBE_OK; +} + static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *info, AppendPipeline* ap) { GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); From ad8b743a9806c7bc96871e612d27a69d6286ea6c Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 4 Feb 2016 12:23:14 +0100 Subject: [PATCH 08/14] [GStreamer][MSE] Check end of append when Ongoing --- .../graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 7aec2c8733ac4..29d5def1753f6 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -1453,7 +1453,7 @@ void AppendPipeline::handleEndOfAppendDataMarkReceived(const GstStructure* struc ASSERT(m_appendIdReceivedInSink); TRACE_MEDIA_MESSAGE("received end of append id %" G_GUINT64_FORMAT " in the sink", m_appendIdReceivedInSink); - if (m_appendStage == Sampling) + if (m_appendStage == Sampling || m_appendStage == Ongoing) checkEndOfAppendDataMarkReceived(); } From ec42f9bc9e301c718d57000a76765b3d855436ee Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 4 Feb 2016 12:28:51 +0100 Subject: [PATCH 09/14] [GStreamer][MSE] Rename appsink probe This renames the appsink probe functions and attributes. --- .../gstreamer/MediaPlayerPrivateGStreamerMSE.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 29d5def1753f6..95ccdfeebb428 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -178,7 +178,7 @@ class AppendPipeline : public ThreadSafeRefCounted { // This is the last id received by the probe in the appsink sink pad guint64 m_appendIdReceivedInSink; - gulong m_endOfDataProbeId; + gulong m_appsinkDataEnteringProbeId; gulong m_appsrcDataLeavingProbeId; // Some appended data are only headers and don't generate any @@ -1211,7 +1211,7 @@ static void appendPipelineDemuxerPadRemoved(GstElement*, GstPad*, AppendPipeline static gboolean appendPipelineDemuxerConnectToAppSinkMainThread(PadInfo*); static gboolean appendPipelineDemuxerDisconnectFromAppSinkMainThread(PadInfo*); static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeline*); -static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *pad, GstPadProbeInfo *info, AppendPipeline* ap); +static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeInfo*, AppendPipeline*); static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInfo*, AppendPipeline*); static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); @@ -1284,7 +1284,7 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo GRefPtr appSinkPad = adoptGRef(gst_element_get_static_pad(m_appsink, "sink")); g_signal_connect(appSinkPad.get(), "notify::caps", G_CALLBACK(appendPipelineAppSinkCapsChanged), this); - m_endOfDataProbeId = gst_pad_add_probe(appSinkPad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast(appendPipelineAppSinkEvent), this, nullptr); + m_appsinkDataEnteringProbeId = gst_pad_add_probe(appSinkPad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast(appendPipelineAppsinkDataEntering), this, nullptr); GRefPtr appsrcPad = adoptGRef(gst_element_get_static_pad(m_appsrc, "src")); m_appsrcDataLeavingProbeId = gst_pad_add_probe(appsrcPad.get(), GST_PAD_PROBE_TYPE_BUFFER, reinterpret_cast(appendPipelineAppsrcDataLeaving), this, nullptr); @@ -1367,7 +1367,7 @@ AppendPipeline::~AppendPipeline() g_signal_handlers_disconnect_by_func(m_appsink, (gpointer)appendPipelineAppSinkNewSample, this); g_signal_handlers_disconnect_by_func(m_appsink, (gpointer)appendPipelineAppSinkEOS, this); - gst_pad_remove_probe(appSinkPad.get(), m_endOfDataProbeId); + gst_pad_remove_probe(appSinkPad.get(), m_appsinkDataEnteringProbeId); gst_object_unref(m_appsink); m_appsink = NULL; @@ -2278,7 +2278,7 @@ static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInf return GST_PAD_PROBE_OK; } -static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *info, AppendPipeline* ap) +static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeInfo* info, AppendPipeline* appendPipeline) { GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) @@ -2292,7 +2292,7 @@ static GstPadProbeReturn appendPipelineAppSinkEvent(GstPad *, GstPadProbeInfo *i TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); - ap->reportEndOfAppendDataMarkReceived(id); + appendPipeline->reportEndOfAppendDataMarkReceived(id); return GST_PAD_PROBE_OK; } From c9b6201726f7ebc548e837dc8d83cdabb26adb1e Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 4 Feb 2016 14:28:22 +0100 Subject: [PATCH 10/14] [GStreamer][MSE] Add pad debug information --- .../MediaPlayerPrivateGStreamerMSE.cpp | 140 ++++++++++++++++-- 1 file changed, 129 insertions(+), 11 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 95ccdfeebb428..3bb497f10763d 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -77,6 +77,13 @@ using namespace std; namespace WebCore { +struct PadProbeInformation +{ + AppendPipeline* m_appendPipeline; + const char* m_description; + gulong m_probeId; +}; + class AppendPipeline : public ThreadSafeRefCounted { public: enum AppendStage { Invalid, NotStarted, Ongoing, KeyNegotiation, DataStarve, Sampling, LastSample, Aborting }; @@ -180,6 +187,11 @@ class AppendPipeline : public ThreadSafeRefCounted { gulong m_appsinkDataEnteringProbeId; gulong m_appsrcDataLeavingProbeId; +#ifdef DEBUG_APPEND_PIPELINE_PADS + struct PadProbeInformation m_demuxerDataEnteringPadProbeInformation; + struct PadProbeInformation m_typefindDataEnteringPadProbeInformation; + struct PadProbeInformation m_typefindDataLeavingPadProbeInformation; +#endif // Some appended data are only headers and don't generate any // useful stream data for decoding. This is detected with a @@ -1213,6 +1225,9 @@ static gboolean appendPipelineDemuxerDisconnectFromAppSinkMainThread(PadInfo*); static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeline*); static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeInfo*, AppendPipeline*); static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInfo*, AppendPipeline*); +#ifdef DEBUG_APPEND_PIPELINE_PADS +static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadProbeInfo*, struct PadProbeInformation*); +#endif static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); static void appendPipelineAppSinkEOS(GstElement*, AppendPipeline*); @@ -1284,10 +1299,35 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo GRefPtr appSinkPad = adoptGRef(gst_element_get_static_pad(m_appsink, "sink")); g_signal_connect(appSinkPad.get(), "notify::caps", G_CALLBACK(appendPipelineAppSinkCapsChanged), this); +#ifdef DEBUG_APPEND_PIPELINE_PADS + m_appsinkDataEnteringProbeId = gst_pad_add_probe(appSinkPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelineAppsinkDataEntering), this, nullptr); +#else m_appsinkDataEnteringProbeId = gst_pad_add_probe(appSinkPad.get(), GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, reinterpret_cast(appendPipelineAppsinkDataEntering), this, nullptr); +#endif GRefPtr appsrcPad = adoptGRef(gst_element_get_static_pad(m_appsrc, "src")); +#ifdef DEBUG_APPEND_PIPELINE_PADS + m_appsrcDataLeavingProbeId = gst_pad_add_probe(appsrcPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelineAppsrcDataLeaving), this, nullptr); +#else m_appsrcDataLeavingProbeId = gst_pad_add_probe(appsrcPad.get(), GST_PAD_PROBE_TYPE_BUFFER, reinterpret_cast(appendPipelineAppsrcDataLeaving), this, nullptr); +#endif + +#ifdef DEBUG_APPEND_PIPELINE_PADS + GRefPtr typefindSinkPad = adoptGRef(gst_element_get_static_pad(m_typefind, "sink")); + m_typefindDataEnteringPadProbeInformation.m_appendPipeline = this; + m_typefindDataEnteringPadProbeInformation.m_description = "typefind data entering"; + m_typefindDataEnteringPadProbeInformation.m_probeId = gst_pad_add_probe(typefindSinkPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelinePadProbeDebugInformation), &m_typefindDataEnteringPadProbeInformation, nullptr); + + GRefPtr typefindSrcPad = adoptGRef(gst_element_get_static_pad(m_typefind, "src")); + m_typefindDataLeavingPadProbeInformation.m_appendPipeline = this; + m_typefindDataLeavingPadProbeInformation.m_description = "typefind data leaving"; + m_typefindDataLeavingPadProbeInformation.m_probeId = gst_pad_add_probe(typefindSrcPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelinePadProbeDebugInformation), &m_typefindDataLeavingPadProbeInformation, nullptr); + + GRefPtr demuxerPad = adoptGRef(gst_element_get_static_pad(m_qtdemux, "sink")); + m_demuxerDataEnteringPadProbeInformation.m_appendPipeline = this; + m_demuxerDataEnteringPadProbeInformation.m_description = "demuxer data entering"; + m_demuxerDataEnteringPadProbeInformation.m_probeId = gst_pad_add_probe(demuxerPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelinePadProbeDebugInformation), &m_demuxerDataEnteringPadProbeInformation, nullptr); +#endif // These signals won't be connected outside of the lifetime of "this". g_signal_connect(m_qtdemux, "pad-added", G_CALLBACK(appendPipelineDemuxerPadAdded), this); @@ -1345,11 +1385,22 @@ AppendPipeline::~AppendPipeline() } if (m_typefind) { +#ifdef DEBUG_APPEND_PIPELINE_PADS + GRefPtr sinkPad = adoptGRef(gst_element_get_static_pad(m_typefind, "sink")); + gst_pad_remove_probe(sinkPad.get(), m_typefindDataEnteringPadProbeInformation.m_probeId); + GRefPtr srcPad = adoptGRef(gst_element_get_static_pad(m_typefind, "src")); + gst_pad_remove_probe(srcPad.get(), m_typefindDataLeavingPadProbeInformation.m_probeId); +#endif gst_object_unref(m_typefind); m_typefind = NULL; } if (m_qtdemux) { +#ifdef DEBUG_APPEND_PIPELINE_PADS + GRefPtr demuxerPad = adoptGRef(gst_element_get_static_pad(m_qtdemux, "sink")); + gst_pad_remove_probe(demuxerPad.get(), m_demuxerDataEnteringPadProbeInformation.m_probeId); +#endif + g_signal_handlers_disconnect_by_func(m_qtdemux, (gpointer)appendPipelineDemuxerPadAdded, this); g_signal_handlers_disconnect_by_func(m_qtdemux, (gpointer)appendPipelineDemuxerPadRemoved, this); @@ -2269,33 +2320,100 @@ static void appendPipelineAppSinkCapsChanged(GObject*, GParamSpec*, AppendPipeli static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInfo* info, AppendPipeline* appendPipeline) { - TRACE_MEDIA_MESSAGE("buffer going thru"); + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) { + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + gsize bufferSize = gst_buffer_get_size(buffer); - GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); - if (gst_buffer_get_size(buffer) > 0) - appendPipeline->reportEndOfAppendDataMarkNeeded(); + TRACE_MEDIA_MESSAGE("buffer of size %d going thru", bufferSize); + + if (bufferSize > 0) + appendPipeline->reportEndOfAppendDataMarkNeeded(); + + return GST_PAD_PROBE_OK; + } + +#ifdef DEBUG_APPEND_PIPELINE_PADS + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { + GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); + if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) + return GST_PAD_PROBE_OK; + + const GstStructure* structure = gst_event_get_structure(event); + if (!gst_structure_has_name(structure, "end-of-append-data-mark")) + return GST_PAD_PROBE_OK; + + guint64 id = guint64(gst_event_get_seqnum(event)); + TRACE_MEDIA_MESSAGE("custom downstream event id=%" G_GUINT64_FORMAT, id); + + return GST_PAD_PROBE_OK; + } +#endif + ASSERT_NOT_REACHED(); return GST_PAD_PROBE_OK; } static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeInfo* info, AppendPipeline* appendPipeline) { - GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); - if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { + GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); + if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) + return GST_PAD_PROBE_OK; + + const GstStructure* structure = gst_event_get_structure(event); + if (!gst_structure_has_name(structure, "end-of-append-data-mark")) + return GST_PAD_PROBE_OK; + + guint64 id = guint64(gst_event_get_seqnum(event)); + + TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); + + appendPipeline->reportEndOfAppendDataMarkReceived(id); + return GST_PAD_PROBE_OK; + } + +#ifdef DEBUG_APPEND_PIPELINE_PADS + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) { + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + TRACE_MEDIA_MESSAGE("buffer of size %d going thru", gst_buffer_get_size(buffer)); + return GST_PAD_PROBE_OK; + } +#endif - const GstStructure* structure = gst_event_get_structure(event); - if (!gst_structure_has_name(structure, "end-of-append-data-mark")) + ASSERT_NOT_REACHED(); + return GST_PAD_PROBE_OK; +} + +#ifdef DEBUG_APPEND_PIPELINE_PADS +static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadProbeInfo* info, struct PadProbeInformation* padProbeInformation) +{ + ASSERT(GST_PAD_PROBE_INFO_TYPE(info) != static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)); + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) { + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + TRACE_MEDIA_MESSAGE("%s: buffer of size %d going thru", padProbeInformation->m_description, gst_buffer_get_size(buffer)); return GST_PAD_PROBE_OK; + } - guint64 id = guint64(gst_event_get_seqnum(event)); + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { + GstEvent* event = GST_PAD_PROBE_INFO_EVENT(info); + if (GST_EVENT_TYPE(event) != GST_EVENT_CUSTOM_DOWNSTREAM) + return GST_PAD_PROBE_OK; - TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); + const GstStructure* structure = gst_event_get_structure(event); + if (!gst_structure_has_name(structure, "end-of-append-data-mark")) + return GST_PAD_PROBE_OK; - appendPipeline->reportEndOfAppendDataMarkReceived(id); + guint64 id = guint64(gst_event_get_seqnum(event)); + TRACE_MEDIA_MESSAGE("%s: custom downstream event id=%" G_GUINT64_FORMAT, padProbeInformation->m_description, id); + return GST_PAD_PROBE_OK; + } + + ASSERT_NOT_REACHED(); return GST_PAD_PROBE_OK; } +#endif static void appendPipelineDemuxerPadAdded(GstElement*, GstPad* demuxerSrcPad, AppendPipeline* ap) { From aedb08af720cd5b8bb7ac104f730805ffa9ef13d Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 4 Feb 2016 14:40:47 +0100 Subject: [PATCH 11/14] [GStreamer][MSE] Remove typefind typefind is causing problems by swaling some buffers and not letting that information go through --- .../MediaPlayerPrivateGStreamerMSE.cpp | 30 ++----------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 3bb497f10763d..c34c38e778ec3 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -158,7 +158,6 @@ class AppendPipeline : public ThreadSafeRefCounted { GstElement* m_pipeline; GRefPtr m_bus; GstElement* m_appsrc; - GstElement* m_typefind; GstElement* m_qtdemux; GstElement* m_decryptor; @@ -189,8 +188,6 @@ class AppendPipeline : public ThreadSafeRefCounted { gulong m_appsrcDataLeavingProbeId; #ifdef DEBUG_APPEND_PIPELINE_PADS struct PadProbeInformation m_demuxerDataEnteringPadProbeInformation; - struct PadProbeInformation m_typefindDataEnteringPadProbeInformation; - struct PadProbeInformation m_typefindDataLeavingPadProbeInformation; #endif // Some appended data are only headers and don't generate any @@ -1283,7 +1280,6 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo m_decryptor = NULL; m_appsrc = gst_element_factory_make("appsrc", NULL); - m_typefind = gst_element_factory_make("typefind", NULL); m_qtdemux = gst_element_factory_make("qtdemux", NULL); { GValue val = G_VALUE_INIT; @@ -1313,16 +1309,6 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo #endif #ifdef DEBUG_APPEND_PIPELINE_PADS - GRefPtr typefindSinkPad = adoptGRef(gst_element_get_static_pad(m_typefind, "sink")); - m_typefindDataEnteringPadProbeInformation.m_appendPipeline = this; - m_typefindDataEnteringPadProbeInformation.m_description = "typefind data entering"; - m_typefindDataEnteringPadProbeInformation.m_probeId = gst_pad_add_probe(typefindSinkPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelinePadProbeDebugInformation), &m_typefindDataEnteringPadProbeInformation, nullptr); - - GRefPtr typefindSrcPad = adoptGRef(gst_element_get_static_pad(m_typefind, "src")); - m_typefindDataLeavingPadProbeInformation.m_appendPipeline = this; - m_typefindDataLeavingPadProbeInformation.m_description = "typefind data leaving"; - m_typefindDataLeavingPadProbeInformation.m_probeId = gst_pad_add_probe(typefindSrcPad.get(), static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), reinterpret_cast(appendPipelinePadProbeDebugInformation), &m_typefindDataLeavingPadProbeInformation, nullptr); - GRefPtr demuxerPad = adoptGRef(gst_element_get_static_pad(m_qtdemux, "sink")); m_demuxerDataEnteringPadProbeInformation.m_appendPipeline = this; m_demuxerDataEnteringPadProbeInformation.m_description = "demuxer data entering"; @@ -1337,12 +1323,11 @@ AppendPipeline::AppendPipeline(PassRefPtr mediaSo // Add_many will take ownership of a reference. Request one ref more for ourselves. gst_object_ref(m_appsrc); - gst_object_ref(m_typefind); gst_object_ref(m_qtdemux); gst_object_ref(m_appsink); - gst_bin_add_many(GST_BIN(m_pipeline), m_appsrc, m_typefind, m_qtdemux, NULL); - gst_element_link_many(m_appsrc, m_typefind, m_qtdemux, NULL); + gst_bin_add_many(GST_BIN(m_pipeline), m_appsrc, m_qtdemux, NULL); + gst_element_link(m_appsrc, m_qtdemux); gst_element_set_state(m_pipeline, GST_STATE_READY); }; @@ -1384,17 +1369,6 @@ AppendPipeline::~AppendPipeline() m_appsrc = NULL; } - if (m_typefind) { -#ifdef DEBUG_APPEND_PIPELINE_PADS - GRefPtr sinkPad = adoptGRef(gst_element_get_static_pad(m_typefind, "sink")); - gst_pad_remove_probe(sinkPad.get(), m_typefindDataEnteringPadProbeInformation.m_probeId); - GRefPtr srcPad = adoptGRef(gst_element_get_static_pad(m_typefind, "src")); - gst_pad_remove_probe(srcPad.get(), m_typefindDataLeavingPadProbeInformation.m_probeId); -#endif - gst_object_unref(m_typefind); - m_typefind = NULL; - } - if (m_qtdemux) { #ifdef DEBUG_APPEND_PIPELINE_PADS GRefPtr demuxerPad = adoptGRef(gst_element_get_static_pad(m_qtdemux, "sink")); From 9ceb98679f0912e145ac07bdf265677f544368d8 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Mon, 8 Feb 2016 11:34:51 +0100 Subject: [PATCH 12/14] [GStreamer][MSE] Make EOA markers guint --- .../MediaPlayerPrivateGStreamerMSE.cpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index c34c38e778ec3..cc76e95caac38 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -134,7 +134,7 @@ class AppendPipeline : public ThreadSafeRefCounted { void cancelLastSampleTimer(); void reportEndOfAppendDataMarkNeeded(); - void reportEndOfAppendDataMarkReceived(guint64 id); + void reportEndOfAppendDataMarkReceived(guint id); private: void resetPipeline(); @@ -179,10 +179,10 @@ class AppendPipeline : public ThreadSafeRefCounted { // ahead of time. // This is the last id marked right after appending to appsrc - guint64 m_appendIdMarkedInSrc; + guint m_appendIdMarkedInSrc; // This is the last id received by the probe in the appsink sink pad - guint64 m_appendIdReceivedInSink; + guint m_appendIdReceivedInSink; gulong m_appsinkDataEnteringProbeId; gulong m_appsrcDataLeavingProbeId; @@ -1474,10 +1474,10 @@ void AppendPipeline::handleApplicationMessage(GstMessage* message) void AppendPipeline::handleEndOfAppendDataMarkReceived(const GstStructure* structure) { - gst_structure_get(structure, "id", G_TYPE_UINT64, &m_appendIdReceivedInSink, NULL); + gst_structure_get(structure, "id", G_TYPE_UINT, &m_appendIdReceivedInSink, NULL); ASSERT(m_appendIdReceivedInSink); - TRACE_MEDIA_MESSAGE("received end of append id %" G_GUINT64_FORMAT " in the sink", m_appendIdReceivedInSink); + TRACE_MEDIA_MESSAGE("received end of append id %d in the sink", m_appendIdReceivedInSink); if (m_appendStage == Sampling || m_appendStage == Ongoing) checkEndOfAppendDataMarkReceived(); } @@ -2043,10 +2043,10 @@ GstFlowReturn AppendPipeline::pushNewBuffer(GstBuffer* buffer) void AppendPipeline::handleEndOfAppendDataMarkNeeded() { GstEvent* event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, gst_structure_new_empty("end-of-append-data-mark")); - m_appendIdMarkedInSrc = guint64(gst_event_get_seqnum(event)); + m_appendIdMarkedInSrc = gst_event_get_seqnum(event); m_appendIdReceivedInSink = 0; - TRACE_MEDIA_MESSAGE("marking end of append with id %" G_GUINT64_FORMAT, m_appendIdMarkedInSrc); + TRACE_MEDIA_MESSAGE("marking end of append with id %d", m_appendIdMarkedInSrc); gst_element_send_event(m_appsrc, event); @@ -2055,12 +2055,12 @@ void AppendPipeline::handleEndOfAppendDataMarkNeeded() gst_app_src_push_buffer(GST_APP_SRC(appsrc()), emptyBuffer); } -void AppendPipeline::reportEndOfAppendDataMarkReceived(guint64 id) +void AppendPipeline::reportEndOfAppendDataMarkReceived(guint id) { - GstStructure* structure = gst_structure_new("end-of-append-data-mark-received", "id", G_TYPE_UINT64, id, NULL); + GstStructure* structure = gst_structure_new("end-of-append-data-mark-received", "id", G_TYPE_UINT, id, NULL); GstMessage* message = gst_message_new_application(GST_OBJECT(m_appsink), structure); gst_bus_post(m_bus.get(), message); - TRACE_MEDIA_MESSAGE("received message with id %" G_GUINT64_FORMAT ", re-posted to bus", id); + TRACE_MEDIA_MESSAGE("received message with id %d, re-posted to bus", id); } void AppendPipeline::reportEndOfAppendDataMarkNeeded() @@ -2316,8 +2316,8 @@ static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInf if (!gst_structure_has_name(structure, "end-of-append-data-mark")) return GST_PAD_PROBE_OK; - guint64 id = guint64(gst_event_get_seqnum(event)); - TRACE_MEDIA_MESSAGE("custom downstream event id=%" G_GUINT64_FORMAT, id); + guint id = gst_event_get_seqnum(event); + TRACE_MEDIA_MESSAGE("custom downstream event id=%d", id); return GST_PAD_PROBE_OK; } @@ -2338,9 +2338,9 @@ static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeI if (!gst_structure_has_name(structure, "end-of-append-data-mark")) return GST_PAD_PROBE_OK; - guint64 id = guint64(gst_event_get_seqnum(event)); + guint id = gst_event_get_seqnum(event); - TRACE_MEDIA_MESSAGE("id=%" G_GUINT64_FORMAT, id); + TRACE_MEDIA_MESSAGE("id=%d", id); appendPipeline->reportEndOfAppendDataMarkReceived(id); @@ -2378,8 +2378,8 @@ static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadP if (!gst_structure_has_name(structure, "end-of-append-data-mark")) return GST_PAD_PROBE_OK; - guint64 id = guint64(gst_event_get_seqnum(event)); - TRACE_MEDIA_MESSAGE("%s: custom downstream event id=%" G_GUINT64_FORMAT, padProbeInformation->m_description, id); + guint id = gst_event_get_seqnum(event); + TRACE_MEDIA_MESSAGE("%s: custom downstream event id=%d", padProbeInformation->m_description, id); return GST_PAD_PROBE_OK; } From f1186079bc33d8e3b5bd8f9cc67863ffc642f009 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Wed, 10 Feb 2016 13:48:57 +0100 Subject: [PATCH 13/14] [GStreamer][MSE] Reinstate data starve timeout In same rare cases, specially in test 30, where appends happen with not enough data, qtdemux stalls waiting for data and append never ends. This is a case that should happen very rarely so I reinstated the timeout to resolve that issue while we find and alternate and more robust solution. --- .../gstreamer/MediaPlayerPrivateGStreamerMSE.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index cc76e95caac38..5fb7acdd5ba98 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -88,7 +88,7 @@ class AppendPipeline : public ThreadSafeRefCounted { public: enum AppendStage { Invalid, NotStarted, Ongoing, KeyNegotiation, DataStarve, Sampling, LastSample, Aborting }; - static const unsigned int s_dataStarvedTimeoutMsec = 1000; + static const unsigned int s_dataStarvedTimeoutMsec = 2000; static const unsigned int s_lastSampleTimeoutMsec = 250; AppendPipeline(PassRefPtr mediaSourceClient, PassRefPtr sourceBufferPrivate, MediaPlayerPrivateGStreamerMSE* playerPrivate); @@ -1229,7 +1229,7 @@ static GstFlowReturn appendPipelineAppSinkNewSample(GstElement*, AppendPipeline* static gboolean appendPipelineAppSinkNewSampleMainThread(NewSampleInfo*); static void appendPipelineAppSinkEOS(GstElement*, AppendPipeline*); static gboolean appendPipelineAppSinkEOSMainThread(AppendPipeline* ap); -static gboolean appendPipelineDataStarveTimeout(gpointer); +static gboolean appendPipelineDataStarveTimeout(AppendPipeline*); static gboolean appendPipelineLastSampleTimeout(gpointer); static void appendPipelineElementMessageCallback(GstBus*, GstMessage* message, AppendPipeline* ap) @@ -1522,7 +1522,7 @@ gint AppendPipeline::id() void AppendPipeline::scheduleDataStarveTimer() { LOG_MEDIA_MESSAGE("Scheduling data starve timer"); - m_dataStarvedTimeoutTag = g_timeout_add(s_dataStarvedTimeoutMsec, appendPipelineDataStarveTimeout, this); + m_dataStarvedTimeoutTag = g_timeout_add(s_dataStarvedTimeoutMsec, GSourceFunc(appendPipelineDataStarveTimeout), this); } void AppendPipeline::cancelDataStarveTimer() @@ -2445,10 +2445,14 @@ static gboolean appendPipelineAppSinkEOSMainThread(AppendPipeline* ap) return G_SOURCE_REMOVE; } -static gboolean appendPipelineDataStarveTimeout(gpointer) +static gboolean appendPipelineDataStarveTimeout(AppendPipeline* appendPipeline) { - ERROR_MEDIA_MESSAGE("data starve timer fired"); - ASSERT_NOT_REACHED(); + AppendPipeline::AppendStage appendStage = appendPipeline->appendStage(); + INFO_MEDIA_MESSAGE("data starve timer fired, stage %s", dumpAppendStage(appendStage)); + if (appendStage == AppendPipeline::AppendStage::Ongoing) { + WARN_MEDIA_MESSAGE("setting DataStarve because of timeout"); + appendPipeline->setAppendStage(AppendPipeline::AppendStage::DataStarve); + } return G_SOURCE_REMOVE; } From dc98ea8eecd63e405d8d048f483e9430ba13e734 Mon Sep 17 00:00:00 2001 From: Xabier Rodriguez Calvar Date: Thu, 11 Feb 2016 11:32:59 +0100 Subject: [PATCH 14/14] [GStreamer][MSE] Correct typos and formats According to Phil's review. --- .../MediaPlayerPrivateGStreamerMSE.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp index 5fb7acdd5ba98..2c89c8f658111 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerMSE.cpp @@ -1477,7 +1477,7 @@ void AppendPipeline::handleEndOfAppendDataMarkReceived(const GstStructure* struc gst_structure_get(structure, "id", G_TYPE_UINT, &m_appendIdReceivedInSink, NULL); ASSERT(m_appendIdReceivedInSink); - TRACE_MEDIA_MESSAGE("received end of append id %d in the sink", m_appendIdReceivedInSink); + TRACE_MEDIA_MESSAGE("received end of append id %u in the sink", m_appendIdReceivedInSink); if (m_appendStage == Sampling || m_appendStage == Ongoing) checkEndOfAppendDataMarkReceived(); } @@ -2046,7 +2046,7 @@ void AppendPipeline::handleEndOfAppendDataMarkNeeded() m_appendIdMarkedInSrc = gst_event_get_seqnum(event); m_appendIdReceivedInSink = 0; - TRACE_MEDIA_MESSAGE("marking end of append with id %d", m_appendIdMarkedInSrc); + TRACE_MEDIA_MESSAGE("marking end of append with id %u", m_appendIdMarkedInSrc); gst_element_send_event(m_appsrc, event); @@ -2060,7 +2060,7 @@ void AppendPipeline::reportEndOfAppendDataMarkReceived(guint id) GstStructure* structure = gst_structure_new("end-of-append-data-mark-received", "id", G_TYPE_UINT, id, NULL); GstMessage* message = gst_message_new_application(GST_OBJECT(m_appsink), structure); gst_bus_post(m_bus.get(), message); - TRACE_MEDIA_MESSAGE("received message with id %d, re-posted to bus", id); + TRACE_MEDIA_MESSAGE("received message with id %u, re-posted to bus", id); } void AppendPipeline::reportEndOfAppendDataMarkNeeded() @@ -2226,7 +2226,7 @@ void AppendPipeline::connectToAppSink(GstPad* demuxerSrcPad) } // The previous mark has probably been lost because appsink was disconnected. Mark again. - TRACE_MEDIA_MESSAGE("previous append end mark lost, reinsterting"); + TRACE_MEDIA_MESSAGE("previous append end mark lost, reinjecting"); handleEndOfAppendDataMarkNeeded(); g_cond_signal(&m_padAddRemoveCondition); @@ -2298,7 +2298,7 @@ static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInf GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); gsize bufferSize = gst_buffer_get_size(buffer); - TRACE_MEDIA_MESSAGE("buffer of size %d going thru", bufferSize); + TRACE_MEDIA_MESSAGE("buffer of size %" G_GSIZE_FORMAT " going thru", bufferSize); if (bufferSize > 0) appendPipeline->reportEndOfAppendDataMarkNeeded(); @@ -2317,7 +2317,7 @@ static GstPadProbeReturn appendPipelineAppsrcDataLeaving(GstPad*, GstPadProbeInf return GST_PAD_PROBE_OK; guint id = gst_event_get_seqnum(event); - TRACE_MEDIA_MESSAGE("custom downstream event id=%d", id); + TRACE_MEDIA_MESSAGE("custom downstream event id=%u", id); return GST_PAD_PROBE_OK; } @@ -2340,7 +2340,7 @@ static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeI guint id = gst_event_get_seqnum(event); - TRACE_MEDIA_MESSAGE("id=%d", id); + TRACE_MEDIA_MESSAGE("id=%u", id); appendPipeline->reportEndOfAppendDataMarkReceived(id); @@ -2350,7 +2350,7 @@ static GstPadProbeReturn appendPipelineAppsinkDataEntering(GstPad*, GstPadProbeI #ifdef DEBUG_APPEND_PIPELINE_PADS if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) { GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); - TRACE_MEDIA_MESSAGE("buffer of size %d going thru", gst_buffer_get_size(buffer)); + TRACE_MEDIA_MESSAGE("buffer of size %" G_GSIZE_FORMAT " going thru", gst_buffer_get_size(buffer)); return GST_PAD_PROBE_OK; } #endif @@ -2365,7 +2365,7 @@ static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadP ASSERT(GST_PAD_PROBE_INFO_TYPE(info) != static_cast(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM)); if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) { GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); - TRACE_MEDIA_MESSAGE("%s: buffer of size %d going thru", padProbeInformation->m_description, gst_buffer_get_size(buffer)); + TRACE_MEDIA_MESSAGE("%s: buffer of size %" G_GSIZE_FORMAT " going thru", padProbeInformation->m_description, gst_buffer_get_size(buffer)); return GST_PAD_PROBE_OK; } @@ -2379,7 +2379,7 @@ static GstPadProbeReturn appendPipelinePadProbeDebugInformation(GstPad*, GstPadP return GST_PAD_PROBE_OK; guint id = gst_event_get_seqnum(event); - TRACE_MEDIA_MESSAGE("%s: custom downstream event id=%d", padProbeInformation->m_description, id); + TRACE_MEDIA_MESSAGE("%s: custom downstream event id=%u", padProbeInformation->m_description, id); return GST_PAD_PROBE_OK; }