xbmc/xbmc — pull request #3639 by jmbreuer (2013-11-13 08:05:12+00:00)
Title: Pause on video mode change while buffering

I noticed that the configured delay when changing refresh rates (or resolution) no longer works; i.e. XBMC would start playing back while the display (plasma TV) is not available due to its change delay. "No longer" as opposed to XBMC Frodo as included in OpenELEC maybe in Q1/2013.

Tracking this down I found this is due to the interaction of the delay processing in `CGraphicContext::SetVideoResolution()` with the behaviour of the video playback engine (always `CDVDPlayer` here):

Immediately when starting playback, `CDVDPlayer` will go to the "waiting for more data" state, i.e. `m_caching == CACHESTATE_FULL || m_caching == CACHESTATE_PVR` (see `CDVDPlayer::IsPaused()`); and this is the state it's in when `CGraphicContext::SetVideoResolution()` sets up the "after refresh change" pause.

With the code in current master `... && !g_application.m_pPlayer->IsPausedPlayback()`, this will simply not process the delay at all; causing the player to start playback as soon as enough data is available - typically this is a significantly shorter delay (< 1 second) then the refresh rate change delay required by my display (about 4.3 seconds).

I've extended `CGraphicContext::SetVideoResolution()` to also delay correctly when the player is waiting for data, i.e. `g_application.m_pPlayer->IsPausedPlayback()` is true.

Since the player API does not seem to expose an appropriate method to unambigiously go to "paused on user request, until unpause" from the "paused due to buffering, will resume as soon as data is available" state, I chose to call `Pause()` twice in that case, mimicking what the user also can do during buffering:

* Press pause the first time to force playback even while buffering
* Press pause again to go from playback to the "normal" user-requested pause state

This is what I regularly do manually for videos that take long to buffer up, to avoid playback starting while I'm out of the room getting a drink or something.

That's certainly a "solution" that someone with more knowledge of the inner workings should have a closer look at; e.g. I cannot be sure whether there's the possibility for a race condition in between the two `Pause()`s which would have the player end up in another state.

In my environment, this change makes the refresh rate change delay work perfectly, i.e.:
* the delay is always adhered to
* playback starts after the delay, it never stuck in pause

I'm open to suggestions how to improve this in the code.