refactoring

This commit is contained in:
Maxim Devaev
2021-12-11 01:17:34 +03:00
parent 55e0a096e7
commit e14644572b
5 changed files with 67 additions and 76 deletions

View File

@@ -115,41 +115,18 @@ workers_pool_s *encoder_workers_pool_init(encoder_s *enc, device_s *dev) {
n_workers = 1;
} else if (type == ENCODER_TYPE_M2M_VIDEO || type == ENCODER_TYPE_M2M_IMAGE) {
LOG_DEBUG("Preparing M2M encoder ...");
LOG_DEBUG("Preparing M2M-%s encoder ...", (type == ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"));
if (ER(m2ms) == NULL) {
A_CALLOC(ER(m2ms), n_workers);
}
// Начинаем с нуля и доинициализируем на следующих заходах при необходимости
if (ER(n_m2ms) < n_workers) {
for (; ER(n_m2ms) < n_workers; ++ER(n_m2ms)) {
// Начинаем с нуля и доинициализируем на следующих заходах при необходимости
char name[32];
snprintf(name, 32, "JPEG-%u", ER(n_m2ms));
if (type == ENCODER_TYPE_M2M_VIDEO) {
double b_min = ENCODER_M2M_BITRATE_MIN;
double b_max = ENCODER_M2M_BITRATE_MAX;
double step = ENCODER_M2M_BITRATE_STEP;
double bitrate = log10(quality) * (b_max - b_min) / 2 + b_min;
bitrate = step * round(bitrate / step);
for (; ER(n_m2ms) < n_workers; ++ER(n_m2ms)) {
assert(bitrate > 0);
char name[32];
snprintf(name, 32, "JPEG-%u", ER(n_m2ms));
m2m_option_s options[] = {
{"BITRATE", true, V4L2_CID_MPEG_VIDEO_BITRATE, bitrate * 1000},
{NULL, false, 0, 0},
};
ER(m2ms[ER(n_m2ms)]) = m2m_encoder_init(name, enc->m2m_path, V4L2_PIX_FMT_MJPEG, 0, options);
}
ER(m2ms[ER(n_m2ms)]) = m2m_mjpeg_encoder_init(name, enc->m2m_path, quality);
} else {
for (; ER(n_m2ms) < n_workers; ++ER(n_m2ms)) {
char name[32];
snprintf(name, 32, "JPEG-%u", ER(n_m2ms));
m2m_option_s options[] = {
{"QUALITY", true, V4L2_CID_JPEG_COMPRESSION_QUALITY, quality},
{NULL, false, 0, 0},
};
ER(m2ms[ER(n_m2ms)]) = m2m_encoder_init(name, enc->m2m_path, V4L2_PIX_FMT_JPEG, 0, options);
}
ER(m2ms[ER(n_m2ms)]) = m2m_jpeg_encoder_init(name, enc->m2m_path, quality);
}
}
@@ -238,7 +215,7 @@ static bool _worker_run_job(worker_s *wr) {
hw_encoder_compress(src, dest);
} else if (ER(type) == ENCODER_TYPE_M2M_VIDEO || ER(type) == ENCODER_TYPE_M2M_IMAGE) {
LOG_VERBOSE("Compressing buffer using M2M");
LOG_VERBOSE("Compressing buffer using M2M-%s", (ER(type) == ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"));
if (m2m_encoder_ensure_ready(ER(m2ms[wr->number]), src) < 0) {
goto error;
}

View File

@@ -25,7 +25,6 @@
#include <stdlib.h>
#include <stdbool.h>
#include <strings.h>
#include <math.h>
#include <assert.h>
#include <pthread.h>
@@ -44,22 +43,6 @@
#include "encoders/hw/encoder.h"
#ifndef CFG_ENCODER_M2M_BITRATE_MIN
# define CFG_ENCODER_M2M_BITRATE_MIN 25
#endif
#define ENCODER_M2M_BITRATE_MIN ((unsigned)CFG_ENCODER_M2M_BITRATE_MIN)
#ifndef CFG_ENCODER_M2M_BITRATE_MAX
# define CFG_ENCODER_M2M_BITRATE_MAX 25000
#endif
#define ENCODER_M2M_BITRATE_MAX ((unsigned)CFG_ENCODER_M2M_BITRATE_MAX)
#ifndef CFG_ENCODER_M2M_BITRATE_STEP
# define CFG_ENCODER_M2M_BITRATE_STEP 25
#endif
#define ENCODER_M2M_BITRATE_STEP ((unsigned)CFG_ENCODER_M2M_BITRATE_STEP)
#define ENCODER_TYPES_STR "CPU, HW, M2M-VIDEO, M2M-IMAGE, NOOP"
typedef enum {

View File

@@ -30,29 +30,7 @@ h264_stream_s *h264_stream_init(memsink_s *sink, const char *path, unsigned bitr
h264->tmp_src = frame_init();
h264->dest = frame_init();
atomic_init(&h264->online, false);
# define OPTION(_required, _key, _value) {#_key, _required, V4L2_CID_MPEG_VIDEO_##_key, _value}
m2m_option_s options[] = {
OPTION(true, BITRATE, bitrate * 1000),
OPTION(false, BITRATE_PEAK, bitrate * 1000),
OPTION(true, H264_I_PERIOD, gop),
OPTION(true, H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE),
OPTION(true, H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0),
OPTION(true, REPEAT_SEQ_HEADER, 1),
OPTION(false, H264_MIN_QP, 16),
OPTION(false, H264_MAX_QP, 32),
{NULL, false, 0, 0},
};
# undef OPTION
// FIXME: 30 or 0? https://github.com/6by9/yavta/blob/master/yavta.c#L2100
// По логике вещей правильно 0, но почему-то на низких разрешениях типа 640x480
// енкодер через несколько секунд перестает производить корректные фреймы.
// TODO: Это было актуально для MMAL, надо проверить для V4L2.
h264->enc = m2m_encoder_init("H264", path, V4L2_PIX_FMT_H264, 30, options);
h264->enc = m2m_h264_encoder_init("H264", path, bitrate, gop);
return h264;
}

View File

@@ -23,6 +23,8 @@
#include "m2m.h"
static m2m_encoder_s *_m2m_encoder_init(const char *name, const char *path, unsigned format, unsigned fps, m2m_option_s *options);
static bool _m2m_encoder_is_prepared_for(m2m_encoder_s *enc, const frame_s *frame);
static int _m2m_encoder_prepare(m2m_encoder_s *enc, const frame_s *frame);
@@ -42,9 +44,57 @@ static int _m2m_encoder_compress_raw(m2m_encoder_s *enc, const frame_s *src, fra
#define E_LOG_DEBUG(_msg, ...) LOG_DEBUG("%s: " _msg, enc->name, ##__VA_ARGS__)
m2m_encoder_s *m2m_encoder_init(const char *name, const char *path, unsigned format, unsigned fps, m2m_option_s *options) {
assert(format == V4L2_PIX_FMT_H264 || format == V4L2_PIX_FMT_JPEG || format == V4L2_PIX_FMT_MJPEG);
m2m_encoder_s *m2m_h264_encoder_init(const char *name, const char *path, unsigned bitrate, unsigned gop) {
# define OPTION(_required, _key, _value) {#_key, _required, V4L2_CID_MPEG_VIDEO_##_key, _value}
m2m_option_s options[] = {
OPTION(true, BITRATE, bitrate * 1000),
// OPTION(false, BITRATE_PEAK, bitrate * 1000),
OPTION(true, H264_I_PERIOD, gop),
OPTION(true, H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE),
OPTION(true, H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0),
OPTION(true, REPEAT_SEQ_HEADER, 1),
OPTION(false, H264_MIN_QP, 16),
OPTION(false, H264_MAX_QP, 32),
{NULL, false, 0, 0},
};
# undef OPTION
// FIXME: 30 or 0? https://github.com/6by9/yavta/blob/master/yavta.c#L2100
// По логике вещей правильно 0, но почему-то на низких разрешениях типа 640x480
// енкодер через несколько секунд перестает производить корректные фреймы.
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_H264, 30, options);
}
m2m_encoder_s *m2m_mjpeg_encoder_init(const char *name, const char *path, unsigned quality) {
const double b_min = 25;
const double b_max = 25000;
const double step = 25;
double bitrate = log10(quality) * (b_max - b_min) / 2 + b_min;
bitrate = step * round(bitrate / step);
bitrate *= 1000; // From Kbps
assert(bitrate > 0);
m2m_option_s options[] = {
{"BITRATE", true, V4L2_CID_MPEG_VIDEO_BITRATE, bitrate},
{NULL, false, 0, 0},
};
// FIXME: То же самое про 30 or 0, но еще даже не проверено на низких разрешениях
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_MJPEG, 30, options);
}
m2m_encoder_s *m2m_jpeg_encoder_init(const char *name, const char *path, unsigned quality) {
m2m_option_s options[] = {
{"QUALITY", true, V4L2_CID_JPEG_COMPRESSION_QUALITY, quality},
{NULL, false, 0, 0},
};
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_JPEG, 30, options);
}
static m2m_encoder_s *_m2m_encoder_init(const char *name, const char *path, unsigned format, unsigned fps, m2m_option_s *options) {
LOG_INFO("%s: Initializing encoder ...", name);
m2m_encoder_s *enc;
@@ -159,8 +209,8 @@ static int _m2m_encoder_prepare(m2m_encoder_s *enc, const frame_s *frame) {
fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;
fmt.fmt.pix_mp.num_planes = 1;
//fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0;
//fmt.fmt.pix_mp.plane_fmt[0].sizeimage = 512 << 10;
// fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0;
// fmt.fmt.pix_mp.plane_fmt[0].sizeimage = 512 << 10;
E_LOG_DEBUG("Configuring OUTPUT format ...");
E_XIOCTL(VIDIOC_S_FMT, &fmt, "Can't set OUTPUT format");
if (fmt.fmt.pix_mp.pixelformat != enc->output_format) {

View File

@@ -26,6 +26,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
@@ -78,7 +79,9 @@ typedef struct {
} m2m_encoder_s;
m2m_encoder_s *m2m_encoder_init(const char *name, const char *path, unsigned format, unsigned fps, m2m_option_s *options);
m2m_encoder_s *m2m_h264_encoder_init(const char *name, const char *path, unsigned bitrate, unsigned gop);
m2m_encoder_s *m2m_mjpeg_encoder_init(const char *name, const char *path, unsigned quality);
m2m_encoder_s *m2m_jpeg_encoder_init(const char *name, const char *path, unsigned quality);
void m2m_encoder_destroy(m2m_encoder_s *enc);
int m2m_encoder_ensure_ready(m2m_encoder_s *enc, const frame_s *frame);