GStreamer for Android Demo

GStreamer for Android

本文主要是梳理GStreamer 官方入门demo写的随手笔记

文章目录

一、编译过程

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)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值