kopia lustrzana https://github.com/f4exb/sdrangel
Copy audio to UDP/RTP: G722 fixes
rodzic
0ff40fb286
commit
010f6b7ec6
|
@ -173,10 +173,21 @@ void AudioNetSink::write(qint16 isample)
|
||||||
|
|
||||||
if (m_type == SinkUDP)
|
if (m_type == SinkUDP)
|
||||||
{
|
{
|
||||||
if (m_bufferIndex >= m_udpBlockSize)
|
if (m_codec == CodecG722)
|
||||||
{
|
{
|
||||||
m_udpSocket->writeDatagram((const char*)m_data, (qint64 ) m_udpBlockSize, m_address, m_port);
|
if (m_bufferIndex >= 2*m_udpBlockSize)
|
||||||
m_bufferIndex = 0;
|
{
|
||||||
|
m_udpSocket->writeDatagram((const char*) m_data, (qint64 ) m_udpBlockSize, m_address, m_port);
|
||||||
|
m_bufferIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_bufferIndex >= m_udpBlockSize)
|
||||||
|
{
|
||||||
|
m_udpSocket->writeDatagram((const char*) m_data, (qint64 ) m_udpBlockSize, m_address, m_port);
|
||||||
|
m_bufferIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(m_codec)
|
switch(m_codec)
|
||||||
|
@ -202,8 +213,8 @@ void AudioNetSink::write(qint16 isample)
|
||||||
*p = sample;
|
*p = sample;
|
||||||
m_bufferIndex += 1;
|
m_bufferIndex += 1;
|
||||||
|
|
||||||
if (m_bufferIndex == m_udpBlockSize) {
|
if (m_bufferIndex == 2*m_udpBlockSize) {
|
||||||
m_g722.encode((uint8_t *) m_data, (const int16_t*) &m_data[3*m_udpBlockSize], m_udpBlockSize);
|
m_g722.encode((uint8_t *) m_data, (const int16_t*) &m_data[m_udpBlockSize], 2*m_udpBlockSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -236,18 +247,20 @@ void AudioNetSink::write(qint16 isample)
|
||||||
break;
|
break;
|
||||||
case CodecG722:
|
case CodecG722:
|
||||||
{
|
{
|
||||||
if (m_bufferIndex >= m_g722BlockSize)
|
|
||||||
|
if (m_bufferIndex >= 2*m_g722BlockSize)
|
||||||
{
|
{
|
||||||
static const int sz = m_g722BlockSize / sizeof(int16_t);
|
m_g722.encode((uint8_t *) m_data, (const int16_t*) &m_data[m_g722BlockSize], 2*m_g722BlockSize);
|
||||||
uint8_t g722_data[sz];
|
|
||||||
m_g722.encode(g722_data, (const int16_t*) m_data, sz);
|
|
||||||
m_rtpBufferAudio->write(g722_data, sz);
|
|
||||||
m_bufferIndex = 0;
|
m_bufferIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint16 *p = (qint16*) &m_data[m_bufferIndex];
|
if (m_bufferIndex%2 == 0) {
|
||||||
|
m_rtpBufferAudio->write((uint8_t *) &m_data[m_bufferIndex/2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint16 *p = (qint16*) &m_data[m_g722BlockSize + 2*m_bufferIndex];
|
||||||
*p = sample;
|
*p = sample;
|
||||||
m_bufferIndex += sizeof(qint16);
|
m_bufferIndex += 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CodecL16:
|
case CodecL16:
|
||||||
|
|
|
@ -68,8 +68,8 @@ public:
|
||||||
void moveToThread(QThread *thread);
|
void moveToThread(QThread *thread);
|
||||||
|
|
||||||
static const int m_udpBlockSize;
|
static const int m_udpBlockSize;
|
||||||
static const int m_dataBlockSize = 65536;
|
static const int m_dataBlockSize = 16384*5; // room for G722 conversion (largest to date)
|
||||||
static const int m_g722BlockSize = 1024; // size in bytes
|
static const int m_g722BlockSize = 16384; // number of resulting G722 bytes
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SinkType m_type;
|
SinkType m_type;
|
||||||
|
|
|
@ -64,8 +64,9 @@ This is the codec applied before sending the stream via UDP. The following are a
|
||||||
|
|
||||||
- `L16`: Linear 16 bit signed integers (native)
|
- `L16`: Linear 16 bit signed integers (native)
|
||||||
- `L8`: Linear 8 bit signed integers
|
- `L8`: Linear 8 bit signed integers
|
||||||
- `PCMA`: A-law compressed 8 bit PCM
|
- `PCMA`: A-law compressed 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||||
- `PCMU`: Mu-law compressed 8 bit PCM
|
- `PCMU`: Mu-law compressed 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||||
|
- `G722`: G722 64 kbit/s (requires 16000 Hz sample rate mono)
|
||||||
|
|
||||||
<h3>1.10 SDP string</h3>
|
<h3>1.10 SDP string</h3>
|
||||||
|
|
||||||
|
|
|
@ -234,28 +234,37 @@ void AudioDialogX::on_outputSampleRate_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_outputDeviceInfo.sampleRate = value;
|
m_outputDeviceInfo.sampleRate = value;
|
||||||
updateOutputSDPString();
|
updateOutputSDPString();
|
||||||
|
check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDialogX::on_decimationFactor_currentIndexChanged(int index)
|
void AudioDialogX::on_decimationFactor_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_outputDeviceInfo.udpDecimationFactor = index + 1;
|
m_outputDeviceInfo.udpDecimationFactor = index + 1;
|
||||||
updateOutputSDPString();
|
updateOutputSDPString();
|
||||||
|
check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDialogX::on_outputUDPChannelCodec_currentIndexChanged(int index)
|
void AudioDialogX::on_outputUDPChannelCodec_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_outputDeviceInfo.udpChannelCodec = (AudioOutput::UDPChannelCodec) index;
|
m_outputDeviceInfo.udpChannelCodec = (AudioOutput::UDPChannelCodec) index;
|
||||||
updateOutputSDPString();
|
updateOutputSDPString();
|
||||||
|
check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDialogX::on_outputUDPChannelMode_currentIndexChanged(int index)
|
void AudioDialogX::on_outputUDPChannelMode_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_outputDeviceInfo.udpChannelMode = (AudioOutput::UDPChannelMode) index;
|
m_outputDeviceInfo.udpChannelMode = (AudioOutput::UDPChannelMode) index;
|
||||||
updateOutputSDPString();
|
updateOutputSDPString();
|
||||||
|
check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDialogX::updateOutputDisplay()
|
void AudioDialogX::updateOutputDisplay()
|
||||||
{
|
{
|
||||||
|
ui->outputSampleRate->blockSignals(true);
|
||||||
|
ui->outputUDPChannelMode->blockSignals(true);
|
||||||
|
ui->outputUDPChannelCodec->blockSignals(true);
|
||||||
|
ui->decimationFactor->blockSignals(true);
|
||||||
|
|
||||||
ui->outputSampleRate->setValue(m_outputDeviceInfo.sampleRate);
|
ui->outputSampleRate->setValue(m_outputDeviceInfo.sampleRate);
|
||||||
ui->outputUDPAddress->setText(m_outputDeviceInfo.udpAddress);
|
ui->outputUDPAddress->setText(m_outputDeviceInfo.udpAddress);
|
||||||
ui->outputUDPPort->setText(tr("%1").arg(m_outputDeviceInfo.udpPort));
|
ui->outputUDPPort->setText(tr("%1").arg(m_outputDeviceInfo.udpPort));
|
||||||
|
@ -264,7 +273,13 @@ void AudioDialogX::updateOutputDisplay()
|
||||||
ui->outputUDPChannelMode->setCurrentIndex((int) m_outputDeviceInfo.udpChannelMode);
|
ui->outputUDPChannelMode->setCurrentIndex((int) m_outputDeviceInfo.udpChannelMode);
|
||||||
ui->outputUDPChannelCodec->setCurrentIndex((int) m_outputDeviceInfo.udpChannelCodec);
|
ui->outputUDPChannelCodec->setCurrentIndex((int) m_outputDeviceInfo.udpChannelCodec);
|
||||||
ui->decimationFactor->setCurrentIndex(m_outputDeviceInfo.udpDecimationFactor == 0 ? 0 : m_outputDeviceInfo.udpDecimationFactor - 1);
|
ui->decimationFactor->setCurrentIndex(m_outputDeviceInfo.udpDecimationFactor == 0 ? 0 : m_outputDeviceInfo.udpDecimationFactor - 1);
|
||||||
|
|
||||||
updateOutputSDPString();
|
updateOutputSDPString();
|
||||||
|
|
||||||
|
ui->outputSampleRate->blockSignals(false);
|
||||||
|
ui->outputUDPChannelMode->blockSignals(false);
|
||||||
|
ui->outputUDPChannelCodec->blockSignals(false);
|
||||||
|
ui->decimationFactor->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDialogX::updateOutputDeviceInfo()
|
void AudioDialogX::updateOutputDeviceInfo()
|
||||||
|
@ -285,40 +300,50 @@ void AudioDialogX::updateOutputSDPString()
|
||||||
int nChannels = m_outputDeviceInfo.udpChannelMode == AudioOutput::UDPChannelStereo ? 2 : 1;
|
int nChannels = m_outputDeviceInfo.udpChannelMode == AudioOutput::UDPChannelStereo ? 2 : 1;
|
||||||
uint32_t decimationFactor = m_outputDeviceInfo.udpDecimationFactor == 0 ? 1 : m_outputDeviceInfo.udpDecimationFactor;
|
uint32_t decimationFactor = m_outputDeviceInfo.udpDecimationFactor == 0 ? 1 : m_outputDeviceInfo.udpDecimationFactor;
|
||||||
|
|
||||||
|
switch (m_outputDeviceInfo.udpChannelCodec)
|
||||||
|
{
|
||||||
|
case AudioOutput::UDPCodecALaw:
|
||||||
|
format = "PCMA";
|
||||||
|
break;
|
||||||
|
case AudioOutput::UDPCodecULaw:
|
||||||
|
format = "PCMU";
|
||||||
|
break;
|
||||||
|
case AudioOutput::UDPCodecG722:
|
||||||
|
format = "G722";
|
||||||
|
break;
|
||||||
|
case AudioOutput::UDPCodecL8:
|
||||||
|
format = "L8";
|
||||||
|
break;
|
||||||
|
case AudioOutput::UDPCodecL16:
|
||||||
|
default:
|
||||||
|
format = "L16";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->outputSDPText->setText(tr("%1/%2/%3").arg(format).arg(m_outputDeviceInfo.sampleRate/decimationFactor).arg(nChannels));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDialogX::check()
|
||||||
|
{
|
||||||
|
int nChannels = m_outputDeviceInfo.udpChannelMode == AudioOutput::UDPChannelStereo ? 2 : 1;
|
||||||
|
uint32_t decimationFactor = m_outputDeviceInfo.udpDecimationFactor == 0 ? 1 : m_outputDeviceInfo.udpDecimationFactor;
|
||||||
|
|
||||||
if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecALaw)
|
if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecALaw)
|
||||||
{
|
{
|
||||||
format = "PCMA";
|
|
||||||
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 8000)) {
|
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 8000)) {
|
||||||
QMessageBox::information(this, tr("Message"), tr("PCMA must be 8000 Hz single channel"));
|
QMessageBox::information(this, tr("Message"), tr("PCMA must be 8000 Hz single channel"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecULaw)
|
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecULaw)
|
||||||
{
|
{
|
||||||
format = "PCMU";
|
|
||||||
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 8000)) {
|
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 8000)) {
|
||||||
QMessageBox::information(this, tr("Message"), tr("PCMU must be 8000 Hz single channel"));
|
QMessageBox::information(this, tr("Message"), tr("PCMU must be 8000 Hz single channel"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecG722)
|
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecG722)
|
||||||
{
|
{
|
||||||
format = "G722";
|
|
||||||
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 16000)) {
|
if ((nChannels != 1) || (m_outputDeviceInfo.sampleRate/decimationFactor != 16000)) {
|
||||||
QMessageBox::information(this, tr("Message"), tr("G722 must be 16000 Hz single channel"));
|
QMessageBox::information(this, tr("Message"), tr("G722 must be 16000 Hz single channel"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecL8)
|
|
||||||
{
|
|
||||||
format = "L8";
|
|
||||||
}
|
|
||||||
else if (m_outputDeviceInfo.udpChannelCodec == AudioOutput::UDPCodecL16)
|
|
||||||
{
|
|
||||||
format = "L16";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMessageBox::information(this, tr("Message"), tr("Unknown codec"));
|
|
||||||
format = "UNK";
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->outputSDPText->setText(tr("%1/%2/%3").arg(format).arg(m_outputDeviceInfo.sampleRate/decimationFactor).arg(nChannels));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
void accept();
|
void accept();
|
||||||
void reject();
|
void reject();
|
||||||
|
void check();
|
||||||
void on_audioInTree_currentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previousItem);
|
void on_audioInTree_currentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previousItem);
|
||||||
void on_audioOutTree_currentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previousItem);
|
void on_audioOutTree_currentItemChanged(QTreeWidgetItem* currentItem, QTreeWidgetItem* previousItem);
|
||||||
void on_inputVolume_valueChanged(int value);
|
void on_inputVolume_valueChanged(int value);
|
||||||
|
|
Ładowanie…
Reference in New Issue