]> git.sesse.net Git - nageru/commitdiff
Fix issues with displaying faded interpolating frames in the preview.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 11 Oct 2018 22:40:41 +0000 (00:40 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 11 Oct 2018 22:40:41 +0000 (00:40 +0200)
jpeg_frame_view.cpp
jpeg_frame_view.h
video_stream.cpp
video_stream.h

index 4598383b9dd6b30c40bd1d54f785ee0aa641a71b..905249a0cfe9e2b7e33c7e4b91b280e7201144f4 100644 (file)
@@ -311,18 +311,22 @@ void JPEGFrameView::setFrame(unsigned stream_idx, int64_t pts, bool interpolated
 
        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,
index 9a4621d46b3bc512b27a04613bc7cd42d6d8642f..b8e26c4a3a98f35170d73e8445098e11488d7d01 100644 (file)
@@ -27,6 +27,19 @@ enum CacheMissBehavior {
        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);
@@ -38,7 +51,7 @@ public:
        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;
 
index 69dfbe6f0fea07ff22a09f60fabf09122b0e93e4..6142aedf6cdf2d0f0bceb73dceca2e8e467ed1e8 100644 (file)
@@ -355,13 +355,20 @@ void VideoStream::schedule_interpolated_frame(int64_t output_pts, unsigned strea
                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();
@@ -373,6 +380,7 @@ void VideoStream::schedule_interpolated_frame(int64_t output_pts, unsigned strea
        qf.output_pts = output_pts;
        qf.stream_idx = stream_idx;
        qf.resources = resources;
+       qf.id = id;
 
        check_error();
 
@@ -539,7 +547,7 @@ void VideoStream::encode_thread_func()
 
                        // 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);
index 146df0bedbae2abbb4887869b21d536319dc98ac..1439eb0db1ef1377fa920feadb2cfdae5bd8e8c5 100644 (file)
@@ -18,6 +18,7 @@ extern "C" {
 #include <movit/mix_effect.h>
 #include <movit/ycbcr_input.h>
 
+#include "jpeg_frame_view.h"
 #include "ref_counted_gl_sync.h"
 
 class ChromaSubsampler;
@@ -82,6 +83,7 @@ private:
                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;