GStreamer for Android
本文主要是梳理GStreamer 官方入门demo写的随手笔记
文章目录
- GStreamer for Android
-
- 一、编译过程
- 二、初始化GStreamer
- 三、API示例
-
- 3.1 tutorial-1 获取版本信息
- 3.2 tutorial-2 播放音频
- 3.3 tutorial-3 简单视频播放
- 3.4 tutorial-4 视频播放
-
- 3.4.1实例代码
- 3.4.2 JNI method列表
- 3.4.3 app_function
- 3.4.4 state_changed_cb 状态改变回调
- 3.4.5 check_media_size 检查媒体的size
- 3.4.6 clock_lost_cb 当计时器丢失时回调
- 3.4.7 buffering_cb 播放流媒体 0%-》100%
- 3.4.8 duration_cb 时长进度回调
- 3.4.9 eos_cb 播放结束
- 3.4.10 error_cb 错误回调
- 3.4.11 delayed_seek_cb 延时seek回调
- 3.4.12 关键 execute_seek 执行seek操作
- 3.4.13 gst_native_set_position设置 pos
- 3.4.14 set_current_ui_position 通知UI时长和pos
- 3.5 turorial-5 完整播放器
一、编译过程
1.1 环境搭建
下载GStreamer SDK https://gstreamer.freedesktop.org/data/pkg/android/
下载Demo https://gitlab.freedesktop.org/gstreamer/gst-docs/
下载NDK
本文使用为 NDK 21.3.65 + gstream 17.1
在gradle.properties中增加配置文件
如
gstAndroidRoot=D:\\GitHubSample\\gstreamer\\gstreamer-1.0-android-universal-1.17.1.tar\\gstreamer-1.0-android-universal-1.17.1
如出现GradleException 找不到的问题 将 GradleException改成Exception
如出现?android:attr/colorError 错误
更改到合适版本号
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
1.2 JNI mk文件配置
APP会加载 两个NDK lib 一个是gstreamer_android包含初始化等,一个是私有的native库提供gstreamer的接口封装
tutorial-5也是依赖gstreamer_android的
static {
System.loadLibrary("gstreamer_android");
System.loadLibrary("tutorial-5");
nativeClassInit();
}
1.2.1 gradle配置
gstAndroidRoot为GStreamer SDK的路径
externalNativeBuild {
ndkBuild {
def gstRoot
if (project.hasProperty('gstAndroidRoot'))
gstRoot = project.gstAndroidRoot
else
gstRoot = System.env.GSTREAMER_ROOT_ANDROID
if (gstRoot == null)
throw new Exception('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"
targets "tutorial-1"
// All archs except MIPS and MIPS64 are supported
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
1.2.2 Application.mk
APP_ABI = armeabi armeabi-v7a arm64-v8a x86 x86_64
APP_STL = c++_shared
1.2.3 Android.mk
编译生成tutorial-5
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tutorial-5
LOCAL_SRC_FILES := tutorial-5.c dummy.cpp
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
#NDK buildpath
GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/
#插件 mk
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS)
G_IO_MODULES := openssl
GSTREAMER_EXTRA_DEPS := gstreamer-video-1.0
#gstreamer 初始化的 mk
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk
1.2.3 plugins.mk
在Android.mk里
#插件 mk
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS)
G_IO_MODULES := openssl
GSTREAMER_EXTRA_DEPS := gstreamer-video-1.0
plugins.mk 里预设了好多插件
如GSTREAMER_PLUGINS_PLAYBACK 对应了GSTREAMER_PLUGINS_PLAYBACK := playback
GSTREAMER_PLUGINS_CORE := coreelements coretracers adder app audioconvert audiomixer audiorate audioresample audiotestsrc compositor gio overlaycomposition pango rawparse typefindfunctions videoconvert videorate videoscale videotestsrc volume autodetect videofilter
GSTREAMER_PLUGINS_CODECS := subparse ogg theora vorbis opus ivorbisdec alaw apetag audioparsers auparse avi dv flac flv flxdec icydemux id3demux isomp4 jpeg lame matroska mpg123 mulaw multipart png speex taglib vpx wavenc wavpack wavparse y4menc adpcmdec adpcmenc bz2 dash dvbsuboverlay dvdspu hls id3tag kate midi mxf openh264 opusparse pcapparse pnm rfbsrc siren smoothstreaming subenc videoparsersbad y4mdec jpegformat gdp rsvg openjpeg spandsp sbc zbar androidmedia
GSTREAMER_PLUGINS_ENCODING := encoding
GSTREAMER_PLUGINS_NET := tcp rtsp rtp rtpmanager soup udp dtls netsim rtmp2 sctp sdpelem srtp srt webrtc nice rtspclientsink
GSTREAMER_PLUGINS_PLAYBACK := playback
GSTREAMER_PLUGINS_SYS := opengl ipcpipeline opensles
GSTREAMER_PLUGINS_VIS := libvisual goom goom2k1 audiovisualizers
GSTREAMER_PLUGINS_EFFECTS := alpha alphacolor audiofx cairo cutter debug deinterlace dtmf effectv equalizer gdkpixbuf imagefreeze interleave level multifile replaygain shapewipe smpte spectrum videobox videocrop videomixer accurip aiff audiobuffersplit audiofxbad audiolatency audiomixmatrix autoconvert bayer coloreffects closedcaption debugutilsbad fieldanalysis freeverb frei0r gaudieffects geometrictransform inter interlace ivtc legacyrawparse proxy removesilence segmentclip smooth speed soundtouch timecode videofiltersbad videoframe_audiolevel webrtcdsp ladspa
GSTREAMER_PLUGINS_CAPTURE := camerabin
GSTREAMER_PLUGINS_CODECS_GPL := assrender
GSTREAMER_PLUGINS_CODECS_RESTRICTED := asfmux dtsdec mpegpsdemux mpegpsmux mpegtsdemux mpegtsmux voaacenc a52dec amrnb amrwbdec asf dvdsub dvdlpcmdec xingmux realmedia x264 libav
GSTREAMER_PLUGINS_NET_RESTRICTED := mms rtmp
GSTREAMER_PLUGINS_VULKAN := vulkan
GSTREAMER_PLUGINS_GES := nle ges
在初始化阶段会将这些插件regist进去
genstatic_$(TARGET_ARCH_ABI):
$(hide)$(HOST_ECHO) "GStreamer : [GEN] => $(PRIV_C)"
$(hide)$(call host-mkdir,$(PRIV_B_DIR))
$(hide)$(SED_LOCAL) "s/@PLUGINS_DECLARATION@/$(PRIV_P_D)/g" $(PRIV_C_IN) | $(SED_LOCAL) "s/@PLUGINS_REGISTRATION@/$(PRIV_P_R)/g" | $(SED_LOCAL) "s/@G_IO_MODULES_LOAD@/$(PRIV_G_L)/g" | $(SED_LOCAL) "s/@G_IO_MODULES_DECLARE@/$(PRIV_G_R)/g" > $(PRIV_C)
@PLUGINS_REGISTRATION@ 引用这个
/* Call this function to register static plugins */
void
gst_android_register_static_plugins (void)
{
@PLUGINS_REGISTRATION@
}
最后编译过程中就是 GST_PLUGIN_STATIC_REGISTER(playback); 是其中一个
/* Call this function to register static plugins */
void
gst_android_register_static_plugins (void)
{
GST_PLUGIN_STATIC_REGISTER(coreelements); GST_PLUGIN_STATIC_REGISTER(coretracers); GST_PLUGIN_STATIC_REGISTER(adder); GST_PLUGIN_STATIC_REGISTER(app); GST_PLUGIN_STATIC_REGISTER(audioconvert); GST_PLUGIN_STATIC_REGISTER(audiomixer); GST_PLUGIN_STATIC_REGISTER(audiorate); GST_PLUGIN_STATIC_REGISTER(audioresample); GST_PLUGIN_STATIC_REGISTER(audiotestsrc); GST_PLUGIN_STATIC_REGISTER(compositor); GST_PLUGIN_STATIC_REGISTER(gio); GST_PLUGIN_STATIC_REGISTER(overlaycomposition); GST_PLUGIN_STATIC_REGISTER(pango); GST_PLUGIN_STATIC_REGISTER(rawparse); GST_PLUGIN_STATIC_REGISTER(typefindfunctions); GST_PLUGIN_STATIC_REGISTER(videoconvert); GST_PLUGIN_STATIC_REGISTER(videorate); GST_PLUGIN_STATIC_REGISTER(videoscale); GST_PLUGIN_STATIC_REGISTER(videotestsrc); GST_PLUGIN_STATIC_REGISTER(volume); GST_PLUGIN_STATIC_REGISTER(autodetect); GST_PLUGIN_STATIC_REGISTER(videofilter); GST_PLUGIN_STATIC_REGISTER(playback); GST_PLUGIN_STATIC_REGISTER(subparse); GST_PLUGIN_STATIC_REGISTER(ogg); GST_PLUGIN_STATIC_REGISTER(theora); GST_PLUGIN_STATIC_REGISTER(vorbis); GST_PLUGIN_STATIC_REGISTER(opus); GST_PLUGIN_STATIC_REGISTER(ivorbisdec); GST_PLUGIN_STATIC_REGISTER(alaw); GST_PLUGIN_STATIC_REGISTER(apetag); GST_PLUGIN_STATIC_REGISTER(audioparsers); GST_PLUGIN_STATIC_REGISTER(auparse); GST_PLUGIN_STATIC_REGISTER(avi); GST_PLUGIN_STATIC_REGISTER(dv); GST_PLUGIN_STATIC_REGISTER(flac); GST_PLUGIN_STATIC_REGISTER(flv); GST_PLUGIN_STATIC_REGISTER(flxdec); GST_PLUGIN_STATIC_REGISTER(icydemux); GST_PLUGIN_STATIC_REGISTER(id3demux); GST_PLUGIN_STATIC_REGISTER(isomp4); GST_PLUGIN_STATIC_REGISTER(jpeg); GST_PLUGIN_STATIC_REGISTER(lame); GST_PLUGIN_STATIC_REGISTER(matroska); GST_PLUGIN_STATIC_REGISTER(mpg123); GST_PLUGIN_STATIC_REGISTER(mulaw); GST_PLUGIN_STATIC_REGISTER(multipart); GST_PLUGIN_STATIC_REGISTER(png); GST_PLUGIN_STATIC_REGISTER(speex); GST_PLUGIN_STATIC_REGISTER(taglib); GST_PLUGIN_STATIC_REGISTER(vpx); GST_PLUGIN_STATIC_REGISTER(wavenc); GST_PLUGIN_STATIC_REGISTER(wavpack); GST_PLUGIN_STATIC_REGISTER(wavparse); GST_PLUGIN_STATIC_REGISTER(y4menc); GST_PLUGIN_STATIC_REGISTER(adpcmdec); GST_PLUGIN_STATIC_REGISTER(adpcmenc); GST_PLUGIN_STATIC_REGISTER(bz2); GST_PLUGIN_STATIC_REGISTER(dash); GST_PLUGIN_STATIC_REGISTER(dvbsuboverlay); GST_PLUGIN_STATIC_REGISTER(dvdspu); GST_PLUGIN_STATIC_REGISTER(hls); GST_PLUGIN_STATIC_REGISTER(id3tag); GST_PLUGIN_STATIC_REGISTER(kate); GST_PLUGIN_STATIC_REGISTER(midi); GST_PLUGIN_STATIC_REGISTER(mxf); GST_PLUGIN_STATIC_REGISTER(openh264); GST_PLUGIN_STATIC_REGISTER(opusparse); GST_PLUGIN_STATIC_REGISTER(pcapparse); GST_PLUGIN_STATIC_REGISTER(pnm); GST_PLUGIN_STATIC_REGISTER(rfbsrc); GST_PLUGIN_STATIC_REGISTER(siren); GST_PLUGIN_STATIC_REGISTER(smoothstreaming); GST_PLUGIN_STATIC_REGISTER(subenc); GST_PLUGIN_STATIC_REGISTER(videoparsersbad); GST_PLUGIN_STATIC_REGISTER(y4mdec); GST_PLUGIN_STATIC_REGISTER(jpegformat); GST_PLUGIN_STATIC_REGISTER(gdp); GST_PLUGIN_STATIC_REGISTER(rsvg); GST_PLUGIN_STATIC_REGISTER(openjpeg); GST_PLUGIN_STATIC_REGISTER(spandsp); GST_PLUGIN_STATIC_REGISTER(sbc); GST_PLUGIN_STATIC_REGISTER(zbar); GST_PLUGIN_STATIC_REGISTER(androidmedia); GST_PLUGIN_STATIC_REGISTER(tcp); GST_PLUGIN_STATIC_REGISTER(rtsp); GST_PLUGIN_STATIC_REGISTER(rtp); GST_PLUGIN_STATIC_REGISTER(rtpmanager); GST_PLUGIN_STATIC_REGISTER(soup); GST_PLUGIN_STATIC_REGISTER(udp); GST_PLUGIN_STATIC_REGISTER(dtls); GST_PLUGIN_STATIC_REGISTER(netsim); GST_PLUGIN_STATIC_REGISTER(rtmp2); GST_PLUGIN_STATIC_REGISTER(sctp); GST_PLUGIN_STATIC_REGISTER(sdpelem); GST_PLUGIN_STATIC_REGISTER(srtp); GST_PLUGIN_STATIC_REGISTER(srt); GST_PLUGIN_STATIC_REGISTER(webrtc); GST_PLUGIN_STATIC_REGISTER(nice); GST_PLUGIN_STATIC_REGISTER(rtspclientsink); GST_PLUGIN_STATIC_REGISTER(opengl); GST_PLUGIN_STATIC_REGISTER(ipcpipeline); GST_PLUGIN_STATIC_REGISTER(opensles);
}
@G_IO_MODULES_DECLARE@
void
gst_android_load_gio_modules (void)
{
GTlsBackend *backend;
const gchar *ca_certs;
GST_G_IO_MODULE_LOAD(openssl);
1.3 SDK里的NDK build
SDK里有以下几个mk
gstreamer-1.0.mk
gstreamer_prebilt.mk
plugins.mk //
tools.mk
1.3.1 gstreamer-1.0.mk
初始化资源路径路径变量相关 GSTREAMER_ROOT为SDK根目录
$(call assert-defined, GSTREAMER_ROOT)
$(if $(wildcard $(GSTREAMER_ROOT)),,\
$(error "The directory GSTREAMER_ROOT=$(GSTREAMER_ROOT) does not exists")\
)
#####################
# Setup variables #
#####################
ifndef GSTREAMER_PLUGINS
$(info "The list of GSTREAMER_PLUGINS is empty")
endif
# Expand home directory (~/)
GSTREAMER_ROOT := $(wildcard $(GSTREAMER_ROOT))
# Path for GStreamer static plugins
GSTREAMER_STATIC_PLUGINS_PATH := $(GSTREAMER_ROOT)/lib/gstreamer-1.0
# Path for the NDK integration makefiles
GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_ROOT)/share/gst-android/ndk-build
ifndef GSTREAMER_INCLUDE_FONTS
GSTREAMER_INCLUDE_FONTS := yes
endif
ifndef GSTREAMER_INCLUDE_CA_CERTIFICATES
GSTREAMER_INCLUDE_CA_CERTIFICATES := yes
endif
ifndef GSTREAMER_JAVA_SRC_DIR
GSTREAMER_JAVA_SRC_DIR := src
endif
加载tools.mk 和工具相关变量
# Include tools
include $(GSTREAMER_NDK_BUILD_PATH)/tools.mk
# Path for the static GIO modules
G_IO_MODULES_PATH := $(GSTREAMER_ROOT)/lib/gio/modules
# Path for libc++_shared
CXX_SHARED_ROOT := $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(TARGET_ARCH_ABI)
# Host tools
ifeq ($(HOST_OS),windows)
SED := $(GSTREAMER_NDK_BUILD_PATH)/tools/windows/sed
SED_LOCAL := "$(GSTREAMER_NDK_BUILD_PATH)/tools/windows/sed"
EXE_SUFFIX := .exe
else
SED := sed
SED_LOCAL := sed
EXE_SUFFIX :=
endif
编译变量和编译module信息 生成gstreamer_android 的库
ifndef GSTREAMER_ANDROID_MODULE_NAME
GSTREAMER_ANDROID_MODULE_NAME := gstreamer_android
endif
GSTREAMER_BUILD_DIR := gst-build-$(TARGET_ARCH_ABI)
GSTREAMER_ANDROID_O := $(GSTREAMER_BUILD_DIR)/$(GSTREAMER_ANDROID_MODULE_NAME).o
GSTREAMER_ANDROID_SO := $(GSTREAMER_BUILD_DIR)/lib$(GSTREAMER_ANDROID_MODULE_NAME).so
GSTREAMER_ANDROID_C := $(GSTREAMER_BUILD_DIR)/$(GSTREAMER_ANDROID_MODULE_NAME).c
GSTREAMER_ANDROID_C_IN := $(GSTREAMER_NDK_BUILD_PATH)/gstreamer_android-1.0.c.in
GSTREAMER_DEPS := $(GSTREAMER_EXTRA_DEPS) gstreamer-1.0
GSTREAMER_LD := -fuse-ld=gold$(EXE_SUFFIX) -Wl,-soname,lib$(GSTREAMER_ANDROID_MODULE_NAME).so
# for setting the default GTlsDatabase
ifeq ($(GSTREAMER_INCLUDE_CA_CERTIFICATES),yes)
GSTREAMER_DEPS += gio-2.0
endif
################################
# NDK Build Prebuilt library #
################################
# Declare a prebuilt library module, a shared library including
# gstreamer, its dependencies and all its plugins.
# Since the shared library is not really prebuilt, but will be built
# using the defined rules in this file, we can't use the
# PREBUILT_SHARED_LIBRARY makefiles like explained in the docs,
# as it checks for the existance of the shared library. We therefore
# use a custom gstreamer_prebuilt.mk, which skips this step
include $(CLEAR_VARS)
LOCAL_MODULE := $(GSTREAMER_ANDROID_MODULE_NAME)
LOCAL_SRC_FILES := $(GSTREAMER_ANDROID_SO)
LOCAL_BUILD_SCRIPT := PREBUILT_SHARED_LIBRARY
LOCAL_MODULE_CLASS := PREBUILT_SHARED_LIBRARY
LOCAL_MAKEFILE := $(local-makefile)
LOCAL_PREBUILT_PREFIX := lib
LOCAL_PREBUILT_SUFFIX := .so
LOCAL_EXPORT_C_INCLUDES := $(subst -I$1, $1, $(call pkg-config-get-includes,$(GSTREAMER_DEPS)))
LOCAL_EXPORT_C_INCLUDES += $(GSTREAMER_ROOT)/include
开始加载plugin 其中会加载到 prebuilt.mk
##################################################################
# Our custom rules to create a shared libray with gstreamer #
# and the requested plugins in GSTREAMER_PLUGINS starts here #
##################################################################
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer_prebuilt.mk
fix-deps = \
$(subst $1,$1 $2,$(GSTREAMER_ANDROID_LIBS))
# Generate list of plugin links (eg: -lcoreelements -lvideoscale)
GSTREAMER_PLUGINS_LIBS := $(foreach plugin, $(GSTREAMER_PLUGINS), -lgst$(plugin) )
GSTREAMER_PLUGINS_CLASSES := $(strip \
$(subst $(GSTREAMER_NDK_BUILD_PATH),, \
$(foreach plugin,$(GSTREAMER_PLUGINS), \
$(wildcard $(GSTREAMER_NDK_BUILD_PATH)/$(plugin)/*.java))))
GSTREAMER_PLUGINS_WITH_CLASSES := $(strip \
$(subst $(GSTREAMER_NDK_BUILD_PATH),, \
$(foreach plugin, $(GSTREAMER_PLUGINS), \
$(wildcard $(GSTREAMER_NDK_BUILD_PATH)/$(plugin)))))
# Generate the plugins' declaration strings
GSTREAMER_PLUGINS_DECLARE := $(foreach plugin, $(GSTREAMER_PLUGINS), \
GST_PLUGIN_STATIC_DECLARE($(plugin));)
# Generate the plugins' registration strings
GSTREAMER_PLUGINS_REGISTER := $(foreach plugin, $(GSTREAMER_PLUGINS), \
GST_PLUGIN_STATIC_REGISTER($(plugin));)
IO模块
# Generate list of gio modules
G_IO_MODULES_LIBS := $(foreach module, $(G_IO_MODULES), $(G_IO_MODULES_PATH)/libgio$(module).a)
G_IO_MODULES_DECLARE := $(foreach module, $(G_IO_MODULES), \
GST_G_IO_MODULE_DECLARE($(module));)
G_IO_MODULES_LOAD := $(foreach module, $(G_IO_MODULES), \
GST_G_IO_MODULE_LOAD($(module));)
# Get the full list of libraries
# link at least to gstreamer-1.0 in case the plugins list is empty
GSTREAMER_ANDROID_LIBS := $(call pkg-config-get-libs,$(GSTREAMER_DEPS))
GSTREAMER_ANDROID_LIBS += $(GSTREAMER_PLUGINS_LIBS) $(G_IO_MODULES_LIBS) $(GSTREAMER_EXTRA_LIBS) -llog -lz
GSTREAMER_ANDROID_WHOLE_AR := $(call pkg-config-get-libs-no-deps,$(GSTREAMER_DEPS)) $(GSTREAMER_EXTRA_LIBS)
GSTREAMER_ANDROID_CFLAGS := $(call pkg-config-get-includes,$(GSTREAMER_DEPS)) -I$(GSTREAMER_ROOT)/include
NDK相关 和 Android cmd
# In newer NDK, SYSROOT is replaced by SYSROOT_INC and SYSROOT_LINK, which
# now points to the root directory. But this will probably change in the future from:
# https://android.googlesource.com/platform/ndk/+/fa8c1b4338c1bef2813ecee0ee298e9498a1aaa7
ifdef SYSROOT
SYSROOT_GST_INC := $(SYSROOT)
SYSROOT_GST_LINK_ARG := --sysroot=$(SYSROOT)
else
ifdef SYSROOT_LINK
ifdef SYSROOT_LINK
SYSROOT_GST_INC := $(SYSROOT_INC)
# SYSROOT_GST_LINK_ARG := --sysroot=$(SYSROOT_LINK)
SYSROOT_GST_LINK_ARG := --sysroot=$(SYSROOT_INC)
endif
else
ifdef SYSROOT_LIB_DIR
# https://android.googlesource.com/platform/ndk/+/8afb627a222005272e61d4b222b50c69e760d77d
# introduced SYSROOT_LIB_DIR
SYSROOT_GST_INC := $(SYSROOT_INC)
SYSROOT_GST_LINK_ARG := -L$(SYSROOT_API_LIB_DIR) -L$(SYSROOT_LIB_DIR)
else
SYSROOT_GST_INC := $(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-$(TARGET_ARCH)
SYSROOT_GST_LINK_ARG := -L$(SYSROOT_GST_INC)
endif
endif
endif
# Create the link command
GSTREAMER_ANDROID_CMD := $(call libtool-link,$(TARGET_CXX) $(GLOBAL_LDFLAGS) $(TARGET_LDFLAGS) -nostdlib++ -shared $(SYSROOT_GST_LINK_ARG) \
-o $(GSTREAMER_ANDROID_SO) $(GSTREAMER_ANDROID_O) \
-L$(GSTREAMER_ROOT)/lib -L$(GSTREAMER_STATIC_PLUGINS_PATH) -L$(CXX_SHARED_ROOT) \
$(GSTREAMER_ANDROID_LIBS), $(GSTREAMER_LD)) -Wl,-no-undefined $(GSTREAMER_LD)
GSTREAMER_ANDROID_CMD := $(call libtool-whole-archive,$(GSTREAMER_ANDROID_CMD),$(GSTREAMER_ANDROID_WHOLE_AR))
重点 用户自定义 包含插件 字体 签名
# This triggers the build of our library using our custom rules
$(GSTREAMER_ANDROID_SO): buildsharedlibrary_$(TARGET_ARCH_ABI)
$(GSTREAMER_ANDROID_SO): copyjavasource_$(TARGET_ARCH_ABI)
ifeq ($(GSTREAMER_INCLUDE_FONTS),yes)
$(GSTREAMER_ANDROID_SO): copyfontsres_$(TARGET_ARCH_ABI)
endif
ifeq ($(GSTREAMER_INCLUDE_CA_CERTIFICATES),yes)
$(GSTREAMER_ANDROID_SO): copycacertificatesres_$(TARGET_ARCH_ABI)
endif
delsharedlib_$(TARGET_ARCH_ABI): PRIV_B_DIR := $(GSTREAMER_BUILD_DIR)
delsharedlib_$(TARGET_ARCH_ABI):
$(hide)$(call host-rm,$(prebuilt))
$(hide)$(foreach path,$(wildcard $(PRIV_B_DIR)/sed*), $(call host-rm,$(path)) && ) echo Done rm
$(LOCAL_INSTALLED): delsharedlib_$(TARGET_ARCH_ABI)
# Generates a source file that declares and registers all the required plugins
# about the sed command, android-studio doesn't seem to like line continuation characters when executing shell commands
genstatic_$(TARGET_ARCH_ABI): PRIV_C := $(GSTREAMER_ANDROID_C)
genstatic_$(TARGET_ARCH_ABI): PRIV_B_DIR := $(GSTREAMER_BUILD_DIR)
genstatic_$(TARGET_ARCH_ABI): PRIV_C_IN := $(GSTREAMER_ANDROID_C_IN)
genstatic_$(TARGET_ARCH_ABI): PRIV_P_D := $(GSTREAMER_PLUGINS_DECLARE)
genstatic_$(TARGET_ARCH_ABI): PRIV_P_R := $(GSTREAMER_PLUGINS_REGISTER)
genstatic_$(TARGET_ARCH_ABI): PRIV_G_L := $(G_IO_MODULES_LOAD)
genstatic_$(TARGET_ARCH_ABI): PRIV_G_R := $(G_IO_MODULES_DECLARE)
genstatic_$(TARGET_ARCH_ABI):
$(hide)$(HOST_ECHO) "GStreamer : [GEN] => $(PRIV_C)"
$(hide)$(call host-mkdir,$(PRIV_B_DIR))
$(hide)$(SED_LOCAL) "s/@PLUGINS_DECLARATION@/$(PRIV_P_D)/g" $(PRIV_C_IN) | $(SED_LOCAL) "s/@PLUGINS_REGISTRATION@/$(PRIV_P_R)/g" | $(SED_LOCAL) "s/@G_IO_MODULES_LOAD@/$(PRIV_G_L)/g" | $(SED_LOCAL) "s/@G_IO_MODULES_DECLARE@/$(PRIV_G_R)/g" > $(PRIV_C)
# Compile the source file
$(GSTREAMER_ANDROID_O): PRIV_C := $(GSTREAMER_ANDROID_C)
$(GSTREAMER_ANDROID_O): PRIV_CC_CMD := $(TARGET_CC) --sysroot=$(SYSROOT_GST_INC) $(SYSROOT_ARCH_INC_ARG) $(GLOBAL_CFLAGS) $(TARGET_CFLAGS) \
-c $(GSTREAMER_ANDROID_C) -Wall -Werror -o $(GSTREAMER_ANDROID_O) $(GSTREAMER_ANDROID_CFLAGS)
$(GSTREAMER_ANDROID_O): PRIV_GST_CFLAGS := $(GSTREAMER_ANDROID_CFLAGS) $(TARGET_CFLAGS)
$(GSTREAMER_ANDROID_O): genstatic_$(TARGET_ARCH_ABI)
$(hide)$(HOST_ECHO) "GStreamer : [COMPILE] => $(PRIV_C)"
$(hide)$(PRIV_CC_CMD)
# Creates a shared library including gstreamer, its plugins and all the dependencies
buildsharedlibrary_$(TARGET_ARCH_ABI): PRIV_CMD := $(GSTREAMER_ANDROID_CMD)
buildsharedlibrary_$(TARGET_ARCH_ABI): PRIV_SO := $(GSTREAMER_ANDROID_SO)
buildsharedlibrary_$(TARGET_ARCH_ABI): $(GSTREAMER_ANDROID_O)
$(hide)$(HOST_ECHO) "GStreamer : [LINK] => $(PRIV_SO)"
$(hide)$(PRIV_CMD)
ifeq ($(GSTREAMER_INCLUDE_FONTS),yes)
GSTREAMER_INCLUDE_FONTS_SUBST :=
else
GSTREAMER_INCLUDE_FONTS_SUBST := //
endif
ifeq ($(GSTREAMER_INCLUDE_CA_CERTIFICATES),yes)
GSTREAMER_INCLUDE_CA_CERTIFICATES_SUBST :=
else
GSTREAMER_INCLUDE_CA_CERTIFICATES_SUBST := //
endif
ifneq (,$(findstring yes,$(GSTREAMER_INCLUDE_FONTS)$(GSTREAMER_INCLUDE_CA_CERTIFICATES)))
GSTREAMER_COPY_FILE_SUBST :=
else
GSTREAMER_COPY_FILE_SUBST := //
endif
# about the sed command, android-studio doesn't seem to like line continuation characters when executing shell commands
copyjavasource_$(TARGET_ARCH_ABI):
$(hide)$(call host-mkdir,$(GSTREAMER_JAVA_SRC_DIR)/org/freedesktop/gstreamer)
$(hide)$(foreach plugin,$(GSTREAMER_PLUGINS_WITH_CLASSES), \
$(call host-mkdir,$(GSTREAMER_JAVA_SRC_DIR)/org/freedesktop/gstreamer/$(plugin)) && ) echo Done mkdir
$(hide)$(foreach file,$(GSTREAMER_PLUGINS_CLASSES), \
$(call host-cp,$(GSTREAMER_NDK_BUILD_PATH)$(file),$(GSTREAMER_JAVA_SRC_DIR)/org/freedesktop/gstreamer/$(file)) && ) echo Done cp
$(hide)$(SED_LOCAL) "s;@INCLUDE_FONTS@;$(GSTREAMER_INCLUDE_FONTS_SUBST);g" $(GSTREAMER_NDK_BUILD_PATH)/GStreamer.java | $(SED_LOCAL) "s;@INCLUDE_CA_CERTIFICATES@;$(GSTREAMER_INCLUDE_CA_CERTIFICATES_SUBST);g" | $(SED_LOCAL) "s;@INCLUDE_COPY_FILE@;$(GSTREAMER_COPY_FILE_SUBST);g" > $(GSTREAMER_JAVA_SRC_DIR)/org/freedesktop/gstreamer/GStreamer.java
ifndef GSTREAMER_ASSETS_DIR
GSTREAMER_ASSETS_DIR := src/main/assets
endif
copyfontsres_$(TARGET_ARCH_ABI):
$(hide)$(call host-mkdir,$(GSTREAMER_ASSETS_DIR)/fontconfig)
$(hide)$(call host-mkdir,$(GSTREAMER_ASSETS_DIR)/fontconfig/fonts/truetype/)
$(hide)$(call host-cp,$(GSTREAMER_NDK_BUILD_PATH)/fontconfig/fonts.conf,$(GSTREAMER_ASSETS_DIR)/fontconfig)
$(hide)$(call host-cp,$(GSTREAMER_NDK_BUILD_PATH)/fontconfig/fonts/Ubuntu-R.ttf,$(GSTREAMER_ASSETS_DIR)/fontconfig/fonts/truetype)
copycacertificatesres_$(TARGET_ARCH_ABI):
$(hide)$(call host-mkdir,$(GSTREAMER_ASSETS_DIR)/ssl/certs)
$(hide)$(call host-cp,$(GSTREAMER_ROOT)/etc/ssl/certs/ca-certificates.crt,$(GSTREAMER_ASSETS_DIR)/ssl/certs)
1.3.2 Tools.mk
加载一堆lib库
1.3.3 Gstreamer_prebuilt.mk
最终加载到build-module.mk
include $(BUILD_SYSTEM)/build-module.mk
二、初始化GStreamer
try {
GStreamer.init(this);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
finish();
return;
}
2.1 GStreamer.java 基础类
public class GStreamer {
private static native void nativeInit(Context context) throws Exception;
public static void init(Context context) throws Exception {
//将assets中签名证书copy到应用的files目录
copyCaCertificates(context);
//将assets字体格式设置copy到应用饿files目录
copyFonts(context);
//调用 native初始化
nativeInit(context);
}
2.2 Gstreamer_android-1.0.c.in 安卓平台初始化专用 jni
jint
JNI_OnLoad (JavaVM * vm, void * reserved)
{
JNIEnv *env = NULL;
GModule *module;
if ((*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_4) != JNI_OK) {
__android_log_print (ANDROID_LOG_ERROR, "GStreamer",
"Could not retrieve JNIEnv");
return 0;
}
// 找到 GStreamer里的java类 适配需要修改这个路径
jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/GStreamer");
if (!klass) {
__android_log_print (ANDROID_LOG_ERROR, "GStreamer",
"Could not retrieve class org.freedesktop.gstreamer.GStreamer");
return 0;
}
//注册JNI函数
if ((*env)->RegisterNatives (env, klass, native_methods,
G_N_ELEMENTS (native_methods))) {
__android_log_print (ANDROID_LOG_ERROR, "GStreamer",
"Could not register native methods for org.freedesktop.gstreamer.GStreamer");
return 0;
}
/* Remember Java VM */
_java_vm = vm;
// 打开模块 set java vm虚拟机
/* Tell the androidmedia plugin about the Java VM if we can */
module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
if (module) {
void (*set_java_vm) (JavaVM *) = NULL;
if (g_module_symbol (module, "gst_amc_jni_set_java_vm",
(gpointer *) & set_java_vm) && set_java_vm) {
set_java_vm (vm);
}
g_module_close (module);
}
return JNI_VERSION_1_4;
}
Gmodule.h
/**
* GModuleFlags:
* @G_MODULE_BIND_LAZY: specifies that symbols are only resolved when
* needed. The default action is to bind all symbols when the module
* is loaded.
* @G_MODULE_BIND_LOCAL: specifies that symbols in the module should
* not be added to the global name space. The default action on most
* platforms is to place symbols in the module in the global name space,
* which may cause conflicts with existing symbols.
* @G_MODULE_BIND_MASK: mask for all flags.
*
* Flags passed to g_module_open().
* Note that these flags are not supported on all platforms.
*/
typedef enum
{
G_MODULE_BIND_LAZY = 1 << 0, //懒加载
G_MODULE_BIND_LOCAL = 1 << 1, //命名空间 local
G_MODULE_BIND_MASK = 0x03 //以上两个集合
} GModuleFlags;
/* open a module 'file_name' and return handle, which is NULL on error */
GLIB_AVAILABLE_IN_ALL
GModule* g_module_open (const gchar *file_name,
GModuleFlags flags);
2.3 gst_android_init 初始化
void
gst_android_init (JNIEnv * env, jobject context)
{
//1. init android context
if (!init (env, context)) {
__android_log_print (ANDROID_LOG_INFO, "GStreamer",
"GStreamer failed to initialize");
}
// 初始化already判定
if (gst_is_initialized ()) {
__android_log_print (ANDROID_LOG_INFO, "GStreamer",
"GStreamer already initialized");
return;
}
//2. 获取存有证书签名和字体config的文件路径 获取APP的 cache目录和 files目录
if (!get_application_dirs (env, context, &cache_dir, &files_dir)) {
__android_log_print (ANDROID_LOG_ERROR, "GStreamer",
"Failed to get application dirs");
}
// 设置环境变量 缓存路径和 home路径
if (cache_dir) {
g_setenv ("TMP", cache_dir, TRUE);
registry = g_build_filename (cache_dir, "registry.bin", NULL); //注册
g_setenv ("GST_REGISTRY", registry, TRUE);
g_free (registry);
····
}
if (files_dir) {
gchar *fontconfig, *certs;
g_setenv ("HOME", files_dir, TRUE);
···
fontconfig = g_build_filename (files_dir, "fontconfig", NULL); //字体
g_setenv ("FONTCONFIG_PATH", fontconfig, TRUE);
g_free (fontconfig);
certs = g_build_filename (files_dir, "ssl", "certs", "ca-certificates.crt", NULL); //证书
g_setenv ("CA_CERTIFICATES", certs, TRUE);
g_free (certs);
}
//设置输出打印 handler
/* Set GLib print handlers */
g_set_print_handler (glib_print_handler);
g_set_printerr_handler (glib_printerr_handler);
g_log_set_default_handler (glib_log_handler, NULL);
//未知
/* Call this function to register static plugins */
gst_android_register_static_plugins ();
/* Call this function to load GIO modules */
gst_android_load_gio_modules ();
}
2.4 init context初始化操作
static gboolean
init (JNIEnv *env, jobject context)
{
jclass context_cls = NULL;
jmethodID get_class_loader_id = 0;
jobject class_loader = NULL;
// 获得java层的 context对象
context_cls = (*env)->GetObjectClass (env, context);
get_class_loader_id = (*env)->GetMethodID (env, context_cls,
"getClassLoader", "()Ljava/lang/ClassLoader;");
if ((*env)->ExceptionCheck (env)) {
(*env)->ExceptionDescribe (env);
(*env)->ExceptionClear (env);
return FALSE;
}
//获取 class loader对象
class_loader = (*env)->CallObjectMethod (env, context, get_class_loader_id);
//context 和 classloader 赋值给全局变量
if (_context) {
(*env)->DeleteGlobalRef (env, _context);
}
_context = (*env)->NewGlobalRef (env, context);
if (_class_loader) {
(*env)->DeleteGlobalRef (env, _class_loader);
}
_class_loader = (*env)->NewGlobalRef (env, class_loader);
return TRUE;
}
2.5 gst_android_register_static_plugins
void
gst_android_register_static_plugins (void)
{
//编译替代
@PLUGINS_REGISTRATION@
}
/* Call this function to register static plugins */
void
gst_android_register_static_plugins (void)
{
GST_PLUGIN_STATIC_REGISTER(coreelements); GST_PLUGIN_STATIC_REGISTER(coretracers); GST_PLUGIN_STATIC_REGISTER(adder); GST_PLUGIN_STATIC_REGISTER(app); GST_PLUGIN_STATIC_REGISTER(audioconvert); GST_PLUGIN_STATIC_REGISTER(audiomixer); GST_PLUGIN_STATIC_REGISTER(audiorate); GST_PLUGIN_STATIC_REGISTER(audioresample); GST_PLUGIN_STATIC_REGISTER(audiotestsrc); GST_PLUGIN_STATIC_REGISTER(compositor); GST_PLUGIN_STATIC_REGISTER(gio); GST_PLUGIN_STATIC_REGISTER(overlaycomposition); GST_PLUGIN_STATIC_REGISTER(pango); GST_PLUGIN_STATIC_REGISTER(rawparse); GST_PLUGIN_STATIC_REGISTER(typefindfunctions); GST_PLUGIN_STATIC_REGISTER(videoconvert); GST_PLUGIN_STATIC_REGISTER(videorate); GST_PLUGIN_STATIC_REGISTER(videoscale); GST_PLUGIN_STATIC_REGISTER(videotestsrc); GST_PLUGIN_STATIC_REGISTER(volume)