mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
Added RTP Sink based on JRTPLib and AudioNetSink to handle sending audio over the network via UDP or RTP
This commit is contained in:
parent
f4e2ac61f8
commit
cc461f2f0f
@ -57,9 +57,9 @@ find_package(Qt5Multimedia 5.0 REQUIRED)
|
|||||||
#find_package(QT5OpenGL 5.0 REQUIRED)
|
#find_package(QT5OpenGL 5.0 REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
|
|
||||||
find_package(Boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
find_package(FFTW3F)
|
find_package(FFTW3F)
|
||||||
|
find_package(JRTPLib)
|
||||||
|
|
||||||
if (NOT BUILD_DEBIAN)
|
if (NOT BUILD_DEBIAN)
|
||||||
find_package(LibDSDcc)
|
find_package(LibDSDcc)
|
||||||
|
37
cmake/Modules/FindJRTPLib.cmake
Normal file
37
cmake/Modules/FindJRTPLib.cmake
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
INCLUDE(FindPkgConfig)
|
||||||
|
PKG_CHECK_MODULES(PC_JRTPLIB "jrtplib")
|
||||||
|
|
||||||
|
FIND_PATH(JRTPLIB_INCLUDE_DIR
|
||||||
|
NAMES rtpsession.h
|
||||||
|
HINTS ${PC_JRTPLIB_INCLUDE_DIR}
|
||||||
|
${CMAKE_INSTALL_PREFIX}/include/jrtplib3
|
||||||
|
${JRTPLIB_INSTALL_PREFIX}/include/jrtplib3
|
||||||
|
PATHS
|
||||||
|
/usr/local/include/jrtplib3
|
||||||
|
/usr/include/jrtplib3
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(JRTPLIB_LIBRARIES
|
||||||
|
NAMES libjrtp
|
||||||
|
HINTS ${PC_JRTPLIB_LIBDIR}
|
||||||
|
${CMAKE_INSTALL_PREFIX}/lib
|
||||||
|
${CMAKE_INSTALL_PREFIX}/lib64
|
||||||
|
PATHS
|
||||||
|
${JRTPLIB_INCLUDE_DIR}/../lib
|
||||||
|
/usr/local/lib
|
||||||
|
/usr/local/lib64
|
||||||
|
/usr/lib
|
||||||
|
/usr/lib64
|
||||||
|
)
|
||||||
|
|
||||||
|
if(JRTPLIB_INCLUDE_DIR AND JRTPLIB_LIBRARIES)
|
||||||
|
set(JRTPLIB_FOUND TRUE CACHE INTERNAL "JRTPLib found")
|
||||||
|
message(STATUS "Found JRTPLib: ${JRTPLIB_INCLUDE_DIR}, ${JRTPLIB_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
set(JRTPLIB_FOUND FALSE CACHE INTERNAL "JRTPLib found")
|
||||||
|
message(STATUS "JRTPLib not found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(JRTPLIB DEFAULT_MSG JRTPLIB_LIBRARIES JRTPLIB_INCLUDE_DIR)
|
||||||
|
MARK_AS_ADVANCED(JRTPLIB_LIBRARIES JRTPLIB_INCLUDE_DIR)
|
@ -7,7 +7,8 @@ set(sdrbase_SOURCES
|
|||||||
audio/audiofifo.cpp
|
audio/audiofifo.cpp
|
||||||
audio/audiooutput.cpp
|
audio/audiooutput.cpp
|
||||||
audio/audioinput.cpp
|
audio/audioinput.cpp
|
||||||
|
audio/audionetsink.cpp
|
||||||
|
|
||||||
channel/channelsinkapi.cpp
|
channel/channelsinkapi.cpp
|
||||||
channel/channelsourceapi.cpp
|
channel/channelsourceapi.cpp
|
||||||
commands/command.cpp
|
commands/command.cpp
|
||||||
@ -85,6 +86,7 @@ set(sdrbase_HEADERS
|
|||||||
audio/audiofifo.h
|
audio/audiofifo.h
|
||||||
audio/audiooutput.h
|
audio/audiooutput.h
|
||||||
audio/audioinput.h
|
audio/audioinput.h
|
||||||
|
audio/audionetsink.h
|
||||||
|
|
||||||
channel/channelsinkapi.h
|
channel/channelsinkapi.h
|
||||||
channel/channelsourceapi.h
|
channel/channelsourceapi.h
|
||||||
@ -209,6 +211,15 @@ else(FFTW3F_FOUND)
|
|||||||
add_definitions(-DUSE_KISSFFT)
|
add_definitions(-DUSE_KISSFFT)
|
||||||
endif(FFTW3F_FOUND)
|
endif(FFTW3F_FOUND)
|
||||||
|
|
||||||
|
if (JRTPLIB_FOUND)
|
||||||
|
set(sdrbase_HEADERS
|
||||||
|
${sdrbase_HEADERS}
|
||||||
|
util/rtpsink.h
|
||||||
|
)
|
||||||
|
add_definitions(-DHAS_JRTPLIB)
|
||||||
|
include_directories(${JRTPLIB_INCLUDE_DIR})
|
||||||
|
endif(JRTPLIB_FOUND)
|
||||||
|
|
||||||
if (LIBSERIALDV_FOUND)
|
if (LIBSERIALDV_FOUND)
|
||||||
set(sdrbase_SOURCES
|
set(sdrbase_SOURCES
|
||||||
${sdrbase_SOURCES}
|
${sdrbase_SOURCES}
|
||||||
@ -271,6 +282,10 @@ if(FFTW3F_FOUND)
|
|||||||
target_link_libraries(sdrbase ${FFTW3F_LIBRARIES})
|
target_link_libraries(sdrbase ${FFTW3F_LIBRARIES})
|
||||||
endif(FFTW3F_FOUND)
|
endif(FFTW3F_FOUND)
|
||||||
|
|
||||||
|
if (JRTPLIB_FOUND)
|
||||||
|
target_link_libraries(sdrbase ${JRTPLIB_LIBRARIES})
|
||||||
|
endif(JRTPLIB_FOUND)
|
||||||
|
|
||||||
if(LIBSERIALDV_FOUND)
|
if(LIBSERIALDV_FOUND)
|
||||||
target_link_libraries(sdrbase ${LIBSERIALDV_LIBRARY})
|
target_link_libraries(sdrbase ${LIBSERIALDV_LIBRARY})
|
||||||
endif(LIBSERIALDV_FOUND)
|
endif(LIBSERIALDV_FOUND)
|
||||||
|
160
sdrbase/audio/audionetsink.cpp
Normal file
160
sdrbase/audio/audionetsink.cpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2018 F4EXB //
|
||||||
|
// written by Edouard Griffiths //
|
||||||
|
// //
|
||||||
|
// 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 as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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 V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "audionetsink.h"
|
||||||
|
|
||||||
|
const int AudioNetSink::m_udpBlockSize = 512;
|
||||||
|
|
||||||
|
AudioNetSink::AudioNetSink(QObject *parent, bool stereo) :
|
||||||
|
m_type(SinkUDP),
|
||||||
|
m_udpBufferAudioMono(0),
|
||||||
|
m_udpBufferAudioStereo(0)
|
||||||
|
{
|
||||||
|
if (stereo)
|
||||||
|
{
|
||||||
|
m_udpBufferAudioStereo = new UDPSink<AudioSample>(parent, m_udpBlockSize);
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
m_rtpBufferAudioStereo = new RTPSink<AudioSample>("127.0.0.1", 9999, 48000);
|
||||||
|
m_rtpBufferAudioMono = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_udpBufferAudioMono = new UDPSink<int16_t>(parent, m_udpBlockSize);
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
m_rtpBufferAudioMono = new RTPSink<int16_t>("127.0.0.1", 9999, 48000);
|
||||||
|
m_rtpBufferAudioStereo = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioNetSink::~AudioNetSink()
|
||||||
|
{
|
||||||
|
if (m_udpBufferAudioMono) { delete m_udpBufferAudioMono; }
|
||||||
|
if (m_udpBufferAudioStereo) { delete m_udpBufferAudioStereo; }
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
if (m_rtpBufferAudioMono) { delete m_rtpBufferAudioMono; }
|
||||||
|
if (m_rtpBufferAudioStereo) { delete m_rtpBufferAudioStereo; }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioNetSink::selectType(SinkType type)
|
||||||
|
{
|
||||||
|
if (type == SinkUDP)
|
||||||
|
{
|
||||||
|
m_type = SinkUDP;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (type == SinkRTP)
|
||||||
|
{
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
m_type = SinkRTP;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
m_type = SinkUDP;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::setDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
if (m_udpBufferAudioMono) {
|
||||||
|
m_udpBufferAudioMono->setDestination(address, port);
|
||||||
|
}
|
||||||
|
if (m_udpBufferAudioStereo) {
|
||||||
|
m_udpBufferAudioStereo->setDestination(address, port);
|
||||||
|
}
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
if (m_rtpBufferAudioMono) {
|
||||||
|
m_rtpBufferAudioMono->setDestination(address, port);
|
||||||
|
}
|
||||||
|
if (m_rtpBufferAudioStereo) {
|
||||||
|
m_rtpBufferAudioStereo->setDestination(address, port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::addDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
if (m_rtpBufferAudioMono) {
|
||||||
|
m_rtpBufferAudioMono->addDestination(address, port);
|
||||||
|
}
|
||||||
|
if (m_rtpBufferAudioStereo) {
|
||||||
|
m_rtpBufferAudioStereo->addDestination(address, port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::deleteDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
if (m_rtpBufferAudioMono) {
|
||||||
|
m_rtpBufferAudioMono->deleteDestination(address, port);
|
||||||
|
}
|
||||||
|
if (m_rtpBufferAudioStereo) {
|
||||||
|
m_rtpBufferAudioStereo->deleteDestination(address, port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::setSampleRate(int sampleRate)
|
||||||
|
{
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
if (m_rtpBufferAudioMono) {
|
||||||
|
m_rtpBufferAudioMono->setSampleRate(sampleRate);
|
||||||
|
}
|
||||||
|
if (m_rtpBufferAudioStereo) {
|
||||||
|
m_rtpBufferAudioStereo->setSampleRate(sampleRate);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::write(qint16 sample)
|
||||||
|
{
|
||||||
|
if (m_udpBufferAudioMono == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_type == SinkUDP) {
|
||||||
|
m_udpBufferAudioMono->write(sample);
|
||||||
|
} else if (m_type == SinkRTP) {
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioNetSink::write(const AudioSample& sample)
|
||||||
|
{
|
||||||
|
if (m_udpBufferAudioStereo == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_type == SinkUDP) {
|
||||||
|
m_udpBufferAudioStereo->write(sample);
|
||||||
|
} else if (m_type == SinkRTP) {
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
65
sdrbase/audio/audionetsink.h
Normal file
65
sdrbase/audio/audionetsink.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2018 F4EXB //
|
||||||
|
// written by Edouard Griffiths //
|
||||||
|
// //
|
||||||
|
// 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 as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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 V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SDRBASE_AUDIO_AUDIONETSINK_H_
|
||||||
|
#define SDRBASE_AUDIO_AUDIONETSINK_H_
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "dsp/dsptypes.h"
|
||||||
|
#include "util/export.h"
|
||||||
|
#include "util/udpsink.h"
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
#include "util/rtpsink.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class SDRANGEL_API AudioNetSink {
|
||||||
|
public:
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SinkUDP,
|
||||||
|
SinkRTP
|
||||||
|
} SinkType;
|
||||||
|
|
||||||
|
AudioNetSink(QObject *parent, bool stereo = false);
|
||||||
|
~AudioNetSink();
|
||||||
|
|
||||||
|
void setDestination(const QString& address, uint16_t port);
|
||||||
|
void addDestination(const QString& address, uint16_t port);
|
||||||
|
void deleteDestination(const QString& address, uint16_t port);
|
||||||
|
void setSampleRate(int sampleRate);
|
||||||
|
|
||||||
|
void write(qint16 sample);
|
||||||
|
void write(const AudioSample& sample);
|
||||||
|
|
||||||
|
bool selectType(SinkType type);
|
||||||
|
|
||||||
|
static const int m_udpBlockSize;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SinkType m_type;
|
||||||
|
UDPSink<qint16> *m_udpBufferAudioMono;
|
||||||
|
UDPSink<AudioSample> *m_udpBufferAudioStereo;
|
||||||
|
#ifdef HAS_JRTPLIB
|
||||||
|
RTPSink<qint16> *m_rtpBufferAudioMono;
|
||||||
|
RTPSink<AudioSample> *m_rtpBufferAudioStereo;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SDRBASE_AUDIO_AUDIONETSINK_H_ */
|
143
sdrbase/util/rtpsink.h
Normal file
143
sdrbase/util/rtpsink.h
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2018 F4EXB //
|
||||||
|
// written by Edouard Griffiths //
|
||||||
|
// //
|
||||||
|
// 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 as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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 V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SDRBASE_UTIL_RTPSINK_H_
|
||||||
|
#define SDRBASE_UTIL_RTPSINK_H_
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// jrtplib includes
|
||||||
|
#include "rtpsession.h"
|
||||||
|
#include "rtpudpv4transmitter.h"
|
||||||
|
#include "rtpipv4address.h"
|
||||||
|
#include "rtpsessionparams.h"
|
||||||
|
#include "rtperrors.h"
|
||||||
|
#include "rtplibraryversion.h"
|
||||||
|
|
||||||
|
template<typename SampleType>
|
||||||
|
class RTPSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RTPSink(const QString& address, uint16_t port, int sampleRate) :
|
||||||
|
m_destport(port),
|
||||||
|
m_sampleBuffer(0),
|
||||||
|
m_sampleBufferIndex(0),
|
||||||
|
m_mutex(QMutex::Recursive)
|
||||||
|
{
|
||||||
|
m_destip = inet_addr(address.toStdString().c_str());
|
||||||
|
m_destip = ntohl(m_destip);
|
||||||
|
m_rtpSessionParams.SetOwnTimestampUnit(1.0/(double) sampleRate);
|
||||||
|
m_rtpTransmissionParams.SetPortbase(8092); // FIXME: sort this out
|
||||||
|
|
||||||
|
int status = m_rtpSession.Create(m_rtpSessionParams, &m_rtpTransmissionParams);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
qCritical("RTPSink::RTPSink: cannot create session: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = m_rtpSession.AddDestination(jrtplib::RTPIPv4Address(m_destip, m_destport));
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
qCritical("RTPSink::RTPSink: cannot set destination address: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sampleBuffer = new SampleType[sampleRate]; // store 1 second
|
||||||
|
}
|
||||||
|
|
||||||
|
~RTPSink()
|
||||||
|
{
|
||||||
|
jrtplib::RTPTime delay = jrtplib::RTPTime(10.0);
|
||||||
|
m_rtpSession.BYEDestroy(delay, "Time's up", 9);
|
||||||
|
|
||||||
|
if (m_sampleBuffer) { delete[] m_sampleBuffer; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
if (!m_sampleBuffer) { return; }
|
||||||
|
|
||||||
|
m_rtpSession.ClearDestinations();
|
||||||
|
m_rtpSession.DeleteDestination(jrtplib::RTPIPv4Address(m_destip, m_destport));
|
||||||
|
m_destip = inet_addr(address.toStdString().c_str());
|
||||||
|
m_destip = ntohl(m_destip);
|
||||||
|
m_destport = port;
|
||||||
|
|
||||||
|
int status = m_rtpSession.AddDestination(jrtplib::RTPIPv4Address(m_destip, m_destport));
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
qCritical("RTPSink::setDestination: cannot set destination address: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
uint32_t destip = inet_addr(address.toStdString().c_str());
|
||||||
|
destip = ntohl(m_destip);
|
||||||
|
|
||||||
|
int status = m_rtpSession.DeleteDestination(jrtplib::RTPIPv4Address(destip, port));
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
qCritical("RTPSink::deleteDestination: cannot delete destination address: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
uint32_t destip = inet_addr(address.toStdString().c_str());
|
||||||
|
destip = ntohl(m_destip);
|
||||||
|
|
||||||
|
int status = m_rtpSession.AddDestination(jrtplib::RTPIPv4Address(destip, port));
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
qCritical("RTPSink::addDestination: cannot add destination address: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSampleRate(int sampleRate)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
if (m_sampleBuffer) { delete[] m_sampleBuffer; }
|
||||||
|
m_sampleBuffer = new SampleType[sampleRate]; // store 1 second
|
||||||
|
|
||||||
|
int status = m_rtpSession.SetTimestampUnit(1.0 / (double) sampleRate);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
qCritical("RTPSink::setSampleRate: cannot set timestamp unit: %s", jrtplib::RTPGetErrorString(status).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_destip;
|
||||||
|
uint16_t m_destport;
|
||||||
|
jrtplib::RTPSession m_rtpSession;
|
||||||
|
jrtplib::RTPSessionParams m_rtpSessionParams;
|
||||||
|
jrtplib::RTPUDPv4TransmissionParams m_rtpTransmissionParams;
|
||||||
|
SampleType *m_sampleBuffer;
|
||||||
|
int m_sampleBufferIndex;
|
||||||
|
QMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SDRBASE_UTIL_RTPSINK_H_ */
|
@ -29,11 +29,11 @@ template<typename T>
|
|||||||
class UDPSink
|
class UDPSink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UDPSink(QObject *parent, unsigned int udpSize, unsigned int port) :
|
UDPSink(QObject *parent, unsigned int udpSize) :
|
||||||
m_udpSize(udpSize),
|
m_udpSize(udpSize),
|
||||||
m_udpSamples(udpSize/sizeof(T)),
|
m_udpSamples(udpSize/sizeof(T)),
|
||||||
m_address(QHostAddress::LocalHost),
|
m_address(QHostAddress::LocalHost),
|
||||||
m_port(port),
|
m_port(9999),
|
||||||
m_sampleBufferIndex(0)
|
m_sampleBufferIndex(0)
|
||||||
{
|
{
|
||||||
assert(m_udpSamples > 0);
|
assert(m_udpSamples > 0);
|
||||||
@ -41,6 +41,18 @@ public:
|
|||||||
m_socket = new QUdpSocket(parent);
|
m_socket = new QUdpSocket(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UDPSink(QObject *parent, unsigned int udpSize, unsigned int port) :
|
||||||
|
m_udpSize(udpSize),
|
||||||
|
m_udpSamples(udpSize/sizeof(T)),
|
||||||
|
m_address(QHostAddress::LocalHost),
|
||||||
|
m_port(port),
|
||||||
|
m_sampleBufferIndex(0)
|
||||||
|
{
|
||||||
|
assert(m_udpSamples > 0);
|
||||||
|
m_sampleBuffer = new T[m_udpSamples];
|
||||||
|
m_socket = new QUdpSocket(parent);
|
||||||
|
}
|
||||||
|
|
||||||
UDPSink (QObject *parent, unsigned int udpSize, QHostAddress& address, unsigned int port) :
|
UDPSink (QObject *parent, unsigned int udpSize, QHostAddress& address, unsigned int port) :
|
||||||
m_udpSize(udpSize),
|
m_udpSize(udpSize),
|
||||||
m_udpSamples(udpSize/sizeof(T)),
|
m_udpSamples(udpSize/sizeof(T)),
|
||||||
@ -62,6 +74,12 @@ public:
|
|||||||
void setAddress(QString& address) { m_address.setAddress(address); }
|
void setAddress(QString& address) { m_address.setAddress(address); }
|
||||||
void setPort(unsigned int port) { m_port = port; }
|
void setPort(unsigned int port) { m_port = port; }
|
||||||
|
|
||||||
|
void setDestination(const QString& address, int port)
|
||||||
|
{
|
||||||
|
m_address.setAddress(const_cast<QString&>(address));
|
||||||
|
m_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write one sample
|
* Write one sample
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user