Refactor MediaInfo.open(File) to throw IOException on error

This commit is contained in:
Reinhard Pointner 2016-03-11 08:16:59 +00:00
parent 8773e3b183
commit aca56eac9a
6 changed files with 48 additions and 67 deletions

View File

@ -34,6 +34,8 @@ import java.util.TreeSet;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.cedarsoftware.util.io.JsonWriter;
import net.filebot.Cache; import net.filebot.Cache;
import net.filebot.CacheType; import net.filebot.CacheType;
import net.filebot.Language; import net.filebot.Language;
@ -45,6 +47,7 @@ import net.filebot.hash.HashType;
import net.filebot.media.MetaAttributes; import net.filebot.media.MetaAttributes;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind; import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.mediainfo.MediaInfoException;
import net.filebot.similarity.SimilarityComparator; import net.filebot.similarity.SimilarityComparator;
import net.filebot.util.FileUtilities; import net.filebot.util.FileUtilities;
import net.filebot.util.WeakValueHashMap; import net.filebot.util.WeakValueHashMap;
@ -60,8 +63,6 @@ import net.filebot.web.SortOrder;
import net.filebot.web.TMDbClient.MovieInfo; import net.filebot.web.TMDbClient.MovieInfo;
import net.filebot.web.TheTVDBSeriesInfo; import net.filebot.web.TheTVDBSeriesInfo;
import com.cedarsoftware.util.io.JsonWriter;
public class MediaBindingBean { public class MediaBindingBean {
private final Object infoObject; private final Object infoObject;
@ -960,15 +961,13 @@ public class MediaBindingBean {
File inferredMediaFile = getInferredMediaFile(); File inferredMediaFile = getInferredMediaFile();
synchronized (sharedMediaInfoObjects) { synchronized (sharedMediaInfoObjects) {
mediaInfo = sharedMediaInfoObjects.get(inferredMediaFile); mediaInfo = sharedMediaInfoObjects.computeIfAbsent(inferredMediaFile, f -> {
if (mediaInfo == null) { try {
MediaInfo mi = new MediaInfo(); return new MediaInfo().open(f);
if (!mi.open(inferredMediaFile)) { } catch (Exception e) {
throw new RuntimeException("Cannot open media file: " + inferredMediaFile); throw new MediaInfoException(e.getMessage());
} }
sharedMediaInfoObjects.put(inferredMediaFile, mi); });
mediaInfo = mi;
}
} }
} }

View File

@ -1,5 +1,7 @@
package net.filebot.mediainfo; package net.filebot.mediainfo;
import static net.filebot.Logging.*;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
@ -25,12 +27,11 @@ public class MediaDurationFilter implements FileFilter {
public long getDuration(File file) { public long getDuration(File file) {
synchronized (mediaInfo) { synchronized (mediaInfo) {
if (mediaInfo.open(file)) { try {
try { String duration = mediaInfo.open(file).get(StreamKind.General, 0, "Duration");
return Long.parseLong(mediaInfo.get(StreamKind.General, 0, "Duration")); return Long.parseLong(duration);
} catch (NumberFormatException e) { } catch (Exception e) {
// ignore, assume duration couldn't be read debug.warning("Failed to read video duration: " + e.getMessage());
}
} }
} }
return -1; return -1;

View File

@ -1,7 +1,5 @@
package net.filebot.mediainfo; package net.filebot.mediainfo;
import static net.filebot.Logging.*;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -29,31 +27,35 @@ public class MediaInfo implements Closeable {
} }
} }
public synchronized boolean open(File file) { public synchronized MediaInfo open(File file) throws IOException {
if (!file.isFile() || file.length() < 64 * 1024) { if (!file.isFile() || file.length() < 64 * 1024) {
return false; throw new IllegalArgumentException("Invalid media file: " + file);
} }
String path = file.getAbsolutePath(); String path = file.getCanonicalPath();
// on Mac files that contain accents cannot be opened via JNA WString file paths due to encoding differences so we use the buffer interface instead for these files // on Mac files that contain accents cannot be opened via JNA WString file paths due to encoding differences so we use the buffer interface instead for these files
if (Platform.isMac() && !StandardCharsets.US_ASCII.newEncoder().canEncode(path)) { if (Platform.isMac() && !StandardCharsets.US_ASCII.newEncoder().canEncode(path)) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
return openViaBuffer(raf); if (openViaBuffer(raf)) {
} catch (IOException e) { throw new IOException("Failed to initialize media info buffer: " + path);
debug.warning("Failed to open random access file: " + e.getMessage()); }
return false;
} }
} }
return MediaInfoLibrary.INSTANCE.Open(handle, new WString(path)) > 0; if (0 == MediaInfoLibrary.INSTANCE.Open(handle, new WString(path))) {
// failed to open file
throw new IOException("Failed to open media file: " + path);
}
return this;
} }
private boolean openViaBuffer(RandomAccessFile f) throws IOException { private boolean openViaBuffer(RandomAccessFile f) throws IOException {
byte[] buffer = new byte[4 * 1024 * 1024]; // use large buffer to reduce JNA calls byte[] buffer = new byte[4 * 1024 * 1024]; // use large buffer to reduce JNA calls
int read = -1; int read = -1;
if (MediaInfoLibrary.INSTANCE.Open_Buffer_Init(handle, f.length(), 0) <= 0) { if (0 == MediaInfoLibrary.INSTANCE.Open_Buffer_Init(handle, f.length(), 0)) {
return false; return false;
} }
@ -249,15 +251,9 @@ public class MediaInfo implements Closeable {
* Helper for easy usage * Helper for easy usage
*/ */
public static Map<StreamKind, List<Map<String, String>>> snapshot(File file) throws IOException { public static Map<StreamKind, List<Map<String, String>>> snapshot(File file) throws IOException {
MediaInfo mi = new MediaInfo(); try (MediaInfo mi = new MediaInfo()) {
try { return mi.open(file).snapshot();
if (mi.open(file)) {
return mi.snapshot();
} else {
throw new IOException("Failed to open file: " + file);
}
} finally {
mi.close();
} }
} }
} }

View File

@ -193,20 +193,19 @@ public enum SubtitleMetrics implements SimilarityMetric {
return mediaInfoCache.computeIfAbsent(file, (f) -> { return mediaInfoCache.computeIfAbsent(file, (f) -> {
try { try {
Map<String, Object> props = new HashMap<String, Object>(); Map<String, Object> props = new HashMap<String, Object>();
MediaInfo mediaInfo = new MediaInfo(); MediaInfo mediaInfo = new MediaInfo().open(file);
if (mediaInfo.open(file)) {
float fps = round(Float.parseFloat(mediaInfo.get(StreamKind.Video, 0, "FrameRate"))); float fps = round(Float.parseFloat(mediaInfo.get(StreamKind.Video, 0, "FrameRate")));
if (fps > 0) { if (fps > 0) {
props.put(FPS, fps); props.put(FPS, fps);
}
long seconds = (long) floor(Long.parseLong(mediaInfo.get(StreamKind.Video, 0, "Duration")) / (double) 1000);
if (seconds > 0) {
props.put(SECONDS, seconds);
}
return props;
} }
long seconds = (long) floor(Long.parseLong(mediaInfo.get(StreamKind.Video, 0, "Duration")) / (double) 1000);
if (seconds > 0) {
props.put(SECONDS, seconds);
}
return props;
} catch (Exception e) { } catch (Exception e) {
debug.warning("Failed to read video properties: " + e); debug.warning("Failed to read video properties: " + e.getMessage());
} }
return emptyMap(); return emptyMap();
}); });

View File

@ -54,7 +54,6 @@ import net.filebot.format.MediaBindingBean;
import net.filebot.media.MediaDetection; import net.filebot.media.MediaDetection;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind; import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.mediainfo.MediaInfoException;
import net.filebot.util.DefaultThreadFactory; import net.filebot.util.DefaultThreadFactory;
import net.filebot.util.FileUtilities.ExtensionFileFilter; import net.filebot.util.FileUtilities.ExtensionFileFilter;
import net.filebot.util.ui.LazyDocumentListener; import net.filebot.util.ui.LazyDocumentListener;
@ -293,22 +292,11 @@ class BindingDialog extends JDialog {
private Map<StreamKind, List<Map<String, String>>> getMediaInfo(File file) { private Map<StreamKind, List<Map<String, String>>> getMediaInfo(File file) {
try { try {
MediaInfo mediaInfo = new MediaInfo(); return MediaInfo.snapshot(file);
} catch (Exception e) {
// read all media info
if (mediaInfo.open(file)) {
try {
return mediaInfo.snapshot();
} finally {
mediaInfo.close();
}
}
} catch (MediaInfoException e) {
log.log(Level.SEVERE, e.getMessage(), e); log.log(Level.SEVERE, e.getMessage(), e);
return null;
} }
// could not retrieve media info
return null;
} }
@Override @Override

View File

@ -15,7 +15,6 @@ import javax.swing.Icon;
import net.filebot.ResourceManager; import net.filebot.ResourceManager;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind; import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.mediainfo.MediaInfoException;
public class ID3Lookup implements MusicIdentificationService { public class ID3Lookup implements MusicIdentificationService {
@ -36,9 +35,8 @@ public class ID3Lookup implements MusicIdentificationService {
try (MediaInfo mediaInfo = new MediaInfo()) { try (MediaInfo mediaInfo = new MediaInfo()) {
for (File f : filter(files, AUDIO_FILES, VIDEO_FILES)) { for (File f : filter(files, AUDIO_FILES, VIDEO_FILES)) {
try { try {
if (!mediaInfo.open(f)) { // open or throw exception
throw new MediaInfoException("Failed to read media info: " + f); mediaInfo.open(f);
}
// artist and song title information is required // artist and song title information is required
String artist = getString(mediaInfo, "Performer", "Composer"); String artist = getString(mediaInfo, "Performer", "Composer");