Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

FFmpeg: make bitrate handling reusable

  • Loading branch information...
commit ece4d6d1f400d68a5937eba069c2eb8d1866796c 1 parent d6e57f4
@chocolateboy chocolateboy authored
View
95 src/main/java/net/pms/encoders/FFMpegVideo.java
@@ -57,6 +57,10 @@
/**
* Pure FFmpeg video player.
+ *
+ * Design note: helper methods that return lists of <code>String</code>s representing options are public
+ * to facilitate composition e.g. a custom engine (plugin) that uses tsMuxeR for videos without
+ * subtitles and FFmpeg otherwise needs to compose and call methods on both players.
*/
public class FFMpegVideo extends Player {
private static final Logger LOGGER = LoggerFactory.getLogger(FFMpegVideo.class);
@@ -86,7 +90,7 @@
* @param media metadata for the DLNA resource which is being transcoded
* @return a rescale spec <code>String</code> or <code>null</code> if resizing isn't required.
*/
- public static String getRescaleSpec(RendererConfiguration renderer, DLNAMediaInfo media) {
+ public String getRescaleSpec(RendererConfiguration renderer, DLNAMediaInfo media) {
String rescaleSpec = null;
boolean isResolutionTooHighForRenderer = renderer.isVideoRescale() // renderer defines a max width/height
&& (media != null)
@@ -109,32 +113,31 @@ public static String getRescaleSpec(RendererConfiguration renderer, DLNAMediaInf
}
/**
- * Takes a {@link RendererConfiguration} and returns a {@link List} of <code>String</code>s representing ffmpeg output options
+ * Takes a renderer and returns a list of <code>String</code>s representing ffmpeg output options
* (i.e. options that define the output file's video codec, audio codec and container)
- * compatible with the renderer's <code>TranscodeVideo</code> profile. Implemented here as a static method
- * so that it can be used by {@link FFmpegWebVideo} and any other engines that wrap ffmpeg.
+ * compatible with the renderer's <code>TranscodeVideo</code> profile.
*
* @param renderer The {@link RendererConfiguration} instance whose <code>TranscodeVideo</code> profile is to be processed.
* @return a {@link List} of <code>String</code>s representing the ffmpeg output parameters for the renderer according
* to its <code>TranscodeVideo</code> profile.
*/
- public static List<String> getTranscodeVideoOptions(RendererConfiguration renderer) {
+ public List<String> getTranscodeVideoOptions(RendererConfiguration renderer) {
List<String> transcodeOptions = new ArrayList<String>();
if (renderer.isTranscodeToWMV()) { // WMV
- transcodeOptions.add("-vcodec");
+ transcodeOptions.add("-c:v");
transcodeOptions.add("wmv2");
- transcodeOptions.add("-acodec");
+ transcodeOptions.add("-c:a");
transcodeOptions.add("wma2");
transcodeOptions.add("-f");
transcodeOptions.add("asf");
} else { // MPEGPSAC3 or MPEGTSAC3
- transcodeOptions.add("-vcodec");
+ transcodeOptions.add("-c:v");
transcodeOptions.add("mpeg2video");
- transcodeOptions.add("-acodec");
+ transcodeOptions.add("-c:a");
transcodeOptions.add("ac3");
if (renderer.isTranscodeToMPEGTSAC3()) { // MPEGTSAC3
@@ -149,6 +152,50 @@ public static String getRescaleSpec(RendererConfiguration renderer, DLNAMediaInf
return transcodeOptions;
}
+ /**
+ * Takes a renderer and metadata for the current video and returns the bitrate spec for the current transcode according to
+ * the limits/requirements of the renderer.
+ *
+ * @param renderer a {@link RendererConfiguration} instance representing the renderer being streamed to
+ * @param media the media metadata for the video being streamed. May contain unset/null values (e.g. for web videos).
+ * @return a {@link List} of <code>String</code>s representing the video bitrate options for this transcode
+ */
+ public List<String> getVideoBitrateOptions(RendererConfiguration renderer, DLNAMediaInfo media) { // media is currently unused
+ List<String> videoBitrateOptions = new ArrayList<String>();
+ String sMaxVideoBitrate = renderer.getMaxVideoBitrate(); // currently Mbit/s
+ int iMaxVideoBitrate = 0;
+
+ if (sMaxVideoBitrate != null) {
+ try {
+ iMaxVideoBitrate = Integer.parseInt(sMaxVideoBitrate);
+ } catch (NumberFormatException nfe) {
+ LOGGER.error("Can't parse max video bitrate", nfe); // XXX this should be handled in RendererConfiguration
+ }
+ }
+
+ if (iMaxVideoBitrate != 0) {
+ // limit the bitrate
+ // FIXME untested
+ videoBitrateOptions.add("-b:v");
+ // convert megabits-per-second (as per the current option name: MaxVideoBitrateMbps) to bps
+ // FIXME rather than dealing with megabit vs mebibit issues here, this should be left up to the client i.e.
+ // the renderer.conf unit should be bits-per-second (and the option should be renamed: MaxVideoBitrateMbps -> MaxVideoBitrate)
+ videoBitrateOptions.add("" + iMaxVideoBitrate * 1000 * 1000);
+ } else {
+ // preserve the bitrate
+ // XXX while this often preserves the bitrate, it's not what -sameq means
+ videoBitrateOptions.add("-sameq");
+ /*
+ if (media.getBitrate() != 0) {
+ videoBitrateOptions.add("-v:b");
+ videoBitrateOptions.add("" + media.getBitrate());
+ }
+ */
+ }
+
+ return videoBitrateOptions;
+ }
+
@Override
public int purpose() {
return VIDEO_SIMPLEFILE_PLAYER;
@@ -307,30 +354,8 @@ protected ProcessWrapperImpl getFFMpegTranscode(
cmdList.add("" + params.timeend);
}
- // quality (bitrate)
- String sMaxVideoBitrate = renderer.getMaxVideoBitrate(); // currently Mbit/s
- int iMaxVideoBitrate = 0;
-
- if (sMaxVideoBitrate != null) {
- try {
- iMaxVideoBitrate = Integer.parseInt(sMaxVideoBitrate);
- } catch (NumberFormatException nfe) {
- LOGGER.error("Can't parse max video bitrate", nfe); // XXX this should be handled in RendererConfiguration
- }
- }
-
- if (iMaxVideoBitrate != 0) {
- // limit the bitrate
- // FIXME untested
- cmdList.add("-b:v");
- // convert megabits-per-second (as per the current option name: MaxVideoBitrateMbps) to bps
- // FIXME rather than dealing with megabit vs mebibit issues here, this should be left up to the client i.e.
- // the renderer.conf unit should be bits-per-second (and the option should be renamed: MaxVideoBitrateMbps -> MaxVideoBitrate)
- cmdList.add("" + iMaxVideoBitrate * 1000 * 1000);
- } else {
- // preserve the bitrate
- cmdList.add("-sameq");
- }
+ // add video bitrate options
+ cmdList.addAll(getVideoBitrateOptions(renderer, media));
// if the source is too large for the renderer, resize it
String rescale = getRescaleSpec(renderer, media);
@@ -339,8 +364,12 @@ protected ProcessWrapperImpl getFFMpegTranscode(
cmdList.add(rescale);
}
+ // add custom args
cmdList.addAll(getSanitizedCustomArgs());
+
+ // add the output options (-f, -acodec, -vcodec)
cmdList.addAll(getTranscodeVideoOptions(renderer));
+
cmdList.add("pipe:");
String[] cmdArray = new String[ cmdList.size() ];
View
11 src/main/java/net/pms/encoders/FFMpegWebVideo.java
@@ -22,6 +22,7 @@
import java.util.List;
import net.pms.configuration.PmsConfiguration;
+import net.pms.configuration.RendererConfiguration;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAResource;
import net.pms.encoders.FFMpegVideo;
@@ -78,6 +79,7 @@ public ProcessWrapper launchTranscode(
) throws IOException {
params.minBufferSize = params.minFileSize;
params.secondread_minsize = 100000;
+ RendererConfiguration renderer = params.mediaRenderer;
// basename of the named pipe:
// ffmpeg -loglevel warning -threads nThreads -i URL -threads nThreads -transcode-video-options /path/to/fifoName
@@ -117,12 +119,11 @@ public ProcessWrapper launchTranscode(
cmdList.add("-threads");
cmdList.add("" + nThreads);
- // preserve the bitrate
- cmdList.add("-sameq");
+ // add video bitrate options
+ cmdList.addAll(getVideoBitrateOptions(renderer, media));
- // get the TranscodeVideo (output) options (-acodec, -vcodec, -f)
- List<String> transcodeOptions = getTranscodeVideoOptions(params.mediaRenderer);
- cmdList.addAll(transcodeOptions);
+ // add the TranscodeVideo (output) options (-acodec, -vcodec, -f)
+ cmdList.addAll(getTranscodeVideoOptions(renderer));
// output file
cmdList.add(pipe.getInputPipe());
Please sign in to comment.
Something went wrong with that request. Please try again.