Various enhancements and fixes:
- fixed handling of Max samples per packet Source parameter in the WebUI and added computation of the real frame duration - fixed max number of channels configurable for a Sink in the WebUI - fixed tic_frame_size_at_1fs daemon parameter documentation - changed daemon default sample_rate parameter to 48000 Hz
This commit is contained in:
parent
9c4913f7e4
commit
07c2b35777
@ -221,8 +221,7 @@ where:
|
|||||||
|
|
||||||
> **tic\_frame\_size\_at\_1fs**
|
> **tic\_frame\_size\_at\_1fs**
|
||||||
> JSON number specifying the TIC frame size at 1FS in samples, valid range is from 6 to 192 samples.
|
> JSON number specifying the TIC frame size at 1FS in samples, valid range is from 6 to 192 samples.
|
||||||
> This global setting is used to determine the driver base timer period. For example with a value of 192 samples this period is set to 4ms and the outgoing RTP packets are scheduled for being sent every 4ms causing an average latency greater than 4ms.
|
> This global setting is used to determine the driver base timer period. For example with a value of 192 samples this period is set to 4ms and the outgoing RTP packets are scheduled for being sent every 4ms resulting on an average latency greater than 4ms.
|
||||||
> A user is able to configure Sources whose max number of samples range from 125μs (6 samples) to the value of this parameter. For example with a value of 48 samples a user is able to configure Sources with a max number of samples ranging from 125μs (6 samples) to 1ms (48 samples) and packets will be affected by a 1ms latency.
|
|
||||||
|
|
||||||
> **max\_tic\_frame\_size**
|
> **max\_tic\_frame\_size**
|
||||||
> JSON number specifying the max tick frame size. This is currently set to 1024.
|
> JSON number specifying the max tick frame size. This is currently set to 1024.
|
||||||
|
@ -65,7 +65,7 @@ std::shared_ptr<Config> Config::parse(const std::string& filename) {
|
|||||||
config.max_tic_frame_size_ > 1024)
|
config.max_tic_frame_size_ > 1024)
|
||||||
config.max_tic_frame_size_ = 1024;
|
config.max_tic_frame_size_ = 1024;
|
||||||
if (config.sample_rate_ == 0)
|
if (config.sample_rate_ == 0)
|
||||||
config.sample_rate_ = 44100;
|
config.sample_rate_ = 48000;
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
ip::address_v4::from_string(config.rtp_mcast_base_.c_str(), ec);
|
ip::address_v4::from_string(config.rtp_mcast_base_.c_str(), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
|
@ -119,7 +119,7 @@ class Config {
|
|||||||
uint32_t playout_delay_{0};
|
uint32_t playout_delay_{0};
|
||||||
uint32_t tic_frame_size_at_1fs_{48};
|
uint32_t tic_frame_size_at_1fs_{48};
|
||||||
uint32_t max_tic_frame_size_{1024};
|
uint32_t max_tic_frame_size_{1024};
|
||||||
uint32_t sample_rate_{44100};
|
uint32_t sample_rate_{48000};
|
||||||
std::string rtp_mcast_base_{"239.1.0.1"};
|
std::string rtp_mcast_base_{"239.1.0.1"};
|
||||||
std::string sap_mcast_addr_{"224.2.127.254"};
|
std::string sap_mcast_addr_{"224.2.127.254"};
|
||||||
uint16_t rtp_port_{5004};
|
uint16_t rtp_port_{5004};
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"playout_delay": 0,
|
"playout_delay": 0,
|
||||||
"tic_frame_size_at_1fs": 48,
|
"tic_frame_size_at_1fs": 48,
|
||||||
"max_tic_frame_size": 1024,
|
"max_tic_frame_size": 1024,
|
||||||
"sample_rate": 44100,
|
"sample_rate": 48000,
|
||||||
"rtp_mcast_base": "239.1.0.1",
|
"rtp_mcast_base": "239.1.0.1",
|
||||||
"rtp_port": 5004,
|
"rtp_port": 5004,
|
||||||
"ptp_domain": 0,
|
"ptp_domain": 0,
|
||||||
|
@ -455,9 +455,7 @@ std::error_code SessionManager::add_source(const StreamSource& source) {
|
|||||||
info.stream.m_byNbOfChannels = source.map.size();
|
info.stream.m_byNbOfChannels = source.map.size();
|
||||||
strncpy(info.stream.m_cCodec, source.codec.c_str(),
|
strncpy(info.stream.m_cCodec, source.codec.c_str(),
|
||||||
sizeof(info.stream.m_cCodec) - 1);
|
sizeof(info.stream.m_cCodec) - 1);
|
||||||
info.stream.m_ui32MaxSamplesPerPacket =
|
info.stream.m_ui32MaxSamplesPerPacket = source.max_samples_per_packet;
|
||||||
source.max_samples_per_packet > config_->get_tic_frame_size_at_1fs() ?
|
|
||||||
config_->get_tic_frame_size_at_1fs() : source.max_samples_per_packet;
|
|
||||||
info.stream.m_ui32SamplingRate = driver_->get_current_sample_rate(); // last set from driver or config
|
info.stream.m_ui32SamplingRate = driver_->get_current_sample_rate(); // last set from driver or config
|
||||||
info.stream.m_uiId = source.id;
|
info.stream.m_uiId = source.id;
|
||||||
info.stream.m_ui32RTCPSrcIP = config_->get_ip_addr();
|
info.stream.m_ui32RTCPSrcIP = config_->get_ip_addr();
|
||||||
|
@ -140,12 +140,13 @@ class Config extends Component {
|
|||||||
<th align="left"> <label>TIC frame size @1FS (samples) </label> </th>
|
<th align="left"> <label>TIC frame size @1FS (samples) </label> </th>
|
||||||
<th align="left">
|
<th align="left">
|
||||||
<select value={this.state.ticFrameSizeAt1fs} onChange={e => this.setState({ticFrameSizeAt1fs: e.target.value})}>
|
<select value={this.state.ticFrameSizeAt1fs} onChange={e => this.setState({ticFrameSizeAt1fs: e.target.value})}>
|
||||||
<option value="6">6 - 125μs@48Khz</option>
|
<option value="6">6 - 125μs</option>
|
||||||
<option value="12">12 - 250μs@48Khz</option>
|
<option value="12">12 - 250μs</option>
|
||||||
<option value="16">16 - 333μs@48Khz</option>
|
<option value="16">16 - 333μs</option>
|
||||||
<option value="48">48 - 1ms@48Khz</option>
|
<option value="24">24 - 500μs</option>
|
||||||
<option value="96">96 - 2ms@48Khz</option>
|
<option value="48">48 - 1ms</option>
|
||||||
<option value="192">192 - 4ms@48Khz</option>
|
<option value="96">96 - 2ms</option>
|
||||||
|
<option value="192">192 - 4ms</option>
|
||||||
</select>
|
</select>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -213,7 +213,7 @@ class SinkEdit extends Component {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th align="left"> <label>Channels</label> </th>
|
<th align="left"> <label>Channels</label> </th>
|
||||||
<th align="left"> <input type='number' min='1' max='8' className='input-number' value={this.state.channels} onChange={this.onChangeChannels} required/> </th>
|
<th align="left"> <input type='number' min='1' max='64' className='input-number' value={this.state.channels} onChange={this.onChangeChannels} required/> </th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th align="left">Audio Channels map</th>
|
<th align="left">Audio Channels map</th>
|
||||||
|
@ -44,6 +44,7 @@ class SourceEdit extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
source: PropTypes.object.isRequired,
|
source: PropTypes.object.isRequired,
|
||||||
ticFrameSizeAt1fs: PropTypes.number.isRequired,
|
ticFrameSizeAt1fs: PropTypes.number.isRequired,
|
||||||
|
sampleRate: PropTypes.number.isRequired,
|
||||||
applyEdit: PropTypes.func.isRequired,
|
applyEdit: PropTypes.func.isRequired,
|
||||||
closeEdit: PropTypes.func.isRequired,
|
closeEdit: PropTypes.func.isRequired,
|
||||||
editIsOpen: PropTypes.bool.isRequired,
|
editIsOpen: PropTypes.bool.isRequired,
|
||||||
@ -59,8 +60,6 @@ class SourceEdit extends Component {
|
|||||||
name: this.props.source.name,
|
name: this.props.source.name,
|
||||||
nameErr: false,
|
nameErr: false,
|
||||||
io: this.props.source.io,
|
io: this.props.source.io,
|
||||||
maxSamplesPerPacket: (this.props.source.max_samples_per_packet > this.props.ticFrameSizeAt1fs) ?
|
|
||||||
this.props.ticFrameSizeAt1fs : this.props.source.max_samples_per_packet,
|
|
||||||
codec: this.props.source.codec,
|
codec: this.props.source.codec,
|
||||||
ttl: this.props.source.ttl,
|
ttl: this.props.source.ttl,
|
||||||
ttlErr: false,
|
ttlErr: false,
|
||||||
@ -70,8 +69,9 @@ class SourceEdit extends Component {
|
|||||||
refclkPtpTraceable: this.props.source.refclk_ptp_traceable,
|
refclkPtpTraceable: this.props.source.refclk_ptp_traceable,
|
||||||
channels: this.props.source.map.length,
|
channels: this.props.source.map.length,
|
||||||
channelsErr: false,
|
channelsErr: false,
|
||||||
maxChannels: Math.floor(max_packet_size / (this.props.source.max_samples_per_packet * (this.props.source.codec === 'L16' ? 2 : 3))),
|
|
||||||
map: this.props.source.map,
|
map: this.props.source.map,
|
||||||
|
maxSamplesPerPacket: this.getMaxSamplesPerPacket(),
|
||||||
|
maxChannels: this.getMaxChannels(this.props.source.codec, this.getMaxSamplesPerPacket()),
|
||||||
audioMap: []
|
audioMap: []
|
||||||
}
|
}
|
||||||
let v;
|
let v;
|
||||||
@ -87,6 +87,10 @@ class SourceEdit extends Component {
|
|||||||
this.onChangeCodec = this.onChangeCodec.bind(this);
|
this.onChangeCodec = this.onChangeCodec.bind(this);
|
||||||
this.inputIsValid = this.inputIsValid.bind(this);
|
this.inputIsValid = this.inputIsValid.bind(this);
|
||||||
this.checkMaxSamplesPerPacket = this.checkMaxSamplesPerPacket.bind(this);
|
this.checkMaxSamplesPerPacket = this.checkMaxSamplesPerPacket.bind(this);
|
||||||
|
this.getMaxSamplesPerPacket = this.getMaxSamplesPerPacket.bind(this);
|
||||||
|
this.getnFS = this.getnFS.bind(this);
|
||||||
|
this.getPacketDuration = this.getPacketDuration.bind(this);
|
||||||
|
this.getMaxChannels = this.getMaxChannels.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -121,15 +125,20 @@ class SourceEdit extends Component {
|
|||||||
this.props.closeEdit();
|
this.props.closeEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMaxChannels(codec, samples) {
|
||||||
|
let maxChannels = Math.floor(max_packet_size / (samples * (codec === 'L16' ? 2 : 3)));
|
||||||
|
return maxChannels > 64 ? 64 : maxChannels;
|
||||||
|
}
|
||||||
|
|
||||||
onChangeMaxSamplesPerPacket(e) {
|
onChangeMaxSamplesPerPacket(e) {
|
||||||
let samples = parseInt(e.target.value, 10);
|
let samples = parseInt(e.target.value, 10);
|
||||||
let maxChannels = Math.floor(max_packet_size / (samples * (this.state.codec === 'L16' ? 2 : 3)));
|
let maxChannels = this.getMaxChannels(this.state.codec, samples);
|
||||||
this.setState({ maxSamplesPerPacket: samples, maxChannels: maxChannels, channelsErr: this.state.channels > maxChannels });
|
this.setState({ maxSamplesPerPacket: samples, maxChannels: maxChannels, channelsErr: this.state.channels > maxChannels });
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeCodec(e) {
|
onChangeCodec(e) {
|
||||||
let codec = e.target.value;
|
let codec = e.target.value;
|
||||||
let maxChannels = Math.floor(max_packet_size / (this.state.maxSamplesPerPacket * (codec === 'L16' ? 2 : 3)));
|
let maxChannels = this.getMaxChannels(this.state.codec, this.state.maxSamplesPerPacket);
|
||||||
this.setState({ codec: codec, maxChannels: maxChannels, channelsErr: this.state.channels > maxChannels });
|
this.setState({ codec: codec, maxChannels: maxChannels, channelsErr: this.state.channels > maxChannels });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +165,47 @@ class SourceEdit extends Component {
|
|||||||
this.setState({ map: map });
|
this.setState({ map: map });
|
||||||
}
|
}
|
||||||
|
|
||||||
checkMaxSamplesPerPacket(value) {
|
getnFS() {
|
||||||
return this.props.ticFrameSizeAt1fs >= value;
|
switch(this.props.sampleRate) {
|
||||||
|
case 384000:
|
||||||
|
case 352800:
|
||||||
|
return 8;
|
||||||
|
break;
|
||||||
|
case 192000:
|
||||||
|
case 176400:
|
||||||
|
return 4;
|
||||||
|
break;
|
||||||
|
case 96000:
|
||||||
|
case 88200:
|
||||||
|
return 2;
|
||||||
|
break;
|
||||||
|
case 48000:
|
||||||
|
case 44100:
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMaxSamplesPerPacket(samples) {
|
||||||
|
return (samples <= (this.props.ticFrameSizeAt1fs * this.getnFS()));
|
||||||
|
}
|
||||||
|
|
||||||
|
getMaxSamplesPerPacket() {
|
||||||
|
return (this.props.source.max_samples_per_packet > (this.props.ticFrameSizeAt1fs * this.getnFS())) ?
|
||||||
|
(this.props.ticFrameSizeAt1fs * this.getnFS()) : this.props.source.max_samples_per_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPacketDuration(samples) {
|
||||||
|
let duration = (samples * 1000000) / this.props.sampleRate;
|
||||||
|
if (duration >= 1000) {
|
||||||
|
duration /= 1000;
|
||||||
|
if (duration == Math.round(duration))
|
||||||
|
return Math.round(duration).toString() + 'ms';
|
||||||
|
else
|
||||||
|
return (Math.round(duration * 1000) / 1000).toString() + 'ms';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Math.round(duration).toString() + 'μs';
|
||||||
}
|
}
|
||||||
|
|
||||||
inputIsValid() {
|
inputIsValid() {
|
||||||
@ -193,12 +241,12 @@ class SourceEdit extends Component {
|
|||||||
<th align="left"> <label>Max samples per packet </label> </th>
|
<th align="left"> <label>Max samples per packet </label> </th>
|
||||||
<th align="left">
|
<th align="left">
|
||||||
<select value={this.state.maxSamplesPerPacket} onChange={this.onChangeMaxSamplesPerPacket}>
|
<select value={this.state.maxSamplesPerPacket} onChange={this.onChangeMaxSamplesPerPacket}>
|
||||||
<option value="6" disabled={this.checkMaxSamplesPerPacket(6) ? undefined : true}>6 - 125μs@48Khz</option>
|
<option value="6" disabled={this.checkMaxSamplesPerPacket(6) ? undefined : true}>6 - {this.getPacketDuration(6)}</option>
|
||||||
<option value="12" disabled={this.checkMaxSamplesPerPacket(12) ? undefined : true}>12 - 250μs@48Khz</option>
|
<option value="12" disabled={this.checkMaxSamplesPerPacket(12) ? undefined : true}>12 - {this.getPacketDuration(12)}</option>
|
||||||
<option value="16" disabled={this.checkMaxSamplesPerPacket(16) ? undefined : true}>16 - 333μs@48Khz</option>
|
<option value="16" disabled={this.checkMaxSamplesPerPacket(16) ? undefined : true}>16 - {this.getPacketDuration(16)}</option>
|
||||||
<option value="48" disabled={this.checkMaxSamplesPerPacket(48) ? undefined : true}>48 - 1ms@48Khz</option>
|
<option value="48" disabled={this.checkMaxSamplesPerPacket(48) ? undefined : true}>48 - {this.getPacketDuration(48)}</option>
|
||||||
<option value="96" disabled={this.checkMaxSamplesPerPacket(96) ? undefined : true}>96 - 2ms@48Khz</option>
|
<option value="96" disabled={this.checkMaxSamplesPerPacket(96) ? undefined : true}>96 - {this.getPacketDuration(96)}</option>
|
||||||
<option value="192" disabled={this.checkMaxSamplesPerPacket(192) ? undefined : true}>192 - 4ms@48Khz</option>
|
<option value="192" disabled={this.checkMaxSamplesPerPacket(192) ? undefined : true}>192 - {this.getPacketDuration(192)}</option>
|
||||||
</select>
|
</select>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -146,6 +146,7 @@ class Sources extends Component {
|
|||||||
infoIsOpen: false,
|
infoIsOpen: false,
|
||||||
removeIsOpen: false,
|
removeIsOpen: false,
|
||||||
ticFrameSizeAt1fs: '',
|
ticFrameSizeAt1fs: '',
|
||||||
|
sampleRate: '',
|
||||||
editTitle: ''
|
editTitle: ''
|
||||||
};
|
};
|
||||||
this.onInfoClick = this.onInfoClick.bind(this);
|
this.onInfoClick = this.onInfoClick.bind(this);
|
||||||
@ -171,7 +172,7 @@ class Sources extends Component {
|
|||||||
RestAPI.getConfig()
|
RestAPI.getConfig()
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(
|
.then(
|
||||||
data => this.setState( { isConfigLoading: false, ticFrameSizeAt1fs: data.tic_frame_size_at_1fs }))
|
data => this.setState( { isConfigLoading: false, ticFrameSizeAt1fs: data.tic_frame_size_at_1fs, sampleRate: data.sample_rate }))
|
||||||
.catch(err => this.setState({ isConfigLoading: false }));
|
.catch(err => this.setState({ isConfigLoading: false }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +282,7 @@ class Sources extends Component {
|
|||||||
editTitle={this.state.editTitle}
|
editTitle={this.state.editTitle}
|
||||||
isEdit={this.state.isEdit}
|
isEdit={this.state.isEdit}
|
||||||
ticFrameSizeAt1fs={this.state.ticFrameSizeAt1fs}
|
ticFrameSizeAt1fs={this.state.ticFrameSizeAt1fs}
|
||||||
|
sampleRate={this.state.sampleRate}
|
||||||
source={this.state.source} />
|
source={this.state.source} />
|
||||||
: undefined }
|
: undefined }
|
||||||
{ this.state.removeIsOpen ?
|
{ this.state.removeIsOpen ?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user