void Player::thread_func(bool also_output_to_stream)
{
+ pthread_setname_np(pthread_self(), "Player");
+
QSurface *surface = create_surface();
QOpenGLContext *context = create_context(surface);
if (!make_current(context, surface)) {
int64_t in_pts = lrint(in_pts_origin + TIMEBASE * frameno * speed / output_framerate);
pts = lrint(out_pts);
+ steady_clock::duration time_behind = steady_clock::now() - next_frame_start;
+ if (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;
+ }
+
int64_t in_pts_lower, in_pts_upper;
// Find the frame immediately before and after this point.
}
}
+ if (progress_callback != nullptr) {
+ // NOTE: None of this will take into account any snapping done below.
+ double played_this_clip = double(in_pts - clip.pts_in) / TIMEBASE / speed;
+ double total_length = double(clip.pts_out - clip.pts_in) / TIMEBASE / speed;
+ progress_callback(played_this_clip, total_length);
+ }
+
if (in_pts_lower == in_pts_upper) {
- destination->setFrame(stream_idx, in_pts_lower);
+ destination->setFrame(stream_idx, in_pts_lower, /*interpolated=*/false);
if (video_stream != nullptr) {
video_stream->schedule_original_frame(lrint(out_pts), stream_idx, in_pts_lower);
}
double in_pts_lower_as_frameno = (in_pts_lower - in_pts_origin) * output_framerate / TIMEBASE / speed;
double in_pts_upper_as_frameno = (in_pts_upper - in_pts_origin) * output_framerate / TIMEBASE / speed;
if (fabs(in_pts_lower_as_frameno - frameno) < 0.01) {
- destination->setFrame(stream_idx, in_pts_lower);
+ destination->setFrame(stream_idx, in_pts_lower, /*interpolated=*/false);
if (video_stream != nullptr) {
video_stream->schedule_original_frame(lrint(out_pts), stream_idx, in_pts_lower);
}
in_pts_origin += in_pts_lower - in_pts;
continue;
} else if (fabs(in_pts_upper_as_frameno - frameno) < 0.01) {
- destination->setFrame(stream_idx, in_pts_upper);
+ destination->setFrame(stream_idx, in_pts_upper, /*interpolated=*/false);
if (video_stream != nullptr) {
video_stream->schedule_original_frame(lrint(out_pts), stream_idx, in_pts_upper);
}
continue;
}
+ if (time_behind >= milliseconds(100)) {
+ fprintf(stderr, "WARNING: %ld ms behind, dropping an interpolated frame.\n",
+ lrint(1e3 * duration<double>(time_behind).count()));
+ continue;
+ }
+
double alpha = double(in_pts - in_pts_lower) / (in_pts_upper - in_pts_lower);
- destination->setFrame(stream_idx, in_pts_lower); // FIXME
- if (video_stream != nullptr) {
- // Send the frame to the stream.
+ if (video_stream == nullptr) {
+ // Previews don't do any interpolation.
+ destination->setFrame(stream_idx, in_pts_lower, /*interpolated=*/false);
+ } else {
+ // Calculate the interpolated frame. When it's done, the destination
+ // will be unblocked.
+ destination->setFrame(stream_idx, lrint(out_pts), /*interpolated=*/true);
video_stream->schedule_interpolated_frame(lrint(out_pts), stream_idx, in_pts_lower, in_pts_upper, alpha);
}
}
if (it == frames[stream_idx].end()) {
return;
}
- destination->setFrame(stream_idx, *it);
+ destination->setFrame(stream_idx, *it, /*interpolated=*/false);
}