resindvd: Fix raciness in rsndvdbin when initially creating pads

Protect pad exposure with a preroll lock to avoid situations
where no-more-pads is fired more than once, or fired just before
the last pad is actually added.
This commit is contained in:
Jan Schmidt 2009-05-13 10:29:36 +01:00
parent b20a88702d
commit b769f22404
2 changed files with 17 additions and 12 deletions

View file

@ -44,6 +44,9 @@ GST_DEBUG_CATEGORY_EXTERN (resindvd_debug);
#define DVDBIN_LOCK(d) g_mutex_lock((d)->dvd_lock) #define DVDBIN_LOCK(d) g_mutex_lock((d)->dvd_lock)
#define DVDBIN_UNLOCK(d) g_mutex_unlock((d)->dvd_lock) #define DVDBIN_UNLOCK(d) g_mutex_unlock((d)->dvd_lock)
#define DVDBIN_PREROLL_LOCK(d) g_mutex_lock((d)->preroll_lock)
#define DVDBIN_PREROLL_UNLOCK(d) g_mutex_unlock((d)->preroll_lock)
#define DEFAULT_DEVICE "/dev/dvd" #define DEFAULT_DEVICE "/dev/dvd"
enum enum
{ {
@ -159,6 +162,7 @@ static void
rsn_dvdbin_init (RsnDvdBin * dvdbin, RsnDvdBinClass * gclass) rsn_dvdbin_init (RsnDvdBin * dvdbin, RsnDvdBinClass * gclass)
{ {
dvdbin->dvd_lock = g_mutex_new (); dvdbin->dvd_lock = g_mutex_new ();
dvdbin->preroll_lock = g_mutex_new ();
} }
static void static void
@ -167,6 +171,7 @@ rsn_dvdbin_finalize (GObject * object)
RsnDvdBin *dvdbin = RESINDVDBIN (object); RsnDvdBin *dvdbin = RESINDVDBIN (object);
g_mutex_free (dvdbin->dvd_lock); g_mutex_free (dvdbin->dvd_lock);
g_mutex_free (dvdbin->preroll_lock);
g_free (dvdbin->last_uri); g_free (dvdbin->last_uri);
g_free (dvdbin->device); g_free (dvdbin->device);
@ -741,58 +746,57 @@ failed:
static void static void
dvdbin_pad_blocked_cb (GstPad * pad, gboolean blocked, RsnDvdBin * dvdbin) dvdbin_pad_blocked_cb (GstPad * pad, gboolean blocked, RsnDvdBin * dvdbin)
{ {
gboolean changed = FALSE; gboolean added_last_pad = FALSE;
gboolean added = FALSE; gboolean added = FALSE;
if (!blocked) if (!blocked)
return; return;
if (pad == dvdbin->subpicture_pad) { if (pad == dvdbin->subpicture_pad) {
GST_DEBUG_OBJECT (dvdbin, "Pad block -> subpicture pad"); GST_DEBUG_OBJECT (dvdbin, "Pad block -> subpicture pad");
GST_OBJECT_LOCK (dvdbin); DVDBIN_PREROLL_LOCK (dvdbin);
added = dvdbin->subpicture_added; added = dvdbin->subpicture_added;
dvdbin->subpicture_added = TRUE; dvdbin->subpicture_added = TRUE;
GST_OBJECT_UNLOCK (dvdbin);
if (!added) { if (!added) {
gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->subpicture_pad); gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->subpicture_pad);
changed = TRUE; added_last_pad = (dvdbin->audio_added && dvdbin->video_added);
} }
DVDBIN_PREROLL_UNLOCK (dvdbin);
gst_pad_set_blocked_async (pad, FALSE, gst_pad_set_blocked_async (pad, FALSE,
(GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin);
} else if (pad == dvdbin->audio_pad) { } else if (pad == dvdbin->audio_pad) {
GST_DEBUG_OBJECT (dvdbin, "Pad block -> audio pad"); GST_DEBUG_OBJECT (dvdbin, "Pad block -> audio pad");
GST_OBJECT_LOCK (dvdbin); DVDBIN_PREROLL_LOCK (dvdbin);
added = dvdbin->audio_added; added = dvdbin->audio_added;
dvdbin->audio_added = TRUE; dvdbin->audio_added = TRUE;
GST_OBJECT_UNLOCK (dvdbin);
if (!added) { if (!added) {
gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->audio_pad); gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->audio_pad);
changed = TRUE; added_last_pad = (dvdbin->subpicture_added && dvdbin->video_added);
} }
DVDBIN_PREROLL_UNLOCK (dvdbin);
gst_pad_set_blocked_async (pad, FALSE, gst_pad_set_blocked_async (pad, FALSE,
(GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin);
} else if (pad == dvdbin->video_pad) { } else if (pad == dvdbin->video_pad) {
GST_DEBUG_OBJECT (dvdbin, "Pad block -> video pad"); GST_DEBUG_OBJECT (dvdbin, "Pad block -> video pad");
GST_OBJECT_LOCK (dvdbin); DVDBIN_PREROLL_LOCK (dvdbin);
added = dvdbin->video_added; added = dvdbin->video_added;
dvdbin->video_added = TRUE; dvdbin->video_added = TRUE;
GST_OBJECT_UNLOCK (dvdbin);
if (!added) { if (!added) {
gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->video_pad); gst_element_add_pad (GST_ELEMENT (dvdbin), dvdbin->video_pad);
changed = TRUE; added_last_pad = (dvdbin->subpicture_added && dvdbin->audio_added);
} }
DVDBIN_PREROLL_UNLOCK (dvdbin);
gst_pad_set_blocked_async (pad, FALSE, gst_pad_set_blocked_async (pad, FALSE,
(GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin); (GstPadBlockCallback) dvdbin_pad_blocked_cb, dvdbin);
} }
if (changed && if (added_last_pad) {
dvdbin->video_added && dvdbin->audio_added && dvdbin->subpicture_added) {
GST_DEBUG_OBJECT (dvdbin, "Firing no more pads from pad-blocked cb"); GST_DEBUG_OBJECT (dvdbin, "Firing no more pads from pad-blocked cb");
gst_element_no_more_pads (GST_ELEMENT (dvdbin)); gst_element_no_more_pads (GST_ELEMENT (dvdbin));
} }

View file

@ -58,6 +58,7 @@ struct _RsnDvdBin
/* Protects pieces list and properties */ /* Protects pieces list and properties */
GMutex *dvd_lock; GMutex *dvd_lock;
GMutex *preroll_lock;
gchar *device; gchar *device;
gchar *last_uri; gchar *last_uri;