Skip to content
Snippets Groups Projects
Commit ddcda82e authored by Philippe Gorley's avatar Philippe Gorley
Browse files

audio: use input as audio source

AudioInput now manages audio frames, not AudioSender.
Makes AudioInput observable.
AudioSender subscribes to AudioInput.

LocalRecorder does not need to observe AudioInput or VideoInput because
these already record frames. Will be done in future work on the recording
system.

Change-Id: I011d742063386498d59b2962f7c333b999d0921c
parent ecf9650a
Branches
No related tags found
No related merge requests found
...@@ -107,6 +107,9 @@ AudioInput::process() ...@@ -107,6 +107,9 @@ AudioInput::process()
rec->recordData(frame, ms); rec->recordData(frame, ms);
} }
} }
std::shared_ptr<AudioFrame> sharedFrame = std::move(audioFrame);
notify(sharedFrame);
} }
void void
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "audio/audiobuffer.h" #include "audio/audiobuffer.h"
#include "media_device.h" #include "media_device.h"
#include "media_buffer.h" #include "media_buffer.h"
#include "observer.h"
#include "threadloop.h" #include "threadloop.h"
namespace ring { namespace ring {
...@@ -34,7 +35,7 @@ namespace ring { ...@@ -34,7 +35,7 @@ namespace ring {
class MediaRecorder; class MediaRecorder;
class Resampler; class Resampler;
class AudioInput class AudioInput : public Observable<std::shared_ptr<AudioFrame>>
{ {
public: public:
AudioInput(const std::string& id); AudioInput(const std::string& id);
......
...@@ -37,16 +37,18 @@ ...@@ -37,16 +37,18 @@
#include "media_io_handle.h" #include "media_io_handle.h"
#include "media_device.h" #include "media_device.h"
#include "audio/audio_input.h"
#include "audio/audiobuffer.h" #include "audio/audiobuffer.h"
#include "audio/ringbufferpool.h" #include "audio/ringbufferpool.h"
#include "audio/resampler.h" #include "audio/resampler.h"
#include "manager.h" #include "manager.h"
#include "observer.h"
#include "smartools.h" #include "smartools.h"
#include <sstream> #include <sstream>
namespace ring { namespace ring {
class AudioSender { class AudioSender : public Observer<std::shared_ptr<AudioFrame>> {
public: public:
AudioSender(const std::string& id, AudioSender(const std::string& id,
const std::string& dest, const std::string& dest,
...@@ -60,6 +62,9 @@ class AudioSender { ...@@ -60,6 +62,9 @@ class AudioSender {
void setMuted(bool isMuted); void setMuted(bool isMuted);
uint16_t getLastSeqValue(); uint16_t getLastSeqValue();
void update(Observable<std::shared_ptr<ring::AudioFrame>>*,
const std::shared_ptr<ring::AudioFrame>&) override;
void initRecorder(std::shared_ptr<MediaRecorder>& rec); void initRecorder(std::shared_ptr<MediaRecorder>& rec);
private: private:
...@@ -73,7 +78,7 @@ class AudioSender { ...@@ -73,7 +78,7 @@ class AudioSender {
std::unique_ptr<MediaEncoder> audioEncoder_; std::unique_ptr<MediaEncoder> audioEncoder_;
std::unique_ptr<MediaIOHandle> muxContext_; std::unique_ptr<MediaIOHandle> muxContext_;
std::unique_ptr<Resampler> resampler_; std::unique_ptr<Resampler> resampler_;
std::unique_ptr<AudioInput> audioInput_;
std::weak_ptr<MediaRecorder> recorder_; std::weak_ptr<MediaRecorder> recorder_;
uint64_t sent_samples = 0; uint64_t sent_samples = 0;
...@@ -85,10 +90,6 @@ class AudioSender { ...@@ -85,10 +90,6 @@ class AudioSender {
uint16_t mtu_; uint16_t mtu_;
const std::chrono::milliseconds msPerPacket_ {20}; const std::chrono::milliseconds msPerPacket_ {20};
ThreadLoop loop_;
void process();
void cleanup();
}; };
AudioSender::AudioSender(const std::string& id, AudioSender::AudioSender(const std::string& id,
...@@ -103,19 +104,21 @@ AudioSender::AudioSender(const std::string& id, ...@@ -103,19 +104,21 @@ AudioSender::AudioSender(const std::string& id,
args_(args), args_(args),
seqVal_(seqVal), seqVal_(seqVal),
muteState_(muteState), muteState_(muteState),
mtu_(mtu), mtu_(mtu)
loop_([&] { return setup(socketPair); },
std::bind(&AudioSender::process, this),
std::bind(&AudioSender::cleanup, this))
{ {
loop_.start(); setup(socketPair);
} }
AudioSender::~AudioSender() AudioSender::~AudioSender()
{ {
if (auto rec = recorder_.lock()) if (auto rec = recorder_.lock())
rec->stopRecording(); rec->stopRecording();
loop_.join(); audioInput_->detach(this);
audioInput_.reset();
audioEncoder_.reset();
muxContext_.reset();
micData_.clear();
resampledData_.clear();
} }
bool bool
...@@ -143,16 +146,13 @@ AudioSender::setup(SocketPair& socketPair) ...@@ -143,16 +146,13 @@ AudioSender::setup(SocketPair& socketPair)
audioEncoder_->print_sdp(); audioEncoder_->print_sdp();
#endif #endif
return true; // NOTE do after encoder is ready to encode
} audioInput_.reset(new AudioInput(id_));
auto codec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
audioInput_->setFormat(codec->audioformat);
audioInput_->attach(this);
void return true;
AudioSender::cleanup()
{
audioEncoder_.reset();
muxContext_.reset();
micData_.clear();
resampledData_.clear();
} }
// seq: frame number for video, sent samples audio // seq: frame number for video, sent samples audio
...@@ -166,52 +166,11 @@ getNextTimestamp(int64_t seq, rational<int64_t> sampleFreq, rational<int64_t> cl ...@@ -166,52 +166,11 @@ getNextTimestamp(int64_t seq, rational<int64_t> sampleFreq, rational<int64_t> cl
} }
void void
AudioSender::process() AudioSender::update(Observable<std::shared_ptr<ring::AudioFrame>>* /*obs*/, const std::shared_ptr<ring::AudioFrame>& framePtr)
{ {
auto& mainBuffer = Manager::instance().getRingBufferPool(); auto frame = framePtr->pointer();
auto mainBuffFormat = mainBuffer.getInternalAudioFormat(); auto ms = MediaStream("a:local", frame->format, rational<int>(1, frame->sample_rate),
frame->sample_rate, frame->channels);
// compute nb of byte to get corresponding to 1 audio frame
const std::size_t samplesToGet = std::chrono::duration_cast<std::chrono::seconds>(msPerPacket_ * mainBuffFormat.sample_rate).count();
if (mainBuffer.availableForGet(id_) < samplesToGet
&& not mainBuffer.waitForDataAvailable(id_, samplesToGet, msPerPacket_)) {
return;
}
// get data
micData_.setFormat(mainBuffFormat);
micData_.resize(samplesToGet);
const auto samples = mainBuffer.getData(micData_, id_);
if (samples != samplesToGet)
return;
// down/upmix as needed
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
micData_.setChannelNum(accountAudioCodec->audioformat.nb_channels, true);
Smartools::getInstance().setLocalAudioCodec(audioEncoder_->getEncoderName());
AudioBuffer buffer;
if (mainBuffFormat.sample_rate != accountAudioCodec->audioformat.sample_rate) {
if (not resampler_) {
RING_DBG("Creating audio resampler");
resampler_.reset(new Resampler);
}
resampledData_.setFormat(accountAudioCodec->audioformat);
resampledData_.resize(samplesToGet);
resampler_->resample(micData_, resampledData_);
buffer = resampledData_;
} else {
buffer = micData_;
}
if (muteState_) // audio is muted, set samples to 0
buffer.reset();
auto audioFrame = buffer.toAVFrame();
auto frame = audioFrame->pointer();
auto ms = MediaStream("a:local", buffer.getFormat());
frame->pts = getNextTimestamp(sent_samples, ms.sampleRate, static_cast<rational<int64_t>>(ms.timeBase)); frame->pts = getNextTimestamp(sent_samples, ms.sampleRate, static_cast<rational<int64_t>>(ms.timeBase));
ms.firstTimestamp = frame->pts; ms.firstTimestamp = frame->pts;
sent_samples += frame->nb_samples; sent_samples += frame->nb_samples;
...@@ -222,7 +181,7 @@ AudioSender::process() ...@@ -222,7 +181,7 @@ AudioSender::process()
rec->recordData(frame, ms); rec->recordData(frame, ms);
} }
if (audioEncoder_->encodeAudio(*audioFrame) < 0) if (audioEncoder_->encodeAudio(*framePtr) < 0)
RING_ERR("encoding failed"); RING_ERR("encoding failed");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment