X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fjpeg_frame_view.cpp;h=c95a2ce0af403d7bf99b3a052d7e7494e13d4056;hb=06c2ef3a3edb23b0e02eca9d5b43b0098c9474e7;hp=c1afafd765ca32f803c35c23b821c949bb807e91;hpb=e0cb348ca42ae7057f8f5acee92a23e7eb26075f;p=nageru diff --git a/futatabi/jpeg_frame_view.cpp b/futatabi/jpeg_frame_view.cpp index c1afafd..c95a2ce 100644 --- a/futatabi/jpeg_frame_view.cpp +++ b/futatabi/jpeg_frame_view.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ using namespace movit; using namespace std; +using namespace std::chrono; namespace { @@ -70,6 +72,7 @@ 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 }; +Summary metric_jpeg_decode_time_seconds; } // namespace @@ -82,11 +85,14 @@ extern atomic should_quit; shared_ptr decode_jpeg(const string &jpeg) { + steady_clock::time_point start = steady_clock::now(); shared_ptr frame; if (vaapi_jpeg_decoding_usable) { frame = decode_jpeg_vaapi(jpeg); if (frame != nullptr) { ++metric_jpeg_vaapi_decode_frames; + steady_clock::time_point stop = steady_clock::now(); + metric_jpeg_decode_time_seconds.count_event(duration(stop - start).count()); return frame; } fprintf(stderr, "VA-API hardware decoding failed; falling back to software.\n"); @@ -109,6 +115,8 @@ shared_ptr decode_jpeg(const string &jpeg) return get_black_frame(); } + jpeg_save_markers(&dinfo, JPEG_APP0 + 1, 0xFFFF); + if (dinfo.num_components != 3) { fprintf(stderr, "Not a color JPEG. (%d components, Y=%dx%d, Cb=%dx%d, Cr=%dx%d)\n", dinfo.num_components, @@ -159,6 +167,14 @@ shared_ptr decode_jpeg(const string &jpeg) frame->pitch_y = luma_width_blocks * DCTSIZE; frame->pitch_chroma = chroma_width_blocks * DCTSIZE; + if (dinfo.marker_list != nullptr && + dinfo.marker_list->marker == JPEG_APP0 + 1 && + dinfo.marker_list->data_length >= 4 && + memcmp(dinfo.marker_list->data, "Exif", 4) == 0) { + frame->exif_data.assign(reinterpret_cast(dinfo.marker_list->data), + dinfo.marker_list->data_length); + } + if (!error_mgr.run([&dinfo, &frame, v_mcu_size, mcu_height_blocks] { JSAMPROW yptr[v_mcu_size], cbptr[v_mcu_size], crptr[v_mcu_size]; JSAMPARRAY data[3] = { yptr, cbptr, crptr }; @@ -179,6 +195,8 @@ shared_ptr decode_jpeg(const string &jpeg) } ++metric_jpeg_software_decode_frames; + steady_clock::time_point stop = steady_clock::now(); + metric_jpeg_decode_time_seconds.count_event(duration(stop - start).count()); return frame; } @@ -238,7 +256,7 @@ shared_ptr decode_jpeg_with_cache(FrameOnDisk frame_spec, CacheMissBehavi ++metric_jpeg_cache_miss_frames; *did_decode = true; - shared_ptr frame = decode_jpeg(frame_reader->read_frame(frame_spec, /*read_audio=*/false).video); + shared_ptr frame = decode_jpeg(frame_reader->read_frame(frame_spec, /*read_video=*/true, /*read_audio=*/false).video); lock_guard lock(cache_mu); cache_bytes_used += frame_size(*frame); @@ -340,6 +358,9 @@ JPEGFrameView::JPEGFrameView(QWidget *parent) 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); + vector quantiles{ 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99 }; + metric_jpeg_decode_time_seconds.init(quantiles, 60.0); + global_metrics.add("jpeg_decode_time_seconds", &metric_jpeg_decode_time_seconds); }); } @@ -415,6 +436,7 @@ void JPEGFrameView::paintGL() overlay_input->set_width(overlay_width); overlay_input->set_height(overlay_height); overlay_input->set_pixel_data(overlay_image->bits()); + overlay_input_needs_refresh = false; } glViewport(gl_width - overlay_width, 0, overlay_width, overlay_height); overlay_chain->render_to_screen(); @@ -454,10 +476,25 @@ void JPEGFrameView::set_overlay(const string &text) return; } + // Figure out how large the texture needs to be. + { + QImage img(overlay_width, overlay_height, QImage::Format_Grayscale8); + QPainter painter(&img); + QFont font = painter.font(); + font.setPointSize(12); + QFontMetrics metrics(font); + overlay_base_width = lrint(metrics.boundingRect(QString::fromStdString(text)).width() + 8.0); + overlay_base_height = lrint(metrics.height()); + } + float dpr = QGuiApplication::primaryScreen()->devicePixelRatio(); overlay_width = lrint(overlay_base_width * dpr); overlay_height = lrint(overlay_base_height * dpr); + // Work around OpenGL alignment issues. + while (overlay_width % 4 != 0) ++overlay_width; + + // Now do the actual drawing. overlay_image.reset(new QImage(overlay_width, overlay_height, QImage::Format_Grayscale8)); overlay_image->setDevicePixelRatio(dpr); overlay_image->fill(0);