+void ImageInput::set_gl_state(GLuint glsl_program_num, const string& prefix, unsigned *sampler_num)
+{
+ // See if the background thread has given us a new version of our image.
+ // Note: The old version might still be lying around in other ImageInputs
+ // (in fact, it's likely), but at least the total amount of memory used
+ // is bounded. Currently we don't even share textures between them,
+ // so there's a fair amount of OpenGL memory waste anyway (the cache
+ // is mostly there to save startup time, not RAM).
+ {
+ unique_lock<mutex> lock(all_images_lock);
+ if (all_images[pathname] != current_image) {
+ current_image = all_images[pathname];
+ set_pixel_data(current_image->pixels.get());
+ }
+ }
+ movit::FlatInput::set_gl_state(glsl_program_num, prefix, sampler_num);
+}
+
+shared_ptr<const ImageInput::Image> ImageInput::load_image(const string &pathname)
+{
+ unique_lock<mutex> lock(all_images_lock); // Held also during loading.
+ if (all_images.count(pathname)) {
+ return all_images[pathname];
+ }
+
+ all_images[pathname] = load_image_raw(pathname);
+ timespec first_modified = all_images[pathname]->last_modified;
+ update_threads[pathname] =
+ thread(bind(update_thread_func, pathname, first_modified));
+
+ return all_images[pathname];
+}
+
+shared_ptr<const ImageInput::Image> ImageInput::load_image_raw(const string &pathname)
+{
+ // Note: Call before open, not after; otherwise, there's a race.
+ // (There is now, too, but it tips the correct way. We could use fstat()
+ // if we had the file descriptor.)
+ struct stat buf;
+ if (stat(pathname.c_str(), &buf) != 0) {
+ fprintf(stderr, "%s: Error stat-ing file\n", pathname.c_str());
+ return nullptr;
+ }
+ timespec last_modified = buf.st_mtim;
+
+ auto format_ctx = avformat_open_input_unique(pathname.c_str(), nullptr, nullptr);
+ if (format_ctx == nullptr) {
+ fprintf(stderr, "%s: Error opening file\n", pathname.c_str());
+ return nullptr;
+ }
+
+ if (avformat_find_stream_info(format_ctx.get(), nullptr) < 0) {
+ fprintf(stderr, "%s: Error finding stream info\n", pathname.c_str());
+ return nullptr;