
org.jitsi.impl.neomedia.conference.InDataSourceDesc Maven / Gradle / Ivy
Show all versions of libjitsi Show documentation
/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.impl.neomedia.conference;
import java.io.*;
import javax.media.*;
import javax.media.protocol.*;
import org.jitsi.impl.neomedia.*;
import org.jitsi.impl.neomedia.protocol.*;
import org.jitsi.utils.logging.*;
/**
* Describes additional information about a specific input DataSource
* of an AudioMixer so that the AudioMixer can, for example,
* quickly discover the output AudioMixingPushBufferDataSource in the
* mix of which the contribution of the DataSource is to not be
* included.
*
* Private to AudioMixer and AudioMixerPushBufferStream but
* extracted into its own file for the sake of clarity.
*
* @author Lyubomir Marinov
*/
class InDataSourceDesc
{
/**
* The constant which represents an empty array with SourceStream
* element type. Explicitly defined in order to avoid unnecessary allocations.
*/
private static final SourceStream[] EMPTY_STREAMS = new SourceStream[0];
/**
* The Logger used by the InDataSourceDesc class and
* its instances for logging output.
*/
private static final Logger logger
= Logger.getLogger(InDataSourceDesc.class);
/**
* The indicator which determines whether the effective input
* DataSource described by this instance is currently connected.
*/
private boolean connected;
/**
* The Thread which currently executes {@link DataSource#connect()}
* on the effective input DataSource described by this instance.
*/
private Thread connectThread;
/**
* The DataSource for which additional information is described by
* this instance.
*/
public final DataSource inDataSource;
/**
* The AudioMixingPushBufferDataSource in which the mix
* contributions of {@link #inDataSource} are to not be included.
*/
public final AudioMixingPushBufferDataSource outDataSource;
/**
* The DataSource, if any, which transcodes the tracks of
* {@link #inDataSource} in the output Format of the associated
* AudioMixer.
*/
private DataSource transcodingDataSource;
/**
* Initializes a new InDataSourceDesc instance which is to
* describe additional information about a specific input
* DataSource of an AudioMixer. Associates the specified
* DataSource with the AudioMixingPushBufferDataSource in
* which the mix contributions of the specified input DataSource
* are to not be included.
*
* @param inDataSource a DataSource for which additional
* information is to be described by the new instance
* @param outDataSource the AudioMixingPushBufferDataSource in
* which the mix contributions of inDataSource are to not be
* included
*/
public InDataSourceDesc(
DataSource inDataSource,
AudioMixingPushBufferDataSource outDataSource)
{
this.inDataSource = inDataSource;
this.outDataSource = outDataSource;
}
/**
* Connects the effective input DataSource described by this
* instance upon request from a specific AudioMixer. If the
* effective input DataSource is to be asynchronously connected,
* the completion of the connect procedure will be reported to the specified
* AudioMixer by calling its
* {@link AudioMixer#connected(InDataSourceDesc)}.
*
* @param audioMixer the AudioMixer requesting the effective input
* DataSource described by this instance to be connected
* @throws IOException if anything wrong happens while connecting the
* effective input DataSource described by this instance
*/
synchronized void connect(final AudioMixer audioMixer)
throws IOException
{
final DataSource effectiveInDataSource
= (transcodingDataSource == null)
? inDataSource
: transcodingDataSource;
if (effectiveInDataSource instanceof TranscodingDataSource)
{
if (connectThread == null)
{
connectThread = new Thread()
{
@Override
public void run()
{
try
{
audioMixer.connect(
effectiveInDataSource,
inDataSource);
synchronized (InDataSourceDesc.this)
{
connected = true;
}
audioMixer.connected(InDataSourceDesc.this);
}
catch (IOException ioex)
{
logger.error(
"Failed to connect to inDataSource "
+ MediaStreamImpl.toString(
inDataSource),
ioex);
}
finally
{
synchronized (InDataSourceDesc.this)
{
if (connectThread == Thread.currentThread())
connectThread = null;
}
}
}
};
connectThread.setDaemon(true);
connectThread.start();
}
}
else
{
audioMixer.connect(effectiveInDataSource, inDataSource);
connected = true;
}
}
/**
* Creates a DataSource which attempts to transcode the tracks of
* the input DataSource described by this instance into a specific
* output Format.
*
* @param outFormat the Format in which the tracks of the input
* DataSource described by this instance are to be transcoded
* @return true if a new transcoding DataSource has been
* created for the input DataSource described by this instance;
* otherwise, false
*/
synchronized boolean createTranscodingDataSource(Format outFormat)
{
if (transcodingDataSource == null)
{
setTranscodingDataSource(
new TranscodingDataSource(inDataSource, outFormat));
return true;
}
else
return false;
}
/**
* Disconnects the effective input DataSource described by this
* instance if it is already connected.
*/
synchronized void disconnect()
{
if (connected)
{
getEffectiveInDataSource().disconnect();
connected = false;
}
}
/**
* Gets the control available for the effective input DataSource
* described by this instance with a specific type.
*
* @param controlType a String value which specifies the type of
* the control to be retrieved
* @return an Object which represents the control available for the
* effective input DataSource described by this instance with the
* specified controlType if such a control exists; otherwise,
* null
*/
public synchronized Object getControl(String controlType)
{
DataSource effectiveInDataSource = getEffectiveInDataSource();
return
(effectiveInDataSource == null)
? null
: effectiveInDataSource.getControl(controlType);
}
/**
* Gets the actual DataSource from which the associated
* AudioMixer directly reads in order to retrieve the mix
* contribution of the DataSource described by this instance.
*
* @return the actual DataSource from which the associated
* AudioMixer directly reads in order to retrieve the mix
* contribution of the DataSource described by this instance
*/
public synchronized DataSource getEffectiveInDataSource()
{
return
(transcodingDataSource == null)
? inDataSource
: (connected ? transcodingDataSource : null);
}
/**
* Returns this instance's inDataSource
*
* @return this instance's inDataSource
*/
public DataSource getInDataSource()
{
return inDataSource;
}
/**
* Gets the SourceStreams of the effective input
* DataSource described by this instance.
*
* @return an array of the SourceStreams of the effective input
* DataSource described by this instance
*/
public synchronized SourceStream[] getStreams()
{
if (!connected)
return EMPTY_STREAMS;
DataSource inDataSource = getEffectiveInDataSource();
if (inDataSource instanceof PushBufferDataSource)
return ((PushBufferDataSource) inDataSource).getStreams();
else if (inDataSource instanceof PullBufferDataSource)
return ((PullBufferDataSource) inDataSource).getStreams();
else if (inDataSource instanceof TranscodingDataSource)
return ((TranscodingDataSource) inDataSource).getStreams();
else
return null;
}
/**
* Returns the TranscodingDataSource object used in this instance.
*
* @return the TranscodingDataSource object used in this instance.
*/
public TranscodingDataSource getTranscodingDataSource()
{
return (TranscodingDataSource) transcodingDataSource;
}
/**
* Sets the DataSource, if any, which transcodes the tracks of the
* input DataSource described by this instance in the output
* Format of the associated AudioMixer.
*
* @param transcodingDataSource the DataSource which transcodes
* the tracks of the input DataSource described by this instance in
* the output Format of the associated AudioMixer
*/
private synchronized void setTranscodingDataSource(
DataSource transcodingDataSource)
{
this.transcodingDataSource = transcodingDataSource;
connected = false;
}
/**
* Starts the effective input DataSource described by this instance
* if it is connected.
*
* @throws IOException if starting the effective input DataSource
* described by this instance fails
*/
synchronized void start()
throws IOException
{
if (connected)
getEffectiveInDataSource().start();
}
/**
* Stops the effective input DataSource described by this instance
* if it is connected.
*
* @throws IOException if stopping the effective input DataSource
* described by this instance fails
*/
synchronized void stop()
throws IOException
{
if (connected)
getEffectiveInDataSource().stop();
}
}