diff --git a/src/media/audio/audio_frame_resizer.cpp b/src/media/audio/audio_frame_resizer.cpp index 311860de95195c1a7136b8919bf2254a56327d09..4bcf86d28f3f8e1748bf012d3217514e4e00d75f 100644 --- a/src/media/audio/audio_frame_resizer.cpp +++ b/src/media/audio/audio_frame_resizer.cpp @@ -30,13 +30,11 @@ extern "C" { namespace ring { -// NOTE 160 samples should the minimum that will be provided (20 ms @ 8kHz), -// barring files that for some obscure reason have smaller packets -AudioFrameResizer::AudioFrameResizer(const AudioFormat& format, int frameSize, std::function<void(std::unique_ptr<AudioFrame>&&)> cb) +AudioFrameResizer::AudioFrameResizer(const AudioFormat& format, int size, std::function<void(std::shared_ptr<AudioFrame>&&)> cb) : format_(format) - , frameSize_(frameSize) + , frameSize_(size) , cb_(cb) - , queue_(av_audio_fifo_alloc(format.sampleFormat, format.nb_channels, 160)) + , queue_(av_audio_fifo_alloc(format.sampleFormat, format.nb_channels, frameSize_)) {} AudioFrameResizer::~AudioFrameResizer() @@ -63,7 +61,32 @@ AudioFrameResizer::format() const } void -AudioFrameResizer::enqueue(std::unique_ptr<AudioFrame>&& frame) +AudioFrameResizer::setFormat(const AudioFormat& format, int size) +{ + if (format != format_) { + if (auto discaded = samples()) + RING_WARN("Discarding %d samples", discaded); + av_audio_fifo_free(queue_); + format_ = format; + queue_ = av_audio_fifo_alloc(format.sampleFormat, format.nb_channels, frameSize_); + } + if (size) + setFrameSize(size); +} + +void +AudioFrameResizer::setFrameSize(int frameSize) +{ + if (frameSize_ != frameSize) { + frameSize_ = frameSize; + if (cb_) + while (auto frame = dequeue()) + cb_(std::move(frame)); + } +} + +void +AudioFrameResizer::enqueue(std::shared_ptr<AudioFrame>&& frame) { int ret = 0; auto f = frame->pointer(); @@ -83,11 +106,12 @@ AudioFrameResizer::enqueue(std::unique_ptr<AudioFrame>&& frame) throw std::runtime_error("Failed to add audio to frame resizer"); } - while (auto frame = dequeue()) - cb_(std::move(frame)); + if (cb_) + while (auto frame = dequeue()) + cb_(std::move(frame)); } -std::unique_ptr<AudioFrame> +std::shared_ptr<AudioFrame> AudioFrameResizer::dequeue() { if (samples() < frameSize_) diff --git a/src/media/audio/audio_frame_resizer.h b/src/media/audio/audio_frame_resizer.h index c80780dc5389ba55a680a302a0622ded1543234e..0023ae99c082aec9e49680aaf4c67498837ce908 100644 --- a/src/media/audio/audio_frame_resizer.h +++ b/src/media/audio/audio_frame_resizer.h @@ -39,7 +39,7 @@ namespace ring { */ class AudioFrameResizer { public: - AudioFrameResizer(const AudioFormat& format, int frameSize, std::function<void(std::unique_ptr<AudioFrame>&&)> cb); + AudioFrameResizer(const AudioFormat& format, int frameSize, std::function<void(std::shared_ptr<AudioFrame>&&)> cb = {}); ~AudioFrameResizer(); /** @@ -53,6 +53,9 @@ public: */ AudioFormat format() const; + void setFormat(const AudioFormat& format, int frameSize); + void setFrameSize(int frameSize); + /** * Gets the number of samples per output frame. */ @@ -66,15 +69,15 @@ public: * * NOTE @frame's format must match @format_, or this will fail. */ - void enqueue(std::unique_ptr<AudioFrame>&& frame); - -private: - NON_COPYABLE(AudioFrameResizer); + void enqueue(std::shared_ptr<AudioFrame>&& frame); /** * Notifies owner of a new frame. */ - std::unique_ptr<AudioFrame> dequeue(); + std::shared_ptr<AudioFrame> dequeue(); + +private: + NON_COPYABLE(AudioFrameResizer); /** * Format used for input and output audio frames. @@ -89,7 +92,7 @@ private: /** * Function to call once @queue_ contains enough samples to produce a frame. */ - std::function<void(std::unique_ptr<AudioFrame>&&)> cb_; + std::function<void(std::shared_ptr<AudioFrame>&&)> cb_; /** * Audio queue operating on the sample level instead of byte level.