unique_lock<mutex> lock(cache_mu);
PendingDecode decode;
- decode.primary = JPEGID{ stream_idx, pts, interpolated };
- decode.secondary = JPEGID{ (unsigned)secondary_stream_idx, secondary_pts, /*interpolated=*/false };
+ if (interpolated && secondary_stream_idx != -1) {
+ // The frame will already be faded for us, so ask for only one; we shouldn't fade it against anything.
+ decode.primary = create_jpegid_for_interpolated_fade(stream_idx, pts, secondary_stream_idx, secondary_pts);
+ decode.secondary = JPEGID{ (unsigned)-1, -1, /*interpolated=*/false };
+ } else {
+ decode.primary = JPEGID{ stream_idx, pts, interpolated };
+ decode.secondary = JPEGID{ (unsigned)secondary_stream_idx, secondary_pts, /*interpolated=*/false };
+ }
decode.fade_alpha = fade_alpha;
decode.destination = this;
pending_decodes.push_back(decode);
any_pending_decodes.notify_all();
}
-void JPEGFrameView::insert_interpolated_frame(unsigned stream_idx, int64_t pts, shared_ptr<Frame> frame)
+void JPEGFrameView::insert_interpolated_frame(JPEGID id, shared_ptr<Frame> frame)
{
- JPEGID id{ stream_idx, pts, true };
-
// We rely on the frame not being evicted from the cache before
// jpeg_decoder_thread() sees it and can display it (otherwise,
// that thread would hang). With a default cache of 1000 elements,
RETURN_NULLPTR_IF_NOT_IN_CACHE
};
+// This is, well, a hack. We hope for no collisions.
+inline JPEGID create_jpegid_for_interpolated_fade(unsigned stream_idx, int64_t pts, unsigned secondary_stream_idx, int64_t secondary_pts)
+{
+ JPEGID id;
+ id.stream_idx = (stream_idx << 8) | secondary_stream_idx;
+
+ uint64_t rot = secondary_stream_idx;
+ rot = (rot << 32) | (rot >> 32);
+ id.pts = pts ^ int64_t(rot);
+ id.interpolated = true;
+ return id;
+}
+
std::string filename_for_frame(unsigned stream_idx, int64_t pts);
std::shared_ptr<Frame> decode_jpeg(const std::string &filename);
std::shared_ptr<Frame> decode_jpeg_with_cache(JPEGID id, CacheMissBehavior cache_miss_behavior, bool *did_decode);
JPEGFrameView(QWidget *parent);
void setFrame(unsigned stream_idx, int64_t pts, bool interpolated, int secondary_stream_idx = -1, int64_t secondary_pts = -1, float fade_alpha = 0.0f);
- static void insert_interpolated_frame(unsigned stream_idx, int64_t pts, std::shared_ptr<Frame> frame);
+ static void insert_interpolated_frame(JPEGID id, std::shared_ptr<Frame> frame);
void mousePressEvent(QMouseEvent *event) override;
fprintf(stderr, "output_pts=%ld interpolated input_pts1=%ld input_pts2=%ld alpha=%.3f\n", output_pts, input_first_pts, input_second_pts, alpha);
}
+ JPEGID id;
+ if (secondary_stream_idx == -1) {
+ id = JPEGID{ stream_idx, output_pts, /*interpolated=*/true };
+ } else {
+ id = create_jpegid_for_interpolated_fade(stream_idx, output_pts, secondary_stream_idx, secondary_input_pts);
+ }
+
// Get the temporary OpenGL resources we need for doing the interpolation.
InterpolatedFrameResources resources;
{
unique_lock<mutex> lock(queue_lock);
if (interpolate_resources.empty()) {
fprintf(stderr, "WARNING: Too many interpolated frames already in transit; dropping one.\n");
- JPEGFrameView::insert_interpolated_frame(stream_idx, output_pts, nullptr);
+ JPEGFrameView::insert_interpolated_frame(id, nullptr);
return;
}
resources = interpolate_resources.front();
qf.output_pts = output_pts;
qf.stream_idx = stream_idx;
qf.resources = resources;
+ qf.id = id;
check_error();
// Send a copy of the frame on to display.
shared_ptr<Frame> frame = frame_from_pbo(qf.resources.pbo_contents, 1280, 720);
- JPEGFrameView::insert_interpolated_frame(qf.stream_idx, qf.output_pts, frame); // TODO: this is wrong for fades
+ JPEGFrameView::insert_interpolated_frame(qf.id, frame);
// Now JPEG encode it, and send it on to the stream.
vector<uint8_t> jpeg = encode_jpeg(frame->y.get(), frame->cb.get(), frame->cr.get(), 1280, 720);
#include <movit/mix_effect.h>
#include <movit/ycbcr_input.h>
+#include "jpeg_frame_view.h"
#include "ref_counted_gl_sync.h"
class ChromaSubsampler;
InterpolatedFrameResources resources;
RefCountedGLsync fence; // Set when the interpolated image is read back to the CPU.
GLuint flow_tex, output_tex, cbcr_tex; // Released in the receiving thread; not really used for anything else.
+ JPEGID id;
};
std::deque<QueuedFrame> frame_queue; // Under <queue_lock>.
std::mutex queue_lock;