support flutter gstreamer player for android
This commit is contained in:
@@ -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_(
|
||||
(uint8_t*)bufferInfo.data,
|
||||
video_info.size,
|
||||
video_info.width,
|
||||
video_info.height);
|
||||
video_info.height,
|
||||
video_info.stride[0]);
|
||||
|
||||
gst_buffer_unmap(buffer_, &bufferInfo);
|
||||
gst_video_frame_unmap(&vframe);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
@@ -10,7 +11,7 @@
|
||||
#include <gst/gst.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 {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user