+++ /dev/null
-#include "disk_space_estimator.h"
-
-#include "shared/timebase.h"
-
-#include <memory>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-
-DiskSpaceEstimator::DiskSpaceEstimator(DiskSpaceEstimator::callback_t callback)
- : callback(callback)
-{
-}
-
-void DiskSpaceEstimator::report_write(const std::string &filename, size_t bytes, uint64_t pts)
-{
- // Reject points that are out-of-order (happens with B-frames).
- if (!measure_points.empty() && pts <= measure_points.back().pts) {
- return;
- }
-
- // Remove too old points.
- while (measure_points.size() > 1 && measure_points.front().pts + window_length < pts) {
- measure_points.pop_front();
- }
-
- total_size += bytes;
-
- struct statfs fst;
- if (statfs(filename.c_str(), &fst) == -1) {
- perror(filename.c_str());
- return;
- }
-
- off_t free_bytes = off_t(fst.f_bavail) * fst.f_frsize;
-
- if (!measure_points.empty()) {
- double bytes_per_second = double(total_size - measure_points.front().size) /
- (pts - measure_points.front().pts) * TIMEBASE;
- double seconds_left = free_bytes / bytes_per_second;
-
- // Only report every second, since updating the UI can be expensive.
- if (last_pts_reported == 0 || pts - last_pts_reported >= TIMEBASE) {
- callback(free_bytes, seconds_left);
- last_pts_reported = pts;
- }
- }
-
- measure_points.push_back({ pts, total_size });
-}
-
-DiskSpaceEstimator *global_disk_space_estimator = nullptr; // Created in MainWindow::MainWindow().
+++ /dev/null
-#ifndef _DISK_SPACE_ESTIMATOR_H
-#define _DISK_SPACE_ESTIMATOR_H
-
-// A class responsible for measuring how much disk there is left when we
-// store our video to disk, and how much recording time that equates to.
-// It gets callbacks from the Mux writing the stream to disk (which also
-// knows which filesystem the file is going to), makes its calculations,
-// and calls back to the MainWindow, which shows it to the user.
-//
-// The bitrate is measured over a simple 30-second sliding window.
-
-#include "shared/timebase.h"
-
-#include <deque>
-#include <functional>
-#include <stdint.h>
-#include <string>
-#include <sys/types.h>
-
-class DiskSpaceEstimator {
-public:
- typedef std::function<void(off_t free_bytes, double estimated_seconds_left)> callback_t;
- DiskSpaceEstimator(callback_t callback);
-
- // Report that a video frame with the given pts and size has just been
- // written (possibly appended) to the given file.
- //
- // <pts> is taken to be in TIMEBASE units (see shared/timebase.h).
- void report_write(const std::string &filename, size_t bytes, uint64_t pts);
-
-private:
- static constexpr int64_t window_length = 30 * TIMEBASE;
-
- callback_t callback;
-
- struct MeasurePoint {
- uint64_t pts;
- off_t size;
- };
- std::deque<MeasurePoint> measure_points;
- uint64_t last_pts_reported = 0;
- off_t total_size = 0;
-};
-
-extern DiskSpaceEstimator *global_disk_space_estimator;
-
-#endif // !defined(_DISK_SPACE_ESTIMATOR_H)
#include "clip_list.h"
#include "shared/context.h"
#include "defs.h"
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
#include "shared/ffmpeg_raii.h"
#include "flags.h"
#include "frame_on_disk.h"
#include "mainwindow.h"
#include "clip_list.h"
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
#include "flags.h"
#include "frame_on_disk.h"
#include "player.h"
# All the other files.
srcs += ['main.cpp', 'player.cpp', 'video_stream.cpp', 'chroma_subsampler.cpp']
-srcs += ['vaapi_jpeg_decoder.cpp', 'db.cpp', 'disk_space_estimator.cpp', 'ycbcr_converter.cpp', 'flags.cpp']
+srcs += ['vaapi_jpeg_decoder.cpp', 'db.cpp', 'ycbcr_converter.cpp', 'flags.cpp']
srcs += ['mainwindow.cpp', 'jpeg_frame_view.cpp', 'clip_list.cpp', 'frame_on_disk.cpp']
srcs += moc_files
srcs += proto_generated
#include "clickable_label.h"
#include "context_menus.h"
#include "correlation_meter.h"
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
#include "ellipsis_label.h"
#include "flags.h"
#include "glwidget.h"
# Mixer objects.
srcs += ['chroma_subsampler.cpp', 'v210_converter.cpp', 'mixer.cpp', 'pbo_frame_allocator.cpp',
'theme.cpp', 'image_input.cpp', 'alsa_output.cpp',
- 'disk_space_estimator.cpp', 'timecode_renderer.cpp', 'tweaked_inputs.cpp']
+ 'timecode_renderer.cpp', 'tweaked_inputs.cpp']
# Streaming and encoding objects (largely the set that is shared between Nageru and Kaeru).
stream_srcs = ['quicksync_encoder.cpp', 'x264_encoder.cpp', 'x264_dynamic.cpp', 'x264_speed_control.cpp', 'video_encoder.cpp',
#include "decklink_capture.h"
#include "decklink_output.h"
#include "defs.h"
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
#include "ffmpeg_capture.h"
#include "flags.h"
#include "input_mapping.h"
#include "audio_encoder.h"
#include "shared/context.h"
#include "defs.h"
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
#include "shared/ffmpeg_raii.h"
#include "flags.h"
#include "shared/mux.h"
lock_guard<mutex> lock(file_audio_encoder_mutex);
AVCodecParametersWithDeleter audio_codecpar = file_audio_encoder->get_codec_parameters();
file_mux.reset(new Mux(avctx, frame_width, frame_height, Mux::CODEC_H264, video_extradata, audio_codecpar.get(), get_color_space(global_flags.ycbcr_rec709_coefficients), Mux::WITH_AUDIO, TIMEBASE,
- std::bind(&DiskSpaceEstimator::report_write, disk_space_estimator, filename, _1),
+ std::bind(&DiskSpaceEstimator::report_append, disk_space_estimator, filename, _1),
Mux::WRITE_BACKGROUND,
{ ¤t_file_mux_metrics, &total_mux_metrics }));
}
-#include "disk_space_estimator.h"
+#include "shared/disk_space_estimator.h"
+#include <memory>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/statfs.h>
-#include <memory>
#include "shared/metrics.h"
#include "shared/timebase.h"
+using namespace std;
+
DiskSpaceEstimator::DiskSpaceEstimator(DiskSpaceEstimator::callback_t callback)
: callback(callback)
{
global_metrics.add("disk_free_bytes", &metric_disk_free_bytes, Metrics::TYPE_GAUGE);
}
-void DiskSpaceEstimator::report_write(const std::string &filename, uint64_t pts)
+void DiskSpaceEstimator::report_write(const string &filename, off_t bytes, uint64_t pts)
+{
+ total_size += bytes;
+ report_write_internal(filename, total_size, pts);
+}
+
+void DiskSpaceEstimator::report_append(const string &filename, uint64_t pts)
{
if (filename != last_filename) {
last_filename = filename;
measure_points.clear();
}
+ struct stat st;
+ if (stat(filename.c_str(), &st) == -1) {
+ perror(filename.c_str());
+ return;
+ }
+
+ report_write_internal(filename, st.st_size, pts);
+}
+
+void DiskSpaceEstimator::report_write_internal(const string &filename, off_t file_size, uint64_t pts)
+{
// Reject points that are out-of-order (happens with B-frames).
- if (!measure_points.empty() && pts < measure_points.back().pts) {
+ if (!measure_points.empty() && pts <= measure_points.back().pts) {
return;
}
measure_points.pop_front();
}
- struct stat st;
- if (stat(filename.c_str(), &st) == -1) {
- perror(filename.c_str());
- return;
- }
-
struct statfs fst;
if (statfs(filename.c_str(), &fst) == -1) {
perror(filename.c_str());
metric_disk_free_bytes = free_bytes;
if (!measure_points.empty()) {
- double bytes_per_second = double(st.st_size - measure_points.front().size) /
+ double bytes_per_second = double(file_size - measure_points.front().size) /
(pts - measure_points.front().pts) * TIMEBASE;
double seconds_left = free_bytes / bytes_per_second;
}
}
- measure_points.push_back({ pts, st.st_size });
+ measure_points.push_back({ pts, file_size });
}
DiskSpaceEstimator *global_disk_space_estimator = nullptr; // Created in MainWindow::MainWindow().
//
// The bitrate is measured over a simple 30-second sliding window.
-#include <stdint.h>
-#include <sys/types.h>
#include <atomic>
#include <deque>
#include <functional>
+#include <stdint.h>
#include <string>
+#include <sys/types.h>
#include "shared/timebase.h"
-class DiskSpaceEstimator
-{
+class DiskSpaceEstimator {
public:
typedef std::function<void(off_t free_bytes, double estimated_seconds_left)> callback_t;
DiskSpaceEstimator(callback_t callback);
+ // Report that a video frame with the given pts and size has just been
+ // written (possibly appended) to the given file.
+ //
+ // <pts> is taken to be in TIMEBASE units (see shared/timebase.h).
+ void report_write(const std::string &filename, off_t bytes, uint64_t pts);
+
// Report that a video frame with the given pts has just been written
// to the given file, so the estimator should stat the file and see
// by how much it grew since last time. Called by the Mux object
//
// If the filename changed since last time, the estimation is reset.
// <pts> is taken to be in TIMEBASE units (see shared/timebase.h).
- void report_write(const std::string &filename, uint64_t pts);
+ //
+ // You should probably not mix this and report_write() on the same
+ // object. Really, report_write() matches Futatabi's controlled writes
+ // to a custom format, and report_append() matches Nageru's use of Mux
+ // (where we don't see the bytes flowing past).
+ void report_append(const std::string &filename, uint64_t pts);
private:
static constexpr int64_t window_length = 30 * TIMEBASE;
+ void report_write_internal(const std::string &filename, off_t file_size, uint64_t pts);
+
callback_t callback;
- std::string last_filename;
struct MeasurePoint {
uint64_t pts;
std::deque<MeasurePoint> measure_points;
uint64_t last_pts_reported = 0;
+ off_t total_size = 0; // For report_write().
+ std::string last_filename; // For report_append().
+
// Metrics.
std::atomic<int64_t> metric_disk_free_bytes{-1};
};
qt5deps = dependency('qt5', modules: ['OpenGL'])
libmicrohttpddep = dependency('libmicrohttpd')
-srcs = ['memcpy_interleaved.cpp', 'metacube2.cpp', 'ffmpeg_raii.cpp', 'mux.cpp', 'metrics.cpp', 'context.cpp', 'httpd.cpp']
+srcs = ['memcpy_interleaved.cpp', 'metacube2.cpp', 'ffmpeg_raii.cpp', 'mux.cpp', 'metrics.cpp', 'context.cpp', 'httpd.cpp', 'disk_space_estimator.cpp']
shared = static_library('shared', srcs, include_directories: top_include, dependencies: [qt5deps, libmicrohttpddep])
shareddep = declare_dependency(
include_directories: top_include,