Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
full rework on archives files.
implements archive directory handle.
  • Loading branch information
SurfaceS authored Oct 31, 2024
1 parent 3847782 commit 166e582
Show file tree
Hide file tree
Showing 15 changed files with 801 additions and 452 deletions.
6 changes: 5 additions & 1 deletion src/main/java/net/pms/encoders/FFmpegHlsVideo.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ public synchronized ProcessWrapper launchTranscode(
cmdList.add("-sn");
}
cmdList.add("-i");
cmdList.add(filename);
if (params.getStdIn() != null) {
cmdList.add("pipe:");
} else {
cmdList.add(filename);
}

if (needSubtitle) {
cmdList.add("-map");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,13 @@ private static void sendMediaResponse(HttpServletRequest req, HttpServletRespons
//only time seek, transcoded
resp.setHeader("ContentFeatures.DLNA.ORG", "DLNA.ORG_OP=10;DLNA.ORG_CI=01;DLNA.ORG_FLAGS=01700000000000000000000000000000");

if (item.getMediaInfo().getDurationInSeconds() > 0) {
if (item.getMediaInfo() != null && item.getMediaInfo().getDurationInSeconds() > 0) {
String durationStr = String.format(Locale.ENGLISH, "%.3f", item.getMediaInfo().getDurationInSeconds());
resp.setHeader("TimeSeekRange.dlna.org", "npt=0-" + durationStr + "/" + durationStr);
resp.setHeader("X-AvailableSeekRange", "npt=0-" + durationStr);
}
}
if (samsungMediaInfo != null && item.getMediaInfo().getDurationInSeconds() > 0) {
if (samsungMediaInfo != null && item.getMediaInfo() != null && item.getMediaInfo().getDurationInSeconds() > 0) {
resp.setHeader("MediaInfo.sec", "SEC_Duration=" + (long) (item.getMediaInfo().getDurationInSeconds() * 1000));
}

Expand Down Expand Up @@ -578,7 +578,7 @@ private static void sendMediaResponse(HttpServletRequest req, HttpServletRespons
resp.setHeader("ContentFeatures.DLNA.ORG", DlnaHelper.getDlnaContentFeatures(item));
}

if (samsungMediaInfo != null && item.getMediaInfo().getDurationInSeconds() > 0) {
if (samsungMediaInfo != null && item.getMediaInfo() != null && item.getMediaInfo().getDurationInSeconds() > 0) {
resp.setHeader("MediaInfo.sec", "SEC_Duration=" + (long) (item.getMediaInfo().getDurationInSeconds() * 1000));
}

Expand All @@ -591,7 +591,7 @@ private static void sendMediaResponse(HttpServletRequest req, HttpServletRespons
}
}

if (timeseekrange.isStartOffsetAvailable()) {
if (timeseekrange.isStartOffsetAvailable() && item.getMediaInfo() != null) {
// Add timeseek information headers.
String timeseekValue = StringUtil.formatDLNADuration(timeseekrange.getStartOrZero());
String timetotalValue = item.getMediaInfo().getDurationString();
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/net/pms/parsers/FFmpegParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,18 @@ public static void parse(MediaInfo media, InputFile inputFile, Format ext, int t

boolean ffmpegParsing = true;

if (type == Format.AUDIO || ext instanceof AudioAsVideo) {
if (file != null && type == Format.AUDIO || ext instanceof AudioAsVideo) {
ffmpegParsing = false;
JaudiotaggerParser.parse(media, file, ext);
}

if (type == Format.IMAGE && file != null) {
if (type == Format.IMAGE) {
try {
ffmpegParsing = false;
MetadataExtractorParser.parse(file, media);
MetadataExtractorParser.parse(inputFile, media);
media.setImageCount(media.getImageCount() + 1);
} catch (IOException e) {
LOGGER.debug("Error parsing image \"{}\", switching to FFmpeg: {}", file.getAbsolutePath(), e.getMessage());
LOGGER.debug("Error parsing image \"{}\", switching to FFmpeg: {}", inputFile.getFilename(), e.getMessage());
LOGGER.trace("", e);
ffmpegParsing = true;
}
Expand Down Expand Up @@ -305,7 +305,7 @@ public static void parseFFmpegInfo(MediaInfo media, List<String> lines, String i
if (line.startsWith("Output")) {
matches = false;
} else if (line.startsWith("Input")) {
if (line.contains(input)) {
if (line.contains(input) || line.contains("from 'fd:':")) {
matches = true;
media.setContainer(line.substring(10, line.indexOf(',', 11)).trim());

Expand Down
79 changes: 62 additions & 17 deletions src/main/java/net/pms/parsers/MetadataExtractorParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collection;
Expand All @@ -74,6 +76,7 @@
import net.pms.image.ImageIOTools;
import net.pms.image.ImageInfo;
import net.pms.media.MediaInfo;
import net.pms.util.InputFile;
import net.pms.util.ParseException;
import net.pms.util.ResettableInputStream;
import net.pms.util.UnknownFormatException;
Expand All @@ -91,6 +94,22 @@ public class MetadataExtractorParser {
private MetadataExtractorParser() {
}

public static void parse(InputFile inputFile, MediaInfo mediaInfo) throws IOException {
if (inputFile.getFile() != null) {
parse(inputFile.getFile(), mediaInfo);
} else if (inputFile.getPush() != null) {
try (PipedOutputStream out = new PipedOutputStream(); InputStream fis = new PipedInputStream(out)) {
inputFile.getPush().push(out);
parseStream(fis, inputFile.getSize(), inputFile.getFilename(), mediaInfo);
} catch (IOException e) {
LOGGER.debug("Error reading \"{}\": {}", inputFile.getFilename(), e.getMessage());
LOGGER.trace("", e);
}
} else {
throw new IllegalArgumentException("parseImage: inputFile cannot be null");
}
}

/**
* Parses an image file and stores the results in the given
* {@link MediaInfo}. Parsing is performed using both
Expand All @@ -110,20 +129,46 @@ private MetadataExtractorParser() {
*
*/
public static void parse(File file, MediaInfo mediaInfo) throws IOException {
long size = file.length();
InputStream fis = Files.newInputStream(file.toPath());
String filename = file.getAbsolutePath();
parseStream(fis, size, filename, mediaInfo);
}

/**
* Parses an image stream and stores the results in the given
* {@link MediaInfo}. Parsing is performed using both
* <a href=https://github.com/drewnoakes/metadata-extractor>Metadata Extractor</a>
* and {@link ImageIO}. While Metadata Extractor offers more detailed
* information, {@link ImageIO} offers information that is convenient for
* image transformation with {@link ImageIO}. Parsing will be performed if
* just one of the two methods produces results, but some details will be
* missing if either one failed.
* <p><b>
* This method consumes and closes {@code inputStream}.
* </b>
* @param stream the {@link InputStream} to parse.
* @param size the size.
* @param filename the filename for debug.
* @param mediaInfo the {@link MediaInfo} instance to store the parsing
* results to.
* @throws IOException if an IO error occurs or no information can be parsed.
*
*/
private static void parseStream(InputStream stream, long size, String filename, MediaInfo mediaInfo) throws IOException {
final int maxBuffer = 1048576; // 1 MB
if (file == null) {
throw new IllegalArgumentException("parseImage: file cannot be null");
if (stream == null) {
throw new IllegalArgumentException("parseImage: stream cannot be null");
}
if (mediaInfo == null) {
throw new IllegalArgumentException("parseImage: media cannot be null");
}

boolean trace = LOGGER.isTraceEnabled();
if (trace) {
LOGGER.trace("Parsing image file \"{}\"", file.getAbsolutePath());
LOGGER.trace("Parsing image file \"{}\"", filename);
}
long size = file.length();
ResettableInputStream inputStream = new ResettableInputStream(Files.newInputStream(file.toPath()), maxBuffer);
ResettableInputStream inputStream = new ResettableInputStream(stream, maxBuffer);
try {
Metadata metadata;
FileType fileType = null;
Expand All @@ -132,14 +177,14 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
metadata = getMetadata(inputStream, fileType);
} catch (IOException e) {
metadata = new Metadata();
LOGGER.debug("Error reading \"{}\": {}", file.getAbsolutePath(), e.getMessage());
LOGGER.debug("Error reading \"{}\": {}", filename, e.getMessage());
LOGGER.trace("", e);
} catch (ImageProcessingException e) {
metadata = new Metadata();
LOGGER.debug(
"Error parsing {} metadata for \"{}\": {}",
fileType != null ? fileType.toString().toUpperCase(Locale.ROOT) : "null",
file.getAbsolutePath(),
filename,
e.getMessage()
);
LOGGER.trace("", e);
Expand All @@ -157,21 +202,21 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
} else {
// If we can't reset it, close it and create a new
inputStream.close();
inputStream = new ResettableInputStream(Files.newInputStream(file.toPath()), maxBuffer);
inputStream = new ResettableInputStream(stream, maxBuffer);
}
ImageInfo imageInfo = null;
try {
imageInfo = readImageInfo(inputStream, size, metadata, false);
} catch (UnknownFormatException | IIOException | ParseException e) {
if (format == null) {
throw new UnknownFormatException(
"Unable to recognize image format for \"" + file.getAbsolutePath() + "\" - parsing failed",
"Unable to recognize image format for \"" + filename + "\" - parsing failed",
e
);
}
LOGGER.debug(
"Unable to parse \"{}\" with ImageIO because the format is unsupported, image information will be limited",
file.getAbsolutePath()
filename
);
LOGGER.trace("ImageIO parse failure reason: {}", e.getMessage());

Expand All @@ -180,14 +225,14 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
try {
imageInfo = ImageInfo.create(metadata, format, size, true, true);
} catch (ParseException pe) {
LOGGER.debug("Unable to parse metadata for \"{}\": {}", file.getAbsolutePath(), pe.getMessage());
LOGGER.debug("Unable to parse metadata for \"{}\": {}", filename, pe.getMessage());
LOGGER.trace("", pe);
}
}
}

if (imageInfo == null && format == null) {
throw new ParseException("Parsing of \"" + file.getAbsolutePath() + "\" failed");
throw new ParseException("Parsing of \"" + filename + "\" failed");
}

if (format == null && imageInfo != null) {
Expand All @@ -204,7 +249,7 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
LOGGER.trace(
"Correcting misidentified image format ARW to {} for \"{}\"",
format,
file.getAbsolutePath()
filename
);
} else {
/*
Expand All @@ -228,14 +273,14 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
LOGGER.trace(
"Correcting misidentified image format TIFF to {} for \"{}\"",
format.toString(),
file.getAbsolutePath()
filename
);
}
} else {
LOGGER.debug(
"Image parsing for \"{}\" was inconclusive, metadata parsing " +
"detected {} format while ImageIO detected {}. Choosing {}.",
file.getAbsolutePath(),
filename,
format,
imageInfo.getFormat(),
imageInfo.getFormat()
Expand All @@ -248,11 +293,11 @@ public static void parse(File file, MediaInfo mediaInfo) throws IOException {
if (format != null) {
mediaInfo.setContainer(format.toFormatConfiguration());
}
mediaInfo.setSize(file.length());
mediaInfo.setSize(size);
mediaInfo.setMediaParser(PARSER_NAME);
Parser.postParse(mediaInfo, Format.IMAGE);
if (trace) {
LOGGER.trace("Parsing of image \"{}\" completed", file.getName());
LOGGER.trace("Parsing of image \"{}\" completed", filename);
}
} finally {
inputStream.close();
Expand Down
57 changes: 14 additions & 43 deletions src/main/java/net/pms/store/container/RarredFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,35 @@
*/
package net.pms.store.container;

import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import com.github.junrar.volume.FileVolumeManager;
import java.io.File;
import java.io.IOException;
import java.util.List;
import net.pms.renderers.Renderer;
import net.pms.store.StoreContainer;
import net.pms.store.item.RarredEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.pms.store.SystemFileResource;

public class RarredFile extends StoreContainer {
private static final Logger LOGGER = LoggerFactory.getLogger(RarredFile.class);
private File f;
private Archive rarFile;
public class RarredFile extends RarredFolder implements SystemFileResource {

public RarredFile(Renderer renderer, File f) {
super(renderer, f.getName(), null);
this.f = f;
setLastModified(f.lastModified());

try {
rarFile = new Archive(new FileVolumeManager(f), null, null);
List<FileHeader> headers = rarFile.getFileHeaders();

for (FileHeader fh : headers) {
// if (fh.getFullUnpackSize() < MAX_ARCHIVE_ENTRY_SIZE && fh.getFullPackSize() < MAX_ARCHIVE_ENTRY_SIZE)
addChild(new RarredEntry(renderer, fh.getFileName(), f, fh.getFileName(), fh.getFullUnpackSize()));
}
public RarredFile(Renderer renderer, File file) {
super(renderer, file, "");
setLastModified(file.lastModified());
}

rarFile.close();
} catch (RarException | IOException e) {
LOGGER.error(null, e);
}
@Override
public String getName() {
return file.getName();
}

@Override
public long length() {
return f.length();
return file.length();
}

@Override
public String getSystemName() {
return f.getAbsolutePath();
return file.getAbsolutePath();
}

@Override
public boolean isValid() {
boolean t = false;

try {
t = f.exists() && !rarFile.isEncrypted();
} catch (RarException th) {
LOGGER.debug("Caught exception", th);
}

return t;
public File getSystemFile() {
return file;
}

}
Loading

0 comments on commit 166e582

Please sign in to comment.