X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fjpeg_frame_view.cpp;h=1924a543ff017346930f0c2d8c605253555e5728;hb=b44bf7cfce6a5aaffbcd1e37df39068a163438ad;hp=a9cf11cf77b51cbbc6fe43cd9b8582c5b66d26a4;hpb=996c5ad2c506048694b32988f7e376a97924c3e9;p=nageru diff --git a/futatabi/jpeg_frame_view.cpp b/futatabi/jpeg_frame_view.cpp index a9cf11c..1924a54 100644 --- a/futatabi/jpeg_frame_view.cpp +++ b/futatabi/jpeg_frame_view.cpp @@ -1,8 +1,10 @@ #include "jpeg_frame_view.h" #include "defs.h" +#include "flags.h" #include "jpeg_destroyer.h" #include "jpeglib_error_wrapper.h" +#include "shared/metrics.h" #include "shared/post_to_main_thread.h" #include "video_stream.h" #include "ycbcr_converter.h" @@ -71,6 +73,18 @@ struct PendingDecode { shared_ptr frame; }; +// There can be multiple JPEGFrameView instances, so make all the metrics static. +once_flag jpeg_metrics_inited; +atomic metric_jpeg_cache_used_bytes{0}; // Same value as cache_bytes_used. +atomic metric_jpeg_cache_limit_bytes{size_t(CACHE_SIZE_MB) * 1024 * 1024}; +atomic metric_jpeg_cache_given_up_frames{0}; +atomic metric_jpeg_cache_hit_frames{0}; +atomic metric_jpeg_cache_miss_frames{0}; +atomic metric_jpeg_software_decode_frames{0}; +atomic metric_jpeg_software_fail_frames{0}; +atomic metric_jpeg_vaapi_decode_frames{0}; +atomic metric_jpeg_vaapi_fail_frames{0}; + } // namespace thread JPEGFrameView::jpeg_decoder_thread; @@ -89,9 +103,11 @@ shared_ptr decode_jpeg(const string &jpeg) if (vaapi_jpeg_decoding_usable) { frame = decode_jpeg_vaapi(jpeg); if (frame != nullptr) { + ++metric_jpeg_vaapi_decode_frames; return frame; } fprintf(stderr, "VA-API hardware decoding failed; falling back to software.\n"); + ++metric_jpeg_vaapi_fail_frames; } frame.reset(new Frame); @@ -179,6 +195,7 @@ shared_ptr decode_jpeg(const string &jpeg) return get_black_frame(); } + ++metric_jpeg_software_decode_frames; return frame; } @@ -207,6 +224,7 @@ void prune_cache() for (auto it = cache.begin(); it != cache.end(); ) { if (it->second.last_used <= lru_cutoff_point) { cache_bytes_used -= frame_size(*it->second.frame); + metric_jpeg_cache_used_bytes = cache_bytes_used; it = cache.erase(it); } else { ++it; @@ -218,23 +236,28 @@ shared_ptr decode_jpeg_with_cache(FrameOnDisk frame_spec, CacheMissBehavi { *did_decode = false; { - unique_lock lock(cache_mu); + lock_guard lock(cache_mu); auto it = cache.find(frame_spec); if (it != cache.end()) { + ++metric_jpeg_cache_hit_frames; it->second.last_used = event_counter++; return it->second.frame; } } if (cache_miss_behavior == RETURN_NULLPTR_IF_NOT_IN_CACHE) { + ++metric_jpeg_cache_given_up_frames; return nullptr; } + ++metric_jpeg_cache_miss_frames; + *did_decode = true; shared_ptr frame = decode_jpeg(frame_reader->read_frame(frame_spec)); - unique_lock lock(cache_mu); + lock_guard lock(cache_mu); cache_bytes_used += frame_size(*frame); + metric_jpeg_cache_used_bytes = cache_bytes_used; cache[frame_spec] = LRUFrame{ frame, event_counter++ }; if (cache_bytes_used > size_t(CACHE_SIZE_MB) * 1024 * 1024) { @@ -328,13 +351,24 @@ void JPEGFrameView::shutdown() JPEGFrameView::JPEGFrameView(QWidget *parent) : QGLWidget(parent, global_share_widget) { + call_once(jpeg_metrics_inited, []{ + global_metrics.add("jpeg_cache_used_bytes", &metric_jpeg_cache_used_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("jpeg_cache_limit_bytes", &metric_jpeg_cache_limit_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("jpeg_cache_frames", {{ "action", "given_up" }}, &metric_jpeg_cache_given_up_frames); + global_metrics.add("jpeg_cache_frames", {{ "action", "hit" }}, &metric_jpeg_cache_hit_frames); + global_metrics.add("jpeg_cache_frames", {{ "action", "miss" }}, &metric_jpeg_cache_miss_frames); + global_metrics.add("jpeg_decode_frames", {{ "decoder", "software" }, { "result", "decode" }}, &metric_jpeg_software_decode_frames); + global_metrics.add("jpeg_decode_frames", {{ "decoder", "software" }, { "result", "fail" }}, &metric_jpeg_software_fail_frames); + global_metrics.add("jpeg_decode_frames", {{ "decoder", "vaapi" }, { "result", "decode" }}, &metric_jpeg_vaapi_decode_frames); + global_metrics.add("jpeg_decode_frames", {{ "decoder", "vaapi" }, { "result", "fail" }}, &metric_jpeg_vaapi_fail_frames); + }); } void JPEGFrameView::setFrame(unsigned stream_idx, FrameOnDisk frame, FrameOnDisk secondary_frame, float fade_alpha) { current_stream_idx = stream_idx; // TODO: Does this interact with fades? - unique_lock lock(cache_mu); + lock_guard lock(cache_mu); PendingDecode decode; decode.primary = frame; decode.secondary = secondary_frame; @@ -346,7 +380,7 @@ void JPEGFrameView::setFrame(unsigned stream_idx, FrameOnDisk frame, FrameOnDisk void JPEGFrameView::setFrame(shared_ptr frame) { - unique_lock lock(cache_mu); + lock_guard lock(cache_mu); PendingDecode decode; decode.frame = std::move(frame); decode.destination = this; @@ -474,15 +508,16 @@ shared_ptr get_black_frame() static once_flag flag; call_once(flag, [] { black_frame.reset(new Frame); - black_frame->y.reset(new uint8_t[1280 * 720]); - black_frame->cb.reset(new uint8_t[(1280 / 2) * (720 / 2)]); - black_frame->cr.reset(new uint8_t[(1280 / 2) * (720 / 2)]); - black_frame->width = 1280; - black_frame->height = 720; + black_frame->y.reset(new uint8_t[global_flags.width * global_flags.height]); + black_frame->cb.reset(new uint8_t[(global_flags.width / 2) * (global_flags.height / 2)]); + black_frame->cr.reset(new uint8_t[(global_flags.width / 2) * (global_flags.height / 2)]); + black_frame->width = global_flags.width; + black_frame->height = global_flags.height; black_frame->chroma_subsampling_x = 2; black_frame->chroma_subsampling_y = 2; - black_frame->pitch_y = 1280; - black_frame->pitch_chroma = 1280 / 2; + black_frame->pitch_y = global_flags.width; + black_frame->pitch_chroma = global_flags.width / 2; }); + ++metric_jpeg_software_fail_frames; return black_frame; }