bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.39k stars 1.56k forks source link

RTSP stream stops after 30 secods when using TCP #2218

Open nickgitnick opened 2 months ago

nickgitnick commented 2 months ago

I am streaming video over RTSP using FFmpegFrameGrabber. If I do not specify UDP vs TCP it seems that the connection is stable and but I sometimes see artifiacts and distortion in the image I am receiving from the camera. However, if I specify TCP as the rtsp_transport, the image is much better with no artifacts. However, after about 30 seconds, when I call Frame.grabImage(), it returns null. At this point, I can call FFmpegFrameGrabber.stop(), followed by FFmpegFrameGrabber.start(), and the streaming of frames will continue for another 30 seconds.

I see the same behavior using ffplay from the command line. I have also discovered that if I set the -err_detect flag to ignore_err, ffplay will continue streaming frames indefinitely and the problem goes away.

ffplay rtsp://192.168.1.254/xxx.mov -rtsp_transport tcp -err_detect ignore_err

However, setting the "err_detect" flag does not seem to make any difference using javacv. Here is the code I am using:

FFmpegLogCallback.set()
val grabber = FFmpegFrameGrabber(url)
grabber.format = "rtsp"
grabber.videoCodecName = "h264_mediacodec"
grabber.options["rtsp_transport"] = "tcp"  //this stops artifacts and distortion but only runs for 30 seconds then stops
grabber.options["err_detect"] = "ignore_err" //this doesn't seem to make any difference as it does using ffplay from the command line 
grabber.frameRate = 30.0
grabber.sampleRate = 30
grabber.start() 
while (alive) {
    val frame = grabber.grabImage()
    if (frame == null) {
        grabber.stop()
        grabber.start()
    } else {
        //process frame 
    }
}
saudet commented 2 months ago

Maybe try to call setOption("ignore_err", "1")?

saudet commented 2 months ago

Maybe that sets the codec option, so maybe try to call setAudioOption() and setVideoOption() instead of setOption()?

nickgitnick commented 2 months ago

I've tried all of these flags but still I start getting null frames after 30 seconds: grabber.options["ignore_err"] = "1" grabber.options["f_err_detect"] = "ignore_err" grabber.videoOptions["err_detect"] = "ignore_err" grabber.audioOptions["err_detect"] = "ignore_err" grabber.videoOptions["f_err_detect"] = "ignore_err" grabber.audioOptions["f_err_detect"] = "ignore_err" grabber.videoOptions["ignore_err"] = "1" grabber.audioOptions["ignore_err"] = "1"

I do call FFmpegLogCallback.set() but I don't see any debug messages being generated when this happens, I just start getting null frames. I can call stop() and then start() on the grabber, but I lose 1-2 seconds of video when doing this.