Search in sources :

Example 11 with RendererConfiguration

use of net.pms.configuration.RendererConfiguration in project UniversalMediaServer by UniversalMediaServer.

the class modAwareHashMap method launchTranscode.

@Override
public ProcessWrapper launchTranscode(DLNAResource dlna, DLNAMediaInfo media, OutputParams params) throws IOException {
    params.minBufferSize = params.minFileSize;
    params.secondread_minsize = 100000;
    // Use device-specific pms conf
    PmsConfiguration prev = configuration;
    configuration = (DeviceConfiguration) params.mediaRenderer;
    RendererConfiguration renderer = params.mediaRenderer;
    String filename = dlna.getFileName();
    setAudioAndSubs(filename, media, params);
    // XXX work around an ffmpeg bug: http://ffmpeg.org/trac/ffmpeg/ticket/998
    if (filename.startsWith("mms:")) {
        filename = "mmsh:" + filename.substring(4);
    }
    // check if we have modifier for this url
    String r = replacements.match(filename);
    if (r != null) {
        filename = filename.replaceAll(r, replacements.get(r));
        LOGGER.debug("modified url: " + filename);
    }
    FFmpegOptions customOptions = new FFmpegOptions();
    // Gather custom options from various sources in ascending priority:
    // - automatic options
    String match = autoOptions.match(filename);
    if (match != null) {
        List<String> opts = autoOptions.get(match);
        if (opts != null) {
            customOptions.addAll(opts);
        }
    }
    // - (http) header options
    if (params.header != null && params.header.length > 0) {
        String hdr = new String(params.header);
        customOptions.addAll(parseOptions(hdr));
    }
    // - attached options
    String attached = (String) dlna.getAttachment(ID);
    if (attached != null) {
        customOptions.addAll(parseOptions(attached));
    }
    // - renderer options
    String ffmpegOptions = renderer.getCustomFFmpegOptions();
    if (StringUtils.isNotEmpty(ffmpegOptions)) {
        customOptions.addAll(parseOptions(ffmpegOptions));
    }
    // Build the command line
    List<String> cmdList = new ArrayList<>();
    if (!dlna.isURLResolved()) {
        URLResult r1 = ExternalFactory.resolveURL(filename);
        if (r1 != null) {
            if (r1.precoder != null) {
                filename = "-";
                if (Platform.isWindows()) {
                    cmdList.add("cmd.exe");
                    cmdList.add("/C");
                }
                cmdList.addAll(r1.precoder);
                cmdList.add("|");
            } else {
                if (StringUtils.isNotEmpty(r1.url)) {
                    filename = r1.url;
                }
            }
            if (r1.args != null && r1.args.size() > 0) {
                customOptions.addAll(r1.args);
            }
        }
    }
    cmdList.add(executable());
    // XXX squashed bug - without this, ffmpeg hangs waiting for a confirmation
    // that it can write to a file that already exists i.e. the named pipe
    cmdList.add("-y");
    cmdList.add("-loglevel");
    if (LOGGER.isTraceEnabled()) {
        // Set -loglevel in accordance with LOGGER setting
        // Could be changed to "verbose" or "debug" if "info" level is not enough
        cmdList.add("info");
    } else {
        cmdList.add("warning");
    }
    /*
		 * FFmpeg uses multithreading by default, so provided that the
		 * user has not disabled FFmpeg multithreading and has not
		 * chosen to use more or less threads than are available, do not
		 * specify how many cores to use.
		 */
    int nThreads = 1;
    if (configuration.isFfmpegMultithreading()) {
        if (Runtime.getRuntime().availableProcessors() == configuration.getNumberOfCpuCores()) {
            nThreads = 0;
        } else {
            nThreads = configuration.getNumberOfCpuCores();
        }
    }
    // Decoder threads
    if (nThreads > 0) {
        cmdList.add("-threads");
        cmdList.add("" + nThreads);
    }
    // Add global and input-file custom options, if any
    if (!customOptions.isEmpty()) {
        customOptions.transferGlobals(cmdList);
        customOptions.transferInputFileOptions(cmdList);
    }
    if (params.timeseek > 0) {
        cmdList.add("-ss");
        cmdList.add("" + (int) params.timeseek);
    }
    cmdList.add("-i");
    cmdList.add(filename);
    cmdList.addAll(getVideoFilterOptions(dlna, media, params));
    // Encoder threads
    if (nThreads > 0) {
        cmdList.add("-threads");
        cmdList.add("" + nThreads);
    }
    // Add the output options (-f, -c:a, -c:v, etc.)
    // Now that inputs and filtering are complete, see if we should
    // give the renderer the final say on the command
    boolean override = false;
    if (renderer instanceof RendererConfiguration.OutputOverride) {
        override = ((RendererConfiguration.OutputOverride) renderer).getOutputOptions(cmdList, dlna, this, params);
    }
    if (!override) {
        cmdList.addAll(getVideoTranscodeOptions(dlna, media, params));
        // Add video bitrate options
        cmdList.addAll(getVideoBitrateOptions(dlna, media, params));
        // Add audio bitrate options
        cmdList.addAll(getAudioBitrateOptions(dlna, media, params));
        // Add any remaining custom options
        if (!customOptions.isEmpty()) {
            customOptions.transferAll(cmdList);
        }
    }
    // Set up the process
    // basename of the named pipe:
    String fifoName = String.format("ffmpegwebvideo_%d_%d", Thread.currentThread().getId(), System.currentTimeMillis());
    // This process wraps the command that creates the named pipe
    PipeProcess pipe = new PipeProcess(fifoName);
    // delete the named pipe later; harmless if it isn't created
    pipe.deleteLater();
    ProcessWrapper mkfifo_process = pipe.getPipeProcess();
    /**
     * It can take a long time for Windows to create a named pipe (and
     * mkfifo can be slow if /tmp isn't memory-mapped), so run this in
     * the current thread.
     */
    mkfifo_process.runInSameThread();
    params.input_pipes[0] = pipe;
    // Output file
    cmdList.add(pipe.getInputPipe());
    // Convert the command list to an array
    String[] cmdArray = new String[cmdList.size()];
    cmdList.toArray(cmdArray);
    // Hook to allow plugins to customize this command line
    cmdArray = finalizeTranscoderArgs(filename, dlna, media, params, cmdArray);
    // Now launch FFmpeg
    ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, params);
    // Better late than never
    parseMediaInfo(filename, dlna, pw);
    // Clean up the mkfifo process when the transcode ends
    pw.attachProcess(mkfifo_process);
    // Give the mkfifo process a little time
    try {
        Thread.sleep(300);
    } catch (InterruptedException e) {
        LOGGER.error("Thread interrupted while waiting for named pipe to be created", e);
    }
    // Launch the transcode command...
    pw.runInNewThread();
    // ...and wait briefly to allow it to start
    try {
        Thread.sleep(200);
    } catch (InterruptedException e) {
        LOGGER.error("Thread interrupted while waiting for transcode to start", e);
    }
    configuration = prev;
    return pw;
}
Also used : PipeProcess(net.pms.io.PipeProcess) ArrayList(java.util.ArrayList) URLResult(net.pms.external.URLResolver.URLResult) ProcessWrapper(net.pms.io.ProcessWrapper) PmsConfiguration(net.pms.configuration.PmsConfiguration) RendererConfiguration(net.pms.configuration.RendererConfiguration) ProcessWrapperImpl(net.pms.io.ProcessWrapperImpl)

Example 12 with RendererConfiguration

use of net.pms.configuration.RendererConfiguration in project UniversalMediaServer by UniversalMediaServer.

the class FormatRecognitionTest method testPlaystationVideoMkvCompatibility.

/**
 * Test the compatibility of the Playstation 3 with the MPG format.
 */
@Test
public void testPlaystationVideoMkvCompatibility() {
    // 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 MKV information
    DLNAMediaInfo info = new DLNAMediaInfo();
    info.setContainer("mkv");
    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.mkv");
    assertEquals("PS3 is incompatible with MKV", 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 13 with RendererConfiguration

use of net.pms.configuration.RendererConfiguration in project UniversalMediaServer by UniversalMediaServer.

the class FormatRecognitionTest method testRendererConfigurationBasics.

/**
 * Test some basic functionality of {@link RendererConfiguration#isCompatible(DLNAMediaInfo, Format)}
 */
@Test
public void testRendererConfigurationBasics() {
    // 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);
    assertEquals("With nothing provided isCompatible() should return false", false, conf.isCompatible(null, null, configuration));
}
Also used : RendererConfiguration(net.pms.configuration.RendererConfiguration) Test(org.junit.Test)

Example 14 with RendererConfiguration

use of net.pms.configuration.RendererConfiguration 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 15 with RendererConfiguration

use of net.pms.configuration.RendererConfiguration in project UniversalMediaServer by UniversalMediaServer.

the class PlayerControlHandler method getRenderers.

public String getRenderers(InetAddress client) {
    Logical player = selectedPlayers.get(client);
    RendererConfiguration selected = player != null ? player.renderer : getDefaultRenderer();
    ArrayList<String> json = new ArrayList<>();
    for (RendererConfiguration r : RendererConfiguration.getConnectedControlPlayers()) {
        json.add(String.format("[\"%s\",%d,\"%s\"]", (r instanceof WebRender) ? r.uuid : r, r == selected ? 1 : 0, r.uuid));
    }
    return "\"renderers\":[" + StringUtils.join(json, ",") + "]";
}
Also used : WebRender(net.pms.configuration.WebRender) RendererConfiguration(net.pms.configuration.RendererConfiguration) Logical(net.pms.util.BasicPlayer.Logical)

Aggregations

RendererConfiguration (net.pms.configuration.RendererConfiguration)24 ArrayList (java.util.ArrayList)10 IOException (java.io.IOException)5 Test (org.junit.Test)5 InetAddress (java.net.InetAddress)4 DLNAMediaInfo (net.pms.dlna.DLNAMediaInfo)4 Format (net.pms.formats.Format)4 UnknownHostException (java.net.UnknownHostException)3 PmsConfiguration (net.pms.configuration.PmsConfiguration)3 WebRender (net.pms.configuration.WebRender)3 DLNAMediaAudio (net.pms.dlna.DLNAMediaAudio)3 ExternalListener (net.pms.external.ExternalListener)3 MPG (net.pms.formats.MPG)3 InetSocketAddress (java.net.InetSocketAddress)2 StringTokenizer (java.util.StringTokenizer)2 DeviceConfiguration (net.pms.configuration.DeviceConfiguration)2 InputFile (net.pms.dlna.InputFile)2 StartStopListener (net.pms.external.StartStopListener)2 MP3 (net.pms.formats.audio.MP3)2 KeyedComboBoxModel (net.pms.util.KeyedComboBoxModel)2