diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferCaptureDevice.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferCaptureDevice.java
new file mode 100644
index 000000000..c1de5f249
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferCaptureDevice.java
@@ -0,0 +1,624 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.media.*;
+import javax.media.control.*;
+import javax.media.protocol.*;
+
+import net.java.sip.communicator.impl.neomedia.control.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * Provides a base implementation of PushBufferDataSource and
+ * CaptureDevice in order to facilitate implementers by taking care of
+ * boilerplate in the most common cases.
+ *
+ * @author Lubomir Marinov
+ */
+public abstract class AbstractPushBufferCaptureDevice
+ extends PushBufferDataSource
+ implements CaptureDevice
+{
+
+ /**
+ * The Logger used by the AbstractPushBufferCaptureDevice
+ * class and its instances for logging output.
+ */
+ private static final Logger logger
+ = Logger.getLogger(AbstractPushBufferCaptureDevice.class);
+
+ /**
+ * The value of the formatControls property of
+ * AbstractPushBufferCaptureDevice which represents an empty array
+ * of FormatControls. Explicitly defined in order to reduce
+ * unnecessary allocations.
+ */
+ protected static final FormatControl[] EMPTY_FORMAT_CONTROLS
+ = new FormatControl[0];
+
+ /**
+ * The value of the streams property of
+ * AbstractPushBufferCaptureDevice which represents an empty array
+ * of PushBufferStreams. Explicitly defined in order to reduce
+ * unnecessary allocations.
+ */
+ protected static final PushBufferStream[] EMPTY_STREAMS
+ = new PushBufferStream[0];
+
+ /**
+ * The indicator which determines whether a connection to the media source
+ * specified by the MediaLocator of this DataSource has
+ * been opened.
+ */
+ private boolean connected = false;
+
+ /**
+ * The array of FormatControl instances each one of which can be
+ * used before {@link #connect()} to get and set the capture Format
+ * of each one of the capture streams.
+ */
+ private FormatControl[] formatControls;
+
+ /**
+ * The indicator which determines whether the transfer of media data from
+ * this DataSource has been started.
+ */
+ private boolean started = false;
+
+ /**
+ * The PushBufferStreams through which this
+ * PushBufferDataSource gives access to its media data.
+ */
+ private AbstractPushBufferStream[] streams;
+
+ /**
+ * Initializes a new AbstractPushBufferCaptureDevice instance.
+ */
+ protected AbstractPushBufferCaptureDevice()
+ {
+ }
+
+ /**
+ * Initializes a new AbstractPushBufferCaptureDevice instance from
+ * a specific MediaLocator.
+ *
+ * @param locator the MediaLocator to create the new instance from
+ */
+ protected AbstractPushBufferCaptureDevice(MediaLocator locator)
+ {
+ setLocator(locator);
+ }
+
+ /**
+ * Determines whether it is allowed to set the format of a specific
+ * FormatControl of the PushBufferStream of this
+ * PushBufferDataSource with a specific index to a specific
+ * Format. The AbstractPushBufferCaptureDevice
+ * implementation always returns false.
+ *
+ * @param format the Format which is to be set
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * in the list of streams of this PushBufferDataSource which is to
+ * have its Format set
+ * @param formatControl the FormatControl of the stream through
+ * which the set request is received
+ * @return true if the specified Format is to be set as
+ * the format of formatControl; otherwise, false
+ */
+ protected boolean canSetFormat(
+ Format format,
+ int streamIndex,
+ FormatControl formatControl)
+ {
+ return false;
+ }
+
+ /**
+ * Opens a connection to the media source specified by the
+ * MediaLocator of this DataSource.
+ *
+ * @throws IOException if anything goes wrong while opening the connection
+ * to the media source specified by the MediaLocator of this
+ * DataSource
+ */
+ public synchronized void connect()
+ throws IOException
+ {
+ if (!connected)
+ {
+ doConnect();
+ connected = true;
+ }
+ }
+
+ /**
+ * Creates a new FormatControl instance which is to be associated
+ * with a PushBufferStream at a specific zero-based index in the
+ * list of streams of this PushBufferDataSource. As the
+ * FormatControls of a PushBufferDataSource can be
+ * requested before {@link #connect()}, its PushBufferStreams may
+ * not exist at the time of the request for the creation of the
+ * FormatControl.
+ *
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * in the list of streams of this PushBufferDataSource which is to
+ * be associated with the new FormatControl instance
+ * @return a new FormatControl instance which is to be associated
+ * with a PushBufferStream at the specified streamIndex in
+ * the list of streams of this PushBufferDataSource
+ */
+ protected FormatControl createFormatControl(final int streamIndex)
+ {
+ return
+ new AbstractFormatControl()
+ {
+ /**
+ * The Format of this FormatControl and,
+ * respectively, of the media data of its owner.
+ */
+ private Format format;
+
+ /**
+ * Gets the Format of the media data of the owner of
+ * this FormatControl.
+ *
+ * @return the Format of the media data of the owner of
+ * this FormatControl
+ */
+ public Format getFormat()
+ {
+ if (format == null)
+ format
+ = AbstractPushBufferCaptureDevice.this
+ .getFormat(streamIndex, this);
+ return format;
+ }
+
+ /**
+ * Gets the Formats in which the owner of this
+ * FormatControl is capable of providing media data.
+ *
+ * @return an array of Formats in which the owner of
+ * this FormatControl is capable of providing media
+ * data
+ */
+ public Format[] getSupportedFormats()
+ {
+ return
+ AbstractPushBufferCaptureDevice.this
+ .getSupportedFormats(streamIndex, this);
+ }
+
+ /**
+ * Implements {@link FormatControl#setFormat(Format)}. Attempts
+ * to set the Format in which the owner of this
+ * FormatControl is to provide media data.
+ *
+ * @param format the Format to be set on this instance
+ * @return the currently set Format after the attempt
+ * to set it on this instance if format is supported by
+ * this instance and regardless of whether it was actually set;
+ * null if format is not supported by this
+ * instance
+ */
+ @Override
+ public Format setFormat(Format format)
+ {
+ format = super.setFormat(format);
+
+ if ((format != null)
+ && canSetFormat(format, streamIndex, this))
+ this.format = format;
+ return getFormat();
+ }
+ };
+ }
+
+ /**
+ * Creates the FormatControls of this CaptureDevice.
+ *
+ * @return an array of the FormatControls of this
+ * CaptureDevice
+ */
+ protected FormatControl[] createFormatControls()
+ {
+ FormatControl formatControl = createFormatControl(0);
+
+ return
+ (formatControl == null)
+ ? EMPTY_FORMAT_CONTROLS
+ : new FormatControl[] { formatControl };
+ }
+
+ /**
+ * Create a new PushBufferStream which is to be at a specific
+ * zero-based index in the list of streams of this
+ * PushBufferDataSource. The Format-related information of
+ * the new instance is to be abstracted by a specific
+ * FormatControl.
+ *
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * in the list of streams of this PushBufferDataSource
+ * @param formatControl the FormatControl which is to abstract the
+ * Format-related information of the new instance
+ * @return a new PushBufferStream which is to be at the specified
+ * streamIndex in the list of streams of this
+ * PushBufferDataSource and which has its Format-related
+ * information abstracted by the specified formatControl
+ */
+ protected abstract AbstractPushBufferStream createStream(
+ int streamIndex,
+ FormatControl formatControl);
+
+ /**
+ * Closes the connection to the media source specified by the
+ * MediaLocator of this DataSource. If such a connection
+ * has not been opened, the call is ignored.
+ */
+ public synchronized void disconnect()
+ {
+ try
+ {
+ stop();
+ }
+ catch (IOException ioex)
+ {
+ logger.error("Failed to stop " + getClass().getSimpleName(), ioex);
+ }
+
+ if (connected)
+ {
+ doDisconnect();
+ connected = false;
+ }
+ }
+
+ /**
+ * Opens a connection to the media source specified by the
+ * MediaLocator of this DataSource. Allows extenders to
+ * override and be sure that there will be no request to open a connection
+ * if the connection has already been opened.
+ *
+ * @throws IOException if anything goes wrong while opening the connection
+ * to the media source specified by the MediaLocator of this
+ * DataSource
+ */
+ protected synchronized void doConnect()
+ throws IOException
+ {
+ }
+
+ /**
+ * Closes the connection to the media source specified by the
+ * MediaLocator of this DataSource. Allows extenders to
+ * override and be sure that there will be no request to close a connection
+ * if the connection has not been opened yet.
+ */
+ protected synchronized void doDisconnect()
+ {
+ if (streams != null)
+ try
+ {
+ for (AbstractPushBufferStream stream : streams)
+ stream.close();
+ }
+ finally
+ {
+ streams = null;
+ }
+ }
+
+ /**
+ * Starts the transfer of media data from this DataSource. Allows
+ * extenders to override and be sure that there will be no request to start
+ * the transfer of media data if it has already been started.
+ *
+ * @throws IOException if anything goes wrong while starting the transfer of
+ * media data from this DataSource
+ */
+ protected synchronized void doStart()
+ throws IOException
+ {
+ if (streams != null)
+ for (AbstractPushBufferStream stream : streams)
+ stream.start();
+ }
+
+ /**
+ * Stops the transfer of media data from this DataSource. Allows
+ * extenders to override and be sure that there will be no request to stop
+ * the transfer of media data if it has not been started yet.
+ *
+ * @throws IOException if anything goes wrong while stopping the transfer of
+ * media data from this DataSource
+ */
+ protected synchronized void doStop()
+ throws IOException
+ {
+ if (streams != null)
+ for (AbstractPushBufferStream stream : streams)
+ stream.stop();
+ }
+
+ /**
+ * Gets the CaptureDeviceInfo of this CaptureDevice which
+ * describes it.
+ *
+ * @return the CaptureDeviceInfo of this CaptureDevice
+ * which describes it
+ */
+ public CaptureDeviceInfo getCaptureDeviceInfo()
+ {
+ return getCaptureDeviceInfo(this);
+ }
+
+ /**
+ * Gets the CaptureDeviceInfo of a specific CaptureDevice
+ * by locating its registration in JMF using its MediaLocator.
+ *
+ * @param captureDevice the CaptureDevice to gets the
+ * CaptureDeviceInfo of
+ * @return the CaptureDeviceInfo of the specified
+ * CaptureDevice as registered in JMF
+ */
+ public static CaptureDeviceInfo getCaptureDeviceInfo(
+ DataSource captureDevice)
+ {
+ /*
+ * TODO The implemented search for the CaptureDeviceInfo of this
+ * CaptureDevice by looking for its MediaLocator is inefficient.
+ */
+ @SuppressWarnings("unchecked")
+ Vector captureDeviceInfos
+ = (Vector)
+ CaptureDeviceManager.getDeviceList(null);
+ MediaLocator locator = captureDevice.getLocator();
+
+ for (CaptureDeviceInfo captureDeviceInfo : captureDeviceInfos)
+ if (captureDeviceInfo.getLocator().equals(locator))
+ return captureDeviceInfo;
+ return null;
+ }
+
+ /**
+ * Gets the content type of the media represented by this instance. The
+ * AbstractPushBufferCaptureDevice implementation always returns
+ * {@link ContentDescriptor#RAW}.
+ *
+ * @return the content type of the media represented by this instance
+ */
+ public String getContentType()
+ {
+ return ContentDescriptor.RAW;
+ }
+
+ /**
+ * Gets the control of the specified type available for this instance.
+ *
+ * @param controlType the type of the control available for this instance to
+ * be retrieved
+ * @return an Object which represents the control of the specified
+ * type available for this instance if such a control is indeed available;
+ * otherwise, null
+ */
+ public Object getControl(String controlType)
+ {
+ return AbstractControls.getControl(this, controlType);
+ }
+
+ /**
+ * Implements {@link Controls#getControls()}. Gets the controls available
+ * for this instance.
+ *
+ * @return an array of Objects which represent the controls
+ * available for this instance
+ */
+ public Object[] getControls()
+ {
+ FormatControl[] formatControls = internalGetFormatControls();
+
+ if ((formatControls == null) || (formatControls.length == 0))
+ return ControlsAdapter.EMPTY_CONTROLS;
+ else
+ {
+ Object[] controls = new Object[formatControls.length];
+
+ System.arraycopy(
+ formatControls,
+ 0,
+ controls,
+ 0,
+ formatControls.length);
+ return controls;
+ }
+ }
+
+ /**
+ * Gets the duration of the media represented by this instance. The
+ * AbstractPushBufferCaptureDevice always returns
+ * {@link #DURATION_UNBOUNDED}.
+ *
+ * @return the duration of the media represented by this instance
+ */
+ public Time getDuration()
+ {
+ return DURATION_UNBOUNDED;
+ }
+
+ /**
+ * Gets the Format which is to be reported by a specific
+ * FormatControl for a PushBufferStream at a specific
+ * zero-based index in the list of streams of this
+ * PushBufferDataSource.
+ *
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * in the list of streams of this PushBufferDataSource for which
+ * the specified FormatControl is to report a Format
+ * @param formatControl the FormatControl which si to report the
+ * Format
+ * @return the Format which is to be reported by
+ * formatControl as the format of the PushBufferStream at
+ * the specified streamIndex in the list of streams of this
+ * PushBufferDataSource
+ */
+ protected Format getFormat(int streamIndex, FormatControl formatControl)
+ {
+ Format[] supportedFormats
+ = getSupportedFormats(streamIndex, formatControl);
+
+ return
+ ((supportedFormats == null) || (supportedFormats.length < 1))
+ ? null
+ : supportedFormats[0];
+ }
+
+ /**
+ * Gets an array of FormatControl instances each one of which can
+ * be used before {@link #connect()} to get and set the capture
+ * Format of each one of the capture streams.
+ *
+ * @return an array of FormatControl instances each one of which
+ * can be used before {@link #connect()} to get and set the capture
+ * Format of each one of the capture streams
+ */
+ public FormatControl[] getFormatControls()
+ {
+ return AbstractFormatControl.getFormatControls(this);
+ }
+
+ /**
+ * Gets the PushBufferStreams through which this
+ * PushBufferDataSource gives access to its media data.
+ *
+ * @return an array of the PushBufferStreams through which this
+ * PushBufferDataSource gives access to its media data
+ */
+ public synchronized PushBufferStream[] getStreams()
+ {
+ if (streams == null)
+ {
+ FormatControl[] formatControls = internalGetFormatControls();
+
+ if (formatControls != null)
+ {
+ int formatControlCount = formatControls.length;
+
+ streams = new AbstractPushBufferStream[formatControlCount];
+ for (int i = 0; i < formatControlCount; i++)
+ streams[i] = createStream(i, formatControls[i]);
+
+ /*
+ * Start the streams if this DataSource has already been
+ * started.
+ */
+ if (started)
+ for (AbstractPushBufferStream stream : streams)
+ try
+ {
+ stream.start();
+ }
+ catch (IOException ioex)
+ {
+ throw new UndeclaredThrowableException(ioex);
+ }
+ }
+ }
+ if (streams == null)
+ return EMPTY_STREAMS;
+ else
+ {
+ PushBufferStream[] clone = new PushBufferStream[streams.length];
+
+ System.arraycopy(streams, 0, clone, 0, streams.length);
+ return clone;
+ }
+ }
+
+ /**
+ * Gets the Formats which are to be reported by a specific
+ * FormatControl as supported formats for a
+ * PushBufferStream at a specific zero-based index in the list of
+ * streams of this PushBufferDataSource.
+ *
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * for which the specified FormatControl is to report the list of
+ * supported Formats
+ * @param formatControl the FormatControl which is to reports a
+ * list of supported Formats
+ * @return an array of Formats to be reported by
+ * formatControl as the supported formats for the
+ * PushBufferStream at the specified streamIndex in the
+ * list of streams of this PushBufferDataSource
+ */
+ protected Format[] getSupportedFormats(
+ int streamIndex,
+ FormatControl formatControl)
+ {
+ CaptureDeviceInfo captureDeviceInfo = getCaptureDeviceInfo();
+
+ return
+ (captureDeviceInfo == null) ? null : captureDeviceInfo.getFormats();
+ }
+
+ /**
+ * Gets an array of FormatControl instances each one of which can
+ * be used before {@link #connect()} to get and set the capture
+ * Format of each one of the capture streams.
+ *
+ * @return an array of FormatControl instances each one of which
+ * can be used before {@link #connect()} to get and set the capture
+ * Format of each one of the capture streams
+ */
+ private synchronized FormatControl[] internalGetFormatControls()
+ {
+ if (formatControls == null)
+ formatControls = createFormatControls();
+ return formatControls;
+ }
+
+ /**
+ * Starts the transfer of media data from this DataSource
+ *
+ * @throws IOException if anything goes wrong while starting the transfer of
+ * media data from this DataSource
+ */
+ public synchronized void start()
+ throws IOException
+ {
+ if (!started)
+ {
+ if (!connected)
+ throw
+ new IOException(
+ getClass().getSimpleName() + " not connected");
+
+ doStart();
+ started = true;
+ }
+ }
+
+ /**
+ * Stops the transfer of media data from this DataSource.
+ *
+ * @throws IOException if anything goes wrong while stopping the transfer of
+ * media data from this DataSource
+ */
+ public synchronized void stop()
+ throws IOException
+ {
+ if (started)
+ {
+ doStop();
+ started = false;
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferStream.java
index 2321173bb..d4a92c8fb 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferStream.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/AbstractPushBufferStream.java
@@ -6,9 +6,14 @@
*/
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol;
+import java.io.*;
+
+import javax.media.*;
+import javax.media.control.*;
import javax.media.protocol.*;
import net.java.sip.communicator.impl.neomedia.control.*;
+import net.java.sip.communicator.util.*;
/**
* Provides a base implementation of PushBufferStream in order to
@@ -18,10 +23,17 @@
* @author Lubomir Marinov
*/
public abstract class AbstractPushBufferStream
- extends ControlsAdapter
+ extends AbstractControls
implements PushBufferStream
{
+ /**
+ * The Logger used by the AbstractPushBufferStream class
+ * and its instances for logging output.
+ */
+ private static final Logger logger
+ = Logger.getLogger(AbstractPushBufferStream.class);
+
/**
* The (default) ContentDescriptor of the
* AbstractPushBufferStream instances.
@@ -29,12 +41,49 @@ public abstract class AbstractPushBufferStream
private static final ContentDescriptor CONTENT_DESCRIPTOR
= new ContentDescriptor(ContentDescriptor.RAW);
+ /**
+ * The FormatControl which gives access to the Format of
+ * the media data provided by this SourceStream and which,
+ * optionally, allows setting it.
+ */
+ private final FormatControl formatControl;
+
/**
* The BufferTransferHandler which is notified by this
* PushBufferStream when data is available for reading.
*/
protected BufferTransferHandler transferHandler;
+ /**
+ * Initializes a new AbstractPushBufferStream instance which is to
+ * have its Format-related information abstracted by a specific
+ * FormatControl.
+ *
+ * @param formatControl the FormatControl which is to abstract the
+ * Format-related information of the new instance
+ */
+ protected AbstractPushBufferStream(FormatControl formatControl)
+ {
+ this.formatControl = formatControl;
+ }
+
+ /**
+ * Releases the resources used by this instance throughout its existence and
+ * makes it available for garbage collection. This instance is considered
+ * unusable after closing.
+ */
+ public void close()
+ {
+ try
+ {
+ stop();
+ }
+ catch (IOException ioex)
+ {
+ logger.error("Failed to stop " + getClass().getSimpleName(), ioex);
+ }
+ }
+
/**
* Determines whether the end of this SourceStream has been
* reached. The AbstractPushBufferStream implementation always
@@ -76,6 +125,33 @@ public long getContentLength()
return LENGTH_UNKNOWN;
}
+ /**
+ * Implements {@link Controls#getControls()}. Gets the controls available
+ * for this instance.
+ *
+ * @return an array of Objects which represent the controls
+ * available for this instance
+ */
+ public Object[] getControls()
+ {
+ if (formatControl != null)
+ return new Object[] { formatControl };
+ else
+ return ControlsAdapter.EMPTY_CONTROLS;
+ }
+
+ /**
+ * Gets the Format of the media data made available by this
+ * PushBufferStream.
+ *
+ * @return the Format of the media data made available by this
+ * PushBufferStream
+ */
+ public Format getFormat()
+ {
+ return (formatControl == null) ? null : formatControl.getFormat();
+ }
+
/**
* Sets the BufferTransferHandler which is to be notified by this
* PushBufferStream when data is available for reading.
@@ -88,4 +164,22 @@ public void setTransferHandler(BufferTransferHandler transferHandler)
{
this.transferHandler = transferHandler;
}
+
+ /**
+ * Starts the transfer of media data from this PushBufferStream.
+ *
+ * @throws IOException if anything goes wrong while starting the transfer of
+ * media data from this PushBufferStream
+ */
+ public abstract void start()
+ throws IOException;
+
+ /**
+ * Stops the transfer of media data from this PushBufferStream.
+ *
+ * @throws IOException if anything goes wrong while stopping the transfer of
+ * media data from this PushBufferStream
+ */
+ public abstract void stop()
+ throws IOException;
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java
index 06f4b9a88..10058ca60 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/DataSource.java
@@ -7,15 +7,12 @@
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.imgstreaming;
import java.awt.*;
-import java.io.*;
import javax.media.*;
-import javax.media.format.*;
-import javax.media.protocol.*;
import javax.media.control.*;
+import javax.media.format.*;
-import net.java.sip.communicator.impl.neomedia.control.*;
-import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.*;
/**
* DataSource for our image streaming (which is used for
@@ -26,61 +23,27 @@
* @author Damian Minkov
*/
public class DataSource
- extends PushBufferDataSource
- implements CaptureDevice
+ extends AbstractPushBufferCaptureDevice
{
- /**
- * The Logger.
- */
- private static final Logger logger = Logger.getLogger(DataSource.class);
/**
- * DataSource connection state.
- */
- private boolean connected = false;
-
- /**
- * DataSource start state.
- */
- private boolean started = false;
-
- /**
- * The JMF controls (which are likely of type Control) available
- * for this DataSource.
- */
- private final Object[] controls = { new FormatControlImpl() };
-
- /**
- * Image stream.
- */
- private ImageStream stream = null;
-
- /**
- * The value of the streams property of DataSource which
- * represents an empty array of PushBufferStreams i.e. no
- * ImageStreams in DataSource. Explicitly defined in
- * order to reduce unnecessary allocations.
+ * Array of supported formats.
*/
- private static final PushBufferStream[] EMPTY_STREAMS =
- new PushBufferStream[0];
+ private static final Format formats[];
/**
- * Resolution supported for image.
+ * Resolutions supported for image. Listed in decreasing order of
+ * preference.
*/
private static final Dimension res[] = new Dimension[] {
- new Dimension(128,96),
- new Dimension(176, 144),
- new Dimension(320, 240),
- new Dimension(352, 288),
- new Dimension(704, 576),
new Dimension(720, 480),
+ new Dimension(704, 576),
+ new Dimension(352, 288),
+ new Dimension(320, 240),
+ new Dimension(176, 144),
+ new Dimension(128,96),
};
- /**
- * Array of supported formats.
- */
- private static final Format formats[];
-
static
{
/* initialize supported format array */
@@ -103,23 +66,6 @@ public class DataSource
}
}
- /**
- * Constructor.
- */
- public DataSource()
- {
- }
-
- /**
- * Constructor.
- *
- * @param locator associated MediaLocator
- */
- public DataSource(MediaLocator locator)
- {
- setLocator(locator);
- }
-
/**
* Get supported formats.
*
@@ -131,202 +77,43 @@ public static Format[] getFormats()
}
/**
- * Get the JMF streams.
- *
- * @return streams (one element in image streaming case)
- */
- public PushBufferStream[] getStreams()
- {
- if(stream == null)
- {
- stream = new ImageStream(getLocator());
- /* XXX allow to select other format */
- stream.setFormat(getFormats()[5]);
- }
-
- return (stream == null) ? EMPTY_STREAMS :
- new PushBufferStream[] {stream};
- }
-
- /**
- * Initialize DataSource.
- *
- * @throws IOException if initialization problem occurred
- */
- public void connect() throws IOException
- {
- if(connected)
- {
- return;
- }
-
- connected = true;
- }
-
- /**
- * Disconnect datasource.
- */
- public void disconnect()
- {
- connected = false;
- }
-
- /**
- * Get content type.
- *
- * @return RAW content type
- */
- public String getContentType()
- {
- return ContentDescriptor.RAW;
- }
-
- /**
- * Get duration for this source which is unknown.
- *
- * @return DURATION_UNKNOWN
- */
- public Time getDuration()
- {
- return DURATION_UNKNOWN;
- }
-
- /**
- * Gives control information to the caller.
- *
- * @return the collection of object controls.
- */
- public Object[] getControls()
- {
- /*
- * The field controls is private so we cannot directly return it.
- * Otherwise, the caller will be able to modify it.
- */
- return controls.clone();
- }
-
- /**
- * Return required control from the Control[] array
- * if exists.
- *
- * @param controlType the control we are interested in.
- * @return the object that implements the control, or null if not found
- */
- public Object getControl(String controlType)
- {
- return AbstractControls.getControl(this, controlType);
- }
-
- /**
- * Get the CaptureDeviceInfo associated
- * with this datasource.
- *
- * @return CaptureDeviceInfo associated
- */
- public CaptureDeviceInfo getCaptureDeviceInfo()
- {
- MediaLocator locator = getLocator();
-
- return
- new CaptureDeviceInfo(
- locator.getRemainder(),
- locator,
- getFormatControls()[0].getSupportedFormats());
- }
-
- /**
- * Get supported FormatControl.
- *
- * @return array of supported FormatControl
+ * Constructor.
*/
- public FormatControl[] getFormatControls()
+ public DataSource()
{
- return AbstractFormatControl.getFormatControls(this);
}
/**
- * Start capture.
+ * Constructor.
*
- * @throws IOException
- */
- public void start() throws IOException
- {
- /* DataSource already started, do not care */
- if(started)
- {
- return;
- }
-
- if(!connected)
- {
- throw new IOException("DataSource must be connected!");
- }
-
- stream.start();
- started = true;
- }
-
- /**
- * Stop capture.
+ * @param locator associated MediaLocator
*/
- public void stop()
+ public DataSource(MediaLocator locator)
{
- if(started)
- {
- started = false;
- stream.stop();
- }
+ super(locator);
}
/**
- * Implementation of FormatControl for this DataSource instance.
+ * Create a new PushBufferStream which is to be at a specific
+ * zero-based index in the list of streams of this
+ * PushBufferDataSource. The Format-related information of
+ * the new instance is to be abstracted by a specific
+ * FormatControl.
*
- * @author Sebastien Vincent
- */
- private class FormatControlImpl
- extends AbstractFormatControl
- {
- /**
- * Current format used.
- */
- private Format format = formats[0];
-
- /**
- * Set the format used.
- *
- * @param format format to use
- * @return format used or null if format is not supported
- */
- @Override
- public Format setFormat(Format format)
- {
- Format f = AbstractFormatControl.setFormat(this, format);
-
- if(f != null)
- this.format = f;
- return f;
- }
-
- /**
- * Get current format used.
- *
- * @return the Format of this DataSource
- */
- public Format getFormat()
- {
- return format;
- }
-
- /**
- * Get supported formats.
- *
- * @return an array of Format element type which lists the JMF
- * formats supported by this DataSource i.e. the ones in which
- * it is able to output
- */
- public Format[] getSupportedFormats()
- {
- return formats.clone();
- }
+ * @param streamIndex the zero-based index of the PushBufferStream
+ * in the list of streams of this PushBufferDataSource
+ * @param formatControl the FormatControl which is to abstract the
+ * Format-related information of the new instance
+ * @return a new PushBufferStream which is to be at the specified
+ * streamIndex in the list of streams of this
+ * PushBufferDataSource and which has its Format-related
+ * information abstracted by the specified formatControl
+ * @see AbstractPushBufferCaptureDevice#createStream(int, FormatControl)
+ */
+ protected AbstractPushBufferStream createStream(
+ int streamIndex,
+ FormatControl formatControl)
+ {
+ return new ImageStream(formatControl);
}
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java
index 129db083b..6f9086f02 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/imgstreaming/ImageStream.java
@@ -11,6 +11,7 @@
import java.io.*;
import javax.media.*;
+import javax.media.control.*;
import javax.media.format.*;
import javax.media.protocol.*;
@@ -36,11 +37,6 @@ public class ImageStream
*/
private static final Logger logger = Logger.getLogger(ImageStream.class);
- /**
- * Current format used.
- */
- private Format currentFormat = null;
-
/**
* Sequence number.
*/
@@ -67,39 +63,15 @@ public class ImageStream
private DesktopInteract desktopInteract = null;
/**
- * Constructor.
- */
- public ImageStream()
- {
- }
-
- /**
- * Constructor.
+ * Initializes a new ImageStream instance which is to have a
+ * specific FormatControl
*
- * @param locator MediaLocator to use
+ * @param formatControl the FormatControl of the new instance which
+ * is to specify the format in which it is to provide its media data
*/
- public ImageStream(MediaLocator locator)
+ ImageStream(FormatControl formatControl)
{
- }
-
- /**
- * Set format to use.
- *
- * @param format new format to use
- */
- public void setFormat(Format format)
- {
- currentFormat = format;
- }
-
- /**
- * Returns the supported format by this stream.
- *
- * @return supported formats
- */
- public Format getFormat()
- {
- return currentFormat;
+ super(formatControl);
}
/**
@@ -142,6 +114,8 @@ public void read(Buffer buffer)
/**
* Start desktop capture stream.
+ *
+ * @see AbstractPushBufferStream#start()
*/
public void start()
{
@@ -149,13 +123,21 @@ public void start()
{
logger.info("Start stream");
captureThread = new Thread(this);
- captureThread.start();
+
+ /*
+ * Set the started indicator before calling Thread#start() because
+ * the Thread may exist upon start if Thread#run() starts executing
+ * before setting the started indicator.
+ */
started = true;
+ captureThread.start();
}
}
/**
* Stop desktop capture stream.
+ *
+ * @see AbstractPushBufferStream#stop()
*/
public void stop()
{
@@ -169,7 +151,7 @@ public void stop()
*/
public void run()
{
- final RGBFormat format = (RGBFormat)currentFormat;
+ final RGBFormat format = (RGBFormat) getFormat();
Dimension formatSize = format.getSize();
final int width = (int)formatSize.getWidth();
final int height = (int)formatSize.getHeight();
@@ -208,7 +190,7 @@ public void run()
buf.setData(data);
buf.setOffset(0);
buf.setLength(data.length);
- buf.setFormat(currentFormat);
+ buf.setFormat(format);
buf.setHeader(null);
buf.setTimeStamp(System.nanoTime());
buf.setSequenceNumber(seqNo++);
diff --git a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java
index 5bce0a5f9..5160dd902 100644
--- a/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java
+++ b/src/net/java/sip/communicator/impl/neomedia/jmfext/media/protocol/portaudio/DataSource.java
@@ -7,7 +7,6 @@
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio;
import java.io.*;
-import java.util.*;
import javax.media.*;
import javax.media.control.*;
@@ -16,6 +15,7 @@
import net.java.sip.communicator.impl.neomedia.*;
import net.java.sip.communicator.impl.neomedia.control.*;
+import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.*;
import net.java.sip.communicator.impl.neomedia.portaudio.*;
import net.java.sip.communicator.util.*;
@@ -144,20 +144,7 @@ public synchronized void disconnect()
*/
public CaptureDeviceInfo getCaptureDeviceInfo()
{
- /*
- * TODO The implemented search for the CaptureDeviceInfo of this
- * CaptureDevice by looking for its MediaLocator is inefficient.
- */
- @SuppressWarnings("unchecked")
- Vector captureDeviceInfos
- = (Vector)
- CaptureDeviceManager.getDeviceList(null);
- MediaLocator locator = getLocator();
-
- for (CaptureDeviceInfo captureDeviceInfo : captureDeviceInfos)
- if (captureDeviceInfo.getLocator().equals(locator))
- return captureDeviceInfo;
- return null;
+ return AbstractPushBufferCaptureDevice.getCaptureDeviceInfo(this);
}
/**