diff options
-rw-r--r-- | capture.c | 10 | ||||
-rw-r--r-- | encode.c | 12 | ||||
-rw-r--r-- | gpu.c | 180 | ||||
-rw-r--r-- | gpu.h | 24 | ||||
-rw-r--r-- | main.c | 12 |
5 files changed, 123 insertions, 115 deletions
@@ -135,7 +135,8 @@ const struct GpuFrame* CaptureContextGetFrame( return NULL; if (capture_context->gpu_frame) { - GpuFrameDestroy(capture_context->gpu_frame); + GpuContextDestroyFrame(capture_context->gpu_context, + capture_context->gpu_frame); capture_context->gpu_frame = NULL; } @@ -155,7 +156,7 @@ const struct GpuFrame* CaptureContextGetFrame( planes[nplanes].modifier = drm_mode_fb_cmd2.modifier[nplanes]; } - capture_context->gpu_frame = GpuFrameCreate( + capture_context->gpu_frame = GpuContextCreateFrame( capture_context->gpu_context, drm_mode_fb_cmd2.width, drm_mode_fb_cmd2.height, drm_mode_fb_cmd2.pixel_format, nplanes, planes); @@ -165,7 +166,10 @@ release_planes: } void CaptureContextDestroy(struct CaptureContext* capture_context) { - if (capture_context->gpu_frame) GpuFrameDestroy(capture_context->gpu_frame); + if (capture_context->gpu_frame) { + GpuContextDestroyFrame(capture_context->gpu_context, + capture_context->gpu_frame); + } drmClose(capture_context->drm_fd); free(capture_context); } @@ -166,8 +166,8 @@ static struct GpuFrame* PrimeToGpuFrame( }; } struct GpuFrame* gpu_frame = - GpuFrameCreate(gpu_context, prime->width, prime->height, prime->fourcc, - prime->layers[0].num_planes, planes); + GpuContextCreateFrame(gpu_context, prime->width, prime->height, + prime->fourcc, prime->layers[0].num_planes, planes); for (size_t i = prime->num_objects; i; i--) close(prime->objects[i - 1].fd); return gpu_frame; } @@ -248,7 +248,8 @@ static bool DrainPacket(const struct AVPacket* packet, int fd) { bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd) { bool result = false; if (encode_context->gpu_frame) { - GpuFrameDestroy(encode_context->gpu_frame); + GpuContextDestroyFrame(encode_context->gpu_context, + encode_context->gpu_frame); encode_context->gpu_frame = NULL; } AVPacket* packet = av_packet_alloc(); @@ -293,7 +294,10 @@ rollback_hw_frame: } void EncodeContextDestroy(struct EncodeContext* encode_context) { - if (encode_context->gpu_frame) GpuFrameDestroy(encode_context->gpu_frame); + if (encode_context->gpu_frame) { + GpuContextDestroyFrame(encode_context->gpu_context, + encode_context->gpu_frame); + } if (encode_context->hw_frame) av_frame_free(&encode_context->hw_frame); avcodec_free_context(&encode_context->codec_context); av_buffer_unref(&encode_context->hwdevice_context); @@ -20,6 +20,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #include <GLES3/gl32.h> #include <drm_fourcc.h> #include <errno.h> @@ -28,9 +29,6 @@ #include <string.h> #include <unistd.h> -// mburakov: Must be included after GLES2/gl2.h -#include <GLES2/gl2ext.h> - #ifndef USE_EGL_MESA_PLATFORM_SURFACELESS #include <fcntl.h> #include <gbm.h> @@ -77,9 +75,8 @@ struct GpuContext { GLuint vertices; }; -struct GpuFrame { - struct GpuContext* gpu_context; - uint32_t width, height; +struct GpuFrameImpl { + struct GpuFrame size; int dmabuf_fds[4]; EGLImage images[2]; GLuint textures[2]; @@ -449,33 +446,6 @@ rollback_gpu_context: return NULL; } -bool GpuContextSync(struct GpuContext* gpu_context) { - EGLSync sync = eglCreateSync(gpu_context->display, EGL_SYNC_FENCE, NULL); - if (sync == EGL_NO_SYNC) { - LOG("Failed to create egl fence sync (%s)", EglErrorString(eglGetError())); - return false; - } - eglClientWaitSync(gpu_context->display, sync, 0, EGL_FOREVER); - eglDestroySync(gpu_context->display, sync); - return true; -} - -void GpuContextDestroy(struct GpuContext* gpu_context) { - glDeleteBuffers(1, &gpu_context->vertices); - glDeleteFramebuffers(1, &gpu_context->framebuffer); - glDeleteProgram(gpu_context->program_chroma); - glDeleteProgram(gpu_context->program_luma); - eglMakeCurrent(gpu_context->display, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - eglDestroyContext(gpu_context->display, gpu_context->context); - eglTerminate(gpu_context->display); -#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS - gbm_device_destroy(gpu_context->device); - close(gpu_context->render_node); -#endif // USE_EGL_MESA_PLATFORM_SURFACELESS - free(gpu_context); -} - static void DumpEglImageParams(const EGLAttrib* attribs) { for (; *attribs != EGL_NONE; attribs += 2) { switch (attribs[0]) { @@ -665,26 +635,25 @@ static GLuint CreateTexture(struct GpuContext* gpu_context, EGLImage image) { return texture; } -struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width, - uint32_t height, uint32_t fourcc, - size_t nplanes, - const struct GpuFramePlane* planes) { - struct GpuFrame* gpu_frame = malloc(sizeof(struct GpuFrame)); - if (!gpu_frame) { +struct GpuFrame* GpuContextCreateFrame(struct GpuContext* gpu_context, + uint32_t width, uint32_t height, + uint32_t fourcc, size_t nplanes, + const struct GpuFramePlane* planes) { + struct GpuFrameImpl* gpu_frame_impl = malloc(sizeof(struct GpuFrameImpl)); + if (!gpu_frame_impl) { LOG("Failed to allocate gpu frame (%s)", strerror(errno)); return NULL; } - *gpu_frame = (struct GpuFrame){ - .gpu_context = gpu_context, - .width = width, - .height = height, + *gpu_frame_impl = (struct GpuFrameImpl){ + .size.width = width, + .size.height = height, .dmabuf_fds = {-1, -1, -1, -1}, .images = {EGL_NO_IMAGE, EGL_NO_IMAGE}, }; for (size_t i = 0; i < nplanes; i++) { - gpu_frame->dmabuf_fds[i] = dup(planes[i].dmabuf_fd); - if (gpu_frame->dmabuf_fds[i] == -1) { + gpu_frame_impl->dmabuf_fds[i] = dup(planes[i].dmabuf_fd); + if (gpu_frame_impl->dmabuf_fds[i] == -1) { LOG("Failed to dup dmabuf fd (%s)", strerror(errno)); goto rollback_dmabuf_fds; } @@ -693,7 +662,7 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width, struct GpuFramePlane dummy_planes[4]; for (size_t i = 0; i < nplanes; i++) { dummy_planes[i] = (struct GpuFramePlane){ - .dmabuf_fd = gpu_frame->dmabuf_fds[i], + .dmabuf_fd = gpu_frame_impl->dmabuf_fds[i], .offset = planes[i].offset, .pitch = planes[i].pitch, .modifier = planes[i].modifier, @@ -701,61 +670,58 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width, } if (fourcc == DRM_FORMAT_NV12) { - gpu_frame->images[0] = CreateEglImage(gpu_context, width, height, - DRM_FORMAT_R8, 1, &dummy_planes[0]); - if (gpu_frame->images[0] == EGL_NO_IMAGE) { + gpu_frame_impl->images[0] = CreateEglImage( + gpu_context, width, height, DRM_FORMAT_R8, 1, &dummy_planes[0]); + if (gpu_frame_impl->images[0] == EGL_NO_IMAGE) { LOG("Failed to create luma plane image"); goto rollback_dmabuf_fds; } - gpu_frame->images[1] = CreateEglImage(gpu_context, width / 2, height / 2, - DRM_FORMAT_GR88, 1, &dummy_planes[1]); - if (gpu_frame->images[1] == EGL_NO_IMAGE) { + gpu_frame_impl->images[1] = + CreateEglImage(gpu_context, width / 2, height / 2, DRM_FORMAT_GR88, 1, + &dummy_planes[1]); + if (gpu_frame_impl->images[1] == EGL_NO_IMAGE) { LOG("Failed to create chroma plane image"); goto rollback_images; } } else { - gpu_frame->images[0] = CreateEglImage(gpu_context, width, height, fourcc, - nplanes, dummy_planes); - if (gpu_frame->images[0] == EGL_NO_IMAGE) { + gpu_frame_impl->images[0] = CreateEglImage(gpu_context, width, height, + fourcc, nplanes, dummy_planes); + if (gpu_frame_impl->images[0] == EGL_NO_IMAGE) { LOG("Failed to create multiplanar image"); goto rollback_dmabuf_fds; } } - for (size_t i = 0; i < LENGTH(gpu_frame->images); i++) { - if (gpu_frame->images[i] == EGL_NO_IMAGE) break; - gpu_frame->textures[i] = CreateTexture(gpu_context, gpu_frame->images[i]); - if (!gpu_frame->textures[i]) { + for (size_t i = 0; i < LENGTH(gpu_frame_impl->images); i++) { + if (gpu_frame_impl->images[i] == EGL_NO_IMAGE) break; + gpu_frame_impl->textures[i] = + CreateTexture(gpu_context, gpu_frame_impl->images[i]); + if (!gpu_frame_impl->textures[i]) { LOG("Failed to create texture"); goto rollback_textures; } } - return gpu_frame; + return (struct GpuFrame*)gpu_frame_impl; rollback_textures: - for (size_t i = LENGTH(gpu_frame->textures); i; i--) { - if (gpu_frame->textures[i - 1]) - glDeleteTextures(1, &gpu_frame->textures[i - 1]); + for (size_t i = LENGTH(gpu_frame_impl->textures); i; i--) { + if (gpu_frame_impl->textures[i - 1]) + glDeleteTextures(1, &gpu_frame_impl->textures[i - 1]); } rollback_images: - for (size_t i = LENGTH(gpu_frame->images); i; i--) { - if (gpu_frame->images[i - 1] != EGL_NO_IMAGE) - eglDestroyImage(gpu_frame->gpu_context->device, gpu_frame->images[i - 1]); + for (size_t i = LENGTH(gpu_frame_impl->images); i; i--) { + if (gpu_frame_impl->images[i - 1] != EGL_NO_IMAGE) + eglDestroyImage(gpu_context->device, gpu_frame_impl->images[i - 1]); } rollback_dmabuf_fds: - for (size_t i = LENGTH(gpu_frame->dmabuf_fds); i; i--) { - if (gpu_frame->dmabuf_fds[i - 1] != -1) close(gpu_frame->dmabuf_fds[i - 1]); + for (size_t i = LENGTH(gpu_frame_impl->dmabuf_fds); i; i--) { + if (gpu_frame_impl->dmabuf_fds[i - 1] != -1) + close(gpu_frame_impl->dmabuf_fds[i - 1]); } - free(gpu_frame); + free(gpu_frame_impl); return NULL; } -void GpuFrameGetSize(const struct GpuFrame* gpu_frame, uint32_t* width, - uint32_t* height) { - *width = gpu_frame->width; - *height = gpu_frame->height; -} - static bool GpuFrameConvertImpl(GLuint from, GLuint to) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to, 0); @@ -775,10 +741,15 @@ static bool GpuFrameConvertImpl(GLuint from, GLuint to) { return true; } -bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to) { - glUseProgram(from->gpu_context->program_luma); +bool GpuContextConvertFrame(struct GpuContext* gpu_context, + const struct GpuFrame* from, + const struct GpuFrame* to) { + const struct GpuFrameImpl* from_impl = (const void*)from; + const struct GpuFrameImpl* to_impl = (const void*)to; + + glUseProgram(gpu_context->program_luma); glViewport(0, 0, (GLsizei)to->width, (GLsizei)to->height); - if (!GpuFrameConvertImpl(from->textures[0], to->textures[0])) { + if (!GpuFrameConvertImpl(from_impl->textures[0], to_impl->textures[0])) { LOG("Failed to convert luma plane"); return false; } @@ -790,27 +761,54 @@ bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to) { _(1.f / (GLfloat)from->width, 1.f / (GLfloat)from->height), }; - glUseProgram(from->gpu_context->program_chroma); - glUniform2fv(from->gpu_context->sample_offsets, 4, sample_offsets); + glUseProgram(gpu_context->program_chroma); + glUniform2fv(gpu_context->sample_offsets, 4, sample_offsets); glViewport(0, 0, (GLsizei)to->width / 2, (GLsizei)to->height / 2); - if (!GpuFrameConvertImpl(from->textures[0], to->textures[1])) { + if (!GpuFrameConvertImpl(from_impl->textures[0], to_impl->textures[1])) { LOG("Failed to convert chroma plane"); return false; } + + EGLSync sync = eglCreateSync(gpu_context->display, EGL_SYNC_FENCE, NULL); + if (sync == EGL_NO_SYNC) { + LOG("Failed to create egl fence sync (%s)", EglErrorString(eglGetError())); + return false; + } + eglClientWaitSync(gpu_context->display, sync, 0, EGL_FOREVER); + eglDestroySync(gpu_context->display, sync); return true; } -void GpuFrameDestroy(struct GpuFrame* gpu_frame) { - for (size_t i = LENGTH(gpu_frame->textures); i; i--) { - if (gpu_frame->textures[i - 1]) - glDeleteTextures(1, &gpu_frame->textures[i - 1]); +void GpuContextDestroyFrame(struct GpuContext* gpu_context, + struct GpuFrame* gpu_frame) { + struct GpuFrameImpl* gpu_frame_impl = (void*)gpu_frame; + for (size_t i = LENGTH(gpu_frame_impl->textures); i; i--) { + if (gpu_frame_impl->textures[i - 1]) + glDeleteTextures(1, &gpu_frame_impl->textures[i - 1]); } - for (size_t i = LENGTH(gpu_frame->images); i; i--) { - if (gpu_frame->images[i - 1] != EGL_NO_IMAGE) - eglDestroyImage(gpu_frame->gpu_context->device, gpu_frame->images[i - 1]); + for (size_t i = LENGTH(gpu_frame_impl->images); i; i--) { + if (gpu_frame_impl->images[i - 1] != EGL_NO_IMAGE) + eglDestroyImage(gpu_context->device, gpu_frame_impl->images[i - 1]); } - for (size_t i = LENGTH(gpu_frame->dmabuf_fds); i; i--) { - if (gpu_frame->dmabuf_fds[i - 1] != -1) close(gpu_frame->dmabuf_fds[i - 1]); + for (size_t i = LENGTH(gpu_frame_impl->dmabuf_fds); i; i--) { + if (gpu_frame_impl->dmabuf_fds[i - 1] != -1) + close(gpu_frame_impl->dmabuf_fds[i - 1]); } - free(gpu_frame); + free(gpu_frame_impl); +} + +void GpuContextDestroy(struct GpuContext* gpu_context) { + glDeleteBuffers(1, &gpu_context->vertices); + glDeleteFramebuffers(1, &gpu_context->framebuffer); + glDeleteProgram(gpu_context->program_chroma); + glDeleteProgram(gpu_context->program_luma); + eglMakeCurrent(gpu_context->display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglDestroyContext(gpu_context->display, gpu_context->context); + eglTerminate(gpu_context->display); +#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS + gbm_device_destroy(gpu_context->device); + close(gpu_context->render_node); +#endif // USE_EGL_MESA_PLATFORM_SURFACELESS + free(gpu_context); } @@ -24,6 +24,11 @@ #include "colorspace.h" +struct GpuFrame { + uint32_t width; + uint32_t height; +}; + struct GpuFramePlane { int dmabuf_fd; uint32_t pitch; @@ -33,16 +38,15 @@ struct GpuFramePlane { struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace, enum YuvRange range); -bool GpuContextSync(struct GpuContext* gpu_context); +struct GpuFrame* GpuContextCreateFrame(struct GpuContext* gpu_context, + uint32_t width, uint32_t height, + uint32_t fourcc, size_t nplanes, + const struct GpuFramePlane* planes); +bool GpuContextConvertFrame(struct GpuContext* gpu_context, + const struct GpuFrame* from, + const struct GpuFrame* to); +void GpuContextDestroyFrame(struct GpuContext* gpu_context, + struct GpuFrame* gpu_frame); void GpuContextDestroy(struct GpuContext* gpu_context); -struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width, - uint32_t height, uint32_t fourcc, - size_t nplanes, - const struct GpuFramePlane* planes); -void GpuFrameGetSize(const struct GpuFrame* gpu_frame, uint32_t* width, - uint32_t* height); -bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to); -void GpuFrameDestroy(struct GpuFrame* gpu_frame); - #endif // STREAMER_GPU_H_ @@ -143,10 +143,9 @@ static void OnTimerExpire(void* user) { } if (!contexts->encode_context) { - uint32_t width, height; - GpuFrameGetSize(captured_frame, &width, &height); - contexts->encode_context = EncodeContextCreate(contexts->gpu_context, width, - height, colorspace, range); + contexts->encode_context = + EncodeContextCreate(contexts->gpu_context, captured_frame->width, + captured_frame->height, colorspace, range); if (!contexts->encode_context) { LOG("Failed to create encode context"); goto drop_client; @@ -159,12 +158,11 @@ static void OnTimerExpire(void* user) { LOG("Failed to get encoded frame"); goto drop_client; } - if (!GpuFrameConvert(captured_frame, encoded_frame)) { + if (!GpuContextConvertFrame(contexts->gpu_context, captured_frame, + encoded_frame)) { LOG("Failed to convert frame"); goto drop_client; } - - GpuContextSync(contexts->gpu_context); if (!EncodeContextEncodeFrame(contexts->encode_context, contexts->client_fd)) { LOG("Failed to encode frame"); |