diff options
author | Christopher James Halse Rogers <chrishr@src.gnome.org> | 2010-03-07 22:02:22 +1100 |
---|---|---|
committer | Christopher James Halse Rogers <chrishr@src.gnome.org> | 2010-03-07 22:02:22 +1100 |
commit | aa52de225310563f0e0f1db2866c972993ff4997 (patch) | |
tree | 1b271cf920802fc69c39f365d0148115ca44e047 /libbanshee | |
parent | 48353efbfd9d77db7aed10c5217c639840a89c8c (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.c | 48 | ||||
-rw-r--r-- | libbanshee/banshee-player-private.h | 1 | ||||
-rw-r--r-- | libbanshee/banshee-player.c | 4 |
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); } |