/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party
* contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.media.server.impl.resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import org.mobicents.media.Buffer;
import org.mobicents.media.Format;
import org.mobicents.media.Inlet;
import org.mobicents.media.MediaSink;
import org.mobicents.media.MediaSource;
import org.mobicents.media.server.impl.AbstractSink;
import org.mobicents.media.server.impl.AbstractSource;
import org.mobicents.media.server.impl.AbstractSourceSet;
import org.mobicents.media.server.spi.Connection;
import org.mobicents.media.server.spi.Endpoint;
import org.mobicents.media.server.spi.SyncSource;
/**
* A Demultiplexer is a media processing component that takes an interleaved
* media stream as input, extracts the individual tracks from the stream, and
* outputs the resulting tracks. It has one input and multiple outputs.
*
* @author Oleg Kulikov
*/
public class Demultiplexer extends AbstractSourceSet implements Inlet {
private Format[] outputFormats = new Format[0];
private Input input = null;
private Buffer buff;
private long timestamp;
/**
* Creates new instance of the demultiplexer.
*
* @param name
*/
public Demultiplexer(String name) {
super(name);
input = new Input(name);
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.Inlet#getInput().
*/
public AbstractSink getInput() {
return input;
}
public void connect(MediaSource source) {
input.connect(source);
}
public void disconnect(MediaSource source) {
input.disconnect(source);
}
@Override
public AbstractSource createSource(MediaSink otherParty) {
Output output = new Output(getName() + "[output]");
output.setSyncSource(input);
output.setEndpoint(getEndpoint());
output.setConnection(getConnection());
return output;
}
@Override
public void setConnection(Connection connection) {
super.setConnection(connection);
input.setConnection(connection);
Collection<AbstractSource> list = getStreams();
for (AbstractSource stream : list) {
stream.setConnection(connection);
}
}
@Override
public void setEndpoint(Endpoint endpoint) {
super.setEndpoint(endpoint);
input.setEndpoint(endpoint);
Collection<AbstractSource> list = getStreams();
for (AbstractSource stream : list) {
stream.setEndpoint(endpoint);
}
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.MediaSource#getFormats().
*/
public Format[] getFormats() {
return input.getOtherPartyFormats();
}
/**
* Reassemblies the list of used formats. This method is called each time
* when connected/disconnected source
*/
private void reassemblyFormats() {
ArrayList list = new ArrayList();
Collection<AbstractSource> streams = getStreams();
for (AbstractSource stream : streams) {
Format[] fmts = ((Output)stream).getOtherPartyFormats();
for (Format format : fmts) {
if (!list.contains(format)) {
list.add(format);
}
}
}
outputFormats = new Format[list.size()];
list.toArray(outputFormats);
}
@Override
public void start() {
input.start();
}
@Override
public void stop() {
input.stop();
}
/**
* Implements input stream of the Demultiplxer.
*
*/
private class Input extends AbstractSink implements SyncSource {
/**
* Creates new instance of input stream.
*
* The name of the demultiplxer.
*/
public Input(String name) {
super(name + "[input]");
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.MediaSink#isAcceptable(org.mobicents.media.Format)
*/
public boolean isAcceptable(Format fmt) {
Collection<AbstractSource> streams = getStreams();
for (AbstractSource stream : streams) {
if (((Output)stream).isAcceptable(fmt)) return true;
}
return false;
}
/**
* Reads supported formats from other party if connected.
*
* @return if other party connected returns array of supported formats
* or empty array if not connected.
*/
protected Format[] getOtherPartyFormats() {
return otherParty != null ? otherParty.getFormats() : new Format[0];
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.server.impl.AbstractSink#onMediaTransfer(org.mobicents.media.Buffer).
*/
public void onMediaTransfer(Buffer buffer) throws IOException {
buff = buffer;
timestamp = buffer.getTimeStamp();
Collection<AbstractSource> streams = getStreams();
for (AbstractSource stream : streams) {
((Output) stream).run();
}
buffer.dispose();
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.MediaSink#getFormats().
*/
public Format[] getFormats() {
reassemblyFormats();
return outputFormats;
}
public void sync(MediaSource mediaSource) {
}
public void unsync(MediaSource mediaSource) {
}
public long getTimestamp() {
return timestamp;
}
}
/**
* Implements output stream.
*/
private class Output extends AbstractSource {
public Output(String parent) {
super(parent);
}
@Override
public void start() {
}
@Override
public void stop() {
}
/**
* Checks is other party supports specofied format.
*
* @param fmt the format to check
* @return true if other party supports this format.
*/
public boolean isAcceptable(Format fmt) {
return otherParty != null && otherParty.isAcceptable(fmt);
}
/**
* Gets list of formats supported by other party.
*
* @return array of formats or empty array if not connected yet.
*/
public Format[] getOtherPartyFormats() {
return otherParty != null ? otherParty.getFormats() : new Format[0];
}
/**
* (Non Java-doc).
*
* @see org.mobicents.media.MediaSource#getFormats()
*/
public Format[] getFormats() {
return input.getOtherPartyFormats();
}
@Override
public void evolve(Buffer buffer, long timestamp, long sequenceNumber) {
buffer.copy(buff);
}
}
@Override
public void evolve(Buffer buffer, long timestamp, long sequenceNumber) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void destroySource(AbstractSource source) {
}
}