// Fire up a thread to update the image every second.
// We could do inotify, but this is good enough for now.
-// TODO: These don't really quit, ever. Should they?
void ImageInput::update_thread_func(const std::string &filename, const timespec &first_modified)
{
timespec last_modified = first_modified;
for ( ;; ) {
sleep(1);
+ if (threads_should_quit) {
+ return;
+ }
+
if (stat(filename.c_str(), &buf) != 0) {
fprintf(stderr, "%s: Couldn't check for new version, leaving the old in place.\n", filename.c_str());
continue;
}
}
+void ImageInput::shutdown_updaters()
+{
+ // TODO: Kick these out of the sleep before one second?
+ threads_should_quit = true;
+
+ for (auto &it : update_threads) {
+ it.second.join();
+ }
+}
+
mutex ImageInput::all_images_lock;
map<string, shared_ptr<const ImageInput::Image>> ImageInput::all_images;
map<string, thread> ImageInput::update_threads;
+volatile bool ImageInput::threads_should_quit = false;
std::string effect_type_id() const override { return "ImageInput"; }
void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num) override;
-
+ static void shutdown_updaters();
+
private:
struct Image {
std::unique_ptr<uint8_t[]> pixels;
static std::mutex all_images_lock;
static std::map<std::string, std::shared_ptr<const Image>> all_images;
static std::map<std::string, std::thread> update_threads;
+ static volatile bool threads_should_quit;
};
#endif // !defined(_IMAGE_INPUT_H)
#include "context.h"
#include "flags.h"
+#include "image_input.h"
#include "mainwindow.h"
#include "mixer.h"
global_mixer->quit();
mainWindow.mixer_shutting_down();
delete global_mixer;
+ ImageInput::shutdown_updaters();
return rc;
}
{
unique_lock<mutex> lock(audio_mutex);
- audio_task_queue_changed.wait(lock, [this]{ return !audio_task_queue.empty(); });
+ audio_task_queue_changed.wait(lock, [this]{ return should_quit || !audio_task_queue.empty(); });
+ if (should_quit) {
+ return;
+ }
task = audio_task_queue.front();
audio_task_queue.pop();
}
void Mixer::quit()
{
should_quit = true;
+ audio_task_queue_changed.notify_one();
mixer_thread.join();
audio_thread.join();
}
while (quicksync_encoders_in_shutdown.load() > 0) {
usleep(10000);
}
- close_output_stream();
}
void VideoEncoder::do_cut(int frame)
stream_mux_header.clear();
}
-void VideoEncoder::close_output_stream()
-{
- stream_mux.reset();
-}
-
int VideoEncoder::write_packet_thunk(void *opaque, uint8_t *buf, int buf_size)
{
VideoEncoder *video_encoder = (VideoEncoder *)opaque;
private:
void open_output_stream();
- void close_output_stream();
static int write_packet_thunk(void *opaque, uint8_t *buf, int buf_size);
int write_packet(uint8_t *buf, int buf_size);