X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fplayer.cpp;h=e20a43cc26bf84fe920ac9dff3b2892d96ee6644;hb=a64b7a670a29674aa4a6cb2abe2f5a29f6cc14bc;hp=b88aa56267e7b7e87f9747be3db8d96e25280e5a;hpb=eeda8995329601f9f4e35047358400833eeae68e;p=nageru diff --git a/futatabi/player.cpp b/futatabi/player.cpp index b88aa56..e20a43c 100644 --- a/futatabi/player.cpp +++ b/futatabi/player.cpp @@ -4,6 +4,7 @@ #include "shared/context.h" #include "defs.h" #include "shared/ffmpeg_raii.h" +#include "flags.h" #include "frame_on_disk.h" #include "shared/httpd.h" #include "jpeg_frame_view.h" @@ -53,7 +54,7 @@ void Player::thread_func(bool also_output_to_stream) bool got_next_clip = false; double next_clip_fade_time = -1.0; - for ( ;; ) { + while (!should_quit) { wait_for_clip: bool clip_ready; steady_clock::time_point before_sleep = steady_clock::now(); @@ -62,8 +63,11 @@ wait_for_clip: { unique_lock lock(queue_state_mu); clip_ready = new_clip_changed.wait_for(lock, milliseconds(100), [this] { - return new_clip_ready && current_clip.pts_in != -1; + return should_quit || (new_clip_ready && current_clip.pts_in != -1); }); + if (should_quit) { + return; + } new_clip_ready = false; playing = true; } @@ -112,9 +116,10 @@ got_clip: double speed = 0.5; int64_t in_pts_start_next_clip = -1; - for (int frameno = 0; ; ++frameno) { // Ends when the clip ends. + steady_clock::time_point next_frame_start; + for (int frameno = 0; !should_quit; ++frameno) { // Ends when the clip ends. double out_pts = out_pts_origin + TIMEBASE * frameno / output_framerate; - steady_clock::time_point next_frame_start = + next_frame_start = origin + microseconds(lrint((out_pts - out_pts_origin) * 1e6 / TIMEBASE)); int64_t in_pts = lrint(in_pts_origin + TIMEBASE * frameno * speed / output_framerate); pts = lrint(out_pts); @@ -196,8 +201,11 @@ got_clip: if (video_stream == nullptr) { // No queue, just wait until the right time and then show the frame. new_clip_changed.wait_until(lock, next_frame_start, [this]{ - return new_clip_ready || override_stream_idx != -1; + return should_quit || new_clip_ready || override_stream_idx != -1; }); + if (should_quit) { + return; + } } else { // If the queue is full (which is really the state we'd like to be in), // wait until there's room for one more frame (ie., one was output from @@ -209,9 +217,12 @@ got_clip: if (num_queued_frames < max_queued_frames) { return true; } - return new_clip_ready || override_stream_idx != -1; + return should_quit || new_clip_ready || override_stream_idx != -1; }); } + if (should_quit) { + return; + } if (new_clip_ready) { if (video_stream != nullptr) { lock.unlock(); // Urg. @@ -228,7 +239,7 @@ got_clip: } } - if (frame_lower.pts == frame_upper.pts) { + if (frame_lower.pts == frame_upper.pts || global_flags.interpolation_quality == 0) { auto display_func = [this, primary_stream_idx, frame_lower, secondary_frame, fade_alpha]{ destination->setFrame(primary_stream_idx, frame_lower, secondary_frame, fade_alpha); }; @@ -253,11 +264,9 @@ got_clip: // (ie., move less than 1% of an _output_ frame), do so. // TODO: Snap secondary (fade-to) clips in the same fashion. bool snapped = false; - for (int64_t snap_pts : { frame_lower.pts, frame_upper.pts }) { - double snap_pts_as_frameno = (snap_pts - in_pts_origin) * output_framerate / TIMEBASE / speed; + for (FrameOnDisk snap_frame : { frame_lower, frame_upper }) { + double snap_pts_as_frameno = (snap_frame.pts - in_pts_origin) * output_framerate / TIMEBASE / speed; if (fabs(snap_pts_as_frameno - frameno) < 0.01) { - FrameOnDisk snap_frame = frame_lower; - snap_frame.pts = snap_pts; auto display_func = [this, primary_stream_idx, snap_frame, secondary_frame, fade_alpha]{ destination->setFrame(primary_stream_idx, snap_frame, secondary_frame, fade_alpha); }; @@ -275,7 +284,7 @@ got_clip: snap_frame, secondary_frame, fade_alpha); } } - in_pts_origin += snap_pts - in_pts; + in_pts_origin += snap_frame.pts - in_pts; snapped = true; break; } @@ -307,6 +316,10 @@ got_clip: } } + if (should_quit) { + return; + } + // The clip ended. // Last-ditch effort to get the next clip (if e.g. the fade time was zero seconds). @@ -329,7 +342,7 @@ got_clip: got_next_clip = false; // Start the next clip from the point where the fade went out. - origin = steady_clock::now(); + origin = next_frame_start; in_pts_origin = in_pts_start_next_clip; goto got_clip; } @@ -373,7 +386,17 @@ bool Player::find_surrounding_frames(int64_t pts, int stream_idx, FrameOnDisk *f Player::Player(JPEGFrameView *destination, bool also_output_to_stream) : destination(destination) { - thread(&Player::thread_func, this, also_output_to_stream).detach(); + player_thread = thread(&Player::thread_func, this, also_output_to_stream); +} + +Player::~Player() +{ + should_quit = true; + if (video_stream != nullptr) { + video_stream->stop(); + } + new_clip_changed.notify_all(); + player_thread.join(); } void Player::play_clip(const Clip &clip, size_t clip_idx, unsigned stream_idx)