use of net.pms.formats.Format in project UniversalMediaServer by UniversalMediaServer.
the class FormatRecognitionTest method testPlaystationVideoMpgCompatibility.
/**
* Test the compatibility of the Playstation 3 with the MPG format.
*/
@Test
public void testPlaystationVideoMpgCompatibility() {
// This test is only useful if the MediaInfo library is available
assumeTrue(mediaInfoParserIsValid);
RendererConfiguration conf = RendererConfiguration.getRendererConfigurationByName("Playstation 3");
assertNotNull("Renderer named \"Playstation 3\" found.", conf);
// Construct regular two channel MPG information
DLNAMediaInfo info = new DLNAMediaInfo();
info.setContainer("avi");
DLNAMediaAudio audio = new DLNAMediaAudio();
audio.setCodecA("ac3");
audio.getAudioProperties().setNumberOfChannels(5);
List<DLNAMediaAudio> audioCodes = new ArrayList<>();
audioCodes.add(audio);
info.setAudioTracksList(audioCodes);
info.setCodecV("mp4");
Format format = new MPG();
format.match("test.avi");
assertEquals("PS3 is compatible with MPG", true, conf.isCompatible(info, format, configuration));
// Construct MPG with wmv codec that the PS3 does not support natively
info.setCodecV("wmv");
assertEquals("PS3 is incompatible with MPG with wmv codec", false, conf.isCompatible(info, format, configuration));
}
use of net.pms.formats.Format in project UniversalMediaServer by UniversalMediaServer.
the class DLNAResource method resolvePlayer.
/**
* Determine whether we are a candidate for streaming or transcoding to the
* given renderer, and return the relevant player or null as appropriate.
*
* @param renderer The target renderer
* @return A player if transcoding or null if streaming
*/
public Player resolvePlayer(RendererConfiguration renderer) {
// Use device-specific pms conf, if any
PmsConfiguration configurationSpecificToRenderer = PMS.getConfiguration(renderer);
boolean parserV2 = media != null && renderer != null && renderer.isUseMediaInfo();
Player resolvedPlayer = null;
if (media == null) {
media = new DLNAMediaInfo();
}
if (format == null) {
// Shouldn't happen, this is just a desperate measure
Format f = FormatFactory.getAssociatedFormat(getSystemName());
setFormat(f != null ? f : FormatFactory.getAssociatedFormat(".mpg"));
}
// Check if we're a transcode folder item
if (isNoName() && (getParent() instanceof FileTranscodeVirtualFolder)) {
// Yes, leave everything as-is
resolvedPlayer = getPlayer();
LOGGER.trace("Selecting player {} based on transcode item settings", resolvedPlayer);
return resolvedPlayer;
}
boolean hasSubsToTranscode = false;
boolean hasEmbeddedSubs = false;
for (DLNAMediaSubtitle s : media.getSubtitleTracksList()) {
hasEmbeddedSubs = (hasEmbeddedSubs || s.isEmbedded());
}
/**
* At this stage, we know the media is compatible with the renderer based on its
* "Supported" lines, and can therefore be streamed to the renderer without a
* player. However, other details about the media can change this, such as
* whether it has subtitles that match this user's language settings, so here we
* perform those checks.
*/
if (format.isVideo() && !configurationSpecificToRenderer.isDisableSubtitles()) {
if (hasEmbeddedSubs || hasExternalSubtitles()) {
OutputParams params = new OutputParams(configurationSpecificToRenderer);
// set proper subtitles in accordance with user setting
Player.setAudioAndSubs(getSystemName(), media, params);
if (params.sid != null) {
if (params.sid.isExternal()) {
if (renderer != null && renderer.isExternalSubtitlesFormatSupported(params.sid, media)) {
media_subtitle = params.sid;
media_subtitle.setSubsStreamable(true);
LOGGER.trace("This video has external subtitles that could be streamed");
} else {
hasSubsToTranscode = true;
LOGGER.trace("This video has external subtitles that should be transcoded");
}
} else if (params.sid.isEmbedded()) {
if (renderer != null && renderer.isEmbeddedSubtitlesFormatSupported(params.sid)) {
LOGGER.trace("This video has embedded subtitles that could be streamed");
} else {
hasSubsToTranscode = true;
LOGGER.trace("This video has embedded subtitles that should be transcoded");
}
}
}
} else {
LOGGER.trace("This video does not have subtitles");
}
}
if (configurationSpecificToRenderer.isDisableTranscoding()) {
LOGGER.trace("Final verdict: \"{}\" will be streamed since transcoding is disabled", getName());
return null;
}
String configurationSkipExtensions = configurationSpecificToRenderer.getDisableTranscodeForExtensions();
String rendererSkipExtensions = renderer == null ? null : renderer.getStreamedExtensions();
// Should transcoding be skipped for this format?
skipTranscode = format.skip(configurationSkipExtensions, rendererSkipExtensions);
if (skipTranscode) {
LOGGER.trace("Final verdict: \"{}\" will be streamed since it is forced by configuration", getName());
return null;
}
// Try to match a player based on media information and format.
resolvedPlayer = PlayerFactory.getPlayer(this);
if (resolvedPlayer != null) {
String configurationForceExtensions = configurationSpecificToRenderer.getForceTranscodeForExtensions();
String rendererForceExtensions = null;
if (renderer != null) {
rendererForceExtensions = renderer.getTranscodedExtensions();
}
// Should transcoding be forced for this format?
boolean forceTranscode = format.skip(configurationForceExtensions, rendererForceExtensions);
boolean isIncompatible = false;
String prependTraceReason = "File \"{}\" will not be streamed because ";
if (forceTranscode) {
LOGGER.trace(prependTraceReason + "transcoding is forced by configuration", getName());
} else if (this instanceof DVDISOTitle) {
forceTranscode = true;
LOGGER.trace("DVD video track \"{}\" will be transcoded because streaming isn't supported", getName());
} else if (!format.isCompatible(media, renderer)) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "it is not supported by the renderer", getName());
} else if (configurationSpecificToRenderer.isEncodedAudioPassthrough()) {
if (getMediaAudio() != null && (FormatConfiguration.AC3.equals(getMediaAudio().getAudioCodec()) || FormatConfiguration.DTS.equals(getMediaAudio().getAudioCodec()))) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the audio will use the encoded audio passthrough feature", getName());
} else {
for (DLNAMediaAudio audioTrack : media.getAudioTracksList()) {
if (audioTrack != null && (FormatConfiguration.AC3.equals(audioTrack.getAudioCodec()) || FormatConfiguration.DTS.equals(audioTrack.getAudioCodec()))) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the audio will use the encoded audio passthrough feature", getName());
break;
}
}
}
}
if (!isIncompatible && format.isVideo() && parserV2 && renderer != null) {
int maxBandwidth = renderer.getMaxBandwidth();
if (renderer.isKeepAspectRatio() && !"16:9".equals(media.getAspectRatioContainer())) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the renderer needs us to add borders to change the aspect ratio from {} to 16/9.", getName(), media.getAspectRatioContainer());
} else if (!renderer.isResolutionCompatibleWithRenderer(media.getWidth(), media.getHeight())) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the resolution is incompatible with the renderer.", getName());
} else if (media.getBitrate() > maxBandwidth) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the bitrate ({} b/s) is too high ({} b/s).", getName(), media.getBitrate(), maxBandwidth);
} else if (!renderer.isVideoBitDepthSupported(media.getVideoBitDepth())) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the video bit depth ({}) is not supported.", getName(), media.getVideoBitDepth());
} else if (renderer.isH264Level41Limited() && media.isH264()) {
if (media.getAvcLevel() != null) {
double h264Level = 4.1;
try {
h264Level = Double.parseDouble(media.getAvcLevel());
} catch (NumberFormatException e) {
LOGGER.trace("Could not convert {} to double: {}", media.getAvcLevel(), e.getMessage());
}
if (h264Level > 4.1) {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the H.264 level ({}) is not supported.", getName(), h264Level);
}
} else {
isIncompatible = true;
LOGGER.trace(prependTraceReason + "the H.264 level is unknown.", getName());
}
} else if (media.is3d() && StringUtils.isNotBlank(renderer.getOutput3DFormat()) && (!media.get3DLayout().toString().toLowerCase(Locale.ROOT).equals(renderer.getOutput3DFormat()))) {
forceTranscode = true;
LOGGER.trace("Video \"{}\" is 3D and is forced to transcode to the format \"{}\"", getName(), renderer.getOutput3DFormat());
}
}
// Prefer transcoding over streaming if:
// 1) the media is unsupported by the renderer, or
// 2) there are subs to transcode
boolean preferTranscode = isIncompatible || hasSubsToTranscode;
// 2) transcoding is preferred and not prevented by configuration
if (forceTranscode || (preferTranscode && !isSkipTranscode())) {
if (parserV2) {
LOGGER.trace("Final verdict: \"{}\" will be transcoded with player \"{}\" with mime type \"{}\"", getName(), resolvedPlayer.toString(), renderer != null ? renderer.getMimeType(mimeType(resolvedPlayer), media) : media.getMimeType());
} else {
LOGGER.trace("Final verdict: \"{}\" will be transcoded with player \"{}\"", getName(), resolvedPlayer.toString());
}
} else {
resolvedPlayer = null;
LOGGER.trace("Final verdict: \"{}\" will be streamed", getName());
}
} else {
LOGGER.trace("Final verdict: \"{}\" will be streamed because no compatible player was found", getName());
}
return resolvedPlayer;
}
use of net.pms.formats.Format in project UniversalMediaServer by UniversalMediaServer.
the class DLNAResource method autoMatch.
// Attempts to automatically create the appropriate container for
// the given uri. Defaults to mpeg video for indeterminate local uris.
public static DLNAResource autoMatch(String uri, String name) {
try {
uri = URLDecoder.decode(uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
LOGGER.error("URL decoding error ", e);
}
boolean isweb = uri.matches("\\S+://.+");
Format format = FormatFactory.getAssociatedFormat(isweb ? "." + FileUtil.getUrlExtension(uri) : uri);
int type = format == null ? Format.VIDEO : format.getType();
if (name == null) {
name = new File(StringUtils.substringBefore(uri, "?")).getName();
}
DLNAResource resource = isweb ? type == Format.VIDEO ? new WebVideoStream(name, uri, null) : type == Format.AUDIO ? new WebAudioStream(name, uri, null) : type == Format.IMAGE ? new FeedItem(name, uri, null, null, Format.IMAGE) : null : new RealFile(new File(uri));
if (format == null && !isweb) {
resource.setFormat(FormatFactory.getAssociatedFormat(".mpg"));
}
LOGGER.debug(resource == null ? ("Could not auto-match " + uri) : ("Created auto-matched container: " + resource));
return resource;
}
use of net.pms.formats.Format in project UniversalMediaServer by UniversalMediaServer.
the class AviSynthMEncoder method isCompatible.
/**
* {@inheritDoc}
*/
@Override
public boolean isCompatible(DLNAResource resource) {
Format format = resource.getFormat();
if (format != null) {
if (format.getIdentifier() == Format.Identifier.WEB) {
return false;
}
}
DLNAMediaSubtitle subtitle = resource.getMediaSubtitle();
// Uninitialized DLNAMediaSubtitle objects have a null language.
if (subtitle != null && subtitle.getLang() != null) {
// This engine only supports external subtitles
if (subtitle.getExternalFile() != null) {
return true;
}
return false;
}
try {
String audioTrackName = resource.getMediaAudio().toString();
String defaultAudioTrackName = resource.getMedia().getAudioTracksList().get(0).toString();
if (!audioTrackName.equals(defaultAudioTrackName)) {
// This engine only supports playback of the default audio track
return false;
}
} catch (NullPointerException e) {
LOGGER.trace("AviSynth/MEncoder cannot determine compatibility based on audio track for " + resource.getSystemName());
} catch (IndexOutOfBoundsException e) {
LOGGER.trace("AviSynth/MEncoder cannot determine compatibility based on default audio track for " + resource.getSystemName());
}
if (PlayerUtil.isVideo(resource, Format.Identifier.MKV) || PlayerUtil.isVideo(resource, Format.Identifier.MPG) || PlayerUtil.isVideo(resource, Format.Identifier.OGG)) {
return true;
}
return false;
}
use of net.pms.formats.Format in project UniversalMediaServer by UniversalMediaServer.
the class AviSynthFFmpeg method isCompatible.
/**
* {@inheritDoc}
*/
@Override
public boolean isCompatible(DLNAResource resource) {
Format format = resource.getFormat();
if (format != null) {
if (format.getIdentifier() == Format.Identifier.WEB) {
return false;
}
}
DLNAMediaSubtitle subtitle = resource.getMediaSubtitle();
// uninitialized DLNAMediaSubtitle objects have a null language.
if (subtitle != null && subtitle.getLang() != null) {
// The resource needs a subtitle, but this engine implementation does not support subtitles yet
return false;
}
try {
String audioTrackName = resource.getMediaAudio().toString();
String defaultAudioTrackName = resource.getMedia().getAudioTracksList().get(0).toString();
if (!audioTrackName.equals(defaultAudioTrackName)) {
// This engine implementation only supports playback of the default audio track at this time
return false;
}
} catch (NullPointerException e) {
LOGGER.trace("AviSynth/FFmpeg cannot determine compatibility based on audio track for " + resource.getSystemName());
} catch (IndexOutOfBoundsException e) {
LOGGER.trace("AviSynth/FFmpeg cannot determine compatibility based on default audio track for " + resource.getSystemName());
}
if (PlayerUtil.isVideo(resource, Format.Identifier.MKV) || PlayerUtil.isVideo(resource, Format.Identifier.MPG) || PlayerUtil.isVideo(resource, Format.Identifier.OGG)) {
return true;
}
return false;
}
Aggregations