namespace {
// Just an arbitrary order for std::map.
-struct JPEGIDLexicalOrder
+struct FrameOnDiskLexicalOrder
{
- bool operator() (const JPEGID &a, const JPEGID &b) const
+ bool operator() (const FrameOnDisk &a, const FrameOnDisk &b) const
{
- if (a.stream_idx != b.stream_idx)
- return a.stream_idx < b.stream_idx;
- return a.pts < b.pts;
+ if (a.pts != b.pts)
+ return a.pts < b.pts;
+ if (a.offset != b.offset)
+ return a.offset < b.offset;
+ if (a.filename_idx != b.filename_idx)
+ return a.filename_idx < b.filename_idx;
+ assert(a.size == b.size);
+ return false;
}
};
JPEGFrameView *destination;
// For actual decodes (only if frame below is nullptr).
- JPEGID primary, secondary;
+ FrameOnDisk primary, secondary;
float fade_alpha; // Irrelevant if secondary.stream_idx == -1.
// Already-decoded frames are also sent through PendingDecode,
thread JPEGFrameView::jpeg_decoder_thread;
mutex cache_mu;
-map<JPEGID, LRUFrame, JPEGIDLexicalOrder> cache; // Under cache_mu.
+map<FrameOnDisk, LRUFrame, FrameOnDiskLexicalOrder> cache; // Under cache_mu.
size_t cache_bytes_used = 0; // Under cache_mu.
condition_variable any_pending_decodes;
deque<PendingDecode> pending_decodes; // Under cache_mu.
}
}
-shared_ptr<Frame> decode_jpeg_with_cache(JPEGID id, CacheMissBehavior cache_miss_behavior, bool *did_decode)
+shared_ptr<Frame> decode_jpeg_with_cache(FrameOnDisk frame_spec, CacheMissBehavior cache_miss_behavior, FrameReader *frame_reader, bool *did_decode)
{
*did_decode = false;
{
unique_lock<mutex> lock(cache_mu);
- auto it = cache.find(id);
+ auto it = cache.find(frame_spec);
if (it != cache.end()) {
it->second.last_used = event_counter++;
return it->second.frame;
}
*did_decode = true;
- shared_ptr<Frame> frame = decode_jpeg(filename_for_frame(id.stream_idx, id.pts));
+ shared_ptr<Frame> frame = decode_jpeg(frame_reader->read_frame(frame_spec));
unique_lock<mutex> lock(cache_mu);
cache_bytes_used += frame_size(*frame);
- cache[id] = LRUFrame{ frame, event_counter++ };
+ cache[frame_spec] = LRUFrame{ frame, event_counter++ };
if (cache_bytes_used > size_t(CACHE_SIZE_MB) * 1024 * 1024) {
prune_cache();
return frame;
}
-void jpeg_decoder_thread_func()
+void JPEGFrameView::jpeg_decoder_thread_func()
{
size_t num_decoded = 0, num_dropped = 0;
shared_ptr<Frame> primary_frame, secondary_frame;
bool drop = false;
for (int subframe_idx = 0; subframe_idx < 2; ++subframe_idx) {
- const JPEGID &id = (subframe_idx == 0 ? decode.primary : decode.secondary);
- if (id.stream_idx == (unsigned)-1) {
+ const FrameOnDisk &frame_spec = (subframe_idx == 0 ? decode.primary : decode.secondary);
+ if (frame_spec.pts == -1) {
// No secondary frame.
continue;
}
bool found_in_cache;
- shared_ptr<Frame> frame = decode_jpeg_with_cache(id, cache_miss_behavior, &found_in_cache);
+ shared_ptr<Frame> frame = decode_jpeg_with_cache(frame_spec, cache_miss_behavior, &decode.destination->frame_reader, &found_in_cache);
if (frame == nullptr) {
assert(cache_miss_behavior == RETURN_NULLPTR_IF_NOT_IN_CACHE);
}
}
if (subframe_idx == 0) {
- primary_frame = move(frame);
+ primary_frame = std::move(frame);
} else {
- secondary_frame = move(frame);
+ secondary_frame = std::move(frame);
}
}
if (drop) {
{
}
-void JPEGFrameView::setFrame(unsigned stream_idx, int64_t pts, int secondary_stream_idx, int64_t secondary_pts, float fade_alpha)
+void JPEGFrameView::setFrame(unsigned stream_idx, FrameOnDisk frame, FrameOnDisk secondary_frame, float fade_alpha)
{
- if (secondary_stream_idx != -1) assert(secondary_pts != -1);
current_stream_idx = stream_idx; // TODO: Does this interact with fades?
unique_lock<mutex> lock(cache_mu);
PendingDecode decode;
- decode.primary = JPEGID{ stream_idx, pts };
- decode.secondary = JPEGID{ (unsigned)secondary_stream_idx, secondary_pts };
+ decode.primary = frame;
+ decode.secondary = secondary_frame;
decode.fade_alpha = fade_alpha;
decode.destination = this;
pending_decodes.push_back(decode);