X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg_capture.cpp;h=464b4cb92d292b8b6bb80f458c92715209f6e902;hb=73ddb883aaf76a76d8c03730e587ac396255c0c9;hp=e03382cec5418c8732bff8f0ecbc0d8346cb0544;hpb=bf6f4393ef3282685392858aaef8151f63e8b3c2;p=nageru diff --git a/ffmpeg_capture.cpp b/ffmpeg_capture.cpp index e03382c..464b4cb 100644 --- a/ffmpeg_capture.cpp +++ b/ffmpeg_capture.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include extern "C" { @@ -44,6 +45,19 @@ steady_clock::time_point compute_frame_start(int64_t frame_pts, int64_t pts_orig return origin + duration_cast(pts / rate); } +bool changed_since(const std::string &pathname, const timespec &ts) +{ + if (ts.tv_sec < 0) { + return false; + } + struct stat buf; + if (stat(pathname.c_str(), &buf) != 0) { + fprintf(stderr, "%s: Couldn't check for new version, leaving the old in place.\n", pathname.c_str()); + return false; + } + return (buf.st_mtim.tv_sec != ts.tv_sec || buf.st_mtim.tv_nsec != ts.tv_nsec); +} + } // namespace FFmpegCapture::FFmpegCapture(const string &filename, unsigned width, unsigned height) @@ -142,6 +156,18 @@ void FFmpegCapture::producer_thread_func() bool FFmpegCapture::play_video(const string &pathname) { + // Note: Call before open, not after; otherwise, there's a race. + // (There is now, too, but it tips the correct way. We could use fstat() + // if we had the file descriptor.) + timespec last_modified; + struct stat buf; + if (stat(pathname.c_str(), &buf) != 0) { + // Probably some sort of protocol, so can't stat. + last_modified.tv_sec = -1; + } else { + last_modified = buf.st_mtim; + } + auto format_ctx = avformat_open_input_unique(pathname.c_str(), nullptr, nullptr); if (format_ctx == nullptr) { fprintf(stderr, "%s: Error opening file\n", pathname.c_str()); @@ -209,6 +235,13 @@ bool FFmpegCapture::play_video(const string &pathname) if (av_seek_frame(format_ctx.get(), /*stream_index=*/-1, /*timestamp=*/0, /*flags=*/0) < 0) { fprintf(stderr, "%s: Rewind failed, stopping play.\n", pathname.c_str()); } + // If the file has changed since last time, return to get it reloaded. + // Note that depending on how you move the file into place, you might + // end up corrupting the one you're already playing, so this path + // might not trigger. + if (changed_since(pathname, last_modified)) { + return true; + } internal_rewind(); break; @@ -260,6 +293,13 @@ bool FFmpegCapture::play_video(const string &pathname) fprintf(stderr, "%s: Rewind failed, not looping.\n", pathname.c_str()); return true; } + // If the file has changed since last time, return to get it reloaded. + // Note that depending on how you move the file into place, you might + // end up corrupting the one you're already playing, so this path + // might not trigger. + if (changed_since(pathname, last_modified)) { + return true; + } internal_rewind(); continue; }