Re: [spice v13 10/29] server: Handle and recover from GStreamer encoding errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 4 May 2016, Christophe Fergeau wrote:

> On Wed, May 04, 2016 at 12:03:57PM +0200, Christophe Fergeau wrote:
> > Ugh that's bad :( Using gst_message_new_request_state() might avoid
> > this, but while the GstAppSink element is blocked waiting for data, I
> > don't know if state changes are going to be handled (ie I'm not sure
> > about GStreamer threading model and which thread the state change is
> > going to come from). I can try asking on #gstreamer if needed.
> 
> Looking at the code, GST_MESSAGE_REQUEST_STATE_CHANGE does not seem to
> be used within GStreamer. GstBin looks at EOS message though from the
> thread GstBus runs in (I think), and GstAppSink also handles this
> message, so maybe we could use EOS to recover from errors?

I tried sending an EOS from handle_pipeline_message() but it does 
not work.

Sending the EOS seems to work but then I get the following messages and 
pull_buffer/pull_sample() never returns:

(Xorg:19764): Spice-WARNING **: gstreamer-encoder.c:809:handle_pipeline_message: GStreamer error from element encoder: Can not initialize x264 encoder.
gstreamer-encoder.c:809:handle_pipeline_message: GStreamer error from element encoder: Can not initialize x264 encoder.
gstreamer-encoder.c:811:handle_pipeline_message: debug details: gstx264enc.c(1269): gst_x264_enc_init_encoder (): /GstPipeline:pipeline3/GstX264Enc:encoder
[...]
(Xorg:19764): Spice-WARNING **: gstreamer-encoder.c:809:handle_pipeline_message: GStreamer error from element src: Internal data flow error.
gstreamer-encoder.c:809:handle_pipeline_message: GStreamer error from element src: Internal data flow error.
gstreamer-encoder.c:811:handle_pipeline_message: debug details: gstbasesrc.c(2625): gst_base_src_loop (): /GstPipeline:pipeline3/GstAppSrc:src:
streaming task paused, reason not-negotiated (-4)
[...]
0:00:00.736257174 19764 0x7f64807fd540 DEBUG               basesink gstbasesink.c:2277:gst_base_sink_wait_preroll:<sink> waiting in preroll for flush or PLAYING

(full log at http://fgouget.free.fr/tmp/Xspice-eos.log.xz)


My understanding is that x264enc did not like the first frame, so the 
pipeline remained in preroll, a state in which an EOS cannot be sent.

I also tried variants like sending a gst_event_new_flush_stop() event 
but the send operation failed altogether (and had no effect obviously).

See the attachment for reference.


-- 
Francois Gouget <fgouget@xxxxxxxxxxxxxxx>
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index c61afea..ba83ead 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -215,6 +215,32 @@ static void set_appsrc_caps(SpiceGstEncoder *encoder)
     gst_app_src_set_caps(encoder->appsrc, encoder->src_caps);
 }
 
+static GstBusSyncReply handle_pipeline_message(GstBus *bus, GstMessage *msg, gpointer video_encoder)
+{
+    SpiceGstEncoder *encoder = video_encoder;
+
+    if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
+        GError *err = NULL;
+        gchar *debug_info;
+        gst_message_parse_error(msg, &err, &debug_info);
+        spice_warning("GStreamer error from element %s: %s",
+                      GST_OBJECT_NAME(msg->src), err->message);
+        if (debug_info) {
+            spice_debug("debug details: %s", debug_info);
+            g_free(debug_info);
+        }
+        g_clear_error(&err);
+
+        /* Unblock the main thread which may be stuck calling gst_app_sink_pull_sample() */
+        spice_debug("sending event");
+        gboolean success = gst_element_send_event(GST_ELEMENT(encoder->pipeline), gst_event_new_eos());
+        //gboolean success = gst_element_send_event(GST_ELEMENT(encoder->pipeline), gst_event_new_flush_stop());
+        //gboolean success = gst_element_send_event(GST_ELEMENT(encoder->pipeline), gst_event_new_seek(1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 0));
+        spice_debug("event sent: %d", success);
+    }
+    return GST_BUS_PASS;
+}
+
 static int physical_core_count = 0;
 static int get_physical_core_count(void)
 {
@@ -294,6 +320,15 @@ static gboolean create_pipeline(SpiceGstEncoder *encoder)
     encoder->gstenc = gst_bin_get_by_name(GST_BIN(encoder->pipeline), "encoder");
     encoder->appsink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(encoder->pipeline), "sink"));
 
+    /* Hook into the bus so we can handle errors */
+    GstBus *bus = gst_element_get_bus(encoder->pipeline);
+#ifdef HAVE_GSTREAMER_0_10
+    gst_bus_set_sync_handler(bus, handle_pipeline_message, encoder);
+#else
+    gst_bus_set_sync_handler(bus, handle_pipeline_message, encoder, NULL);
+#endif
+    gst_object_unref(bus);
+
     if (encoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG) {
         /* See https://bugzilla.gnome.org/show_bug.cgi?id=753257 */
         spice_debug("removing the pipeline clock");
@@ -340,6 +375,7 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder)
         return TRUE;
     }
 
+    spice_debug("start...");
     /* If the pipeline state does not need to be changed it's because it is
      * already in the PLAYING state. So first set it to the NULL state so it
      * can be (re)configured.
@@ -368,6 +404,7 @@ static gboolean configure_pipeline(SpiceGstEncoder *encoder)
         return FALSE;
     }
 
+    spice_debug("done");
     encoder->set_pipeline = 0;
     return TRUE;
 }
@@ -562,7 +599,9 @@ static int spice_gst_encoder_encode_frame(VideoEncoder *video_encoder,
 
     int rc = push_raw_frame(encoder, bitmap, src, top_down);
     if (rc == VIDEO_ENCODER_FRAME_ENCODE_DONE) {
+        spice_debug("calling pull_compressed_buffer");
         rc = pull_compressed_buffer(encoder, outbuf);
+        spice_debug("pull_compressed_buffer returned %d", rc);
         if (rc != VIDEO_ENCODER_FRAME_ENCODE_DONE) {
             /* The input buffer will be stuck in the pipeline, preventing
              * later ones from being processed. Furthermore something went
_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]