package javaforce.media;
/** Base class for Media Coders.
*
* @author pquiring
*/
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.zip.*;
import javaforce.*;
import javaforce.jni.*;
public class MediaCoder {
private long ctx = 0;
private static boolean inited = false;
public static boolean loaded = false;
static {
if (!inited) {
JFNative.load();
if (JFNative.loaded) {
init();
inited = true;
}
}
}
/** Loads the media framework native libraries. */
public static boolean init() {
if (loaded) return true;
boolean libav_org = false;
File sysFolders[];
String ext = "";
if (JF.isWindows()) {
sysFolders = new File[] {new File("."), new File(System.getenv("appdata") + "/ffmpeg")};
ext = ".dll";
} else {
sysFolders = new File[] {new File("/usr/lib"), new File("/usr/lib64")};
if (JF.isMac()) {
ext = ".dylib";
} else {
ext = ".so";
}
}
Library libs[] = {
new Library("avcodec")
, new Library("avdevice")
, new Library("avfilter")
, new Library("avformat")
, new Library("avutil")
, new Library("swscale")
, new Library("postproc")
, new Library("swresample", true) //(ffmpeg)
, new Library("avresample", true) //(libav_org)
};
JFNative.findLibraries(sysFolders, libs, ext, libs.length-1, true);
if (libs[6].path != null) {
libav_org = false;
} else if (libs[7].path != null) {
libav_org = true;
}
if (!haveLibs(libs)) {
for(int a=0;a<libs.length;a++) {
if (a == 7 && libav_org) continue;
if (a == 8 && !libav_org) continue;
if (libs[a].path == null) {
System.out.println("Error:Unable to load library:" + libs[a].name + ext);
}
}
// JFLog.logTrace("MediaCoder.init() failed");
return false;
}
loaded = ffmpeg_init(libs[0].path, libs[1].path, libs[2].path, libs[3].path
, libs[4].path, libs[5].path, libs[6].path, libav_org ? libs[8].path : libs[7].path, libav_org);
return loaded;
}
private static native boolean ffmpeg_init(String codec, String device, String filter, String format, String util, String scale, String postproc, String resample, boolean libav_org);
private static boolean haveLibs(Library libs[]) {
int cnt = 0;
for(int a=0;a<7;a++) {
if (libs[a].path != null) cnt++;
}
if (libs[7].path != null) cnt++;
else if (libs[8].path != null) cnt++;
return cnt == 8;
}
//constants
//constants
public static final int SEEK_SET = 0;
public static final int SEEK_CUR = 1;
public static final int SEEK_END = 2;
//for use with VideoDecoder
public static final int AV_CODEC_ID_NONE = 0;
public static final int AV_CODEC_ID_MPEG1VIDEO = 1;
public static final int AV_CODEC_ID_MPEG2VIDEO = 2;
public static final int AV_CODEC_ID_H263 = 5;
public static final int AV_CODEC_ID_MPEG4 = 13;
public static final int AV_CODEC_ID_H264 = 28;
public static final int AV_CODEC_ID_THEORA = 31;
public static final int AV_CODEC_ID_VP8 = 141;
//a few audio codecs
public static final int AV_CODEC_ID_PCM_S16LE = 0x10000; //wav file
public static final int AV_CODEC_ID_FLAC = 0x1500c;
//returned by MediaDecoder.read()
public static final int END_FRAME = -1;
public static final int NULL_FRAME = 0; //could be metadata frame
public static final int AUDIO_FRAME = 1;
public static final int VIDEO_FRAME = 2;
/** Downloads the codec pack for Windows (supports .zip or .7z) */
public static boolean download() {
if (!JF.isWindows()) {
JF.showError("Notice", "This application requires the codecpack which was not detected.\n"
+ "Please visit http://pquiring.github.io/javaforce/codecpack.html for more info.\n"
+ "Press OK to visit this page now");
JF.openURL("http://pquiring.github.io/javaforce/codecpack.html");
return false;
}
if (!JF.showConfirm("Notice", "This application requires the codecpack which was not detected.\n"
+ "Please visit http://pquiring.github.io/javaforce/codecpack.html for more info.\n"
+ "Press OK to download and install now.\n"
+ "Press CANCEL to visit website now.\n"))
{
JF.openURL("http://pquiring.github.io/javaforce/codecpack.html");
return false;
}
JFTask task = new JFTask() {
public boolean work() {
this.setTitle("Downloading CodecPack");
this.setLabel("Downloading CodecPack...");
this.setProgress(-1);
String destFolder = System.getenv("appdata") + "/ffmpeg";
try {
new File(destFolder).mkdir();
File file = new File(destFolder + "/$testfile$.tmp");
FileOutputStream fos = new FileOutputStream(file);
fos.close();
file.delete();
} catch (Exception e) {
this.setLabel("Download failed (no write access to folder)");
return false;
}
//first download latest URL from javaforce.sf.net
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new URL("http://pquiring.github.io/javaforce/codecpackwin"
+ (JF.is64Bit() ? "64" : "32") + ".html").openStream()));
String url = reader.readLine();
int zLength = JF.atoi(reader.readLine());
byte buf[] = new byte[64 * 1024];
int length = 0;
File zfile;
boolean z7;
int z7Length = 0;
String url7 = null;
String filename = null;
if (url.endsWith(".zip")) {
zfile = new File(destFolder + "\\codecpack.zip");
z7 = false;
} else if (url.endsWith(".7z")) {
zfile = new File(destFolder + "\\codecpack.7z");
z7 = true;
url7 = reader.readLine();
z7Length = JF.atoi(reader.readLine());
int i1 = url.lastIndexOf("/")+1;
int i2 = url.lastIndexOf(".");
filename = url.substring(i1,i2);
} else {
JF.showError("Error", "Unsupported file type");
return false;
}
{
URL urlAddr = new URL(url);
URLConnection conn = urlAddr.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393");
conn.connect();
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(zfile);
System.out.println("Downloading:" + url);
while (true) {
int read = is.read(buf);
if (read == -1) break;
if (read == 0) {
JF.sleep(10);
continue;
}
fos.write(buf, 0, read);
length += read;
this.setProgress(length * 100 / zLength);
}
fos.close();
if (length != zLength) {
this.setLabel("Download failed...");
return false;
}
}
if (z7) {
//download 7za.exe (~500KB)
URL urlAddr = new URL(url7);
URLConnection conn = urlAddr.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393");
conn.connect();
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(new File(destFolder + "/7za.exe"));
length = 0;
System.out.println("Downloading:" + url7);
while (true) {
int read = is.read(buf);
if (read == -1) break;
if (read == 0) {
JF.sleep(10);
continue;
}
fos.write(buf, 0, read);
length += read;
}
fos.close();
if (length != z7Length) {
this.setLabel("Download failed (7za.exe)...");
return false;
}
}
this.setLabel("Download complete, now installing...");
this.setProgress(0);
if (z7) {
ShellProcess sp = new ShellProcess();
// sp.setFolder(new File(destFolder));
System.out.println("Exec:7za e " + zfile.getName()+ " " + filename+"/bin/*.dll");
sp.run(new String[]{"7za.exe", "e", zfile.getName(), filename+"\\bin\\*.dll"}, false);
} else {
ZipFile zf = new ZipFile(zfile);
int cnt = 0;
FileOutputStream fos;
for (Enumeration e = zf.entries(); e.hasMoreElements();) {
ZipEntry ze = (ZipEntry)e.nextElement();
String name = ze.getName().toLowerCase();
if (!name.endsWith(".dll")) continue;
int idx = name.lastIndexOf("/");
if (idx != -1) {
name = name.substring(idx+1); //remove any path
}
fos = new FileOutputStream(destFolder + "\\" + name);
InputStream zis = zf.getInputStream(ze);
JFLog.log("extracting:" + name + ",length=" + ze.getSize());
JF.copyAll(zis, fos, ze.getSize());
zis.close();
fos.close();
cnt++;
this.setProgress(cnt * 100 / 8);
}
}
this.setProgress(100);
this.setLabel("Install complete");
return true;
} catch (Exception e) {
this.setLabel("An error occured, see console output for details.");
JFLog.log(e);
return false;
}
}
};
new ProgressDialog(null, true, task).setVisible(true);
return task.getStatus();
}
}