Package net.pms.encoders

Source Code of net.pms.encoders.FFmpegWebVideo

/*
* PS3 Media Server, for streaming any medias to your PS3.
* Copyright (C) 2008-2012 A.Brochard
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package net.pms.encoders;

import net.pms.configuration.PmsConfiguration;
import net.pms.configuration.RendererConfiguration;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAResource;
import net.pms.formats.Format;
import net.pms.formats.FormatFactory;
import net.pms.formats.WEB;
import net.pms.io.OutputParams;
import net.pms.io.PipeProcess;
import net.pms.io.ProcessWrapper;
import net.pms.io.ProcessWrapperImpl;
import net.pms.util.PlayerUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

import static org.apache.commons.lang3.StringUtils.isNotEmpty;

public class FFmpegWebVideo extends FFmpegVideo {
  private static final Logger logger = LoggerFactory.getLogger(FFmpegWebVideo.class);
  private final PmsConfiguration configuration;
  private final FFmpegProtocols protocols;

  // FIXME we have an id() accessor for this; no need for the field to be public
  @Deprecated
  public static final String ID = "ffmpegwebvideo";

  public FFmpegWebVideo(PmsConfiguration configuration) {
    super(configuration);
    this.configuration = configuration;
    this.protocols = getProtocols(); // fetch/create the FFmpegProtocols singleton
  }

  // use FFmpegWebVideo(PmsConfiguration)
  @Deprecated
  public FFmpegWebVideo(PmsConfiguration configuration, FFmpegProtocols protocols) {
    this(configuration);
  }

  @Override
  public JComponent config() {
    return null;
  }

  @Override
  public String id() {
    return ID;
  }

  @Override
  public PlayerPurpose getPurpose() {
    return PlayerPurpose.VIDEO_WEB_STREAM_PLAYER;
  }

  @Override
  public boolean isTimeSeekable() {
    return false;
  }

  @Override
  public synchronized ProcessWrapper launchTranscode(
    DLNAResource dlna,
    DLNAMediaInfo media,
    OutputParams params
  ) throws IOException {
    params.minBufferSize = params.minFileSize;
    params.secondread_minsize = 100000;
    params.waitbeforestart = 6000;

    RendererConfiguration renderer = params.mediaRenderer;
    String filename = protocols.getFilename(dlna.getSystemName());
    FFmpegOptions customOptions = new FFmpegOptions();

    // (HTTP) header options
    if (params.header != null && params.header.length > 0) {
      String hdr = new String(params.header);
      customOptions.addAll(parseOptions(hdr));
    }

    // renderer options
    if (isNotEmpty(renderer.getCustomFFmpegOptions())) {
      customOptions.addAll(parseOptions(renderer.getCustomFFmpegOptions()));
    }

    // basename of the named pipe:
    // ffmpeg -global-options -input-options -i URL -output-options /path/to/fifoName
    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);
    pipe.deleteLater(); // delete the named pipe later; harmless if it isn't created
    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;

    // Build the command line
    final List<String> cmdList = new ArrayList<String>();
    cmdList.add(executable());
    cmdList.addAll(getGlobalOptions(logger));

    int nThreads = configuration.getNumberOfCpuCores();

    // Decoder threads
    cmdList.add("-threads");
    cmdList.add("" + nThreads);

    // Add global and input-file custom options, if any
    if (!customOptions.isEmpty()) {
      customOptions.transferGlobals(cmdList);
      customOptions.transferInputFileOptions(cmdList);
    }

    cmdList.add("-i");
    cmdList.add(filename);

    cmdList.addAll(getVideoFilterOptions(dlna, media, params));

    // Encoder threads
    cmdList.add("-threads");
    cmdList.add("" + nThreads);

    // Add the output options (-f, -acodec, -vcodec)
    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);
    }

    // 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);
    pw.attachProcess(mkfifo_process); // Clean up the mkfifo process when the transcode ends

    // 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);
    }

    return pw;
  }

  @Override
  public String name() {
    return "FFmpeg Web Video";
  }

  // TODO remove this when it's removed from Player
  @Deprecated
  @Override
  public String[] args() {
    return null;
  }

  @Override
  public boolean isCompatible(DLNAResource dlna) {
    if (!PlayerUtil.isWebVideo(dlna)) {
      return false;
    }

    String protocol = dlna.getFormat().getMatchedExtension();
    return protocols.isSupportedProtocol(protocol);
  }
}
TOP

Related Classes of net.pms.encoders.FFmpegWebVideo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.