diff --git a/src/ustreamer/encoders/omx/encoder.c b/src/ustreamer/encoders/omx/encoder.c index e52b6c3..10f3389 100644 --- a/src/ustreamer/encoders/omx/encoder.c +++ b/src/ustreamer/encoders/omx/encoder.c @@ -27,7 +27,6 @@ static const OMX_U32 _INPUT_PORT = 340; static const OMX_U32 _OUTPUT_PORT = 341; -static int _vcos_semwait(VCOS_SEMAPHORE_T *sem); static int _omx_init_component(omx_encoder_s *omx); static int _omx_init_disable_ports(omx_encoder_s *omx); static int _omx_setup_input(omx_encoder_s *omx, const frame_s *frame); @@ -194,7 +193,7 @@ int omx_encoder_compress(omx_encoder_s *omx, const frame_s *src, frame_s *dest) } } - if (_vcos_semwait(&omx->handler_sem) != 0) { + if (vcos_my_semwait("", &omx->handler_sem, 1) < 0) { return -1; } } @@ -204,42 +203,6 @@ int omx_encoder_compress(omx_encoder_s *omx, const frame_s *src, frame_s *dest) return 0; } -static int _vcos_semwait(VCOS_SEMAPHORE_T *sem) { - // vcos_semaphore_wait() can wait infinite - // vcos_semaphore_wait_timeout() is broken by design: - // - https://github.com/pikvm/ustreamer/issues/56 - // - https://github.com/raspberrypi/userland/issues/658 - // CFG_OMX_SEMWAIT_TIMEOUT is ugly busyloop - // Три стула. - -# ifdef CFG_OMX_SEMWAIT_TIMEOUT - long double deadline_ts = get_now_monotonic() + (long double)CFG_OMX_SEMWAIT_TIMEOUT; // Seconds - VCOS_STATUS_T sem_status; - - while (true) { - sem_status = vcos_semaphore_trywait(sem); - if (sem_status == VCOS_SUCCESS) { - return 0; - } else if (sem_status != VCOS_EAGAIN || get_now_monotonic() > deadline_ts) { - break; - } - if (usleep(1000) < 0) { - break; - } - } - - switch (sem_status) { - case VCOS_EAGAIN: LOG_ERROR("Can't wait VCOS semaphore: EAGAIN (timeout)"); break; - case VCOS_EINVAL: LOG_ERROR("Can't wait VCOS semaphore: EINVAL"); break; - default: LOG_ERROR("Can't wait VCOS semaphore: %d", sem_status); break; - } - return -1; - -# else - return (vcos_semaphore_wait(sem) == VCOS_SUCCESS ? 0 : -1); -# endif -} - static int _omx_init_component(omx_encoder_s *omx) { OMX_ERRORTYPE error; diff --git a/src/ustreamer/encoders/omx/encoder.h b/src/ustreamer/encoders/omx/encoder.h index 67aa57b..32189f9 100644 --- a/src/ustreamer/encoders/omx/encoder.h +++ b/src/ustreamer/encoders/omx/encoder.h @@ -39,6 +39,7 @@ #include "../../../libs/logging.h" #include "../../../libs/frame.h" +#include "vcos.h" #include "formatters.h" #include "component.h" diff --git a/src/ustreamer/encoders/omx/vcos.c b/src/ustreamer/encoders/omx/vcos.c new file mode 100644 index 0000000..022669f --- /dev/null +++ b/src/ustreamer/encoders/omx/vcos.c @@ -0,0 +1,55 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# Copyright (C) 2018-2021 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#include "vcos.h" + + +int vcos_my_semwait(const char *prefix, VCOS_SEMAPHORE_T *sem, long double timeout) { + // vcos_semaphore_wait() can wait infinite + // vcos_semaphore_wait_timeout() is broken by design: + // - https://github.com/pikvm/ustreamer/issues/56 + // - https://github.com/raspberrypi/userland/issues/658 + // - The current approach is an ugly busyloop + // Три стула. + + long double deadline_ts = get_now_monotonic() + timeout; + VCOS_STATUS_T sem_status; + + while (true) { + sem_status = vcos_semaphore_trywait(sem); + if (sem_status == VCOS_SUCCESS) { + return 0; + } else if (sem_status != VCOS_EAGAIN || get_now_monotonic() > deadline_ts) { + break; + } + if (usleep(1000) < 0) { + break; + } + } + + switch (sem_status) { + case VCOS_EAGAIN: LOG_ERROR("%sCan't wait VCOS semaphore: EAGAIN (timeout)", prefix); break; + case VCOS_EINVAL: LOG_ERROR("%sCan't wait VCOS semaphore: EINVAL", prefix); break; + default: LOG_ERROR("%sCan't wait VCOS semaphore: %d", prefix, sem_status); break; + } + return -1; +} diff --git a/src/ustreamer/encoders/omx/vcos.h b/src/ustreamer/encoders/omx/vcos.h new file mode 100644 index 0000000..1c0fba2 --- /dev/null +++ b/src/ustreamer/encoders/omx/vcos.h @@ -0,0 +1,31 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPG-HTTP streamer. # +# # +# Copyright (C) 2018-2021 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#pragma once + +#include + +#include "../../../libs/tools.h" +#include "../../../libs/logging.h" + + +int vcos_my_semwait(const char *prefix, VCOS_SEMAPHORE_T *sem, long double timeout); diff --git a/src/ustreamer/h264/encoder.c b/src/ustreamer/h264/encoder.c index 59d25c8..a49bc07 100644 --- a/src/ustreamer/h264/encoder.c +++ b/src/ustreamer/h264/encoder.c @@ -225,7 +225,7 @@ int h264_encoder_prepare(h264_encoder_s *enc, const frame_s *frame, bool zero_co error: _h264_encoder_cleanup(enc); - LOG_ERROR("H264: Encoder disabled due error (prepare)"); + LOG_ERROR("H264: Encoder destroyed due an error (prepare)"); return -1; # undef ENABLE_PORT @@ -276,7 +276,7 @@ int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, int src_vcsm_ if (_h264_encoder_compress_raw(enc, src, src_vcsm_handle, dest, force_key) < 0) { _h264_encoder_cleanup(enc); - LOG_ERROR("H264: Encoder disabled due error (compress)"); + LOG_ERROR("H264: Encoder destroyed due an error (compress)"); return -1; } @@ -340,7 +340,9 @@ static int _h264_encoder_compress_raw(h264_encoder_s *enc, const frame_s *src, i error = mmal_wrapper_buffer_get_full(enc->output_port, &out, 0); if (error == MMAL_EAGAIN) { - vcos_semaphore_wait(&enc->handler_sem); + if (vcos_my_semwait("H264: ", &enc->handler_sem, 1) < 0) { + return -1; + } continue; } else if (error != MMAL_SUCCESS) { LOG_ERROR_MMAL(error, "H264: Can't get MMAL output buffer"); diff --git a/src/ustreamer/h264/encoder.h b/src/ustreamer/h264/encoder.h index be5de71..01c786c 100644 --- a/src/ustreamer/h264/encoder.h +++ b/src/ustreamer/h264/encoder.h @@ -38,6 +38,7 @@ #include "../../libs/tools.h" #include "../../libs/logging.h" #include "../../libs/frame.h" +#include "../encoders/omx/vcos.h" typedef struct {