GStreamer——教程——Android教程1:Link against GStreamer

目标

这个第一个Android教程非常简单:它只是检索GStreamer版本并将其显示在屏幕上。它示例了如何从Java访问GStreamer C代码,并验证没有链接问题。

你好GStreamer[Java代码]

教程代码位于gst-docs子目录中。 此目录包含通常的Android NDK结构:一个用于Java代码的src文件夹,一个用于C代码的jni文件夹和一个用于UI资源的res文件夹。

我们建议您在Eclipse中打开这个项目(如前所述 在安装为Android开发),这样您可以轻松查看所有部分是如何组合在一起的。

让我们首先介绍Java代码,然后是C代码,最后是允许集成GStreamer的makefile。

src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java

package org.freedesktop.gstreamer.tutorials.tutorial_1;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import org.freedesktop.gstreamer.GStreamer;

public class Tutorial1 extends Activity {
    private native String nativeGetGStreamerInfo();

    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        try {
            GStreamer.init(this);
        } catch (Exception e) {
            Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        setContentView(R.layout.main);

        TextView tv = (TextView)findViewById(R.id.textview_info);
        tv.setText("Welcome to " + nativeGetGStreamerInfo() + " !");
    }

    static {
        System.loadLibrary("gstreamer_android");
        System.loadLibrary("tutorial-1");
    }

}

从Java到C的调用通过本地方法进行,如下所声明:

private native String nativeGetGStreamerInfo();

这告诉Java存在一个具有此签名的方法,因此它可以愉快地编译。确保在运行时此方法是可访问的是你的责任。稍后显示的C代码完成了这一点。

实际执行的第一段代码是类的静态初始化器:

static {
    System.loadLibrary("gstreamer_android");
    System.loadLibrary("tutorial-1");
}

它加载libgstreamer_android.so,其中包含所有GStreamer方法,以及libtutorial-1.so,其中包含本教程的C部分,如下所述。

在加载时,这些库的JNI_OnLoad()方法会被执行。它基本上注册了这些库公开的本地方法。GStreamer库仅公开了一个init()方法,该方法初始化GStreamer并注册所有插件(稍后将在下面解释教程库)。

try {
    GStreamer.init(this);
} catch (Exception e) {
    Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
    finish();
    return;
}

接下来,在Activity的OnCreate()方法中,我们通过调用GStreamer.init()来实际初始化GStreamer。此方法需要一个Context,因此不能从静态初始化器中调用,但多次调用也没有危险,因为除了第一次之外的所有调用都将被忽略。

如果初始化失败,init()方法将抛出一个异常,其中包含GStreamer库提供的详细信息。 然后,调用本地方法nativeGetGStreamerInfo()并检索一个字符串,该字符串用于格式化UI中TextView的内容。

这就完成了本教程的UI部分。让我们看一下C代码:

TextView tv = (TextView)findViewById(R.id.textview_info);
tv.setText("Welcome to " + nativeGetGStreamerInfo() + " !");

然后,调用本机方法nativeGetGStreamerInfo()并 检索字符串,用于格式化内容 文本视图 在UI中。

本教程的UI部分到此结束。让我们看一下C代码:

你好GStreamer[C代码]

jni/tutorial-1.c

#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <gst/gst.h>

/*
 * Java Bindings
 */
static jstring gst_native_get_gstreamer_info (JNIEnv* env, jobject thiz) {
  char *version_utf8 = gst_version_string();
  jstring *version_jstring = (*env)->NewStringUTF(env, version_utf8);
  g_free (version_utf8);
  return version_jstring;
}

static JNINativeMethod native_methods[] = {
  { "nativeGetGStreamerInfo", "()Ljava/lang/String;", (void *) gst_native_get_gstreamer_info}
};

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  JNIEnv *env = NULL;

  if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    __android_log_print (ANDROID_LOG_ERROR, "tutorial-1", "Could not retrieve JNIEnv");
    return 0;
  }
  jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1");
  (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods));

  return JNI_VERSION_1_4;
}

JNI_OnLoad()方法是在Java虚拟机(VM)每次加载库时执行的。

在这里,我们检索与Java交互所需的JNI环境:

JNIEnv *env = NULL;

if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  __android_log_print (ANDROID_LOG_ERROR, "tutorial-1", "Could not retrieve JNIEnv");
  return 0;
}

然后使用FindClass()定位包含本教程UI部分的类:

jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1");

最后,我们使用RegisterNatives()注册我们的本地方法,也就是说,我们为使用Java中的native关键字声明的方法提供代码:

(*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods));

native_methods数组描述了要注册的每个方法(本教程中只有一个)。对于每个方法,它提供了其Java名称、类型签名和指向实现它的C函数的指针:

static JNINativeMethod native_methods[] = {
  { "nativeGetGStreamerInfo", "()Ljava/lang/String;", (void *) gst_native_get_gstreamer_info}
};

本教程中使用的唯一本地方法是nativeGetGStreamerInfo():

jstring gst_native_get_gstreamer_info (JNIEnv* env, jobject thiz) {
  char *version_utf8 = gst_version_string();
  jstring *version_jstring = (*env)->NewStringUTF(env, version_utf8);
  g_free (version_utf8);
  return version_jstring;
}

它简单地调用gst_version_string()以获取描述此版本GStreamer的字符串。然后,这个修改过的UTF8字符串通过NewStringUTF()转换为Java所需的UTF16,并返回。Java将负责释放新UTF16 String使用的内存,但我们必须释放gst_version_string()返回的char *。

你好GStreamer[Android.mk]

JNI/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

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

ifndef GSTREAMER_ROOT
ifndef GSTREAMER_ROOT_ANDROID
$(error GSTREAMER_ROOT_ANDROID is not defined!)
endif
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)
endif
GSTREAMER_NDK_BUILD_PATH  := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/
GSTREAMER_PLUGINS         := coreelements
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk

这是一个支持GStreamer的项目的简单makefile。它仅仅声明它依赖于libgstreamer_android.so库(第7行),并且需要coreelements插件(第18行)。更复杂的应用程序可能会在Android.mk中添加更多的库和插件。

结论

这结束了第一个Android教程。它展示了,除了Java和C之间的互连(遵循标准的JNI程序)之外,将GStreamer支持添加到Android应用程序并不比将其添加到桌面应用程序复杂。

后续教程将详细介绍在专门为Android平台开发时需要注意的几个方面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值