blob: 6b8c222e9b9e8221f0a3ba499e027a50b244fe23 [file]
/*
* Copyright (c) 2026 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef TEST_TESTSUPPORT_PENDULUM_FRAME_GENERATOR_H_
#define TEST_TESTSUPPORT_PENDULUM_FRAME_GENERATOR_H_
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include "api/scoped_refptr.h"
#include "api/test/frame_generator_interface.h"
#include "api/video/i420_buffer.h"
#include "test/testsupport/frame_reader.h"
namespace webrtc {
namespace test {
// A synthetic frame generator that crops and scales a high-detail static image
// along a smooth, erratic, non-repeating trajectory governed by double-pendulum
// chaotic physics with dynamic zoom and optional luma noise. Designed as an
// absolute stress test for video encoders.
class PendulumFrameGenerator : public FrameGeneratorInterface {
public:
struct Config {
// Path to an i420 static image file.
std::string source_image_path = "resources/difficult_photo_1850_1110.yuv";
Resolution source_resolution = {.width = 1850, .height = 1110};
// Target output frame resolution.
Resolution target_resolution = {.width = 1280, .height = 720};
// Target framerate (used for physics time step integration).
int fps = 30;
// Zoom limits (1.0 = maximum crop area fitting aspect ratio).
double min_zoom = 1.2;
double max_zoom = 3.0;
// Base zoom cycle frequency in cycles per second.
double zoom_speed = 0.3;
// Luma white noise amplitude (+/- noise_level added to pixel values).
// Set to 0 to disable noise.
int noise_level = 20;
};
explicit PendulumFrameGenerator(Config config);
~PendulumFrameGenerator() override = default;
void ChangeResolution(size_t width, size_t height) override;
VideoFrameData NextFrame() override;
scoped_refptr<I420Buffer> NextI420Frame();
FrameGeneratorInterface::Resolution GetResolution() const override;
std::optional<int> fps() const override { return config_.fps; }
void Reset();
private:
void StepPhysics(double dt);
void LoadOrGenerateSourceImage();
void ApplyNoise(I420Buffer* buffer);
Config config_;
scoped_refptr<I420Buffer> source_image_;
// Double pendulum state: angles (rad), angular velocities (rad/s)
double th1_ = 0.5;
double th2_ = 0.5;
double w1_ = 0.0;
double w2_ = 0.0;
double sim_time_ = 0.0;
// Zoom oscillation phase (rad)
double zoom_phase_ = 0.0;
// Fast PRNG state for additive luma noise
uint32_t prng_state_ = 123456789;
};
// Factory functions.
std::unique_ptr<PendulumFrameGenerator> CreatePendulumFrameGenerator(
const PendulumFrameGenerator::Config& config);
std::unique_ptr<FrameReader> CreatePendulumFrameReader(
const PendulumFrameGenerator::Config& config);
} // namespace test
} // namespace webrtc
#endif // TEST_TESTSUPPORT_PENDULUM_FRAME_GENERATOR_H_