s/ffmpegcolorspace/videoconvert/ in a few places
[platform/upstream/gstreamer.git] / sdk-android-tutorial-link-against-gstreamer.md
1 # Android tutorial 1: Link against GStreamer
2
3 ## Goal!
4
5 ![screenshot]
6
7 This first Android tutorial is extremely simple: it just retrieves the
8 GStreamer version and displays it on the screen. It exemplifies how to
9 access GStreamer C code from Java and verifies that there have been no
10 linkage problems. 
11
12 ## Hello GStreamer \[Java code\]
13
14 At **FIXME: add path** folder you should find an `android-tutorial-1` directory,
15 with the usual Android NDK structure: a `src` folder for the Java code,
16 a `jni` folder for the C code and a `res` folder for UI resources.
17
18 We recommend that you open this project in Eclipse (as explained
19 in [](sdk-installing-for-android-development.md)) so you can
20 easily see how all the pieces fit together.
21
22 Let’s first introduce the Java code, then the C code and finally the
23 makefile that allows GStreamer integration.
24
25 **src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java**
26
27 ``` java
28 package org.freedesktop.gstreamer.tutorials.tutorial_1;
29
30 import android.app.Activity;
31 import android.os.Bundle;
32 import android.widget.TextView;
33 import android.widget.Toast;
34
35 import org.freedesktop.gstreamer.GStreamer;
36
37 public class Tutorial1 extends Activity {
38     private native String nativeGetGStreamerInfo();
39
40     // Called when the activity is first created.
41     @Override
42     public void onCreate(Bundle savedInstanceState)
43     {
44         super.onCreate(savedInstanceState);
45
46         try {
47             GStreamer.init(this);
48         } catch (Exception e) {
49             Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
50             finish();
51             return;
52         }
53
54         setContentView(R.layout.main);
55
56         TextView tv = (TextView)findViewById(R.id.textview_info);
57         tv.setText("Welcome to " + nativeGetGStreamerInfo() + " !");
58     }
59
60     static {
61         System.loadLibrary("gstreamer_android");
62         System.loadLibrary("tutorial-1");
63     }
64
65 }
66 ```
67
68 Calls from Java to C happen through native methods, like the one
69 declared here:
70
71 ``` java
72 private native String nativeGetGStreamerInfo();
73 ```
74
75 This tells Java that there exists a method with this signature somewhere
76 so it compiles happily. It is your responsibility to ensure that, **at
77 runtime**, this method is accessible. This is accomplished by the C code
78 shown later.
79
80 The first bit of code that gets actually executed is the static
81 initializer of the class:
82
83 ``` java
84 static {
85     System.loadLibrary("gstreamer_android");
86     System.loadLibrary("tutorial-1");
87 }
88 ```
89
90 It loads `libgstreamer_android.so`, which contains all GStreamer
91 methods, and `libtutorial-1.so`, which contains the C part of this
92 tutorial, explained below.
93
94 Upon loading, each of these libraries’ `JNI_OnLoad()` method is
95 executed. It basically registers the native methods that these libraries
96 expose. The GStreamer library only exposes a `init()` method, which
97 initializes GStreamer and registers all plugins (The tutorial library is
98 explained later below).
99
100 ``` java
101 try {
102     GStreamer.init(this);
103 } catch (Exception e) {
104     Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
105     finish();
106     return;
107 }
108 ```
109
110 Next, in the `OnCreate()` method of the
111 [Activity](http://developer.android.com/reference/android/app/Activity.html)
112 we actually initialize GStreamer by calling `GStreamer.init()`. This
113 method requires a
114 [Context](http://developer.android.com/reference/android/content/Context.html)
115 so it cannot be called from the static initializer, but there is no
116 danger in calling it multiple times, as all but the first time the calls
117 will be ignored.
118
119 Should initialization fail, the `init()` method would throw an
120 [Exception](http://developer.android.com/reference/java/lang/Exception.html)
121 with the details provided by the GStreamer library.
122
123 ``` java
124 TextView tv = (TextView)findViewById(R.id.textview_info);
125 tv.setText("Welcome to " + nativeGetGStreamerInfo() + " !");
126 ```
127
128 Then, the native method `nativeGetGStreamerInfo()` is called and a
129 string is retrieved, which is used to format the content of the
130 [TextView](http://developer.android.com/reference/android/widget/TextView.html)
131 in the UI.
132
133 This finishes the UI part of this tutorial. Let’s take a look at the C
134 code:
135
136 ## Hello GStreamer \[C code\]
137
138 **jni/tutorial-1.c**
139
140 ``` c
141 #include <string.h>
142 #include <jni.h>
143 #include <android/log.h>
144 #include <gst/gst.h>
145
146 /*
147  * Java Bindings
148  */
149 static jstring gst_native_get_gstreamer_info (JNIEnv* env, jobject thiz) {
150   char *version_utf8 = gst_version_string();
151   jstring *version_jstring = (*env)->NewStringUTF(env, version_utf8);
152   g_free (version_utf8);
153   return version_jstring;
154 }
155
156 static JNINativeMethod native_methods[] = {
157   { "nativeGetGStreamerInfo", "()Ljava/lang/String;", (void *) gst_native_get_gstreamer_info}
158 };
159
160 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
161   JNIEnv *env = NULL;
162
163   if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
164     __android_log_print (ANDROID_LOG_ERROR, "tutorial-1", "Could not retrieve JNIEnv");
165     return 0;
166   }
167   jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1");
168   (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods));
169
170   return JNI_VERSION_1_4;
171 }
172 ```
173
174 The `JNI_OnLoad()` method is executed every time the Java Virtual
175 Machine (VM) loads a library.
176
177 Here, we retrieve the JNI environment needed to make calls that interact
178 with Java:
179
180 ``` c
181 JNIEnv *env = NULL;
182
183 if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
184   __android_log_print (ANDROID_LOG_ERROR, "tutorial-1", "Could not retrieve JNIEnv");
185   return 0;
186
187 ```
188
189 And then locate the class containing the UI part of this tutorial using
190 `
191 FindClass()`:
192
193 ``` c
194 jclass klass = (*env)->FindClass (env, "org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1");
195 ```
196
197 Finally, we register our native methods with `RegisterNatives()`, this
198 is, we provide the code for the methods we advertised in Java using the
199 **`native`**
200  keyword:
201
202 ``` c
203 (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods));
204 ```
205
206 The `native_methods` array describes each one of the methods to register
207 (only one in this tutorial).  For each method, it provides its Java
208 name, its [type
209 signature](http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp276)
210 and a pointer to the C function implementing it:
211
212 ``` c
213 static JNINativeMethod native_methods[] = {
214   { "nativeGetGStreamerInfo", "()Ljava/lang/String;", (void *) gst_native_get_gstreamer_info}
215 };
216 ```
217
218 The only native method used in this tutorial
219 is `nativeGetGStreamerInfo()`:
220
221 ``` c
222 jstring gst_native_get_gstreamer_info (JNIEnv* env, jobject thiz) {
223   char *version_utf8 = gst_version_string();
224   jstring *version_jstring = (*env)->NewStringUTF(env, version_utf8);
225   g_free (version_utf8);
226   return version_jstring;
227 }
228 ```
229
230 It simply calls `gst_version_string()` to obtain a string describing
231 this version of GStreamer. This [Modified
232 UTF8](http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8) string is then
233 converted to [UTF16](http://en.wikipedia.org/wiki/UTF-16) by `
234 NewStringUTF()` as required by Java and returned. Java will be
235 responsible for freeing the memory used by the new UTF16 String, but we
236 must free the `char *` returned by `gst_version_string()`.
237
238 ## Hello GStreamer \[Android.mk\]
239
240 **jni/Android.mk**
241
242 ``` ruby
243 LOCAL_PATH := $(call my-dir)
244
245 include $(CLEAR_VARS)
246
247 LOCAL_MODULE    := tutorial-1
248 LOCAL_SRC_FILES := tutorial-1.c
249 LOCAL_SHARED_LIBRARIES := gstreamer_android
250 LOCAL_LDLIBS := -llog
251 include $(BUILD_SHARED_LIBRARY)
252
253 ifndef GSTREAMER_ROOT
254 ifndef GSTREAMER_ROOT_ANDROID
255 $(error GSTREAMER_ROOT_ANDROID is not defined!)
256 endif
257 GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)
258 endif
259 GSTREAMER_NDK_BUILD_PATH  := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/
260 GSTREAMER_PLUGINS         := coreelements
261 include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk
262 ```
263
264 This is a barebones makefile for a project with GStreamer support. It
265 simply states that it depends on the `libgstreamer_android.so` library
266 (line 7), and requires the `coreelements` plugin (line 18). More complex
267 applications will probably add more libraries and plugins
268 to `Android.mk`
269
270 ## Conclusion
271
272 This ends the first Android tutorial. It has shown that, besides the
273 interconnection between Java and C (which abides to the standard JNI
274 procedure), adding GStreamer support to an Android application is not
275 any more complicated than adding it to a desktop application.
276
277 The following tutorials detail the few places in which care has to be
278 taken when developing specifically for the Android platform.
279
280 As usual, it has been a pleasure having you here, and see you soon\!
281
282   [screenshot]: images/sdk-android-tutorial-link-against-gstreamer-screenshot.png