Browse Source

Add fast network mode, allowing zero latency transmission when possible

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2760 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.90
moret 17 years ago
parent
commit
275195f153
4 changed files with 50 additions and 51 deletions
  1. +14
    -25
      common/JackNetDriver.cpp
  2. +33
    -23
      common/JackNetManager.cpp
  3. +2
    -2
      common/JackNetTool.cpp
  4. +1
    -1
      common/JackNetTool.h

+ 14
- 25
common/JackNetDriver.cpp View File

@@ -54,7 +54,7 @@ namespace Jack

JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
const char* net_name, uint transport_sync, char network_master_mode )
const char* net_name, uint transport_sync, char network_mode )
: JackAudioDriver ( name, alias, engine, table ), fSocket ( ip, port )
{
jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port );
@@ -67,7 +67,7 @@ namespace Jack
strcpy ( fParams.fName, net_name );
fSocket.GetName ( fParams.fSlaveNetName );
fParams.fTransportSync = transport_sync;
fParams.fNetworkMasterMode = network_master_mode;
fParams.fNetworkMode = network_mode;
#ifdef JACK_MONITOR
fMonitor = NULL;
fMeasure = NULL;
@@ -348,7 +348,7 @@ namespace Jack
string plot_name = string ( fParams.fName );
plot_name += string ( "_slave" );
plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
plot_name += ( fParams.fNetworkMasterMode == 'f' ) ? string ( "_fast-network" ) : string ( "_slow-network" );
plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast-network" ) : string ( "" );
fMonitor = new JackGnuPlotMonitor<float> ( JackNetDriver::fMeasureCnt, JackNetDriver::fMeasurePoints, plot_name );
fMeasure = new float[JackNetDriver::fMeasurePoints];
fMonitor->SetPlotFile ( JackNetDriver::fMonitorPlotOptions, JackNetDriver::fMonitorPlotOptionsCnt,
@@ -400,7 +400,7 @@ namespace Jack
}
port = fGraphManager->GetPort ( port_id );
port->SetAlias ( alias );
port->SetLatency ( fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
fPlaybackPortList[audio_port_index] = port_id;
jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
}
@@ -434,7 +434,7 @@ namespace Jack
return -1;
}
port = fGraphManager->GetPort ( port_id );
port->SetLatency ( fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
fMidiPlaybackPortList[midi_port_index] = port_id;
jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
}
@@ -614,7 +614,7 @@ namespace Jack
if ( fEngineControl->fSyncMode )
fTxHeader.fCycle = fRxHeader.fCycle;
else
fTxHeader.fCycle++;
fTxHeader.fCycle = fRxHeader.fCycle - 1;
fTxHeader.fSubCycle = 0;
fTxHeader.fIsLastPckt = 'n';

@@ -777,10 +777,10 @@ namespace Jack

i++;
strcpy ( desc->params[i].name, "network_mode" );
desc->params[i].character = 'N';
desc->params[i].type = JackDriverParamChar;
desc->params[i].value.ui = 's';
strcpy ( desc->params[i].short_desc, "Slow network add 1 cycle latency" );
desc->params[i].character = 'f';
desc->params[i].type = JackDriverParamString;
strcpy ( desc->params[i].value.str, "" );
strcpy ( desc->params[i].short_desc, "Fast mode allows a zero latency transmission." );
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

return desc;
@@ -806,7 +806,7 @@ namespace Jack
int midi_input_ports = 0;
int midi_output_ports = 0;
bool monitor = false;
char network_master_mode = 's';
char network_mode = 'n';

const JSList* node;
const jack_driver_param_t* param;
@@ -842,26 +842,15 @@ namespace Jack
case 't' :
transport_sync = param->value.ui;
break;
case 'N' :
switch ( param->value.ui )
{
case 's' :
network_master_mode = 's';
break;
case 'f' :
network_master_mode = 'f';
break;
default :
network_master_mode = 's';
break;
}
case 'f' :
network_mode = 'f';
break;
}
}

Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
midi_input_ports, midi_output_ports, name, transport_sync, network_master_mode ) );
midi_input_ports, midi_output_ports, name, transport_sync, network_mode ) );
if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
return driver;


+ 33
- 23
common/JackNetManager.cpp View File

@@ -125,7 +125,7 @@ namespace Jack
string plot_name = string ( fParams.fName );
plot_name += string ( "_master" );
plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
plot_name += ( fParams.fNetworkMasterMode == 'f' ) ? string ( "_fast-network" ) : string ( "_slow-network" );
plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast-network" ) : string ( "" );
fMonitor = new JackGnuPlotMonitor<float> ( JackNetMaster::fMeasureCnt, JackNetMaster::fMeasurePoints, plot_name );
fMeasure = new float[JackNetMaster::fMeasurePoints];
fMonitor->SetPlotFile ( JackNetMaster::fMonitorPlotOptions, JackNetMaster::fMonitorPlotOptionsCnt,
@@ -253,7 +253,7 @@ namespace Jack
sprintf ( name, "from_slave_%d", i+1 );
if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL )
goto fail;
jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fNetworkMode == 'f' ) ? 0 : port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
}
//midi
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
@@ -270,7 +270,7 @@ namespace Jack
sprintf ( name, "midi_from_slave_%d", i+1 );
if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL )
goto fail;
jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fNetworkMode == 'f' ) ? 0 : port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
}

fRunning = true;
@@ -494,28 +494,34 @@ namespace Jack
#endif

//receive --------------------------------------------------------------------------------------------------------------------
//sync
//sync : how much data is available ?
rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
//wait here for sync, switch network mode :
// -fast : this recv will wait for a long time (90% of cycle duration)
// -slow : just wait for a short time, then return, the data will be available at the next cycle
if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
return rx_bytes;

//slow mode :
if ( fParams.fNetworkMasterMode == 's' )
switch ( fParams.fNetworkMode )
{
if ( rx_head->fCycle == fTxHeader.fCycle )
return 0;
else
rx_bytes = Recv ( rx_head->fPacketSize, 0);
}

//fast mode :
if ( fParams.fNetworkMasterMode == 'f' )
{
if ( fTxHeader.fCycle - fRxHeader.fCycle )
jack_log ( "%s : %s = %d", fParams.fName, ( fParams.fSlaveSyncMode ) ? "SyncCycleOffset" : "AsyncCycleOffset", fTxHeader.fCycle - fRxHeader.fCycle );
case 'n' : //normal mode
//normal use of the network : allow to use full bandwith
// - extra latency is set to one cycle, what corresponds to the time needed to receive streams using full network bandwith
// - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
// - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
if ( rx_head->fCycle == fTxHeader.fCycle )
return 0;
else
{
rx_bytes = Recv ( rx_head->fPacketSize, 0 );
}
break;
case 'f' : //fast mode
//fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
// - packets can be quickly received, quickly is here relative to the cycle duration
// - here, receive data, we can't keep it queued on the rx buffer,
// - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
rx_bytes = Recv ( rx_head->fPacketSize, 0 );
if ( rx_head->fCycle != fTxHeader.fCycle )
jack_error ( "%s, can't stay in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fTxHeader.fCycle - rx_head->fCycle );
break;
}

#ifdef JACK_MONITOR
@@ -526,16 +532,20 @@ namespace Jack
{
do
{
//how much data is queued on the rx buffer ?
rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
if ( rx_bytes == SOCKET_ERROR )
return rx_bytes;
if ( ++jumpcnt == fNSubProcess )
//if no data,
if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
{
jack_error ( "No data from %s...", fParams.fName );
jumpcnt = 0;
}
//else if data is valid,
if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) )
{
//read data
switch ( rx_head->fDataType )
{
case 'm': //midi
@@ -558,8 +568,8 @@ namespace Jack
jumpcnt = 0;
break;
case 's': //sync
Recv ( rx_head->fPacketSize, 0 );
return 0;
if ( rx_head->fCycle == fTxHeader.fCycle )
return 0;
}
}
}


+ 2
- 2
common/JackNetTool.cpp View File

@@ -218,7 +218,7 @@ namespace Jack
jack_info ( "Packet per period : %u", params->fPeriodSize / params->fFramesPerPacket );
jack_info ( "Bitdepth : %s", bitdepth );
jack_info ( "Slave mode : %s", ( params->fSlaveSyncMode ) ? "sync" : "async" );
jack_info ( "Network mode : %s", ( params->fNetworkMasterMode == 'f' ) ? "fast" : "slow" );
jack_info ( "Network mode : %s", ( params->fNetworkMode == 'f' ) ? "fast" : "normal" );
jack_info ( "****************************************************" );
}

@@ -375,7 +375,7 @@ namespace Jack
{
float time;
//fast mode, wait for the entire cycle duration
if ( params->fNetworkMasterMode == 'f' )
if ( params->fNetworkMode == 'f' )
time = 900000.f * ( static_cast<float> ( params->fPeriodSize ) / static_cast<float> ( params->fSampleRate ) );
//slow mode, just try recv during two subcycle audio packets
else


+ 1
- 1
common/JackNetTool.h View File

@@ -73,7 +73,7 @@ namespace Jack
uint32_t fFramesPerPacket; //complete frames per packet
uint32_t fBitdepth; //samples bitdepth (unused)
uint32_t fSlaveSyncMode; //is the slave in sync mode ?
char fNetworkMasterMode; //fast or slow mode
char fNetworkMode; //fast or slow mode
};

//net status **********************************************************************************


Loading…
Cancel
Save