summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Burakov <mburakov@mailbox.org>2023-04-08 13:49:13 +0200
committerMikhail Burakov <mburakov@mailbox.org>2023-04-09 10:26:16 +0200
commitb4996b76e99ab602ff87df31d61074cfa72f9f61 (patch)
treed8ec2684929e1e2b98394d31896b1e048b8adaa3
parent0fe1d5648f5ee5f1548eb887e96ca149f9e6481c (diff)
Get rid of auto variables
-rw-r--r--capture.c90
-rw-r--r--capture.h2
-rw-r--r--encode.c153
-rw-r--r--encode.h2
-rw-r--r--gpu.c163
-rw-r--r--gpu.h4
-rw-r--r--main.c29
-rw-r--r--util.h8
8 files changed, 256 insertions, 195 deletions
diff --git a/capture.c b/capture.c
index 79a76ae..c1b64b6 100644
--- a/capture.c
+++ b/capture.c
@@ -53,45 +53,38 @@ static int OpenAnyModule(void) {
return -1;
}
-static void drmModeResPtrDestroy(drmModeResPtr* res) {
- if (res && *res) drmModeFreeResources(*res);
-}
-
-static void drmModeCrtcPtrDestroy(drmModeCrtcPtr* crtc) {
- if (crtc && *crtc) drmModeFreeCrtc(*crtc);
-}
-
-static void drmModeFB2PtrDestroy(drmModeFB2Ptr* fb2) {
- if (fb2 && *fb2) drmModeFreeFB2(*fb2);
-}
-
static bool IsCrtcComplete(int drm_fd, uint32_t crtc_id) {
- AUTO(drmModeCrtcPtr)
- crtc = drmModeGetCrtc(drm_fd, crtc_id);
+ drmModeCrtcPtr crtc = drmModeGetCrtc(drm_fd, crtc_id);
if (!crtc) {
- LOG("Failed to get crtc %u", crtc_id);
+ LOG("Failed to get crtc %u (%s)", crtc_id, strerror(errno));
return false;
}
+ bool result = false;
if (!crtc->buffer_id) {
LOG("Crtc %u has no framebuffer", crtc_id);
- return false;
+ goto rollback_crtc;
}
- AUTO(drmModeFB2Ptr)
- fb2 = drmModeGetFB2(drm_fd, crtc->buffer_id);
+ drmModeFB2Ptr fb2 = drmModeGetFB2(drm_fd, crtc->buffer_id);
if (!fb2) {
- LOG("Failed to get framebuffer %u", crtc->buffer_id);
- return false;
+ LOG("Failed to get framebuffer %u (%s)", crtc->buffer_id, strerror(errno));
+ goto rollback_crtc;
}
if (!fb2->handles[0]) {
LOG("Framebuffer %u has no handles", crtc->buffer_id);
- return false;
+ goto rollback_fb2;
}
- return true;
+ result = true;
+
+rollback_fb2:
+ drmModeFreeFB2(fb2);
+rollback_crtc:
+ drmModeFreeCrtc(crtc);
+ return result;
}
struct CaptureContext* CaptureContextCreate(struct GpuContext* gpu_context) {
- struct AUTO(CaptureContext)* capture_context =
+ struct CaptureContext* capture_context =
malloc(sizeof(struct CaptureContext));
if (!capture_context) {
LOG("Failed to allocate capture context (%s)", strerror(errno));
@@ -103,23 +96,33 @@ struct CaptureContext* CaptureContextCreate(struct GpuContext* gpu_context) {
};
capture_context->drm_fd = OpenAnyModule();
- if (capture_context->drm_fd == -1) return NULL;
+ if (capture_context->drm_fd == -1) {
+ LOG("Failed to open any module");
+ goto rollback_capture_context;
+ }
- AUTO(drmModeResPtr) res = drmModeGetResources(capture_context->drm_fd);
+ drmModeResPtr res = drmModeGetResources(capture_context->drm_fd);
if (!res) {
LOG("Failed to get drm mode resources (%s)", strerror(errno));
- return NULL;
+ goto rollback_drm_fd;
}
for (int i = 0; i < res->count_crtcs; i++) {
if (IsCrtcComplete(capture_context->drm_fd, res->crtcs[i])) {
LOG("Capturing crtc %u", res->crtcs[i]);
capture_context->crtc_id = res->crtcs[i];
- return RELEASE(capture_context);
+ drmModeFreeResources(res);
+ return capture_context;
}
}
LOG("Nothing to capture");
+ drmModeFreeResources(res);
+
+rollback_drm_fd:
+ drmClose(capture_context->drm_fd);
+rollback_capture_context:
+ free(capture_context);
return NULL;
}
@@ -155,35 +158,38 @@ release_planes:
const struct GpuFrame* CaptureContextGetFrame(
struct CaptureContext* capture_context) {
- AUTO(drmModeCrtcPtr)
- crtc = drmModeGetCrtc(capture_context->drm_fd, capture_context->crtc_id);
+ drmModeCrtcPtr crtc =
+ drmModeGetCrtc(capture_context->drm_fd, capture_context->crtc_id);
if (!crtc) {
LOG("Failed to get crtc %u", capture_context->crtc_id);
return NULL;
}
- AUTO(drmModeFB2Ptr)
- fb2 = drmModeGetFB2(capture_context->drm_fd, crtc->buffer_id);
+ struct GpuFrame* gpu_frame = NULL;
+ drmModeFB2Ptr fb2 = drmModeGetFB2(capture_context->drm_fd, crtc->buffer_id);
if (!fb2) {
LOG("Failed to get framebuffer %u", crtc->buffer_id);
- return NULL;
+ goto rollback_crtc;
}
if (!fb2->handles[0]) {
LOG("Framebuffer %u has no handles", crtc->buffer_id);
- return NULL;
+ goto rollback_fb2;
}
- GpuFrameDestroy(&capture_context->gpu_frame);
+ if (capture_context->gpu_frame) GpuFrameDestroy(capture_context->gpu_frame);
capture_context->gpu_frame = WrapFramebuffer(capture_context->drm_fd, fb2,
capture_context->gpu_context);
- return capture_context->gpu_frame;
+ gpu_frame = capture_context->gpu_frame;
+
+rollback_fb2:
+ drmModeFreeFB2(fb2);
+rollback_crtc:
+ drmModeFreeCrtc(crtc);
+ return gpu_frame;
}
-void CaptureContextDestroy(struct CaptureContext** capture_context) {
- if (!capture_context || !*capture_context) return;
- if ((*capture_context)->gpu_frame)
- GpuFrameDestroy(&(*capture_context)->gpu_frame);
- if ((*capture_context)->drm_fd != -1) drmClose((*capture_context)->drm_fd);
- free(*capture_context);
- capture_context = NULL;
+void CaptureContextDestroy(struct CaptureContext* capture_context) {
+ GpuFrameDestroy(capture_context->gpu_frame);
+ drmClose(capture_context->drm_fd);
+ free(capture_context);
}
diff --git a/capture.h b/capture.h
index f351429..7b0b60d 100644
--- a/capture.h
+++ b/capture.h
@@ -25,6 +25,6 @@ struct GpuFrame;
struct CaptureContext* CaptureContextCreate(struct GpuContext* gpu_context);
const struct GpuFrame* CaptureContextGetFrame(
struct CaptureContext* capture_context);
-void CaptureContextDestroy(struct CaptureContext** capture_context);
+void CaptureContextDestroy(struct CaptureContext* capture_context);
#endif // STREAMER_CAPTURE_H_
diff --git a/encode.c b/encode.c
index 243a72a..16842a6 100644
--- a/encode.c
+++ b/encode.c
@@ -34,10 +34,6 @@
#include "perf.h"
#include "util.h"
-#define AVBufferRefDestroy av_buffer_unref
-#define AVFrameDestroy av_frame_free
-#define AVPacketDestroy av_packet_free
-
struct EncodeContext {
struct GpuContext* gpu_context;
AVBufferRef* hwdevice_context;
@@ -49,32 +45,26 @@ struct EncodeContext {
static bool SetHwFramesContext(struct EncodeContext* encode_context, int width,
int height) {
- AUTO(AVBufferRef)* hwframes_context =
+ encode_context->codec_context->hw_frames_ctx =
av_hwframe_ctx_alloc(encode_context->hwdevice_context);
- if (!hwframes_context) {
+ if (!encode_context->codec_context->hw_frames_ctx) {
LOG("Failed to allocate hwframes context");
return false;
}
- AVHWFramesContext* hwframes_context_data = (void*)(hwframes_context->data);
+ AVHWFramesContext* hwframes_context_data =
+ (void*)(encode_context->codec_context->hw_frames_ctx->data);
hwframes_context_data->initial_pool_size = 8;
hwframes_context_data->format = AV_PIX_FMT_VAAPI;
hwframes_context_data->sw_format = AV_PIX_FMT_NV12;
hwframes_context_data->width = width;
hwframes_context_data->height = height;
- int err = av_hwframe_ctx_init(hwframes_context);
+ int err = av_hwframe_ctx_init(encode_context->codec_context->hw_frames_ctx);
if (err < 0) {
LOG("Failed to init hwframes context (%s)", av_err2str(err));
+ av_buffer_unref(&encode_context->codec_context->hw_frames_ctx);
return false;
}
-
- encode_context->codec_context->hw_frames_ctx =
- av_buffer_ref(hwframes_context);
- if (!encode_context->codec_context->hw_frames_ctx) {
- LOG("Failed to ref hwframes context");
- return false;
- }
-
return true;
}
@@ -105,38 +95,32 @@ struct EncodeContext* EncodeContextCreate(struct GpuContext* gpu_context,
uint32_t width, uint32_t height,
enum YuvColorspace colrospace,
enum YuvRange range) {
- struct AUTO(EncodeContext)* encode_context =
- malloc(sizeof(struct EncodeContext));
+ struct EncodeContext* encode_context = malloc(sizeof(struct EncodeContext));
if (!encode_context) {
LOG("Failed to allocate encode context (%s)", strerror(errno));
return NULL;
}
*encode_context = (struct EncodeContext){
.gpu_context = gpu_context,
- .hwdevice_context = NULL,
- .codec_context = NULL,
- .hw_frame = NULL,
- .gpu_frame = NULL,
};
int err = av_hwdevice_ctx_create(&encode_context->hwdevice_context,
AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0);
if (err < 0) {
LOG("Failed to create hwdevice context (%s)", av_err2str(err));
- return NULL;
+ goto rollback_encode_context;
}
static const char codec_name[] = "hevc_vaapi";
const AVCodec* codec = avcodec_find_encoder_by_name(codec_name);
if (!codec) {
LOG("Failed to find %s encoder", codec_name);
- return NULL;
+ goto rollback_hwdevice_context;
}
-
encode_context->codec_context = avcodec_alloc_context3(codec);
if (!encode_context->codec_context) {
LOG("Failed to allocate codec context");
- return NULL;
+ goto rollback_hwdevice_context;
}
encode_context->codec_context->time_base = (AVRational){1, 60};
@@ -145,26 +129,53 @@ struct EncodeContext* EncodeContextCreate(struct GpuContext* gpu_context,
encode_context->codec_context->pix_fmt = AV_PIX_FMT_VAAPI;
encode_context->codec_context->max_b_frames = 0;
encode_context->codec_context->refs = 1;
- encode_context->codec_context->global_quality = 32;
+ encode_context->codec_context->global_quality = 28;
encode_context->codec_context->colorspace = ConvertColorspace(colrospace);
encode_context->codec_context->color_range = ConvertRange(range);
if (!SetHwFramesContext(encode_context, (int)width, (int)height)) {
LOG("Failed to set hwframes context");
- return NULL;
+ goto rollback_codec_context;
}
-
err = avcodec_open2(encode_context->codec_context, codec, NULL);
if (err < 0) {
LOG("Failed to open codec (%s)", av_err2str(err));
- return NULL;
+ goto rollback_codec_context;
}
- return RELEASE(encode_context);
+ return encode_context;
+
+rollback_codec_context:
+ avcodec_free_context(&encode_context->codec_context);
+rollback_hwdevice_context:
+ av_buffer_unref(&encode_context->hwdevice_context);
+rollback_encode_context:
+ free(encode_context);
+ return NULL;
+}
+
+static struct GpuFrame* PrimeToGpuFrame(
+ struct GpuContext* gpu_context, const VADRMPRIMESurfaceDescriptor* prime) {
+ struct GpuFramePlane planes[4];
+ for (size_t i = 0; i < prime->layers[0].num_planes; i++) {
+ uint32_t object_index = prime->layers[0].object_index[i];
+ if (prime->objects[object_index].fd == -1) break;
+ planes[i] = (struct GpuFramePlane){
+ .dmabuf_fd = prime->objects[object_index].fd,
+ .pitch = prime->layers[0].pitch[i],
+ .offset = prime->layers[0].offset[i],
+ .modifier = prime->objects[object_index].drm_format_modifier,
+ };
+ }
+ struct GpuFrame* gpu_frame =
+ GpuFrameCreate(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;
}
const struct GpuFrame* EncodeContextGetFrame(
struct EncodeContext* encode_context) {
- AUTO(AVFrame)* hw_frame = av_frame_alloc();
+ AVFrame* hw_frame = av_frame_alloc();
if (!hw_frame) {
LOG("Failed to allocate hwframe");
return NULL;
@@ -174,11 +185,11 @@ const struct GpuFrame* EncodeContextGetFrame(
hw_frame, 0);
if (err < 0) {
LOG("Failed to get hwframe buffer (%s)", av_err2str(err));
- return NULL;
+ goto rollback_hw_frame;
}
if (!hw_frame->hw_frames_ctx) {
LOG("Failed to ref hwframe context");
- return NULL;
+ goto rollback_hw_frame;
}
// mburakov: Roughly based on Sunshine code...
@@ -193,33 +204,23 @@ const struct GpuFrame* EncodeContextGetFrame(
VA_EXPORT_SURFACE_WRITE_ONLY | VA_EXPORT_SURFACE_COMPOSED_LAYERS, &prime);
if (status != VA_STATUS_SUCCESS) {
LOG("Failed to export vaapi surface (%d)", status);
- return NULL;
+ goto rollback_hw_frame;
}
- struct GpuFramePlane planes[prime.layers[0].num_planes];
- for (size_t i = 0; i < LENGTH(planes); i++) {
- planes[i] = (struct GpuFramePlane){
- .dmabuf_fd = prime.objects[prime.layers[0].object_index[i]].fd,
- .pitch = prime.layers[0].pitch[i],
- .offset = prime.layers[0].offset[i],
- .modifier =
- prime.objects[prime.layers[0].object_index[i]].drm_format_modifier,
- };
- }
- struct AUTO(GpuFrame)* gpu_frame =
- GpuFrameCreate(encode_context->gpu_context, prime.width, prime.height,
- prime.fourcc, LENGTH(planes), planes);
+ struct GpuFrame* gpu_frame =
+ PrimeToGpuFrame(encode_context->gpu_context, &prime);
if (!gpu_frame) {
LOG("Failed to create gpu frame");
- goto release_planes;
+ goto rollback_hw_frame;
}
- encode_context->hw_frame = RELEASE(hw_frame);
- encode_context->gpu_frame = RELEASE(gpu_frame);
+ encode_context->hw_frame = hw_frame;
+ encode_context->gpu_frame = gpu_frame;
+ return gpu_frame;
-release_planes:
- for (size_t i = prime.num_objects; i; i--) close(prime.objects[i - 1].fd);
- return encode_context->gpu_frame;
+rollback_hw_frame:
+ av_frame_free(&hw_frame);
+ return NULL;
}
static bool DrainPacket(const struct AVPacket* packet, int fd) {
@@ -255,19 +256,23 @@ static bool DrainPacket(const struct AVPacket* packet, int fd) {
bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd,
struct TimingStats* encode,
struct TimingStats* drain) {
+ bool result = false;
unsigned long long before_send = MicrosNow();
- GpuFrameDestroy(&encode_context->gpu_frame);
- AUTO(AVFrame)* hw_frame = RELEASE(encode_context->hw_frame);
- AUTO(AVPacket)* packet = av_packet_alloc();
+ if (encode_context->gpu_frame) {
+ GpuFrameDestroy(encode_context->gpu_frame);
+ encode_context->gpu_frame = NULL;
+ }
+ AVPacket* packet = av_packet_alloc();
if (!packet) {
LOG("Failed to allocate packet (%s)", strerror(errno));
- return false;
+ goto rollback_hw_frame;
}
- int err = avcodec_send_frame(encode_context->codec_context, hw_frame);
+ int err = avcodec_send_frame(encode_context->codec_context,
+ encode_context->hw_frame);
if (err < 0) {
LOG("Failed to send frame (%s)", av_err2str(err));
- return false;
+ goto rollback_packet;
}
unsigned long long total_send = MicrosNow() - before_send;
@@ -284,10 +289,11 @@ bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd,
total_receive += MicrosNow() - before_receive;
if (encode) TimingStatsRecord(encode, total_send + total_receive);
if (drain) TimingStatsRecord(drain, total_drain);
- return true;
+ result = true;
+ goto rollback_packet;
default:
LOG("Failed to receive packet (%s)", av_err2str(err));
- return false;
+ goto rollback_packet;
}
packet->stream_index = 0;
@@ -296,21 +302,24 @@ bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd,
av_packet_unref(packet);
if (!result) {
LOG("Failed to write full packet (%s)", strerror(errno));
- return false;
+ goto rollback_packet;
}
total_receive += before_drain - before_receive;
total_drain += MicrosNow() - before_drain;
}
+
+rollback_packet:
+ av_packet_free(&packet);
+rollback_hw_frame:
+ av_frame_free(&encode_context->hw_frame);
+ return result;
}
-void EncodeContextDestroy(struct EncodeContext** encode_context) {
- if (!encode_context || !*encode_context) return;
- if ((*encode_context)->gpu_frame)
- GpuFrameDestroy(&(*encode_context)->gpu_frame);
- if ((*encode_context)->hw_frame) av_frame_free(&(*encode_context)->hw_frame);
- if ((*encode_context)->codec_context)
- avcodec_free_context(&(*encode_context)->codec_context);
- if ((*encode_context)->hwdevice_context)
- av_buffer_unref(&(*encode_context)->hwdevice_context);
+void EncodeContextDestroy(struct EncodeContext* encode_context) {
+ if (encode_context->gpu_frame) GpuFrameDestroy(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);
+ free(encode_context);
}
diff --git a/encode.h b/encode.h
index 318ab02..d03e286 100644
--- a/encode.h
+++ b/encode.h
@@ -37,6 +37,6 @@ const struct GpuFrame* EncodeContextGetFrame(
bool EncodeContextEncodeFrame(struct EncodeContext* encode_context, int fd,
struct TimingStats* encode,
struct TimingStats* drain);
-void EncodeContextDestroy(struct EncodeContext** encode_context);
+void EncodeContextDestroy(struct EncodeContext* encode_context);
#endif // STREAMER_ENCODE_H_
diff --git a/gpu.c b/gpu.c
index 71ef625..4d32f76 100644
--- a/gpu.c
+++ b/gpu.c
@@ -42,7 +42,7 @@
gpu_context->b = (a)eglGetProcAddress(#b); \
if (!gpu_context->b) { \
LOG("Failed to look up " #b " function"); \
- return NULL; \
+ goto rollback_display; \
}
// TODO(mburakov): It should be theoretically possible to do everything in a
@@ -269,7 +269,7 @@ static bool SetupCommonUniforms(GLuint program, enum YuvColorspace colorspace,
struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
enum YuvRange range) {
- struct AUTO(GpuContext)* gpu_context = malloc(sizeof(struct GpuContext));
+ struct GpuContext* gpu_context = malloc(sizeof(struct GpuContext));
if (!gpu_context) {
LOG("Failed to allocate gpu context (%s)", strerror(errno));
return NULL;
@@ -287,7 +287,7 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
if (!egl_ext) {
LOG("Failed to query platformless egl extensions (%s)",
EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_gpu_context;
}
LOG("EGL_EXTENSIONS: %s", egl_ext);
@@ -297,40 +297,46 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
// framebuffers are reported as supported by EGL. Maybe that's because the
// support for RDNA3 is still quite young in MESA.
#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS
- if (!HasExtension(egl_ext, "EGL_MESA_platform_gbm")) return NULL;
+ if (!HasExtension(egl_ext, "EGL_MESA_platform_gbm"))
+ goto rollback_gpu_context;
gpu_context->render_node = open("/dev/dri/renderD128", O_RDWR);
if (gpu_context->render_node == -1) {
LOG("Failed to open render node (%s)", strerror(errno));
- return NULL;
+ goto rollback_gpu_context;
}
gpu_context->device = gbm_create_device(gpu_context->render_node);
if (!gpu_context->device) {
LOG("Failed to create gbm device (%s)", strerror(errno));
- return NULL;
+ goto rollback_render_node;
}
gpu_context->display =
eglGetPlatformDisplay(EGL_PLATFORM_GBM_MESA, gpu_context->device, NULL);
#else // USE_EGL_MESA_PLATFORM_SURFACELESS
- if (!HasExtension(egl_ext, "EGL_MESA_platform_surfaceless")) return NULL;
+ if (!HasExtension(egl_ext, "EGL_MESA_platform_surfaceless"))
+ goto rollback_gpu_context;
gpu_context->display =
eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, NULL, NULL);
#endif // USE_EGL_MESA_PLATFORM_SURFACELESS
if (gpu_context->display == EGL_NO_DISPLAY) {
LOG("Failed to get egl display (%s)", EglErrorString(eglGetError()));
- return NULL;
+#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS
+ goto rollback_device;
+#else // USE_EGL_MESA_PLATFORM_SURFACELESS
+ goto rollback_gpu_context;
+#endif // USE_EGL_MESA_PLATFORM_SURFACELESS
}
EGLint major, minor;
if (!eglInitialize(gpu_context->display, &major, &minor)) {
LOG("Failed to initialize egl display (%s)", EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_display;
}
LOG("Initialized EGL %d.%d", major, minor);
egl_ext = eglQueryString(gpu_context->display, EGL_EXTENSIONS);
if (!egl_ext) {
LOG("Failed to query egl extensions (%s)", EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_display;
}
LOG("EGL_EXTENSIONS: %s", egl_ext);
@@ -338,13 +344,13 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
!HasExtension(egl_ext, "EGL_KHR_no_config_context") ||
!HasExtension(egl_ext, "EGL_EXT_image_dma_buf_import") ||
!HasExtension(egl_ext, "EGL_EXT_image_dma_buf_import_modifiers"))
- return NULL;
+ goto rollback_display;
LOOKUP_FUNCTION(PFNEGLQUERYDMABUFFORMATSEXTPROC, eglQueryDmaBufFormatsEXT)
LOOKUP_FUNCTION(PFNEGLQUERYDMABUFMODIFIERSEXTPROC, eglQueryDmaBufModifiersEXT)
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
LOG("Failed to bind egl api (%s)", EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_display;
}
static const EGLint context_attribs[] = {
@@ -356,24 +362,24 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
gpu_context->display, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, context_attribs);
if (gpu_context->context == EGL_NO_CONTEXT) {
LOG("Failed to create egl context (%s)", EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_display;
}
if (!eglMakeCurrent(gpu_context->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
gpu_context->context)) {
LOG("Failed to make egl context current (%s)",
EglErrorString(eglGetError()));
- return NULL;
+ goto rollback_context;
}
const char* gl_ext = (const char*)glGetString(GL_EXTENSIONS);
if (!gl_ext) {
LOG("Failed to get gl extensions (%s)", GlErrorString(glGetError()));
- return NULL;
+ goto rollback_context;
}
LOG("GL_EXTENSIONS: %s", gl_ext);
- if (!HasExtension(gl_ext, "GL_OES_EGL_image")) return NULL;
+ if (!HasExtension(gl_ext, "GL_OES_EGL_image")) goto rollback_context;
LOOKUP_FUNCTION(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC,
glEGLImageTargetTexture2DOES)
@@ -383,7 +389,7 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
if (!gpu_context->program_luma ||
!SetupCommonUniforms(gpu_context->program_luma, colorspace, range)) {
LOG("Failed to create luma program");
- return NULL;
+ goto rollback_context;
}
gpu_context->program_chroma =
@@ -392,14 +398,14 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
if (!gpu_context->program_chroma ||
!SetupCommonUniforms(gpu_context->program_chroma, colorspace, range)) {
LOG("Failed to create chroma program");
- return NULL;
+ goto rollback_program_luma;
}
gpu_context->sample_offsets =
glGetUniformLocation(gpu_context->program_chroma, "sample_offsets");
if (gpu_context->sample_offsets == -1) {
LOG("Failed to find sample_offsets uniform (%s)",
GlErrorString(glGetError()));
- return NULL;
+ goto rollback_program_chroma;
}
glGenFramebuffers(1, &gpu_context->framebuffer);
@@ -413,9 +419,33 @@ struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
LOG("Failed to create gl objects (%s)", GlErrorString(glGetError()));
- return NULL;
- }
- return RELEASE(gpu_context);
+ goto rollback_buffers;
+ }
+ return gpu_context;
+
+rollback_buffers:
+ if (gpu_context->vertices) glDeleteBuffers(1, &gpu_context->vertices);
+ if (gpu_context->framebuffer)
+ glDeleteFramebuffers(1, &gpu_context->framebuffer);
+rollback_program_chroma:
+ glDeleteProgram(gpu_context->program_chroma);
+rollback_program_luma:
+ glDeleteProgram(gpu_context->program_luma);
+rollback_context:
+ eglMakeCurrent(gpu_context->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroyContext(gpu_context->display, gpu_context->context);
+rollback_display:
+ eglTerminate(gpu_context->display);
+#ifndef USE_EGL_MESA_PLATFORM_SURFACELESS
+rollback_device:
+ gbm_device_destroy(gpu_context->device);
+rollback_render_node:
+ close(gpu_context->render_node);
+#endif // USE_EGL_MESA_PLATFORM_SURFACELESS
+rollback_gpu_context:
+ free(gpu_context);
+ return NULL;
}
bool GpuContextSync(struct GpuContext* gpu_context) {
@@ -429,28 +459,20 @@ bool GpuContextSync(struct GpuContext* gpu_context) {
return true;
}
-void GpuContextDestroy(struct GpuContext** gpu_context) {
- if (!gpu_context || !*gpu_context) return;
- if ((*gpu_context)->vertices) glDeleteBuffers(1, &(*gpu_context)->vertices);
- if ((*gpu_context)->framebuffer)
- glDeleteFramebuffers(1, &(*gpu_context)->framebuffer);
- if ((*gpu_context)->program_chroma)
- glDeleteProgram((*gpu_context)->program_chroma);
- if ((*gpu_context)->program_luma)
- glDeleteProgram((*gpu_context)->program_luma);
- if ((*gpu_context)->context != EGL_NO_CONTEXT) {
- eglMakeCurrent((*gpu_context)->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglDestroyContext((*gpu_context)->display, (*gpu_context)->context);
- }
- if ((*gpu_context)->display != EGL_NO_DISPLAY)
- eglTerminate((*gpu_context)->display);
+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
- if ((*gpu_context)->device) gbm_device_destroy((*gpu_context)->device);
- if ((*gpu_context)->render_node != -1) close((*gpu_context)->render_node);
+ gbm_device_destroy(gpu_context->device);
+ close(gpu_context->render_node);
#endif // USE_EGL_MESA_PLATFORM_SURFACELESS
- free(*gpu_context);
- *gpu_context = NULL;
+ free(gpu_context);
}
static void DumpEglImageParams(const EGLAttrib* attribs) {
@@ -646,7 +668,7 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
uint32_t height, uint32_t fourcc,
size_t nplanes,
const struct GpuFramePlane* planes) {
- struct AUTO(GpuFrame)* gpu_frame = malloc(sizeof(struct GpuFrame));
+ struct GpuFrame* gpu_frame = malloc(sizeof(struct GpuFrame));
if (!gpu_frame) {
LOG("Failed to allocate gpu frame (%s)", strerror(errno));
return NULL;
@@ -657,18 +679,17 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
.height = height,
.dmabuf_fds = {-1, -1, -1, -1},
.images = {EGL_NO_IMAGE, EGL_NO_IMAGE},
- .textures = {0, 0},
};
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) {
LOG("Failed to dup dmabuf fd (%s)", strerror(errno));
- return NULL;
+ goto rollback_dmabuf_fds;
}
}
- struct GpuFramePlane dummy_planes[nplanes];
+ 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],
@@ -683,20 +704,20 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
DRM_FORMAT_R8, 1, &dummy_planes[0]);
if (gpu_frame->images[0] == EGL_NO_IMAGE) {
LOG("Failed to create luma plane image");
- return NULL;
+ 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) {
LOG("Failed to create chroma plane image");
- return NULL;
+ 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) {
LOG("Failed to create multiplanar image");
- return NULL;
+ goto rollback_dmabuf_fds;
}
}
@@ -705,11 +726,27 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
gpu_frame->textures[i] = CreateTexture(gpu_context, gpu_frame->images[i]);
if (!gpu_frame->textures[i]) {
LOG("Failed to create texture");
- return NULL;
+ goto rollback_textures;
}
}
+ return gpu_frame;
- return RELEASE(gpu_frame);
+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]);
+ }
+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]);
+ }
+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]);
+ }
+ free(gpu_frame);
+ return NULL;
}
void GpuFrameGetSize(const struct GpuFrame* gpu_frame, uint32_t* width,
@@ -762,21 +799,17 @@ bool GpuFrameConvert(const struct GpuFrame* from, const struct GpuFrame* to) {
return true;
}
-void GpuFrameDestroy(struct GpuFrame** gpu_frame) {
- if (!gpu_frame || !*gpu_frame) return;
- for (size_t i = LENGTH((*gpu_frame)->textures); i; i--) {
- if ((*gpu_frame)->textures[i - 1])
- glDeleteTextures(1, &(*gpu_frame)->textures[i - 1]);
+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]);
}
- for (size_t i = LENGTH((*gpu_frame)->images); i; i--) {
- if ((*gpu_frame)->images[i - 1] != EGL_NO_IMAGE)
- eglDestroyImage((*gpu_frame)->gpu_context->display,
- (*gpu_frame)->images[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)->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->dmabuf_fds); i; i--) {
+ if (gpu_frame->dmabuf_fds[i - 1] != -1) close(gpu_frame->dmabuf_fds[i - 1]);
}
- free(*gpu_frame);
- *gpu_frame = NULL;
+ free(gpu_frame);
}
diff --git a/gpu.h b/gpu.h
index 0043aca..0f0d71d 100644
--- a/gpu.h
+++ b/gpu.h
@@ -34,7 +34,7 @@ struct GpuFramePlane {
struct GpuContext* GpuContextCreate(enum YuvColorspace colorspace,
enum YuvRange range);
bool GpuContextSync(struct GpuContext* gpu_context);
-void GpuContextDestroy(struct GpuContext** gpu_context);
+void GpuContextDestroy(struct GpuContext* gpu_context);
struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
uint32_t height, uint32_t fourcc,
@@ -43,6 +43,6 @@ struct GpuFrame* GpuFrameCreate(struct GpuContext* gpu_context, uint32_t width,
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);
+void GpuFrameDestroy(struct GpuFrame* gpu_frame);
#endif // STREAMER_GPU_H_
diff --git a/main.c b/main.c
index 1d30c25..f8c07c6 100644
--- a/main.c
+++ b/main.c
@@ -39,6 +39,24 @@ static const enum YuvRange range = kNarrowRange;
static volatile sig_atomic_t g_signal;
static void OnSignal(int status) { g_signal = status; }
+static void GpuContextDtor(struct GpuContext** gpu_context) {
+ if (!*gpu_context) return;
+ GpuContextDestroy(*gpu_context);
+ *gpu_context = NULL;
+}
+
+static void CaptureContextDtor(struct CaptureContext** capture_context) {
+ if (!*capture_context) return;
+ CaptureContextDestroy(*capture_context);
+ *capture_context = NULL;
+}
+
+static void EncodeContextDtor(struct EncodeContext** encode_context) {
+ if (!*encode_context) return;
+ EncodeContextDestroy(*encode_context);
+ *encode_context = NULL;
+}
+
int main(int argc, char* argv[]) {
(void)argc;
(void)argv;
@@ -50,20 +68,23 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}
- struct AUTO(GpuContext)* gpu_context = GpuContextCreate(colorspace, range);
+ struct GpuContext __attribute__((cleanup(GpuContextDtor)))* gpu_context =
+ GpuContextCreate(colorspace, range);
if (!gpu_context) {
LOG("Failed to create gpu context");
return EXIT_FAILURE;
}
- struct AUTO(CaptureContext)* capture_context =
- CaptureContextCreate(gpu_context);
+ struct CaptureContext
+ __attribute__((cleanup(CaptureContextDtor)))* capture_context =
+ CaptureContextCreate(gpu_context);
if (!capture_context) {
LOG("Failed to create capture context");
return EXIT_FAILURE;
}
- struct AUTO(EncodeContext)* encode_context = NULL;
+ struct EncodeContext
+ __attribute__((cleanup(EncodeContextDtor)))* encode_context = NULL;
struct TimingStats capture;
struct TimingStats convert;
diff --git a/util.h b/util.h
index 47c4008..fe5fa56 100644
--- a/util.h
+++ b/util.h
@@ -22,17 +22,9 @@
#define STR(x) STR_IMPL(x)
#define LOG(fmt, ...) \
fprintf(stderr, __FILE__ ":" STR(__LINE__) " " fmt "\n", ##__VA_ARGS__)
-#define AUTO(x) x __attribute__((__cleanup__(x##Destroy)))
-#define RELEASE(x) Release((void**)&x)
#define LENGTH(x) (sizeof(x) / sizeof *(x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define _(...) __VA_ARGS__
-static inline void* Release(void** x) {
- void* result = *x;
- *x = 0;
- return result;
-}
-
#endif // STREAMER_UTIL_H_