Search in sources :

Example 6 with Format

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));
}
Also used : DLNAMediaAudio(net.pms.dlna.DLNAMediaAudio) Format(net.pms.formats.Format) MPG(net.pms.formats.MPG) DLNAMediaInfo(net.pms.dlna.DLNAMediaInfo) RendererConfiguration(net.pms.configuration.RendererConfiguration) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 7 with Format

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;
}
Also used : ImageFormat(net.pms.image.ImageFormat) SimpleDateFormat(java.text.SimpleDateFormat) Format(net.pms.formats.Format) PmsConfiguration(net.pms.configuration.PmsConfiguration) OutputParams(net.pms.io.OutputParams)

Example 8 with Format

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;
}
Also used : ImageFormat(net.pms.image.ImageFormat) SimpleDateFormat(java.text.SimpleDateFormat) Format(net.pms.formats.Format)

Example 9 with Format

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;
}
Also used : DLNAMediaSubtitle(net.pms.dlna.DLNAMediaSubtitle) Format(net.pms.formats.Format)

Example 10 with Format

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;
}
Also used : DLNAMediaSubtitle(net.pms.dlna.DLNAMediaSubtitle) Format(net.pms.formats.Format)

Aggregations

Format (net.pms.formats.Format)17 Test (org.junit.Test)6 ArrayList (java.util.ArrayList)5 DLNAMediaInfo (net.pms.dlna.DLNAMediaInfo)5 RendererConfiguration (net.pms.configuration.RendererConfiguration)4 DLNAMediaAudio (net.pms.dlna.DLNAMediaAudio)4 MPG (net.pms.formats.MPG)4 SimpleDateFormat (java.text.SimpleDateFormat)3 OutputParams (net.pms.io.OutputParams)3 File (java.io.File)2 IOException (java.io.IOException)2 PmsConfiguration (net.pms.configuration.PmsConfiguration)2 DLNAMediaSubtitle (net.pms.dlna.DLNAMediaSubtitle)2 MP3 (net.pms.formats.audio.MP3)2 ImageFormat (net.pms.image.ImageFormat)2 FileInputStream (java.io.FileInputStream)1 InputStream (java.io.InputStream)1 OutputStream (java.io.OutputStream)1 MalformedURLException (java.net.MalformedURLException)1 Socket (java.net.Socket)1