]> git.sesse.net Git - nageru/blob - shared/va_resource_pool.h
Move VAResourcePool into a shared class between MJPEGEncoder in Nageru and the VA...
[nageru] / shared / va_resource_pool.h
1 #ifndef _VA_RESOURCE_POOL
2 #define _VA_RESOURCE_POOL 1
3
4 #include <inttypes.h>
5 #include <va/va.h>
6
7 #include <list>
8 #include <mutex>
9
10 #define CHECK_VASTATUS(va_status, func) \
11         if (va_status != VA_STATUS_SUCCESS) { \
12                 fprintf(stderr, "%s:%d (%s) failed: %s\n", __func__, __LINE__, func, vaErrorStr(va_status)); \
13                 exit(1); \
14         }
15
16 #define CHECK_VASTATUS_RET(va_status, func) \
17         if (va_status != VA_STATUS_SUCCESS) { \
18                 fprintf(stderr, "%s:%d (%s) failed with %d\n", __func__, __LINE__, func, va_status); \
19                 return nullptr; \
20         }
21
22 class VAResourcePool {
23 public:
24         struct VAResources {
25                 unsigned width, height;
26                 uint32_t fourcc;
27                 VASurfaceID surface;
28                 VAContextID context;
29                 VABufferID data_buffer;
30                 VAImage image;
31         };
32
33         VAResourcePool(VADisplay va_dpy, VAImageFormat uyvy_format, VAImageFormat nv12_format, VAConfigID config_id_422, VAConfigID config_id_420, bool with_data_buffer)
34                 : va_dpy(va_dpy),
35                   uyvy_format(uyvy_format),
36                   nv12_format(nv12_format),
37                   config_id_422(config_id_422),
38                   config_id_420(config_id_420),
39                   with_data_buffer(with_data_buffer) {}
40         VAResources get_va_resources(unsigned width, unsigned height, uint32_t fourcc);
41         void release_va_resources(VAResources resources);
42
43 private:
44         const VADisplay va_dpy;
45         VAImageFormat uyvy_format, nv12_format;
46         const VAConfigID config_id_422, config_id_420;
47         const bool with_data_buffer;
48
49         std::mutex mu;
50         std::list<VAResources> freelist;  // Under mu.
51 };
52
53 // RAII wrapper to release VAResources on return (even on error).
54 class ReleaseVAResources {
55 public:
56         ReleaseVAResources() : committed(true) {}
57
58         ReleaseVAResources(VAResourcePool *pool, const VAResourcePool::VAResources &resources)
59                 : pool(pool), resources(resources) {}
60
61         ReleaseVAResources(ReleaseVAResources &) = delete;
62
63         ReleaseVAResources(ReleaseVAResources &&other)
64                 : pool(other.pool), resources(other.resources), committed(other.committed) {
65                 other.commit();
66         }
67
68         ReleaseVAResources &operator= (ReleaseVAResources &) = delete;
69
70         ReleaseVAResources &operator= (ReleaseVAResources &&other) {
71                 if (!committed) {
72                         pool->release_va_resources(resources);
73                 }
74                 pool = other.pool;
75                 resources = std::move(other.resources);
76                 committed = other.committed;
77                 other.commit();
78                 return *this;
79         }
80
81         ~ReleaseVAResources()
82         {
83                 if (!committed) {
84                         pool->release_va_resources(resources);
85                 }
86         }
87
88         void commit() { committed = true; }
89
90 private:
91         VAResourcePool *pool = nullptr;
92         VAResourcePool::VAResources resources;
93         bool committed = false;
94 };
95
96 #endif  // !defined(_VA_RESOURCE_POOL)