net.pms.configuration.FormatConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pms Show documentation
Show all versions of pms Show documentation
PS3 Media Server is a cross-platform DLNA-compliant UPnP Media Server.
Originally written to support the PlayStation 3, PS3 Media Server has been
expanded to support a range of other media renderers, including smartphones,
televisions, music players and more.
The newest version!
package net.pms.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import net.pms.dlna.DLNAMediaAudio;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.InputFile;
import net.pms.dlna.MediaInfoParser;
import net.pms.formats.Format;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FormatConfiguration {
private static final Logger logger = LoggerFactory.getLogger(FormatConfiguration.class);
public static final String MPEGPS = "mpegps";
public static final String MPEGTS = "mpegts";
public static final String WMV = "wmv";
public static final String AVI = "avi";
public static final String MP4 = "mp4";
public static final String MOV = "mov";
public static final String FLV = "flv";
public static final String RM = "rm";
public static final String MATROSKA = "mkv";
public static final String WAV = "wav";
public static final String WAVPACK = "wavpack";
public static final String LPCM = "lpcm";
public static final String AAC = "aac";
public static final String AC3 = "ac3";
public static final String MP3 = "mp3";
public static final String SHORTEN = "shn";
public static final String MPA = "mpa";
public static final String OGG = "ogg";
public static final String WMA = "wma";
public static final String ALAC = "alac";
public static final String DTS = "dts";
public static final String DTSHD = "dtshd";
public static final String TRUEHD = "truehd";
public static final String EAC3 = "eac3";
public static final String ATRAC = "atrac";
public static final String FLAC = "flac";
public static final String APE = "ape";
public static final String RA = "ra";
public static final String MPC = "mpc";
public static final String AIFF = "aiff";
public static final String DV = "dv";
public static final String MPEG1 = "mpeg1";
public static final String MPEG2 = "mpeg2";
public static final String DIVX = "divx";
public static final String H264 = "h264";
public static final String MLP = "mlp";
public static final String MJPEG = "mjpeg";
public static final String VC1 = "vc1";
public static final String JPG = "jpg";
public static final String PNG = "png";
public static final String GIF = "gif";
public static final String TIFF = "tiff";
public static final String BMP = "bmp";
public static final String und = "und";
public static final String MI_QPEL = "qpel";
public static final String MI_GMC = "gmc";
// Use old parser for Jpeg files (MediaInfo does not support EXIF)
private static final String PARSER_V1_EXTENSIONS[] = new String[]{".jpg", ".jpe", ".jpeg"};
public void parse(DLNAMediaInfo media, InputFile file, Format ext, int type) {
boolean force_v1 = false;
if (file.getFile() != null) {
String fName = file.getFile().getName().toLowerCase();
for (String e : PARSER_V1_EXTENSIONS) {
if (fName.endsWith(e)) {
force_v1 = true;
break;
}
}
if (force_v1) {
media.parse(file, ext, type, false);
} else {
MediaInfoParser.parse(media, file, type);
}
} else {
media.parse(file, ext, type, false);
}
}
public static final String MIMETYPE_AUTO = "MIMETYPE_AUTO";
ArrayList list;
class Supports {
String format;
String videocodec;
String audiocodec;
String mimetype;
String maxnbchannels;
String maxfrequency;
String maxbitrate;
String maxvideowidth;
String maxvideoheight;
Map miExtras;
Pattern pformat;
Pattern pvideocodec;
Pattern paudiocodec;
int imaxnbchannels = Integer.MAX_VALUE;
int imaxfrequency = Integer.MAX_VALUE;
int imaxbitrate = Integer.MAX_VALUE;
int imaxvideowidth = Integer.MAX_VALUE;
int imaxvideoheight = Integer.MAX_VALUE;
Supports() {
mimetype = MIMETYPE_AUTO;
}
boolean isValid() {
boolean v = format != null && format.length() > 0;
if (v) {
try {
pformat = Pattern.compile(format);
} catch (PatternSyntaxException pe) {
logger.info("Couldn't resolve this pattern: " + format + " / " + pe.getMessage());
v = false;
}
if (videocodec != null) {
try {
pvideocodec = Pattern.compile(videocodec);
} catch (PatternSyntaxException pe) {
logger.info("Couldn't resolve this pattern: " + videocodec + " / " + pe.getMessage());
v = false;
}
}
if (audiocodec != null) {
try {
paudiocodec = Pattern.compile(audiocodec);
} catch (PatternSyntaxException pe) {
logger.info("Couldn't resolve this pattern: " + audiocodec + " / " + pe.getMessage());
v = false;
}
}
try {
if (maxnbchannels != null) {
imaxnbchannels = Integer.parseInt(maxnbchannels);
}
} catch (Exception e) {
logger.info("Error in parsing number: " + maxnbchannels);
v = false;
}
try {
if (maxfrequency != null) {
imaxfrequency = Integer.parseInt(maxfrequency);
}
} catch (Exception e) {
logger.info("Error in parsing number: " + maxfrequency);
v = false;
}
try {
if (maxbitrate != null) {
imaxbitrate = Integer.parseInt(maxbitrate);
}
} catch (Exception e) {
logger.info("Error in parsing number: " + maxbitrate);
v = false;
}
try {
if (maxvideowidth != null) {
imaxvideowidth = Integer.parseInt(maxvideowidth);
}
} catch (Exception e) {
logger.info("Error in parsing number: " + maxvideowidth);
v = false;
}
try {
if (maxvideoheight != null) {
imaxvideoheight = Integer.parseInt(maxvideoheight);
}
} catch (Exception e) {
logger.info("Error in parsing number: " + maxvideoheight);
v = false;
}
}
return v;
}
public boolean match(String container, String videocodec, String audiocodec) {
return match(container, videocodec, audiocodec, 0, 0, 0, 0, 0, null);
}
public boolean match(String format, String videocodec, String audiocodec, int nbAudioChannels, int frequency, int bitrate, int videowidth, int videoheight, Map extras) {
boolean matched = false;
if (format != null && !(matched = pformat.matcher(format).matches())) {
return false;
}
if (matched && videocodec != null && pvideocodec != null && !(matched = pvideocodec.matcher(videocodec).matches())) {
return false;
}
if (matched && audiocodec != null && paudiocodec != null && !(matched = paudiocodec.matcher(audiocodec).matches())) {
return false;
}
if (matched && nbAudioChannels > 0 && imaxnbchannels > 0 && nbAudioChannels > imaxnbchannels) {
return false;
}
if (matched && frequency > 0 && imaxfrequency > 0 && frequency > imaxfrequency) {
return false;
}
if (matched && bitrate > 0 && imaxbitrate > 0 && bitrate > imaxbitrate) {
return false;
}
if (matched && videowidth > 0 && imaxvideowidth > 0 && videowidth > imaxvideowidth) {
return false;
}
if (matched && videoheight > 0 && imaxvideoheight > 0 && videoheight > imaxvideoheight) {
return false;
}
if (matched && extras != null && miExtras != null) {
Iterator keyIt = extras.keySet().iterator();
while (keyIt.hasNext()) {
String key = keyIt.next();
String value = extras.get(key);
if (matched && key.equals(MI_QPEL) && miExtras.get(MI_QPEL) != null) {
matched = miExtras.get(MI_QPEL).matcher(value).matches();
} else if (matched && key.equals(MI_GMC) && miExtras.get(MI_GMC) != null) {
matched = miExtras.get(MI_GMC).matcher(value).matches();
}
}
}
return matched;
}
}
public boolean isDVDVideoRemuxSupported() {
return match(MPEGPS, MPEG2, null) != null;
}
public boolean isFormatSupported(String container) {
return match(container, null, null) != null;
}
public boolean isDTSSupported() {
return match(MPEGPS, null, DTS) != null || match(MPEGTS, null, DTS) != null;
}
public boolean isLPCMSupported() {
return match(MPEGPS, null, LPCM) != null || match(MPEGTS, null, LPCM) != null;
}
public boolean isMpeg2Supported() {
return match(MPEGPS, MPEG2, null) != null || match(MPEGTS, MPEG2, null) != null;
}
public boolean isHiFiMusicFileSupported() {
return match(WAV, null, null, 0, 96000, 0, 0, 0, null) != null || match(MP3, null, null, 0, 96000, 0, 0, 0, null) != null;
}
public String getPrimaryVideoTranscoder() {
for (Supports conf : list) {
if (conf.match(MPEGPS, MPEG2, AC3)) {
return MPEGPS;
}
if (conf.match(MPEGTS, MPEG2, AC3)) {
return MPEGTS;
}
if (conf.match(WMV, WMV, WMA)) {
return WMV;
}
}
return null;
}
public String getPrimaryAudioTranscoder() {
for (Supports conf : list) {
if (conf.match(WAV, null, null)) {
return WAV;
}
if (conf.match(MP3, null, null)) {
return MP3;
}
}
return null;
}
public FormatConfiguration(List> supported) {
list = new ArrayList();
for (Object line : supported) {
if (line != null) {
Supports conf = parseSupportLine(line.toString());
if (conf.isValid()) {
list.add(conf);
} else {
logger.info("Invalid configuration line: " + line);
}
}
}
}
/**
* Match a media information to available audio codes for the renderer
* and return its mimetype if the match is successful. Returns null if
* the media is not natively supported by the renderer, which means it
* has to be transcoded.
* @param media The media information
* @return The mimetype or null if no match was found.
*/
public String match(DLNAMediaInfo media) {
if (media.getFirstAudioTrack() == null) {
// no sound
return match(media.getContainer(), media.getCodecV(), null, 0, 0, media.getBitrate(), media.getWidth(), media.getHeight(), media.getExtras());
} else {
String finalMimeType = null;
for (DLNAMediaAudio audio : media.getAudioCodes()) {
String mimeType = match(media.getContainer(), media.getCodecV(), audio.getCodecA(), audio.getNrAudioChannels(), audio.getSampleRate(), media.getBitrate(), media.getWidth(), media.getHeight(), media.getExtras());
finalMimeType = mimeType;
if (mimeType == null) // if at least one audio track is not compatible, the file must be transcoded.
{
return null;
}
}
return finalMimeType;
}
}
public String match(String container, String videocodec, String audiocodec) {
return match(container, videocodec, audiocodec, 0, 0, 0, 0, 0, null);
}
public String match(String container, String videocodec, String audiocodec, int nbAudioChannels, int frequency, int bitrate, int videowidth, int videoheight, Map extras) {
String matchedMimeType = null;
for (Supports conf : list) {
if (conf.match(container, videocodec, audiocodec, nbAudioChannels, frequency, bitrate, videowidth, videoheight, extras)) {
matchedMimeType = conf.mimetype;
break;
}
}
return matchedMimeType;
}
private Supports parseSupportLine(String line) {
StringTokenizer st = new StringTokenizer(line, "\t ");
Supports conf = new Supports();
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.startsWith("f:")) {
conf.format = token.substring(2).trim();
} else if (token.startsWith("v:")) {
conf.videocodec = token.substring(2).trim();
} else if (token.startsWith("a:")) {
conf.audiocodec = token.substring(2).trim();
} else if (token.startsWith("n:")) {
conf.maxnbchannels = token.substring(2).trim();
} else if (token.startsWith("s:")) {
conf.maxfrequency = token.substring(2).trim();
} else if (token.startsWith("w:")) {
conf.maxvideowidth = token.substring(2).trim();
} else if (token.startsWith("h:")) {
conf.maxvideoheight = token.substring(2).trim();
} else if (token.startsWith("m:")) {
conf.mimetype = token.substring(2).trim();
} else if (token.startsWith("b:")) {
conf.maxbitrate = token.substring(2).trim();
} else if (token.contains(":")) {
// extra mediainfo stuff
if (conf.miExtras == null) {
conf.miExtras = new HashMap();
}
String key = token.substring(0, token.indexOf(":"));
String value = token.substring(token.indexOf(":") + 1);
conf.miExtras.put(key, Pattern.compile(value));
}
}
return conf;
}
}