mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-10 23:56:43 +02:00
Replace some pointers with references
This commit is contained in:
parent
dde63f9dd8
commit
dec7306a84
17 changed files with 77 additions and 67 deletions
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef ENCODER_H
|
#ifndef ENCODER_HPP
|
||||||
#define ENCODER_H
|
#define ENCODER_HPP
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Here the work is done. Encoded data is passed to the EncoderListener.
|
/// Here the work is done. Encoded data is passed to the EncoderListener.
|
||||||
virtual void encode(const msg::PcmChunk* chunk) = 0;
|
virtual void encode(const msg::PcmChunk& chunk) = 0;
|
||||||
|
|
||||||
virtual std::string name() const = 0;
|
virtual std::string name() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ using namespace std;
|
||||||
namespace encoder
|
namespace encoder
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr auto LOG_TAG = "FlacEnc";
|
||||||
|
|
||||||
FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0), flacChunk_(nullptr)
|
FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0), flacChunk_(nullptr)
|
||||||
{
|
{
|
||||||
headerChunk_.reset(new msg::CodecHeader("flac"));
|
headerChunk_.reset(new msg::CodecHeader("flac"));
|
||||||
|
@ -67,14 +69,14 @@ std::string FlacEncoder::name() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
void FlacEncoder::encode(const msg::PcmChunk& chunk)
|
||||||
{
|
{
|
||||||
if (flacChunk_ == nullptr)
|
if (flacChunk_ == nullptr)
|
||||||
flacChunk_ = make_shared<msg::PcmChunk>(chunk->format, 0);
|
flacChunk_ = make_shared<msg::PcmChunk>(chunk.format, 0);
|
||||||
|
|
||||||
int samples = chunk->getSampleCount();
|
int samples = chunk.getSampleCount();
|
||||||
int frames = chunk->getFrameCount();
|
int frames = chunk.getFrameCount();
|
||||||
// LOG(INFO) << "payload: " << chunk->payloadSize << "\tframes: " << frames << "\tsamples: " << samples << "\tduration: " <<
|
// LOG(INFO, LOG_TAG) << "payload: " << chunk->payloadSize << "\tframes: " << frames << "\tsamples: " << samples << "\tduration: " <<
|
||||||
// chunk->duration<chronos::msec>().count() << "\n";
|
// chunk->duration<chronos::msec>().count() << "\n";
|
||||||
|
|
||||||
if (pcmBufferSize_ < samples)
|
if (pcmBufferSize_ < samples)
|
||||||
|
@ -85,19 +87,19 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
|
|
||||||
if (sampleFormat_.sampleSize() == 1)
|
if (sampleFormat_.sampleSize() == 1)
|
||||||
{
|
{
|
||||||
FLAC__int8* buffer = (FLAC__int8*)chunk->payload;
|
FLAC__int8* buffer = (FLAC__int8*)chunk.payload;
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
||||||
}
|
}
|
||||||
else if (sampleFormat_.sampleSize() == 2)
|
else if (sampleFormat_.sampleSize() == 2)
|
||||||
{
|
{
|
||||||
FLAC__int16* buffer = (FLAC__int16*)chunk->payload;
|
FLAC__int16* buffer = (FLAC__int16*)chunk.payload;
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
||||||
}
|
}
|
||||||
else if (sampleFormat_.sampleSize() == 4)
|
else if (sampleFormat_.sampleSize() == 4)
|
||||||
{
|
{
|
||||||
FLAC__int32* buffer = (FLAC__int32*)chunk->payload;
|
FLAC__int32* buffer = (FLAC__int32*)chunk.payload;
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
pcmBuffer_[i] = (FLAC__int32)(buffer[i]);
|
||||||
}
|
}
|
||||||
|
@ -108,10 +110,10 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
if (encodedSamples_ > 0)
|
if (encodedSamples_ > 0)
|
||||||
{
|
{
|
||||||
double resMs = static_cast<double>(encodedSamples_) / sampleFormat_.msRate();
|
double resMs = static_cast<double>(encodedSamples_) / sampleFormat_.msRate();
|
||||||
// LOG(INFO) << "encoded: " << chunk->payloadSize << "\tframes: " << encodedSamples_ << "\tres: " << resMs << "\n";
|
// LOG(INFO, LOG_TAG) << "encoded: " << chunk->payloadSize << "\tframes: " << encodedSamples_ << "\tres: " << resMs << "\n";
|
||||||
encodedSamples_ = 0;
|
encodedSamples_ = 0;
|
||||||
listener_->onChunkEncoded(this, flacChunk_, resMs);
|
listener_->onChunkEncoded(this, flacChunk_, resMs);
|
||||||
flacChunk_ = make_shared<msg::PcmChunk>(chunk->format, 0);
|
flacChunk_ = make_shared<msg::PcmChunk>(chunk.format, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +121,7 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder* /*encoder*/, const FLAC__byte buffer[], size_t bytes, unsigned samples,
|
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder* /*encoder*/, const FLAC__byte buffer[], size_t bytes, unsigned samples,
|
||||||
unsigned current_frame)
|
unsigned current_frame)
|
||||||
{
|
{
|
||||||
// LOG(INFO) << "write_callback: " << bytes << ", " << samples << ", " << current_frame << "\n";
|
// LOG(INFO, LOG_TAG) << "write_callback: " << bytes << ", " << samples << ", " << current_frame << "\n";
|
||||||
if ((current_frame == 0) && (bytes > 0) && (samples == 0))
|
if ((current_frame == 0) && (bytes > 0) && (samples == 0))
|
||||||
{
|
{
|
||||||
headerChunk_->payload = (char*)realloc(headerChunk_->payload, headerChunk_->payloadSize + bytes);
|
headerChunk_->payload = (char*)realloc(headerChunk_->payload, headerChunk_->payloadSize + bytes);
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef FLAC_ENCODER_H
|
#ifndef FLAC_ENCODER_HPP
|
||||||
#define FLAC_ENCODER_H
|
#define FLAC_ENCODER_HPP
|
||||||
#include "encoder.hpp"
|
#include "encoder.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -34,7 +34,7 @@ class FlacEncoder : public Encoder
|
||||||
public:
|
public:
|
||||||
FlacEncoder(const std::string& codecOptions = "");
|
FlacEncoder(const std::string& codecOptions = "");
|
||||||
~FlacEncoder() override;
|
~FlacEncoder() override;
|
||||||
void encode(const msg::PcmChunk* chunk) override;
|
void encode(const msg::PcmChunk& chunk) override;
|
||||||
std::string getAvailableOptions() const override;
|
std::string getAvailableOptions() const override;
|
||||||
std::string getDefaultOptions() const override;
|
std::string getDefaultOptions() const override;
|
||||||
std::string name() const override;
|
std::string name() const override;
|
||||||
|
|
|
@ -31,6 +31,8 @@ using namespace std;
|
||||||
namespace encoder
|
namespace encoder
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr auto LOG_TAG = "OggEnc";
|
||||||
|
|
||||||
OggEncoder::OggEncoder(const std::string& codecOptions) : Encoder(codecOptions), lastGranulepos_(0)
|
OggEncoder::OggEncoder(const std::string& codecOptions) : Encoder(codecOptions), lastGranulepos_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -64,12 +66,13 @@ std::string OggEncoder::name() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OggEncoder::encode(const msg::PcmChunk* chunk)
|
void OggEncoder::encode(const msg::PcmChunk& chunk)
|
||||||
{
|
{
|
||||||
double res = 0;
|
double res = 0;
|
||||||
// LOG(TRACE) << "payload: " << chunk->payloadSize << "\tframes: " << chunk->getFrameCount() << "\tduration: " << chunk->duration<chronos::msec>().count()
|
// LOG(TRACE, LOG_TAG) << "payload: " << chunk->payloadSize << "\tframes: " << chunk->getFrameCount() << "\tduration: " <<
|
||||||
|
// chunk->duration<chronos::msec>().count()
|
||||||
// << "\n";
|
// << "\n";
|
||||||
int frames = chunk->getFrameCount();
|
int frames = chunk.getFrameCount();
|
||||||
float** buffer = vorbis_analysis_buffer(&vd_, frames);
|
float** buffer = vorbis_analysis_buffer(&vd_, frames);
|
||||||
|
|
||||||
/* uninterleave samples */
|
/* uninterleave samples */
|
||||||
|
@ -77,19 +80,19 @@ void OggEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
{
|
{
|
||||||
if (sampleFormat_.sampleSize() == 1)
|
if (sampleFormat_.sampleSize() == 1)
|
||||||
{
|
{
|
||||||
int8_t* chunkBuffer = (int8_t*)chunk->payload;
|
int8_t* chunkBuffer = (int8_t*)chunk.payload;
|
||||||
for (int i = 0; i < frames; i++)
|
for (int i = 0; i < frames; i++)
|
||||||
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 128.f;
|
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 128.f;
|
||||||
}
|
}
|
||||||
else if (sampleFormat_.sampleSize() == 2)
|
else if (sampleFormat_.sampleSize() == 2)
|
||||||
{
|
{
|
||||||
int16_t* chunkBuffer = (int16_t*)chunk->payload;
|
int16_t* chunkBuffer = (int16_t*)chunk.payload;
|
||||||
for (int i = 0; i < frames; i++)
|
for (int i = 0; i < frames; i++)
|
||||||
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 32768.f;
|
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 32768.f;
|
||||||
}
|
}
|
||||||
else if (sampleFormat_.sampleSize() == 4)
|
else if (sampleFormat_.sampleSize() == 4)
|
||||||
{
|
{
|
||||||
int32_t* chunkBuffer = (int32_t*)chunk->payload;
|
int32_t* chunkBuffer = (int32_t*)chunk.payload;
|
||||||
for (int i = 0; i < frames; i++)
|
for (int i = 0; i < frames; i++)
|
||||||
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 2147483648.f;
|
buffer[channel][i] = chunkBuffer[sampleFormat_.channels() * i + channel] / 2147483648.f;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +101,7 @@ void OggEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
/* tell the library how much we actually submitted */
|
/* tell the library how much we actually submitted */
|
||||||
vorbis_analysis_wrote(&vd_, frames);
|
vorbis_analysis_wrote(&vd_, frames);
|
||||||
|
|
||||||
auto oggChunk = make_shared<msg::PcmChunk>(chunk->format, 0);
|
auto oggChunk = make_shared<msg::PcmChunk>(chunk.format, 0);
|
||||||
|
|
||||||
/* vorbis does some data preanalysis, then divvies up blocks for
|
/* vorbis does some data preanalysis, then divvies up blocks for
|
||||||
more involved (potentially parallel) processing. Get a single
|
more involved (potentially parallel) processing. Get a single
|
||||||
|
@ -142,7 +145,7 @@ void OggEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
{
|
{
|
||||||
res /= sampleFormat_.msRate();
|
res /= sampleFormat_.msRate();
|
||||||
// LOG(INFO) << "res: " << res << "\n";
|
// LOG(INFO, LOG_TAG) << "res: " << res << "\n";
|
||||||
lastGranulepos_ = os_.granulepos;
|
lastGranulepos_ = os_.granulepos;
|
||||||
// make oggChunk smaller
|
// make oggChunk smaller
|
||||||
oggChunk->payload = (char*)realloc(oggChunk->payload, pos);
|
oggChunk->payload = (char*)realloc(oggChunk->payload, pos);
|
||||||
|
@ -260,7 +263,7 @@ void OggEncoder::initEncoder()
|
||||||
break;
|
break;
|
||||||
headerChunk_->payloadSize += og_.header_len + og_.body_len;
|
headerChunk_->payloadSize += og_.header_len + og_.body_len;
|
||||||
headerChunk_->payload = (char*)realloc(headerChunk_->payload, headerChunk_->payloadSize);
|
headerChunk_->payload = (char*)realloc(headerChunk_->payload, headerChunk_->payloadSize);
|
||||||
LOG(DEBUG) << "HeadLen: " << og_.header_len << ", bodyLen: " << og_.body_len << ", result: " << result << "\n";
|
LOG(DEBUG, LOG_TAG) << "HeadLen: " << og_.header_len << ", bodyLen: " << og_.body_len << ", result: " << result << "\n";
|
||||||
memcpy(headerChunk_->payload + pos, og_.header, og_.header_len);
|
memcpy(headerChunk_->payload + pos, og_.header, og_.header_len);
|
||||||
pos += og_.header_len;
|
pos += og_.header_len;
|
||||||
memcpy(headerChunk_->payload + pos, og_.body, og_.body_len);
|
memcpy(headerChunk_->payload + pos, og_.body, og_.body_len);
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef OGG_ENCODER_H
|
#ifndef OGG_ENCODER_HPP
|
||||||
#define OGG_ENCODER_H
|
#define OGG_ENCODER_HPP
|
||||||
#include "encoder.hpp"
|
#include "encoder.hpp"
|
||||||
#include <ogg/ogg.h>
|
#include <ogg/ogg.h>
|
||||||
#include <vorbis/vorbisenc.h>
|
#include <vorbis/vorbisenc.h>
|
||||||
|
@ -31,7 +31,7 @@ public:
|
||||||
OggEncoder(const std::string& codecOptions = "");
|
OggEncoder(const std::string& codecOptions = "");
|
||||||
~OggEncoder() override;
|
~OggEncoder() override;
|
||||||
|
|
||||||
void encode(const msg::PcmChunk* chunk) override;
|
void encode(const msg::PcmChunk& chunk) override;
|
||||||
std::string getAvailableOptions() const override;
|
std::string getAvailableOptions() const override;
|
||||||
std::string getDefaultOptions() const override;
|
std::string getDefaultOptions() const override;
|
||||||
std::string name() const override;
|
std::string name() const override;
|
||||||
|
|
|
@ -30,8 +30,9 @@ namespace encoder
|
||||||
#define ID_OPUS 0x4F505553
|
#define ID_OPUS 0x4F505553
|
||||||
static constexpr opus_int32 const_min_bitrate = 6000;
|
static constexpr opus_int32 const_min_bitrate = 6000;
|
||||||
static constexpr opus_int32 const_max_bitrate = 512000;
|
static constexpr opus_int32 const_max_bitrate = 512000;
|
||||||
|
static constexpr int min_chunk_size = 10;
|
||||||
|
|
||||||
static constexpr auto LOG_TAG = "OpusEncoder";
|
static constexpr auto LOG_TAG = "OpusEnc";
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -163,7 +164,7 @@ void OpusEncoder::initEncoder()
|
||||||
assign(payload + 8, SWAP_16(sampleFormat_.bits()));
|
assign(payload + 8, SWAP_16(sampleFormat_.bits()));
|
||||||
assign(payload + 10, SWAP_16(sampleFormat_.channels()));
|
assign(payload + 10, SWAP_16(sampleFormat_.channels()));
|
||||||
|
|
||||||
remainder_ = std::make_unique<msg::PcmChunk>(sampleFormat_, 10);
|
remainder_ = std::make_unique<msg::PcmChunk>(sampleFormat_, min_chunk_size);
|
||||||
remainder_max_size_ = remainder_->payloadSize;
|
remainder_max_size_ = remainder_->payloadSize;
|
||||||
remainder_->payloadSize = 0;
|
remainder_->payloadSize = 0;
|
||||||
}
|
}
|
||||||
|
@ -174,25 +175,25 @@ void OpusEncoder::initEncoder()
|
||||||
// 240, 480, 960, 1920, 2880 frames
|
// 240, 480, 960, 1920, 2880 frames
|
||||||
// We will split the chunk into encodable sizes and store any remaining data in the remainder_ buffer
|
// We will split the chunk into encodable sizes and store any remaining data in the remainder_ buffer
|
||||||
// and encode the buffer content in the next iteration
|
// and encode the buffer content in the next iteration
|
||||||
void OpusEncoder::encode(const msg::PcmChunk* chunk)
|
void OpusEncoder::encode(const msg::PcmChunk& chunk)
|
||||||
{
|
{
|
||||||
// chunk =
|
// chunk =
|
||||||
// resampler_->resample(std::make_shared<msg::PcmChunk>(chunk)).get();
|
// resampler_->resample(std::make_shared<msg::PcmChunk>(chunk)).get();
|
||||||
auto in = std::make_shared<msg::PcmChunk>(*chunk);
|
auto in = std::make_shared<msg::PcmChunk>(chunk);
|
||||||
auto out = resampler_->resample(in); //, std::chrono::milliseconds(20));
|
auto out = resampler_->resample(in); //, std::chrono::milliseconds(20));
|
||||||
if (out == nullptr)
|
if (out == nullptr)
|
||||||
return;
|
return;
|
||||||
chunk = out.get();
|
// chunk = out.get();
|
||||||
|
|
||||||
// LOG(TRACE, LOG_TAG) << "encode " << chunk->duration<std::chrono::milliseconds>().count() << "ms\n";
|
// LOG(TRACE, LOG_TAG) << "encode " << chunk->duration<std::chrono::milliseconds>().count() << "ms\n";
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
// check if there is something left from the last call to encode and fill the remainder buffer to
|
// check if there is something left from the last call to encode and fill the remainder buffer to
|
||||||
// an encodable size of 10ms
|
// an encodable size of 10ms (min_chunk_size)
|
||||||
if (remainder_->payloadSize > 0)
|
if (remainder_->payloadSize > 0)
|
||||||
{
|
{
|
||||||
offset = std::min(static_cast<uint32_t>(remainder_max_size_ - remainder_->payloadSize), chunk->payloadSize);
|
offset = std::min(static_cast<uint32_t>(remainder_max_size_ - remainder_->payloadSize), out->payloadSize);
|
||||||
memcpy(remainder_->payload + remainder_->payloadSize, chunk->payload, offset);
|
memcpy(remainder_->payload + remainder_->payloadSize, out->payload, offset);
|
||||||
// LOG(TRACE, LOG_TAG) << "remainder buffer size: " << remainder_->payloadSize << "/" << remainder_max_size_ << ", appending " << offset << " bytes\n";
|
// LOG(TRACE, LOG_TAG) << "remainder buffer size: " << remainder_->payloadSize << "/" << remainder_max_size_ << ", appending " << offset << " bytes\n";
|
||||||
remainder_->payloadSize += offset;
|
remainder_->payloadSize += offset;
|
||||||
|
|
||||||
|
@ -202,32 +203,32 @@ void OpusEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
<< "\n";
|
<< "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
encode(chunk->format, remainder_->payload, remainder_->payloadSize);
|
encode(out->format, remainder_->payload, remainder_->payloadSize);
|
||||||
remainder_->payloadSize = 0;
|
remainder_->payloadSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode greedy 60ms, 40ms, 20ms, 10ms chunks
|
// encode greedy 60ms, 40ms, 20ms, 10ms chunks
|
||||||
std::vector<size_t> chunk_durations{60, 40, 20, 10};
|
std::vector<size_t> chunk_durations{60, 40, 20, min_chunk_size};
|
||||||
for (const auto duration : chunk_durations)
|
for (const auto duration : chunk_durations)
|
||||||
{
|
{
|
||||||
auto ms2bytes = [this](size_t ms) { return (ms * sampleFormat_.msRate() * sampleFormat_.frameSize()); };
|
auto ms2bytes = [this](size_t ms) { return (ms * sampleFormat_.msRate() * sampleFormat_.frameSize()); };
|
||||||
uint32_t bytes = ms2bytes(duration);
|
uint32_t bytes = ms2bytes(duration);
|
||||||
while (chunk->payloadSize - offset >= bytes)
|
while (out->payloadSize - offset >= bytes)
|
||||||
{
|
{
|
||||||
// LOG(TRACE, LOG_TAG) << "encoding " << duration << "ms (" << bytes << "), offset: " << offset << ", chunk size: " << chunk->payloadSize - offset
|
// LOG(TRACE, LOG_TAG) << "encoding " << duration << "ms (" << bytes << "), offset: " << offset << ", chunk size: " << chunk->payloadSize - offset
|
||||||
// << "\n";
|
// << "\n";
|
||||||
encode(chunk->format, chunk->payload + offset, bytes);
|
encode(out->format, out->payload + offset, bytes);
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
}
|
}
|
||||||
if (chunk->payloadSize == offset)
|
if (out->payloadSize == offset)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// something is left (must be less than 10ms)
|
// something is left (must be less than min_chunk_size (10ms))
|
||||||
if (chunk->payloadSize > offset)
|
if (out->payloadSize > offset)
|
||||||
{
|
{
|
||||||
memcpy(remainder_->payload + remainder_->payloadSize, chunk->payload + offset, chunk->payloadSize - offset);
|
memcpy(remainder_->payload + remainder_->payloadSize, out->payload + offset, out->payloadSize - offset);
|
||||||
remainder_->payloadSize = chunk->payloadSize - offset;
|
remainder_->payloadSize = out->payloadSize - offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
OpusEncoder(const std::string& codecOptions = "");
|
OpusEncoder(const std::string& codecOptions = "");
|
||||||
~OpusEncoder() override;
|
~OpusEncoder() override;
|
||||||
|
|
||||||
void encode(const msg::PcmChunk* chunk) override;
|
void encode(const msg::PcmChunk& chunk) override;
|
||||||
std::string getAvailableOptions() const override;
|
std::string getAvailableOptions() const override;
|
||||||
std::string getDefaultOptions() const override;
|
std::string getDefaultOptions() const override;
|
||||||
std::string name() const override;
|
std::string name() const override;
|
||||||
|
|
|
@ -47,10 +47,10 @@ PcmEncoder::PcmEncoder(const std::string& codecOptions) : Encoder(codecOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmEncoder::encode(const msg::PcmChunk* chunk)
|
void PcmEncoder::encode(const msg::PcmChunk& chunk)
|
||||||
{
|
{
|
||||||
// copy the chunk into a shared_ptr
|
// copy the chunk into a shared_ptr
|
||||||
auto pcmChunk = std::make_shared<msg::PcmChunk>(*chunk);
|
auto pcmChunk = std::make_shared<msg::PcmChunk>(chunk);
|
||||||
listener_->onChunkEncoded(this, pcmChunk, pcmChunk->durationMs());
|
listener_->onChunkEncoded(this, pcmChunk, pcmChunk->durationMs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef PCM_ENCODER_H
|
#ifndef PCM_ENCODER_HPP
|
||||||
#define PCM_ENCODER_H
|
#define PCM_ENCODER_HPP
|
||||||
#include "encoder.hpp"
|
#include "encoder.hpp"
|
||||||
|
|
||||||
namespace encoder
|
namespace encoder
|
||||||
|
@ -27,7 +27,7 @@ class PcmEncoder : public Encoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PcmEncoder(const std::string& codecOptions = "");
|
PcmEncoder(const std::string& codecOptions = "");
|
||||||
void encode(const msg::PcmChunk* chunk) override;
|
void encode(const msg::PcmChunk& chunk) override;
|
||||||
std::string name() const override;
|
std::string name() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -175,7 +175,7 @@ session_ptr StreamServer::getStreamSession(StreamSession* streamSession) const
|
||||||
|
|
||||||
session_ptr StreamServer::getStreamSession(const std::string& clientId) const
|
session_ptr StreamServer::getStreamSession(const std::string& clientId) const
|
||||||
{
|
{
|
||||||
// LOG(INFO) << "getStreamSession: " << mac << "\n";
|
// LOG(INFO, LOG_TAG) << "getStreamSession: " << mac << "\n";
|
||||||
std::lock_guard<std::recursive_mutex> mlock(sessionsMutex_);
|
std::lock_guard<std::recursive_mutex> mlock(sessionsMutex_);
|
||||||
for (auto session : sessions_)
|
for (auto session : sessions_)
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,7 +105,7 @@ void StreamSessionWebsocket::on_read_ws(beast::error_code ec, std::size_t bytes_
|
||||||
|
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "ControlSessionWebsocket::on_read_ws error: " << ec.message() << "\n";
|
LOG(ERROR, LOG_TAG) << "ControlSessionWebsocket::on_read_ws error: " << ec.message() << "\n";
|
||||||
messageReceiver_->onDisconnect(this);
|
messageReceiver_->onDisconnect(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,7 @@ void AlsaStream::do_read()
|
||||||
tvEncodedChunk_ = std::chrono::steady_clock::now() - duration;
|
tvEncodedChunk_ = std::chrono::steady_clock::now() - duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChunkRead(chunk_.get());
|
onChunkRead(*chunk_);
|
||||||
|
|
||||||
nextTick_ += duration;
|
nextTick_ += duration;
|
||||||
auto currentTick = std::chrono::steady_clock::now();
|
auto currentTick = std::chrono::steady_clock::now();
|
||||||
|
|
|
@ -86,7 +86,8 @@ AsioStream<ReadStream>::AsioStream(PcmListener* pcmListener, boost::asio::io_con
|
||||||
: PcmStream(pcmListener, ioc, uri), read_timer_(ioc), state_timer_(ioc)
|
: PcmStream(pcmListener, ioc, uri), read_timer_(ioc), state_timer_(ioc)
|
||||||
{
|
{
|
||||||
chunk_ = std::make_unique<msg::PcmChunk>(sampleFormat_, chunk_ms_);
|
chunk_ = std::make_unique<msg::PcmChunk>(sampleFormat_, chunk_ms_);
|
||||||
LOG(DEBUG) << "Chunk duration: " << chunk_->durationMs() << " ms, frames: " << chunk_->getFrameCount() << ", size: " << chunk_->payloadSize << "\n";
|
LOG(DEBUG, "AsioStream") << "Chunk duration: " << chunk_->durationMs() << " ms, frames: " << chunk_->getFrameCount() << ", size: " << chunk_->payloadSize
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
bytes_read_ = 0;
|
bytes_read_ = 0;
|
||||||
buffer_ms_ = 50;
|
buffer_ms_ = 50;
|
||||||
|
@ -197,7 +198,7 @@ void AsioStream<ReadStream>::do_read()
|
||||||
nextTick_ = std::chrono::steady_clock::now();
|
nextTick_ = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChunkRead(chunk_.get());
|
onChunkRead(*chunk_);
|
||||||
nextTick_ += chunk_->duration<std::chrono::nanoseconds>();
|
nextTick_ += chunk_->duration<std::chrono::nanoseconds>();
|
||||||
auto currentTick = std::chrono::steady_clock::now();
|
auto currentTick = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ void PcmStream::onChunkEncoded(const encoder::Encoder* /*encoder*/, std::shared_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmStream::onChunkRead(const msg::PcmChunk* chunk)
|
void PcmStream::onChunkRead(const msg::PcmChunk& chunk)
|
||||||
{
|
{
|
||||||
encoder_->encode(chunk);
|
encoder_->encode(chunk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ protected:
|
||||||
std::atomic<bool> active_;
|
std::atomic<bool> active_;
|
||||||
|
|
||||||
void setState(const ReaderState& newState);
|
void setState(const ReaderState& newState);
|
||||||
virtual void onChunkRead(const msg::PcmChunk* chunk);
|
virtual void onChunkRead(const msg::PcmChunk& chunk);
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> tvEncodedChunk_;
|
std::chrono::time_point<std::chrono::steady_clock> tvEncodedChunk_;
|
||||||
PcmListener* pcmListener_;
|
PcmListener* pcmListener_;
|
||||||
|
|
|
@ -105,7 +105,7 @@ void PosixStream::do_read()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// LOG(DEBUG) << "count: " << count << "\n";
|
// LOG(DEBUG, LOG_TAG) << "count: " << count << "\n";
|
||||||
len += count;
|
len += count;
|
||||||
bytes_read_ += len;
|
bytes_read_ += len;
|
||||||
idle_bytes_ = 0;
|
idle_bytes_ = 0;
|
||||||
|
@ -123,7 +123,7 @@ void PosixStream::do_read()
|
||||||
if ((idle_bytes_ == 0) || (idle_bytes_ <= max_idle_bytes_))
|
if ((idle_bytes_ == 0) || (idle_bytes_ <= max_idle_bytes_))
|
||||||
{
|
{
|
||||||
// the encoder will update the tvEncodedChunk when a chunk is encoded
|
// the encoder will update the tvEncodedChunk when a chunk is encoded
|
||||||
onChunkRead(chunk_.get());
|
onChunkRead(*chunk_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -143,7 +143,8 @@ void PosixStream::do_read()
|
||||||
}
|
}
|
||||||
else if (next_read >= -kResyncTolerance)
|
else if (next_read >= -kResyncTolerance)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "next read < 0 (" << getName() << "): " << std::chrono::duration_cast<std::chrono::microseconds>(next_read).count() / 1000. << " ms\n";
|
LOG(INFO, LOG_TAG) << "next read < 0 (" << getName() << "): " << std::chrono::duration_cast<std::chrono::microseconds>(next_read).count() / 1000.
|
||||||
|
<< " ms\n";
|
||||||
do_read();
|
do_read();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -35,6 +35,8 @@ using namespace std;
|
||||||
namespace streamreader
|
namespace streamreader
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr auto LOG_TAG = "TcpStream";
|
||||||
|
|
||||||
TcpStream::TcpStream(PcmListener* pcmListener, boost::asio::io_context& ioc, const StreamUri& uri)
|
TcpStream::TcpStream(PcmListener* pcmListener, boost::asio::io_context& ioc, const StreamUri& uri)
|
||||||
: AsioStream<tcp::socket>(pcmListener, ioc, uri), reconnect_timer_(ioc)
|
: AsioStream<tcp::socket>(pcmListener, ioc, uri), reconnect_timer_(ioc)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +59,7 @@ TcpStream::TcpStream(PcmListener* pcmListener, boost::asio::io_context& ioc, con
|
||||||
|
|
||||||
port_ = cpt::stoi(uri_.getQuery("port", cpt::to_string(port_)), port_);
|
port_ = cpt::stoi(uri_.getQuery("port", cpt::to_string(port_)), port_);
|
||||||
|
|
||||||
LOG(INFO) << "TcpStream host: " << host_ << ", port: " << port_ << ", is server: " << is_server_ << "\n";
|
LOG(INFO, LOG_TAG) << "TcpStream host: " << host_ << ", port: " << port_ << ", is server: " << is_server_ << "\n";
|
||||||
if (is_server_)
|
if (is_server_)
|
||||||
acceptor_ = make_unique<tcp::acceptor>(ioc_, tcp::endpoint(boost::asio::ip::address::from_string(host_), port_));
|
acceptor_ = make_unique<tcp::acceptor>(ioc_, tcp::endpoint(boost::asio::ip::address::from_string(host_), port_));
|
||||||
}
|
}
|
||||||
|
@ -73,13 +75,13 @@ void TcpStream::do_connect()
|
||||||
acceptor_->async_accept([this](boost::system::error_code ec, tcp::socket socket) {
|
acceptor_->async_accept([this](boost::system::error_code ec, tcp::socket socket) {
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
LOG(DEBUG) << "New client connection\n";
|
LOG(DEBUG, LOG_TAG) << "New client connection\n";
|
||||||
stream_ = make_unique<tcp::socket>(move(socket));
|
stream_ = make_unique<tcp::socket>(move(socket));
|
||||||
on_connect();
|
on_connect();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "Accept failed: " << ec.message() << "\n";
|
LOG(ERROR, LOG_TAG) << "Accept failed: " << ec.message() << "\n";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -90,12 +92,12 @@ void TcpStream::do_connect()
|
||||||
stream_->async_connect(endpoint, [this](const boost::system::error_code& ec) {
|
stream_->async_connect(endpoint, [this](const boost::system::error_code& ec) {
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
LOG(DEBUG) << "Connected\n";
|
LOG(DEBUG, LOG_TAG) << "Connected\n";
|
||||||
on_connect();
|
on_connect();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(DEBUG) << "Connect failed: " << ec.message() << "\n";
|
LOG(DEBUG, LOG_TAG) << "Connect failed: " << ec.message() << "\n";
|
||||||
wait(reconnect_timer_, 1s, [this] { connect(); });
|
wait(reconnect_timer_, 1s, [this] { connect(); });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue