OutputParams params
) throws IOException {
final String filename = dlna.getSystemName();
setAudioAndSubs(filename, media, params);
PipeIPCProcess ffVideoPipe;
ProcessWrapperImpl ffVideo;
PipeIPCProcess ffAudioPipe[] = null;
ProcessWrapperImpl ffAudio[] = null;
String fps = media.getValidFps(false);
int width = media.getWidth();
int height = media.getHeight();
if (width < 320 || height < 240) {
width = -1;
height = -1;
}
String videoType = "V_MPEG4/ISO/AVC";
if (media.getCodecV() != null && media.getCodecV().startsWith("mpeg2")) {
videoType = "V_MPEG-2";
}
if (this instanceof TsMuxeRAudio && media.getFirstAudioTrack() != null) {
ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "fakevideo", System.currentTimeMillis() + "videoout", false, true);
String timeEndValue1 = "-t";
String timeEndValue2 = "" + params.timeend;
if (params.timeend < 1) {
timeEndValue1 = "-y";
timeEndValue2 = "-y";
}
String[] ffmpegLPCMextract = new String[] {
configuration.getFfmpegPath(),
timeEndValue1, timeEndValue2,
"-loop", "1",
"-i", "DummyInput.jpg",
"-f", "h264",
"-c:v", "libx264",
"-level", "31",
"-pix_fmt", "yuv420p",
"-an",
"-y",
ffVideoPipe.getInputPipe()
};
videoType = "V_MPEG4/ISO/AVC";
OutputParams ffparams = new OutputParams(configuration);
ffparams.maxBufferSize = 1;
ffVideo = new ProcessWrapperImpl(ffmpegLPCMextract, ffparams);
if (
filename.toLowerCase().endsWith(".flac") &&
media.getFirstAudioTrack().getBitsperSample() >= 24 &&
media.getFirstAudioTrack().getSampleRate() % 48000 == 0
) {
ffAudioPipe = new PipeIPCProcess[1];
ffAudioPipe[0] = new PipeIPCProcess(System.currentTimeMillis() + "flacaudio", System.currentTimeMillis() + "audioout", false, true);
String[] flacCmd = new String[] {
configuration.getFlacPath(),
"--output-name=" + ffAudioPipe[0].getInputPipe(),
"-d",
"-f",
"-F",
filename
};
ffparams = new OutputParams(configuration);
ffparams.maxBufferSize = 1;
ffAudio = new ProcessWrapperImpl[1];
ffAudio[0] = new ProcessWrapperImpl(flacCmd, ffparams);
} else {
ffAudioPipe = new PipeIPCProcess[1];
ffAudioPipe[0] = new PipeIPCProcess(System.currentTimeMillis() + "mlpaudio", System.currentTimeMillis() + "audioout", false, true);
String depth = "pcm_s16le";
String rate = "48000";
if (media.getFirstAudioTrack().getBitsperSample() >= 24) {
depth = "pcm_s24le";
}
if (media.getFirstAudioTrack().getSampleRate() > 48000) {
rate = "" + media.getFirstAudioTrack().getSampleRate();
}
String[] flacCmd = new String[] {
configuration.getFfmpegPath(),
"-i", filename,
"-ar", rate,
"-f", "wav",
"-acodec", depth,
"-y",
ffAudioPipe[0].getInputPipe()
};
ffparams = new OutputParams(configuration);
ffparams.maxBufferSize = 1;
ffAudio = new ProcessWrapperImpl[1];
ffAudio[0] = new ProcessWrapperImpl(flacCmd, ffparams);
}
} else {
params.waitbeforestart = 5000;
params.manageFastStart();
String mencoderPath = configuration.getMencoderPath();
ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegvideo", System.currentTimeMillis() + "videoout", false, true);
// Special handling for evo files
String evoValue1 = "-quiet";
String evoValue2 = "-quiet";
if (filename.toLowerCase().endsWith(".evo")) {
evoValue1 = "-psprobe";
evoValue2 = "1000000";
}
String[] ffmpegLPCMextract = new String[] {
mencoderPath,
"-ss", params.timeseek > 0 ? "" + params.timeseek : "0",
params.stdin != null ? "-" : filename,
evoValue1, evoValue2,
"-really-quiet",
"-msglevel", "statusline=2",
"-ovc", "copy",
"-nosound",
"-mc", "0",
"-noskip",
"-of", "rawvideo",
"-o", ffVideoPipe.getInputPipe()
};
InputFile newInput = new InputFile();
newInput.setFilename(filename);
newInput.setPush(params.stdin);
/**
* Note: This logic is weird; on one hand we check if the renderer requires videos to be Level 4.1 or below, but then
* the other function allows the video to exceed those limits.
* In reality this won't cause problems since renderers typically don't support above 4.1 anyway - nor are many
* videos encoded higher than that either - but it's worth acknowledging the logic discrepancy.
*/
if (!media.isVideoWithinH264LevelLimits(newInput, params.mediaRenderer) && params.mediaRenderer.isH264Level41Limited()) {
LOGGER.info("The video will not play or will show a black screen");
}
if (media.getH264AnnexB() != null && media.getH264AnnexB().length > 0) {
StreamModifier sm = new StreamModifier();
sm.setHeader(media.getH264AnnexB());
sm.setH264AnnexB(true);
ffVideoPipe.setModifier(sm);
}
OutputParams ffparams = new OutputParams(configuration);
ffparams.maxBufferSize = 1;
ffparams.stdin = params.stdin;
ffVideo = new ProcessWrapperImpl(ffmpegLPCMextract, ffparams);
int numAudioTracks = 1;
if (media.getAudioTracksList() != null && media.getAudioTracksList().size() > 1 && configuration.isMuxAllAudioTracks()) {
numAudioTracks = media.getAudioTracksList().size();
}
boolean singleMediaAudio = media.getAudioTracksList().size() <= 1;
if (params.aid != null) {
boolean ac3Remux;
boolean dtsRemux;
boolean encodedAudioPassthrough;
boolean pcm;
if (numAudioTracks <= 1) {
ffAudioPipe = new PipeIPCProcess[numAudioTracks];
ffAudioPipe[0] = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegaudio01", System.currentTimeMillis() + "audioout", false, true);
/**
* Disable AC3 remux for stereo tracks with 384 kbits bitrate and PS3 renderer (PS3 FW bug?)
*
* Commented out until we can find a way to detect when a video has an audio track that switches from 2 to 6 channels
* because MEncoder can't handle those files, which are very common these days.
boolean ps3_and_stereo_and_384_kbits = params.aid != null &&
(params.mediaRenderer.isPS3() && params.aid.getAudioProperties().getNumberOfChannels() == 2) &&
(params.aid.getBitRate() > 370000 && params.aid.getBitRate() < 400000);
*/
encodedAudioPassthrough = configuration.isEncodedAudioPassthrough() && params.aid.isNonPCMEncodedAudio() && params.mediaRenderer.isWrapEncodedAudioIntoPCM();
ac3Remux = params.aid.isAC3() && configuration.isAudioRemuxAC3() && !encodedAudioPassthrough;
dtsRemux = configuration.isAudioEmbedDtsInPcm() && params.aid.isDTS() && params.mediaRenderer.isDTSPlayable() && !encodedAudioPassthrough;
pcm = configuration.isAudioUsePCM() &&
media.isValidForLPCMTranscoding() &&
(
params.aid.isLossless() ||
(params.aid.isDTS() && params.aid.getAudioProperties().getNumberOfChannels() <= 6) ||
params.aid.isTrueHD() ||
(
!configuration.isMencoderUsePcmForHQAudioOnly() &&
(
params.aid.isAC3() ||
params.aid.isMP3() ||
params.aid.isAAC() ||
params.aid.isVorbis() ||
// params.aid.isWMA() ||
params.aid.isMpegAudio()
)
)
) && params.mediaRenderer.isLPCMPlayable();
int channels;
if (ac3Remux) {
channels = params.aid.getAudioProperties().getNumberOfChannels(); // AC-3 remux
} else if (dtsRemux || encodedAudioPassthrough) {
channels = 2;
} else if (pcm) {
channels = params.aid.getAudioProperties().getNumberOfChannels();
} else {
channels = configuration.getAudioChannelCount(); // 5.1 max for AC-3 encoding
}
if (!ac3Remux && (dtsRemux || pcm || encodedAudioPassthrough)) {
// DTS remux or LPCM
StreamModifier sm = new StreamModifier();
sm.setPcm(pcm);
sm.setDtsEmbed(dtsRemux);
sm.setEncodedAudioPassthrough(encodedAudioPassthrough);
sm.setNbChannels(channels);
sm.setSampleFrequency(params.aid.getSampleRate() < 48000 ? 48000 : params.aid.getSampleRate());
sm.setBitsPerSample(16);
String mixer = null;
if (pcm && !dtsRemux && !encodedAudioPassthrough) {
mixer = getLPCMChannelMappingForMencoder(params.aid);
}
ffmpegLPCMextract = new String[] {
mencoderPath,
"-ss", params.timeseek > 0 ? "" + params.timeseek : "0",
params.stdin != null ? "-" : filename,
evoValue1, evoValue2,
"-really-quiet",
"-msglevel", "statusline=2",
"-channels", "" + sm.getNbChannels(),
"-ovc", "copy",
"-of", "rawaudio",
"-mc", sm.isDtsEmbed() || sm.isEncodedAudioPassthrough() ? "0.1" : "0",
"-noskip",
"-oac", sm.isDtsEmbed() || sm.isEncodedAudioPassthrough() ? "copy" : "pcm",
isNotBlank(mixer) ? "-af" : "-quiet", isNotBlank(mixer) ? mixer : "-quiet",
singleMediaAudio ? "-quiet" : "-aid", singleMediaAudio ? "-quiet" : ("" + params.aid.getId()),
"-srate", "48000",
"-o", ffAudioPipe[0].getInputPipe()
};
// Use PCM trick when media renderer does not support DTS in MPEG
if (!params.mediaRenderer.isMuxDTSToMpeg()) {
ffAudioPipe[0].setModifier(sm);
}
} else {
// AC-3 remux or encoding
ffmpegLPCMextract = new String[] {
mencoderPath,
"-ss", params.timeseek > 0 ? "" + params.timeseek : "0",
params.stdin != null ? "-" : filename,
evoValue1, evoValue2,
"-really-quiet",
"-msglevel", "statusline=2",
"-channels", "" + channels,
"-ovc", "copy",
"-of", "rawaudio",
"-mc", "0",
"-noskip",
"-oac", (ac3Remux) ? "copy" : "lavc",
params.aid.isAC3() ? "-fafmttag" : "-quiet", params.aid.isAC3() ? "0x2000" : "-quiet",
"-lavcopts", "acodec=" + (configuration.isMencoderAc3Fixed() ? "ac3_fixed" : "ac3") + ":abitrate=" + CodecUtil.getAC3Bitrate(configuration, params.aid),
"-af", "lavcresample=48000",
"-srate", "48000",
singleMediaAudio ? "-quiet" : "-aid", singleMediaAudio ? "-quiet" : ("" + params.aid.getId()),
"-o", ffAudioPipe[0].getInputPipe()
};
}
ffparams = new OutputParams(configuration);
ffparams.maxBufferSize = 1;
ffparams.stdin = params.stdin;
ffAudio = new ProcessWrapperImpl[numAudioTracks];
ffAudio[0] = new ProcessWrapperImpl(ffmpegLPCMextract, ffparams);
} else {
ffAudioPipe = new PipeIPCProcess[numAudioTracks];
ffAudio = new ProcessWrapperImpl[numAudioTracks];
for (int i = 0; i < media.getAudioTracksList().size(); i++) {
DLNAMediaAudio audio = media.getAudioTracksList().get(i);
ffAudioPipe[i] = new PipeIPCProcess(System.currentTimeMillis() + "ffmpeg" + i, System.currentTimeMillis() + "audioout" + i, false, true);
/**
* Disable AC3 remux for stereo tracks with 384 kbits bitrate and PS3 renderer (PS3 FW bug?)
*
* Commented out until we can find a way to detect when a video has an audio track that switches from 2 to 6 channels