首页 文章

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

提问于
浏览
1

我在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-build \

  • gst-build \ gstreamer_android.c

  • gst-build \ gstreamer_android.o

用依赖项替换了Jars:

导入程序将以下.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 to Gradle导入程序的错误或限制,请在http://b.android.com提交类别为Component-Tools的错误 .

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

的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

1 回答

  • 0

    我建议移动到AS,但保持NDK构建"the traditional way" . 我捍卫这种方法的主要论点是,实验性插件仍然是一个问题:DSL一直在变化,其局限性需要随着实验插件的每个版本而变化的变通方法 . 第二个原因是像Fabric这样的第三方工具不适用于实验性插件 .

    对于非实验性插件,您可以在 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
    }
    

相关问题