warren-bank/Android-RTSP-IPCam-Viewer

when the stream is interrupted, the client wont auto reconnect

orangpelupa opened this issue · 5 comments

reproduction:

  1. start an RTSP stream, play the stream on the android app
  2. stop the stream, the stream on android app will be frozen on the last frame.
  3. start the stream, the stream on anroid app did not auto reconnect.

need to close the view (pressing back) and opening the view again on the app to reconnect the stream.

Hi. I just updated ExoPlayer to r2.16.0 ..which is the most recent stable release. RTSP is now officially supported.. so the experimental dependency is no-longer needed.

Regarding your issue..

  • the logic to handle how many times to attempt a retry.. how much time to wait between each attempt.. etc, would normally be handled by an implementation of the LoadErrorHandlingPolicy interface.. which would typically be based on the DefaultLoadErrorHandlingPolicy class
  • implementations of MediaSourceFactory have a setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) method to accept such a policy
  • RtspMediaSource.Factory does not yet support this feature.. and the method to accept this policy doesn't actually do anything
    • when ExoPlayer does add support to RtspMediaSource for using a LoadErrorHandlingPolicy.. I'll be sure to add one

what I just said about LoadErrorHandlingPolicy applies to adding the ability for each instance of ExoPlayer to automatically resume playback..

however, (thinking out loud atm).. there's no reason I couldn't add some logic that could be manually triggered by the user. For example:

  • in low-res list or grid layout, a long-press currently toggles between pause/resume..
    • when the video is to resume, I could detect playback state and retry (if needed)
  • in high-res full-screen layout, the visible controls overlay includes a button to toggle between pause/resume..
    • the same behavior could be added

note to self..

attempted the following sledge-hammer approach.. by retrying any instance of ExoPlayer after a 5-second delay anytime there is any error; it still didn't resume video playback after network connectivity is lost and then subsequently re-established (ie: while in airplane mode, toggle wifi off and then back on):

package com.github.warren_bank.rtsp_ipcam_viewer.common.exoplayer2;

import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;

import android.os.Handler;
import android.os.Looper;

public final class PlayerErrorListener implements Player.Listener {
  private static int RETRY_DELAY_MS = 5000;

  private ExoPlayer player;
  private boolean   pending;
  private Handler   handler;
  private Runnable  runnable;

  public PlayerErrorListener(ExoPlayer player) {
    this.player   = player;
    this.pending  = false;
    this.handler  = new Handler(Looper.getMainLooper());
    this.runnable = new Runnable() {
      @Override
      public void run() {
        pending = false;

        try {
          player.setPlayWhenReady(false);
          player.seekToDefaultPosition(0);
          player.retry();
          player.setPlayWhenReady(true);
        }
        catch(Exception e) {}
      }
    };
  }

  @Override
  public void onPlayerError(PlaybackException error) {
    if (!pending && player.getPlayWhenReady() && (player.getMediaItemCount() > 0)) {
      pending = true;
      handler.postDelayed(runnable, RETRY_DELAY_MS);
    }
  }
}

public final class ExoPlayerUtils {
  //...
  public static ExoPlayer initializeExoPlayer(Context context) {
    context = context.getApplicationContext();

    if (USER_AGENT == null)
      setUserAgent(context);

    ExoPlayer player = new ExoPlayer.Builder(
      context,
      getRenderersFactory(context),
      getMediaSourceFactory(context),
      getTrackSelector(context),
      getLoadControl(),
      getBandwidthMeter(context),
      getAnalyticsCollector()
    ).build();

    player.addListener(
      new PlayerErrorListener(player)
    );

    return player;
  }
}

Based on the above observations.. we're definitely going to need to wait until the RTSP library is made more robust.. with code to support fixing broken streams. My understanding of RTSP is that the protocol has a ton of handshaking.. it's not stateless.. so it's not as simple as resending a failed request.

cross-reference to related exoplayer issue