Browse Source

Expose radio compressor settings to publication workers

master
evgeny 5 days ago
parent
commit
77acdb2d65
  1. 7
      src/stream/stream_publisher.c
  2. 1
      src/stream/stream_publisher.h
  3. 31
      tools/chatgui/src/stream_video_encoder.h

7
src/stream/stream_publisher.c

@ -4,6 +4,7 @@
#include "../../lib/debug_config.h"
#include "../../lib/u_async.h"
#include "../utun_instance.h"
#include "../chat/chat_setting.h"
#include "stream.h"
#include "stream_network.h"
#include "stream_publisher.h"
@ -82,6 +83,9 @@ static void publisher_stats(void *arg) {
pthread_mutex_lock(&p->lock); p->stats_timer = NULL;
if (p->handle && stream_handle_active(p->handle)) {
uint64_t now = get_time_us(); struct etcp_tx_snapshot transport; struct stream_info info;
p->status.compressor_enabled = chat_setting_get_int(p->inst, "radio_compressor_enabled", 1);
p->status.compressor_max_gain_db = chat_setting_get_int(p->inst, "radio_compressor_max_gain_db", 15);
p->status.compressor_rise_rate = chat_setting_get_int(p->inst, "compressor_rise_rate", 2);
if (etcp_tx_get_snapshot(p->inst, now, &transport) == 0 && stream_get_info(p->handle, &info) == STREAM_OK) {
p->status.sample_us = now; p->status.video_bytes = p->video.bytes - (p->video.head ? p->video.head->offset : 0);
p->status.audio_bytes = p->audio.bytes; p->status.stream_bytes = stream_network_pending_bytes(p->inst, &info.descriptor);
@ -155,6 +159,9 @@ static void publisher_process(void *arg) {
publisher_close(p, p->stopping ? 0 : STREAM_CLOSE_FAILED);
} else {
p->status.epoch = info.descriptor.source_epoch; p->status.state = STREAM_PUBLISHER_LIVE;
p->status.compressor_enabled = chat_setting_get_int(p->inst, "radio_compressor_enabled", 1);
p->status.compressor_max_gain_db = chat_setting_get_int(p->inst, "radio_compressor_max_gain_db", 15);
p->status.compressor_rise_rate = chat_setting_get_int(p->inst, "compressor_rise_rate", 2);
p->stats_timer = uasync_set_timeout(p->inst->ua, 1000, p, publisher_stats, "publisher_stats");
if (!p->stats_timer) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "publisher stats start failed"); publisher_close(p, STREAM_CLOSE_FAILED); }
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "publisher opened id=%llu group=%llx epoch=%llx codec=%u size=%ux%u audio=%u",

1
src/stream/stream_publisher.h

@ -17,6 +17,7 @@ struct stream_publisher_status {
uint64_t id, epoch, sample_us, video_bytes, audio_bytes, stream_bytes, transport_bytes, inflight_bytes, acked_1s, total_bytes;
unsigned connections;
int state, reason, need_key;
int compressor_enabled, compressor_max_gain_db, compressor_rise_rate;
};
int stream_publisher_create(struct stream_publisher **out, struct UTUN_INSTANCE *inst);
void stream_publisher_destroy(struct stream_publisher *publisher);

31
tools/chatgui/src/stream_video_encoder.h

@ -0,0 +1,31 @@
/* FFmpeg live encoder: один worker владеет контекстом, конвертером и decoder configuration.
* open/encode/close последовательны; каждый KEY содержит uAV2 envelope. Пакеты имеют capture PTS.
* Encoder открывается по фактическим возможностям; GPU имеет приоритет, затем software того же кодека. */
#pragma once
#include <QByteArray>
#include <QImage>
#include <QString>
#include <QList>
#include <memory>
#include <cstdint>
struct StreamVideoConfig {
int width = 1280, height = 720, fps = 30, bitrate = 2500000, codec = 1, rotation = 0;
bool operator==(const StreamVideoConfig&) const = default;
};
struct StreamEncodedFrame { QByteArray data; uint64_t pts = 0; bool key = false; };
class StreamVideoEncoder {
public:
StreamVideoEncoder();
~StreamVideoEncoder();
bool open(const StreamVideoConfig& config);
void close();
bool encode(const QImage& image, uint64_t pts, bool key, QList<StreamEncodedFrame>& output);
QString error() const;
QString name() const;
static QList<int> available(); // реальная проба открытия и первого KEY; вызывать вне GUI
static QString codecName(int codec);
private:
struct Impl;
std::unique_ptr<Impl> m;
};
Loading…
Cancel
Save