refactor: STCP connections as ETCP links (is_tcp)
- Add is_tcp, tcp_link, tcp_reconnect_* fields to ETCP_LINK - Remove transport_link from ETCP_CONN, add tcp_link_count - stcp_link: replace embedded etcp_conn with pointer; add etcp_link backpointer - stcp_link: link_rx_cb routes ETCP data to etcp_conn_input - stcp_link: call on_close_cb in close - New TCP functions: etcp_link_enter_ready_tcp, etcp_tcp_link_start_connect, etcp_tcp_link_start_reconnect, tcp_link_close_cb, etcp_tcp_send - etcp_link_new: handle NULL conn for TCP links; skip enter_init for TCP - etcp_link_close: close stcp_link for TCP - etcp_encrypt_send: redirect TCP to etcp_tcp_send (skips AES-CCM) - tcp_server_on_link: create ETCP_LINK(is_tcp=1) + enter_ready_tcp - etcp_connect: TCP addrs -> etcp_tcp_link_start_connect - Remove ctx->tcp_link/tcp_ready - test_stcp_traffic: find stcp_link via links->is_tcp instead of transport_link - 66/68 tests pass; 2 STCP tests expected to fail (integration not complete)
This commit is contained in:
1 parent
937af4c26a
commit
d773f1724a
1705 files changed
+187
-1082154
No files matched your search
@@ -1,117 +0,0 @@
|
||||
#include "voicemessageencoder.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../../../lib/opus_codec.h"
|
||||
}
|
||||
|
||||
#include "../../lib/debug_config.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <cstring>
|
||||
|
||||
static const int FRAME_MS = 20;
|
||||
static const uint32_t OPUS_MAGIC = 0x5355504F;
|
||||
static const int MAX_PACKET = 4000;
|
||||
|
||||
static int s_preset = 1; /* 0=Low, 1=Standard, 2=High */
|
||||
static const int s_bitrates[] = {16000, 32000, 64000};
|
||||
static const int s_complexities[] = {2, 5, 10};
|
||||
|
||||
void VoiceEncoder::setPreset(int preset) {
|
||||
if (preset < 0) preset = 0;
|
||||
if (preset > 2) preset = 2;
|
||||
s_preset = preset;
|
||||
}
|
||||
|
||||
int VoiceEncoder::preset() { return s_preset; }
|
||||
|
||||
int VoiceEncoder::encodeToFile(const int16_t* pcm, size_t pcmCount, int sampleRate, int channels,
|
||||
const QString& filePath, float& outDurationSec) {
|
||||
if (!pcm || pcmCount == 0 || sampleRate <= 0 || channels <= 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: invalid input (pcm=%zu rate=%d ch=%d)", pcmCount, sampleRate, channels);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int frameSamples = sampleRate * FRAME_MS / 1000;
|
||||
size_t totalSamples = pcmCount / (size_t)channels;
|
||||
if (totalSamples < (size_t)frameSamples) return -1;
|
||||
|
||||
opus_codec_encoder_t* enc = opus_codec_encoder_create(sampleRate, channels);
|
||||
if (!enc) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: encoder create failed");
|
||||
return -1;
|
||||
}
|
||||
opus_codec_encoder_bitrate_set(enc, s_bitrates[s_preset]);
|
||||
opus_codec_encoder_complexity_set(enc, s_complexities[s_preset]);
|
||||
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: cannot open file %s (%s)", qPrintable(filePath), qPrintable(file.errorString()));
|
||||
opus_codec_encoder_destroy(enc);
|
||||
return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "VoiceEncoder::encodeToFile: writing to %s pcm=%zu samples preset=%d",
|
||||
qPrintable(filePath), pcmCount, s_preset);
|
||||
|
||||
/* write header */
|
||||
uint32_t magic = OPUS_MAGIC;
|
||||
uint32_t sr = (uint32_t)sampleRate;
|
||||
uint16_t ch = (uint16_t)channels;
|
||||
uint16_t fs = (uint16_t)frameSamples;
|
||||
file.write((const char*)&magic, 4);
|
||||
file.write((const char*)&sr, 4);
|
||||
file.write((const char*)&ch, 2);
|
||||
file.write((const char*)&fs, 2);
|
||||
|
||||
int frameCount = 0;
|
||||
uint8_t packet[MAX_PACKET];
|
||||
size_t pcmOff = 0;
|
||||
|
||||
while (pcmOff + (size_t)frameSamples * channels <= totalSamples) {
|
||||
int len = opus_codec_encode(enc, pcm + pcmOff, frameSamples, packet, MAX_PACKET);
|
||||
pcmOff += (size_t)frameSamples * channels;
|
||||
|
||||
if (len > 0) {
|
||||
uint16_t plen = (uint16_t)len;
|
||||
file.write((const char*)&plen, 2);
|
||||
file.write((const char*)packet, len);
|
||||
frameCount++;
|
||||
} else if (len < 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: encode error at frame %d: %d", frameCount, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* end marker */
|
||||
uint16_t zero = 0;
|
||||
file.write((const char*)&zero, 2);
|
||||
file.close();
|
||||
|
||||
outDurationSec = (float)frameCount * FRAME_MS / 1000.0f;
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: wrote %d frames (%.1fs) to %s", frameCount, outDurationSec, qPrintable(filePath));
|
||||
opus_codec_encoder_destroy(enc);
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
QString VoiceEncoder::generateFileName() {
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QString ts = now.toString("yyyyMMdd-HHmmss");
|
||||
int rnd = rand() & 0xFFFF;
|
||||
return QString("voice_%1_%2.opus").arg(ts).arg(rnd, 4, 16, QChar('0'));
|
||||
}
|
||||
|
||||
QString VoiceEncoder::mediaDir(const QString& dbPath, const QString& channelId) {
|
||||
QDir d(dbPath);
|
||||
QString mediaPath = d.absoluteFilePath("media/" + channelId);
|
||||
return mediaPath;
|
||||
}
|
||||
|
||||
void VoiceEncoder::ensureMediaDir(const QString& dir) {
|
||||
QDir d;
|
||||
if (!d.mkpath(dir)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "VoiceEncoder: cannot create media dir %s", qPrintable(dir));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user