[gstreamer1-plugins-base] Add upstream fix for excessive alsasink CPU usage

Daniel Drake dsd at fedoraproject.org
Thu Jan 24 19:26:56 UTC 2013


commit 90cbd03f3273b9ed088e80a29db0eb8e276a30bd
Author: Daniel Drake <dsd at laptop.org>
Date:   Thu Jan 24 13:25:18 2013 -0600

    Add upstream fix for excessive alsasink CPU usage

 alsa-delay-lock.patch        |   91 ++++++++++++++++++++++++++++++++++++++++++
 gstreamer1-plugins-base.spec |    7 +++-
 2 files changed, 97 insertions(+), 1 deletions(-)
---
diff --git a/alsa-delay-lock.patch b/alsa-delay-lock.patch
new file mode 100644
index 0000000..f378414
--- /dev/null
+++ b/alsa-delay-lock.patch
@@ -0,0 +1,91 @@
+From 67a7b5a99317ca1f92fb6a88542647aa3ad92c4b Mon Sep 17 00:00:00 2001
+From: yanghuolin <Huolin.Yang at delphi.com>
+Date: Thu, 15 Nov 2012 08:31:47 +0000
+Subject: alsasink: don't use 100% CPU
+
+The root cause is that alsa-lib is not thread safe for the same handle.
+There are two threads in the gstreamer accessing alsa-lib not serilized.
+The race condition happens when one thread holds the old framebuffer app_ptr
+position in the kernel, another thread advances the framebuffer app_ptr.
+when the former thread is scheduled to run again, it overwrites the app_ptr
+to old value by copying from kernel.Thus,the app_ptr in the upper
+alsa-lib(pcm_rate) become one period size more advanced than the lower
+alsa-lib(pcm_hw & kernel).
+
+gstreamer uses noblock and poll method to communicate with the alsa-lib.
+The app_ptr unsync situation as described above makes the poll return immediately because
+it concludes there is enough space for the ring-buffer via the low-level alsa-lib.
+The write function returns immediately because it concludes there is not enough
+space for the ring-buffer from the upper-level alsa-lib. Then the loop of poll
+and write runs again and again until another period size is available for
+ring-buffer.This leads to the cpu 100 problem.
+
+delay_lock  is used to avoid the race condition.
+
+Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=690937
+---
+diff --git a/ext/alsa/gstalsasink.c b/ext/alsa/gstalsasink.c
+index 1ef6b91..81731b6 100644
+--- a/ext/alsa/gstalsasink.c
++++ b/ext/alsa/gstalsasink.c
+@@ -118,6 +118,7 @@ gst_alsasink_finalise (GObject * object)
+ 
+   g_free (sink->device);
+   g_mutex_clear (&sink->alsa_lock);
++  g_mutex_clear (&sink->delay_lock);
+ 
+   g_mutex_lock (&output_mutex);
+   --output_ref;
+@@ -255,6 +256,7 @@ gst_alsasink_init (GstAlsaSink * alsasink)
+   alsasink->handle = NULL;
+   alsasink->cached_caps = NULL;
+   g_mutex_init (&alsasink->alsa_lock);
++  g_mutex_init (&alsasink->delay_lock);
+ 
+   g_mutex_lock (&output_mutex);
+   if (output_ref == 0) {
+@@ -1011,7 +1013,9 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
+     if (err < 0) {
+       GST_DEBUG_OBJECT (asink, "wait error, %d", err);
+     } else {
++      GST_DELAY_SINK_LOCK (asink);
+       err = snd_pcm_writei (alsa->handle, ptr, cptr);
++      GST_DELAY_SINK_UNLOCK (asink);
+     }
+ 
+     GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
+@@ -1057,7 +1061,9 @@ gst_alsasink_delay (GstAudioSink * asink)
+ 
+   alsa = GST_ALSA_SINK (asink);
+ 
++  GST_DELAY_SINK_LOCK (asink);
+   res = snd_pcm_delay (alsa->handle, &delay);
++  GST_DELAY_SINK_UNLOCK (asink);
+   if (G_UNLIKELY (res < 0)) {
+     /* on errors, report 0 delay */
+     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
+diff --git a/ext/alsa/gstalsasink.h b/ext/alsa/gstalsasink.h
+index 3a64a92..8c4c1b0 100644
+--- a/ext/alsa/gstalsasink.h
++++ b/ext/alsa/gstalsasink.h
+@@ -43,6 +43,10 @@ typedef struct _GstAlsaSinkClass GstAlsaSinkClass;
+ #define GST_ALSA_SINK_LOCK(obj)	    (g_mutex_lock (GST_ALSA_SINK_GET_LOCK (obj)))
+ #define GST_ALSA_SINK_UNLOCK(obj)   (g_mutex_unlock (GST_ALSA_SINK_GET_LOCK (obj)))
+ 
++#define GST_DELAY_SINK_GET_LOCK(obj)	(&GST_ALSA_SINK_CAST (obj)->delay_lock)
++#define GST_DELAY_SINK_LOCK(obj)	        (g_mutex_lock (GST_DELAY_SINK_GET_LOCK (obj)))
++#define GST_DELAY_SINK_UNLOCK(obj)	(g_mutex_unlock (GST_DELAY_SINK_GET_LOCK (obj)))
++
+ /**
+  * GstAlsaSink:
+  *
+@@ -73,6 +77,7 @@ struct _GstAlsaSink {
+   GstCaps *cached_caps;
+ 
+   GMutex alsa_lock;
++  GMutex delay_lock;
+ };
+ 
+ struct _GstAlsaSinkClass {
+--
+cgit v0.9.0.2-2-gbebe
diff --git a/gstreamer1-plugins-base.spec b/gstreamer1-plugins-base.spec
index 78d914e..e11a432 100644
--- a/gstreamer1-plugins-base.spec
+++ b/gstreamer1-plugins-base.spec
@@ -2,13 +2,14 @@
 
 Name:           gstreamer1-plugins-base
 Version:        1.0.5
-Release:        2%{?dist}
+Release:        3%{?dist}
 Summary:        GStreamer streaming media framework base plugins
 
 License:        LGPLv2+
 URL:            http://gstreamer.freedesktop.org/
 Source0:        http://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-%{version}.tar.xz
 Patch0:         0001-missing-plugins-Remove-the-mpegaudioversion-field.patch
+Patch1:         alsa-delay-lock.patch
 
 BuildRequires:  gstreamer1-devel >= %{version}
 BuildRequires:  gobject-introspection-devel >= 1.31.1
@@ -89,6 +90,7 @@ for the GStreamer Base Plugins library.
 %prep
 %setup -q -n gst-plugins-base-%{version}
 %patch0 -p1
+%patch1 -p1
 
 
 %build
@@ -333,6 +335,9 @@ chrpath --delete $RPM_BUILD_ROOT%{_bindir}/gst-discoverer-1.0
 
 
 %changelog
+* Thu Jan 24 2013 Daniel Drake <dsd at laptop.org> - 1.0.5-3
+- Add upstream fix for excessive alsasink CPU usage
+
 * Fri Jan 18 2013 Brian Pepple <bpepple at fedoraproject.org> - 1.0.5-2
 - Add patch to fix missing mp3 codec discovery. (#680809, #896018)
 


More information about the scm-commits mailing list