Compare commits

...

4 Commits

Author SHA1 Message Date
denny
dc3390460a Updates build to beta.6 2016-02-15 10:01:11 -05:00
denny
8db226cd7b Adds broadcasting of unknown P25 message types. If a P25 message passes
the NID crc check but uses an unrecognized data unit id, it will now be
broadcast as NID:UNKN, but allows for detection of new DUID types when
we have a large number of occurances of unknonwn duid types.
2016-02-15 10:00:29 -05:00
denny
b7a54598b1 Changes audio panel call timeout from 2 seconds to 1 second in order to
increase audio output cycle time.
2016-02-15 09:59:04 -05:00
denny
dd22397f75 Resolves issue with application memory growth and thread pool
saturation.

Each tunerchannelsource was sharing a thread pool and as the processing
load increased, the thread pool was not expanding and the processing
tasks were backing up, causing the buffers to grow with unprocessed
data.

Changed so that each tuner channel source is handed a thread pool to use
for processing incoming sample data.  Processing chain maintains the
thread pool and starts the channel source.  This allows traffic channels
to reuse the thread pool across multiple iterations.
2016-02-15 09:46:33 -05:00
20 changed files with 74 additions and 66 deletions

View File

@@ -7,7 +7,7 @@
<property name="major" value="0"/> <property name="major" value="0"/>
<property name="minor" value="2"/> <property name="minor" value="2"/>
<property name="patch" value="0"/> <property name="patch" value="0"/>
<property name="release" value="beta.5"/> <property name="release" value="beta.6"/>
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}-${release}"/> <property name="filename" value="sdrtrunk_${major}.${minor}.${patch}-${release}"/>
<!-- Build properties --> <!-- Build properties -->

View File

@@ -50,7 +50,7 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
{ {
private static final Logger mLog = LoggerFactory.getLogger( AudioManager.class ); private static final Logger mLog = LoggerFactory.getLogger( AudioManager.class );
public static final int AUDIO_TIMEOUT = 2000; //2 seconds public static final int AUDIO_TIMEOUT = 1000; //1 second
public static final String AUDIO_CHANNELS_PROPERTY = "audio.manager.channels"; public static final String AUDIO_CHANNELS_PROPERTY = "audio.manager.channels";
public static final String AUDIO_MIXER_PROPERTY = "audio.manager.mixer"; public static final String AUDIO_MIXER_PROPERTY = "audio.manager.mixer";
@@ -431,7 +431,6 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
*/ */
public class AudioOutputConnection implements Listener<AudioEvent> public class AudioOutputConnection implements Listener<AudioEvent>
{ {
private static final long CALL_END_DELAY = 2000; //2 seconds
private static final int DISCONNECTED = -1; private static final int DISCONNECTED = -1;
private AudioOutput mAudioOutput; private AudioOutput mAudioOutput;
@@ -546,7 +545,7 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
public boolean isInactive() public boolean isInactive()
{ {
return mLastActivity != Long.MAX_VALUE && return mLastActivity != Long.MAX_VALUE &&
mLastActivity + CALL_END_DELAY < System.currentTimeMillis(); mLastActivity + AUDIO_TIMEOUT < System.currentTimeMillis();
} }
public int getPriority() public int getPriority()

View File

@@ -297,6 +297,9 @@ public class Channel extends Configuration
/* Broadcast channel deleted event */ /* Broadcast channel deleted event */
fireChannelEvent( Event.CHANNEL_DELETED ); fireChannelEvent( Event.CHANNEL_DELETED );
mProcessingChain.dispose();
mProcessingChain = null;
} }
/** /**
@@ -809,7 +812,7 @@ public class Channel extends Configuration
{ {
if( mProcessingChain == null ) if( mProcessingChain == null )
{ {
mProcessingChain = new ProcessingChain(); mProcessingChain = new ProcessingChain( getName() );
/* Get the optional alias list for the decode modules to use */ /* Get the optional alias list for the decode modules to use */
AliasList aliasList = mResourceManager.getPlaylistManager() AliasList aliasList = mResourceManager.getPlaylistManager()

View File

@@ -12,8 +12,9 @@ import source.Source;
public class InstrumentableProcessingChain extends ProcessingChain implements Instrumentable public class InstrumentableProcessingChain extends ProcessingChain implements Instrumentable
{ {
public InstrumentableProcessingChain() public InstrumentableProcessingChain( String name )
{ {
super( name );
} }
public void setSource( Source source ) throws IllegalStateException public void setSource( Source source ) throws IllegalStateException

View File

@@ -99,7 +99,7 @@ public class DecoderViewFrame extends JInternalFrame
mDecodeConfig = decodeConfig; mDecodeConfig = decodeConfig;
mProcessingChain = new InstrumentableProcessingChain(); mProcessingChain = new InstrumentableProcessingChain( "instrumented" );
List<Module> modules = DecoderFactory List<Module> modules = DecoderFactory
.getModules( ChannelType.STANDARD, .getModules( ChannelType.STANDARD,

View File

@@ -19,7 +19,8 @@ package module;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import message.IMessageListener; import message.IMessageListener;
@@ -61,7 +62,7 @@ import audio.metadata.Metadata;
import audio.squelch.ISquelchStateListener; import audio.squelch.ISquelchStateListener;
import audio.squelch.ISquelchStateProvider; import audio.squelch.ISquelchStateProvider;
import audio.squelch.SquelchState; import audio.squelch.SquelchState;
import controller.ThreadPoolManager; import controller.NamingThreadFactory;
import controller.channel.ChannelEvent; import controller.channel.ChannelEvent;
import controller.channel.IChannelEventListener; import controller.channel.IChannelEventListener;
import controller.channel.IChannelEventProvider; import controller.channel.IChannelEventProvider;
@@ -99,15 +100,17 @@ public class ProcessingChain implements IChannelEventListener
private Broadcaster<RealBuffer> mRealBufferBroadcaster = new Broadcaster<>(); private Broadcaster<RealBuffer> mRealBufferBroadcaster = new Broadcaster<>();
private Broadcaster<SquelchState> mSquelchStateBroadcaster = new Broadcaster<>(); private Broadcaster<SquelchState> mSquelchStateBroadcaster = new Broadcaster<>();
// private ThreadPoolManager mThreadPoolManager; private ScheduledExecutorService mScheduledExecutorService;
private AtomicBoolean mRunning = new AtomicBoolean(); private AtomicBoolean mRunning = new AtomicBoolean();
protected Source mSource; protected Source mSource;
private List<Module> mModules = new ArrayList<>(); private List<Module> mModules = new ArrayList<>();
private IFrequencyCorrectionController mFrequencyCorrectionController; private IFrequencyCorrectionController mFrequencyCorrectionController;
public ProcessingChain() public ProcessingChain( String name )
{ {
mScheduledExecutorService = Executors.newScheduledThreadPool( 1,
new NamingThreadFactory( "channel " + name ) );
} }
public void dispose() public void dispose()
@@ -121,6 +124,9 @@ public class ProcessingChain implements IChannelEventListener
mModules.clear(); mModules.clear();
mScheduledExecutorService.shutdownNow();
mScheduledExecutorService = null;
mFrequencyCorrectionController = null; mFrequencyCorrectionController = null;
mAudioPacketBroadcaster.dispose(); mAudioPacketBroadcaster.dispose();
@@ -432,9 +438,11 @@ public class ProcessingChain implements IChannelEventListener
* of the decoder state's */ * of the decoder state's */
if( mSource instanceof TunerChannelSource ) if( mSource instanceof TunerChannelSource )
{ {
TunerChannelSource tunerChannelSource = (TunerChannelSource)mSource;
try try
{ {
long frequency = ((TunerChannelSource)mSource).getFrequency(); long frequency = tunerChannelSource.getFrequency();
mDecoderStateEventBroadcaster.broadcast( mDecoderStateEventBroadcaster.broadcast(
new DecoderStateEvent( this, Event.SOURCE_FREQUENCY, new DecoderStateEvent( this, Event.SOURCE_FREQUENCY,
@@ -444,6 +452,8 @@ public class ProcessingChain implements IChannelEventListener
{ {
mLog.error( "Error getting frequency from tuner channel source", e ); mLog.error( "Error getting frequency from tuner channel source", e );
} }
tunerChannelSource.start( mScheduledExecutorService );
} }
} }
else else

View File

@@ -289,6 +289,7 @@ public class P25MessageFramer implements Listener<Dibit>
else else
{ {
mComplete = true; mComplete = true;
dispatch( new P25Message( mMessage.copy(), duid, mAliasList ) );
} }
} }
else else

View File

@@ -91,6 +91,15 @@ public class TrafficChannelManager extends Module
@Override @Override
public void dispose() public void dispose()
{ {
mLog.debug( "dispose() on traffic channel manager" );
for( Channel trafficChannel: mTrafficChannelPool )
{
trafficChannel.setEnabled( false );
trafficChannel.dispose();
}
mTrafficChannelPool.clear();
mCallEventListener = null; mCallEventListener = null;
mResourceManager = null; mResourceManager = null;
mDecodeConfiguration = null; mDecodeConfiguration = null;

View File

@@ -63,9 +63,8 @@ public class Recording implements Comparable<Recording>,
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, throws RejectedExecutionException, SourceException
SourceException
{ {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;

View File

@@ -71,9 +71,7 @@ public class RecordingSourceManager
if( recording != null ) if( recording != null )
{ {
retVal = recording.getChannel( retVal = recording.getChannel( tunerChannel );
mResourceManager.getThreadPoolManager(),
tunerChannel );
} }
else else
{ {

View File

@@ -30,10 +30,9 @@ import sample.complex.ComplexBuffer;
import source.SourceException; import source.SourceException;
import source.tuner.frequency.FrequencyChangeBroadcaster; import source.tuner.frequency.FrequencyChangeBroadcaster;
import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent;
import source.tuner.frequency.FrequencyChangeListener;
import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeEvent.Event;
import source.tuner.frequency.FrequencyChangeListener;
import controller.ResourceManager; import controller.ResourceManager;
import controller.ThreadPoolManager;
/** /**
* Tuner - provides tuner channel sources, representing a channel frequency * Tuner - provides tuner channel sources, representing a channel frequency
@@ -147,8 +146,8 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
* *
* @return - source for 48k sample rate * @return - source for 48k sample rate
*/ */
public abstract TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public abstract TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException; throws RejectedExecutionException, SourceException;
/** /**
* Releases the tuned channel resources * Releases the tuned channel resources

View File

@@ -14,8 +14,8 @@ public interface TunerChannelProvider
* *
* @return - source for 48k sample rate * @return - source for 48k sample rate
*/ */
public abstract TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public abstract TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException; throws RejectedExecutionException, SourceException;
/** /**
* Releases the tuned channel resources * Releases the tuned channel resources

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,8 +38,6 @@ import source.SourceException;
import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent;
import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeEvent.Event;
import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeListener;
import controller.ThreadPoolManager;
import controller.ThreadPoolManager.ThreadType;
import dsp.filter.FilterFactory; import dsp.filter.FilterFactory;
import dsp.filter.Window.WindowType; import dsp.filter.Window.WindowType;
import dsp.filter.cic.ComplexPrimeCICDecimate; import dsp.filter.cic.ComplexPrimeCICDecimate;
@@ -62,7 +61,6 @@ public class TunerChannelSource extends ComplexSource
private ComplexPrimeCICDecimate mDecimationFilter; private ComplexPrimeCICDecimate mDecimationFilter;
private Listener<ComplexBuffer> mListener; private Listener<ComplexBuffer> mListener;
private FrequencyChangeListener mFrequencyChangeListener; private FrequencyChangeListener mFrequencyChangeListener;
private ThreadPoolManager mThreadPoolManager;
private ScheduledFuture<?> mTaskHandle; private ScheduledFuture<?> mTaskHandle;
private long mTunerFrequency = 0; private long mTunerFrequency = 0;
@@ -71,15 +69,11 @@ public class TunerChannelSource extends ComplexSource
private DecimationProcessor mDecimationProcessor = new DecimationProcessor(); private DecimationProcessor mDecimationProcessor = new DecimationProcessor();
public TunerChannelSource( ThreadPoolManager threadPoolManager, public TunerChannelSource( Tuner tuner, TunerChannel tunerChannel )
Tuner tuner, throws RejectedExecutionException, SourceException
TunerChannel tunerChannel )
throws RejectedExecutionException, SourceException
{ {
super( "Tuner Channel Source" ); super( "Tuner Channel Source" );
mThreadPoolManager = threadPoolManager;
mTuner = tuner; mTuner = tuner;
mTuner.addListener( (FrequencyChangeListener)this ); mTuner.addListener( (FrequencyChangeListener)this );
@@ -95,14 +89,17 @@ public class TunerChannelSource extends ComplexSource
/* Fire a sample rate change event to setup the decimation chain */ /* Fire a sample rate change event to setup the decimation chain */
frequencyChanged( new FrequencyChangeEvent( frequencyChanged( new FrequencyChangeEvent(
Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) ); Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) );
}
/* Schedule the decimation task to run every 20 ms (50 iterations/second) */ public void start( ScheduledExecutorService scheduledExecutorService )
mTaskHandle = mThreadPoolManager.scheduleFixedRate( ThreadType.DECIMATION, {
mDecimationProcessor, 20, TimeUnit.MILLISECONDS ); /* Schedule the decimation task to run every 10 ms (100 iterations/second) */
mTaskHandle = scheduledExecutorService.scheduleAtFixedRate(
mDecimationProcessor, 0, 10, TimeUnit.MILLISECONDS );
/* Finally, register to receive samples from the tuner */ /* Finally, register to receive samples from the tuner */
mTuner.addListener( (Listener<ComplexBuffer>)this ); mTuner.addListener( (Listener<ComplexBuffer>)this );
} }
@Override @Override
public void dispose() public void dispose()
@@ -129,12 +126,10 @@ public class TunerChannelSource extends ComplexSource
{ {
if( mTaskHandle != null ) if( mTaskHandle != null )
{ {
mThreadPoolManager.cancel( mTaskHandle ); mTaskHandle.cancel( true );
mThreadPoolManager = null;
mTaskHandle = null; mTaskHandle = null;
} }
mBuffer.clear(); mBuffer.clear();
mBuffer = null; mBuffer = null;
@@ -290,7 +285,7 @@ public class TunerChannelSource extends ComplexSource
{ {
if( mBuffer != null ) if( mBuffer != null )
{ {
mBuffer.drainTo( mSampleBuffers, 4 ); mBuffer.drainTo( mSampleBuffers, 8 );
for( Buffer buffer: mSampleBuffers ) for( Buffer buffer: mSampleBuffers )
{ {

View File

@@ -194,8 +194,8 @@ public abstract class TunerController implements Tunable
* *
* @throws RejectedExecutionException if the decimation processor has an error * @throws RejectedExecutionException if the decimation processor has an error
*/ */
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( Tuner tuner, TunerChannel channel )
Tuner tuner, TunerChannel channel ) throws RejectedExecutionException throws RejectedExecutionException
{ {
TunerChannelSource source = null; TunerChannelSource source = null;
@@ -210,8 +210,7 @@ public abstract class TunerController implements Tunable
updateLOFrequency(); updateLOFrequency();
} }
source = new TunerChannelSource( threadPoolManager, source = new TunerChannelSource( tuner, channel );
tuner, channel );
} }
catch( SourceException se ) catch( SourceException se )
{ {

View File

@@ -100,8 +100,7 @@ public class TunerManager
try try
{ {
retVal = tuner.getChannel( retVal = tuner.getChannel( tunerChannel );
mResourceManager.getThreadPoolManager(), tunerChannel );
} }
catch ( RejectedExecutionException ree ) catch ( RejectedExecutionException ree )
{ {

View File

@@ -128,8 +128,8 @@ public class AirspyTuner extends Tuner
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException throws RejectedExecutionException, SourceException
{ {
//TODO: this channel has a decimated sample rate of: //TODO: this channel has a decimated sample rate of:
// 10.0 MSps = 10,000,000 / 208 = 48076.923 // 10.0 MSps = 10,000,000 / 208 = 48076.923
@@ -138,7 +138,7 @@ public class AirspyTuner extends Tuner
//Consider implementing a fractional resampler to get a correct 48 kHz //Consider implementing a fractional resampler to get a correct 48 kHz
//output sample rate //output sample rate
return mController.getChannel( threadPoolManager, this, channel ); return mController.getChannel( this, channel );
} }
@Override @Override

View File

@@ -99,8 +99,8 @@ public class B100Tuner extends Tuner
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException throws RejectedExecutionException, SourceException
{ {
//TODO: pass this call to the tuner controller //TODO: pass this call to the tuner controller
return null; return null;

View File

@@ -112,11 +112,10 @@ public class FCDTuner extends MixerTuner
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel tunerChannel )
TunerChannel tunerChannel ) throws RejectedExecutionException, throws RejectedExecutionException, SourceException
SourceException
{ {
return mController.getChannel( threadPoolManager, this, tunerChannel ); return mController.getChannel( this, tunerChannel );
} }
/** /**

View File

@@ -106,10 +106,10 @@ public class HackRFTuner extends Tuner
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException throws RejectedExecutionException, SourceException
{ {
return mController.getChannel( threadPoolManager, this, channel ); return mController.getChannel( this, channel );
} }
@Override @Override

View File

@@ -37,7 +37,6 @@ import source.tuner.TunerType;
import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeListener;
import source.tuner.rtl.RTL2832TunerController.SampleRate; import source.tuner.rtl.RTL2832TunerController.SampleRate;
import controller.ResourceManager; import controller.ResourceManager;
import controller.ThreadPoolManager;
public class RTL2832Tuner extends Tuner public class RTL2832Tuner extends Tuner
{ {
@@ -148,16 +147,14 @@ public class RTL2832Tuner extends Tuner
} }
@Override @Override
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager, public TunerChannelSource getChannel( TunerChannel channel )
TunerChannel channel ) throws RejectedExecutionException, SourceException
throws RejectedExecutionException,
SourceException
{ {
TunerChannelSource source = null; TunerChannelSource source = null;
try try
{ {
source = mController.getChannel( threadPoolManager, this, channel ); source = mController.getChannel( this, channel );
} }
catch( Exception e ) catch( Exception e )
{ {