From 4b286cabe961c426ce340a85167346012691d711 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 24 Apr 2016 23:45:55 +0200 Subject: [PATCH] Make QuickSyncEncoder get its textures from ResourcePool. This fixes a problem where the ResourcePool would not be aware that a given texture had been deleted (and a new one come back using the same texture number), and thus happily continue to give out cached FBOs from it, even though OpenGL had unlinked those FBOs when the texture was deleted. --- quicksync_encoder.cpp | 33 +++++++++++++++------------------ quicksync_encoder.h | 6 +++++- video_encoder.cpp | 9 +++++---- video_encoder.h | 7 ++++++- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/quicksync_encoder.cpp b/quicksync_encoder.cpp index 03bc706..5ebd454 100644 --- a/quicksync_encoder.cpp +++ b/quicksync_encoder.cpp @@ -1,6 +1,7 @@ //#include "sysdeps.h" #include "quicksync_encoder.h" +#include #include #include #include @@ -193,7 +194,7 @@ FrameReorderer::Frame FrameReorderer::get_first_frame() class QuickSyncEncoderImpl { public: - QuickSyncEncoderImpl(const std::string &filename, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); + QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); ~QuickSyncEncoderImpl(); void add_audio(int64_t pts, vector audio); bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex); @@ -270,6 +271,7 @@ private: map pending_video_frames; // under frame_queue_mutex map> pending_audio_frames; // under frame_queue_mutex + movit::ResourcePool *resource_pool; QSurface *surface; unique_ptr file_audio_encoder; @@ -1201,17 +1203,12 @@ int QuickSyncEncoderImpl::setup_encode() //glGenFramebuffers(SURFACE_NUM, fbos); for (i = 0; i < SURFACE_NUM; i++) { - glGenTextures(1, &gl_surfaces[i].y_tex); - glGenTextures(1, &gl_surfaces[i].cbcr_tex); - - if (!use_zerocopy) { - // Create Y image. - glBindTexture(GL_TEXTURE_2D, gl_surfaces[i].y_tex); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, frame_width, frame_height); - - // Create CbCr image. - glBindTexture(GL_TEXTURE_2D, gl_surfaces[i].cbcr_tex); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG8, frame_width / 2, frame_height / 2); + if (use_zerocopy) { + gl_surfaces[i].y_tex = resource_pool->create_2d_texture(GL_R8, 1, 1); + gl_surfaces[i].cbcr_tex = resource_pool->create_2d_texture(GL_RG8, 1, 1); + } else { + gl_surfaces[i].y_tex = resource_pool->create_2d_texture(GL_R8, frame_width, frame_height); + gl_surfaces[i].cbcr_tex = resource_pool->create_2d_texture(GL_RG8, frame_width / 2, frame_height / 2); // Generate a PBO to read into. It doesn't necessarily fit 1:1 with the VA-API // buffers, due to potentially differing pitch. @@ -1707,8 +1704,8 @@ int QuickSyncEncoderImpl::release_encode() glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glDeleteBuffers(1, &gl_surfaces[i].pbo); } - glDeleteTextures(1, &gl_surfaces[i].y_tex); - glDeleteTextures(1, &gl_surfaces[i].cbcr_tex); + resource_pool->release_2d_texture(gl_surfaces[i].y_tex); + resource_pool->release_2d_texture(gl_surfaces[i].cbcr_tex); } vaDestroyContext(va_dpy, context_id); @@ -1730,8 +1727,8 @@ namespace { } // namespace -QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) - : current_storage_frame(0), surface(surface), stream_audio_encoder(stream_audio_encoder), x264_encoder(x264_encoder), stream_mux(stream_mux), frame_width(width), frame_height(height) +QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) + : current_storage_frame(0), resource_pool(resource_pool), surface(surface), stream_audio_encoder(stream_audio_encoder), x264_encoder(x264_encoder), stream_mux(stream_mux), frame_width(width), frame_height(height) { file_audio_encoder.reset(new AudioEncoder(AUDIO_OUTPUT_CODEC_NAME, DEFAULT_AUDIO_OUTPUT_BIT_RATE)); open_output_file(filename); @@ -2173,8 +2170,8 @@ void QuickSyncEncoderImpl::encode_frame(QuickSyncEncoderImpl::PendingFrame frame } // Proxy object. -QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) - : impl(new QuickSyncEncoderImpl(filename, surface, va_display, width, height, stream_mux, stream_audio_encoder, x264_encoder)) {} +QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) + : impl(new QuickSyncEncoderImpl(filename, resource_pool, surface, va_display, width, height, stream_mux, stream_audio_encoder, x264_encoder)) {} // Must be defined here because unique_ptr<> destructor needs to know the impl. QuickSyncEncoder::~QuickSyncEncoder() {} diff --git a/quicksync_encoder.h b/quicksync_encoder.h index 40bf15e..4f2bca5 100644 --- a/quicksync_encoder.h +++ b/quicksync_encoder.h @@ -42,12 +42,16 @@ class QuickSyncEncoderImpl; class QSurface; class X264Encoder; +namespace movit { +class ResourcePool; +} // namespace movit + // This is just a pimpl, because including anything X11-related in a .h file // tends to trip up Qt. All the real logic is in QuickSyncEncoderImpl, defined in the // .cpp file. class QuickSyncEncoder { public: - QuickSyncEncoder(const std::string &filename, QSurface *surface, const std::string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); + QuickSyncEncoder(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const std::string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); ~QuickSyncEncoder(); void add_audio(int64_t pts, std::vector audio); diff --git a/video_encoder.cpp b/video_encoder.cpp index 2576529..910d4b7 100644 --- a/video_encoder.cpp +++ b/video_encoder.cpp @@ -12,6 +12,7 @@ #include "x264_encoder.h" using namespace std; +using namespace movit; namespace { @@ -34,8 +35,8 @@ string generate_local_dump_filename(int frame) } // namespace -VideoEncoder::VideoEncoder(QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd) - : surface(surface), va_display(va_display), width(width), height(height), httpd(httpd) +VideoEncoder::VideoEncoder(ResourcePool *resource_pool, QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd) + : resource_pool(resource_pool), surface(surface), va_display(va_display), width(width), height(height), httpd(httpd) { open_output_stream(); @@ -51,7 +52,7 @@ VideoEncoder::VideoEncoder(QSurface *surface, const std::string &va_display, int } string filename = generate_local_dump_filename(/*frame=*/0); - quicksync_encoder.reset(new QuickSyncEncoder(filename, surface, va_display, width, height, stream_mux.get(), stream_audio_encoder.get(), x264_encoder.get())); + quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, stream_mux.get(), stream_audio_encoder.get(), x264_encoder.get())); } VideoEncoder::~VideoEncoder() @@ -65,7 +66,7 @@ void VideoEncoder::do_cut(int frame) string filename = generate_local_dump_filename(frame); printf("Starting new recording: %s\n", filename.c_str()); quicksync_encoder->shutdown(); - quicksync_encoder.reset(new QuickSyncEncoder(filename, surface, va_display, width, height, stream_mux.get(), stream_audio_encoder.get(), x264_encoder.get())); + quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, stream_mux.get(), stream_audio_encoder.get(), x264_encoder.get())); } void VideoEncoder::add_audio(int64_t pts, std::vector audio) diff --git a/video_encoder.h b/video_encoder.h index 81c4899..bb1be55 100644 --- a/video_encoder.h +++ b/video_encoder.h @@ -20,9 +20,13 @@ class QSurface; class QuickSyncEncoder; class X264Encoder; +namespace movit { +class ResourcePool; +} // namespace movit + class VideoEncoder : public KeyFrameSignalReceiver { public: - VideoEncoder(QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd); + VideoEncoder(movit::ResourcePool *resource_pool, QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd); ~VideoEncoder(); void add_audio(int64_t pts, std::vector audio); @@ -43,6 +47,7 @@ private: int write_packet(uint8_t *buf, int buf_size); std::unique_ptr quicksync_encoder; + movit::ResourcePool *resource_pool; QSurface *surface; std::string va_display; int width, height; -- 2.39.2