#include <movit/mix_effect.h>
#include <movit/ycbcr_input.h>
#include <stdint.h>
+#include <condition_variable>
+#include <deque>
#include <thread>
enum CacheMissBehavior {
RETURN_NULLPTR_IF_NOT_IN_CACHE
};
-std::shared_ptr<Frame> decode_jpeg(const std::string &filename);
+std::shared_ptr<Frame> decode_jpeg(const std::string &jpeg);
std::shared_ptr<Frame> decode_jpeg_with_cache(FrameOnDisk id, CacheMissBehavior cache_miss_behavior, FrameReader *frame_reader, bool *did_decode);
+std::shared_ptr<Frame> get_black_frame();
class JPEGFrameView : public QGLWidget {
Q_OBJECT
public:
JPEGFrameView(QWidget *parent);
+ ~JPEGFrameView();
void setFrame(unsigned stream_idx, FrameOnDisk frame, FrameOnDisk secondary_frame = {}, float fade_alpha = 0.0f);
void setFrame(std::shared_ptr<Frame> frame);
void setDecodedFrame(std::shared_ptr<Frame> frame, std::shared_ptr<Frame> secondary_frame, float fade_alpha);
void set_overlay(const std::string &text); // Blank for none.
- static void shutdown();
-
signals:
void clicked();
void paintGL() override;
private:
- static void jpeg_decoder_thread_func();
+ void jpeg_decoder_thread_func();
FrameReader frame_reader;
std::unique_ptr<YCbCrConverter> ycbcr_converter;
movit::EffectChain *current_chain = nullptr; // Owned by ycbcr_converter.
- std::shared_ptr<Frame> current_frame; // So that we hold on to the pixels.
+ bool displayed_this_frame = false; // Owned by the UI frame.
+ std::shared_ptr<Frame> current_frame; // So that we hold on to the textures.
std::shared_ptr<Frame> current_secondary_frame; // Same.
- static constexpr int overlay_base_width = 16, overlay_base_height = 16;
+ int overlay_base_width = 16, overlay_base_height = 16;
int overlay_width = overlay_base_width, overlay_height = overlay_base_height;
std::unique_ptr<QImage> overlay_image; // If nullptr, no overlay.
std::unique_ptr<movit::EffectChain> overlay_chain; // Just to get the overlay on screen in the easiest way possible.
int gl_width, gl_height;
- static std::thread jpeg_decoder_thread;
+ std::thread jpeg_decoder_thread;
+ movit::ResourcePool *resource_pool = nullptr;
+
+ struct PendingDecode {
+ // For actual decodes (only if frame below is nullptr).
+ FrameOnDisk primary, secondary;
+ float fade_alpha; // Irrelevant if secondary.stream_idx == -1.
+
+ // Already-decoded frames are also sent through PendingDecode,
+ // so that they get drawn in the right order. If frame is nullptr,
+ // it's a real decode.
+ std::shared_ptr<Frame> frame;
+ };
+
+ std::condition_variable any_pending_decodes;
+ std::deque<PendingDecode> pending_decodes; // Under cache_mu.
};
#endif // !defined(_JPEG_FRAME_VIEW_H)