refactoring

This commit is contained in:
Maxim Devaev
2024-04-04 02:36:28 +03:00
parent 0a639eabca
commit ae2f270f50
2 changed files with 97 additions and 90 deletions

View File

@@ -22,6 +22,26 @@
#include "encoder.h" #include "encoder.h"
#include <stdlib.h>
#include <strings.h>
#include <assert.h>
#include <pthread.h>
#include "../libs/types.h"
#include "../libs/tools.h"
#include "../libs/array.h"
#include "../libs/threading.h"
#include "../libs/logging.h"
#include "../libs/frame.h"
#include "../libs/capture.h"
#include "workers.h"
#include "m2m.h"
#include "encoders/cpu/encoder.h"
#include "encoders/hw/encoder.h"
static const struct { static const struct {
const char *name; const char *name;
@@ -43,9 +63,6 @@ static void _worker_job_destroy(void *v_job);
static bool _worker_run_job(us_worker_s *wr); static bool _worker_run_job(us_worker_s *wr);
#define _ER(x_next) enc->run->x_next
us_encoder_s *us_encoder_init(void) { us_encoder_s *us_encoder_init(void) {
us_encoder_runtime_s *run; us_encoder_runtime_s *run;
US_CALLOC(run, 1); US_CALLOC(run, 1);
@@ -62,14 +79,15 @@ us_encoder_s *us_encoder_init(void) {
} }
void us_encoder_destroy(us_encoder_s *enc) { void us_encoder_destroy(us_encoder_s *enc) {
if (_ER(m2ms) != NULL) { us_encoder_runtime_s *const run = enc->run;
for (unsigned index = 0; index < _ER(n_m2ms); ++index) { if (run->m2ms != NULL) {
US_DELETE(_ER(m2ms[index]), us_m2m_encoder_destroy) for (uint index = 0; index < run->n_m2ms; ++index) {
US_DELETE(run->m2ms[index], us_m2m_encoder_destroy);
} }
free(_ER(m2ms)); free(run->m2ms);
} }
US_MUTEX_DESTROY(_ER(mutex)); US_MUTEX_DESTROY(run->mutex);
free(enc->run); free(run);
free(enc); free(enc);
} }
@@ -92,79 +110,78 @@ const char *us_encoder_type_to_string(us_encoder_type_e type) {
} }
void us_encoder_open(us_encoder_s *enc, us_capture_s *cap) { void us_encoder_open(us_encoder_s *enc, us_capture_s *cap) {
assert(enc->run->pool == NULL); us_encoder_runtime_s *const run = enc->run;
us_capture_runtime_s *const cr = cap->run;
# define DR(x_next) cap->run->x_next assert(run->pool == NULL);
us_encoder_type_e type = (_ER(cpu_forced) ? US_ENCODER_TYPE_CPU : enc->type); us_encoder_type_e type = (run->cpu_forced ? US_ENCODER_TYPE_CPU : enc->type);
unsigned quality = cap->jpeg_quality; uint quality = cap->jpeg_quality;
unsigned n_workers = US_MIN(enc->n_workers, DR(n_bufs)); uint n_workers = US_MIN(enc->n_workers, cr->n_bufs);
bool cpu_forced = false; bool cpu_forced = false;
if (us_is_jpeg(DR(format)) && type != US_ENCODER_TYPE_HW) { if (us_is_jpeg(cr->format) && type != US_ENCODER_TYPE_HW) {
US_LOG_INFO("Switching to HW encoder: the input is (M)JPEG ..."); US_LOG_INFO("Switching to HW encoder: the input is (M)JPEG ...");
type = US_ENCODER_TYPE_HW; type = US_ENCODER_TYPE_HW;
} }
if (type == US_ENCODER_TYPE_HW) { if (type == US_ENCODER_TYPE_HW) {
if (!us_is_jpeg(DR(format))) { if (!us_is_jpeg(cr->format)) {
US_LOG_INFO("Switching to CPU encoder: the input format is not (M)JPEG ..."); US_LOG_INFO("Switching to CPU encoder: the input format is not (M)JPEG ...");
goto use_cpu; goto use_cpu;
} }
quality = DR(jpeg_quality); quality = cr->jpeg_quality;
n_workers = 1; n_workers = 1;
} else if (type == US_ENCODER_TYPE_M2M_VIDEO || type == US_ENCODER_TYPE_M2M_IMAGE) { } else if (type == US_ENCODER_TYPE_M2M_VIDEO || type == US_ENCODER_TYPE_M2M_IMAGE) {
US_LOG_DEBUG("Preparing M2M-%s encoder ...", (type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE")); US_LOG_DEBUG("Preparing M2M-%s encoder ...", (type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"));
if (_ER(m2ms) == NULL) { if (run->m2ms == NULL) {
US_CALLOC(_ER(m2ms), n_workers); US_CALLOC(run->m2ms, n_workers);
} }
for (; _ER(n_m2ms) < n_workers; ++_ER(n_m2ms)) { for (; run->n_m2ms < n_workers; ++run->n_m2ms) {
// Начинаем с нуля и доинициализируем на следующих заходах при необходимости // Начинаем с нуля и доинициализируем на следующих заходах при необходимости
char name[32]; char name[32];
US_SNPRINTF(name, 31, "JPEG-%u", _ER(n_m2ms)); US_SNPRINTF(name, 31, "JPEG-%u", run->n_m2ms);
if (type == US_ENCODER_TYPE_M2M_VIDEO) { if (type == US_ENCODER_TYPE_M2M_VIDEO) {
_ER(m2ms[_ER(n_m2ms)]) = us_m2m_mjpeg_encoder_init(name, enc->m2m_path, quality); run->m2ms[run->n_m2ms] = us_m2m_mjpeg_encoder_init(name, enc->m2m_path, quality);
} else { } else {
_ER(m2ms[_ER(n_m2ms)]) = us_m2m_jpeg_encoder_init(name, enc->m2m_path, quality); run->m2ms[run->n_m2ms] = us_m2m_jpeg_encoder_init(name, enc->m2m_path, quality);
} }
} }
} }
goto ok; goto ok;
use_cpu: use_cpu:
type = US_ENCODER_TYPE_CPU; type = US_ENCODER_TYPE_CPU;
quality = cap->jpeg_quality; quality = cap->jpeg_quality;
ok: ok:
if (quality == 0) { if (quality == 0) {
US_LOG_INFO("Using JPEG quality: encoder default"); US_LOG_INFO("Using JPEG quality: encoder default");
} else { } else {
US_LOG_INFO("Using JPEG quality: %u%%", quality); US_LOG_INFO("Using JPEG quality: %u%%", quality);
} }
US_MUTEX_LOCK(_ER(mutex)); US_MUTEX_LOCK(run->mutex);
_ER(type) = type; run->type = type;
_ER(quality) = quality; run->quality = quality;
if (cpu_forced) { if (cpu_forced) {
_ER(cpu_forced) = true; run->cpu_forced = true;
} }
US_MUTEX_UNLOCK(_ER(mutex)); US_MUTEX_UNLOCK(run->mutex);
const long double desired_interval = ( const ldf desired_interval = (
cap->desired_fps > 0 && (cap->desired_fps < cap->run->hw_fps || cap->run->hw_fps == 0) cap->desired_fps > 0 && (cap->desired_fps < cap->run->hw_fps || cap->run->hw_fps == 0)
? (long double)1 / cap->desired_fps ? (ldf)1 / cap->desired_fps
: 0 : 0
); );
enc->run->pool = us_workers_pool_init( enc->run->pool = us_workers_pool_init(
"JPEG", "jw", n_workers, desired_interval, "JPEG", "jw", n_workers, desired_interval,
_worker_job_init, (void*)enc, _worker_job_init, (void*)enc,
_worker_job_destroy, _worker_job_destroy,
_worker_run_job); _worker_run_job);
# undef DR
} }
void us_encoder_close(us_encoder_s *enc) { void us_encoder_close(us_encoder_s *enc) {
@@ -172,11 +189,12 @@ void us_encoder_close(us_encoder_s *enc) {
US_DELETE(enc->run->pool, us_workers_pool_destroy); US_DELETE(enc->run->pool, us_workers_pool_destroy);
} }
void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, unsigned *quality) { void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, uint *quality) {
US_MUTEX_LOCK(_ER(mutex)); us_encoder_runtime_s *const run = enc->run;
*type = _ER(type); US_MUTEX_LOCK(run->mutex);
*quality = _ER(quality); *type = run->type;
US_MUTEX_UNLOCK(_ER(mutex)); *quality = run->quality;
US_MUTEX_UNLOCK(run->mutex);
} }
static void *_worker_job_init(void *v_enc) { static void *_worker_job_init(void *v_enc) {
@@ -194,25 +212,25 @@ static void _worker_job_destroy(void *v_job) {
} }
static bool _worker_run_job(us_worker_s *wr) { static bool _worker_run_job(us_worker_s *wr) {
us_encoder_job_s *job = wr->job; us_encoder_job_s *const job = wr->job;
us_encoder_s *enc = job->enc; // Just for _ER() us_encoder_runtime_s *const run = job->enc->run;
const us_frame_s *src = &job->hw->raw; const us_frame_s *const src = &job->hw->raw;
us_frame_s *dest = job->dest; us_frame_s *const dest = job->dest;
if (_ER(type) == US_ENCODER_TYPE_CPU) { if (run->type == US_ENCODER_TYPE_CPU) {
US_LOG_VERBOSE("Compressing JPEG using CPU: worker=%s, buffer=%u", US_LOG_VERBOSE("Compressing JPEG using CPU: worker=%s, buffer=%u",
wr->name, job->hw->buf.index); wr->name, job->hw->buf.index);
us_cpu_encoder_compress(src, dest, _ER(quality)); us_cpu_encoder_compress(src, dest, run->quality);
} else if (_ER(type) == US_ENCODER_TYPE_HW) { } else if (run->type == US_ENCODER_TYPE_HW) {
US_LOG_VERBOSE("Compressing JPEG using HW (just copying): worker=%s, buffer=%u", US_LOG_VERBOSE("Compressing JPEG using HW (just copying): worker=%s, buffer=%u",
wr->name, job->hw->buf.index); wr->name, job->hw->buf.index);
us_hw_encoder_compress(src, dest); us_hw_encoder_compress(src, dest);
} else if (_ER(type) == US_ENCODER_TYPE_M2M_VIDEO || _ER(type) == US_ENCODER_TYPE_M2M_IMAGE) { } else if (run->type == US_ENCODER_TYPE_M2M_VIDEO || run->type == US_ENCODER_TYPE_M2M_IMAGE) {
US_LOG_VERBOSE("Compressing JPEG using M2M-%s: worker=%s, buffer=%u", US_LOG_VERBOSE("Compressing JPEG using M2M-%s: worker=%s, buffer=%u",
(_ER(type) == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), wr->name, job->hw->buf.index); (run->type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), wr->name, job->hw->buf.index);
if (us_m2m_encoder_compress(_ER(m2ms[wr->number]), src, dest, false) < 0) { if (us_m2m_encoder_compress(run->m2ms[wr->number], src, dest, false) < 0) {
goto error; goto error;
} }
@@ -228,11 +246,11 @@ static bool _worker_run_job(us_worker_s *wr) {
return true; return true;
error: error:
US_LOG_ERROR("Compression failed: worker=%s, buffer=%u", wr->name, job->hw->buf.index); US_LOG_ERROR("Compression failed: worker=%s, buffer=%u", wr->name, job->hw->buf.index);
US_LOG_ERROR("Error while compressing buffer, falling back to CPU"); US_LOG_ERROR("Error while compressing buffer, falling back to CPU");
US_MUTEX_LOCK(_ER(mutex)); US_MUTEX_LOCK(run->mutex);
_ER(cpu_forced) = true; run->cpu_forced = true;
US_MUTEX_UNLOCK(_ER(mutex)); US_MUTEX_UNLOCK(run->mutex);
return false; return false;
} }

View File

@@ -22,30 +22,19 @@
#pragma once #pragma once
#include <stdlib.h>
#include <stdbool.h>
#include <strings.h>
#include <assert.h>
#include <pthread.h> #include <pthread.h>
#include <linux/videodev2.h>
#include "../libs/tools.h" #include "../libs/types.h"
#include "../libs/array.h"
#include "../libs/threading.h"
#include "../libs/logging.h"
#include "../libs/frame.h" #include "../libs/frame.h"
#include "../libs/capture.h" #include "../libs/capture.h"
#include "workers.h" #include "workers.h"
#include "m2m.h" #include "m2m.h"
#include "encoders/cpu/encoder.h"
#include "encoders/hw/encoder.h"
#define ENCODER_TYPES_STR "CPU, HW, M2M-VIDEO, M2M-IMAGE" #define ENCODER_TYPES_STR "CPU, HW, M2M-VIDEO, M2M-IMAGE"
typedef enum { typedef enum {
US_ENCODER_TYPE_CPU, US_ENCODER_TYPE_CPU,
US_ENCODER_TYPE_HW, US_ENCODER_TYPE_HW,
@@ -55,11 +44,11 @@ typedef enum {
typedef struct { typedef struct {
us_encoder_type_e type; us_encoder_type_e type;
unsigned quality; uint quality;
bool cpu_forced; bool cpu_forced;
pthread_mutex_t mutex; pthread_mutex_t mutex;
unsigned n_m2ms; uint n_m2ms;
us_m2m_encoder_s **m2ms; us_m2m_encoder_s **m2ms;
us_workers_pool_s *pool; us_workers_pool_s *pool;
@@ -67,7 +56,7 @@ typedef struct {
typedef struct { typedef struct {
us_encoder_type_e type; us_encoder_type_e type;
unsigned n_workers; uint n_workers;
char *m2m_path; char *m2m_path;
us_encoder_runtime_s *run; us_encoder_runtime_s *run;
@@ -89,4 +78,4 @@ const char *us_encoder_type_to_string(us_encoder_type_e type);
void us_encoder_open(us_encoder_s *enc, us_capture_s *cap); void us_encoder_open(us_encoder_s *enc, us_capture_s *cap);
void us_encoder_close(us_encoder_s *enc); void us_encoder_close(us_encoder_s *enc);
void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, unsigned *quality); void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, uint *quality);