将使用 NDK 和 Gstreamer 的 Eclipse android 项目迁移到 Android Studio

Posted

技术标签:

【中文标题】将使用 NDK 和 Gstreamer 的 Eclipse android 项目迁移到 Android Studio【英文标题】:Migrating Eclipse android project with NDK and Gstreamer usage to Android Studio 【发布时间】:2016-08-07 01:34:51 【问题描述】:

我在 Eclipse 中有一个完美运行的 android 项目,该项目包括 NDK 支持并使用 Gstreamer。 当我将项目从 Eclipse 迁移到 Android Studio 时,会出现各种问题,我就是无法成功编译项目。

我对遇到的每一个错误都进行了彻底的研究,但仍然无法在 android studio 上编译和运行该项目。

https://drive.google.com/file/d/0B_euzgSjTAqcQngwbzR1cXY0MkU/view?usp=sharing

一个指向工作 Eclipse 项目的链接,我希望有人可以指导我正确的方式。

这是导入摘要:

ECLIPSE ANDROID 项目导入摘要

忽略的文件:

以下文件没有复制到新的 Gradle 项目中;你 应该评估您的项目中是否仍需要这些,以及是否 所以手动移动它们:

.externalToolBuilders\ .externalToolBuilders\Wiz.launch gst 构建\ gst-build\gstreamer_android.c gst-build\gstreamer_android.o

用依赖替换了jar:

导入器将以下 .jar 文件识别为第三方 库并将它们替换为 Gradle 依赖项。这有 知道更明确的版本信息的优点,以及 库可以自动更新。但是,有可能 项目中的 .jar 文件的版本比 我们选择的依赖项,这可能会使项目无法编译。 您可以在导入向导中禁用 jar 替换,然后重试:

android-support-v4.jar => com.android.support:support-v4:23.3.0

移动的文件:

Android Gradle 项目使用与 ADT 不同的目录结构 Eclipse 项目。以下是项目的重组方式:

AndroidManifest.xml => app\src\main\AndroidManifest.xml assets\ => app\src\main\assets\ jni\ => app\src\main\jni\ libs\armeabi\libavcodec.so => app\src\main\jniLibs\armeabi\libavcodec.so libs\armeabi\libavdevice.so => app\src\main\jniLibs\armeabi\libavdevice.so libs\armeabi\libavfilter.so => app\src\main\jniLibs\armeabi\libavfilter.so libs\armeabi\libavformat.so => app\src\main\jniLibs\armeabi\libavformat.so libs\armeabi\libavutil.so => app\src\main\jniLibs\armeabi\libavutil.so libs\armeabi\libgstreamer_android.so => app\src\main\jniLibs\armeabi\libgstreamer_android.so libs\armeabi\libjniARToolKitPlus.so => app\src\main\jniLibs\armeabi\libjniARToolKitPlus.so libs\armeabi\libjniavcodec.so => app\src\main\jniLibs\armeabi\libjniavcodec.so libs\armeabi\libjniavdevice.so => app\src\main\jniLibs\armeabi\libjniavdevice.so libs\armeabi\libjniavfilter.so => app\src\main\jniLibs\armeabi\libjniavfilter.so libs\armeabi\libjniavformat.so => app\src\main\jniLibs\armeabi\libjniavformat.so libs\armeabi\libjniavutil.so => app\src\main\jniLibs\armeabi\libjniavutil.so libs\armeabi\libjnicvkernels.so => app\src\main\jniLibs\armeabi\libjnicvkernels.so libs\armeabi\libjniopencv_calib3d.so => app\src\main\jniLibs\armeabi\libjniopencv_calib3d.so libs\armeabi\libjniopencv_contrib.so => app\src\main\jniLibs\armeabi\libjniopencv_contrib.so libs\armeabi\libjniopencv_core.so => app\src\main\jniLibs\armeabi\libjniopencv_core.so libs\armeabi\libjniopencv_features2d.so => app\src\main\jniLibs\armeabi\libjniopencv_features2d.so libs\armeabi\libjniopencv_flann.so => app\src\main\jniLibs\armeabi\libjniopencv_flann.so libs\armeabi\libjniopencv_highgui.so => app\src\main\jniLibs\armeabi\libjniopencv_highgui.so libs\armeabi\libjniopencv_imgproc.so => app\src\main\jniLibs\armeabi\libjniopencv_imgproc.so libs\armeabi\libjniopencv_legacy.so => app\src\main\jniLibs\armeabi\libjniopencv_legacy.so libs\armeabi\libjniopencv_ml.so => app\src\main\jniLibs\armeabi\libjniopencv_ml.so libs\armeabi\libjniopencv_nonfree.so => app\src\main\jniLibs\armeabi\libjniopencv_nonfree.so libs\armeabi\libjniopencv_objdetect.so => app\src\main\jniLibs\armeabi\libjniopencv_objdetect.so libs\armeabi\libjniopencv_photo.so => app\src\main\jniLibs\armeabi\libjniopencv_photo.so libs\armeabi\libjniopencv_stitching.so => app\src\main\jniLibs\armeabi\libjniopencv_stitching.so libs\armeabi\libjniopencv_video.so => app\src\main\jniLibs\armeabi\libjniopencv_video.so libs\armeabi\libjniopencv_videostab.so => app\src\main\jniLibs\armeabi\libjniopencv_videostab.so libs\armeabi\libjnipostproc.so => app\src\main\jniLibs\armeabi\libjnipostproc.so libs\armeabi\libjniswresample.so => app\src\main\jniLibs\armeabi\libjniswresample.so libs\armeabi\libjniswscale.so => app\src\main\jniLibs\armeabi\libjniswscale.so libs\armeabi\libopencv_calib3d.so => app\src\main\jniLibs\armeabi\libopencv_calib3d.so libs\armeabi\libopencv_contrib.so => app\src\main\jniLibs\armeabi\libopencv_contrib.so libs\armeabi\libopencv_core.so => app\src\main\jniLibs\armeabi\libopencv_core.so libs\armeabi\libopencv_features2d.so => app\src\main\jniLibs\armeabi\libopencv_features2d.so libs\armeabi\libopencv_flann.so => app\src\main\jniLibs\armeabi\libopencv_flann.so libs\armeabi\libopencv_highgui.so => app\src\main\jniLibs\armeabi\libopencv_highgui.so libs\armeabi\libopencv_imgproc.so => app\src\main\jniLibs\armeabi\libopencv_imgproc.so libs\armeabi\libopencv_info.so => app\src\main\jniLibs\armeabi\libopencv_info.so libs\armeabi\libopencv_legacy.so => app\src\main\jniLibs\armeabi\libopencv_legacy.so libs\armeabi\libopencv_ml.so => app\src\main\jniLibs\armeabi\libopencv_ml.so libs\armeabi\libopencv_nonfree.so => app\src\main\jniLibs\armeabi\libopencv_nonfree.so libs\armeabi\libopencv_objdetect.so => app\src\main\jniLibs\armeabi\libopencv_objdetect.so libs\armeabi\libopencv_photo.so => app\src\main\jniLibs\armeabi\libopencv_photo.so libs\armeabi\libopencv_stitching.so => app\src\main\jniLibs\armeabi\libopencv_stitching.so libs\armeabi\libopencv_ts.so => app\src\main\jniLibs\armeabi\libopencv_ts.so libs\armeabi\libopencv_video.so => app\src\main\jniLibs\armeabi\libopencv_video.so libs\armeabi\libopencv_videostab.so => app\src\main\jniLibs\armeabi\libopencv_videostab.so libs\armeabi\libpostproc.so => app\src\main\jniLibs\armeabi\libpostproc.so libs\armeabi\libswresample.so => app\src\main\jniLibs\armeabi\libswresample.so libs\armeabi\libswscale.so => app\src\main\jniLibs\armeabi\libswscale.so libs\armeabi\libtbb.so => app\src\main\jniLibs\armeabi\libtbb.so libs\javacpp.jar => app\libs\javacpp.jar libs\javacv.jar => app\libs\javacv.jar res\ => app\src\main\res\ src\ => app\src\main\java\

后续步骤:

您现在可以构建项目了。 Gradle 项目需要网络 连接下载依赖项。

错误:

如果由于某种原因您的项目没有构建,并且您确定 这是由于 Eclipse 到 Gradle 导入器的错误或限制, 请在http://b.android.com 提交错误,并注明类别 组件工具。

(此导入摘要仅供您参考,可以删除 导入后对结果感到满意。)

Build.Gradle:

apply plugin: 'com.android.model.application'

model 
    android 
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"

        defaultConfig.with 
            applicationId = "com.gst_sdk_tutorials.tutorial_4"
            minSdkVersion.apiLevel = 17
            targetSdkVersion.apiLevel = 22
        

    

    android.ndk 
        moduleName = "tutorial-4"
        cppFlags.addAll(["-I$file("src/main/jni/Common/native_app_glue")".toString(),
                         "-I$file("src/main/jni/Common/cpufeatures")".toString(),
                         "-I$file("src/main/jni/Common/ndk_helper")".toString()])
        ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "atomic"])
        stl     = "c++_static"
    
    // jni is the default dir; config this if yours is in different directory
    android.sources 
        main 
            jni 
                source 
                    srcDirs 'src/main/jni'
                
            
        
    
    android.buildTypes 
        release 
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
        
    
    // Turn on hard float support in armeabi-v7a
    android.abis 
        create("armeabi-v7a") 
            cppFlags.addAll(["-mhard-float", "-D_NDK_MATH_NO_SOFTFP=1", "-mfloat-abi=hard"])
            ldLibs.add("m_hard")
            ldFlags.add("-Wl,--no-warn-mismatch")
        
    
    android.productFlavors 
        create ("arm7") 
            ndk.abiFilters.add("armeabi-v7a")
        
        create ("arm8") 
            ndk.abiFilters.add("arm64-v8a")
        
        create ("x86-32") 
            ndk.abiFilters.add("x86")
        
        // for detailed abiFilter descriptions, refer to "Supported ABIs" @
        // https://developer.android.com/ndk/guides/abis.html#sa
        // build one including all productFlavors
        create("fat")
    


dependencies 
    compile 'com.android.support:support-v4:23.3.0'
    compile files('libs/javacpp.jar')
    compile files('libs/javacv.jar')

local.properties:

ndk.dir=C\:\\Users\\wiz\\Downloads\\android-ndk-r9d
sdk.dir=D\:\\sdk

.c 文件:(由于字数限制,不完整)

#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/video/video.h>
#include <pthread.h>

GST_DEBUG_CATEGORY_STATIC (debug_category);
#define GST_CAT_DEFAULT debug_category

/*
 * These macros provide a way to store the native pointer to CustomData, which might be 32 or 64 bits, into
 * a jlong, which is always 64 bits, without warnings.
 */
#if GLIB_SIZEOF_VOID_P == 8
# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(*env)->GetLongField (env, thiz, fieldID)
# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)data)
#else
# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(jint)(*env)->GetLongField (env, thiz, fieldID)
# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)(jint)data)
#endif

/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably
 * confuse some demuxers. */
#define SEEK_MIN_DELAY (500 * GST_MSECOND)

/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData 
  jobject app;                  /* Application instance, used to call its methods. A global reference is kept. */
  GstElement *pipeline;         /* The running pipeline */
  GMainContext *context;        /* GLib context used to run the main loop */
  GMainLoop *main_loop;         /* GLib main loop */
  gboolean initialized;         /* To avoid informing the UI multiple times about the initialization */
  ANativeWindow *native_window; /* The Android native window where video will be rendered */
  GstState state;               /* Current pipeline state */
  GstState target_state;        /* Desired pipeline state, to be set once buffering is complete */
  gint64 duration;              /* Cached clip duration */
  gint64 desired_position;      /* Position to seek to, once the pipeline is running */
  GstClockTime last_seek_time;  /* For seeking overflow prevention (throttling) */
  gboolean is_live;             /* Live streams do not use buffering */
 CustomData;

/* playbin2 flags */
typedef enum 
  GST_PLAY_FLAG_TEXT = (1 << 2)  /* We want subtitle output */
 GstPlayFlags;

/* These global variables cache values which are not changing during execution */
static pthread_t gst_app_thread;
static pthread_key_t current_jni_env;
static JavaVM *java_vm;
static jfieldID custom_data_field_id;
static jmethodID set_message_method_id;
static jmethodID set_current_position_method_id;
static jmethodID on_gstreamer_initialized_method_id;
static jmethodID on_media_size_changed_method_id;

/*
 * Private methods
 */

/* Register this thread with the VM */
static JNIEnv *attach_current_thread (void) 
  JNIEnv *env;
  JavaVMAttachArgs args;

  GST_DEBUG ("Attaching thread %p", g_thread_self ());
  args.version = JNI_VERSION_1_4;
  args.name = NULL;
  args.group = NULL;

  if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) 
    GST_ERROR ("Failed to attach current thread");
    return NULL;
  

  return env;


/* Unregister this thread from the VM */
static void detach_current_thread (void *env) 
  GST_DEBUG ("Detaching thread %p", g_thread_self ());
  (*java_vm)->DetachCurrentThread (java_vm);


/* Retrieve the JNI environment for this thread */
static JNIEnv *get_jni_env (void) 
  JNIEnv *env;

  if ((env = pthread_getspecific (current_jni_env)) == NULL) 
    env = attach_current_thread ();
    pthread_setspecific (current_jni_env, env);
  

  return env;

导入前的android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := tutorial-4
LOCAL_SRC_FILES := tutorial-4.c
LOCAL_SHARED_LIBRARIES := gstreamer_android
LOCAL_LDLIBS := -llog -landroid
include $(BUILD_SHARED_LIBRARY)

ifndef GSTREAMER_SDK_ROOT
ifndef GSTREAMER_SDK_ROOT_ANDROID
$(error GSTREAMER_SDK_ROOT_ANDROID is not defined!)
endif
GSTREAMER_SDK_ROOT        := $(GSTREAMER_SDK_ROOT_ANDROID)
endif
GSTREAMER_NDK_BUILD_PATH  := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
GSTREAMER_PLUGINS         := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS) $(GSTREAMER_PLUGINS_NET_RESTRICTED) 
GSTREAMER_EXTRA_DEPS      := gstreamer-interfaces-0.10 gstreamer-video-0.10
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk

【问题讨论】:

您能否添加一些显示的示例错误?如果有人真正尝试您的压缩项目,您将非常幸运。如果我不知道“问题弹出”是什么,您将无法帮助您:) 请按照导入前的原样发布 Android.mk 我在导入之前添加了代码示例和 android.mk 文件。我得到的错误是代码没有找到 gst 文件夹,尽管我已经更改了 GStreamer 文件夹位置并将其定向到环境变量中的正确位置 获得了更多信息,我已经手动将 GStreamer 文件夹移动到 JNI 文件夹中并成功包含了 gst.h 和 video.h 文件,问题是编译器将这些包含标记为未使用代码。 【参考方案1】:

我建议迁移到 AS,但保持 NDK 构建“传统方式”。我为这种方法辩护的主要论点是,实验性插件仍然是一个“移动目标”:DSL 一直在变化,它的局限性需要随着实验性插件的每个版本而改变的变通方法。第二个原因是像 Fabric 这样的 3rd 方工具无法与实验性插件一起使用。

对于非实验性的插件,你可以在 build.gradle 中使用如下部分:

def ndkBuild = android.ndkDirectory
import org.apache.tools.ant.taskdefs.condition.Os
if (Os.isFamily(Os.FAMILY_WINDOWS)) 
    ndkBuild += '.cmd'


task buildNative(type: Exec, description: 'Compile JNI source via NDK') 
    commandLine '$ndkBuild', 'NDK_PROJECT_PATH="$jniSrc/..'


task cleanNative(type: Exec, description: 'Clean JNI object files') 
    commandLine '$ndkBuild', 'clean', 'NDK_PROJECT_PATH="$jniSrc/..'


clean.dependsOn 'cleanNative'

tasks.withType(JavaCompile) 
    compileTask -> compileTask.dependsOn buildNative


tasks.all 
    task -> if (task.name.contains('compileDebugNdk') || task.name.contains('compileReleaseNdk')) task.enabled = false

【讨论】:

好吧,最终我搬到了 Android Studio。我现在使用 Vitamio 库而不是 GStreamer,它运行良好。尽管如此,我并没有设法让 GStreamer 在 android studio 上工作。无论如何感谢您的建议! 请注意,Android Studio 2.2(仍为测试版)通过其官方 gradle 插件支持 ndk-build。

以上是关于将使用 NDK 和 Gstreamer 的 Eclipse android 项目迁移到 Android Studio的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Gstreamer 通过 RTMP 流式传输?

如何通过gstreamer将pcap转换为带有视频和音频的avi文件?

使用 gstreamer 和 ffmpeg 进行 H.264 解码

控制 gstreamer 源插件的输出速率

集成 Gstreamer Camera Output 窗口和 Qml 窗口

使用 gstreamer 将 PCM 数据发送到 VLC 播放器