extern HTTPD *global_httpd;
-void Player::thread_func(bool also_output_to_stream)
+void Player::thread_func(Player::StreamOutput stream_output, AVFormatContext *file_avctx)
{
pthread_setname_np(pthread_self(), "Player");
check_error();
// Create the VideoStream object, now that we have an OpenGL context.
- if (also_output_to_stream) {
- video_stream.reset(new VideoStream);
+ if (stream_output != NO_STREAM_OUTPUT) {
+ video_stream.reset(new VideoStream(file_avctx));
video_stream->start();
}
lock_guard<mutex> lock(frame_mu);
// Find the first frame such that frame.pts <= in_pts.
- auto it = lower_bound(frames[stream_idx].begin(),
- frames[stream_idx].end(),
- in_pts_origin,
- [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; });
+ auto it = find_last_frame_before(frames[stream_idx], in_pts_origin);
if (it != frames[stream_idx].end()) {
in_pts_origin = it->pts;
}
}
steady_clock::duration time_behind = steady_clock::now() - next_frame_start;
- if (time_behind >= milliseconds(200)) {
+ if (stream_output != FILE_STREAM_OUTPUT && time_behind >= milliseconds(200)) {
fprintf(stderr, "WARNING: %ld ms behind, dropping a frame (no matter the type).\n",
lrint(1e3 * duration<double>(time_behind).count()));
continue;
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);
+ if (destination != nullptr) {
+ destination->setFrame(primary_stream_idx, frame_lower, secondary_frame, fade_alpha);
+ }
};
if (video_stream == nullptr) {
display_func();
double snap_pts_as_frameno = (snap_frame.pts - in_pts_origin) * output_framerate / TIMEBASE / speed;
if (fabs(snap_pts_as_frameno - frameno) < 0.01) {
auto display_func = [this, primary_stream_idx, snap_frame, secondary_frame, fade_alpha]{
- destination->setFrame(primary_stream_idx, snap_frame, secondary_frame, fade_alpha);
+ if (destination != nullptr) {
+ destination->setFrame(primary_stream_idx, snap_frame, secondary_frame, fade_alpha);
+ }
};
if (video_stream == nullptr) {
display_func();
continue;
}
- if (time_behind >= milliseconds(100)) {
+ if (stream_output != FILE_STREAM_OUTPUT && time_behind >= milliseconds(100)) {
fprintf(stderr, "WARNING: %ld ms behind, dropping an interpolated frame.\n",
lrint(1e3 * duration<double>(time_behind).count()));
continue;
if (video_stream == nullptr) {
// Previews don't do any interpolation.
assert(secondary_stream_idx == -1);
- destination->setFrame(primary_stream_idx, frame_lower);
+ if (destination != nullptr) {
+ destination->setFrame(primary_stream_idx, frame_lower);
+ }
} else {
auto display_func = [this](shared_ptr<Frame> frame) {
- destination->setFrame(frame);
+ if (destination != nullptr) {
+ destination->setFrame(frame);
+ }
};
video_stream->schedule_interpolated_frame(
next_frame_start, pts, display_func, QueueSpotHolder(this),
lock_guard<mutex> lock(frame_mu);
// Find the first frame such that frame.pts >= pts.
- auto it = lower_bound(frames[stream_idx].begin(),
- frames[stream_idx].end(),
- pts,
- [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; });
+ auto it = find_last_frame_before(frames[stream_idx], pts);
if (it == frames[stream_idx].end()) {
return false;
}
return true;
}
-Player::Player(JPEGFrameView *destination, bool also_output_to_stream)
+Player::Player(JPEGFrameView *destination, Player::StreamOutput stream_output, AVFormatContext *file_avctx)
: destination(destination)
{
- player_thread = thread(&Player::thread_func, this, also_output_to_stream);
+ player_thread = thread(&Player::thread_func, this, stream_output, file_avctx);
}
Player::~Player()
}
lock_guard<mutex> lock(frame_mu);
- auto it = upper_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts_out,
- [](int64_t pts, const FrameOnDisk &frame) { return pts < frame.pts; });
+ auto it = find_first_frame_at_or_after(frames[stream_idx], pts_out);
if (it == frames[stream_idx].end()) {
return;
}