support flutter gstreamer player for android

This commit is contained in:
hpdragon
2022-08-21 15:57:09 +07:00
parent 0bc07eed97
commit d6034e51f8
41 changed files with 5263 additions and 20 deletions
+8
View File
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
+79
View File
@@ -0,0 +1,79 @@
group 'com.hpdragon1618.flutter_gstreamer_player'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 31
ndkVersion "21.4.7075529"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
main.java.srcDirs += 'src'
}
defaultConfig {
minSdkVersion 16
externalNativeBuild {
ndkBuild {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
gstRoot = project.gstAndroidRoot
else
gstRoot = System.env.GSTREAMER_ROOT_ANDROID
if (gstRoot == null)
throw new GradleException('GSTREAMER_ROOT_ANDROID must be set, or "gstAndroidRoot" must be defined in your gradle.properties in the top level directory of the unpacked universal GStreamer Android binaries')
arguments "NDK_APPLICATION_MK=../gst_player/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
targets "flutter_gstreamer_player_plugin_android"
// All archs except MIPS and MIPS64 are supported
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
}
externalNativeBuild {
ndkBuild {
path '../gst_player/Android.mk'
}
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
+1
View File
@@ -0,0 +1 @@
rootProject.name = 'flutter_gstreamer_player'
+126
View File
@@ -0,0 +1,126 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- /etc/fonts/fonts.conf file to configure system font access -->
<fontconfig>
<!-- Font directory list -->
<dir prefix="xdg">fontconfig/fonts</dir>
<!-- Font cache directory list -->
<cachedir prefix="xdg">fontconfig</cachedir>
<!--
Accept deprecated 'mono' alias, replacing it with 'monospace'
-->
<match target="pattern">
<test qual="any" name="family">
<string>mono</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>monospace</string>
</edit>
</match>
<!--
Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<!--
Accept deprecated 'sans' alias, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<config>
<!--
These are the default Unicode chars that are expected to be blank
in fonts. All other blank chars are assumed to be broken and
won't appear in the resulting charsets
-->
<blank>
<int>0x0020</int> <!-- SPACE -->
<int>0x00A0</int> <!-- NO-BREAK SPACE -->
<int>0x00AD</int> <!-- SOFT HYPHEN -->
<int>0x034F</int> <!-- COMBINING GRAPHEME JOINER -->
<int>0x0600</int> <!-- ARABIC NUMBER SIGN -->
<int>0x0601</int> <!-- ARABIC SIGN SANAH -->
<int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER -->
<int>0x0603</int> <!-- ARABIC SIGN SAFHA -->
<int>0x06DD</int> <!-- ARABIC END OF AYAH -->
<int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK -->
<int>0x115F</int> <!-- HANGUL CHOSEONG FILLER -->
<int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER -->
<int>0x1680</int> <!-- OGHAM SPACE MARK -->
<int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ -->
<int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA -->
<int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR -->
<int>0x2000</int> <!-- EN QUAD -->
<int>0x2001</int> <!-- EM QUAD -->
<int>0x2002</int> <!-- EN SPACE -->
<int>0x2003</int> <!-- EM SPACE -->
<int>0x2004</int> <!-- THREE-PER-EM SPACE -->
<int>0x2005</int> <!-- FOUR-PER-EM SPACE -->
<int>0x2006</int> <!-- SIX-PER-EM SPACE -->
<int>0x2007</int> <!-- FIGURE SPACE -->
<int>0x2008</int> <!-- PUNCTUATION SPACE -->
<int>0x2009</int> <!-- THIN SPACE -->
<int>0x200A</int> <!-- HAIR SPACE -->
<int>0x200B</int> <!-- ZERO WIDTH SPACE -->
<int>0x200C</int> <!-- ZERO WIDTH NON-JOINER -->
<int>0x200D</int> <!-- ZERO WIDTH JOINER -->
<int>0x200E</int> <!-- LEFT-TO-RIGHT MARK -->
<int>0x200F</int> <!-- RIGHT-TO-LEFT MARK -->
<int>0x2028</int> <!-- LINE SEPARATOR -->
<int>0x2029</int> <!-- PARAGRAPH SEPARATOR -->
<int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING -->
<int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING -->
<int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING -->
<int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE -->
<int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE -->
<int>0x202F</int> <!-- NARROW NO-BREAK SPACE -->
<int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE -->
<int>0x2060</int> <!-- WORD JOINER -->
<int>0x2061</int> <!-- FUNCTION APPLICATION -->
<int>0x2062</int> <!-- INVISIBLE TIMES -->
<int>0x2063</int> <!-- INVISIBLE SEPARATOR -->
<int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING -->
<int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING -->
<int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING -->
<int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING -->
<int>0x206E</int> <!-- NATIONAL DIGIT SHAPES -->
<int>0x206F</int> <!-- NOMINAL DIGIT SHAPES -->
<int>0x2800</int> <!-- BRAILLE PATTERN BLANK -->
<int>0x3000</int> <!-- IDEOGRAPHIC SPACE -->
<int>0x3164</int> <!-- HANGUL FILLER -->
<int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE -->
<int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER -->
<int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR -->
<int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR -->
<int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR -->
</blank>
<!--
Rescan configuration every 30 seconds when FcFontSetList is called
-->
<rescan>
<int>30</int>
</rescan>
</config>
</fontconfig>
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hpdragon1618.flutter_gstreamer_player">
</manifest>
@@ -0,0 +1,77 @@
package com.hpdragon1618.flutter_gstreamer_player
import android.content.Context
import androidx.annotation.NonNull
import android.view.Surface
import android.graphics.SurfaceTexture
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.view.TextureRegistry
import android.util.Log
/** FlutterGstreamerPlayerPlugin */
class FlutterGstreamerPlayerPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
private var entries: MutableList<TextureRegistry.SurfaceTextureEntry> = mutableListOf()
external fun handlePlayerRegisterTexture(pipeline: String, playerId: Int, surface: Any): Int
companion object {
lateinit var messenger: BinaryMessenger;
lateinit var context: Context;
lateinit var registry: TextureRegistry;
lateinit var assets: FlutterPlugin.FlutterAssets;
init {
System.loadLibrary("gstreamer_android")
System.loadLibrary("flutter_gstreamer_player_plugin_android")
}
}
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_gstreamer_player")
channel.setMethodCallHandler(this)
messenger = flutterPluginBinding.binaryMessenger;
context = flutterPluginBinding.applicationContext;
registry = flutterPluginBinding.textureRegistry;
assets = flutterPluginBinding.flutterAssets;
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else if (call.method == "PlayerRegisterTexture") {
val arguments = call.arguments as Map<String, Any>;
var pipeline = arguments["pipeline"] as String;
var player_id = arguments["playerId"] as Int;
entries.add(registry.createSurfaceTexture())
var surfaceTexture = entries[entries.lastIndex].surfaceTexture()
var textureID = entries[entries.lastIndex].id().toInt();
var surface = Surface(surfaceTexture)
handlePlayerRegisterTexture(pipeline, player_id, surface);
result.success(textureID);
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
@@ -0,0 +1,99 @@
package org.freedesktop.gstreamer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.content.res.AssetManager;
public class GStreamer {
private static native void nativeInit(Context context) throws Exception;
public static void init(Context context) throws Exception {
copyCaCertificates(context);
copyFonts(context);
nativeInit(context);
}
private static void copyFonts(Context context) {
AssetManager assetManager = context.getAssets();
File filesDir = context.getFilesDir();
File fontsFCDir = new File (filesDir, "fontconfig");
File fontsDir = new File (fontsFCDir, "fonts");
File fontsCfg = new File (fontsFCDir, "fonts.conf");
fontsDir.mkdirs();
try {
/* Copy the config file */
copyFile (assetManager, "fontconfig/fonts.conf", fontsCfg);
/* Copy the fonts */
for(String filename : assetManager.list("fontconfig/fonts/truetype")) {
File font = new File(fontsDir, filename);
copyFile (assetManager, "fontconfig/fonts/truetype/" + filename, font);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copyCaCertificates(Context context) {
AssetManager assetManager = context.getAssets();
File filesDir = context.getFilesDir();
File sslDir = new File (filesDir, "ssl");
File certsDir = new File (sslDir, "certs");
File certs = new File (certsDir, "ca-certificates.crt");
certsDir.mkdirs();
try {
/* Copy the certificates file */
copyFile (assetManager, "ssl/certs/ca-certificates.crt", certs);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void copyFile(AssetManager assetManager, String assetPath, File outFile) throws IOException {
InputStream in = null;
OutputStream out = null;
IOException exception = null;
if (outFile.exists())
outFile.delete();
try {
in = assetManager.open(assetPath);
out = new FileOutputStream(outFile);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.flush();
} catch (IOException e) {
exception = e;
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
if (exception == null)
exception = e;
}
if (out != null)
try {
out.close();
} catch (IOException e) {
if (exception == null)
exception = e;
}
if (exception != null)
throw exception;
}
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2012, Collabora Ltd.
* Author: Youness Alaoui
*
* Copyright (C) 2015, Collabora Ltd.
* Author: Justin Kim <justin.kim@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.freedesktop.gstreamer.androidmedia;
import android.hardware.Camera;
public class GstAhcCallback implements Camera.PreviewCallback,
Camera.ErrorCallback,
Camera.AutoFocusCallback {
public long mUserData;
public long mCallback;
public static native void gst_ah_camera_on_preview_frame(byte[] data, Camera camera,
long callback, long user_data);
public static native void gst_ah_camera_on_error(int error, Camera camera,
long callback, long user_data);
public static native void gst_ah_camera_on_auto_focus(boolean success, Camera camera,
long callback, long user_data);
public GstAhcCallback(long callback, long user_data) {
mCallback = callback;
mUserData = user_data;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
gst_ah_camera_on_preview_frame(data, camera, mCallback, mUserData);
}
@Override
public void onError(int error, Camera camera) {
gst_ah_camera_on_error(error, camera, mCallback, mUserData);
}
@Override
public void onAutoFocus(boolean success, Camera camera) {
gst_ah_camera_on_auto_focus(success, camera, mCallback, mUserData);
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 SurroundIO
* Author: Martin Kelly <martin@surround.io>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
package org.freedesktop.gstreamer.androidmedia;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
public class GstAhsCallback implements SensorEventListener {
public long mUserData;
public long mSensorCallback;
public long mAccuracyCallback;
public static native void gst_ah_sensor_on_sensor_changed(SensorEvent event,
long callback, long user_data);
public static native void gst_ah_sensor_on_accuracy_changed(Sensor sensor, int accuracy,
long callback, long user_data);
public GstAhsCallback(long sensor_callback,
long accuracy_callback, long user_data) {
mSensorCallback = sensor_callback;
mAccuracyCallback = accuracy_callback;
mUserData = user_data;
}
@Override
public void onSensorChanged(SensorEvent event) {
gst_ah_sensor_on_sensor_changed(event, mSensorCallback, mUserData);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
gst_ah_sensor_on_accuracy_changed(sensor, accuracy,
mAccuracyCallback, mUserData);
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2015, Collabora Ltd.
* Author: Matthieu Bouron <matthieu.bouron@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.freedesktop.gstreamer.androidmedia;
import android.graphics.SurfaceTexture;
import android.graphics.SurfaceTexture.OnFrameAvailableListener;
public class GstAmcOnFrameAvailableListener implements OnFrameAvailableListener
{
private long context = 0;
public synchronized void onFrameAvailable (SurfaceTexture surfaceTexture) {
native_onFrameAvailable(context, surfaceTexture);
}
public synchronized long getContext () {
return context;
}
public synchronized void setContext (long c) {
context = c;
}
private native void native_onFrameAvailable (long context, SurfaceTexture surfaceTexture);
}