Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Make FFmpeg display external subtitles.

(Requires FFmpeg version 1.1 or higher)
  • Loading branch information...
commit 453d4c32b39a6182ed8184f88622b6c261e1f122 1 parent 5e9a3e6
@Raptor399 Raptor399 authored
View
1  src/main/java/net/pms/encoders/FFMpegAudio.java
@@ -51,6 +51,7 @@
JCheckBox noresample;
public FFMpegAudio(PmsConfiguration configuration) {
+ super(configuration);
this.configuration = configuration;
}
View
4 src/main/java/net/pms/encoders/FFMpegAviSynthVideo.java
@@ -44,6 +44,10 @@
private static final Logger logger = LoggerFactory.getLogger(FFMpegAviSynthVideo.class);
public static final String ID = "avsffmpeg";
+ FFMpegAviSynthVideo() {
+ super(PMS.getConfiguration());
+ }
+
@Override
public String id() {
return ID;
View
97 src/main/java/net/pms/encoders/FFMpegVideo.java
@@ -22,6 +22,7 @@
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,6 +33,7 @@
import net.pms.Messages;
import net.pms.PMS;
+import net.pms.configuration.PmsConfiguration;
import net.pms.configuration.RendererConfiguration;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAMediaSubtitle;
@@ -41,6 +43,8 @@
import net.pms.io.ProcessWrapper;
import net.pms.io.ProcessWrapperImpl;
import net.pms.network.HTTPResource;
+import net.pms.util.FileUtil;
+import net.pms.util.ProcessUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
@@ -67,6 +71,7 @@
public class FFMpegVideo extends Player {
private static final Logger LOGGER = LoggerFactory.getLogger(FFMpegVideo.class);
private JTextField ffmpeg;
+ private final PmsConfiguration configuration;
private static final String DEFAULT_QSCALE = "3";
// FIXME we have an id() accessor for this; no need for the field to be public
@@ -74,6 +79,23 @@
public static final String ID = "ffmpegvideo";
/**
+ * This constructor is not used in the codebase.
+ */
+ @Deprecated
+ public FFMpegVideo() {
+ this(PMS.getConfiguration());
+ }
+
+ /**
+ * Default constructor.
+ *
+ * @param configuration The PMS configuration options object
+ */
+ public FFMpegVideo(PmsConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ /**
* Returns a list of strings representing the rescale options for this transcode i.e. the ffmpeg -vf
* options used to resize a video that's too wide and/or high for the specified renderer.
* If the renderer has no size limits, or there's no media metadata, or the video is within the renderer's
@@ -266,6 +288,47 @@ public int type() {
return customOptions;
}
+ /**
+ * Returns subtitle options based on the provided media and output parameters.
+ *
+ * @param renderer The renderer configuration settings
+ * @param media The media information
+ * @param params The output parameter settings
+ * @return The list of subtitle options
+ */
+ private List<String> getSubtitleOptions(RendererConfiguration renderer,
+ DLNAMediaInfo media, OutputParams params) {
+
+ List<String> subtitleOptions = new ArrayList<String>();
+ String externalSubtitlesFileName = null;
+
+ if (params.sid != null) {
+ if (params.sid.isExternal()) {
+ // 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());
+ }
+
+ // Burn in subtitles with the subtitles filter (available since ffmpeg 1.1)
+ subtitleOptions.add("-vf");
+ subtitleOptions.add("subtitles=" + externalSubtitlesFileName);
+ }
+ // TODO: Handle embedded subtitles
+ }
+
+ return subtitleOptions;
+ }
+
// XXX hardwired to false and not referenced anywhere else in the codebase
@Deprecated
public boolean mplayer() {
@@ -289,22 +352,12 @@ public ProcessWrapper launchTranscode(
DLNAMediaInfo media,
OutputParams params
) throws IOException {
- return getFFMpegTranscode(fileName, dlna, media, params, null);
- }
-
- // XXX pointless redirection of launchTranscode
- // TODO remove this method and move its body into launchTranscode
- // TODO call setAudioAndSubs to populate params with audio track/subtitles metadata
- @Deprecated
- protected ProcessWrapperImpl getFFMpegTranscode(
- String fileName,
- DLNAResource dlna,
- DLNAMediaInfo media,
- OutputParams params,
- String args[]
- ) throws IOException {
int nThreads = PMS.getConfiguration().getNumberOfCpuCores();
List<String> cmdList = new ArrayList<String>();
+
+ // Populate params with audio track and subtitles metadata
+ setAudioAndSubs(fileName, media, params, configuration);
+
RendererConfiguration renderer = params.mediaRenderer;
cmdList.add(executable());
@@ -342,6 +395,9 @@ protected ProcessWrapperImpl getFFMpegTranscode(
// if the source is too large for the renderer, resize it
cmdList.addAll(getRescaleOptions(renderer, media));
+ // Add subtitle options
+ cmdList.addAll(getSubtitleOptions(renderer, media, params));
+
// add custom args
cmdList.addAll(getCustomArgs());
@@ -367,6 +423,19 @@ protected ProcessWrapperImpl getFFMpegTranscode(
return pw;
}
+ // XXX pointless redirection of launchTranscode
+ // TODO remove this method and move its body into launchTranscode
+ @Deprecated
+ protected ProcessWrapperImpl getFFMpegTranscode(
+ String fileName,
+ DLNAResource dlna,
+ DLNAMediaInfo media,
+ OutputParams params,
+ String args[]
+ ) throws IOException {
+ return (ProcessWrapperImpl) launchTranscode(fileName, dlna, media, params);
+ }
+
@Override
public JComponent config() {
return config("FFMpegVideo.1");
View
1  src/main/java/net/pms/encoders/FFMpegWebVideo.java
@@ -67,6 +67,7 @@ public boolean isTimeSeekable() {
}
public FFMpegWebVideo(PmsConfiguration configuration) {
+ super(configuration);
this.configuration = configuration;
}
View
2  src/main/java/net/pms/encoders/PlayerFactory.java
@@ -131,7 +131,7 @@ private static void registerPlayers(final PmsConfiguration configuration) {
registerPlayer(new MEncoderAviSynth(configuration));
}
- registerPlayer(new FFMpegVideo());
+ registerPlayer(new FFMpegVideo(configuration));
registerPlayer(new MPlayerAudio(configuration));
registerPlayer(new FFMpegWebVideo(configuration));
registerPlayer(new MEncoderWebVideo(configuration));
Please sign in to comment.
Something went wrong with that request. Please try again.