| 371 | } |
| 372 | |
| 373 | static TimingStats RunCpuBenchmark(const BenchmarkOptions& options, const QImage& overlay_image) { |
| 374 | TimingStats stats; |
| 375 | const auto total_start = Clock::now(); |
| 376 | |
| 377 | FFmpegReader reader(options.video_path); |
| 378 | reader.Open(); |
| 379 | |
| 380 | const int64_t frame_limit = std::min<int64_t>(options.max_frames, reader.info.video_length); |
| 381 | if (frame_limit <= 0) { |
| 382 | reader.Close(); |
| 383 | return stats; |
| 384 | } |
| 385 | |
| 386 | RenderLayout layout; |
| 387 | QImage prepared_overlay; |
| 388 | bool overlay_ready = false; |
| 389 | for (int64_t frame_number = 1; frame_number <= frame_limit; ++frame_number) { |
| 390 | const auto decode_start = Clock::now(); |
| 391 | std::shared_ptr<Frame> source_frame = reader.GetFrame(frame_number); |
| 392 | const auto decode_end = Clock::now(); |
| 393 | stats.decode_ms += std::chrono::duration<double, std::milli>(decode_end - decode_start).count(); |
| 394 | |
| 395 | const auto composite_start = Clock::now(); |
| 396 | const std::shared_ptr<QImage> source_image = source_frame->GetImage(); |
| 397 | if (!overlay_ready) { |
| 398 | layout = ComputeRenderLayout(options, source_image->width(), source_image->height()); |
| 399 | prepared_overlay = PrepareOverlayImage(options, layout, overlay_image); |
| 400 | overlay_ready = true; |
| 401 | } |
| 402 | QImage output(layout.output_width, layout.output_height, QImage::Format_RGBA8888_Premultiplied); |
| 403 | output.fill(QColor("#101418")); |
| 404 | |
| 405 | QPainter painter(&output); |
| 406 | painter.setRenderHint(QPainter::SmoothPixmapTransform, true); |
| 407 | painter.setRenderHint(QPainter::Antialiasing, true); |
| 408 | |
| 409 | painter.drawImage(output.rect(), *source_image); |
| 410 | painter.setOpacity(1.0); |
| 411 | painter.drawImage(layout.overlay_x, layout.overlay_y, prepared_overlay); |
| 412 | painter.end(); |
| 413 | SaveDumpImage(options, "CPU->CPU", static_cast<int>(frame_number), output); |
| 414 | |
| 415 | const auto composite_end = Clock::now(); |
| 416 | stats.composite_ms += std::chrono::duration<double, std::milli>(composite_end - composite_start).count(); |
| 417 | stats.frames++; |
| 418 | } |
| 419 | |
| 420 | reader.Close(); |
| 421 | stats.total_ms = std::chrono::duration<double, std::milli>(Clock::now() - total_start).count(); |
| 422 | return stats; |
| 423 | } |
| 424 | |
| 425 | static TimingStats RunCpuCompositeBenchmark(const BenchmarkOptions& options, const QImage& overlay_image, |
| 426 | DecodeKind decode_kind, bool& used_hw_decode); |
no test coverage detected