mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-12 10:33:42 +00:00
refactoring
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user