summaryrefslogtreecommitdiff
path: root/libbanshee
diff options
context:
space:
mode:
authorChristopher James Halse Rogers <chrishr@src.gnome.org>2010-03-07 22:02:22 +1100
committerChristopher James Halse Rogers <chrishr@src.gnome.org>2010-03-07 22:02:22 +1100
commitaa52de225310563f0e0f1db2866c972993ff4997 (patch)
tree1b271cf920802fc69c39f365d0148115ca44e047 /libbanshee
parent48353efbfd9d77db7aed10c5217c639840a89c8c (diff)
[Gapless] Work around BGO #602437
Playbin2 currently behaves incorrectly when trying to transition gaplessly to or from a stream audio and video, resulting in the A/V sync being significantly out. Don't send about-to-finish when the current track has a video stream; instead let the track play out to EOS. If the new track has a video stream and we're in a gapless transition, drop back to READY and do a non-gapless transition
Diffstat (limited to 'libbanshee')
-rw-r--r--libbanshee/banshee-player-pipeline.c48
-rw-r--r--libbanshee/banshee-player-private.h1
-rw-r--r--libbanshee/banshee-player.c4
3 files changed, 49 insertions, 4 deletions
diff --git a/libbanshee/banshee-player-pipeline.c b/libbanshee/banshee-player-pipeline.c
index 5903ec9e1..b4664697b 100644
--- a/libbanshee/banshee-player-pipeline.c
+++ b/libbanshee/banshee-player-pipeline.c
@@ -38,6 +38,15 @@
// Private Functions
// ---------------------------------------------------------------------------
+static gboolean
+bp_stream_has_video (GstElement *playbin)
+{
+ int n_video;
+ g_object_get (G_OBJECT (playbin), "n-video", &n_video, NULL);
+ return n_video > 0;
+}
+
+
static void
bp_pipeline_process_tag (const GstTagList *tag_list, const gchar *tag_name, BansheePlayer *player)
{
@@ -59,13 +68,36 @@ bp_pipeline_process_tag (const GstTagList *tag_list, const gchar *tag_name, Bans
}
static gboolean
-bp_next_track_starting (gpointer player)
+bp_next_track_starting (BansheePlayer *player)
{
g_return_val_if_fail (IS_BANSHEE_PLAYER (player), FALSE);
+ g_return_val_if_fail (GST_IS_ELEMENT (player->playbin), FALSE);
- bp_debug ("[gapless] Triggering track-change signal");
- if (((BansheePlayer *)player)->next_track_starting_cb != NULL) {
- ((BansheePlayer *)player)->next_track_starting_cb (player);
+ // Work around BGO #602437 - gapless transition between tracks with
+ // video streams results in broken behaviour - most obviously, huge A/V
+ // sync issues.
+ gboolean has_video = bp_stream_has_video (player->playbin);
+ if (player->in_gapless_transition && has_video) {
+ gchar *uri;
+
+ bp_debug ("[Gapless]: Aborting gapless transition to stream with video.");
+ bp_debug ("[Gapless]: Triggering normal track change.");
+ g_object_get (G_OBJECT (player->playbin), "uri", &uri, NULL);
+ gst_element_set_state (player->playbin, GST_STATE_READY);
+
+ g_object_set (G_OBJECT (player->playbin), "uri", uri, NULL);
+ gst_element_set_state (player->playbin, GST_STATE_PLAYING);
+ g_free (uri);
+ player->in_gapless_transition = FALSE;
+ // The transition to playing will happen asynchronously, and will trigger
+ // a second track-starting message. Stop processing this one.
+ return FALSE;
+ }
+ player->in_gapless_transition = FALSE;
+
+ if (player->next_track_starting_cb != NULL) {
+ bp_debug ("[gapless] Triggering track-change signal");
+ player->next_track_starting_cb (player);
}
return FALSE;
}
@@ -187,8 +219,16 @@ bp_pipeline_bus_callback (GstBus *bus, GstMessage *message, gpointer userdata)
static void bp_about_to_finish_callback (GstElement *playbin, BansheePlayer *player)
{
g_return_if_fail (IS_BANSHEE_PLAYER (player));
+ g_return_if_fail (GST_IS_ELEMENT (playbin));
+
+ if (bp_stream_has_video (playbin)) {
+ bp_debug ("[Gapless]: Not attempting gapless transition from stream with video");
+ return;
+ }
if (player->about_to_finish_cb != NULL) {
+ player->in_gapless_transition = TRUE;
+
bp_debug ("[Gapless] Requesting next track");
player->about_to_finish_cb (player);
}
diff --git a/libbanshee/banshee-player-private.h b/libbanshee/banshee-player-private.h
index 20a2d1ca6..1edd37566 100644
--- a/libbanshee/banshee-player-private.h
+++ b/libbanshee/banshee-player-private.h
@@ -121,6 +121,7 @@ struct BansheePlayer {
guint iterate_timeout_id;
gboolean buffering;
gchar *cdda_device;
+ gboolean in_gapless_transition;
// Video State
BpVideoDisplayContextType video_display_context_type;
diff --git a/libbanshee/banshee-player.c b/libbanshee/banshee-player.c
index 157494d98..fe47eb536 100644
--- a/libbanshee/banshee-player.c
+++ b/libbanshee/banshee-player.c
@@ -163,6 +163,8 @@ bp_open (BansheePlayer *player, const gchar *uri)
// Pass the request off to playbin
g_object_set (G_OBJECT (player->playbin), "uri", uri, NULL);
+ player->in_gapless_transition = FALSE;
+
return TRUE;
}
@@ -181,6 +183,8 @@ bp_stop (BansheePlayer *player, gboolean nullstate)
bp_debug ("bp_stop: setting state to %s",
state == GST_STATE_NULL ? "GST_STATE_NULL" : "GST_STATE_PAUSED");
+ player->in_gapless_transition = FALSE;
+
bp_pipeline_set_state (player, state);
}