-
Boris Grozev authored
opus to be advertised with 2 channels)
Boris Grozev authoredopus to be advertised with 2 channels)
MediaUtils.java 33.15 KiB
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jitsi.impl.neomedia;
import java.util.*;
import javax.media.*;
import javax.media.format.*;
import javax.sdp.*;
import org.jitsi.impl.neomedia.codec.*;
import org.jitsi.impl.neomedia.codec.video.h264.*;
import org.jitsi.impl.neomedia.device.*;
import org.jitsi.impl.neomedia.format.*;
import org.jitsi.service.configuration.*;
import org.jitsi.service.libjitsi.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.codec.*;
import org.jitsi.service.neomedia.device.*;
import org.jitsi.service.neomedia.format.*;
import org.jitsi.util.*;
/**
* Implements static utility methods used by media classes.
*
* @author Emil Ivov
* @author Lyubomir Marinov
* @author Boris Grozev
*/
public class MediaUtils
{
/**
* An empty array with <tt>MediaFormat</tt> element type. Explicitly defined
* in order to reduce unnecessary allocations, garbage collection.
*/
public static final MediaFormat[] EMPTY_MEDIA_FORMATS = new MediaFormat[0];
/**
* The <tt>Map</tt> of JMF-specific encodings to well-known encodings as
* defined in RFC 3551.
*/
private static final Map<String, String> jmfEncodingToEncodings
= new HashMap<String, String>();
/**
* The maximum number of channels for audio that is available through
* <tt>MediaUtils</tt>.
*/
public static final int MAX_AUDIO_CHANNELS;
/**
* The maximum sample rate for audio that is available through
* <tt>MediaUtils</tt>.
*/
public static final double MAX_AUDIO_SAMPLE_RATE;
/**
* The maximum sample size in bits for audio that is available through
* <tt>MediaUtils</tt>.
*/
public static final int MAX_AUDIO_SAMPLE_SIZE_IN_BITS;
/**
* The <tt>MediaFormat</tt>s which do not have RTP payload types assigned by
* RFC 3551 and are thus referred to as having dynamic RTP payload types.
*/
private static final List<MediaFormat> rtpPayloadTypelessMediaFormats
= new ArrayList<MediaFormat>();
/**
* The <tt>Map</tt> of RTP payload types (expressed as <tt>String</tt>s) to
* <tt>MediaFormat</tt>s.
*/
private static final Map<String, MediaFormat[]>
rtpPayloadTypeStrToMediaFormats
= new HashMap<String, MediaFormat[]>();
static
{
addMediaFormats(
(byte) SdpConstants.PCMU,
"PCMU",
MediaType.AUDIO,
AudioFormat.ULAW_RTP,
8000);
/*
* Some codecs depend on JMF native libraries which are only available
* on 32-bit Linux and 32-bit Windows.
*/
if(OSUtils.IS_LINUX32 || OSUtils.IS_WINDOWS32)
{
Map<String, String> g723FormatParams
= new HashMap<String, String>();
g723FormatParams.put("annexa", "no");
g723FormatParams.put("bitrate", "6.3");
addMediaFormats(
(byte) SdpConstants.G723,
"G723",
MediaType.AUDIO,
AudioFormat.G723_RTP,
g723FormatParams,
null,
8000);
}
addMediaFormats(
(byte) SdpConstants.GSM,
"GSM",
MediaType.AUDIO,
AudioFormat.GSM_RTP,
8000);
addMediaFormats(
(byte) SdpConstants.PCMA,
"PCMA",
MediaType.AUDIO,
Constants.ALAW_RTP,
8000);
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"iLBC",
MediaType.AUDIO,
Constants.ILBC_RTP,
8000);
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"speex",
MediaType.AUDIO,
Constants.SPEEX_RTP,
8000, 16000, 32000);
addMediaFormats(
(byte) SdpConstants.G722,
"G722",
MediaType.AUDIO,
Constants.G722_RTP,
8000);
if (EncodingConfigurationImpl.G729)
{
addMediaFormats(
(byte) SdpConstants.G729,
"G729",
MediaType.AUDIO,
AudioFormat.G729_RTP,
8000);
}
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"telephone-event",
MediaType.AUDIO,
Constants.TELEPHONE_EVENT,
8000);
ConfigurationService cfg = LibJitsi.getConfigurationService();
boolean advertiseFEC
= cfg.getBoolean(Constants.PROP_SILK_ADVERSISE_FEC, false);
Map<String,String> silkFormatParams = new HashMap<String, String>();
if(advertiseFEC)
silkFormatParams.put("useinbandfec", "1");
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"SILK",
MediaType.AUDIO,
Constants.SILK_RTP,
silkFormatParams,
null,
8000, 12000, 16000, 24000);
Map<String, String> opusFormatParams = new HashMap<String,String>();
boolean opusFec = cfg.getBoolean(Constants.PROP_OPUS_FEC, true);
if(!opusFec)
opusFormatParams.put("useinbandfec", "0");
boolean opusDtx = cfg.getBoolean(Constants.PROP_OPUS_DTX, true);
if(opusDtx)
opusFormatParams.put("usedtx", "1");
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"opus",
MediaType.AUDIO,
Constants.OPUS_RTP,
2,
opusFormatParams,
null,
48000);
/*
* We don't really support these.
*
addMediaFormats(
(byte) SdpConstants.JPEG,
"JPEG",
MediaType.VIDEO,
VideoFormat.JPEG_RTP);
addMediaFormats(
(byte) SdpConstants.H263,
"H263",
MediaType.VIDEO,
VideoFormat.H263_RTP);
addMediaFormats(
(byte) SdpConstants.H261,
"H261",
MediaType.VIDEO,
VideoFormat.H261_RTP);
*/
/* H264 */
Map<String, String> h264FormatParams
= new HashMap<String, String>();
String packetizationMode = "packetization-mode";
Map<String, String> h264AdvancedAttributes
= new HashMap<String, String>();
/*
* Disable PLI because the periodic intra-refresh feature of FFmpeg/x264
* is used.
*/
// h264AdvancedAttributes.put("rtcp-fb", "nack pli");
/*
* XXX The initialization of MediaServiceImpl is very complex so it is
* wise to not reference it at the early stage of its initialization.
*/
ScreenDevice screen = ScreenDeviceImpl.getDefaultScreenDevice();
java.awt.Dimension res = (screen == null) ? null : screen.getSize();
h264AdvancedAttributes.put("imageattr", createImageAttr(null, res));
if ((cfg == null)
|| cfg
.getString(
"net.java.sip.communicator.impl.neomedia"
+ ".codec.video.h264.defaultProfile",
JNIEncoder.MAIN_PROFILE)
.equals(JNIEncoder.MAIN_PROFILE))
{
// main profile, common features, HD capable level 3.1
h264FormatParams.put("profile-level-id", "4DE01f");
}
else
{
// baseline profile, common features, HD capable level 3.1
h264FormatParams.put("profile-level-id", "42E01f");
}
// By default, packetization-mode=1 is enabled.
if ((cfg == null)
|| cfg.getBoolean(
"net.java.sip.communicator.impl.neomedia"
+ ".codec.video.h264.packetization-mode-1.enabled",
true))
{
// packetization-mode=1
h264FormatParams.put(packetizationMode, "1");
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"H264",
MediaType.VIDEO,
Constants.H264_RTP,
h264FormatParams,
h264AdvancedAttributes);
}
/*
* XXX Android's current video CaptureDevice is based on MediaRecorder
* and provides support for packetization-mode=1 only.
*/
if (!OSUtils.IS_ANDROID)
{
// packetization-mode=0
/*
* XXX At the time of this writing,
* EncodingConfiguration#compareEncodingPreferences(MediaFormat,
* MediaFormat) is incomplete and considers two MediaFormats to be
* equal if they have an equal number of format parameters (given
* that the encodings and clock rates are equal, of course). Either
* fix the method in question or don't add a format parameter for
* packetization-mode 0 (which is equivalent to having
* packetization-mode explicitly defined as 0 anyway, according to
* the respective RFC).
*/
h264FormatParams.remove(packetizationMode);
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"H264",
MediaType.VIDEO,
Constants.H264_RTP,
h264FormatParams,
h264AdvancedAttributes);
}
/* H263+ */
Map<String, String> h263FormatParams
= new HashMap<String, String>();
Map<String, String> h263AdvancedAttributes
= new LinkedHashMap<String, String>();
/*
* The maximum resolution we can receive is the size of our screen
* device.
*/
if (res != null)
h263FormatParams.put("CUSTOM", res.width + "," + res.height + ",2");
h263FormatParams.put("VGA", "2");
h263FormatParams.put("CIF", "1");
h263FormatParams.put("QCIF", "1");
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"H263-1998",
MediaType.VIDEO,
Constants.H263P_RTP,
h263FormatParams,
h263AdvancedAttributes);
addMediaFormats(
MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN,
"VP8",
MediaType.VIDEO,
Constants.VP8_RTP,
null, null);
// Calculate the values of the MAX_AUDIO_* static fields of MediaUtils.
List<MediaFormat> audioMediaFormats
= new ArrayList<MediaFormat>(
rtpPayloadTypeStrToMediaFormats.size()
+ rtpPayloadTypelessMediaFormats.size());
for (MediaFormat[] mediaFormats
: rtpPayloadTypeStrToMediaFormats.values())
for (MediaFormat mediaFormat : mediaFormats)
if (MediaType.AUDIO.equals(mediaFormat.getMediaType()))
audioMediaFormats.add(mediaFormat);
for (MediaFormat mediaFormat : rtpPayloadTypelessMediaFormats)
if (MediaType.AUDIO.equals(mediaFormat.getMediaType()))
audioMediaFormats.add(mediaFormat);
int maxAudioChannels = Format.NOT_SPECIFIED;
double maxAudioSampleRate = Format.NOT_SPECIFIED;
int maxAudioSampleSizeInBits = Format.NOT_SPECIFIED;
for (MediaFormat mediaFormat : audioMediaFormats)
{
AudioMediaFormatImpl audioMediaFormat
= (AudioMediaFormatImpl) mediaFormat;
int channels = audioMediaFormat.getChannels();
double sampleRate = audioMediaFormat.getClockRate();
int sampleSizeInBits
= audioMediaFormat.getFormat().getSampleSizeInBits();
if (maxAudioChannels < channels)
maxAudioChannels = channels;
if (maxAudioSampleRate < sampleRate)
maxAudioSampleRate = sampleRate;
if (maxAudioSampleSizeInBits < sampleSizeInBits)
maxAudioSampleSizeInBits = sampleSizeInBits;
}
MAX_AUDIO_CHANNELS = maxAudioChannels;
MAX_AUDIO_SAMPLE_RATE = maxAudioSampleRate;
MAX_AUDIO_SAMPLE_SIZE_IN_BITS = maxAudioSampleSizeInBits;
}
/**
* Adds a new mapping of a specific RTP payload type to a list of
* <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific
* JMF encoding and, optionally, with specific clock rates.
*
* @param rtpPayloadType the RTP payload type to be associated with a list
* of <tt>MediaFormat</tt>s
* @param encoding the well-known encoding (name) corresponding to
* <tt>rtpPayloadType</tt> (in contrast to the JMF-specific encoding
* specified by <tt>jmfEncoding</tt>)
* @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to
* be associated with <tt>rtpPayloadType</tt>
* @param jmfEncoding the JMF encoding of the <tt>MediaFormat</tt>s to be
* associated with <tt>rtpPayloadType</tt>
* @param clockRates the optional list of clock rates of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt>
*/
private static void addMediaFormats(
byte rtpPayloadType,
String encoding,
MediaType mediaType,
String jmfEncoding,
double... clockRates)
{
addMediaFormats(
rtpPayloadType,
encoding,
mediaType,
jmfEncoding,
null,
null,
clockRates);
}
/**
* Adds a new mapping of a specific RTP payload type to a list of
* <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific
* JMF encoding and, optionally, with specific clock rates.
*
* @param rtpPayloadType the RTP payload type to be associated with a list
* of <tt>MediaFormat</tt>s
* @param encoding the well-known encoding (name) corresponding to
* <tt>rtpPayloadType</tt> (in contrast to the JMF-specific encoding
* specified by <tt>jmfEncoding</tt>)
* @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to
* be associated with <tt>rtpPayloadType</tt>
* @param jmfEncoding the JMF encoding of the <tt>MediaFormat</tt>s to be
* associated with <tt>rtpPayloadType</tt>
* @param formatParameters the set of format-specific parameters of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt>
* @param advancedAttributes the set of advanced attributes of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayload</tt>
* @param clockRates the optional list of clock rates of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt>
*/
private static void addMediaFormats(
byte rtpPayloadType,
String encoding,
MediaType mediaType,
String jmfEncoding,
Map<String, String> formatParameters,
Map<String, String> advancedAttributes,
double... clockRates)
{
addMediaFormats(
rtpPayloadType,
encoding,
mediaType,
jmfEncoding,
1 /* channel */,
formatParameters,
advancedAttributes,
clockRates);
}
/**
* Adds a new mapping of a specific RTP payload type to a list of
* <tt>MediaFormat</tt>s of a specific <tt>MediaType</tt>, with a specific
* JMF encoding and, optionally, with specific clock rates.
*
* @param rtpPayloadType the RTP payload type to be associated with a list
* of <tt>MediaFormat</tt>s
* @param encoding the well-known encoding (name) corresponding to
* <tt>rtpPayloadType</tt> (in contrast to the JMF-specific encoding
* specified by <tt>jmfEncoding</tt>)
* @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to
* be associated with <tt>rtpPayloadType</tt>
* @param jmfEncoding the JMF encoding of the <tt>MediaFormat</tt>s to be
* associated with <tt>rtpPayloadType</tt>
* @param channels number of channels
* @param formatParameters the set of format-specific parameters of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt>
* @param advancedAttributes the set of advanced attributes of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayload</tt>
* @param clockRates the optional list of clock rates of the
* <tt>MediaFormat</tt>s to be associated with <tt>rtpPayloadType</tt>
*/
@SuppressWarnings("unchecked")
private static void addMediaFormats(
byte rtpPayloadType,
String encoding,
MediaType mediaType,
String jmfEncoding,
int channels,
Map<String, String> formatParameters,
Map<String, String> advancedAttributes,
double... clockRates)
{
int clockRateCount = clockRates.length;
List<MediaFormat> mediaFormats
= new ArrayList<MediaFormat>(clockRateCount);
if (clockRateCount > 0)
{
for (double clockRate : clockRates)
{
Format format;
switch (mediaType)
{
case AUDIO:
if(channels == 1)
format = new AudioFormat(jmfEncoding);
else
format = new AudioFormat(
jmfEncoding,
Format.NOT_SPECIFIED,
Format.NOT_SPECIFIED,
channels);
break;
case VIDEO:
format
= new ParameterizedVideoFormat(
jmfEncoding,
formatParameters);
break;
default:
throw new IllegalArgumentException("mediaType");
}
MediaFormat mediaFormat
= MediaFormatImpl.createInstance(
format,
clockRate,
formatParameters,
advancedAttributes);
if (mediaFormat != null)
mediaFormats.add(mediaFormat);
}
}
else
{
Format format;
double clockRate;
switch (mediaType)
{
case AUDIO:
AudioFormat audioFormat = new AudioFormat(jmfEncoding);
format = audioFormat;
clockRate = audioFormat.getSampleRate();
break;
case VIDEO:
format
= new ParameterizedVideoFormat(
jmfEncoding,
formatParameters);
clockRate = VideoMediaFormatImpl.DEFAULT_CLOCK_RATE;
break;
default:
throw new IllegalArgumentException("mediaType");
}
MediaFormat mediaFormat
= MediaFormatImpl.createInstance(
format,
clockRate,
formatParameters,
advancedAttributes);
if (mediaFormat != null)
mediaFormats.add(mediaFormat);
}
if (mediaFormats.size() > 0)
{
if (MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN == rtpPayloadType)
rtpPayloadTypelessMediaFormats.addAll(mediaFormats);
else
rtpPayloadTypeStrToMediaFormats.put(
Byte.toString(rtpPayloadType),
mediaFormats.toArray(EMPTY_MEDIA_FORMATS));
jmfEncodingToEncodings.put(
((MediaFormatImpl<? extends Format>) mediaFormats.get(0))
.getJMFEncoding(),
encoding);
}
}
/**
* Creates value of an imgattr.
*
* http://tools.ietf.org/html/draft-ietf-mmusic-image-attributes-04
*
* @param sendSize maximum size peer can send
* @param maxRecvSize maximum size peer can display
* @return string that represent imgattr that can be encoded via SIP/SDP or
* XMPP/Jingle
*/
public static String createImageAttr(
java.awt.Dimension sendSize,
java.awt.Dimension maxRecvSize)
{
StringBuffer img = new StringBuffer();
/* send width */
if(sendSize != null)
{
/* single value => send [x=width,y=height] */
/*img.append("send [x=");
img.append((int)sendSize.getWidth());
img.append(",y=");
img.append((int)sendSize.getHeight());
img.append("]");*/
/* send [x=[min-max],y=[min-max]] */
img.append("send [x=[0-");
img.append((int)sendSize.getWidth());
img.append("],y=[0-");
img.append((int)sendSize.getHeight());
img.append("]]");
/*
else
{
// range
img.append(" send [x=[");
img.append((int)minSendSize.getWidth());
img.append("-");
img.append((int)maxSendSize.getWidth());
img.append("],y=[");
img.append((int)minSendSize.getHeight());
img.append("-");
img.append((int)maxSendSize.getHeight());
img.append("]]");
}
*/
}
else
{
/* can send "all" sizes */
img.append("send *");
}
/* receive size */
if(maxRecvSize != null)
{
/* basically we can receive any size up to our
* screen display size
*/
/* recv [x=[min-max],y=[min-max]] */
img.append(" recv [x=[0-");
img.append((int)maxRecvSize.getWidth());
img.append("],y=[0-");
img.append((int)maxRecvSize.getHeight());
img.append("]]");
}
else
{
/* accept all sizes */
img.append(" recv *");
}
return img.toString();
}
/**
* Gets a <tt>MediaFormat</tt> predefined in <tt>MediaUtils</tt> which
* represents a specific JMF <tt>Format</tt>. If there is no such
* representing <tt>MediaFormat</tt> in <tt>MediaUtils</tt>, returns
* <tt>null</tt>.
*
* @param format the JMF <tt>Format</tt> to get the <tt>MediaFormat</tt>
* representation for
* @return a <tt>MediaFormat</tt> predefined in <tt>MediaUtils</tt> which
* represents <tt>format</tt> if any; <tt>null</tt> if there is no such
* representing <tt>MediaFormat</tt> in <tt>MediaUtils</tt>
*/
@SuppressWarnings("unchecked")
public static MediaFormat getMediaFormat(Format format)
{
double clockRate;
if (format instanceof AudioFormat)
clockRate = ((AudioFormat) format).getSampleRate();
else if (format instanceof VideoFormat)
clockRate = VideoMediaFormatImpl.DEFAULT_CLOCK_RATE;
else
clockRate = Format.NOT_SPECIFIED;
byte rtpPayloadType = getRTPPayloadType(format.getEncoding(), clockRate);
if (MediaFormatImpl.RTP_PAYLOAD_TYPE_UNKNOWN != rtpPayloadType)
{
for (MediaFormat mediaFormat : getMediaFormats(rtpPayloadType))
{
MediaFormatImpl<? extends Format> mediaFormatImpl
= (MediaFormatImpl<? extends Format>) mediaFormat;
if (format.matches(mediaFormatImpl.getFormat()))
return mediaFormat;
}
}
return null;
}
/**
* Gets the <tt>MediaFormat</tt> known to <tt>MediaUtils</tt> and having the
* specified well-known <tt>encoding</tt> (name) and <tt>clockRate</tt>.
*
* @param encoding the well-known encoding (name) of the
* <tt>MediaFormat</tt> to get
* @param clockRate the clock rate of the <tt>MediaFormat</tt> to get
* @return the <tt>MediaFormat</tt> known to <tt>MediaUtils</tt> and having
* the specified <tt>encoding</tt> and <tt>clockRate</tt>
*/
public static MediaFormat getMediaFormat(String encoding, double clockRate)
{
return getMediaFormat(encoding, clockRate, null);
}
/**
* Gets the <tt>MediaFormat</tt> known to <tt>MediaUtils</tt> and having the
* specified well-known <tt>encoding</tt> (name), <tt>clockRate</tt> and
* matching format parameters.
*
* @param encoding the well-known encoding (name) of the
* <tt>MediaFormat</tt> to get
* @param clockRate the clock rate of the <tt>MediaFormat</tt> to get
* @param fmtps the format parameters of the <tt>MediaFormat</tt> to get
* @return the <tt>MediaFormat</tt> known to <tt>MediaUtils</tt> and having
* the specified <tt>encoding</tt> (name), <tt>clockRate</tt> and matching
* format parameters
*/
public static MediaFormat getMediaFormat(
String encoding, double clockRate,
Map<String, String> fmtps)
{
for (MediaFormat format : getMediaFormats(encoding))
if ((format.getClockRate() == clockRate)
&& format.formatParametersMatch(fmtps))
return format;
return null;
}
/**
* Gets the index of a specific <tt>MediaFormat</tt> instance within the
* internal storage of <tt>MediaUtils</tt>. Since the index is in the
* internal storage which may or may not be one and the same for the various
* <tt>MediaFormat</tt> instances and which may or may not be searched for
* the purposes of determining the index, the index is not to be used as a
* way to determine whether <tt>MediaUtils</tt> knows the specified
* <tt>mediaFormat</tt>
*
* @param mediaFormat the <tt>MediaFormat</tt> to determine the index of
* @return the index of the specified <tt>mediaFormat</tt> in the internal
* storage of <tt>MediaUtils</tt>
*/
public static int getMediaFormatIndex(MediaFormat mediaFormat)
{
return rtpPayloadTypelessMediaFormats.indexOf(mediaFormat);
}
/**
* Gets the <tt>MediaFormat</tt>s (expressed as an array) corresponding to
* a specific RTP payload type.
*
* @param rtpPayloadType the RTP payload type to retrieve the
* corresponding <tt>MediaFormat</tt>s for
* @return an array of <tt>MediaFormat</tt>s corresponding to the specified
* RTP payload type
*/
public static MediaFormat[] getMediaFormats(byte rtpPayloadType)
{
MediaFormat[] mediaFormats
= rtpPayloadTypeStrToMediaFormats.get(Byte.toString(rtpPayloadType));
return
(mediaFormats == null)
? EMPTY_MEDIA_FORMATS
: mediaFormats.clone();
}
/**
* Gets the <tt>MediaFormat</tt>s known to <tt>MediaUtils</tt> and being of
* the specified <tt>MediaType</tt>.
*
* @param mediaType the <tt>MediaType</tt> of the <tt>MediaFormat</tt>s to
* get
* @return the <tt>MediaFormat</tt>s known to <tt>MediaUtils</tt> and being
* of the specified <tt>mediaType</tt>
*/
public static MediaFormat[] getMediaFormats(MediaType mediaType)
{
List<MediaFormat> mediaFormats = new ArrayList<MediaFormat>();
for (MediaFormat[] formats : rtpPayloadTypeStrToMediaFormats.values())
for (MediaFormat format : formats)
if (format.getMediaType().equals(mediaType))
mediaFormats.add(format);
for (MediaFormat format : rtpPayloadTypelessMediaFormats)
if (format.getMediaType().equals(mediaType))
mediaFormats.add(format);
return mediaFormats.toArray(EMPTY_MEDIA_FORMATS);
}
/**
* Gets the <tt>MediaFormat</tt>s predefined in <tt>MediaUtils</tt> with a
* specific well-known encoding (name) as defined by RFC 3551 "RTP Profile
* for Audio and Video Conferences with Minimal Control".
*
* @param encoding the well-known encoding (name) to get the corresponding
* <tt>MediaFormat</tt>s of
* @return a <tt>List</tt> of <tt>MediaFormat</tt>s corresponding to the
* specified encoding (name)
*/
@SuppressWarnings("unchecked")
public static List<MediaFormat> getMediaFormats(String encoding)
{
String jmfEncoding = null;
for (Map.Entry<String, String> jmfEncodingToEncoding
: jmfEncodingToEncodings.entrySet())
if (jmfEncodingToEncoding.getValue().equals(encoding))
{
jmfEncoding = jmfEncodingToEncoding.getKey();
break;
}
List<MediaFormat> mediaFormats = new ArrayList<MediaFormat>();
if (jmfEncoding != null)
{
for (MediaFormat[] rtpPayloadTypeMediaFormats
: rtpPayloadTypeStrToMediaFormats.values())
for (MediaFormat rtpPayloadTypeMediaFormat
: rtpPayloadTypeMediaFormats)
if (((MediaFormatImpl<? extends Format>)
rtpPayloadTypeMediaFormat)
.getJMFEncoding().equals(jmfEncoding))
mediaFormats.add(rtpPayloadTypeMediaFormat);
if (mediaFormats.size() < 1)
{
for (MediaFormat rtpPayloadTypelessMediaFormat
: rtpPayloadTypelessMediaFormats)
if (((MediaFormatImpl<? extends Format>)
rtpPayloadTypelessMediaFormat)
.getJMFEncoding().equals(jmfEncoding))
mediaFormats.add(rtpPayloadTypelessMediaFormat);
}
}
return mediaFormats;
}
/**
* Gets the RTP payload type corresponding to a specific JMF encoding and
* clock rate.
*
* @param jmfEncoding the JMF encoding as returned by
* {@link Format#getEncoding()} or the respective <tt>AudioFormat</tt> and
* <tt>VideoFormat</tt> encoding constants to get the corresponding RTP
* payload type of
* @param clockRate the clock rate to be taken into account in the search
* for the RTP payload type if the JMF encoding does not uniquely identify
* it
* @return the RTP payload type corresponding to the specified JMF encoding
* and clock rate if known in RFC 3551 "RTP Profile for Audio and Video
* Conferences with Minimal Control"; otherwise,
* {@link MediaFormat#RTP_PAYLOAD_TYPE_UNKNOWN}
*/
public static byte getRTPPayloadType(String jmfEncoding, double clockRate)
{
if (jmfEncoding == null)
return MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN;
else if (jmfEncoding.equals(AudioFormat.ULAW_RTP))
return SdpConstants.PCMU;
else if (jmfEncoding.equals(Constants.ALAW_RTP))
return SdpConstants.PCMA;
else if (jmfEncoding.equals(AudioFormat.GSM_RTP))
return SdpConstants.GSM;
else if (jmfEncoding.equals(AudioFormat.G723_RTP))
return SdpConstants.G723;
else if (jmfEncoding.equals(AudioFormat.DVI_RTP)
&& (clockRate == 8000))
return SdpConstants.DVI4_8000;
else if (jmfEncoding.equals(AudioFormat.DVI_RTP)
&& (clockRate == 16000))
return SdpConstants.DVI4_16000;
else if (jmfEncoding.equals(AudioFormat.ALAW))
return SdpConstants.PCMA;
else if (jmfEncoding.equals(Constants.G722))
return SdpConstants.G722;
else if (jmfEncoding.equals(Constants.G722_RTP))
return SdpConstants.G722;
else if (jmfEncoding.equals(AudioFormat.GSM))
return SdpConstants.GSM;
else if (jmfEncoding.equals(AudioFormat.GSM_RTP))
return SdpConstants.GSM;
else if (jmfEncoding.equals(AudioFormat.G728_RTP))
return SdpConstants.G728;
else if (jmfEncoding.equals(AudioFormat.G729_RTP))
return SdpConstants.G729;
else if (jmfEncoding.equals(VideoFormat.H263_RTP))
return SdpConstants.H263;
else if (jmfEncoding.equals(VideoFormat.JPEG_RTP))
return SdpConstants.JPEG;
else if (jmfEncoding.equals(VideoFormat.H261_RTP))
return SdpConstants.H261;
else
return MediaFormat.RTP_PAYLOAD_TYPE_UNKNOWN;
}
/**
* Gets the well-known encoding (name) as defined in RFC 3551 "RTP Profile
* for Audio and Video Conferences with Minimal Control" corresponding to a
* given JMF-specific encoding.
*
* @param jmfEncoding the JMF encoding to get the corresponding well-known
* encoding of
* @return the well-known encoding (name) as defined in RFC 3551 "RTP
* Profile for Audio and Video Conferences with Minimal Control"
* corresponding to <tt>jmfEncoding</tt> if any; otherwise, <tt>null</tt>
*/
public static String jmfEncodingToEncoding(String jmfEncoding)
{
return jmfEncodingToEncodings.get(jmfEncoding);
}
}