warren-bank / Android-RTSP-IPCam-Viewer

Android app to view RTSP and RTMP IP camera video streams.
GNU General Public License v2.0
77 stars 11 forks source link

when the stream is interrupted, the client wont auto reconnect #6

Open orangpelupa opened 2 years ago

orangpelupa commented 2 years ago

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.

warren-bank commented 2 years ago

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..

warren-bank commented 2 years ago

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:

warren-bank commented 2 years ago

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;
  }
}
warren-bank commented 2 years ago

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.

warren-bank commented 2 years ago

cross-reference to related exoplayer issue