Bug 882567 - Handle fatal gstreamer errors by aborting playback r=alessandro.d
☠☠ backed out by 822b350df442 ☠ ☠
authorEdwin Flores <eflores@mozilla.com>
Wed, 19 Jun 2013 10:22:29 +1200
changeset 147020 9173dcf026eeea673ee03428702a3f52e4d1c17d
parent 147019 398e348e3ed885a0ee2d6a42d33d46d81d86fd6d
child 147021 a73bc11da47154d10a70f9efc7320d02231f07e7
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersalessandro
bugs882567
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 882567 - Handle fatal gstreamer errors by aborting playback r=alessandro.d
content/media/gstreamer/GStreamerFunctionList.h
content/media/gstreamer/GStreamerReader.cpp
content/media/gstreamer/GStreamerReader.h
--- a/content/media/gstreamer/GStreamerFunctionList.h
+++ b/content/media/gstreamer/GStreamerFunctionList.h
@@ -21,16 +21,17 @@ GST_FUNC(LIBGSTAPP, gst_app_src_set_size
 GST_FUNC(LIBGSTAPP, gst_app_src_set_stream_type)
 GST_FUNC(LIBGSTREAMER, gst_bin_get_by_name)
 GST_FUNC(LIBGSTREAMER, gst_bin_get_type)
 GST_FUNC(LIBGSTREAMER, gst_bin_iterate_recurse)
 GST_FUNC(LIBGSTREAMER, gst_buffer_copy_metadata)
 GST_FUNC(LIBGSTREAMER, gst_buffer_get_type)
 GST_FUNC(LIBGSTREAMER, gst_buffer_new)
 GST_FUNC(LIBGSTREAMER, gst_buffer_new_and_alloc)
+GST_FUNC(LIBGSTREAMER, gst_bus_set_sync_handler)
 GST_FUNC(LIBGSTREAMER, gst_bus_timed_pop_filtered)
 GST_FUNC(LIBGSTREAMER, gst_caps_append)
 GST_FUNC(LIBGSTREAMER, gst_caps_can_intersect)
 GST_FUNC(LIBGSTREAMER, gst_caps_from_string)
 GST_FUNC(LIBGSTREAMER, gst_caps_get_size)
 GST_FUNC(LIBGSTREAMER, gst_caps_get_structure)
 GST_FUNC(LIBGSTREAMER, gst_caps_new_any)
 GST_FUNC(LIBGSTREAMER, gst_caps_new_empty)
@@ -49,16 +50,17 @@ GST_FUNC(LIBGSTREAMER, gst_element_query
 GST_FUNC(LIBGSTREAMER, gst_element_seek_simple)
 GST_FUNC(LIBGSTREAMER, gst_element_set_state)
 GST_FUNC(LIBGSTREAMER, gst_event_parse_new_segment)
 GST_FUNC(LIBGSTREAMER, gst_flow_get_name)
 GST_FUNC(LIBGSTREAMER, gst_init)
 GST_FUNC(LIBGSTREAMER, gst_init_check)
 GST_FUNC(LIBGSTREAMER, gst_iterator_next)
 GST_FUNC(LIBGSTREAMER, gst_message_parse_error)
+GST_FUNC(LIBGSTREAMER, gst_message_type_get_name)
 GST_FUNC(LIBGSTREAMER, gst_mini_object_get_type)
 GST_FUNC(LIBGSTREAMER, gst_mini_object_new)
 GST_FUNC(LIBGSTREAMER, gst_mini_object_ref)
 GST_FUNC(LIBGSTREAMER, gst_mini_object_unref)
 GST_FUNC(LIBGSTREAMER, gst_object_get_parent)
 GST_FUNC(LIBGSTREAMER, gst_object_unref)
 GST_FUNC(LIBGSTREAMER, gst_pad_add_event_probe)
 GST_FUNC(LIBGSTREAMER, gst_pad_alloc_buffer)
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -173,16 +173,32 @@ nsresult GStreamerReader::Init(MediaDeco
                nullptr);
 
   g_signal_connect(G_OBJECT(mPlayBin), "notify::source",
                    G_CALLBACK(GStreamerReader::PlayBinSourceSetupCb), this);
 
   return NS_OK;
 }
 
+GstBusSyncReply
+GStreamerReader::ErrorCb(GstBus *aBus, GstMessage *aMessage, gpointer aUserData)
+{
+  return static_cast<GStreamerReader*>(aUserData)->Error(aBus, aMessage);
+}
+
+GstBusSyncReply
+GStreamerReader::Error(GstBus *aBus, GstMessage *aMessage)
+{
+  if (GST_MESSAGE_TYPE(aMessage) == GST_MESSAGE_ERROR) {
+    Eos();
+  }
+
+  return GST_BUS_PASS;
+}
+
 void GStreamerReader::PlayBinSourceSetupCb(GstElement* aPlayBin,
                                            GParamSpec* pspec,
                                            gpointer aUserData)
 {
   GstElement *source;
   GStreamerReader* reader = reinterpret_cast<GStreamerReader*>(aUserData);
 
   g_object_get(aPlayBin, "source", &source, NULL);
@@ -342,16 +358,19 @@ nsresult GStreamerReader::ReadMetadata(V
   g_object_get(mPlayBin, "n-video", &n_video, "n-audio", &n_audio, nullptr);
   mInfo.mHasVideo = n_video != 0;
   mInfo.mHasAudio = n_audio != 0;
 
   *aInfo = mInfo;
 
   *aTags = nullptr;
 
+  // Watch the pipeline for fatal errors
+  gst_bus_set_sync_handler(mBus, GStreamerReader::ErrorCb, this);
+
   /* set the pipeline to PLAYING so that it starts decoding and queueing data in
    * the appsinks */
   gst_element_set_state(mPlayBin, GST_STATE_PLAYING);
 
   return NS_OK;
 }
 
 nsresult GStreamerReader::CheckSupportedFormats()
@@ -999,20 +1018,20 @@ void GStreamerReader::NewAudioBuffer()
    */
   mAudioSinkBufferCount++;
   mon.NotifyAll();
 }
 
 void GStreamerReader::EosCb(GstAppSink* aSink, gpointer aUserData)
 {
   GStreamerReader* reader = reinterpret_cast<GStreamerReader*>(aUserData);
-  reader->Eos(aSink);
+  reader->Eos();
 }
 
-void GStreamerReader::Eos(GstAppSink* aSink)
+void GStreamerReader::Eos()
 {
   /* We reached the end of the stream */
   {
     ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
     /* Potentially unblock DecodeVideoFrame and DecodeAudioData */
     mReachedEos = true;
     mon.NotifyAll();
   }
--- a/content/media/gstreamer/GStreamerReader.h
+++ b/content/media/gstreamer/GStreamerReader.h
@@ -59,16 +59,19 @@ private:
 
   /* Called once the pipeline is setup to check that the stream only contains
    * supported formats
    */
   nsresult CheckSupportedFormats();
 
   /* Gst callbacks */
 
+  static GstBusSyncReply ErrorCb(GstBus *aBus, GstMessage *aMessage, gpointer aUserData);
+  GstBusSyncReply Error(GstBus *aBus, GstMessage *aMessage);
+
   /* Called on the source-setup signal emitted by playbin. Used to
    * configure appsrc .
    */
   static void PlayBinSourceSetupCb(GstElement* aPlayBin,
                                    GParamSpec* pspec,
                                    gpointer aUserData);
   void PlayBinSourceSetup(GstAppSrc* aSource);
 
@@ -111,17 +114,17 @@ private:
 
   /* Called when buffers reach the sinks */
   static GstFlowReturn NewBufferCb(GstAppSink* aSink, gpointer aUserData);
   void NewVideoBuffer();
   void NewAudioBuffer();
 
   /* Called at end of stream, when decoding has finished */
   static void EosCb(GstAppSink* aSink, gpointer aUserData);
-  void Eos(GstAppSink* aSink);
+  void Eos();
 
   GstElement* mPlayBin;
   GstBus* mBus;
   GstAppSrc* mSource;
   /* video sink bin */
   GstElement* mVideoSink;
   /* the actual video app sink */
   GstAppSink* mVideoAppSink;