use of net.pms.io.OutputParams in project UniversalMediaServer by UniversalMediaServer.
the class DLNAResource method getDlnaOrgPnFlags.
/**
* Creates the DLNA.ORG_PN to send.
* DLNA.ORG_PN is a string that tells the renderer what type of file to expect, like its
* container, framerate, codecs and resolution.
* Some renderers will not play a file if it has the wrong DLNA.ORG_PN string, while others
* are fine with any string or even nothing.
*
* @param mediaRenderer
* Media Renderer for which to represent this information.
* @param localizationValue
* @return String representation of the DLNA.ORG_PN flags
*/
@SuppressWarnings("deprecation")
private String getDlnaOrgPnFlags(RendererConfiguration mediaRenderer, int localizationValue) {
// Use device-specific pms conf, if any
PmsConfiguration configurationSpecificToRenderer = PMS.getConfiguration(mediaRenderer);
String mime = getRendererMimeType(mediaRenderer);
String dlnaOrgPnFlags = null;
if (mediaRenderer.isDLNAOrgPNUsed() || mediaRenderer.isAccurateDLNAOrgPN()) {
if (mediaRenderer.isPS3()) {
if (mime.equals(DIVX_TYPEMIME)) {
dlnaOrgPnFlags = "DLNA.ORG_PN=AVI";
} else if (mime.equals(WMV_TYPEMIME) && media != null && media.getHeight() > 700) {
dlnaOrgPnFlags = "DLNA.ORG_PN=WMVHIGH_PRO";
}
} else {
if (mime.equals(MPEG_TYPEMIME)) {
dlnaOrgPnFlags = "DLNA.ORG_PN=" + getMPEG_PS_PALLocalizedValue(localizationValue);
if (player != null) {
// VLC Web Video (Legacy) and tsMuxeR always output MPEG-TS
boolean isFileMPEGTS = TsMuxeRVideo.ID.equals(player.id()) || VideoLanVideoStreaming.ID.equals(player.id());
// Check if the renderer settings make the current engine always output MPEG-TS
if (!isFileMPEGTS && mediaRenderer.isTranscodeToMPEGTS() && (MEncoderVideo.ID.equals(player.id()) || FFMpegVideo.ID.equals(player.id()) || VLCVideo.ID.equals(player.id()) || AviSynthFFmpeg.ID.equals(player.id()) || AviSynthMEncoder.ID.equals(player.id()))) {
isFileMPEGTS = true;
}
boolean isMuxableResult = getMedia() != null && getMedia().isMuxable(mediaRenderer);
// If the engine is capable of automatically muxing to MPEG-TS and the setting is enabled, it might be MPEG-TS
if (!isFileMPEGTS && ((configurationSpecificToRenderer.isMencoderMuxWhenCompatible() && MEncoderVideo.ID.equals(player.id())) || (configurationSpecificToRenderer.isFFmpegMuxWithTsMuxerWhenCompatible() && FFMpegVideo.ID.equals(player.id())))) {
/**
* Media renderer needs ORG_PN to be accurate.
* If the value does not match the media, it won't play the media.
* Often we can lazily predict the correct value to send, but due to
* MEncoder needing to mux via tsMuxeR, we need to work it all out
* before even sending the file list to these devices.
* This is very time-consuming so we should a) avoid using this
* chunk of code whenever possible, and b) design a better system.
* Ideally we would just mux to MPEG-PS instead of MPEG-TS so we could
* know it will always be PS, but most renderers will not accept H.264
* inside MPEG-PS. Another option may be to always produce MPEG-TS
* instead and we should check if that will be OK for all renderers.
*
* This code block comes from Player.setAudioAndSubs()
*/
if (mediaRenderer.isAccurateDLNAOrgPN()) {
boolean finishedMatchingPreferences = false;
OutputParams params = new OutputParams(configurationSpecificToRenderer);
if (params.aid == null && media != null && media.getFirstAudioTrack() != null) {
// check for preferred audio
DLNAMediaAudio dtsTrack = null;
StringTokenizer st = new StringTokenizer(configurationSpecificToRenderer.getAudioLanguages(), ",");
while (st.hasMoreTokens()) {
String lang = st.nextToken().trim();
LOGGER.trace("Looking for an audio track with lang: " + lang);
for (DLNAMediaAudio audio : media.getAudioTracksList()) {
if (audio.matchCode(lang)) {
params.aid = audio;
LOGGER.trace("Matched audio track: " + audio);
break;
}
if (dtsTrack == null && audio.isDTS()) {
dtsTrack = audio;
}
}
}
// preferred audio not found, take a default audio track, dts first if available
if (dtsTrack != null) {
params.aid = dtsTrack;
LOGGER.trace("Found priority audio track with DTS: " + dtsTrack);
} else {
params.aid = media.getAudioTracksList().get(0);
LOGGER.trace("Chose a default audio track: " + params.aid);
}
}
String currentLang = null;
DLNAMediaSubtitle matchedSub = null;
if (params.aid != null) {
currentLang = params.aid.getLang();
}
if (params.sid != null && params.sid.getId() == -1) {
LOGGER.trace("Don't want subtitles!");
params.sid = null;
media_subtitle = params.sid;
finishedMatchingPreferences = true;
}
/**
* Check for live subtitles
*/
if (!finishedMatchingPreferences && params.sid != null && !StringUtils.isEmpty(params.sid.getLiveSubURL())) {
LOGGER.debug("Live subtitles " + params.sid.getLiveSubURL());
try {
matchedSub = params.sid;
String file = OpenSubtitle.fetchSubs(matchedSub.getLiveSubURL(), matchedSub.getLiveSubFile());
if (!StringUtils.isEmpty(file)) {
matchedSub.setExternalFile(new File(file), null);
params.sid = matchedSub;
media_subtitle = params.sid;
finishedMatchingPreferences = true;
}
} catch (IOException e) {
}
}
if (!finishedMatchingPreferences) {
StringTokenizer st = new StringTokenizer(configurationSpecificToRenderer.getAudioSubLanguages(), ";");
/**
* Check for external and internal subtitles matching the user's language
* preferences
*/
boolean matchedInternalSubtitles = false;
boolean matchedExternalSubtitles = false;
while (st.hasMoreTokens()) {
String pair = st.nextToken();
if (pair.contains(",")) {
String audio = pair.substring(0, pair.indexOf(','));
String sub = pair.substring(pair.indexOf(',') + 1);
audio = audio.trim();
sub = sub.trim();
if (currentLang != null && LOGGER.isTraceEnabled()) {
LOGGER.trace("Searching for a match for language \"{}\" with audio \"{}\" and subtitle \"{}\"", currentLang, audio, sub);
}
if (Iso639.isCodesMatching(audio, currentLang) || (currentLang != null && audio.equals("*"))) {
if (sub.equals("off")) {
/**
* Ignore the "off" language for external subtitles if the user setting is enabled
* TODO: Prioritize multiple external subtitles properly instead of just taking the first one we load
*/
if (configurationSpecificToRenderer.isForceExternalSubtitles()) {
for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
if (present_sub.getExternalFile() != null) {
matchedSub = present_sub;
matchedExternalSubtitles = true;
LOGGER.trace("Ignoring the \"off\" language because there are external subtitles");
break;
}
}
}
if (!matchedExternalSubtitles) {
matchedSub = new DLNAMediaSubtitle();
matchedSub.setLang("off");
}
} else if (getMedia() != null) {
for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
if (present_sub.matchCode(sub) || sub.equals("*")) {
if (present_sub.getExternalFile() != null) {
if (configurationSpecificToRenderer.isAutoloadExternalSubtitles()) {
// Subtitle is external and we want external subtitles, look no further
matchedSub = present_sub;
LOGGER.trace("Matched external subtitles track: {}", matchedSub);
break;
}
// Subtitle is external but we do not want external subtitles, keep searching
LOGGER.trace("External subtitles ignored because of user setting: {}", present_sub);
} else if (!matchedInternalSubtitles) {
matchedSub = present_sub;
LOGGER.trace("Matched internal subtitles track: {}", matchedSub);
if (configurationSpecificToRenderer.isAutoloadExternalSubtitles()) {
// Subtitle is internal and we will wait to see if an external one is available instead
matchedInternalSubtitles = true;
} else {
// Subtitle is internal and we will use it
break;
}
}
}
}
}
if (matchedSub != null && !matchedInternalSubtitles) {
break;
}
}
}
}
/**
* Check for external subtitles that were skipped in the above code block
* because they didn't match language preferences, if there wasn't already
* a match and the user settings specify it.
*/
if (matchedSub == null && configurationSpecificToRenderer.isForceExternalSubtitles()) {
for (DLNAMediaSubtitle present_sub : media.getSubtitleTracksList()) {
if (present_sub.getExternalFile() != null) {
matchedSub = present_sub;
LOGGER.trace("Matched external subtitles track that did not match language preferences: " + matchedSub);
break;
}
}
}
/**
* Disable chosen subtitles if the user has disabled all subtitles or
* if the language preferences have specified the "off" language.
*
* TODO: Can't we save a bunch of looping by checking for isDisableSubtitles
* just after the Live Subtitles check above?
*/
if (matchedSub != null && params.sid == null) {
if (configurationSpecificToRenderer.isDisableSubtitles() || (matchedSub.getLang() != null && matchedSub.getLang().equals("off"))) {
LOGGER.trace("Disabled the subtitles: " + matchedSub);
} else {
if (mediaRenderer.isExternalSubtitlesFormatSupported(matchedSub, media)) {
matchedSub.setSubsStreamable(true);
}
params.sid = matchedSub;
media_subtitle = params.sid;
}
}
/**
* Check for forced subtitles.
*/
if (!configurationSpecificToRenderer.isDisableSubtitles() && params.sid == null && media != null) {
// Check for subtitles again
File video = new File(getSystemName());
FileUtil.isSubtitlesExists(video, media, false);
if (configurationSpecificToRenderer.isAutoloadExternalSubtitles()) {
boolean forcedSubsFound = false;
// Priority to external subtitles
for (DLNAMediaSubtitle sub : media.getSubtitleTracksList()) {
if (matchedSub != null && matchedSub.getLang() != null && matchedSub.getLang().equals("off")) {
st = new StringTokenizer(configurationSpecificToRenderer.getForcedSubtitleTags(), ",");
while (sub.getSubtitlesTrackTitleFromMetadata() != null && st.hasMoreTokens()) {
String forcedTags = st.nextToken();
forcedTags = forcedTags.trim();
if (sub.getSubtitlesTrackTitleFromMetadata().toLowerCase().contains(forcedTags) && Iso639.isCodesMatching(sub.getLang(), configurationSpecificToRenderer.getForcedSubtitleLanguage())) {
LOGGER.trace("Forcing preferred subtitles: " + sub.getLang() + "/" + sub.getSubtitlesTrackTitleFromMetadata());
LOGGER.trace("Forced subtitles track: " + sub);
if (sub.getExternalFile() != null) {
LOGGER.trace("Found external forced file: " + sub.getExternalFile().getAbsolutePath());
}
if (mediaRenderer.isExternalSubtitlesFormatSupported(sub, media)) {
sub.setSubsStreamable(true);
}
params.sid = sub;
media_subtitle = params.sid;
forcedSubsFound = true;
break;
}
}
if (forcedSubsFound == true) {
break;
}
} else {
LOGGER.trace("Found subtitles track: " + sub);
if (sub.getExternalFile() != null) {
LOGGER.trace("Found external file: " + sub.getExternalFile().getAbsolutePath());
if (mediaRenderer.isExternalSubtitlesFormatSupported(sub, media)) {
sub.setSubsStreamable(true);
}
params.sid = sub;
media_subtitle = params.sid;
break;
}
}
}
}
if (matchedSub != null && matchedSub.getLang() != null && matchedSub.getLang().equals("off")) {
finishedMatchingPreferences = true;
}
if (!finishedMatchingPreferences && params.sid == null) {
st = new StringTokenizer(UMSUtils.getLangList(params.mediaRenderer), ",");
while (st.hasMoreTokens()) {
String lang = st.nextToken();
lang = lang.trim();
LOGGER.trace("Looking for a subtitle track with lang: " + lang);
for (DLNAMediaSubtitle sub : media.getSubtitleTracksList()) {
if (sub.matchCode(lang) && !(!configurationSpecificToRenderer.isAutoloadExternalSubtitles() && sub.getExternalFile() != null)) {
if (mediaRenderer.isExternalSubtitlesFormatSupported(sub, media)) {
sub.setSubsStreamable(true);
}
params.sid = sub;
LOGGER.trace("Matched subtitles track: " + params.sid);
break;
}
}
}
}
}
}
if (media_subtitle == null) {
LOGGER.trace("We do not want a subtitle for " + getName());
} else {
LOGGER.trace("We do want a subtitle for " + getName());
}
}
/**
* If:
* - There are no subtitles
* - This is not a DVD track
* - The media is muxable
* - The renderer accepts media muxed to MPEG-TS
* then the file is MPEG-TS
*/
if (media_subtitle == null && !hasExternalSubtitles() && media != null && media.getDvdtrack() == 0 && isMuxableResult && mediaRenderer.isMuxH264MpegTS()) {
isFileMPEGTS = true;
}
}
if (isFileMPEGTS) {
dlnaOrgPnFlags = "DLNA.ORG_PN=" + getMPEG_TS_SD_EU_ISOLocalizedValue(localizationValue);
if (media.isH264() && !VideoLanVideoStreaming.ID.equals(player.id()) && isMuxableResult) {
dlnaOrgPnFlags = "DLNA.ORG_PN=AVC_TS_HD_24_AC3_ISO";
if (mediaRenderer.isTranscodeToMPEGTSH264AAC()) {
dlnaOrgPnFlags = "DLNA.ORG_PN=AVC_TS_HP_HD_AAC";
}
}
}
} else if (media != null) {
if (media.isMpegTS()) {
dlnaOrgPnFlags = "DLNA.ORG_PN=" + getMPEG_TS_EULocalizedValue(localizationValue, media.isHDVideo());
if (media.isH264()) {
dlnaOrgPnFlags = "DLNA.ORG_PN=AVC_TS_HD_50_AC3";
if (mediaRenderer.isTranscodeToMPEGTSH264AAC()) {
dlnaOrgPnFlags = "DLNA.ORG_PN=AVC_TS_HP_HD_AAC";
}
}
}
}
} else if (media != null && mime.equals("video/vnd.dlna.mpeg-tts")) {
// patters - on Sony BDP m2ts clips aren't listed without this
dlnaOrgPnFlags = "DLNA.ORG_PN=" + getMPEG_TS_EULocalizedValue(localizationValue, media.isHDVideo());
} else if (media != null && mime.equals(JPEG_TYPEMIME)) {
int width = media.getWidth();
int height = media.getHeight();
if (width > 1024 || height > 768) {
// 1024 * 768
dlnaOrgPnFlags = "DLNA.ORG_PN=JPEG_LRG";
} else if (width > 640 || height > 480) {
// 640 * 480
dlnaOrgPnFlags = "DLNA.ORG_PN=JPEG_MED";
} else if (width > 160 || height > 160) {
// 160 * 160
dlnaOrgPnFlags = "DLNA.ORG_PN=JPEG_SM";
} else {
dlnaOrgPnFlags = "DLNA.ORG_PN=JPEG_TN";
}
} else if (mime.equals(AUDIO_MP3_TYPEMIME)) {
dlnaOrgPnFlags = "DLNA.ORG_PN=MP3";
} else if (mime.substring(0, 9).equals(AUDIO_LPCM_TYPEMIME) || mime.equals(AUDIO_WAV_TYPEMIME)) {
dlnaOrgPnFlags = "DLNA.ORG_PN=LPCM";
}
}
if (dlnaOrgPnFlags != null) {
dlnaOrgPnFlags = "DLNA.ORG_PN=" + mediaRenderer.getDLNAPN(dlnaOrgPnFlags.substring(12));
}
}
return dlnaOrgPnFlags;
}
use of net.pms.io.OutputParams in project UniversalMediaServer by UniversalMediaServer.
the class DVDISOFile method resolveOnce.
@Override
protected void resolveOnce() {
double[] titles = new double[100];
String[] cmd = new String[] { configuration.getMplayerPath(), "-identify", "-endpos", "0", "-ao", "null", "-vc", "null", "-vo", "null", "-dvd-device", ProcessUtil.getShortFileNameIfWideChars(file.getAbsolutePath()), "dvd://" };
OutputParams params = new OutputParams(configuration);
params.maxBufferSize = 1;
params.log = true;
final ProcessWrapperImpl pw = new ProcessWrapperImpl(cmd, params, true, false);
Runnable r = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
pw.stopProcess();
}
};
Thread failsafe = new Thread(r, "DVDISO Failsafe");
failsafe.start();
pw.runInSameThread();
List<String> lines = pw.getOtherResults();
if (lines != null) {
for (String line : lines) {
if (line.startsWith("ID_DVD_TITLE_") && line.contains("_LENGTH")) {
int rank = Integer.parseInt(line.substring(13, line.indexOf("_LENGT")));
double duration = Double.parseDouble(line.substring(line.lastIndexOf("LENGTH=") + 7));
titles[rank] = duration;
} else if (line.startsWith("ID_DVD_VOLUME_ID")) {
String volumeId = line.substring(line.lastIndexOf("_ID=") + 4).trim();
if (configuration.isPrettifyFilenames()) {
volumeId = volumeId.replaceAll("_", " ");
if (isNotBlank(volumeId) && volumeId.equals(volumeId.toUpperCase(PMS.getLocale()))) {
volumeId = WordUtils.capitalize(volumeId.toLowerCase(PMS.getLocale()));
}
}
this.volumeId = volumeId;
}
}
}
double oldduration = -1;
for (int i = 1; i < 99; i++) {
/**
* Don't take into account titles less than 10 seconds
* Also, workaround for the MPlayer bug which reports a unique title with the same length several times
* The "maybe wrong" title is taken into account only if its duration is less than 1 hour.
* Common-sense is a single video track on a DVD is usually greater than 1h
*/
if (titles[i] > 10 && (titles[i] != oldduration || oldduration < 3600)) {
DVDISOTitle dvd = new DVDISOTitle(file, volumeId, i);
addChild(dvd);
oldduration = titles[i];
}
}
if (childrenNumber() > 0) {
PMS.get().storeFileInCache(file, Format.ISO);
}
}
use of net.pms.io.OutputParams in project UniversalMediaServer by UniversalMediaServer.
the class DLNAMediaInfo method getMplayerThumbnail.
private ProcessWrapperImpl getMplayerThumbnail(InputFile media, boolean resume, RendererConfiguration renderer) throws IOException {
File file = media.getFile();
String[] args = new String[14];
args[0] = configuration.getMplayerPath();
args[1] = "-ss";
if (resume) {
args[2] = "" + (int) getDurationInSeconds();
} else {
args[2] = "" + configuration.getThumbnailSeekPos();
}
args[3] = "-quiet";
if (file != null) {
args[4] = ProcessUtil.getShortFileNameIfWideChars(file.getAbsolutePath());
} else {
args[4] = "-";
}
args[5] = "-msglevel";
args[6] = "all=4";
int thumbnailWidth = 320;
int thumbnailHeight = 180;
boolean isThumbnailPadding = true;
if (renderer != null) {
thumbnailWidth = renderer.getThumbnailWidth();
thumbnailHeight = renderer.getThumbnailHeight();
isThumbnailPadding = renderer.isThumbnailPadding();
}
if (isThumbnailPadding) {
args[7] = "-vf";
args[8] = "scale=" + thumbnailWidth + ":-2,expand=:" + thumbnailHeight;
} else {
args[7] = "-vf";
args[8] = "scale=" + thumbnailWidth + ":-2";
}
args[9] = "-frames";
args[10] = "1";
args[11] = "-vo";
String frameName = "" + media.hashCode();
frameName = "mplayer_thumbs:subdirs=\"" + frameName + "\"";
frameName = frameName.replace(',', '_');
args[12] = "jpeg:outdir=" + frameName;
args[13] = "-nosound";
OutputParams params = new OutputParams(configuration);
params.workDir = configuration.getTempFolder();
params.maxBufferSize = 1;
params.stdin = media.getPush();
params.log = true;
// not serious if anything happens during the thumbnailer
params.noexitcheck = true;
final ProcessWrapperImpl pw = new ProcessWrapperImpl(args, true, params);
// FAILSAFE
synchronized (parsingLock) {
parsing = true;
}
Runnable r = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
pw.stopProcess();
synchronized (parsingLock) {
parsing = false;
}
}
};
Thread failsafe = new Thread(r, "MPlayer Thumbnail Failsafe");
failsafe.start();
pw.runInSameThread();
synchronized (parsingLock) {
parsing = false;
}
return pw;
}
use of net.pms.io.OutputParams in project UniversalMediaServer by UniversalMediaServer.
the class RemotePlayHandler method mkPage.
private String mkPage(String id, HttpExchange t) throws IOException {
HashMap<String, Object> vars = new HashMap<>();
vars.put("serverName", configuration.getServerDisplayName());
LOGGER.debug("Make play page " + id);
RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
if (root == null) {
LOGGER.debug("root not found");
throw new IOException("Unknown root");
}
WebRender renderer = (WebRender) root.getDefaultRenderer();
renderer.setBrowserInfo(RemoteUtil.getCookie("UMSINFO", t), t.getRequestHeaders().getFirst("User-agent"));
// List<DLNAResource> res = root.getDLNAResources(id, false, 0, 0, renderer);
DLNAResource r = root.getDLNAResource(id, renderer);
if (r == null) {
LOGGER.debug("Bad web play id: " + id);
throw new IOException("Bad Id");
}
if (!r.isCodeValid(r)) {
LOGGER.debug("coded object with invalid code");
throw new IOException("Bad code");
}
if (r instanceof VirtualVideoAction) {
// waste of resource to play dummy video
if (((VirtualVideoAction) r).enable()) {
renderer.notify(renderer.INFO, r.getName() + " enabled");
} else {
renderer.notify(renderer.INFO, r.getName() + " disabled");
}
return returnPage();
}
Format format = r.getFormat();
boolean isImage = format.isImage();
boolean isVideo = format.isVideo();
boolean isAudio = format.isAudio();
String query = t.getRequestURI().getQuery();
boolean forceFlash = StringUtils.isNotEmpty(RemoteUtil.getQueryVars(query, "flash"));
boolean forcehtml5 = StringUtils.isNotEmpty(RemoteUtil.getQueryVars(query, "html5"));
boolean flowplayer = isVideo && (forceFlash || (!forcehtml5 && configuration.getWebFlash()));
// hack here to ensure we got a root folder to use for recently played etc.
root.getDefaultRenderer().setRootFolder(root);
String id1 = URLEncoder.encode(id, "UTF-8");
String name = StringEscapeUtils.escapeHtml(r.resumeName());
String mime = root.getDefaultRenderer().getMimeType(r.mimeType(), r.getMedia());
String mediaType = isVideo ? "video" : isAudio ? "audio" : isImage ? "image" : "";
String auto = "autoplay";
@SuppressWarnings("unused") String coverImage = "";
if (isVideo) {
if (mime.equals(FormatConfiguration.MIMETYPE_AUTO)) {
if (r.getMedia() != null && r.getMedia().getMimeType() != null) {
mime = r.getMedia().getMimeType();
}
}
if (!flowplayer) {
if (!RemoteUtil.directmime(mime) || RemoteUtil.transMp4(mime, r.getMedia()) || r.isResume()) {
WebRender render = (WebRender) r.getDefaultRenderer();
mime = render != null ? render.getVideoMimeType() : RemoteUtil.transMime();
}
}
}
vars.put("isVideo", isVideo);
vars.put("name", name);
vars.put("id1", id1);
vars.put("autoContinue", configuration.getWebAutoCont(format));
if (configuration.isDynamicPls()) {
if (r.getParent() instanceof Playlist) {
vars.put("plsOp", "del");
vars.put("plsSign", "-");
vars.put("plsAttr", RemoteUtil.getMsgString("Web.4", t));
} else {
vars.put("plsOp", "add");
vars.put("plsSign", "+");
vars.put("plsAttr", RemoteUtil.getMsgString("Web.5", t));
}
}
addNextByType(r, vars);
if (isImage) {
// do this like this to simplify the code
// skip all player crap since img tag works well
int delay = configuration.getWebImgSlideDelay() * 1000;
if (delay > 0 && configuration.getWebAutoCont(format)) {
vars.put("delay", delay);
}
} else {
vars.put("mediaType", mediaType);
vars.put("auto", auto);
vars.put("mime", mime);
if (flowplayer) {
if (RemoteUtil.directmime(mime) && !RemoteUtil.transMp4(mime, r.getMedia()) && !r.isResume() && !forceFlash) {
vars.put("src", true);
}
} else {
vars.put("width", renderer.getVideoWidth());
vars.put("height", renderer.getVideoHeight());
}
}
if (configuration.useWebControl()) {
vars.put("push", true);
}
if (isVideo && configuration.getWebSubs()) {
// only if subs are requested as <track> tags
// otherwise we'll transcode them in
boolean isFFmpegFontConfig = configuration.isFFmpegFontConfig();
if (isFFmpegFontConfig) {
// do not apply fontconfig to flowplayer subs
configuration.setFFmpegFontConfig(false);
}
OutputParams p = new OutputParams(configuration);
p.sid = r.getMediaSubtitle();
Player.setAudioAndSubs(r.getName(), r.getMedia(), p);
if (p.sid != null && p.sid.getType().isText()) {
try {
File subFile = SubtitleUtils.getSubtitles(r, r.getMedia(), p, configuration, SubtitleType.WEBVTT);
LOGGER.debug("subFile " + subFile);
if (subFile != null) {
vars.put("sub", parent.getResources().add(subFile));
}
} catch (Exception e) {
LOGGER.debug("error when doing sub file " + e);
}
}
// return back original fontconfig value
configuration.setFFmpegFontConfig(isFFmpegFontConfig);
}
return parent.getResources().getTemplate(isImage ? "image.html" : flowplayer ? "flow.html" : "play.html").execute(vars);
}
use of net.pms.io.OutputParams 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;
}
Aggregations