50#include <libavutil/display.h>
56 : frame_ {av_frame_alloc()}
59 throw std::bad_alloc();
72 packet_.reset(av_packet_alloc());
81 av_frame_unref(
frame_.get());
103 av_channel_layout_default(&d->ch_layout, format.
nb_channels);
112 (
unsigned)
frame_->ch_layout.nb_channels,
113 (AVSampleFormat)
frame_->format};
119 return frame_->nb_samples;
123AudioFrame::reserve(
size_t nb_samples)
125 if (nb_samples != 0) {
127 d->nb_samples = nb_samples;
129 if ((err = av_frame_get_buffer(d, 0)) < 0) {
130 throw std::bad_alloc();
140 if (f.ch_layout.nb_channels != fIn.ch_layout.nb_channels || f.format != fIn.format
141 || f.sample_rate != fIn.sample_rate) {
142 throw std::invalid_argument(
"Unable to mix frames with different formats");
144 if (f.nb_samples == 0) {
145 reserve(fIn.nb_samples);
147 }
else if (f.nb_samples != fIn.nb_samples) {
148 throw std::invalid_argument(
"Unable to mix frames with different length");
150 AVSampleFormat fmt = (AVSampleFormat) f.format;
151 bool isPlanar = av_sample_fmt_is_planar(fmt);
152 unsigned samplesPerChannel = isPlanar ? f.nb_samples : f.nb_samples * f.ch_layout.nb_channels;
153 unsigned channels = isPlanar ? f.ch_layout.nb_channels : 1;
154 if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P) {
155 for (
unsigned i = 0; i < channels; i++) {
156 auto c = (int16_t*) f.extended_data[i];
157 auto cIn = (int16_t*) fIn.extended_data[i];
158 for (
unsigned s = 0; s < samplesPerChannel; s++) {
159 c[s] = std::clamp((int32_t) c[s] + (int32_t) cIn[s],
160 (int32_t) std::numeric_limits<int16_t>::min(),
161 (int32_t) std::numeric_limits<int16_t>::max());
164 }
else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP) {
165 for (
unsigned i = 0; i < channels; i++) {
166 auto c = (
float*) f.extended_data[i];
167 auto cIn = (
float*) fIn.extended_data[i];
168 for (
unsigned s = 0; s < samplesPerChannel; s++) {
173 throw std::invalid_argument(std::string(
"Unsupported format for mixing: ")
174 + av_get_sample_fmt_name(fmt));
182 auto fmt =
static_cast<AVSampleFormat
>(
frame_->format);
183 bool planar = av_sample_fmt_is_planar(fmt);
184 int perChannel = planar ?
frame_->nb_samples
186 int channels = planar ?
frame_->ch_layout.nb_channels : 1;
187 if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P) {
188 for (
int c = 0; c < channels; ++c) {
189 auto buf =
reinterpret_cast<int16_t*
>(
frame_->extended_data[c]);
190 for (
int i = 0; i < perChannel; ++i) {
191 auto sample = buf[i] * 0.000030517578125f;
192 rms += sample * sample;
195 }
else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP) {
196 for (
int c = 0; c < channels; ++c) {
197 auto buf =
reinterpret_cast<float*
>(
frame_->extended_data[c]);
198 for (
int i = 0; i < perChannel; ++i) {
199 rms += buf[i] * buf[i];
204 JAMI_ERR() <<
"Unsupported format for getting volume level: "
205 << av_get_sample_fmt_name(fmt);
209 return sqrt(rms / (
frame_->nb_samples *
frame_->ch_layout.nb_channels));
216 if (releaseBufferCb_)
217 releaseBufferCb_(ptr_);
225 releaseBufferCb_ = {};
233 allocated_ = o.allocated_;
239 return av_image_get_buffer_size((AVPixelFormat)
frame_->format,
264VideoFrame::setGeometry(
int format,
int width,
int height)
noexcept
266 frame_->format = format;
267 frame_->width = width;
268 frame_->height = height;
274 auto libav_frame =
frame_.get();
278 if (
width == libav_frame->width and
height == libav_frame->height
279 and
format == libav_frame->format)
280 av_frame_unref(libav_frame);
284 if (av_frame_get_buffer(libav_frame, 32))
285 throw std::bad_alloc();
287 releaseBufferCb_ = {};
294 setGeometry(format, width, height);
297 av_image_fill_arrays(frame_->data,
300 (AVPixelFormat) frame_->format,
311 const std::function<
void(uint8_t*)>& cb)
noexcept
313 setFromMemory(ptr, format, width, height);
315 releaseBufferCb_ = cb;
324 releaseBufferCb_ = cb;
332 if (f->data[0] ==
nullptr)
334 for (std::size_t i = 0; i <
size(); ++i) {
335 f->data[0][i] = std::rand() & 255;
342 int32_t* matrix {
nullptr};
344 matrix =
reinterpret_cast<int32_t*
>(
345 av_packet_get_side_data(p, AV_PKT_DATA_DISPLAYMATRIX,
nullptr));
346 }
else if (
auto p =
pointer()) {
347 if (AVFrameSideData* side_data = av_frame_get_side_data(p, AV_FRAME_DATA_DISPLAYMATRIX)) {
348 matrix =
reinterpret_cast<int32_t*
>(side_data->data);
352 double angle = av_display_rotation_get(matrix);
353 return std::isnan(angle) ? 0 : -(int) angle;
359getNewFrame(std::string_view
id)
362 if (
auto input = vm->getVideoInput(
id))
363 return &input->getNewFrame();
364 JAMI_WARNING(
"getNewFrame: Unable to find input {}",
id);
369publishFrame(std::string_view
id)
372 if (
auto input = vm->getVideoInput(
id))
373 input->publishFrame();
382std::vector<std::string>
386 return vm->videoDeviceMonitor.getDeviceList();
394 return vm->videoDeviceMonitor.getCapabilities(deviceId);
402 return vm->videoDeviceMonitor.getDefaultDevice();
409 JAMI_DBG(
"Setting default device to %s", deviceId.c_str());
411 vm->videoDeviceMonitor.setDefaultDevice(deviceId);
420 vm->setDeviceOrientation(deviceId, angle);
423std::map<std::string, std::string>
427 auto params = vm->videoDeviceMonitor.getDeviceParams(
429 std::ostringstream rate;
430 rate << params.framerate;
431 return {{
"format", params.format},
432 {
"width", std::to_string(params.width)},
433 {
"height", std::to_string(params.height)},
434 {
"rate", rate.str()}};
439std::map<std::string, std::string>
443 return vm->videoDeviceMonitor.getSettings(deviceId)
450applySettings(
const std::string& deviceId,
const std::map<std::string, std::string>& settings)
453 vm->videoDeviceMonitor.applySettings(deviceId, settings);
462 auto id = path.empty() ? vm->videoDeviceMonitor.getMRLForDefaultDevice() : path;
463 auto& input = vm->clientVideoInputs[id];
476 return vm->clientVideoInputs.erase(
id) > 0;
486 vm->audioPreview = newPreview;
487 newPreview->switchInput(
"");
495 vm->audioPreview.reset();
501 auto rec = std::make_unique<jami::LocalRecorder>(videoInputId);
502 rec->setPath(filepath);
505 auto path = rec->getPath();
510 recordManager.insertRecorder(path, std::move(rec));
511 }
catch (
const std::invalid_argument&) {
515 auto ret = recordManager.getRecorderByPath(path)->startRecording();
517 recordManager.removeRecorderByPath(filepath);
529 JAMI_WARN(
"Unable to stop non existing local recorder.");
542 sink->registerTarget(std::move(target));
545 JAMI_WARN(
"No sink found for id '%s'", sinkId.c_str());
552startShmSink(
const std::string& sinkId,
bool value)
556 sink->enableShm(value);
558 JAMI_WARN(
"No sink found for id '%s'", sinkId.c_str());
563std::map<std::string, std::string>
646 JAMI_DBG(
"%s hardware acceleration", (state ?
"Enabling" :
"Disabling"));
666 JAMI_DBG(
"%s hardware acceleration", (state ?
"Enabling" :
"Disabling"));
674 acc->setCodecActive(AV_CODEC_ID_HEVC);
676 acc->setCodecInactive(AV_CODEC_ID_HEVC);
678 acc->setActiveCodecs(acc->getActiveCodecs());
683#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
685addVideoDevice(
const std::string& node,
686 const std::vector<std::map<std::string, std::string>>& devInfo)
689 videoManager->videoDeviceMonitor.addDevice(node, devInfo);
694removeVideoDevice(
const std::string& node)
697 videoManager->videoDeviceMonitor.removeDevice(node);
707video::VideoDeviceMonitor*
711 return &
vm->videoDeviceMonitor;
715std::shared_ptr<video::VideoInput>
722 std::lock_guard<std::mutex>
lk(
vmgr->videoMutex);
723 auto it =
vmgr->videoInputs.find(sinkId);
724 if (
it !=
vmgr->videoInputs.end()) {
725 if (
auto input =
it->second.lock()) {
731 vmgr->videoInputs[sinkId] = input;
736VideoManager::setDeviceOrientation(
const std::string& deviceId,
int angle)
742std::shared_ptr<AudioInput>
748 std::lock_guard<std::mutex>
lk(
vmgr->audioMutex);
751 for (
auto it =
vmgr->audioInputs.cbegin();
it !=
vmgr->audioInputs.cend();) {
752 if (
it->second.expired())
758 auto it =
vmgr->audioInputs.find(device);
759 if (
it !=
vmgr->audioInputs.end()) {
760 if (
auto input =
it->second.lock()) {
765 auto input = std::make_shared<AudioInput>(device);
766 vmgr->audioInputs[device] = input;
774 return !
vmgr->mediaPlayers.empty();
778std::shared_ptr<MediaPlayer>
782 auto it =
vmgr->mediaPlayers.find(
id);
783 if (
it !=
vmgr->mediaPlayers.end()) {
796 player = std::make_shared<MediaPlayer>(path);
817 return vm->mediaPlayers.erase(
id) > 0;
843 return player->getPlayerPosition();
851 return player->getPlayerDuration();
859 player->setAutoRestart(restart);
Interface to protocol account (ex: SIPAccount) It can be enable on loading or activate after.
static LocalRecorderManager & instance()
LocalRecorder * getRecorderByPath(const std::string &path)
Get local recorder instance with passed path as key.
void removeRecorderByPath(const std::string &path)
Remove given local recorder instance from the map.
void stopRecording() override
Stops recording.
std::vector< std::shared_ptr< T > > getAllAccounts() const
Get a list of account pointers of type T (baseclass Account)
static LIBJAMI_TEST_EXPORT Manager & instance()
void saveConfig()
Save config to file.
VideoManager * getVideoManager() const
static const char *const DEFAULT_ID
void mix(const AudioFrame &o)
size_t getFrameSize() const
jami::AudioFormat getFormat() const
void reserve(int format, int width, int height)
std::size_t size() const noexcept
int format() const noexcept
void setFromMemory(uint8_t *data, int format, int width, int height) noexcept
int height() const noexcept
int getOrientation() const
int width() const noexcept
void setReleaseCb(const std::function< void(uint8_t *)> &cb) noexcept
void reset() noexcept override
void copyFrom(const VideoFrame &o)
#define JAMI_WARNING(formatstr,...)
void fillWithSilence(AVFrame *frame)
std::shared_ptr< MediaPlayer > getMediaPlayer(const std::string &id)
bool closeMediaPlayer(const std::string &id)
void emitSignal(Args... args)
libjami::VideoFrame VideoFrame
std::shared_ptr< AudioInput > getAudioInput(const std::string &device)
int64_t getPlayerDuration(const std::string &id)
void setAutoRestart(const std::string &id, bool restart)
bool playerSeekToTime(const std::string &id, int time)
int64_t getPlayerPosition(const std::string &id)
bool pausePlayer(const std::string &id, bool pause)
std::string createMediaPlayer(const std::string &path)
bool mutePlayerAudio(const std::string &id, bool mute)
LIBJAMI_PUBLIC void applySettings(const std::string &deviceId, const std::map< std::string, std::string > &settings)
LIBJAMI_PUBLIC std::map< std::string, std::string > getDeviceParams(const std::string &deviceId)
bool closeMediaPlayer(const std::string &id)
LIBJAMI_PUBLIC std::string getDefaultDevice()
bool getEncodingAccelerated()
std::string startLocalMediaRecorder(const std::string &videoInputId, const std::string &filepath)
bool playerSeekToTime(const std::string &id, const int &time)
std::map< std::string, std::string > getRenderer(const std::string &callId)
LIBJAMI_PUBLIC VideoCapabilities getCapabilities(const std::string &deviceId)
void setEncodingAccelerated(bool state)
bool registerSinkTarget(const std::string &sinkId, SinkTarget target)
LIBJAMI_PUBLIC void setDefaultDevice(const std::string &deviceId)
LIBJAMI_PUBLIC std::map< std::string, std::string > getSettings(const std::string &deviceId)
std::unique_ptr< AVPacket, AVPacket_deleter > PacketBuffer
bool pausePlayer(const std::string &id, const bool &pause)
void registerSignalHandlers(const std::map< std::string, std::shared_ptr< CallbackWrapperBase > > &handlers)
LIBJAMI_PUBLIC void registerVideoHandlers(const std::map< std::string, std::shared_ptr< CallbackWrapperBase > > &)
std::string createMediaPlayer(const std::string &path)
void setDecodingAccelerated(bool state)
void stopLocalRecorder(const std::string &filepath)
LIBJAMI_PUBLIC std::vector< std::string > getDeviceList()
bool getDecodingAccelerated()
LIBJAMI_PUBLIC std::string openVideoInput(const std::string &path)
std::map< std::string, std::map< std::string, std::vector< std::string > > > VideoCapabilities
int64_t getPlayerPosition(const std::string &id)
int64_t getPlayerDuration(const std::string &id)
LIBJAMI_PUBLIC void setDeviceOrientation(const std::string &deviceId, int angle)
LIBJAMI_PUBLIC bool closeVideoInput(const std::string &id)
void setAutoRestart(const std::string &id, const bool &restart)
bool mutePlayerAudio(const std::string &id, const bool &mute)