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"); | 
