support flutter gstreamer player for android
This commit is contained in:
@@ -1,12 +1,20 @@
|
|||||||
# GStreamer Player Plugin
|
# GStreamer Player Plugin
|
||||||
|
|
||||||
A GStreamer-powered alternative to Flutter's video_player that support Linux.
|
A GStreamer-powered alternative to Flutter's video_player that support Linux and Android.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Follow GStreamer's [Install on Linux](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=c) instuction
|
### Linux
|
||||||
|
|
||||||
|
Follow GStreamer's [Install on Linux](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=c) instuction.
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
Follow GStreamer's [Install on Android](https://gstreamer.freedesktop.org/documentation/installing/for-android-development.html?gi-language=c) instuction.
|
||||||
|
|
||||||
|
This source code has been tested with gstreamer 1.20.1 [prebuild binary](https://gstreamer.freedesktop.org/data/pkg/android/)
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/libraries
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'flutter_gstreamer_player'
|
||||||
@@ -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>
|
||||||
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.hpdragon1618.flutter_gstreamer_player">
|
||||||
|
</manifest>
|
||||||
+77
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
gradle-wrapper.jar
|
||||||
|
/.gradle
|
||||||
|
/captures/
|
||||||
|
/gradlew
|
||||||
|
/gradlew.bat
|
||||||
|
/local.properties
|
||||||
|
GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
|
# Remember to never publicly share your keystore.
|
||||||
|
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||||
|
key.properties
|
||||||
|
**/*.keystore
|
||||||
|
**/*.jks
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
def localProperties = new Properties()
|
||||||
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
|
localProperties.load(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
flutterVersionCode = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
flutterVersionName = '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion flutter.compileSdkVersion
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
|
applicationId "com.hpdragon1618.flutter_gstreamer_player_example"
|
||||||
|
minSdkVersion flutter.minSdkVersion
|
||||||
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
versionName flutterVersionName
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
// TODO: Add your own signing config for the release build.
|
||||||
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source '../..'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.hpdragon1618.flutter_gstreamer_player_example">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.hpdragon1618.flutter_gstreamer_player_example">
|
||||||
|
<application
|
||||||
|
android:label="flutter_gstreamer_player_example"
|
||||||
|
android:name="${applicationName}"
|
||||||
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
|
the Android process has started. This theme is visible to the user
|
||||||
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
|
to determine the Window background behind the Flutter UI. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
|
android:resource="@style/NormalTheme"
|
||||||
|
/>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<!-- Don't delete the meta-data below.
|
||||||
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
<meta-data
|
||||||
|
android:name="flutterEmbedding"
|
||||||
|
android:value="2" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.hpdragon1618.flutter_gstreamer_player_example
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
import org.freedesktop.gstreamer.GStreamer
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
GStreamer.init(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="?android:colorBackground" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@android:color/white" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 442 B |
Binary file not shown.
|
After Width: | Height: | Size: 721 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
Flutter draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
Flutter draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
This theme determines the color of the Android Window while your
|
||||||
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
|
running.
|
||||||
|
|
||||||
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.hpdragon1618.flutter_gstreamer_player_example">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.buildDir = '../build'
|
||||||
|
subprojects {
|
||||||
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
|
}
|
||||||
|
subprojects {
|
||||||
|
project.evaluationDependsOn(':app')
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#Fri Jun 23 08:50:38 CEST 2017
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
include ':app'
|
||||||
|
|
||||||
|
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
||||||
|
def properties = new Properties()
|
||||||
|
|
||||||
|
assert localPropertiesFile.exists()
|
||||||
|
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||||
|
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||||
@@ -6,6 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
flutter_gstreamer_player
|
flutter_gstreamer_player
|
||||||
)
|
)
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
||||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||||
@@ -14,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
|||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||||
endforeach(plugin)
|
endforeach(plugin)
|
||||||
|
|
||||||
|
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||||
|
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||||
|
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||||
|
endforeach(ffi_plugin)
|
||||||
|
|||||||
+8
-15
@@ -42,7 +42,7 @@ packages:
|
|||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.16.0"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -56,7 +56,7 @@ packages:
|
|||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -101,7 +101,7 @@ packages:
|
|||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.4"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -115,7 +115,7 @@ packages:
|
|||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -127,7 +127,7 @@ packages:
|
|||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.2"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -162,21 +162,14 @@ packages:
|
|||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.8"
|
version: "0.4.9"
|
||||||
typed_data:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: typed_data
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.0"
|
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.16.2 <3.0.0"
|
dart: ">=2.17.0-0 <3.0.0"
|
||||||
flutter: ">=2.5.0"
|
flutter: ">=2.5.0"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := flutter_gstreamer_player_plugin_android
|
||||||
|
LOCAL_SRC_FILES := flutter_gstreamer_player_plugin_android.cc gst_player.cc
|
||||||
|
# LOCAL_STATIC_LIBRARIES := android_native_app_glue
|
||||||
|
LOCAL_SHARED_LIBRARIES := gstreamer_android
|
||||||
|
LOCAL_LDLIBS := -llog -landroid
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
ifndef GSTREAMER_ROOT_ANDROID
|
||||||
|
$(error GSTREAMER_ROOT_ANDROID is not defined!)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_ARCH_ABI),armeabi)
|
||||||
|
GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/arm
|
||||||
|
else ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||||
|
GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/armv7
|
||||||
|
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||||
|
GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/arm64
|
||||||
|
else ifeq ($(TARGET_ARCH_ABI),x86)
|
||||||
|
GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/x86
|
||||||
|
else ifeq ($(TARGET_ARCH_ABI),x86_64)
|
||||||
|
GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/x86_64
|
||||||
|
else
|
||||||
|
$(error Target arch ABI not supported: $(TARGET_ARCH_ABI))
|
||||||
|
endif
|
||||||
|
|
||||||
|
GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/
|
||||||
|
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
|
||||||
|
GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) ${GSTREAMER_PLUGINS_CODECS} ${GSTREAMER_PLUGINS_ENCODING} ${GSTREAMER_PLUGINS_NET} ${GSTREAMER_PLUGINS_PLAYBACK} ${GSTREAMER_PLUGINS_SYS} ${GSTREAMER_PLUGINS_EFFECTS} ${GSTREAMER_PLUGINS_VIS} ${GSTREAMER_PLUGINS_CAPTURE} ${GSTREAMER_PLUGINS_CODECS_RESTRICTED} ${GSTREAMER_PLUGINS_NET_RESTRICTED} ${GSTREAMER_PLUGINS_GES}
|
||||||
|
GSTREAMER_EXTRA_DEPS := gstreamer-video-1.0 gstreamer-app-1.0
|
||||||
|
GSTREAMER_EXTRA_LIBS := -liconv
|
||||||
|
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
APP_CPPFLAGS := -std=c++17
|
||||||
|
APP_ABI = armeabi armeabi-v7a arm64-v8a x86 x86_64
|
||||||
|
APP_STL = c++_shared
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#include "gst_player.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
|
||||||
|
#define LOG_TAG "flutter_gstreamer_player_plugin_android"
|
||||||
|
#define ANATIVEWINDOW_BUFFER_FORMAT AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
static jint
|
||||||
|
handle_player_register_texture(JNIEnv * env, jobject thiz, jstring pipeline, jint player_id, jobject surface) {
|
||||||
|
const char *pipelineString = env->GetStringUTFChars(pipeline, 0);
|
||||||
|
|
||||||
|
ANativeWindow *native_window = ANativeWindow_fromSurface (env, surface);
|
||||||
|
|
||||||
|
__android_log_print (ANDROID_LOG_INFO,
|
||||||
|
LOG_TAG,
|
||||||
|
"pipeline: %s, player_id: %d",
|
||||||
|
pipelineString,
|
||||||
|
player_id);
|
||||||
|
|
||||||
|
GstPlayer* gstPlayer = g_players->Get(player_id);
|
||||||
|
|
||||||
|
gstPlayer->onVideo([
|
||||||
|
native_window = native_window
|
||||||
|
](
|
||||||
|
uint8_t* frame,
|
||||||
|
uint32_t size,
|
||||||
|
int32_t width,
|
||||||
|
int32_t height,
|
||||||
|
int32_t stride) -> void {
|
||||||
|
if (native_window != NULL) {
|
||||||
|
ANativeWindow_Buffer nativeBuffer;
|
||||||
|
|
||||||
|
if (ANativeWindow_lock(native_window, &nativeBuffer, NULL) == 0) {
|
||||||
|
if (nativeBuffer.width != width || nativeBuffer.height != height) {
|
||||||
|
ANativeWindow_unlockAndPost(native_window);
|
||||||
|
ANativeWindow_setBuffersGeometry(native_window,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
ANATIVEWINDOW_BUFFER_FORMAT);
|
||||||
|
if (ANativeWindow_lock(native_window, &nativeBuffer, NULL) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pixelSize = size / (width * height);
|
||||||
|
for (int h = 0; h < height; h++) {
|
||||||
|
memcpy((void*)((long)nativeBuffer.bits + h * nativeBuffer.stride * pixelSize),
|
||||||
|
frame + h*stride,
|
||||||
|
width * pixelSize);
|
||||||
|
}
|
||||||
|
ANativeWindow_unlockAndPost(native_window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
gstPlayer->play(pipelineString);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(pipeline, pipelineString);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List of implemented native methods */
|
||||||
|
static JNINativeMethod native_methods[] = {
|
||||||
|
{"handlePlayerRegisterTexture", "(Ljava/lang/String;ILjava/lang/Object;)I",
|
||||||
|
(void *) handle_player_register_texture},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Library initializer */
|
||||||
|
jint
|
||||||
|
JNI_OnLoad (JavaVM * vm, void *reserved)
|
||||||
|
{
|
||||||
|
JNIEnv *env = NULL;
|
||||||
|
|
||||||
|
if (vm->GetEnv ((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
|
||||||
|
__android_log_print (ANDROID_LOG_ERROR, LOG_TAG,
|
||||||
|
"Could not retrieve JNIEnv");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
jclass klass = env->FindClass (
|
||||||
|
"com/hpdragon1618/flutter_gstreamer_player/FlutterGstreamerPlayerPlugin");
|
||||||
|
env->RegisterNatives (klass, native_methods,
|
||||||
|
G_N_ELEMENTS (native_methods));
|
||||||
|
|
||||||
|
return JNI_VERSION_1_4;
|
||||||
|
}
|
||||||
@@ -74,8 +74,10 @@ GstFlowReturn GstPlayer::newSample(GstAppSink *sink, gpointer gSelf) {
|
|||||||
|
|
||||||
self->video_callback_(
|
self->video_callback_(
|
||||||
(uint8_t*)bufferInfo.data,
|
(uint8_t*)bufferInfo.data,
|
||||||
|
video_info.size,
|
||||||
video_info.width,
|
video_info.width,
|
||||||
video_info.height);
|
video_info.height,
|
||||||
|
video_info.stride[0]);
|
||||||
|
|
||||||
gst_buffer_unmap(buffer_, &bufferInfo);
|
gst_buffer_unmap(buffer_, &bufferInfo);
|
||||||
gst_video_frame_unmap(&vframe);
|
gst_video_frame_unmap(&vframe);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -10,7 +11,7 @@
|
|||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/app/gstappsink.h>
|
#include <gst/app/gstappsink.h>
|
||||||
|
|
||||||
typedef std::function<void(uint8_t*, int32_t, int32_t)> VideoFrameCallback;
|
typedef std::function<void(uint8_t*, uint32_t, int32_t, int32_t, int32_t)> VideoFrameCallback;
|
||||||
|
|
||||||
class GstPlayer {
|
class GstPlayer {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static void flutter_gstreamer_player_plugin_handle_method_call(
|
|||||||
gstPlayer->onVideo([texture_registrar = self->texture_registrar,
|
gstPlayer->onVideo([texture_registrar = self->texture_registrar,
|
||||||
video_outlet_ptr = it->second,
|
video_outlet_ptr = it->second,
|
||||||
video_outlet_private = video_outlet_private]
|
video_outlet_private = video_outlet_private]
|
||||||
(uint8_t* frame, int32_t width, int32_t height) -> void {
|
(uint8_t* frame, uint32_t size, int32_t width, int32_t height, int32_t stride) -> void {
|
||||||
video_outlet_private->buffer = frame;
|
video_outlet_private->buffer = frame;
|
||||||
video_outlet_private->video_width = width;
|
video_outlet_private->video_width = width;
|
||||||
video_outlet_private->video_height = height;
|
video_outlet_private->video_height = height;
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ flutter:
|
|||||||
platforms:
|
platforms:
|
||||||
linux:
|
linux:
|
||||||
pluginClass: FlutterGstreamerPlayerPlugin
|
pluginClass: FlutterGstreamerPlayerPlugin
|
||||||
|
android:
|
||||||
|
package: com.hpdragon1618.flutter_gstreamer_player
|
||||||
|
pluginClass: FlutterGstreamerPlayerPlugin
|
||||||
|
|
||||||
# To add assets to your plugin package, add an assets section, like this:
|
# To add assets to your plugin package, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
|
|||||||
Reference in New Issue
Block a user