refactoring

This commit is contained in:
Devaev Maxim
2021-01-03 12:24:01 +03:00
parent 0ccf540417
commit 3fdd69b444
3 changed files with 43 additions and 35 deletions

View File

@@ -25,6 +25,7 @@
static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame); static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame);
static void _h264_encoder_cleanup(h264_encoder_s *encoder); static void _h264_encoder_cleanup(h264_encoder_s *encoder);
static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key); static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key);
static void _mmal_callback(MMAL_WRAPPER_T *wrapper); static void _mmal_callback(MMAL_WRAPPER_T *wrapper);
@@ -41,7 +42,8 @@ static const char *_mmal_error_to_string(MMAL_STATUS_T error);
h264_encoder_s *h264_encoder_init(void) { h264_encoder_s *h264_encoder_init(void) {
h264_encoder_runtime_s *run; h264_encoder_runtime_s *run;
A_CALLOC(run, 1); A_CALLOC(run, 1);
run->tmp = frame_init("h264_tmp"); run->unjpegged = frame_init("h264_unjpegged_src");
run->last_online = -1;
h264_encoder_s *encoder; h264_encoder_s *encoder;
A_CALLOC(encoder, 1); A_CALLOC(encoder, 1);
@@ -49,7 +51,18 @@ h264_encoder_s *h264_encoder_init(void) {
encoder->bps = 5000 * 1000; // Kbps * 1000 encoder->bps = 5000 * 1000; // Kbps * 1000
encoder->fps = 30; encoder->fps = 30;
encoder->run = run; encoder->run = run;
if (vcos_semaphore_create(&run->handler_sem, "h264_handler_sem", 0) != VCOS_SUCCESS) {
LOG_PERROR("Can't create VCOS semaphore");
goto error;
}
run->i_handler_sem = true;
return encoder; return encoder;
error:
h264_encoder_destroy(encoder);
return NULL;
} }
void h264_encoder_destroy(h264_encoder_s *encoder) { void h264_encoder_destroy(h264_encoder_s *encoder) {
@@ -57,43 +70,37 @@ void h264_encoder_destroy(h264_encoder_s *encoder) {
if (RUN(i_handler_sem)) { if (RUN(i_handler_sem)) {
vcos_semaphore_delete(&RUN(handler_sem)); vcos_semaphore_delete(&RUN(handler_sem));
} }
frame_destroy(RUN(tmp)); frame_destroy(RUN(unjpegged));
free(encoder); free(encoder);
} }
int h264_encoder_compress(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key) { int h264_encoder_compress(h264_encoder_s *encoder, const frame_s *src, frame_s *dest) {
assert(src->used > 0); assert(src->used > 0);
assert(src->width > 0); assert(src->width > 0);
assert(src->height > 0); assert(src->height > 0);
assert(src->format > 0); assert(src->format > 0);
if (!RUN(i_handler_sem)) {
if (vcos_semaphore_create(&RUN(handler_sem), "h264_handler_sem", 0) != VCOS_SUCCESS) {
LOG_PERROR("Can't create VCOS semaphore");
return -1;
}
RUN(i_handler_sem) = true;
}
if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) { if (src->format == V4L2_PIX_FMT_MJPEG || src->format == V4L2_PIX_FMT_JPEG) {
LOG_DEBUG("Input frame format is JPEG; decoding ..."); LOG_DEBUG("Input frame format is JPEG; decoding ...");
if (unjpeg(src, RUN(tmp), true) < 0) { if (unjpeg(src, RUN(unjpegged), true) < 0) {
return -1; return -1;
} }
src = RUN(tmp); src = RUN(unjpegged);
} }
if (RUN(width) != src->width || RUN(height) != src->height || RUN(format) != src->format) { if (RUN(i_width) != src->width || RUN(i_height) != src->height || RUN(i_format) != src->format) {
if (_h264_encoder_configure(encoder, src) < 0) { if (_h264_encoder_configure(encoder, src) < 0) {
return -1; return -1;
} }
force_key = true; RUN(last_online) = -1;
} }
if (_h264_encoder_compress_raw(encoder, src, dest, force_key) < 0) { if (_h264_encoder_compress_raw(encoder, src, dest, (RUN(last_online) != src->online)) < 0) {
_h264_encoder_cleanup(encoder); _h264_encoder_cleanup(encoder);
return -1; return -1;
} }
RUN(last_online) = src->online;
return 0; return 0;
} }
@@ -133,8 +140,6 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
_h264_encoder_cleanup(encoder); _h264_encoder_cleanup(encoder);
LOG_INFO("Applying H264 configuration ...");
if ((error = mmal_wrapper_create(&RUN(wrapper), MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER)) != MMAL_SUCCESS) { if ((error = mmal_wrapper_create(&RUN(wrapper), MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER)) != MMAL_SUCCESS) {
LOG_ERROR_MMAL(error, "Can't create MMAL wrapper"); LOG_ERROR_MMAL(error, "Can't create MMAL wrapper");
goto error; goto error;
@@ -221,9 +226,9 @@ static int _h264_encoder_configure(h264_encoder_s *encoder, const frame_s *frame
ENABLE_PORT(input); ENABLE_PORT(input);
ENABLE_PORT(output); ENABLE_PORT(output);
RUN(width) = frame->width; RUN(i_width) = frame->width;
RUN(height) = frame->height; RUN(i_height) = frame->height;
RUN(format) = frame->format; RUN(i_format) = frame->format;
return 0; return 0;
@@ -261,16 +266,16 @@ static void _h264_encoder_cleanup(h264_encoder_s *encoder) {
RUN(wrapper) = NULL; RUN(wrapper) = NULL;
} }
RUN(width) = 0; RUN(i_width) = 0;
RUN(height) = 0; RUN(i_height) = 0;
RUN(format) = 0; RUN(i_format) = 0;
} }
static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key) { static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key) {
assert(src->used > 0); assert(src->used > 0);
assert(src->width == encoder->width); assert(src->width == encoder->i_width);
assert(src->height == encoder->height); assert(src->height == encoder->i_height);
assert(src->format == encoder->format); assert(src->format == encoder->i_format);
MMAL_STATUS_T error; MMAL_STATUS_T error;
@@ -339,8 +344,8 @@ static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *sr
} }
dest->encode_end_ts = get_now_monotonic(); dest->encode_end_ts = get_now_monotonic();
LOG_VERBOSE("Compressed new H264 frame: force_key=%d, size=%zu, time=%0.3Lf", LOG_VERBOSE("Compressed new H264 frame: size=%zu, time=%0.3Lf, force_key=%d",
force_key, dest->used, dest->encode_end_ts - dest->encode_begin_ts); dest->used, dest->encode_end_ts - dest->encode_begin_ts, force_key);
return 0; return 0;
} }

View File

@@ -47,16 +47,19 @@ typedef struct {
VCOS_SEMAPHORE_T handler_sem; VCOS_SEMAPHORE_T handler_sem;
bool i_handler_sem; bool i_handler_sem;
unsigned width; frame_s *unjpegged;
unsigned height; int last_online;
unsigned format;
frame_s *tmp; unsigned i_width;
unsigned i_height;
unsigned i_format;
} h264_encoder_runtime_s; } h264_encoder_runtime_s;
typedef struct { typedef struct {
unsigned gop; // Interval between keyframes unsigned gop; // Interval between keyframes
unsigned bps; // Bit-per-sec unsigned bps; // Bit-per-sec
unsigned fps; unsigned fps;
h264_encoder_runtime_s *run; h264_encoder_runtime_s *run;
} h264_encoder_s; } h264_encoder_s;
@@ -64,4 +67,4 @@ typedef struct {
h264_encoder_s *h264_encoder_init(void); h264_encoder_s *h264_encoder_init(void);
void h264_encoder_destroy(h264_encoder_s *encoder); void h264_encoder_destroy(h264_encoder_s *encoder);
int h264_encoder_compress(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key); int h264_encoder_compress(h264_encoder_s *encoder, const frame_s *src, frame_s *dest);

View File

@@ -25,7 +25,7 @@ int main(void) {
int error = 0; int error = 0;
while ((error = memsink_client_get(memsink, src)) != -1) { while ((error = memsink_client_get(memsink, src)) != -1) {
if (error == 0 /*|| (error == -2 && src->used > 0)*/) { if (error == 0 /*|| (error == -2 && src->used > 0)*/) {
if (!h264_encoder_compress(encoder, src, dest, false)) { if (!h264_encoder_compress(encoder, src, dest)) {
LOG_INFO("frame %Lf", get_now_monotonic() - dest->grab_ts); LOG_INFO("frame %Lf", get_now_monotonic() - dest->grab_ts);
fwrite(dest->data, 1, dest->used, fp); fwrite(dest->data, 1, dest->used, fp);
fflush(fp); fflush(fp);