mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-26 19:56:33 +00:00
refactoring
This commit is contained in:
@@ -22,6 +22,26 @@
|
||||
|
||||
#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 {
|
||||
const char *name;
|
||||
@@ -43,9 +63,6 @@ static void _worker_job_destroy(void *v_job);
|
||||
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_runtime_s *run;
|
||||
US_CALLOC(run, 1);
|
||||
@@ -62,14 +79,15 @@ us_encoder_s *us_encoder_init(void) {
|
||||
}
|
||||
|
||||
void us_encoder_destroy(us_encoder_s *enc) {
|
||||
if (_ER(m2ms) != NULL) {
|
||||
for (unsigned index = 0; index < _ER(n_m2ms); ++index) {
|
||||
US_DELETE(_ER(m2ms[index]), us_m2m_encoder_destroy)
|
||||
us_encoder_runtime_s *const run = enc->run;
|
||||
if (run->m2ms != NULL) {
|
||||
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));
|
||||
free(enc->run);
|
||||
US_MUTEX_DESTROY(run->mutex);
|
||||
free(run);
|
||||
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) {
|
||||
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);
|
||||
unsigned quality = cap->jpeg_quality;
|
||||
unsigned n_workers = US_MIN(enc->n_workers, DR(n_bufs));
|
||||
us_encoder_type_e type = (run->cpu_forced ? US_ENCODER_TYPE_CPU : enc->type);
|
||||
uint quality = cap->jpeg_quality;
|
||||
uint n_workers = US_MIN(enc->n_workers, cr->n_bufs);
|
||||
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 ...");
|
||||
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 ...");
|
||||
goto use_cpu;
|
||||
}
|
||||
quality = DR(jpeg_quality);
|
||||
quality = cr->jpeg_quality;
|
||||
n_workers = 1;
|
||||
|
||||
} 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"));
|
||||
if (_ER(m2ms) == NULL) {
|
||||
US_CALLOC(_ER(m2ms), n_workers);
|
||||
if (run->m2ms == NULL) {
|
||||
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];
|
||||
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) {
|
||||
_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 {
|
||||
_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;
|
||||
|
||||
use_cpu:
|
||||
type = US_ENCODER_TYPE_CPU;
|
||||
quality = cap->jpeg_quality;
|
||||
use_cpu:
|
||||
type = US_ENCODER_TYPE_CPU;
|
||||
quality = cap->jpeg_quality;
|
||||
|
||||
ok:
|
||||
if (quality == 0) {
|
||||
US_LOG_INFO("Using JPEG quality: encoder default");
|
||||
} else {
|
||||
US_LOG_INFO("Using JPEG quality: %u%%", quality);
|
||||
}
|
||||
ok:
|
||||
if (quality == 0) {
|
||||
US_LOG_INFO("Using JPEG quality: encoder default");
|
||||
} else {
|
||||
US_LOG_INFO("Using JPEG quality: %u%%", quality);
|
||||
}
|
||||
|
||||
US_MUTEX_LOCK(_ER(mutex));
|
||||
_ER(type) = type;
|
||||
_ER(quality) = quality;
|
||||
if (cpu_forced) {
|
||||
_ER(cpu_forced) = true;
|
||||
}
|
||||
US_MUTEX_UNLOCK(_ER(mutex));
|
||||
US_MUTEX_LOCK(run->mutex);
|
||||
run->type = type;
|
||||
run->quality = quality;
|
||||
if (cpu_forced) {
|
||||
run->cpu_forced = true;
|
||||
}
|
||||
US_MUTEX_UNLOCK(run->mutex);
|
||||
|
||||
const long double desired_interval = (
|
||||
cap->desired_fps > 0 && (cap->desired_fps < cap->run->hw_fps || cap->run->hw_fps == 0)
|
||||
? (long double)1 / cap->desired_fps
|
||||
: 0
|
||||
);
|
||||
const ldf desired_interval = (
|
||||
cap->desired_fps > 0 && (cap->desired_fps < cap->run->hw_fps || cap->run->hw_fps == 0)
|
||||
? (ldf)1 / cap->desired_fps
|
||||
: 0
|
||||
);
|
||||
|
||||
enc->run->pool = us_workers_pool_init(
|
||||
"JPEG", "jw", n_workers, desired_interval,
|
||||
_worker_job_init, (void*)enc,
|
||||
_worker_job_destroy,
|
||||
_worker_run_job);
|
||||
|
||||
# undef DR
|
||||
enc->run->pool = us_workers_pool_init(
|
||||
"JPEG", "jw", n_workers, desired_interval,
|
||||
_worker_job_init, (void*)enc,
|
||||
_worker_job_destroy,
|
||||
_worker_run_job);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, unsigned *quality) {
|
||||
US_MUTEX_LOCK(_ER(mutex));
|
||||
*type = _ER(type);
|
||||
*quality = _ER(quality);
|
||||
US_MUTEX_UNLOCK(_ER(mutex));
|
||||
void us_encoder_get_runtime_params(us_encoder_s *enc, us_encoder_type_e *type, uint *quality) {
|
||||
us_encoder_runtime_s *const run = enc->run;
|
||||
US_MUTEX_LOCK(run->mutex);
|
||||
*type = run->type;
|
||||
*quality = run->quality;
|
||||
US_MUTEX_UNLOCK(run->mutex);
|
||||
}
|
||||
|
||||
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) {
|
||||
us_encoder_job_s *job = wr->job;
|
||||
us_encoder_s *enc = job->enc; // Just for _ER()
|
||||
const us_frame_s *src = &job->hw->raw;
|
||||
us_frame_s *dest = job->dest;
|
||||
us_encoder_job_s *const job = wr->job;
|
||||
us_encoder_runtime_s *const run = job->enc->run;
|
||||
const us_frame_s *const src = &job->hw->raw;
|
||||
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",
|
||||
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",
|
||||
wr->name, job->hw->buf.index);
|
||||
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",
|
||||
(_ER(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) {
|
||||
(run->type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), wr->name, job->hw->buf.index);
|
||||
if (us_m2m_encoder_compress(run->m2ms[wr->number], src, dest, false) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -228,11 +246,11 @@ static bool _worker_run_job(us_worker_s *wr) {
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
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_MUTEX_LOCK(_ER(mutex));
|
||||
_ER(cpu_forced) = true;
|
||||
US_MUTEX_UNLOCK(_ER(mutex));
|
||||
return false;
|
||||
error:
|
||||
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_MUTEX_LOCK(run->mutex);
|
||||
run->cpu_forced = true;
|
||||
US_MUTEX_UNLOCK(run->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -22,30 +22,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "../libs/tools.h"
|
||||
#include "../libs/array.h"
|
||||
#include "../libs/threading.h"
|
||||
#include "../libs/logging.h"
|
||||
#include "../libs/types.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"
|
||||
|
||||
|
||||
#define ENCODER_TYPES_STR "CPU, HW, M2M-VIDEO, M2M-IMAGE"
|
||||
|
||||
|
||||
typedef enum {
|
||||
US_ENCODER_TYPE_CPU,
|
||||
US_ENCODER_TYPE_HW,
|
||||
@@ -55,11 +44,11 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
us_encoder_type_e type;
|
||||
unsigned quality;
|
||||
uint quality;
|
||||
bool cpu_forced;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
unsigned n_m2ms;
|
||||
uint n_m2ms;
|
||||
us_m2m_encoder_s **m2ms;
|
||||
|
||||
us_workers_pool_s *pool;
|
||||
@@ -67,7 +56,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
us_encoder_type_e type;
|
||||
unsigned n_workers;
|
||||
uint n_workers;
|
||||
char *m2m_path;
|
||||
|
||||
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_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