From dbeba831a571dd45ba9622b5e4e742c0966f903f Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 13 Oct 2017 13:53:47 +0200 Subject: [PATCH] Added instance() method in Factory object of generated Java wrapper --- wrappers/java/CMakeLists.txt | 2 +- wrappers/java/classes/tools/H264Helper.java | 79 ++++++ wrappers/java/classes/tools/Lpc2Xml.java | 68 +++++ .../classes/tools/OpenH264DownloadHelper.java | 240 ++++++++++++++++++ wrappers/java/classes/tools/Xml2Lpc.java | 73 ++++++ wrappers/java/java_class.mustache | 66 ++++- wrappers/java/migration.sh | 4 + 7 files changed, 523 insertions(+), 9 deletions(-) create mode 100644 wrappers/java/classes/tools/H264Helper.java create mode 100644 wrappers/java/classes/tools/Lpc2Xml.java create mode 100644 wrappers/java/classes/tools/OpenH264DownloadHelper.java create mode 100644 wrappers/java/classes/tools/Xml2Lpc.java diff --git a/wrappers/java/CMakeLists.txt b/wrappers/java/CMakeLists.txt index 7dcb317fb..c6d29d950 100644 --- a/wrappers/java/CMakeLists.txt +++ b/wrappers/java/CMakeLists.txt @@ -41,4 +41,4 @@ add_custom_target(linphonej ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/src/linphon set(LINPHONE_JNI_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc" PARENT_SCOPE) install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/java" DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/") -install(DIRECTORY classes/ DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/java/org/linphone/core/" FILES_MATCHING PATTERN "*.java") \ No newline at end of file +install(DIRECTORY classes/ DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/java/org/linphone/core/") diff --git a/wrappers/java/classes/tools/H264Helper.java b/wrappers/java/classes/tools/H264Helper.java new file mode 100644 index 000000000..421d44f6f --- /dev/null +++ b/wrappers/java/classes/tools/H264Helper.java @@ -0,0 +1,79 @@ +package org.linphone.core.tools; + + +import android.os.Build; + +import org.linphone.core.LinphoneCore; +import org.linphone.mediastream.Log; + +/** + * Created by brieucviel on 09/12/2016. + */ + +public class H264Helper { + private static String FILTER_NAME_OPENH264_ENC = "MSOpenH264Enc" ; + private static String FILTER_NAME_OPENH264_DEC = "MSOpenH264Dec" ; + private static String FILTER_NAME_MEDIA_CODEC_ENC = "MSMediaCodecH264Enc" ; + private static String FILTER_NAME_MEDIA_CODEC_DEC = "MSMediaCodecH264Dec" ; + + public static String MODE_AUTO = "Auto" ; + public static String MODE_OPENH264 = "OpenH264" ; + public static String MODE_MEDIA_CODEC = "MediaCodec" ; + + + /** + * H264Helper + */ + public H264Helper() { + } + + + /** + * Define the Codec to use between MediaCodec and OpenH264 + * Possible mode are: + * - Auto to let the system choose in function of you OS version, + * - OpenH264 to enable OpenH264 Encoder and Decoder, + * - Mediacodec to enable Mediacodec only. + * @param mode String value between Auto, OpenH264 and MediaCodec + */ + public static void setH264Mode(String mode, LinphoneCore linphoneCore){ + if(mode.equals(MODE_OPENH264)){ + Log.i("H264Helper"," setH264Mode MODE_OPENH264 - Mode = "+mode); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , true); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , true); + }else if(mode.equals(MODE_MEDIA_CODEC)){ + Log.i("H264Helper"," setH264Mode MODE_MEDIA_CODEC - Mode = "+mode); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , true); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , true); + }else if(mode.equals(MODE_AUTO)){ + Log.i("H264Helper"," setH264Mode MODE_AUTO - Mode = "+mode); + // if android >= 5.0 use MediaCodec + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + Log.i("H264Helper"," setH264Mode MODE_AUTO 1 - Mode = "+mode); + Log.i("H264Helper"," Openh264 disabled on the project, now using MediaCodec"); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , true); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , true); + } + //otherwise use OpenH264 + else{ + Log.i("H264Helper"," setH264Mode MODE_AUTO 2 - Mode = "+mode); + Log.i("H264Helper"," Openh264 enabled on the project"); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , false); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , true); + linphoneCore.getMSFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , true); + } + }else { + Log.i("H264Helper"," Error: Openh264 mode not reconized !"); + } + Log.i("H264Helper"," setH264Mode - Mode = "+mode); + } + +} + diff --git a/wrappers/java/classes/tools/Lpc2Xml.java b/wrappers/java/classes/tools/Lpc2Xml.java new file mode 100644 index 000000000..e61f4d2df --- /dev/null +++ b/wrappers/java/classes/tools/Lpc2Xml.java @@ -0,0 +1,68 @@ +package org.linphone.core.tools; + +import org.linphone.core.LpConfig; +import org.linphone.mediastream.Log; + +public class Lpc2Xml { + + private enum LogLevel { + DEBUG, + MESSAGE, + WARNING, + ERROR, + } + + private static boolean mAvailable; + + private long internalPtr = 0; + + private native void init(); + private native void destroy(); + + public Lpc2Xml() { + init(); + } + + public void finalize() { + destroy(); + } + + public native int setLpc(LpConfig lpc); + + public native int convertFile(String file); + public native int convertString(StringBuffer content); + + public void printLog(int level, String message) { + if(level > 0 && level < LogLevel.values().length) { + switch(LogLevel.values()[level]) { + case DEBUG: + Log.d(message); + break; + case MESSAGE: + Log.i(message); + break; + case WARNING: + Log.w(message); + break; + case ERROR: + Log.e(message); + break; + } + } + } + + static boolean isAvailable() { + return mAvailable; + } + + // Load library + static { + try { + System.loadLibrary("xml2"); + //System.loadLibrary("lpc2xml"); + mAvailable = true; + } catch (Throwable e) { + mAvailable = false; + } + } +} diff --git a/wrappers/java/classes/tools/OpenH264DownloadHelper.java b/wrappers/java/classes/tools/OpenH264DownloadHelper.java new file mode 100644 index 000000000..fc81245f4 --- /dev/null +++ b/wrappers/java/classes/tools/OpenH264DownloadHelper.java @@ -0,0 +1,240 @@ +package org.linphone.core.tools; +/* +CodecDownloader.java +Copyright (C) 2016 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.content.Context; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; + +import org.apache.commons.compress.compressors.bzip2.*; +import org.linphone.core.OpenH264DownloadHelperListener; +import org.linphone.mediastream.Log; + +/** + * @author Erwan Croze + */ +public class OpenH264DownloadHelper { + private OpenH264DownloadHelperListener openH264DownloadHelperListener; + private ArrayList userData; + private String fileDirection; + private String nameLib; + private String urlDownload; + private String nameFileDownload; + private String licenseMessage; + + /** + * Default values + * nameLib = "libopenh264-1.5.so" + * urlDownload = "http://ciscobinary.openh264.org/libopenh264-1.5.0-android19.so.bz2" + * nameFileDownload = "libopenh264-1.5.0-android19.so.bz2" + */ + public OpenH264DownloadHelper(Context context) { + userData = new ArrayList(); + licenseMessage = "OpenH264 Video Codec provided by Cisco Systems, Inc."; + nameLib = "libopenh264.so"; + urlDownload = "http://ciscobinary.openh264.org/libopenh264-1.5.0-android19.so.bz2"; + nameFileDownload = "libopenh264-1.5.0-android19.so.bz2"; + if(context.getFilesDir() != null) { + fileDirection = context.getFilesDir().toString(); + } + } + + /** + * Set OpenH264DownloadHelperListener + * @param h264Listener + */ + public void setOpenH264HelperListener(OpenH264DownloadHelperListener h264Listener) { + openH264DownloadHelperListener = h264Listener; + } + + /** + * @return OpenH264DownloadHelperListener + */ + public OpenH264DownloadHelperListener getOpenH264DownloadHelperListener() { + return openH264DownloadHelperListener; + } + + /** + * @param index of object in UserData list + * constraints (index superior or egal to 0 and index inferior to userData.size()) + * @return object if constraints are met + */ + public Object getUserData(int index) { + if (index < 0 || index >= userData.size()) return null; + return userData.get(index); + } + + /** + * Adding of object into UserData list + * @param object + * @return index of object in UserData list + */ + public int setUserData(Object object) { + this.userData.add(object); + return this.userData.indexOf(object); + } + + /** + * @param index + * @param object + * constraints (index superior or egal to 0 and index inferior to userData.size()) + */ + public void setUserData(int index, Object object) { + if (index < 0 || index > userData.size()) return; + this.userData.add(index,object); + } + + /** + * @return size of UserData list + */ + public int getUserDataSize() { + return this.userData.size(); + } + + /** + * @return OpenH264 license message + */ + public String getLicenseMessage() { + return licenseMessage; + } + + /** + * Set filename to storage for OpenH264 codec + * @param name + */ + public void setNameLib(String name) { + nameLib = name; + } + + /** + * @return filename of OpenH264 codec + */ + public String getNameLib() { + return nameLib; + } + + /** + * @return path of the lib + */ + public String getFullPathLib() { + return this.fileDirection + "/" + this.getNameLib(); + } + + /** + * Set name download file + * @param name : must be the same name relative to the url + */ + public void setNameFileDownload(String name) { + nameFileDownload = name; + } + + /** + * Set new url + * @param url : must be a Cisco Url to OpenH264 and .bzip2 file + */ + public void setUrlDownload(String url) { + urlDownload = url; + } + + /** + * Indicates whether the lib exists + * Requirements : fileDirection and nameLib init + * @return file exists ? + */ + public boolean isCodecFound() { + return new File(fileDirection+"/" + nameLib).exists(); + } + + /** + * Try to download and load codec + * Requirements : + * fileDirection + * nameFileDownload + * urlDownload + * nameLib + * codecDownListener + */ + public void downloadCodec() { + Thread thread = new Thread(new Runnable() + { + @Override + public void run() + { + try { + String path = fileDirection+"/" + nameLib; + URL url = new URL(urlDownload); + HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); + urlConnection.connect(); + Log.i("OpenH264Downloader"," "); + InputStream inputStream = urlConnection.getInputStream(); + FileOutputStream fileOutputStream = new FileOutputStream(fileDirection+"/"+nameFileDownload); + int totalSize = urlConnection.getContentLength(); + openH264DownloadHelperListener.OnProgress(0,totalSize); + + Log.i("OpenH264Downloader"," Download file:" + nameFileDownload); + + byte[] buffer = new byte[4096]; + int bufferLength; + int total = 0; + while((bufferLength = inputStream.read(buffer))>0 ){ + total += bufferLength; + fileOutputStream.write(buffer, 0, bufferLength); + openH264DownloadHelperListener.OnProgress(total, totalSize); + } + + fileOutputStream.close(); + inputStream.close(); + + Log.i("OpenH264Downloader"," Uncompress file:" + nameFileDownload); + + FileInputStream in = new FileInputStream(fileDirection+"/"+nameFileDownload); + FileOutputStream out = new FileOutputStream(path); + BZip2CompressorInputStream bzIn = new BZip2CompressorInputStream(in); + + while ((bufferLength = bzIn.read(buffer))>0) { + out.write(buffer, 0, bufferLength); + } + in.close(); + out.close(); + bzIn.close(); + + Log.i("OpenH264Downloader"," Remove file:" + nameFileDownload); + new File(fileDirection+"/"+nameFileDownload).delete(); + + Log.i("OpenH264Downloader"," Loading plugin:" + path); + System.load(path); + openH264DownloadHelperListener.OnProgress(2,1); + } catch (FileNotFoundException e) { + openH264DownloadHelperListener.OnError(e.getLocalizedMessage()); + } catch (IOException e) { + openH264DownloadHelperListener.OnError(e.getLocalizedMessage()); + } + } + }); + thread.start(); + } +} diff --git a/wrappers/java/classes/tools/Xml2Lpc.java b/wrappers/java/classes/tools/Xml2Lpc.java new file mode 100644 index 000000000..9b874152e --- /dev/null +++ b/wrappers/java/classes/tools/Xml2Lpc.java @@ -0,0 +1,73 @@ +package org.linphone.core.tools; + +import org.linphone.core.LpConfig; +import org.linphone.mediastream.Log; + +public class Xml2Lpc { + + private enum LogLevel { + DEBUG, + MESSAGE, + WARNING, + ERROR + } + + private static boolean mAvailable; + + private long internalPtr = 0; + + private native void init(); + private native void destroy(); + + public Xml2Lpc() { + init(); + } + + public void finalize() { + destroy(); + } + + public native int setXmlFile(String filename); + public native int setXmlString(String content); + + public native int setXsdFile(String filename); + public native int setXsdString(String content); + + public native int validate(); + public native int convert(LpConfig config); + + public void printLog(int level, String message) { + if(level > 0 && level < LogLevel.values().length) { + switch(LogLevel.values()[level]) { + case DEBUG: + Log.d(message); + break; + case MESSAGE: + Log.i(message); + break; + case WARNING: + Log.w(message); + break; + case ERROR: + Log.e(message); + break; + } + } + } + + public static boolean isAvailable() { + return mAvailable; + } + + // Load library + static { + try { + new Xml2Lpc(); + //System.loadLibrary("xml2"); + //System.loadLibrary("xml2lpc"); + mAvailable = true; + } catch (Throwable e) { + mAvailable = false; + } + } +} diff --git a/wrappers/java/java_class.mustache b/wrappers/java/java_class.mustache index 77778af8d..0cc0252ec 100644 --- a/wrappers/java/java_class.mustache +++ b/wrappers/java/java_class.mustache @@ -23,7 +23,17 @@ package {{packageName}}; import {{import}} {{/imports}} {{#isLinphoneFactory}} +import android.content.Context; +import android.os.Build; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.linphone.mediastream.Log; import org.linphone.mediastream.Version; +import org.linphone.core.tools.OpenH264DownloadHelper; {{/isLinphoneFactory}} {{#doc}} @@ -33,7 +43,7 @@ import org.linphone.mediastream.Version; {{/lines}} */ {{/doc}} -public interface {{className}} { +public {{#isLinphoneFactory}}abstract class{{/isLinphoneFactory}}{{#isNotLinphoneFactory}}interface{{/isNotLinphoneFactory}} {{className}} { {{#enums}} enum {{className}} { {{#values}} @@ -70,7 +80,18 @@ public interface {{className}} { {{/enums}} {{#isLinphoneFactory}} - + static Factory _Factory; + + public static final synchronized Factory instance() { + try { + if (_Factory == null) { + _Factory = new FactoryImpl(0); + } + } catch (Exception e) { + System.err.println("Cannot instanciate factory"); + } + return _Factory; + } {{/isLinphoneFactory}} {{#methods}} {{#doc}} @@ -81,18 +102,18 @@ public interface {{className}} { */ {{/doc}} {{#deprecated}}@Deprecated - {{/deprecated}}public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}}{{#enumCast}} throws CoreException{{/enumCast}}; + {{/deprecated}}{{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}}{{#enumCast}} throws CoreException{{/enumCast}}; {{/methods}} /** * Sets the object to store in this object user's data */ - public void setUserData(Object data); + {{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public void setUserData(Object data); /** * Gets the object stored in this object user's data */ - public Object getUserData(); + {{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public Object getUserData(); {{#isNotLinphoneFactory}} {{#staticMethods}} @@ -109,7 +130,7 @@ public interface {{className}} { {{/isNotLinphoneFactory}} } -class {{classImplName}} implements {{className}} { +class {{classImplName}} {{#isLinphoneFactory}}extends{{/isLinphoneFactory}}{{#isNotLinphoneFactory}}implements{{/isNotLinphoneFactory}} {{className}} { protected long nativePtr = 0; protected Object userData = null; @@ -119,12 +140,12 @@ class {{classImplName}} implements {{className}} { } {{#isLinphoneFactory}} - private static boolean loadOptionalLibrary(String s) { + private static boolean loadOptionalLibrary(String s) { try { System.loadLibrary(s); return true; } catch (Throwable e) { - android.util.Log.w("LinphoneCoreFactoryImpl", "Unable to load optional library " + s + ": " + e.getMessage()); + android.util.Log.w("FactoryImpl", "Unable to load optional library " + s + ": " + e.getMessage()); } return false; } @@ -139,10 +160,37 @@ class {{classImplName}} implements {{className}} { System.loadLibrary("linphone"); Version.dumpCapabilities(); } + + private boolean loadingDownloadedOpenH264(Context context) { + File file = new File(context.getApplicationInfo().nativeLibraryDir + "/libmsopenh264.so"); + + if (!file.exists()) { + Log.i("FactoryImpl"," libmsopenh264 not found, we disable the download of Openh264"); + return false; + } + + OpenH264DownloadHelper downloadHelper = new OpenH264DownloadHelper(context); + if (downloadHelper.isCodecFound()) { + Log.i("FactoryImpl"," Loading OpenH264 downloaded plugin:" + downloadHelper.getFullPathLib()); + System.load(downloadHelper.getFullPathLib()); + } else { + Log.i("FactoryImpl"," Cannot load OpenH264 downloaded plugin"); + } + return true; + } + + public OpenH264DownloadHelper createOpenH264DownloadHelper() { + if (fcontext == null) { + new CoreException("Cannot create OpenH264DownloadHelper"); + return null;//exception + } + return new OpenH264DownloadHelper(fcontext); + } {{/isLinphoneFactory}} {{#methods}} private native {{return_native}} {{name}}({{native_params}}); + @Override public {{return}} {{name}}({{params}}) {{#exception}}throws CoreException{{/exception}}{{#enumCast}}throws CoreException{{/enumCast}} { {{#exception}}int exceptionResult = {{/exception}}{{return_keyword}}{{#enumCast}}{{return}}.fromInt({{/enumCast}}{{#classCast}}({{return}}){{/classCast}}{{name}}(nativePtr{{native_params_impl}}){{#enumCast}}){{/enumCast}};{{#exception}} if (exceptionResult != 0) throw new CoreException("{{name}} returned value " + exceptionResult);{{/exception}} @@ -160,10 +208,12 @@ class {{classImplName}} implements {{className}} { } {{/isNotLinphoneFactory}} + @Override public void setUserData(Object data) { userData = data; } + @Override public Object getUserData() { return userData; } diff --git a/wrappers/java/migration.sh b/wrappers/java/migration.sh index 8ebac2c72..75c029679 100644 --- a/wrappers/java/migration.sh +++ b/wrappers/java/migration.sh @@ -3,6 +3,9 @@ SED_START='find ./src/android/org/linphone/ -type f -exec sed -i -e ' SED_END='{} \;' +# Imports +eval "$SED_START 's/import org.linphone.tools/import org.linphone.core.tools/g' $SED_END" + # Listeners eval "$SED_START 's/AccountCreator.AccountCreatorListener/AccountCreatorListener/g' $SED_END" eval "$SED_START 's/LinphoneCoreListenerBase/CoreListenerStub/g' $SED_END" @@ -204,6 +207,7 @@ eval "$SED_START 's/transports.tcp/transports.getTcpPort()/g' $SED_END" eval "$SED_START 's/transports.tls/transports.getTlsPort()/g' $SED_END" eval "$SED_START 's/getPrimaryContactUsername()/getPrimaryContactParsed().getUsername()/g' $SED_END" eval "$SED_START 's/getPrimaryContactDisplayName()/getPrimaryContactParsed().getDisplayName()/g' $SED_END" +eval "$SED_START 's/.sendDtmf(/.getCurrentCall().sendDtmf(/g' $SED_END" #Changes in library required #OpenH264DownloadHelper