]> git.sesse.net Git - nageru/blobdiff - x264_speed_control.h
Release Nageru 1.7.2.
[nageru] / x264_speed_control.h
index b498826830d20ba649e1e37724da5824f6189ca6..bd58dcbf8773c6624706f23e6775ce2bc758bf0a 100644 (file)
 // one does not need to patch x264 to use it in Nageru. It still could do with
 // some cleanup, but it's much, much better than just using a static preset.
 
-#include <stdio.h>
 #include <stdint.h>
-#include <string.h>
-#include <math.h>
+#include <atomic>
+#include <chrono>
+#include <functional>
 
 extern "C" {
-#include "x264.h"
+#include <x264.h>
 }
 
+#include "metrics.h"
+#include "x264_dynamic.h"
+
 class X264SpeedControl {
 public:
        // x264: Encoding object we are using; must be opened. Assumed to be
@@ -80,20 +83,32 @@ public:
        void before_frame(float new_buffer_fill, int new_buffer_size, float f_uspf);
        void after_frame();
 
+       // x264 seemingly has an issue where x264_encoder_reconfig() is not reflected
+       // immediately in x264_encoder_parameters(). Since speed control keeps calling
+       // those two all the time, any changes you make outside X264SpeedControl
+       // could be overridden. Thus, to make changes to encoder parameters, you should
+       // instead set a function here, which will be called every time parameters
+       // are modified.
+       void set_config_override_function(std::function<void(x264_param_t *)> override_func)
+       {
+               this->override_func = override_func;
+       }
+
 private:
        void set_buffer_size(int new_buffer_size);
        int dither_preset(float f);
        void apply_preset(int new_preset);
-       int64_t mdate();  // Current time in microseconds.
+
+       X264Dynamic dyn;
 
        // Not owned by us.
        x264_t *x264;
 
        float f_speed;
 
-       // all times are in usec
-       int64_t timestamp;   // when was speedcontrol last invoked
-       int64_t cpu_time_last_frame = 0;    // time spent encoding the previous frame
+       // all times that are not std::chrono::* are in usec
+       std::chrono::steady_clock::time_point timestamp;   // when was speedcontrol last invoked
+       std::chrono::steady_clock::duration cpu_time_last_frame{std::chrono::seconds{0}};   // time spent encoding the previous frame
        int64_t buffer_size; // assumed application-side buffer of frames to be streamed (measured in microseconds),
        int64_t buffer_fill; //   where full = we don't have to hurry
        int64_t compensation_period; // how quickly we try to return to the target buffer fullness
@@ -105,7 +120,6 @@ private:
        float dither = 0.0f;
 
        bool first = true;
-       bool buffer_complete = false;
 
        struct
        {
@@ -113,4 +127,13 @@ private:
                double avg_preset;
                int den;
        } stat;
+
+       std::function<void(x264_param_t *)> override_func = nullptr;
+
+       // Metrics.
+       Histogram metric_x264_speedcontrol_preset_used_frames;
+       std::atomic<double> metric_x264_speedcontrol_buffer_available_seconds{0.0};
+       std::atomic<double> metric_x264_speedcontrol_buffer_size_seconds{0.0};
+       std::atomic<int64_t> metric_x264_speedcontrol_idle_frames{0};
+       std::atomic<int64_t> metric_x264_speedcontrol_late_frames{0};
 };