Merge branch 'android' into 'main'

Draft: android: Port over to the CMake Cerbero SDK module

See merge request gstreamer/gstreamer!6794
This commit is contained in:
amyspark 2024-05-03 21:26:22 +00:00
commit e1e644c64a
15 changed files with 319 additions and 99 deletions

View file

@ -12,7 +12,7 @@ android {
externalNativeBuild {
ndkBuild {
cmake {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
@ -23,7 +23,7 @@ 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=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
arguments "-DANDROID_STL=c++_shared", "-DGSTREAMER_JAVA_SRC_DIR=src", "-DGSTREAMER_ROOT_ANDROID=$gstRoot", "-DGSTREAMER_ASSETS_DIR=src/assets"
targets "tutorial-1"
@ -52,8 +52,8 @@ android {
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
cmake {
path 'jni/CMakeLists.txt'
}
}
ndkVersion '25.2.9519653'

View file

@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.18.1)
project("android-tutorial-1" LANGUAGES C CXX)
if(NOT DEFINED GSTREAMER_ROOT_ANDROID)
message(FATAL_ERROR "GSTREAMER_ROOT_ANDROID is not defined!")
endif()
if(ANDROID_ABI STREQUAL "armeabi")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm")
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/armv7")
elseif(ANDROID_ABI STREQUAL "arm64-v8a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm64")
elseif(ANDROID_ABI STREQUAL "x86")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86")
elseif(ANDROID_ABI STREQUAL "x86_64")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86_64")
else()
message(FATAL_ERROR "Target arch ABI not supported: ${ANDROID_ABI}")
endif()
list(PREPEND CMAKE_FIND_ROOT_PATH "${GSTREAMER_ROOT}")
set(GSTREAMER_NDK_BUILD_PATH "${GSTREAMER_ROOT}/share/gst-android/ndk-build/")
set(GSTREAMER_PLUGINS coreelements)
find_library(LOG_LIB log REQUIRED)
include(${GSTREAMER_NDK_BUILD_PATH}/gstreamer-1.0.cmake)
add_library(tutorial-1 SHARED tutorial-1.c dummy.cpp)
target_link_libraries(tutorial-1
PUBLIC
gstreamer_android
${LOG_LIB}
)
set_target_properties(tutorial-1
PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)

View file

@ -7,7 +7,7 @@
* Java Bindings
*/
static jstring
gst_native_get_gstreamer_info (JNIEnv * env, jobject thiz)
gst_native_get_gstreamer_info (JNIEnv *env, jobject thiz)
{
char *version_utf8 = gst_version_string ();
jstring *version_jstring = (*env)->NewStringUTF (env, version_utf8);
@ -20,8 +20,8 @@ static JNINativeMethod native_methods[] = {
(void *) gst_native_get_gstreamer_info}
};
jint
JNI_OnLoad (JavaVM * vm, void *reserved)
JNIEXPORT jint
JNI_OnLoad (JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;

View file

@ -12,7 +12,7 @@ android {
externalNativeBuild {
ndkBuild {
cmake {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
@ -23,7 +23,7 @@ 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=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
arguments "-DANDROID_STL=c++_shared", "-DGSTREAMER_JAVA_SRC_DIR=src", "-DGSTREAMER_ROOT_ANDROID=$gstRoot", "-DGSTREAMER_ASSETS_DIR=src/assets"
targets "tutorial-2"
@ -52,11 +52,11 @@ android {
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
cmake {
path 'jni/CMakeLists.txt'
}
}
ndkVersion '25.2.9519653'
ndkVersion '25.2.9519653'
}
afterEvaluate {

View file

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.18.1)
project("android-tutorial-2" LANGUAGES C CXX)
if(NOT DEFINED GSTREAMER_ROOT_ANDROID)
message(FATAL_ERROR "GSTREAMER_ROOT_ANDROID is not defined!")
endif()
if(ANDROID_ABI STREQUAL "armeabi")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm")
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/armv7")
elseif(ANDROID_ABI STREQUAL "arm64-v8a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm64")
elseif(ANDROID_ABI STREQUAL "x86")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86")
elseif(ANDROID_ABI STREQUAL "x86_64")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86_64")
else()
message(FATAL_ERROR "Target arch ABI not supported: ${ANDROID_ABI}")
endif()
list(PREPEND CMAKE_FIND_ROOT_PATH "${GSTREAMER_ROOT}")
set(GSTREAMER_NDK_BUILD_PATH "${GSTREAMER_ROOT}/share/gst-android/ndk-build/")
include("${GSTREAMER_NDK_BUILD_PATH}/plugins.cmake")
set(GSTREAMER_PLUGINS ${GSTREAMER_PLUGINS_CORE} ${GSTREAMER_PLUGINS_SYS})
find_library(LOG_LIB log REQUIRED)
include(${GSTREAMER_NDK_BUILD_PATH}/gstreamer-1.0.cmake)
add_library(tutorial-2 SHARED tutorial-2.c dummy.cpp)
target_link_libraries(tutorial-2
PUBLIC
gstreamer_android
${LOG_LIB}
)
set_target_properties(tutorial-2
PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)

View file

@ -85,7 +85,7 @@ get_jni_env (void)
/* Change the content of the UI's TextView */
static void
set_ui_message (const gchar * message, CustomData * data)
set_ui_message (const gchar *message, CustomData *data)
{
JNIEnv *env = get_jni_env ();
GST_DEBUG ("Setting message to: %s", message);
@ -100,7 +100,7 @@ set_ui_message (const gchar * message, CustomData * data)
/* Retrieve errors from the bus and show them on the UI */
static void
error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
error_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GError *err;
gchar *debug_info;
@ -119,7 +119,7 @@ error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Notify UI about pipeline state changes */
static void
state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
@ -135,7 +135,7 @@ state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Check if all conditions are met to report GStreamer as initialized.
* These conditions will change depending on the application */
static void
check_initialization_complete (CustomData * data)
check_initialization_complete (CustomData *data)
{
JNIEnv *env = get_jni_env ();
if (!data->initialized && data->main_loop) {
@ -216,7 +216,7 @@ app_function (void *userdata)
/* Instruct the native code to create its internal data structure, pipeline and thread */
static void
gst_native_init (JNIEnv * env, jobject thiz)
gst_native_init (JNIEnv *env, jobject thiz)
{
CustomData *data = g_new0 (CustomData, 1);
SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data);
@ -231,7 +231,7 @@ gst_native_init (JNIEnv * env, jobject thiz)
/* Quit the main loop, remove the native thread and free resources */
static void
gst_native_finalize (JNIEnv * env, jobject thiz)
gst_native_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -250,7 +250,7 @@ gst_native_finalize (JNIEnv * env, jobject thiz)
/* Set pipeline to PLAYING state */
static void
gst_native_play (JNIEnv * env, jobject thiz)
gst_native_play (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -261,7 +261,7 @@ gst_native_play (JNIEnv * env, jobject thiz)
/* Set pipeline to PAUSED state */
static void
gst_native_pause (JNIEnv * env, jobject thiz)
gst_native_pause (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -272,7 +272,7 @@ gst_native_pause (JNIEnv * env, jobject thiz)
/* Static class initializer: retrieve method and field IDs */
static jboolean
gst_native_class_init (JNIEnv * env, jclass klass)
gst_native_class_init (JNIEnv *env, jclass klass)
{
custom_data_field_id =
(*env)->GetFieldID (env, klass, "native_custom_data", "J");
@ -303,8 +303,8 @@ static JNINativeMethod native_methods[] = {
};
/* Library initializer */
jint
JNI_OnLoad (JavaVM * vm, void *reserved)
JNIEXPORT jint
JNI_OnLoad (JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;

View file

@ -12,7 +12,7 @@ android {
externalNativeBuild {
ndkBuild {
cmake {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
@ -23,7 +23,7 @@ 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=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
arguments "-DANDROID_STL=c++_shared", "-DGSTREAMER_JAVA_SRC_DIR=src", "-DGSTREAMER_ROOT_ANDROID=$gstRoot", "-DGSTREAMER_ASSETS_DIR=src/assets"
targets "tutorial-3"
@ -52,11 +52,11 @@ android {
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
cmake {
path 'jni/CMakeLists.txt'
}
}
ndkVersion '25.2.9519653'
ndkVersion '25.2.9519653'
}
afterEvaluate {

View file

@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.18.1)
project("android-tutorial-3" LANGUAGES C CXX)
if(NOT DEFINED GSTREAMER_ROOT_ANDROID)
message(FATAL_ERROR "GSTREAMER_ROOT_ANDROID is not defined!")
endif()
if(ANDROID_ABI STREQUAL "armeabi")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm")
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/armv7")
elseif(ANDROID_ABI STREQUAL "arm64-v8a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm64")
elseif(ANDROID_ABI STREQUAL "x86")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86")
elseif(ANDROID_ABI STREQUAL "x86_64")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86_64")
else()
message(FATAL_ERROR "Target arch ABI not supported: ${ANDROID_ABI}")
endif()
list(PREPEND CMAKE_FIND_ROOT_PATH "${GSTREAMER_ROOT}")
set(GSTREAMER_NDK_BUILD_PATH "${GSTREAMER_ROOT}/share/gst-android/ndk-build/")
include("${GSTREAMER_NDK_BUILD_PATH}/plugins.cmake")
set(GSTREAMER_PLUGINS ${GSTREAMER_PLUGINS_CORE} ${GSTREAMER_PLUGINS_SYS} ${GSTREAMER_PLUGINS_EFFECTS})
set(GSTREAMER_EXTRA_DEPS gstreamer-video-1.0 gobject-2.0)
find_library(LOG_LIB log REQUIRED)
find_library(ANDROID_LIB android REQUIRED)
include(${GSTREAMER_NDK_BUILD_PATH}/gstreamer-1.0.cmake)
add_library(tutorial-3 SHARED tutorial-3.c dummy.cpp)
target_link_libraries(tutorial-3
PUBLIC
gstreamer_android
${ANDROID_LIB}
${LOG_LIB}
)
set_target_properties(tutorial-3
PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)

View file

@ -91,7 +91,7 @@ get_jni_env (void)
/* Change the content of the UI's TextView */
static void
set_ui_message (const gchar * message, CustomData * data)
set_ui_message (const gchar *message, CustomData *data)
{
JNIEnv *env = get_jni_env ();
GST_DEBUG ("Setting message to: %s", message);
@ -106,7 +106,7 @@ set_ui_message (const gchar * message, CustomData * data)
/* Retrieve errors from the bus and show them on the UI */
static void
error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
error_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GError *err;
gchar *debug_info;
@ -125,7 +125,7 @@ error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Notify UI about pipeline state changes */
static void
state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
@ -141,7 +141,7 @@ state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Check if all conditions are met to report GStreamer as initialized.
* These conditions will change depending on the application */
static void
check_initialization_complete (CustomData * data)
check_initialization_complete (CustomData *data)
{
JNIEnv *env = get_jni_env ();
if (!data->initialized && data->native_window && data->main_loop) {
@ -240,7 +240,7 @@ app_function (void *userdata)
/* Instruct the native code to create its internal data structure, pipeline and thread */
static void
gst_native_init (JNIEnv * env, jobject thiz)
gst_native_init (JNIEnv *env, jobject thiz)
{
CustomData *data = g_new0 (CustomData, 1);
SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data);
@ -255,7 +255,7 @@ gst_native_init (JNIEnv * env, jobject thiz)
/* Quit the main loop, remove the native thread and free resources */
static void
gst_native_finalize (JNIEnv * env, jobject thiz)
gst_native_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -274,7 +274,7 @@ gst_native_finalize (JNIEnv * env, jobject thiz)
/* Set pipeline to PLAYING state */
static void
gst_native_play (JNIEnv * env, jobject thiz)
gst_native_play (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -285,7 +285,7 @@ gst_native_play (JNIEnv * env, jobject thiz)
/* Set pipeline to PAUSED state */
static void
gst_native_pause (JNIEnv * env, jobject thiz)
gst_native_pause (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -296,7 +296,7 @@ gst_native_pause (JNIEnv * env, jobject thiz)
/* Static class initializer: retrieve method and field IDs */
static jboolean
gst_native_class_init (JNIEnv * env, jclass klass)
gst_native_class_init (JNIEnv *env, jclass klass)
{
custom_data_field_id =
(*env)->GetFieldID (env, klass, "native_custom_data", "J");
@ -318,7 +318,7 @@ gst_native_class_init (JNIEnv * env, jclass klass)
}
static void
gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -348,7 +348,7 @@ gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
}
static void
gst_native_surface_finalize (JNIEnv * env, jobject thiz)
gst_native_surface_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -379,8 +379,8 @@ static JNINativeMethod native_methods[] = {
};
/* Library initializer */
jint
JNI_OnLoad (JavaVM * vm, void *reserved)
JNIEXPORT jint
JNI_OnLoad (JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;

View file

@ -12,7 +12,7 @@ android {
externalNativeBuild {
ndkBuild {
cmake {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
@ -23,7 +23,7 @@ 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=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
arguments "-DANDROID_STL=c++_shared", "-DGSTREAMER_JAVA_SRC_DIR=src", "-DGSTREAMER_ROOT_ANDROID=$gstRoot", "-DGSTREAMER_ASSETS_DIR=src/assets"
targets "tutorial-4"
@ -52,11 +52,11 @@ android {
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
cmake {
path 'jni/CMakeLists.txt'
}
}
ndkVersion '25.2.9519653'
ndkVersion '25.2.9519653'
}
afterEvaluate {

View file

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.18.1)
project("android-tutorial-4" LANGUAGES C CXX)
if(NOT DEFINED GSTREAMER_ROOT_ANDROID)
message(FATAL_ERROR "GSTREAMER_ROOT_ANDROID is not defined!")
endif()
if(ANDROID_ABI STREQUAL "armeabi")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm")
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/armv7")
elseif(ANDROID_ABI STREQUAL "arm64-v8a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm64")
elseif(ANDROID_ABI STREQUAL "x86")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86")
elseif(ANDROID_ABI STREQUAL "x86_64")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86_64")
else()
message(FATAL_ERROR "Target arch ABI not supported: ${ANDROID_ABI}")
endif()
list(PREPEND CMAKE_FIND_ROOT_PATH "${GSTREAMER_ROOT}")
set(GSTREAMER_NDK_BUILD_PATH "${GSTREAMER_ROOT}/share/gst-android/ndk-build/")
include("${GSTREAMER_NDK_BUILD_PATH}/plugins.cmake")
set(GSTREAMER_PLUGINS ${GSTREAMER_PLUGINS_CORE} ${GSTREAMER_PLUGINS_PLAYBACK} ${GSTREAMER_PLUGINS_CODECS} ${GSTREAMER_PLUGINS_NET} ${GSTREAMER_PLUGINS_SYS})
set(GSTREAMER_EXTRA_DEPS gstreamer-video-1.0)
set(G_IO_MODULES openssl)
find_library(ANDROID_LIB android REQUIRED)
find_library(LOG_LIB log REQUIRED)
include(${GSTREAMER_NDK_BUILD_PATH}/gstreamer-1.0.cmake)
add_library(tutorial-4 SHARED tutorial-4.c dummy.cpp)
target_link_libraries(tutorial-4
PUBLIC
gstreamer_android
${ANDROID_LIB}
${LOG_LIB}
)
set_target_properties(tutorial-4
PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)

View file

@ -108,7 +108,7 @@ get_jni_env (void)
/* Change the content of the UI's TextView */
static void
set_ui_message (const gchar * message, CustomData * data)
set_ui_message (const gchar *message, CustomData *data)
{
JNIEnv *env = get_jni_env ();
GST_DEBUG ("Setting message to: %s", message);
@ -123,7 +123,7 @@ set_ui_message (const gchar * message, CustomData * data)
/* Tell the application what is the current position and clip duration */
static void
set_current_ui_position (gint position, gint duration, CustomData * data)
set_current_ui_position (gint position, gint duration, CustomData *data)
{
JNIEnv *env = get_jni_env ();
(*env)->CallVoidMethod (env, data->app, set_current_position_method_id,
@ -137,7 +137,7 @@ set_current_ui_position (gint position, gint duration, CustomData * data)
/* If we have pipeline and it is running, query the current position and clip duration and inform
* the application */
static gboolean
refresh_ui (CustomData * data)
refresh_ui (CustomData *data)
{
gint64 current = -1;
gint64 position;
@ -168,7 +168,7 @@ static gboolean delayed_seek_cb (CustomData * data);
/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for
* some time in the future. */
static void
execute_seek (gint64 desired_position, CustomData * data)
execute_seek (gint64 desired_position, CustomData *data)
{
gint64 diff;
@ -209,7 +209,7 @@ execute_seek (gint64 desired_position, CustomData * data)
/* Delayed seek callback. This gets called by the timer setup in the above function. */
static gboolean
delayed_seek_cb (CustomData * data)
delayed_seek_cb (CustomData *data)
{
GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT,
GST_TIME_ARGS (data->desired_position));
@ -219,7 +219,7 @@ delayed_seek_cb (CustomData * data)
/* Retrieve errors from the bus and show them on the UI */
static void
error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
error_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GError *err;
gchar *debug_info;
@ -239,7 +239,7 @@ error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */
static void
eos_cb (GstBus * bus, GstMessage * msg, CustomData * data)
eos_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
data->target_state = GST_STATE_PAUSED;
data->is_live =
@ -250,7 +250,7 @@ eos_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */
static void
duration_cb (GstBus * bus, GstMessage * msg, CustomData * data)
duration_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
data->duration = GST_CLOCK_TIME_NONE;
}
@ -258,7 +258,7 @@ duration_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when buffering messages are received. We inform the UI about the current buffering level and
* keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */
static void
buffering_cb (GstBus * bus, GstMessage * msg, CustomData * data)
buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
gint percent;
@ -280,7 +280,7 @@ buffering_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the clock is lost */
static void
clock_lost_cb (GstBus * bus, GstMessage * msg, CustomData * data)
clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
if (data->target_state >= GST_STATE_PLAYING) {
gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
@ -290,7 +290,7 @@ clock_lost_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Retrieve the video sink's Caps and tell the application about the media size */
static void
check_media_size (CustomData * data)
check_media_size (CustomData *data)
{
JNIEnv *env = get_jni_env ();
GstElement *video_sink;
@ -323,7 +323,7 @@ check_media_size (CustomData * data)
/* Notify UI about pipeline state changes */
static void
state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
@ -350,7 +350,7 @@ state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Check if all conditions are met to report GStreamer as initialized.
* These conditions will change depending on the application */
static void
check_initialization_complete (CustomData * data)
check_initialization_complete (CustomData *data)
{
JNIEnv *env = get_jni_env ();
if (!data->initialized && data->native_window && data->main_loop) {
@ -460,7 +460,7 @@ app_function (void *userdata)
/* Instruct the native code to create its internal data structure, pipeline and thread */
static void
gst_native_init (JNIEnv * env, jobject thiz)
gst_native_init (JNIEnv *env, jobject thiz)
{
CustomData *data = g_new0 (CustomData, 1);
data->desired_position = GST_CLOCK_TIME_NONE;
@ -477,7 +477,7 @@ gst_native_init (JNIEnv * env, jobject thiz)
/* Quit the main loop, remove the native thread and free resources */
static void
gst_native_finalize (JNIEnv * env, jobject thiz)
gst_native_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -496,7 +496,7 @@ gst_native_finalize (JNIEnv * env, jobject thiz)
/* Set playbin's URI */
void
gst_native_set_uri (JNIEnv * env, jobject thiz, jstring uri)
gst_native_set_uri (JNIEnv *env, jobject thiz, jstring uri)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data || !data->pipeline)
@ -515,7 +515,7 @@ gst_native_set_uri (JNIEnv * env, jobject thiz, jstring uri)
/* Set pipeline to PLAYING state */
static void
gst_native_play (JNIEnv * env, jobject thiz)
gst_native_play (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -529,7 +529,7 @@ gst_native_play (JNIEnv * env, jobject thiz)
/* Set pipeline to PAUSED state */
static void
gst_native_pause (JNIEnv * env, jobject thiz)
gst_native_pause (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -543,7 +543,7 @@ gst_native_pause (JNIEnv * env, jobject thiz)
/* Instruct the pipeline to seek to a different position */
void
gst_native_set_position (JNIEnv * env, jobject thiz, int milliseconds)
gst_native_set_position (JNIEnv *env, jobject thiz, int milliseconds)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -560,7 +560,7 @@ gst_native_set_position (JNIEnv * env, jobject thiz, int milliseconds)
/* Static class initializer: retrieve method and field IDs */
static jboolean
gst_native_class_init (JNIEnv * env, jclass klass)
gst_native_class_init (JNIEnv *env, jclass klass)
{
custom_data_field_id =
(*env)->GetFieldID (env, klass, "native_custom_data", "J");
@ -587,7 +587,7 @@ gst_native_class_init (JNIEnv * env, jclass klass)
}
static void
gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -617,7 +617,7 @@ gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
}
static void
gst_native_surface_finalize (JNIEnv * env, jobject thiz)
gst_native_surface_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -650,8 +650,8 @@ static JNINativeMethod native_methods[] = {
};
/* Library initializer */
jint
JNI_OnLoad (JavaVM * vm, void *reserved)
JNIEXPORT jint
JNI_OnLoad (JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;

View file

@ -12,7 +12,7 @@ android {
externalNativeBuild {
ndkBuild {
cmake {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
@ -23,7 +23,7 @@ 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=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets"
arguments "-DANDROID_STL=c++_shared", "-DGSTREAMER_JAVA_SRC_DIR=src", "-DGSTREAMER_ROOT_ANDROID=$gstRoot", "-DGSTREAMER_ASSETS_DIR=src/assets"
targets "tutorial-5"
@ -52,11 +52,11 @@ android {
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
cmake {
path 'jni/CMakeLists.txt'
}
}
ndkVersion '25.2.9519653'
ndkVersion '25.2.9519653'
}
afterEvaluate {

View file

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.18.1)
project("android-tutorial-5" LANGUAGES C CXX)
if(NOT DEFINED GSTREAMER_ROOT_ANDROID)
message(FATAL_ERROR "GSTREAMER_ROOT_ANDROID is not defined!")
endif()
if(ANDROID_ABI STREQUAL "armeabi")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm")
elseif(ANDROID_ABI STREQUAL "armeabi-v7a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/armv7")
elseif(ANDROID_ABI STREQUAL "arm64-v8a")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/arm64")
elseif(ANDROID_ABI STREQUAL "x86")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86")
elseif(ANDROID_ABI STREQUAL "x86_64")
set(GSTREAMER_ROOT "${GSTREAMER_ROOT_ANDROID}/x86_64")
else()
message(FATAL_ERROR "Target arch ABI not supported: ${ANDROID_ABI}")
endif()
list(PREPEND CMAKE_FIND_ROOT_PATH "${GSTREAMER_ROOT}")
set(GSTREAMER_NDK_BUILD_PATH "${GSTREAMER_ROOT}/share/gst-android/ndk-build/")
include("${GSTREAMER_NDK_BUILD_PATH}/plugins.cmake")
set(GSTREAMER_PLUGINS ${GSTREAMER_PLUGINS_CORE} ${GSTREAMER_PLUGINS_PLAYBACK} ${GSTREAMER_PLUGINS_CODECS} ${GSTREAMER_PLUGINS_NET} ${GSTREAMER_PLUGINS_SYS})
set(GSTREAMER_EXTRA_DEPS gstreamer-video-1.0)
set(G_IO_MODULES openssl)
find_library(ANDROID_LIB android REQUIRED)
find_library(LOG_LIB log REQUIRED)
include(${GSTREAMER_NDK_BUILD_PATH}/gstreamer-1.0.cmake)
add_library(tutorial-5 SHARED tutorial-5.c dummy.cpp)
target_link_libraries(tutorial-5
PUBLIC
gstreamer_android
${ANDROID_LIB}
${LOG_LIB}
)
set_target_properties(tutorial-5
PROPERTIES
C_VISIBILITY_PRESET hidden
CXX_VISIBILITY_PRESET hidden
)

View file

@ -109,7 +109,7 @@ get_jni_env (void)
/* Change the content of the UI's TextView */
static void
set_ui_message (const gchar * message, CustomData * data)
set_ui_message (const gchar *message, CustomData *data)
{
JNIEnv *env = get_jni_env ();
GST_DEBUG ("Setting message to: %s", message);
@ -124,7 +124,7 @@ set_ui_message (const gchar * message, CustomData * data)
/* Tell the application what is the current position and clip duration */
static void
set_current_ui_position (gint position, gint duration, CustomData * data)
set_current_ui_position (gint position, gint duration, CustomData *data)
{
JNIEnv *env = get_jni_env ();
(*env)->CallVoidMethod (env, data->app, set_current_position_method_id,
@ -138,7 +138,7 @@ set_current_ui_position (gint position, gint duration, CustomData * data)
/* If we have pipeline and it is running, query the current position and clip duration and inform
* the application */
static gboolean
refresh_ui (CustomData * data)
refresh_ui (CustomData *data)
{
gint64 current = -1;
gint64 position;
@ -175,7 +175,7 @@ static gboolean delayed_seek_cb (CustomData * data);
/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for
* some time in the future. */
static void
execute_seek (gint64 desired_position, CustomData * data)
execute_seek (gint64 desired_position, CustomData *data)
{
gint64 diff;
@ -216,7 +216,7 @@ execute_seek (gint64 desired_position, CustomData * data)
/* Delayed seek callback. This gets called by the timer setup in the above function. */
static gboolean
delayed_seek_cb (CustomData * data)
delayed_seek_cb (CustomData *data)
{
GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT,
GST_TIME_ARGS (data->desired_position));
@ -226,7 +226,7 @@ delayed_seek_cb (CustomData * data)
/* Retrieve errors from the bus and show them on the UI */
static void
error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
error_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GError *err;
gchar *debug_info;
@ -246,7 +246,7 @@ error_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */
static void
eos_cb (GstBus * bus, GstMessage * msg, CustomData * data)
eos_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
data->target_state = GST_STATE_PAUSED;
data->is_live |=
@ -257,7 +257,7 @@ eos_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */
static void
duration_cb (GstBus * bus, GstMessage * msg, CustomData * data)
duration_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
data->duration = GST_CLOCK_TIME_NONE;
}
@ -265,7 +265,7 @@ duration_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when buffering messages are received. We inform the UI about the current buffering level and
* keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */
static void
buffering_cb (GstBus * bus, GstMessage * msg, CustomData * data)
buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
gint percent;
@ -287,7 +287,7 @@ buffering_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Called when the clock is lost */
static void
clock_lost_cb (GstBus * bus, GstMessage * msg, CustomData * data)
clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
if (data->target_state >= GST_STATE_PLAYING) {
gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
@ -297,7 +297,7 @@ clock_lost_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Retrieve the video sink's Caps and tell the application about the media size */
static void
check_media_size (CustomData * data)
check_media_size (CustomData *data)
{
JNIEnv *env = get_jni_env ();
GstElement *video_sink;
@ -330,7 +330,7 @@ check_media_size (CustomData * data)
/* Notify UI about pipeline state changes */
static void
state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data)
{
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
@ -360,7 +360,7 @@ state_changed_cb (GstBus * bus, GstMessage * msg, CustomData * data)
/* Check if all conditions are met to report GStreamer as initialized.
* These conditions will change depending on the application */
static void
check_initialization_complete (CustomData * data)
check_initialization_complete (CustomData *data)
{
JNIEnv *env = get_jni_env ();
if (!data->initialized && data->native_window && data->main_loop) {
@ -470,7 +470,7 @@ app_function (void *userdata)
/* Instruct the native code to create its internal data structure, pipeline and thread */
static void
gst_native_init (JNIEnv * env, jobject thiz)
gst_native_init (JNIEnv *env, jobject thiz)
{
CustomData *data = g_new0 (CustomData, 1);
data->desired_position = GST_CLOCK_TIME_NONE;
@ -487,7 +487,7 @@ gst_native_init (JNIEnv * env, jobject thiz)
/* Quit the main loop, remove the native thread and free resources */
static void
gst_native_finalize (JNIEnv * env, jobject thiz)
gst_native_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -506,7 +506,7 @@ gst_native_finalize (JNIEnv * env, jobject thiz)
/* Set playbin2's URI */
void
gst_native_set_uri (JNIEnv * env, jobject thiz, jstring uri)
gst_native_set_uri (JNIEnv *env, jobject thiz, jstring uri)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data || !data->pipeline)
@ -525,7 +525,7 @@ gst_native_set_uri (JNIEnv * env, jobject thiz, jstring uri)
/* Set pipeline to PLAYING state */
static void
gst_native_play (JNIEnv * env, jobject thiz)
gst_native_play (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -539,7 +539,7 @@ gst_native_play (JNIEnv * env, jobject thiz)
/* Set pipeline to PAUSED state */
static void
gst_native_pause (JNIEnv * env, jobject thiz)
gst_native_pause (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -553,7 +553,7 @@ gst_native_pause (JNIEnv * env, jobject thiz)
/* Instruct the pipeline to seek to a different position */
void
gst_native_set_position (JNIEnv * env, jobject thiz, int milliseconds)
gst_native_set_position (JNIEnv *env, jobject thiz, int milliseconds)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -570,7 +570,7 @@ gst_native_set_position (JNIEnv * env, jobject thiz, int milliseconds)
/* Static class initializer: retrieve method and field IDs */
static jboolean
gst_native_class_init (JNIEnv * env, jclass klass)
gst_native_class_init (JNIEnv *env, jclass klass)
{
custom_data_field_id =
(*env)->GetFieldID (env, klass, "native_custom_data", "J");
@ -597,7 +597,7 @@ gst_native_class_init (JNIEnv * env, jclass klass)
}
static void
gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -627,7 +627,7 @@ gst_native_surface_init (JNIEnv * env, jobject thiz, jobject surface)
}
static void
gst_native_surface_finalize (JNIEnv * env, jobject thiz)
gst_native_surface_finalize (JNIEnv *env, jobject thiz)
{
CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id);
if (!data)
@ -660,8 +660,8 @@ static JNINativeMethod native_methods[] = {
};
/* Library initializer */
jint
JNI_OnLoad (JavaVM * vm, void *reserved)
JNIEXPORT jint
JNI_OnLoad (JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;