package net.filebot.media;
import static java.util.Comparator.*;
import static net.filebot.MediaTypes.*;
import static net.filebot.media.CachedMediaCharacteristics.*;
import static net.filebot.media.MediaDetection.*;
import static net.filebot.media.MediaFileUtilities.*;
import static net.filebot.util.StringUtilities.*;
import java.io.File;
import java.util.Comparator;
import java.util.regex.Pattern;
public class VideoQuality implements Comparator<File> {
public static final Comparator<File> DESCENDING_ORDER = new VideoQuality(VideoFormat.DEFAULT_GROUPS, releaseInfo.getRepackPattern()).reversed();
public static boolean isBetter(File f1, File f2) {
return DESCENDING_ORDER.compare(f1, f2) < 0;
}
private final VideoFormat quality;
private final Pattern repack;
public VideoQuality(VideoFormat quality, Pattern repack) {
this.quality = quality;
this.repack = repack;
}
private final Comparator<File> chain = comparingInt(this::getQuality)
.thenComparing(VideoCodec::compare)
.thenComparingInt(this::getRepack)
.thenComparingDouble(this::getScore)
.thenComparingLong(File::length);
@Override
public int compare(File f1, File f2) {
return chain.compare(getPrimaryFile(f1), getPrimaryFile(f2));
}
private File getPrimaryFile(File f) {
return findPrimaryFile(f, VIDEO_FILES).orElse(f);
}
private int getRepack(File f) {
return find(f.getName(), repack) ? 1 : 0;
}
private int getQuality(File f) {
// use primary video file when checking video resolution of subtitle files or disk folders
return getMediaCharacteristics(f, mi -> {
Integer w = mi.getWidth();
Integer h = mi.getHeight();
// invalid media file
if (w == null || h == null) {
return null;
}
return quality.guessFormat(w, h);
}).orElse(Integer.MIN_VALUE);
}
private double getScore(File f) {
// use primary video file when checking video resolution of subtitle files or disk folders
return getMediaCharacteristics(f, mi -> {
Integer w = mi.getWidth();
Integer h = mi.getHeight();
Double br = mi.getBitRate();
// invalid media file
if (w == null || h == null || br == null) {
return null;
}
return w * h * br;
}).orElse(Double.MIN_VALUE);
}
public enum VideoCodec {
MPEG, AVC, HEVC;
public static VideoCodec get(MediaCharacteristics mi) {
switch (mi.getVideoCodec()) {
case "HEVC":
return HEVC;
case "AVC":
return AVC;
case "MPEG-4 Visual":
return MPEG;
}
// print missing codec name
throw new UnsupportedOperationException("Unknown Video Codec: " + mi.getVideoCodec());
}
public static int compare(File f1, File f2) {
VideoCodec vc1 = getMediaCharacteristics(f1, VideoCodec::get).orElse(null);
VideoCodec vc2 = getMediaCharacteristics(f2, VideoCodec::get).orElse(null);
if (vc1 == null || vc2 == null) {
return 0;
}
return vc1.compareTo(vc2);
}
}
}
Comments