blob: 9981141a7e38c0fc55a19e0212e385288e5f35cb [file] [log] [blame]
/*
* Copyright (C) 2018-2019 Savoir-faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "audio_input.h"
#include "audio_sender.h"
#include "client/videomanager.h"
#include "libav_deps.h"
#include "logger.h"
#include "media_encoder.h"
#include "media_io_handle.h"
#include "media_stream.h"
#include "resampler.h"
#include "smartools.h"
#include <memory>
namespace ring {
AudioSender::AudioSender(const std::string& id,
const std::string& dest,
const MediaDescription& args,
SocketPair& socketPair,
const uint16_t seqVal,
bool muteState,
const uint16_t mtu) :
id_(id),
dest_(dest),
args_(args),
seqVal_(seqVal),
muteState_(muteState),
mtu_(mtu)
{
setup(socketPair);
}
AudioSender::~AudioSender()
{
audioInput_->detach(this);
audioInput_.reset();
audioEncoder_.reset();
muxContext_.reset();
micData_.clear();
resampledData_.clear();
}
bool
AudioSender::setup(SocketPair& socketPair)
{
audioEncoder_.reset(new MediaEncoder);
muxContext_.reset(socketPair.createIOContext(mtu_));
try {
/* Encoder setup */
RING_DBG("audioEncoder_->openLiveOutput %s", dest_.c_str());
audioEncoder_->setMuted(muteState_);
audioEncoder_->openLiveOutput(dest_, args_);
audioEncoder_->setInitSeqVal(seqVal_);
audioEncoder_->setIOContext(muxContext_);
audioEncoder_->startIO();
} catch (const MediaEncoderException &e) {
RING_ERR("%s", e.what());
return false;
}
Smartools::getInstance().setLocalAudioCodec(audioEncoder_->getEncoderName());
#ifdef DEBUG_SDP
audioEncoder_->print_sdp();
#endif
// NOTE do after encoder is ready to encode
auto codec = std::static_pointer_cast<AccountAudioCodecInfo>(args_.codec);
audioInput_ = ring::getAudioInput(id_);
audioInput_->setFormat(codec->audioformat);
audioInput_->attach(this);
return true;
}
void
AudioSender::update(Observable<std::shared_ptr<ring::MediaFrame>>* /*obs*/, const std::shared_ptr<ring::MediaFrame>& framePtr)
{
auto frame = framePtr->pointer();
auto ms = MediaStream("a:local", frame->format, rational<int>(1, frame->sample_rate),
frame->sample_rate, frame->channels, frame->nb_samples);
frame->pts = sent_samples;
ms.firstTimestamp = frame->pts;
sent_samples += frame->nb_samples;
if (audioEncoder_->encodeAudio(*std::static_pointer_cast<AudioFrame>(framePtr)) < 0)
RING_ERR("encoding failed");
}
void
AudioSender::setMuted(bool isMuted)
{
muteState_ = isMuted;
audioEncoder_->setMuted(isMuted);
}
uint16_t
AudioSender::getLastSeqValue()
{
return audioEncoder_->getLastSeqValue();
}
} // namespace ring