X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fffmpeg_capture.cpp;h=9af4e833f76340bfa3b92717f78e3763fad02776;hb=22d74c9f49f8602fd33c499a575a3fa605f43dee;hp=79fba7b9ab4ebf4135e8e9f34c145e78a676e7b4;hpb=685a74b4a2e928670eb5fb53919bbcffca45c8e3;p=nageru diff --git a/nageru/ffmpeg_capture.cpp b/nageru/ffmpeg_capture.cpp index 79fba7b..9af4e83 100644 --- a/nageru/ffmpeg_capture.cpp +++ b/nageru/ffmpeg_capture.cpp @@ -531,10 +531,13 @@ bool FFmpegCapture::play_video(const string &pathname) AVFormatContextWithCloser format_ctx; if (srt_sock == -1) { - // Regular file. + // Regular file (or stream). + frame_timeout_started = steady_clock::now(); + frame_timeout_valid = true; format_ctx = avformat_open_input_unique(pathname.c_str(), /*fmt=*/nullptr, /*options=*/nullptr, AVIOInterruptCB{ &FFmpegCapture::interrupt_cb_thunk, this }); + frame_timeout_valid = false; } else { #ifdef HAVE_SRT // SRT socket, already opened. @@ -653,8 +656,15 @@ bool FFmpegCapture::play_video(const string &pathname) int64_t audio_pts; bool error; + frame_timeout_started = steady_clock::now(); + frame_timeout_valid = true; AVFrameWithDeleter frame = decode_frame(format_ctx.get(), video_codec_ctx.get(), audio_codec_ctx.get(), pathname, video_stream_index, audio_stream_index, subtitle_stream_index, audio_frame.get(), &audio_format, &audio_pts, &error); + frame_timeout_valid = false; + if (should_interrupt.load()) { + // Abort no matter whether we got a frame or not. + return false; + } if (error) { if (++consecutive_errors >= 100) { fprintf(stderr, "More than 100 consecutive error video frames, aborting playback.\n"); @@ -1166,6 +1176,21 @@ int FFmpegCapture::interrupt_cb_thunk(void *opaque) int FFmpegCapture::interrupt_cb() { + // If ten seconds is gone without anything happening, we assume that + // we are in a network stream that died and FFmpeg just didn't + // pick it up (or perhaps it just hung, keeping the connection open). + // Called back approximately every 100 ms if something is hanging, + // so we get more than enough accuracy for our purposes. + if (!should_interrupt && frame_timeout_valid && + duration(steady_clock::now() - frame_timeout_started).count() >= 10.0) { + string filename_copy; + { + lock_guard lock(filename_mu); + filename_copy = filename; + } + fprintf(stderr, "%s: No frame for more than 10 seconds, restarting stream.\n", filename.c_str()); + should_interrupt = true; + } return should_interrupt.load(); }