X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fpbo_frame_allocator.h;h=cff50aa6310036fe320f2f2021c9b445ec7e7a75;hb=a0e57ec99e9dfdd7e79bcf21e8c996dc43b6cb49;hp=eead7f4a32f979c8203a184f535862c6f1dab0e2;hpb=392f9d1ccb835c05a3874c4bea163788b2c37024;p=nageru diff --git a/nageru/pbo_frame_allocator.h b/nageru/pbo_frame_allocator.h index eead7f4..cff50aa 100644 --- a/nageru/pbo_frame_allocator.h +++ b/nageru/pbo_frame_allocator.h @@ -4,13 +4,21 @@ #include #include #include +#include +#include #include #include +#include #include +#include #include #include "bmusb/bmusb.h" +#include "mjpeg_encoder.h" +#include "shared/va_resource_pool.h" + +class MJPEGEncoder; // An allocator that allocates straight into OpenGL pinned memory. // Meant for video frames only. We use a queue rather than a stack, @@ -22,14 +30,28 @@ public: PBOFrameAllocator(bmusb::PixelFormat pixel_format, size_t frame_size, GLuint width, GLuint height, + unsigned card_index, + MJPEGEncoder *mjpeg_encoder = nullptr, size_t num_queued_frames = 16, GLenum buffer = GL_PIXEL_UNPACK_BUFFER_ARB, GLenum permissions = GL_MAP_WRITE_BIT, GLenum map_bits = GL_MAP_FLUSH_EXPLICIT_BIT); ~PBOFrameAllocator() override; Frame alloc_frame() override; + Frame create_frame(size_t width, size_t height, size_t stride) override; void release_frame(Frame frame) override; + // NOTE: Does not check the buffer types; they are just assumed to be compatible. + void reconfigure(bmusb::PixelFormat pixel_format, + size_t frame_size, + GLuint width, GLuint height, + unsigned card_index, + MJPEGEncoder *mjpeg_encoder = nullptr, + size_t num_queued_frames = 16, + GLenum buffer = GL_PIXEL_UNPACK_BUFFER_ARB, + GLenum permissions = GL_MAP_WRITE_BIT, + GLenum map_bits = GL_MAP_FLUSH_EXPLICIT_BIT); + struct Userdata { GLuint pbo; @@ -52,17 +74,57 @@ public: GLuint last_v210_width[2]; // PixelFormat_10BitYCbCr. bool last_interlaced, last_has_signal, last_is_connected; unsigned last_frame_rate_nom, last_frame_rate_den; + bool has_last_subtitle = false; + std::string last_subtitle; + movit::RGBTriplet white_balance{1.0f, 1.0f, 1.0f}; + + // These are the source of the “data_copy” member in Frame, + // used for MJPEG encoding. There are three possibilities: + // + // - MJPEG encoding is not active (at all, or for this specific + // card). Then data_copy is nullptr, and what's in here + // does not matter at all. + // - We can encode directly into VA-API buffers (ie., VA-API + // is active, and nothing strange happened wrt. strides); + // then va_resources, va_resources_release and va_image + // are fetched from MJPEGEncoder at create_frame() and released + // back when the frame is uploaded (or would have been). + // In this case, data_copy points into the mapped VAImage. + // - If not, data_copy points to data_copy_malloc, and is copied + // from there into VA-API buffers (by MJPEGEncoder) if needed. + enum { FROM_MALLOC, FROM_VA_API } data_copy_current_src; + uint8_t *data_copy_malloc; + VAResourcePool::VAResources va_resources; + ReleaseVAResources va_resources_release; + + int generation; }; private: - void init_frame(size_t frame_idx, size_t frame_size, GLuint width, GLuint height, GLenum permissions, GLenum map_bits); + void init_frame(size_t frame_idx, size_t frame_size, GLuint width, GLuint height, GLenum permissions, GLenum map_bits, int generation); void destroy_frame(Frame *frame); + unsigned card_index; + MJPEGEncoder *mjpeg_encoder; bmusb::PixelFormat pixel_format; std::mutex freelist_mutex; std::queue freelist; GLenum buffer; std::unique_ptr userdata; + + // Used only for reconfigure(), to check whether we can do without. + size_t frame_size; + size_t num_queued_frames; + GLuint width, height; + GLenum permissions; + GLenum map_bits; + int generation = 0; // Under freelist_mutex. + + struct LingeringGeneration { + std::unique_ptr userdata; + size_t num_frames_left; + }; + std::map lingering_generations; }; #endif // !defined(_PBO_FRAME_ALLOCATOR)