use of net.pms.configuration.PmsConfiguration 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;
}
use of net.pms.configuration.PmsConfiguration in project UniversalMediaServer by UniversalMediaServer.
the class MEncoderVideo method addMaximumBitrateConstraints.
/**
* Note: This is not exact. The bitrate can go above this but it is generally pretty good.
*
* @return The maximum bitrate the video should be along with the buffer size using MEncoder vars
*/
private String addMaximumBitrateConstraints(String encodeSettings, DLNAMediaInfo media, String quality, RendererConfiguration mediaRenderer, String audioType) {
// Use device-specific pms conf
PmsConfiguration configuration = PMS.getConfiguration(mediaRenderer);
int[] defaultMaxBitrates = getVideoBitrateConfig(configuration.getMaximumBitrate());
int[] rendererMaxBitrates = new int[2];
if (isNotEmpty(mediaRenderer.getMaxVideoBitrate())) {
rendererMaxBitrates = getVideoBitrateConfig(mediaRenderer.getMaxVideoBitrate());
}
// Give priority to the renderer's maximum bitrate setting over the user's setting
if (rendererMaxBitrates[0] > 0 && rendererMaxBitrates[0] < defaultMaxBitrates[0]) {
LOGGER.trace("Using video bitrate limit from {} configuration ({} Mb/s) because " + "it is lower than the general configuration bitrate limit ({} Mb/s)", mediaRenderer.getRendererName(), rendererMaxBitrates[0], defaultMaxBitrates[0]);
defaultMaxBitrates = rendererMaxBitrates;
} else {
LOGGER.trace("Using video bitrate limit from the general configuration ({} Mb/s)", defaultMaxBitrates[0]);
}
if (mediaRenderer.getCBRVideoBitrate() == 0 && !quality.contains("vrc_buf_size") && !quality.contains("vrc_maxrate") && !quality.contains("vbitrate")) {
// Convert value from Mb to Kb
defaultMaxBitrates[0] = 1000 * defaultMaxBitrates[0];
if (mediaRenderer.isHalveBitrate()) {
defaultMaxBitrates[0] /= 2;
LOGGER.trace("Halving the video bitrate limit to {} kb/s", defaultMaxBitrates[0]);
}
int bufSize = 1835;
boolean bitrateLevel41Limited = false;
boolean isXboxOneWebVideo = mediaRenderer.isXboxOne() && purpose() == VIDEO_WEBSTREAM_PLAYER;
/**
* Although the maximum bitrate for H.264 Level 4.1 is
* officially 50,000 kbit/s, some 4.1-capable renderers
* like the PS3 stutter when video exceeds roughly 31,250
* kbit/s.
*
* We also apply the correct buffer size in this section.
*/
if ((mediaRenderer.isTranscodeToH264() || mediaRenderer.isTranscodeToH265()) && !isXboxOneWebVideo) {
if (mediaRenderer.isH264Level41Limited() && defaultMaxBitrates[0] > 31250) {
defaultMaxBitrates[0] = 31250;
bitrateLevel41Limited = true;
LOGGER.trace("Adjusting the video bitrate limit to the H.264 Level 4.1-safe value of 31250 kb/s");
}
bufSize = defaultMaxBitrates[0];
} else {
if (media.isHDVideo()) {
bufSize = defaultMaxBitrates[0] / 3;
}
if (bufSize > 7000) {
bufSize = 7000;
}
if (defaultMaxBitrates[1] > 0) {
bufSize = defaultMaxBitrates[1];
}
if (mediaRenderer.isDefaultVBVSize() && rendererMaxBitrates[1] == 0) {
bufSize = 1835;
}
}
if (!bitrateLevel41Limited) {
// Make room for audio
switch(audioType) {
case "pcm":
defaultMaxBitrates[0] -= 4600;
break;
case "dts":
defaultMaxBitrates[0] -= 1510;
break;
case "aac":
case "ac3":
defaultMaxBitrates[0] -= configuration.getAudioBitrate();
break;
default:
break;
}
// Round down to the nearest Mb
defaultMaxBitrates[0] = defaultMaxBitrates[0] / 1000 * 1000;
LOGGER.trace("Adjusting the video bitrate limit to {} kb/s to make room for audio", defaultMaxBitrates[0]);
}
encodeSettings += ":vrc_maxrate=" + defaultMaxBitrates[0] + ":vrc_buf_size=" + bufSize;
}
return encodeSettings;
}
use of net.pms.configuration.PmsConfiguration in project UniversalMediaServer by UniversalMediaServer.
the class DCRaw method getThumbnail.
/**
* Extracts or generates a thumbnail for {@code fileName}.
*
* @param params the {@link OutputParams} to use. Can be {@code null}.
* @param fileName the path of the image file to process.
* @param imageInfo the {@link ImageInfo} for the image file.
* @return A byte array containing the thumbnail or {@code null}.
* @throws IOException if an IO error occurs.
*/
@Override
public byte[] getThumbnail(OutputParams params, String fileName, ImageInfo imageInfo) {
boolean trace = LOGGER.isTraceEnabled();
if (trace) {
LOGGER.trace("Extracting thumbnail from \"{}\" with DCRaw", fileName);
}
if (params == null) {
params = new OutputParams(PMS.getConfiguration());
}
// Use device-specific pms conf
PmsConfiguration configuration = PMS.getConfiguration(params);
params.log = false;
// This is a wild guess at a decent buffer size for an embedded thumbnail.
// Every time the buffer has to grow, the whole buffer must be copied in memory.
params.outputByteArrayStreamBufferSize = 150000;
// First try to get the embedded thumbnail
String[] cmdArray = new String[6];
cmdArray[0] = configuration.getDCRawPath();
cmdArray[1] = "-e";
cmdArray[2] = "-c";
cmdArray[3] = "-M";
cmdArray[4] = "-w";
cmdArray[5] = fileName;
ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, true, params, false, true);
pw.runInSameThread();
byte[] bytes = pw.getOutputByteArray().toByteArray();
List<String> results = pw.getResults();
if (bytes.length > 0) {
// DCRaw doesn't seem to apply Exif Orientation to embedded thumbnails, handle it
boolean isJPEG = (bytes[0] & 0xFF) == 0xFF && (bytes[1] & 0xFF) == 0xD8;
ExifOrientation thumbnailOrientation = null;
Dimension jpegResolution = null;
int exifOrientationOffset = -1;
if (isJPEG) {
try {
ByteArrayReader reader = new ByteArrayReader(bytes);
exifOrientationOffset = ImagesUtil.getJPEGExifIFDTagOffset(0x112, reader);
jpegResolution = ImagesUtil.getJPEGResolution(reader);
} catch (IOException e) {
exifOrientationOffset = -1;
LOGGER.debug("Unexpected error while trying to find Exif orientation offset in embedded thumbnail for \"{}\": {}", fileName, e.getMessage());
LOGGER.trace("", e);
}
if (exifOrientationOffset > 0) {
thumbnailOrientation = ExifOrientation.typeOf(bytes[exifOrientationOffset]);
} else {
LOGGER.debug("Couldn't find Exif orientation in the thumbnail extracted from \"{}\"", fileName);
}
}
ExifOrientation imageOrientation = imageInfo instanceof ExifInfo ? ((ExifInfo) imageInfo).getOriginalExifOrientation() : null;
if (imageOrientation != null && imageOrientation != thumbnailOrientation) {
if (thumbnailOrientation != null) {
if (imageInfo.getWidth() > 0 && imageInfo.getHeight() > 0 && jpegResolution != null && jpegResolution.getWidth() > 0 && jpegResolution.getHeight() > 0) {
// Try to determine which orientation to trust
double imageAspect, thumbnailAspect;
if (ImagesUtil.isExifAxesSwapNeeded(imageOrientation)) {
imageAspect = (double) imageInfo.getHeight() / imageInfo.getWidth();
} else {
imageAspect = (double) imageInfo.getWidth() / imageInfo.getHeight();
}
if (ImagesUtil.isExifAxesSwapNeeded(thumbnailOrientation)) {
thumbnailAspect = (double) jpegResolution.getHeight() / jpegResolution.getWidth();
} else {
thumbnailAspect = (double) jpegResolution.getWidth() / jpegResolution.getHeight();
}
if (Math.abs(imageAspect - thumbnailAspect) > 0.001d) {
// The image and the thumbnail seems to have different aspect ratios, use that of the image
bytes[exifOrientationOffset] = (byte) imageOrientation.getValue();
}
}
} else if (imageOrientation != ExifOrientation.TOP_LEFT) {
// Apply the orientation to the thumbnail
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Thumbnails.of(new ByteArrayInputStream(bytes)).scale(1.0d).addFilter(ExifFilterUtils.getFilterForOrientation(imageOrientation.getThumbnailatorOrientation())).outputFormat(// PNG here to avoid further degradation from rotation
"PNG").outputQuality(1.0f).toOutputStream(outputStream);
bytes = outputStream.toByteArray();
} catch (IOException e) {
LOGGER.error("Unexpected error when trying to rotate thumbnail for \"{}\" - cancelling rotation: {}", fileName, e.getMessage());
LOGGER.trace("", e);
}
}
}
}
if (bytes.length == 0 || !results.isEmpty() && results.get(0).contains("has no thumbnail")) {
// No embedded thumbnail retrieved, generate thumbnail from the actual file
if (trace) {
LOGGER.trace("No embedded thumbnail found in \"{}\", " + "trying to generate thumbnail from the image itself", fileName);
}
params.outputByteArrayStreamBufferSize = imageInfo != null && imageInfo.getSize() != ImageInfo.SIZE_UNKNOWN ? (int) imageInfo.getSize() / 4 : 500000;
cmdArray[1] = "-h";
pw = new ProcessWrapperImpl(cmdArray, true, params);
pw.runInSameThread();
bytes = pw.getOutputByteArray().toByteArray();
}
if (trace && (bytes == null || bytes.length == 0)) {
LOGGER.trace("Failed to generate thumbnail with DCRaw for image \"{}\"", fileName);
}
return bytes != null && bytes.length > 0 ? bytes : null;
}
use of net.pms.configuration.PmsConfiguration in project UniversalMediaServer by UniversalMediaServer.
the class FFmpegAudio method launchTranscode.
@Override
public synchronized ProcessWrapper launchTranscode(DLNAResource dlna, DLNAMediaInfo media, OutputParams params) throws IOException {
PmsConfiguration prev = configuration;
// Use device-specific pms conf
configuration = (DeviceConfiguration) params.mediaRenderer;
final String filename = dlna.getFileName();
params.maxBufferSize = configuration.getMaxAudioBuffer();
params.waitbeforestart = 2000;
params.manageFastStart();
/*
* 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();
}
}
List<String> cmdList = new ArrayList<>();
cmdList.add(executable());
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");
}
if (params.timeseek > 0) {
cmdList.add("-ss");
cmdList.add("" + params.timeseek);
}
// Decoder threads
if (nThreads > 0) {
cmdList.add("-threads");
cmdList.add("" + nThreads);
}
cmdList.add("-i");
cmdList.add(filename);
// Make sure FFmpeg doesn't try to encode embedded images into the stream
cmdList.add("-vn");
// Encoder threads
if (nThreads > 0) {
cmdList.add("-threads");
cmdList.add("" + nThreads);
}
if (params.timeend > 0) {
cmdList.add("-t");
cmdList.add("" + params.timeend);
}
if (params.mediaRenderer.isTranscodeToMP3()) {
cmdList.add("-f");
cmdList.add("mp3");
cmdList.add("-ab");
cmdList.add("320000");
} else if (params.mediaRenderer.isTranscodeToWAV()) {
cmdList.add("-f");
cmdList.add("wav");
} else {
// default: LPCM
cmdList.add("-f");
cmdList.add("s16be");
}
if (configuration.isAudioResample()) {
if (params.mediaRenderer.isTranscodeAudioTo441()) {
cmdList.add("-ar");
cmdList.add("44100");
cmdList.add("-ac");
cmdList.add("2");
} else {
cmdList.add("-ar");
cmdList.add("48000");
cmdList.add("-ac");
cmdList.add("2");
}
}
cmdList.add("pipe:");
String[] cmdArray = new String[cmdList.size()];
cmdList.toArray(cmdArray);
cmdArray = finalizeTranscoderArgs(filename, dlna, media, params, cmdArray);
ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, params);
pw.runInNewThread();
configuration = prev;
return pw;
}
use of net.pms.configuration.PmsConfiguration in project UniversalMediaServer by UniversalMediaServer.
the class VLCVideo method launchTranscode.
@Override
public ProcessWrapper launchTranscode(DLNAResource dlna, DLNAMediaInfo media, OutputParams params) throws IOException {
// Use device-specific pms conf
PmsConfiguration prev = configuration;
configuration = (DeviceConfiguration) params.mediaRenderer;
final String filename = dlna.getFileName();
boolean isWindows = Platform.isWindows();
setAudioAndSubs(filename, media, params);
// Make sure we can play this
CodecConfig config = genConfig(params.mediaRenderer);
PipeProcess tsPipe = new PipeProcess("VLC" + System.currentTimeMillis() + "." + config.container);
ProcessWrapper pipe_process = tsPipe.getPipeProcess();
// XXX 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 start this as early as possible
pipe_process.runInNewThread();
tsPipe.deleteLater();
params.input_pipes[0] = tsPipe;
params.minBufferSize = params.minFileSize;
params.secondread_minsize = 100000;
List<String> cmdList = new ArrayList<>();
cmdList.add(executable());
cmdList.add("-I");
cmdList.add("dummy");
/**
* Disable hardware acceleration which is enabled by default,
* but for hardware acceleration, user must enable it in "VLC Preferences",
* until they release documentation for new functionalities introduced in 2.1.4+
*/
if (registry.getVlcVersion() != null) {
String vlcVersion = registry.getVlcVersion();
Version currentVersion = new Version(vlcVersion);
Version requiredVersion = new Version("2.1.4");
if (currentVersion.compareTo(requiredVersion) > 0) {
if (!configuration.isGPUAcceleration()) {
cmdList.add("--avcodec-hw=disabled");
LOGGER.trace("Disabled VLC's hardware acceleration.");
}
} else if (!configuration.isGPUAcceleration()) {
LOGGER.trace("Version " + vlcVersion + " of VLC is too low to handle the way we disable hardware acceleration.");
}
}
// Useful for the more esoteric codecs people use
if (experimentalCodecs.isSelected()) {
cmdList.add("--sout-avcodec-strict=-2");
}
// Stop the DOS box from appearing on windows
if (isWindows) {
cmdList.add("--dummy-quiet");
}
// File needs to be given before sout, otherwise vlc complains
cmdList.add(filename);
String disableSuffix = "track=-1";
// Handle audio language
if (params.aid != null) {
// User specified language at the client, acknowledge it
if (params.aid.getLang() == null || params.aid.getLang().equals("und")) {
// VLC doesn't understand "und", so try to get audio track by ID
cmdList.add("--audio-track=" + params.aid.getId());
} else {
cmdList.add("--audio-language=" + params.aid.getLang());
}
} else {
// Not specified, use language from GUI
// FIXME: VLC does not understand "loc" or "und".
cmdList.add("--audio-language=" + configuration.getAudioLanguages());
}
// Handle subtitle language
if (params.sid != null) {
// User specified language at the client, acknowledge it
if (params.sid.isExternal() && !params.sid.isStreamable() && !params.mediaRenderer.streamSubsForTranscodedVideo()) {
String externalSubtitlesFileName;
// External subtitle file
if (params.sid.isExternalFileUtf16()) {
try {
// Convert UTF-16 -> UTF-8
File convertedSubtitles = new File(configuration.getTempFolder(), "utf8_" + params.sid.getExternalFile().getName());
FileUtil.convertFileFromUtf16ToUtf8(params.sid.getExternalFile(), convertedSubtitles);
externalSubtitlesFileName = ProcessUtil.getShortFileNameIfWideChars(convertedSubtitles.getAbsolutePath());
} catch (IOException e) {
LOGGER.debug("Error converting file from UTF-16 to UTF-8", e);
externalSubtitlesFileName = ProcessUtil.getShortFileNameIfWideChars(params.sid.getExternalFile().getAbsolutePath());
}
} else {
externalSubtitlesFileName = ProcessUtil.getShortFileNameIfWideChars(params.sid.getExternalFile().getAbsolutePath());
}
if (externalSubtitlesFileName != null) {
cmdList.add("--sub-file");
cmdList.add(externalSubtitlesFileName);
}
} else if (params.sid.getLang() != null && !params.sid.getLang().equals("und")) {
// Load by ID (better)
cmdList.add("--sub-track=" + params.sid.getId());
} else {
// VLC doesn't understand "und", but does understand a nonexistent track
cmdList.add("--sub-" + disableSuffix);
}
} else {
cmdList.add("--sub-" + disableSuffix);
}
// x264 options
if (videoRemux) {
cmdList.add("--sout-x264-preset");
cmdList.add("superfast");
/**
* This option prevents VLC from speeding up transcoding by disabling certain
* codec optimizations if the CPU is struggling to keep up.
* It is already disabled by default so there is no reason to specify that here,
* plus the option doesn't work on versions of VLC from 2.0.7 to 2.1.5.
*/
// cmdList.add("--no-sout-avcodec-hurry-up");
cmdList.addAll(getVideoBitrateOptions(dlna, media, params));
}
// Skip forward if necessary
if (params.timeseek != 0) {
cmdList.add("--start-time");
cmdList.add(String.valueOf(params.timeseek));
}
// Generate encoding args
String separator = "";
StringBuilder encodingArgsBuilder = new StringBuilder();
for (Map.Entry<String, Object> curEntry : getEncodingArgs(config, params).entrySet()) {
encodingArgsBuilder.append(separator);
encodingArgsBuilder.append(curEntry.getKey());
if (curEntry.getValue() != null) {
encodingArgsBuilder.append('=');
encodingArgsBuilder.append(curEntry.getValue());
}
separator = ",";
}
// Add our transcode options
String transcodeSpec = String.format("#transcode{%s}:standard{access=file,mux=%s,dst='%s%s'}", encodingArgsBuilder.toString(), config.container, (isWindows ? "\\\\" : ""), tsPipe.getInputPipe());
cmdList.add("--sout");
cmdList.add(transcodeSpec);
// Force VLC to exit when finished
cmdList.add("vlc://quit");
// Pass to process wrapper
String[] cmdArray = new String[cmdList.size()];
cmdList.toArray(cmdArray);
cmdArray = finalizeTranscoderArgs(filename, dlna, media, params, cmdArray);
LOGGER.trace("Finalized args: " + StringUtils.join(cmdArray, " "));
ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, params);
pw.attachProcess(pipe_process);
// TODO: Why is this here?
try {
Thread.sleep(150);
} catch (InterruptedException e) {
}
pw.runInNewThread();
configuration = prev;
return pw;
}
Aggregations