+ struct VAResources {
+ unsigned width, height;
+ VASurfaceID surface;
+ VAContextID context;
+ VABufferID data_buffer;
+ VAImage image;
+ };
+
+ // RAII wrapper to release VAResources on return (even on error).
+ class ReleaseVAResources {
+ public:
+ ReleaseVAResources() : committed(true) {}
+
+ ReleaseVAResources(MJPEGEncoder *mjpeg, const VAResources &resources)
+ : mjpeg(mjpeg), resources(resources) {}
+
+ ReleaseVAResources(ReleaseVAResources &) = delete;
+
+ ReleaseVAResources(ReleaseVAResources &&other)
+ : mjpeg(other.mjpeg), resources(other.resources), committed(other.committed) {
+ other.commit();
+ }
+
+ ReleaseVAResources &operator= (ReleaseVAResources &) = delete;
+
+ ReleaseVAResources &operator= (ReleaseVAResources &&other) {
+ if (!committed) {
+ mjpeg->release_va_resources(resources);
+ }
+ mjpeg = other.mjpeg;
+ resources = std::move(other.resources);
+ committed = other.committed;
+ other.commit();
+ return *this;
+ }
+
+ ~ReleaseVAResources()
+ {
+ if (!committed) {
+ mjpeg->release_va_resources(resources);
+ }
+ }
+
+ void commit() { committed = true; }
+
+ private:
+ MJPEGEncoder *mjpeg = nullptr;
+ VAResources resources;
+ bool committed = false;
+ };
+