mirror of
https://github.com/pikvm/ustreamer.git
synced 2025-12-23 18:50:00 +00:00
refactoring
This commit is contained in:
parent
dd90d378a4
commit
85e63f49a0
2
Makefile
2
Makefile
@ -113,6 +113,7 @@ regen:
|
||||
|
||||
|
||||
$(USTR): $(_USTR_SRCS:%.c=$(BUILD)/%.o)
|
||||
$(info ========================================)
|
||||
$(info == LD $@)
|
||||
@ $(CC) $^ -o $@ $(LDFLAGS) $(_USTR_LIBS)
|
||||
$(info :: CC = $(CC))
|
||||
@ -123,6 +124,7 @@ $(USTR): $(_USTR_SRCS:%.c=$(BUILD)/%.o)
|
||||
|
||||
ifneq ($(call optbool,$(WITH_OMX)),)
|
||||
$(REC): $(_REC_SRCS:%.c=$(BUILD)/%.o)
|
||||
$(info ========================================)
|
||||
$(info == LD $@)
|
||||
@ $(CC) $^ -o $@ $(LDFLAGS) $(_REC_LIBS)
|
||||
$(info :: CC = $(CC))
|
||||
|
||||
@ -142,7 +142,7 @@ void encoder_prepare(encoder_s *enc, device_s *dev) {
|
||||
}
|
||||
|
||||
for (unsigned index = 0; index < ER(n_omxs); ++index) {
|
||||
if (omx_encoder_prepare(ER(omxs[index]), dev, quality) < 0) {
|
||||
if (omx_encoder_prepare(ER(omxs[index]), DR(width), DR(height), DR(format), quality) < 0) {
|
||||
LOG_ERROR("Can't prepare OMX encoder, falling back to CPU");
|
||||
goto force_cpu;
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ 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, device_s *dev);
|
||||
static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format);
|
||||
static int _omx_setup_output(omx_encoder_s *omx, unsigned quality);
|
||||
static int _omx_encoder_clear_ports(omx_encoder_s *omx);
|
||||
|
||||
@ -106,14 +106,14 @@ void omx_encoder_destroy(omx_encoder_s *omx) {
|
||||
free(omx);
|
||||
}
|
||||
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality) {
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format, unsigned quality) {
|
||||
if (omx_component_set_state(&omx->comp, OMX_StateIdle) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_omx_encoder_clear_ports(omx) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_omx_setup_input(omx, dev) < 0) {
|
||||
if (_omx_setup_input(omx, width, height, format) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_omx_setup_output(omx, quality) < 0) {
|
||||
@ -277,7 +277,7 @@ static int _omx_init_disable_ports(omx_encoder_s *omx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omx_setup_input(omx_encoder_s *omx, device_s *dev) {
|
||||
static int _omx_setup_input(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format) {
|
||||
LOG_DEBUG("Setting up OMX JPEG input port ...");
|
||||
|
||||
OMX_ERRORTYPE error;
|
||||
@ -289,14 +289,14 @@ static int _omx_setup_input(omx_encoder_s *omx, device_s *dev) {
|
||||
}
|
||||
|
||||
# define IFMT(_next) portdef.format.image._next
|
||||
IFMT(nFrameWidth) = dev->run->width;
|
||||
IFMT(nFrameHeight) = dev->run->height;
|
||||
IFMT(nFrameWidth) = width;
|
||||
IFMT(nFrameHeight) = height;
|
||||
IFMT(nStride) = 0;
|
||||
IFMT(nSliceHeight) = align_size(dev->run->height, 16);
|
||||
IFMT(nSliceHeight) = align_size(height, 16);
|
||||
IFMT(bFlagErrorConcealment) = OMX_FALSE;
|
||||
IFMT(eCompressionFormat) = OMX_IMAGE_CodingUnused;
|
||||
portdef.nBufferSize = ((dev->run->width * dev->run->height) << 1) * 2;
|
||||
switch (dev->run->format) {
|
||||
portdef.nBufferSize = ((width * height) << 1) * 2;
|
||||
switch (format) {
|
||||
// https://www.fourcc.org/yuv.php
|
||||
// Also see comments inside OMX_IVCommon.h
|
||||
case V4L2_PIX_FMT_YUYV: IFMT(eColorFormat) = OMX_COLOR_FormatYCbYCr; break;
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
#include "../../../libs/common/tools.h"
|
||||
#include "../../../libs/common/logging.h"
|
||||
#include "../../../libs/common/frame.h"
|
||||
#include "../../device.h"
|
||||
|
||||
#include "formatters.h"
|
||||
#include "component.h"
|
||||
@ -69,5 +68,5 @@ typedef struct {
|
||||
omx_encoder_s *omx_encoder_init(void);
|
||||
void omx_encoder_destroy(omx_encoder_s *omx);
|
||||
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality);
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, unsigned width, unsigned height, unsigned format, unsigned quality);
|
||||
int omx_encoder_compress(omx_encoder_s *omx, const frame_s *src, frame_s *dest);
|
||||
|
||||
@ -23,9 +23,7 @@
|
||||
#include "encoder.h"
|
||||
|
||||
|
||||
static int _h264_encoder_configure(h264_encoder_s *enc, const frame_s *frame);
|
||||
static void _h264_encoder_cleanup(h264_encoder_s *enc);
|
||||
|
||||
static int _h264_encoder_compress_raw(h264_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key);
|
||||
|
||||
static void _mmal_callback(MMAL_WRAPPER_T *wrapper);
|
||||
@ -97,53 +95,8 @@ void h264_encoder_destroy(h264_encoder_s *enc) {
|
||||
free(enc);
|
||||
}
|
||||
|
||||
int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, frame_s *dest) {
|
||||
assert(src->used > 0);
|
||||
assert(src->width > 0);
|
||||
assert(src->height > 0);
|
||||
assert(src->format > 0);
|
||||
|
||||
frame_copy_meta(src, dest);
|
||||
dest->encode_begin_ts = get_now_monotonic();
|
||||
dest->format = V4L2_PIX_FMT_H264;
|
||||
|
||||
if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) {
|
||||
LOG_DEBUG("H264: Input frame format is JPEG; decoding ...");
|
||||
if (unjpeg(src, RUN(tmp), true) < 0) {
|
||||
return -1;
|
||||
}
|
||||
LOG_VERBOSE("H264: JPEG decoded; time=%Lf", get_now_monotonic() - dest->encode_begin_ts);
|
||||
} else {
|
||||
LOG_DEBUG("H264: Copying source to tmp buffer ...");
|
||||
frame_copy(src, RUN(tmp));
|
||||
LOG_VERBOSE("H264: Source copied; time=%Lf", get_now_monotonic() - dest->encode_begin_ts);
|
||||
}
|
||||
src = RUN(tmp);
|
||||
|
||||
if (RUN(i_width) != src->width || RUN(i_height) != src->height || RUN(i_format) != src->format) {
|
||||
if (_h264_encoder_configure(enc, src) < 0) {
|
||||
return -1;
|
||||
}
|
||||
RUN(last_online) = -1;
|
||||
}
|
||||
|
||||
bool force_key = (RUN(last_online) != src->online);
|
||||
|
||||
if (_h264_encoder_compress_raw(enc, src, dest, force_key) < 0) {
|
||||
_h264_encoder_cleanup(enc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest->encode_end_ts = get_now_monotonic();
|
||||
LOG_VERBOSE("H264: Compressed new frame: size=%zu, time=%0.3Lf, force_key=%d",
|
||||
dest->used, dest->encode_end_ts - dest->encode_begin_ts, force_key);
|
||||
|
||||
RUN(last_online) = src->online;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _h264_encoder_configure(h264_encoder_s *enc, const frame_s *frame) {
|
||||
LOG_INFO("H264: Reconfiguring MMAL encoder ...");
|
||||
int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, unsigned format) {
|
||||
LOG_INFO("H264: Configuring MMAL encoder ...");
|
||||
|
||||
MMAL_STATUS_T error;
|
||||
|
||||
@ -186,19 +139,21 @@ static int _h264_encoder_configure(h264_encoder_s *enc, const frame_s *frame) {
|
||||
|
||||
# define IFMT(_next) RUN(input_port->format->_next)
|
||||
IFMT(type) = MMAL_ES_TYPE_VIDEO;
|
||||
switch (frame->format) {
|
||||
switch (format) {
|
||||
case V4L2_PIX_FMT_YUYV: IFMT(encoding) = MMAL_ENCODING_YUYV; break;
|
||||
case V4L2_PIX_FMT_UYVY: IFMT(encoding) = MMAL_ENCODING_UYVY; break;
|
||||
case V4L2_PIX_FMT_RGB565: IFMT(encoding) = MMAL_ENCODING_RGB16; break;
|
||||
case V4L2_PIX_FMT_MJPEG:
|
||||
case V4L2_PIX_FMT_JPEG: // See unjpeg.c
|
||||
case V4L2_PIX_FMT_RGB24: IFMT(encoding) = MMAL_ENCODING_RGB24; break;
|
||||
default: assert(0 && "Unsupported input format for MMAL H264 encoder");
|
||||
}
|
||||
IFMT(es->video.width) = align_size(frame->width, 32);
|
||||
IFMT(es->video.height) = align_size(frame->height, 16);
|
||||
IFMT(es->video.width) = align_size(width, 32);
|
||||
IFMT(es->video.height) = align_size(height, 16);
|
||||
IFMT(es->video.crop.x) = 0;
|
||||
IFMT(es->video.crop.y) = 0;
|
||||
IFMT(es->video.crop.width) = frame->width;
|
||||
IFMT(es->video.crop.height) = frame->height;
|
||||
IFMT(es->video.crop.width) = width;
|
||||
IFMT(es->video.crop.height) = height;
|
||||
IFMT(flags) = MMAL_ES_FORMAT_FLAG_FRAMED;
|
||||
RUN(input_port->buffer_size) = 1000 * 1000;
|
||||
RUN(input_port->buffer_num) = RUN(input_port->buffer_num_recommended) * 4;
|
||||
@ -256,9 +211,9 @@ static int _h264_encoder_configure(h264_encoder_s *enc, const frame_s *frame) {
|
||||
ENABLE_PORT(input);
|
||||
ENABLE_PORT(output);
|
||||
|
||||
RUN(i_width) = frame->width;
|
||||
RUN(i_height) = frame->height;
|
||||
RUN(i_format) = frame->format;
|
||||
RUN(width) = width;
|
||||
RUN(height) = height;
|
||||
RUN(format) = format;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -289,17 +244,52 @@ static void _h264_encoder_cleanup(h264_encoder_s *enc) {
|
||||
|
||||
# undef DISABLE_PORT
|
||||
|
||||
RUN(i_width) = 0;
|
||||
RUN(i_height) = 0;
|
||||
RUN(i_format) = 0;
|
||||
RUN(width) = 0;
|
||||
RUN(height) = 0;
|
||||
RUN(format) = 0;
|
||||
RUN(last_online) = -1;
|
||||
}
|
||||
|
||||
int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, frame_s *dest) {
|
||||
frame_copy_meta(src, dest);
|
||||
dest->encode_begin_ts = get_now_monotonic();
|
||||
dest->format = V4L2_PIX_FMT_H264;
|
||||
|
||||
if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) {
|
||||
LOG_DEBUG("H264: Input frame format is JPEG; decoding ...");
|
||||
if (unjpeg(src, RUN(tmp), true) < 0) {
|
||||
return -1;
|
||||
}
|
||||
assert(RUN(tmp->format) == V4L2_PIX_FMT_RGB24);
|
||||
LOG_VERBOSE("H264: JPEG decoded; time=%Lf", get_now_monotonic() - dest->encode_begin_ts);
|
||||
} else {
|
||||
LOG_DEBUG("H264: Copying source to tmp buffer ...");
|
||||
frame_copy(src, RUN(tmp));
|
||||
assert(src->format == RUN(format));
|
||||
LOG_VERBOSE("H264: Source copied; time=%Lf", get_now_monotonic() - dest->encode_begin_ts);
|
||||
}
|
||||
src = RUN(tmp);
|
||||
|
||||
assert(src->used > 0);
|
||||
assert(src->width == RUN(width));
|
||||
assert(src->height == RUN(height));
|
||||
|
||||
bool force_key = (RUN(last_online) != src->online);
|
||||
|
||||
if (_h264_encoder_compress_raw(enc, src, dest, force_key) < 0) {
|
||||
_h264_encoder_cleanup(enc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest->encode_end_ts = get_now_monotonic();
|
||||
LOG_VERBOSE("H264: Compressed new frame: size=%zu, time=%0.3Lf, force_key=%d",
|
||||
dest->used, dest->encode_end_ts - dest->encode_begin_ts, force_key);
|
||||
|
||||
RUN(last_online) = src->online;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _h264_encoder_compress_raw(h264_encoder_s *enc, const frame_s *src, frame_s *dest, bool force_key) {
|
||||
assert(src->used > 0);
|
||||
assert(src->width == RUN(i_width));
|
||||
assert(src->height == RUN(i_height));
|
||||
assert(src->format == RUN(i_format));
|
||||
|
||||
LOG_DEBUG("H264: Compressing new frame; force_key=%d ...", force_key);
|
||||
|
||||
MMAL_STATUS_T error;
|
||||
|
||||
@ -50,9 +50,9 @@ typedef struct {
|
||||
frame_s *tmp;
|
||||
int last_online;
|
||||
|
||||
unsigned i_width;
|
||||
unsigned i_height;
|
||||
unsigned i_format;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned format;
|
||||
} h264_encoder_runtime_s;
|
||||
|
||||
typedef struct {
|
||||
@ -67,4 +67,5 @@ typedef struct {
|
||||
h264_encoder_s *h264_encoder_init(void);
|
||||
void h264_encoder_destroy(h264_encoder_s *enc);
|
||||
|
||||
int h264_encoder_prepare(h264_encoder_s *enc, unsigned width, unsigned height, unsigned format);
|
||||
int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, frame_s *dest);
|
||||
|
||||
@ -428,8 +428,15 @@ static void _h264_stream_destroy(h264_stream_s *h264) {
|
||||
}
|
||||
|
||||
static void _h264_stream_process(h264_stream_s *h264, const frame_s *frame) {
|
||||
if (h264_encoder_compress(h264->enc, frame, h264->dest) == 0) {
|
||||
memsink_server_put(h264->sink, h264->dest);
|
||||
# define NEQ(_field) (frame->_field != h264->enc->run->_field)
|
||||
if (NEQ(width) || NEQ(height) || NEQ(format)) {
|
||||
# undef NEQ
|
||||
h264_encoder_prepare(h264->enc, frame->width, frame->height, frame->format);
|
||||
}
|
||||
if (h264->enc->run->format) {
|
||||
if (h264_encoder_compress(h264->enc, frame, h264->dest) == 0) {
|
||||
memsink_server_put(h264->sink, h264->dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user