From 669b10b6f69c7654db2d221c352d723b10738ff4 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 9 Jul 2012 14:44:44 +0200 Subject: [PATCH 01/90] Added basic tutorial 15 (Clutter) --- gst-sdk/tutorials/basic-tutorial-15.c | 98 +++++++++++++++++ .../basic-tutorial-15.vcxproj | 100 ++++++++++++++++++ .../basic-tutorial-15.vcxproj.filters | 6 ++ gst-sdk/tutorials/vs2010/tutorials.sln | 10 ++ 4 files changed, 214 insertions(+) create mode 100644 gst-sdk/tutorials/basic-tutorial-15.c create mode 100644 gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj create mode 100644 gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters diff --git a/gst-sdk/tutorials/basic-tutorial-15.c b/gst-sdk/tutorials/basic-tutorial-15.c new file mode 100644 index 0000000000..f14e1889af --- /dev/null +++ b/gst-sdk/tutorials/basic-tutorial-15.c @@ -0,0 +1,98 @@ +#ifdef _WIN32 +#include +#endif +#include + +/* Setup the video texture once its size is known */ +void size_change (ClutterActor *texture, gint width, gint height, gpointer user_data) { + ClutterActor *stage; + gfloat new_x, new_y, new_width, new_height; + gfloat stage_width, stage_height; + ClutterAnimation *animation = NULL; + + stage = clutter_actor_get_stage (texture); + if (stage == NULL) + return; + + clutter_actor_get_size (stage, &stage_width, &stage_height); + + /* Center video on window */ + new_height = (height * stage_width) / width; + if (new_height <= stage_height) { + new_width = stage_width; + + new_x = 0; + new_y = (stage_height - new_height) / 2; + } else { + new_width = (width * stage_height) / height; + new_height = stage_height; + + new_x = (stage_width - new_width) / 2; + new_y = 0; + } + clutter_actor_set_position (texture, new_x, new_y); + clutter_actor_set_size (texture, new_width, new_height); + /* Animate it */ + clutter_actor_set_rotation (texture, CLUTTER_Y_AXIS, 0.0, stage_width / 2, 0, 0); + animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000, "rotation-angle-y", 360.0, NULL); + clutter_animation_set_loop (animation, TRUE); +} + +int main(int argc, char *argv[]) { + GstElement *pipeline, *sink; + ClutterTimeline *timeline; + ClutterActor *stage, *texture; + + if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { + g_error ("Failed to initialize clutter\n"); + return -1; + } + + stage = clutter_stage_get_default (); + + /* Make a timeline */ + timeline = clutter_timeline_new (1000); + g_object_set(timeline, "loop", TRUE, NULL); + + /* We need to set certain props on the target texture currently for + * efficient/correct playback onto the texture */ + texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL)); + + g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL); + + /* Build the pipeline */ + pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL); + + /* Instantiate the Clutter sink */ + sink = gst_element_factory_make ("autocluttersink", NULL); + if (sink == NULL) { + /* Revert to the older cluttersink, in case autocluttersink was not found */ + sink = gst_element_factory_make ("cluttersink", NULL); + } + if (sink == NULL) { + g_printerr ("Unable to find a Cluttre sink.\n"); + return -1; + } + + /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/ + g_object_set (sink, "texture", texture, NULL); + + /* Add the Clutter sink to the pipeline */ + g_object_set (pipeline, "video-sink", sink, NULL); + + /* Start playing */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* start the timeline */ + clutter_timeline_start (timeline); + + clutter_group_add (CLUTTER_GROUP (stage), texture); + clutter_actor_show_all (stage); + + clutter_main(); + + /* Free resources */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return 0; +} diff --git a/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj b/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj new file mode 100644 index 0000000000..cd7e3270a5 --- /dev/null +++ b/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + \ No newline at end of file diff --git a/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters b/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters new file mode 100644 index 0000000000..790763f571 --- /dev/null +++ b/gst-sdk/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/gst-sdk/tutorials/vs2010/tutorials.sln b/gst-sdk/tutorials/vs2010/tutorials.sln index 17529d26b1..b75567188f 100644 --- a/gst-sdk/tutorials/vs2010/tutorials.sln +++ b/gst-sdk/tutorials/vs2010/tutorials.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-7", "play EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-13", "basic-tutorial-13\basic-tutorial-13.vcxproj", "{6D962544-E7A2-450B-998B-6D09B17ACCB3}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-15", "basic-tutorial-15\basic-tutorial-15.vcxproj", "{94A762CB-2856-4CFF-BF1A-DB44882D4BD5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -189,6 +191,14 @@ Global {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|Win32.Build.0 = Release|Win32 {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.ActiveCfg = Release|x64 {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.Build.0 = Release|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.ActiveCfg = Debug|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.Build.0 = Debug|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.ActiveCfg = Debug|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.Build.0 = Debug|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.ActiveCfg = Release|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.Build.0 = Release|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.ActiveCfg = Release|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 37de9e77c6dbf03fbd3dde6081d21614d9e688ea Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 10 Jul 2012 16:21:33 +0200 Subject: [PATCH 02/90] Comments and cosmetics --- gst-sdk/tutorials/basic-tutorial-15.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/gst-sdk/tutorials/basic-tutorial-15.c b/gst-sdk/tutorials/basic-tutorial-15.c index f14e1889af..1daf10b6c8 100644 --- a/gst-sdk/tutorials/basic-tutorial-15.c +++ b/gst-sdk/tutorials/basic-tutorial-15.c @@ -1,6 +1,3 @@ -#ifdef _WIN32 -#include -#endif #include /* Setup the video texture once its size is known */ @@ -16,7 +13,7 @@ void size_change (ClutterActor *texture, gint width, gint height, gpointer user_ clutter_actor_get_size (stage, &stage_width, &stage_height); - /* Center video on window */ + /* Center video on window and calculate new size preserving aspect ratio */ new_height = (height * stage_width) / width; if (new_height <= stage_height) { new_width = stage_width; @@ -32,8 +29,8 @@ void size_change (ClutterActor *texture, gint width, gint height, gpointer user_ } clutter_actor_set_position (texture, new_x, new_y); clutter_actor_set_size (texture, new_width, new_height); - /* Animate it */ clutter_actor_set_rotation (texture, CLUTTER_Y_AXIS, 0.0, stage_width / 2, 0, 0); + /* Animate it */ animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000, "rotation-angle-y", 360.0, NULL); clutter_animation_set_loop (animation, TRUE); } @@ -43,6 +40,7 @@ int main(int argc, char *argv[]) { ClutterTimeline *timeline; ClutterActor *stage, *texture; + /* clutter-gst takes care of initializing Clutter and GStreamer */ if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { g_error ("Failed to initialize clutter\n"); return -1; @@ -54,13 +52,11 @@ int main(int argc, char *argv[]) { timeline = clutter_timeline_new (1000); g_object_set(timeline, "loop", TRUE, NULL); - /* We need to set certain props on the target texture currently for - * efficient/correct playback onto the texture */ + /* Create new texture and disable slicing so the video is properly mapped onto it */ texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL)); - g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL); - /* Build the pipeline */ + /* Build the GStreamer pipeline */ pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL); /* Instantiate the Clutter sink */ @@ -70,7 +66,7 @@ int main(int argc, char *argv[]) { sink = gst_element_factory_make ("cluttersink", NULL); } if (sink == NULL) { - g_printerr ("Unable to find a Cluttre sink.\n"); + g_printerr ("Unable to find a Clutter sink.\n"); return -1; } @@ -86,6 +82,7 @@ int main(int argc, char *argv[]) { /* start the timeline */ clutter_timeline_start (timeline); + /* Add texture to the stage, and show it */ clutter_group_add (CLUTTER_GROUP (stage), texture); clutter_actor_show_all (stage); From d72831ea721042b4b73aa94ad93adb6ce2f7bcef Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 13 Jul 2012 12:01:27 +0200 Subject: [PATCH 03/90] Fix forward seeks stop position (it should be the EOF, not the previous stop position). --- gst-sdk/tutorials/basic-tutorial-13.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/basic-tutorial-13.c b/gst-sdk/tutorials/basic-tutorial-13.c index 2361a6fb8c..4f8dda3391 100644 --- a/gst-sdk/tutorials/basic-tutorial-13.c +++ b/gst-sdk/tutorials/basic-tutorial-13.c @@ -25,7 +25,7 @@ static void send_seek_event (CustomData *data) { /* Create the seek event */ if (data->rate > 0) { seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, - GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, 0); + GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, -1); } else { seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, position); From ef7757b7cae82c8c68d8d1c054d63ae3042812de Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 12:20:02 +0200 Subject: [PATCH 04/90] Initial tutorial-1 --- .../android-tutorial-1/AndroidManifest.xml | 17 +++++++ .../android-tutorial-1/default.properties | 14 ++++++ .../android-tutorial-1/jni/Android.mk | 29 ++++++++++++ .../android-tutorial-1/jni/tutorial-1.c | 27 +++++++++++ .../android-tutorial-1/res/values/strings.xml | 4 ++ .../tutorial_1/Tutorial1.java | 45 +++++++++++++++++++ 6 files changed, 136 insertions(+) create mode 100755 gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml create mode 100644 gst-sdk/tutorials/android-tutorial-1/default.properties create mode 100755 gst-sdk/tutorials/android-tutorial-1/jni/Android.mk create mode 100755 gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c create mode 100755 gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml create mode 100755 gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml new file mode 100755 index 0000000000..1701aa602c --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/gst-sdk/tutorials/android-tutorial-1/default.properties b/gst-sdk/tutorials/android-tutorial-1/default.properties new file mode 100644 index 0000000000..85aac54016 --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/default.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8 diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk new file mode 100755 index 0000000000..b2a6cd3289 --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -0,0 +1,29 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := tutorial-1 +LOCAL_SRC_FILES := tutorial-1.c +LOCAL_LDLIBS := -L./ -lgstreamer_android +LOCAL_CFLAGS := $(shell pkg-config gstreamer-0.10 --cflags) +include $(BUILD_SHARED_LIBRARY) + +GSTREAMER_PLUGINS = coreelements +GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static +GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ +include $(GSTREAMER_MK_PATH)/gstreamer.mk + diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c new file mode 100755 index 0000000000..076ced6c95 --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include + +jstring +Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, + jobject thiz ) +{ + return (*env)->NewStringUTF(env, gst_version_string()); +} + diff --git a/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml b/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml new file mode 100755 index 0000000000..b956d6d241 --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Android tutorial 1 + diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java new file mode 100755 index 0000000000..97e3a21144 --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gst_sdk_tutorials.tutorial_1; + +import android.app.Activity; +import android.widget.TextView; +import android.os.Bundle; + +public class Tutorial1 extends Activity +{ + public native String gstVersion(); + + /* Called when the activity is first created. + @Override */ + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + /* Create a TextView and set its content. + * the text is retrieved by calling a native + * function. + */ + TextView tv = new TextView(this); + tv.setText( gstVersion() ); + setContentView(tv); + } + + static { + System.loadLibrary("gstreamer_android"); + System.loadLibrary("tutorial-1"); + } +} From 625bed684481a62e0dd93f07c65658224e258233 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 12:53:20 +0200 Subject: [PATCH 05/90] Added icon --- .gitignore | 6 +++++- .../android-tutorial-1/AndroidManifest.xml | 3 ++- .../res/drawable-ldpi/gst_sdk_icon.png | Bin 0 -> 2743 bytes .../res/drawable-xhdpi/gst_sdk_icon.png | Bin 0 -> 9283 bytes 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100755 gst-sdk/tutorials/android-tutorial-1/res/drawable-ldpi/gst_sdk_icon.png create mode 100755 gst-sdk/tutorials/android-tutorial-1/res/drawable-xhdpi/gst_sdk_icon.png diff --git a/.gitignore b/.gitignore index d4a0768bad..411d4aefab 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,8 @@ ipch *.sdf *.suo *.opensdf -vs/2010/libs \ No newline at end of file +vs/2010/libs +bin +gen +libs +obj diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml index 1701aa602c..dfc3c54085 100755 --- a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -5,7 +5,8 @@ android:versionName="1.0"> + android:debuggable="true" + android:icon="@drawable/gst_sdk_icon"> diff --git a/gst-sdk/tutorials/android-tutorial-1/res/drawable-ldpi/gst_sdk_icon.png b/gst-sdk/tutorials/android-tutorial-1/res/drawable-ldpi/gst_sdk_icon.png new file mode 100755 index 0000000000000000000000000000000000000000..98f66e7a42ac29033ba3aa4376c9fe0cd4a6ddfd GIT binary patch literal 2743 zcmV;o3P|;dP)`-{rqe-*jLH~+k&q%f<^!l`kikSCfdsSUgFrT$ z-Ry2QyZe6J``&w>bNa`-n?c7R>2v4Yd;fW!bAIRJcg{l}|M*tgvExZH#)xwcms$kC z5E%u?sb&O_0@@Y&t?QbK*RF3aUiZObVP#k7_cVIkL{?EHH~DrFpLqWK)X%paAN|4U zYBmfNvvuoMXN!5`14s;$5rI?v*qeZ?eNHBOvLu9ceH=$xBrW$Uq9ns zW&$%4)4LR_DxAVORRJKOVY8vFxcauvwoh(qnf0+QFKBb3T1kaUnNtOXn24Z61Ofno zYV1_2iAW)DnjiYe{6|aG2_8?}k4Rqr++$;}?A-Ft+bf@V{5RuICz;A0q7Mw2549AQ z+|<>4^Nn+wZ(EYjEuoB2P8@2fI#MVr8LCI9{w4(&Aftd+7xES2i^~SWIR$U<}o>SDESoMj``W4a)#U_;PP^j&u|(lSRV~QQ@;&y5XgE$L zo*lZd_nFc0pS^OSyni@JhAWV)CG?8(n{rqDMQ`zjPcCcuyY>dtIUwrjpYFM%^`5?c zzwK>mSul0prMAWvG10q2pfv(g0urdCB$BFS#Trv}b{@9C(#_gIH#{N>Fbp1ZvL#a&A4Qf2Z3`78G45SQAfT@a0es{L=^0TMLpWHoB-re8fC$whn=8m-;pK9%C zT*W?-%M_XdD_L@8EFL&X=_)f_s0Jmc&zgX-ANA~{QehDFBtpg zsh_^FecyjR_l@DhLq{QhK!&Y(f7XZQuI*XhbH}{ZogWKZ!j@W`XjG1nrOpW)ITa%! zAP|Tc1_p*KrVW54A07qpI6y$5bIPXssNHA*P&^soia%d==e&&zZy)O)>YqF_{#IqI zT(XT`K4{DJ6uOIxxzXm6EJHLEp*kKprw%|JCWJ1V31_I96zE>H=z0qvWy6Rkqb$?R zYwBxXT3pn+)QKR?QY5tmNmN68A#%<+Rj46L29AJBb#H|#bVe}EKQlcFL1Vtl5|M)f zY}mj7Sv8e3%QSPTI&sLvk%}@IHUz0FeJ>_d6^M$GGCX4ASu$i{*#kL-IuV69z!()F zTNy1)X^YM{hKPyS5C{x{fb?RIdoQG-P6dGB&|@zbFl7ukkxnE-r9q>%V%ZA{O~uY! zdvm*ILK9Ec01)iptEUfSJ-OHhCPck)T$&GQ8my>OQD)z=*Wj_M#acOb?!d(Up&w7Y zIxGu~G^s6w0E4 zx;GV4|Eh?nIC0`s!OW)M5n18t;OMcDy(hjs@T0T;I<$u#FQ4g6Fl)`4+y}1TnqRX1 z#$dr!SKH>f9a%XVojURMk&}B~dm>3vxpwo04oeK|`TWk$b}a0gKW9bPy6R+EvWkO> ziaJqs0u?0yYywNB!J{los4_e{Jht!b&&Lj?zp9MRkEvnZ3V-R94;D6dF5@7_V5+B^ zVUTY@)&d&WqBnoNbK>a-zHoH=3-=#fxOy4g`^b*X|Mj=G{l*Wd{3my>`-i@pm)%w9 zY*&Do|QNIbGny+0T)MbQ4EMU zVpbRi83sH9@+@)SlWlHeN~g{ozi-QRx2|4xjQ)Kf-oE|EJK9fu{oY&RiSa5iFsr+< zv$4DB{a&L#%cV&z8Y`WPF1S(g<~0QKuUTJMvf<8f{-U)U_|{b`$f8IzQxO4+C_@2a z#*6_}Hvr^Y1#244?es?uzxd1R-g@f8^wlFn-+8V?ck{^5JA-?kd}Q>c=bxz#44iaH zRsuK(+B@er^!@4D#w)MhlJ8xzjtj-mMOCDgib~>~2v{6goj{yIoZvkS0QnwlXtfNY zkBseGPhUGa^4(nn6MtXu{7k*Pby1A8Qb{FqsW^mWLl$LZ)fj2H3|C7tbs!NK$pn(s z6<@vq7B=);#du~*!}))-06@k-vsBZ{SSA@*1)d5#%>-FADJ~UJrvwEP8>=F?1otXb z>Lo-92%thBAwUh!)G~Q~&VnebS3fZsYe)nTxp+FUVPfLCQh7HI{E-n!9Kl&2YDKN_&>f}@Pnx1rcZpC z8;W5TC90YbvZQ{FH2?<&9zo++lXHW|%g0{cJ$2~WC!!Ot?AI*G>L6#7h+GWK#jKoh z1QA=$xZl07_rgyf`jtg}>^CRAeg8KGcRlgMoK3fWs&UE6jdoUhFXxI4Qj1+Oe*S!X zZs2(3`0Fo~`w#r0dg|~iQmfW39?8ZkR3IWyCzlAHLd5}K7nS1w1979CsEV+arND6{9hzJskfOIV)Qqr-K zOS5!0$ldSn-oNjC?jP^WocGL}nRCuO@B4W_??h^8sF0H~lL7$9pFVl~8~_Nu2>~QT z_{!L=&<0;Ic__W`&~di$@V0QX2J)|*Ev-48I$GFTKex7cg>db%mImO~($mNCx;_&d znSTDXqvIX6Cp$vIJGND#5P7F=<<=s)${wX+%ft~Q`_f+2^QtQG$Aq+{Pm`odZ;$zY z8*`wgv%mZPorIv&?(@<@0ceOZ@yKz13gJwP%r>GgV?48od;E{-%5i9yv6q+E%7!#{ zU%EfTUD-OCuUc16kE3wnu*KcxZ0YlFp6m~eB^`TDHA{+PQ@b}lKD=s}+|7Du7HhaJ z@W8icW%rFxHf=gF$SD%rLAT4=O})b9)w-Th|3(QbJ#C40FSR9xXCdbQid-X2V`o5e zJajnYq5$ytm*HD2e^ITM6-P&1d~v}k1Yk_s+OQG(!#wA}RY&v(rsW+3P~CS4J?=6J zsLxn8B(HUY#Q#N2%!PH6$zp$DxF+ly<^dqEX7&%wu)k#S(Sx8TvZf@s%yZlr9eCNv z04S^=Z`Q{TGIO}T|INTp694VB?se?E!o~0jUYhHrgYP`5x4rDwtt7=NoCJIm&lg=^y^fe3J%uNW$QGIa6ZP+7m z#}c9cg>s)BY1w#b&`LdSfmY4gUPbT5)4Fj{j{Rm5mT{^RGb z!`_;kt}NioY$`btKFauSRP54!EkRk+T~4)Kj5NzBb3!|wCgBe8tU)u6g!b>SB-%#1 zAmZ*?Xw1Kf)UKD_f3$ll1w;@nJ)IC;6AJSe6ZX=yjN?^hSTE@19mp^wXXmi`hQ#)E zNY_U*o|XQAlYZ{BMNwONxpZw9n1Le2q1u<79nGS|q{ung#kH|aLpj9RJF{)dR)U^a zCz#$HDc>nO-W$B{?=$@)oa%(US|%`ktda9Y8T(LC?sS;x=F|xvD$eaEvBia!++KFG zcejFsJBX@sQs3|!o!wtfXe}Gi$YE5*J{D|t+5A?0Y+Ji8u!^euHx&>DOs_*Wjl1?doboi%+4V^*PJXO=^wYBc8C7a?&Kms1v-e$tzjIzu5%%?W!I32b9JysUZ?hsM z4W3ZYzd6A4KZ*U)HuPwAF|!SZB#!TZJrTsj7*}HdtU$=vfA%Y&*6N4*)pKu{D&At? zxXlO2OkWr(m0~wqmRF*USs2h4phVZnXlxQH&rmpX6c1v35|)L1RgBBH?fW33 z7dv1ULe>p?w|}{&Tr$Hh6iyt!N-iz-QE;a^!Fx+g+WDZRu~TDtT=BKMR-_Ijio2}I z1r-q9aFI$otgI;~IZDOWYBB?D?MkQF3JCqwRu#d2i;RRpiXc8Qt+^N4%5Kjq7^~~SI581i&Qlt`db8@ccQ#63)r)5+=M;$mv%a~ zsz!fl@rq-u!@}Gt@T4H&U7TiVCcREc^4kDf!DwG|&GDwtlg-2W`)+P42!S&0ilgs{ zLe(W90}8Z}foM(T_EN;7xDMJxO%d76>g6KIwK<{pqOukjg6zktx|u;jqF%kCUKR&N zZ^+8N{=!9DN3LXw$hZOg{xqdPR%7B`Si~F}cC*4cb3;%MozgSc8quj*KPFi>G|;~- z;L%IM#$Tg9{4VVjp*;N69`)wtUMvGuaTpbvT!QF$l=HO~ zM2AdmNlga$I0uaWbU$POz7S9t5-s~PX69fhGH&fuG;4>HJ_E}sKU=R7UnMs1 z&g|V0;6}+6swrcC7u1XVE;#gG+e_QEMbFmB+>9z3dCHOW3&!EOZ+8==Qusx@Y0lBA z|5|X%cI5kk*}na68NReBAKsnS{x3Z_60TN!tjh4h9IMr8=&+mm7LkhXB zb=AuL;(;m6LkY6}_Vgr-@+sol(;2`mrwQk7V?aPRKR?;kXe0afG_3oVBguuQnX&d; z9x5*>V)OT+aU%*(Ra_NeF1wqxY%JL=epWsoFFLWkS0t-5UtU_3O zERP%Amm(>apc*(?eTRg!nb&uU!H%AIW{h$>Cjgp^42wv184nYb0b=Y4(7M%Ewdz56uXH zOP+yWhr?Y{tgq9KtO_|c$!UX)0J)!O(cE;7-LH>=PK!O`k#K#6#cv`4f`17Vc)S$_ z;0!M%?i~Jhm^4gc#(j_|s|s(ljLPOy>vtFHUI*W6Sp0MM&Gy;cFRK?)iFryF*j>8y z011h-ME+9+I1KQ!0h^z=nk^3*REtNCzsbm+TC_Xn7poZ>kqH5kkoekk^h)Mc#<6Xi z63`-!$ygh(X1l1rpE!EE3W&~gRBZ{PPP&4_H*$(hbrJDU{jTfN`isBJyZ$fg9e zWWWzAd^LHrHdTf4eT{;_;j^jV(g-1VlmV6qk(qziZ|=wXDVk57?Y@*7wPtl@3aD>| z0Te*H-Ys`;n;JEtBS#XDWTn-|Uu~@eR;}69kp?CaQ90u@lInO6efpuqf)r>; zgNI{$a#X(7TdI|xAsie#i@MoiNOr)>4>pn!>AxG7ng`8xH4=Xpnn>pLng8jiFopwo z7cfV_ikN*7eNj)8U>uN;77cPzDlK<)fW8NI(oFL|1rFoxZLtKjHT0$xt}1cGiI*?x z<^9j<7cMh}dJSi^cmMm18E!ECw}hpU+`j#7(@z+%QnO-GCI`C00LQLJ6wI(9&FswrN-sK!%}ztxQD!~`S6uLcUvkMr_eUVe zUk}bi$Yr-#Zl0FBzPD%N+$6u!;u!w{aq;S)gopy@UI#ewwJcU2i@sZ~5|Dwun(Or? z()O-{6MWf5V!a(PIeJqnUSY&+5a7LDnq_$)+%s6lP>{^iJAQOs{rCPoE)n~5?jDO- z02hZKj~1x3U`>@$^Pz0f^2v-H35Hln?RBY?ImpO6VsoJg zKiisP`(hY5Bty={XLLOOEu56{97|NGWY0XrDaPZh>u)eu`R)j0-{QGh-!0(=&8$d=t;8$yYHdlPh|NCJP zA7R1&Xj?i83}=3F05thaKO2MgShJui*GfU7m4rF5)%gOJ2Vm9{40I|U$^=KuD?WwV z=(y}k-2Esn=byvRkt0L@{{2gPJ(T@fpkr0vg0i#qE+=o9$EdH9`O6?Fio3J31i`q^ zG76Ff=17UApZ1HM@wP-zDaqV7IktHJyWs7<-0N|rDw(S}dVU{T zmir#3&hJq>3~jI{VdINwGv5A)TRJarLRRcQ+t`V7vjb_r%zTIuZB_|}w`-XSnSXl5 zu26a$J8ds$uYg!FSO{`*d~?A&(pHc-^>kfZRJrplhd~>-3c;xcl}jT%oXr24^W+Tvh*LhCHAV$zhM^8mUU(L2j zGCVLcy&x5B#5c$y+td~~p?*ukUk)Ww_+eOc2_SVw6z};Q-G8vhS-GQHLV;e+R#LM*Ed{i4;P_m7Nh5czpQ0$VY9C?;YolzpjRD zOp!)0{n_dD+&sJ?W-|+#`?|Oj=7L#X!v^~yTxoaPX{|%;v6kbv+zd%%uFthqan}ZS z>(*u^Cc%4&x4gdxI((8ACz6V261|NYrX&zP1O$>o<=x6)%EQJ8$DkntxpuMShgim8e{noUUBh|@m z*4JBQ9+bcll4JC3l-w|{W2WWE>`n_x!tBt)I52`%>we3z3JU@G(m}P}vd?{#YFzh6 z-`NK72HNxTae<}XiR2UxEM|K>_HskT_vPf$*st}dh1F&?SJ{73t|O3^tW%F!V{HEn z&u(9ER`CLBMYi+Nw$x5QMRv_a_R`eN9zIQ_zRK*p#^>FFyPT4y-o|2G0XjXxo6~&T zU2aVLZ;~CmTA~gaR|NccQrf2$*Q;Au*!!@r^{;dA=`D*Q>C63!J9sM9-L?&~;X_S2uf*>#f3q}jx`^DXG%r>YRFB%U11P`<<~RzZVExH3JaPs^fwzP=)mCu-kdecl!@#4=!f48j;(j;KFZMsh_MN3Bnu z=yt?3r)pX-UJV?~XQ*%uvG8`uyb8uE@TTfGTx%n@Fo;QxqdMgj4dNI^1hr(+*0 zP-Gu8Ht!hNzU5lL?K?Yo>1LvR{n3|}mYaQuMMV~h@US+gW;I9JKQzyT#QEolN%{jH z(oXCaifU<^quG!<&}PHY)^9Tulz3>w$WC!!Oc2TUq^Q`T0d@ zOHn#BruiyY`+X$X>c|}P8F%eLi=8-hXfEL(9ilB*-Vc0H;?bu{?V=f&g^V;3n_KTP zt^b={Q&)7e3pzo2sWbb+ZnfFQ&U|IUieTtoDzPDr4fMpVf=Dr^M>AHA4D>SIJCiv6 z!7A)MO1Pn4-wuQ&?UG-wGG(J-%B=61;{%j=q0&}Po4a+@$ zVINTYE?b!>NUdw=MIi?zdMtoPe<#sgW(U0a4U0GQr{8LLVHG*{UX(GMG^uO0rK#Hp7@F70I##MP}^H=zXn zA|!x}5pbJ{bmFj1FU*8L^_!dqqyE-xzSxV@{N_aobZ-D$P&B)g%gNZ&{~`g6-P>1u z&`Fz7y8O1E(<&35s?AQqri2 zDI)sbGeD8X0g#P8*~4~#URaRgGbO*A+iAN$@*?r$t(^m_&W*v8^O=mppYd&Fk;QUf z9x#v|Z+fEF{!-?M29Ww#2C zJ7#oE)~FY}>p9;GSRB%EWUt#mU=)h?#{zH9``Td3`rmi}_$CbQ;2_1C@fQ#GaX~(Q zk({$5nZ#^6FE2aBJ#2#Ii?#49fySJA_Go2nyJ^d!W+q&BV6Ot&+sY1=M6E?pYbc zCMN7Jo!B$TS<&ui@W>pAOv~R;cUzqjBclWWlvpSBuTfswDERX}MLUr8iNrqdWtq6a zXfPHbDJ^B~Y0TYQ!8~2+x4kc=e`)Adu98rtL=+(16BxPR{Au@#cC345W@9lxW1H1!m)>N}Bf{HfOZ4iRf8}Tsh0y5B>^IHh%xtBq$(rhj#$$)J7^T zJ*qm0KDu?2clD?EVcFH_32nyNNl@MeL!QXw7$2h}lbg!FYwK|*=aY6PRB~T36?1~m zX>)N??l-8(w1%@zenc9YIEM0)7rrwEOVDUbC_Fw~Ap~9BHq8p%A#r26Ow2yBCdw8) zWmYBNk7U>xx^X$syU=S1MN?dxxO_=DOvom>ocVqVU`{nRzxYSuJUi_DYmc;;8o@_5 zRY$y?xL4nq_wShE26z;6m&b>KfI)gc6=$Y-yutLwxA1~AnHpTfgc@y#H`)j1Y!^)s zwjS8ZVHP**iN;wOlqvN-{J18>?)d1S*frrflp~ehoRwgk_5Kp0=iG5w7Gv2F^`Xph zou&e6(0AlxqglkHmzI(;#PU;31wb<~58Oj}8Z>$e|6G_;zhBWyjL9;f6D|z;cin_h znnttaqltsXs@7d3d0i0?A>{%qH#|O z4pFZ`IrLUwbh3{Yxi4f+6$TgNh<}_N*28uFZQ>4z7F)1F__W<7mV9tbrm0kt#v&qX zY^zBgHS8r*Cr2<^Ps8yO6GaSfW)0aQ;mml`QFdJ(R*_3au2=_;x5cwscrv^wl0}Ui zkLkC&iSdws53eIYXz&9dkLNk$vqpIT>rb!pqa?tRmzrcx5X|GN zkpF-^27EtsyUB*1;V&#l#rl5`e|Uuq^Pk7%aJCz78(k&kmR?lTU46CE@B4m|VSSbB zdXz~y`5mLuWo^>6`vj#*gmyA!(2D6w3U7M(C)F~rflGMN9}^iN_)Jb&f7{TkVK@-C z=^=S+APT6U@G7m!Vb3X*9xN)uM89mz_`X>3vLWwTeg7pjL5ylL&ry;pzg5?YRdEsj zvb)?vujjR*YKsJmG&MSGU8P@SKS=f1>&v#D);dXb%=#O9|E~YrKO@<1yYf#k^t`bo z8@ufr>n^a9G2CC-(%;*Xb!0NsV&B})KH%Nma_`bzwB=c{<7u_6ae1WNH}OV(vOt=k z-V>+8j3QMVjOX@H-LCkq`|CL@mgi6WzuU`2pC2V}ifRoXY3tgxF>R}tc(XNXZ@WzR zqdG!WPG}!1LG`|KRfNa+*Vv#8dwJYSse~ewNh$y(dI5YM_rv^8 z98=kno(;aMsrpQX>{-MrL1?vW(0N5-fBMM?idH1yQ$GyXDo*^-@Tq-AuV*}g z2dL{LE*5FOWtvj>7d+c{NGhP_lO^>hQ^#>iw}UwfS(ULpF>LpAt`T`_T#pN~VgJ~r zuzG`b8pd%51zJz1{ggJBb{m7|J4X_vzCLI2j1D>~{(jJRsYHmbzPrXXbzS%)sdFdL zt9q<{wYgSzgSH*W?@aQ&N(|oZ-!$WG3*r3MvI`z*FUI$9)yV!T7@XQkx40k-F>ifU zZ?9EGR=(t93S5LZN^hJ-IbAO!YeTugKh6MH{xbrd$r- z;LOO7ZpC`1{zu-YTn~n;lRU`C9^GffmQ<>&op}rE9E)?L3gOHaJ0>@$fMd~Rw^s$q z$rwbaFq`a-_=}?8Wo48tyd{>OdKJTOz0pka5z{Uqb?LHO41u<=VMXThZ&`f|qz*M~ zfUOK~;Iy-UGRnghz0LEJ8(WAB#omIfUVF_upXRaqtvZg?-WlC=w#I^Qu5PMon{QYh^v6e7+61=J6|C7dC4F-xRz<+T?)n!5i3SQP=6oDpk z=Zt{o6@w>mj%ONpzWfQeO*H!OVpiZs>oGHdsW^ih@TeojCj}fM_?rKAQZC`SZEA2s zd0|Q9j+@V_z^_BLlywkK#X*Uz=OKb1qX4q?>fNiE+;gFbLB)1Ll5nTm{Ht@J?iPCMW=FE$mw;`X3G5#~EX`asBkInpLJffVYC2l1pw?+|Al!(O(Bz zo&Y^Y=gj`48VV)2n8yHQAjJH+K))Go66?k1G%i0%4hn3V4y(w>X>Wojtg?MrbKX5W z39~9wD2A;_9o&Y0U$SSvy3h|il;Eo{3+@2sOw!rg4d*IEg6f?*z-4W(mpHAK^S)bK zPMv-pc*1xwBWFw&8Uc_FXS-i717+=BsYzd;4e~*bTGOE#KKbAmC`Yro$qCHA*9+{? z-68uHS)Ls Date: Tue, 4 Sep 2012 12:54:38 +0200 Subject: [PATCH 06/90] More .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 411d4aefab..cae038aa75 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ bin gen libs obj +.classpath +.project +.settings From 24136b80112281910c7907425b048ddf8e953be2 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 13:55:04 +0200 Subject: [PATCH 07/90] List available plugins and features --- .../android-tutorial-1/jni/tutorial-1.c | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 076ced6c95..44806f9850 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -22,6 +22,32 @@ jstring Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, jobject thiz ) { - return (*env)->NewStringUTF(env, gst_version_string()); + char buffer[8192] = ""; + GList *original_plugin_list = gst_registry_get_plugin_list (gst_registry_get_default()); + GList *plugin_list = original_plugin_list; + + g_strlcat (buffer, gst_version_string(), sizeof (buffer)); + g_strlcat (buffer, "\n", sizeof (buffer)); + while (plugin_list) { + GstPlugin *plugin = (GstPlugin *)plugin_list->data; + GList *original_features_list, *features_list; + plugin_list = plugin_list->next; + + g_strlcat (buffer, gst_plugin_get_name (plugin), sizeof (buffer)); + g_strlcat (buffer, "\n", sizeof (buffer)); + original_features_list = features_list = gst_registry_get_feature_list_by_plugin (gst_registry_get_default(), plugin->desc.name); + + while (features_list) { + GstPluginFeature *feature = (GstPluginFeature *)features_list->data; + features_list = features_list->next; + + g_strlcat (buffer, " ", sizeof (buffer)); + g_strlcat (buffer, gst_plugin_feature_get_name (feature), sizeof (buffer)); + g_strlcat (buffer, "\n", sizeof (buffer)); + } + gst_plugin_feature_list_free (original_features_list); + } + gst_plugin_list_free (original_plugin_list); + return (*env)->NewStringUTF(env, buffer); } From 2905b5073a1664a765b673da8d06facb572916a8 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 16:06:51 +0200 Subject: [PATCH 08/90] Add more plugins, to test --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index b2a6cd3289..a485b8a484 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_LDLIBS := -L./ -lgstreamer_android LOCAL_CFLAGS := $(shell pkg-config gstreamer-0.10 --cflags) include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements +GSTREAMER_PLUGINS = vorbis coreelements audiotestsrc videotestsrc ogg theora GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk From 77c4117da5fc95f9e7a0a705f334e679c076aa29 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 16:07:11 +0200 Subject: [PATCH 09/90] Allow the textview to scroll --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 97e3a21144..8dedd22d0d 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -18,6 +18,7 @@ package com.gst_sdk_tutorials.tutorial_1; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; +import android.text.method.ScrollingMovementMethod; public class Tutorial1 extends Activity { @@ -34,6 +35,7 @@ public class Tutorial1 extends Activity * function. */ TextView tv = new TextView(this); + tv.setMovementMethod(new ScrollingMovementMethod()); tv.setText( gstVersion() ); setContentView(tv); } From 1947de8006943b4e7181bb98c30d5109ad1167b2 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 16:54:11 +0200 Subject: [PATCH 10/90] More test plugins and nicer scrolling effect --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index a485b8a484..3646087403 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_LDLIBS := -L./ -lgstreamer_android LOCAL_CFLAGS := $(shell pkg-config gstreamer-0.10 --cflags) include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = vorbis coreelements audiotestsrc videotestsrc ogg theora +GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 8dedd22d0d..5afe4cc035 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -36,6 +36,8 @@ public class Tutorial1 extends Activity */ TextView tv = new TextView(this); tv.setMovementMethod(new ScrollingMovementMethod()); + tv.setClickable (false); + tv.setLongClickable (false); tv.setText( gstVersion() ); setContentView(tv); } From 7b3c680da506bd5039ec9d2ecb938625fa6189fc Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 4 Sep 2012 17:10:40 +0200 Subject: [PATCH 11/90] Better memory management during string construction --- .../android-tutorial-1/jni/tutorial-1.c | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 44806f9850..c95a78e3fa 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -22,32 +22,35 @@ jstring Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, jobject thiz ) { - char buffer[8192] = ""; + jstring ret; + char *buffer, *tmp; GList *original_plugin_list = gst_registry_get_plugin_list (gst_registry_get_default()); GList *plugin_list = original_plugin_list; - g_strlcat (buffer, gst_version_string(), sizeof (buffer)); - g_strlcat (buffer, "\n", sizeof (buffer)); + buffer = g_strdup_printf ("Version: %s\n", gst_version_string()); while (plugin_list) { GstPlugin *plugin = (GstPlugin *)plugin_list->data; GList *original_features_list, *features_list; plugin_list = plugin_list->next; - g_strlcat (buffer, gst_plugin_get_name (plugin), sizeof (buffer)); - g_strlcat (buffer, "\n", sizeof (buffer)); + tmp = g_strdup_printf ("%sPlugin: %s\n", buffer, gst_plugin_get_name (plugin)); + g_free (buffer); + buffer = tmp; original_features_list = features_list = gst_registry_get_feature_list_by_plugin (gst_registry_get_default(), plugin->desc.name); while (features_list) { GstPluginFeature *feature = (GstPluginFeature *)features_list->data; features_list = features_list->next; - g_strlcat (buffer, " ", sizeof (buffer)); - g_strlcat (buffer, gst_plugin_feature_get_name (feature), sizeof (buffer)); - g_strlcat (buffer, "\n", sizeof (buffer)); + tmp = g_strdup_printf ("%s %s\n", buffer, gst_plugin_feature_get_name (feature)); + g_free (buffer); + buffer = tmp; } gst_plugin_feature_list_free (original_features_list); } gst_plugin_list_free (original_plugin_list); - return (*env)->NewStringUTF(env, buffer); + ret = (*env)->NewStringUTF(env, buffer); + g_free (buffer); + return ret; } From 734e54ddfb7c5f7133fd833ae3b079365722d61b Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 6 Sep 2012 13:13:02 +0200 Subject: [PATCH 12/90] Add more plugins --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 3646087403..880595d4aa 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_LDLIBS := -L./ -lgstreamer_android LOCAL_CFLAGS := $(shell pkg-config gstreamer-0.10 --cflags) include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback +GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk From 70242780c3d2c90caf7281fea3768e0fd55a33cd Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 6 Sep 2012 13:13:44 +0200 Subject: [PATCH 13/90] Testing logging facilities --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index c95a78e3fa..5a115ffcad 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -18,6 +18,9 @@ #include #include +GST_DEBUG_CATEGORY_STATIC (debug_category); +#define GST_CAT_DEFAULT debug_category + jstring Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, jobject thiz ) @@ -27,6 +30,7 @@ Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, GList *original_plugin_list = gst_registry_get_plugin_list (gst_registry_get_default()); GList *plugin_list = original_plugin_list; + GST_DEBUG ("Preparing to dump plugin list"); buffer = g_strdup_printf ("Version: %s\n", gst_version_string()); while (plugin_list) { GstPlugin *plugin = (GstPlugin *)plugin_list->data; @@ -48,9 +52,14 @@ Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, } gst_plugin_feature_list_free (original_features_list); } + GST_DEBUG ("Plugin list dumped"); gst_plugin_list_free (original_plugin_list); ret = (*env)->NewStringUTF(env, buffer); g_free (buffer); return ret; } +jint JNI_OnLoad(JavaVM *vm, void *reserved) { + GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-1", 0, "Android tutorial 1"); + return JNI_VERSION_1_4; +} From 112f4f92f341ea44dda817eaa833b695162d720f Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 6 Sep 2012 15:56:13 +0200 Subject: [PATCH 14/90] In this way, -it's more ndk-build-ish- --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 880595d4aa..4e8fbd2757 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -18,8 +18,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := tutorial-1 LOCAL_SRC_FILES := tutorial-1.c -LOCAL_LDLIBS := -L./ -lgstreamer_android -LOCAL_CFLAGS := $(shell pkg-config gstreamer-0.10 --cflags) +LOCAL_SHARED_LIBRARIES := gstreamer_android include $(BUILD_SHARED_LIBRARY) GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse From b0e6ae8eb7fd1c657e00feaf4bc8b854232240a1 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 7 Sep 2012 16:26:04 +0200 Subject: [PATCH 15/90] Having a running pipeline now, controlled from the UI --- .../android-tutorial-1/jni/tutorial-1.c | 156 ++++++++++++++---- .../android-tutorial-1/res/values/strings.xml | 2 + .../tutorial_1/Tutorial1.java | 48 ++++-- 3 files changed, 159 insertions(+), 47 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 5a115ffcad..9bc84c8d2b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -17,49 +17,137 @@ #include #include #include +#include GST_DEBUG_CATEGORY_STATIC (debug_category); #define GST_CAT_DEFAULT debug_category -jstring -Java_com_gst_1sdk_1tutorials_tutorial_11_Tutorial1_gstVersion (JNIEnv* env, - jobject thiz ) -{ - jstring ret; - char *buffer, *tmp; - GList *original_plugin_list = gst_registry_get_plugin_list (gst_registry_get_default()); - GList *plugin_list = original_plugin_list; +typedef struct _CustomData { + JNIEnv *env; + GstElement *pipeline; + GMainLoop *main_loop; +} CustomData; - GST_DEBUG ("Preparing to dump plugin list"); - buffer = g_strdup_printf ("Version: %s\n", gst_version_string()); - while (plugin_list) { - GstPlugin *plugin = (GstPlugin *)plugin_list->data; - GList *original_features_list, *features_list; - plugin_list = plugin_list->next; +static pthread_t gst_app_thread; +static pthread_key_t gst_app_thread_key; +static JavaVM *java_vm; +static jfieldID custom_data_field_id; - tmp = g_strdup_printf ("%sPlugin: %s\n", buffer, gst_plugin_get_name (plugin)); - g_free (buffer); - buffer = tmp; - original_features_list = features_list = gst_registry_get_feature_list_by_plugin (gst_registry_get_default(), plugin->desc.name); - - while (features_list) { - GstPluginFeature *feature = (GstPluginFeature *)features_list->data; - features_list = features_list->next; - - tmp = g_strdup_printf ("%s %s\n", buffer, gst_plugin_feature_get_name (feature)); - g_free (buffer); - buffer = tmp; - } - gst_plugin_feature_list_free (original_features_list); - } - GST_DEBUG ("Plugin list dumped"); - gst_plugin_list_free (original_plugin_list); - ret = (*env)->NewStringUTF(env, buffer); - g_free (buffer); - return ret; +/* + * Private methods + */ +static void gst_detach_current_thread (void *env) { + GST_DEBUG ("Detaching thread %p", g_thread_self ()); + (*java_vm)->DetachCurrentThread (java_vm); } +static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); +} + +static void *gst_app_function (void *userdata) { + JavaVMAttachArgs args; + GstBus *bus; + GstMessage *msg; + CustomData *data = (CustomData *)userdata; + + pthread_key_create (&gst_app_thread_key, gst_detach_current_thread); + pthread_setspecific (gst_app_thread_key, &data); + + 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, &data->env, &args) < 0) { + GST_ERROR ("Failed to attach current thread"); + return; + } + + GST_DEBUG ("Creating pipeline in CustomData at %p", data); + + data->pipeline = gst_parse_launch ("videotestsrc num-buffers=10000 ! fakesink", NULL); + + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ + bus = gst_element_get_bus (data->pipeline); + gst_bus_add_signal_watch (bus); + g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); + g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)error_cb, data); + gst_object_unref (bus); + + /* Create a GLib Main Loop and set it to run */ + GST_DEBUG ("Entering main loop..."); + data->main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (data->main_loop); + GST_DEBUG ("Exitted main loop"); + + /* Free resources */ + gst_object_unref (bus); + gst_element_set_state (data->pipeline, GST_STATE_NULL); + gst_object_unref (data->pipeline); + // data = pthread_getspecific (gst_app_thread_key); +} + +/* + * Java Bindings + */ +void gst_native_init (JNIEnv* env, jobject thiz) { + CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); + (*env)->SetLongField (env, thiz, custom_data_field_id, (jlong)data); + GST_DEBUG ("Created CustomData at %p", data); + pthread_create (&gst_app_thread, NULL, &gst_app_function, data); +} + +void gst_native_finalize (JNIEnv* env, jobject thiz) { + CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + GST_DEBUG ("Quitting main loop..."); + g_main_loop_quit (data->main_loop); + GST_DEBUG ("Waiting for thread to finish..."); + pthread_join (gst_app_thread, NULL); + GST_DEBUG ("Freeing CustomData at %p", data); + g_free (data); + GST_DEBUG ("Done finalizing"); +} + +void gst_native_play (JNIEnv* env, jobject thiz) { + CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + GST_DEBUG ("Setting state to PLAYING"); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); +} + +void gst_native_pause (JNIEnv* env, jobject thiz) { + CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + GST_DEBUG ("Setting state to READY"); + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); +} + +void gst_class_init (JNIEnv* env, jclass klass) { + custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); + GST_DEBUG ("The FieldID for the native_custom_data field is %p", custom_data_field_id); +} + +static JNINativeMethod native_methods[] = { + { "nativeInit", "()V", (void *) gst_native_init}, + { "nativeFinalize", "()V", (void *) gst_native_finalize}, + { "nativePlay", "()V", (void *) gst_native_play}, + { "nativePause", "()V", (void *) gst_native_pause}, + { "classInit", "()V", (void *) gst_class_init} +}; + jint JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv *env = NULL; + int ret; + GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-1", 0, "Android tutorial 1"); + + java_vm = vm; + + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { + GST_ERROR ("Could not retrieve JNIEnv"); + return 0; + } + jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_1/Tutorial1"); + ret = (*env)->RegisterNatives (env, klass, native_methods, 5); + return JNI_VERSION_1_4; } diff --git a/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml b/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml index b956d6d241..60c84d95a7 100755 --- a/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml +++ b/gst-sdk/tutorials/android-tutorial-1/res/values/strings.xml @@ -1,4 +1,6 @@ Android tutorial 1 + Play + Stop diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 5afe4cc035..2e62669fb5 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -16,34 +16,56 @@ package com.gst_sdk_tutorials.tutorial_1; import android.app.Activity; -import android.widget.TextView; import android.os.Bundle; -import android.text.method.ScrollingMovementMethod; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageButton; +import android.widget.TextView; public class Tutorial1 extends Activity { - public native String gstVersion(); + public native void nativeInit(); + public native void nativeFinalize(); + public native void nativePlay(); + public native void nativePause(); + private static native void classInit(); + private long native_custom_data; /* Called when the activity is first created. @Override */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + setContentView(R.layout.main); + + ImageButton play = (ImageButton)this.findViewById(R.id.button_play); + play.setOnClickListener(new OnClickListener() { + + public void onClick(View v) { + nativePlay(); + } + }); + + ImageButton pause = (ImageButton)this.findViewById(R.id.button_stop); + pause.setOnClickListener(new OnClickListener() { + + public void onClick(View v) { + nativePause(); + } + }); - /* Create a TextView and set its content. - * the text is retrieved by calling a native - * function. - */ - TextView tv = new TextView(this); - tv.setMovementMethod(new ScrollingMovementMethod()); - tv.setClickable (false); - tv.setLongClickable (false); - tv.setText( gstVersion() ); - setContentView(tv); + nativeInit(); + } + + protected void onDestroy () { + nativeFinalize(); + super.onDestroy(); } static { System.loadLibrary("gstreamer_android"); System.loadLibrary("tutorial-1"); + classInit(); } } From 4f23fc027c7ac2c3f34b64d016a03a08e098fa9b Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 12:06:16 +0200 Subject: [PATCH 16/90] Remove warnings due to storing 32bits pointers inside jlongs. Fix handling of TLS (still unused, though) --- .../android-tutorial-1/jni/tutorial-1.c | 66 +++++++++++++------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 9bc84c8d2b..0285a4c157 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -22,6 +22,18 @@ 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 + typedef struct _CustomData { JNIEnv *env; GstElement *pipeline; @@ -29,18 +41,46 @@ typedef struct _CustomData { } CustomData; static pthread_t gst_app_thread; -static pthread_key_t gst_app_thread_key; +static pthread_key_t current_jni_env; static JavaVM *java_vm; static jfieldID custom_data_field_id; /* * Private methods */ +static JNIEnv * gst_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; +} + static void gst_detach_current_thread (void *env) { GST_DEBUG ("Detaching thread %p", g_thread_self ()); (*java_vm)->DetachCurrentThread (java_vm); } +static JNIEnv *gst_get_jni_env (void) { + JNIEnv *env; + + if ((env = pthread_getspecific (current_jni_env)) == NULL) { + env = gst_attach_current_thread (); + pthread_setspecific (current_jni_env, env); + } + + return env; +} + static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); } @@ -51,19 +91,6 @@ static void *gst_app_function (void *userdata) { GstMessage *msg; CustomData *data = (CustomData *)userdata; - pthread_key_create (&gst_app_thread_key, gst_detach_current_thread); - pthread_setspecific (gst_app_thread_key, &data); - - 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, &data->env, &args) < 0) { - GST_ERROR ("Failed to attach current thread"); - return; - } - GST_DEBUG ("Creating pipeline in CustomData at %p", data); data->pipeline = gst_parse_launch ("videotestsrc num-buffers=10000 ! fakesink", NULL); @@ -85,7 +112,6 @@ static void *gst_app_function (void *userdata) { gst_object_unref (bus); gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->pipeline); - // data = pthread_getspecific (gst_app_thread_key); } /* @@ -93,13 +119,13 @@ static void *gst_app_function (void *userdata) { */ void gst_native_init (JNIEnv* env, jobject thiz) { CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); - (*env)->SetLongField (env, thiz, custom_data_field_id, (jlong)data); + SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); pthread_create (&gst_app_thread, NULL, &gst_app_function, data); } void gst_native_finalize (JNIEnv* env, jobject thiz) { - CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); GST_DEBUG ("Quitting main loop..."); g_main_loop_quit (data->main_loop); GST_DEBUG ("Waiting for thread to finish..."); @@ -110,13 +136,13 @@ void gst_native_finalize (JNIEnv* env, jobject thiz) { } void gst_native_play (JNIEnv* env, jobject thiz) { - CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); GST_DEBUG ("Setting state to PLAYING"); gst_element_set_state (data->pipeline, GST_STATE_PLAYING); } void gst_native_pause (JNIEnv* env, jobject thiz) { - CustomData *data = (CustomData *)(*env)->GetLongField (env, thiz, custom_data_field_id); + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); GST_DEBUG ("Setting state to READY"); gst_element_set_state (data->pipeline, GST_STATE_PAUSED); } @@ -149,5 +175,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_1/Tutorial1"); ret = (*env)->RegisterNatives (env, klass, native_methods, 5); + pthread_key_create (¤t_jni_env, gst_detach_current_thread); + return JNI_VERSION_1_4; } From 30f8381ac93efb2bab3f23e78bcdfd09c2355156 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 12:08:33 +0200 Subject: [PATCH 17/90] Remove copyright note from Android samples --- .../android-tutorial-1/jni/tutorial-1.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 0285a4c157..7ad5ffcd0a 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -1,19 +1,3 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ #include #include #include From ca35131d479d18746176db017073cb7e5d0b94d8 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 12:09:56 +0200 Subject: [PATCH 18/90] Remove unused variable --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 7ad5ffcd0a..91747fc9a4 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -19,7 +19,6 @@ GST_DEBUG_CATEGORY_STATIC (debug_category); #endif typedef struct _CustomData { - JNIEnv *env; GstElement *pipeline; GMainLoop *main_loop; } CustomData; From 66d4f1873b27ef2ca9bf5aed9e8d3469adc30682 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 12:16:09 +0200 Subject: [PATCH 19/90] Whitespace --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 2e62669fb5..0e50affd5e 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -36,20 +36,18 @@ public class Tutorial1 extends Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + setContentView(R.layout.main); - + ImageButton play = (ImageButton)this.findViewById(R.id.button_play); play.setOnClickListener(new OnClickListener() { - public void onClick(View v) { nativePlay(); } }); - + ImageButton pause = (ImageButton)this.findViewById(R.id.button_stop); pause.setOnClickListener(new OnClickListener() { - public void onClick(View v) { nativePause(); } From ba4182c47049ce824b72322ed16350eac819767e Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 16:10:48 +0200 Subject: [PATCH 20/90] Add method to test Java UI code being called from C callbacks --- .../android-tutorial-1/jni/tutorial-1.c | 20 ++++++++++++++++--- .../tutorial_1/Tutorial1.java | 15 ++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 91747fc9a4..0baf3a37a2 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -19,6 +19,7 @@ GST_DEBUG_CATEGORY_STATIC (debug_category); #endif typedef struct _CustomData { + jobject app; GstElement *pipeline; GMainLoop *main_loop; } CustomData; @@ -27,11 +28,12 @@ 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; /* * Private methods */ -static JNIEnv * gst_attach_current_thread (void) { +static JNIEnv *gst_attach_current_thread (void) { JNIEnv *env; JavaVMAttachArgs args; @@ -65,7 +67,13 @@ static JNIEnv *gst_get_jni_env (void) { } static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); + GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); + JNIEnv *env = gst_get_jni_env (); + (*env)->CallVoidMethod (env, data->app, set_message_method_id, (*env)->NewStringUTF(env, GST_MESSAGE_TYPE_NAME (msg))); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } } static void *gst_app_function (void *userdata) { @@ -76,7 +84,7 @@ static void *gst_app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); - data->pipeline = gst_parse_launch ("videotestsrc num-buffers=10000 ! fakesink", NULL); + data->pipeline = gst_parse_launch ("videotestsrc num-buffers=1000 ! fakesink", NULL); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); @@ -105,6 +113,8 @@ void gst_native_init (JNIEnv* env, jobject thiz) { SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); pthread_create (&gst_app_thread, NULL, &gst_app_function, data); + data->app = (*env)->NewGlobalRef (env, thiz); + GST_DEBUG ("Created GlobalRef for app objet at %p", data->app); } void gst_native_finalize (JNIEnv* env, jobject thiz) { @@ -113,6 +123,8 @@ void gst_native_finalize (JNIEnv* env, jobject thiz) { g_main_loop_quit (data->main_loop); GST_DEBUG ("Waiting for thread to finish..."); pthread_join (gst_app_thread, NULL); + GST_DEBUG ("Deleting GlobalRef at %p", data->app); + (*env)->DeleteGlobalRef (env, data->app); GST_DEBUG ("Freeing CustomData at %p", data); g_free (data); GST_DEBUG ("Done finalizing"); @@ -133,6 +145,8 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { void gst_class_init (JNIEnv* env, jclass klass) { custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); GST_DEBUG ("The FieldID for the native_custom_data field is %p", custom_data_field_id); + set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); + GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); } static JNINativeMethod native_methods[] = { diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 0e50affd5e..e32c1a165b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -16,6 +16,7 @@ package com.gst_sdk_tutorials.tutorial_1; import android.app.Activity; +import android.util.Log; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; @@ -61,6 +62,20 @@ public class Tutorial1 extends Activity super.onDestroy(); } + private void setMessage (final String message) { + final TextView tv = (TextView)this.findViewById(R.id.textview_message); + Log.d ("GStreamer", "Received message " + message); + try { + runOnUiThread (new Runnable() {@Override public void run() + { + tv.setText (message); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + static { System.loadLibrary("gstreamer_android"); System.loadLibrary("tutorial-1"); From e4a142b38ad0b3f704bb2bfdba73fe6935f03f6a Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 10 Sep 2012 16:45:19 +0200 Subject: [PATCH 21/90] Add missing layour file --- .../android-tutorial-1/res/layout/main.xml | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml diff --git a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml new file mode 100755 index 0000000000..a6b9824c2b --- /dev/null +++ b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + \ No newline at end of file From 6c3dcf57305382f96bab27de5797efb385734d5d Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 12 Sep 2012 10:59:23 +0200 Subject: [PATCH 22/90] Assorted small fixes, string leaks and beautifying --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 10 ++++++---- .../com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 0baf3a37a2..e6dd32a93d 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -69,11 +69,13 @@ static JNIEnv *gst_get_jni_env (void) { static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); JNIEnv *env = gst_get_jni_env (); - (*env)->CallVoidMethod (env, data->app, set_message_method_id, (*env)->NewStringUTF(env, GST_MESSAGE_TYPE_NAME (msg))); + jstring jmessage = (*env)->NewStringUTF(env, GST_MESSAGE_TYPE_NAME (msg)); + (*env)->CallVoidMethod (env, data->app, set_message_method_id, jmessage); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); } + (*env)->DeleteLocalRef (env, jmessage); } static void *gst_app_function (void *userdata) { @@ -112,9 +114,9 @@ void gst_native_init (JNIEnv* env, jobject thiz) { CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); - pthread_create (&gst_app_thread, NULL, &gst_app_function, data); data->app = (*env)->NewGlobalRef (env, thiz); - GST_DEBUG ("Created GlobalRef for app objet at %p", data->app); + GST_DEBUG ("Created GlobalRef for app object at %p", data->app); + pthread_create (&gst_app_thread, NULL, &gst_app_function, data); } void gst_native_finalize (JNIEnv* env, jobject thiz) { @@ -170,7 +172,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { return 0; } jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_1/Tutorial1"); - ret = (*env)->RegisterNatives (env, klass, native_methods, 5); + ret = (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); pthread_key_create (¤t_jni_env, gst_detach_current_thread); diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index e32c1a165b..809bd2c6e3 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -25,10 +25,10 @@ import android.widget.TextView; public class Tutorial1 extends Activity { - public native void nativeInit(); - public native void nativeFinalize(); - public native void nativePlay(); - public native void nativePause(); + private native void nativeInit(); + private native void nativeFinalize(); + private native void nativePlay(); + private native void nativePause(); private static native void classInit(); private long native_custom_data; From c4363559c80d8b9b551c31593d663412aea4b343 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 12 Sep 2012 17:38:17 +0200 Subject: [PATCH 23/90] Update minimum SDk version to 9 --- gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml index dfc3c54085..88f60cefab 100755 --- a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -3,7 +3,7 @@ package="com.gst_sdk_tutorials.tutorial_1" android:versionCode="1" android:versionName="1.0"> - + From f7446956c9ffcea6cdfa13d2b0aff0c45e655497 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 12 Sep 2012 17:39:14 +0200 Subject: [PATCH 24/90] Add a SurfaceView and tell native code about it. Still no sink though. --- .../android-tutorial-1/jni/Android.mk | 1 + .../android-tutorial-1/jni/tutorial-1.c | 25 ++++++- .../android-tutorial-1/res/layout/main.xml | 5 ++ .../tutorial_1/Tutorial1.java | 72 ++++++++++++------- 4 files changed, 78 insertions(+), 25 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 4e8fbd2757..7bf074de46 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -19,6 +19,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := tutorial-1 LOCAL_SRC_FILES := tutorial-1.c LOCAL_SHARED_LIBRARIES := gstreamer_android +LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index e6dd32a93d..8bd7256620 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -22,6 +24,7 @@ typedef struct _CustomData { jobject app; GstElement *pipeline; GMainLoop *main_loop; + ANativeWindow *native_window; } CustomData; static pthread_t gst_app_thread; @@ -151,12 +154,32 @@ void gst_class_init (JNIEnv* env, jclass klass) { GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); } +void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + GST_DEBUG ("Received surface %p", surface); + if (data->native_window) { + GST_DEBUG ("Releasing previous native window %p", data->native_window); + ANativeWindow_release (data->native_window); + } + data->native_window = ANativeWindow_fromSurface(env, surface); + GST_DEBUG ("Got Native Window %p", data->native_window); +} + +void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + GST_DEBUG ("Releasing Native Window %p", data->native_window); + ANativeWindow_release (data->native_window); + data->native_window = NULL; +} + static JNINativeMethod native_methods[] = { { "nativeInit", "()V", (void *) gst_native_init}, { "nativeFinalize", "()V", (void *) gst_native_finalize}, { "nativePlay", "()V", (void *) gst_native_play}, { "nativePause", "()V", (void *) gst_native_pause}, - { "classInit", "()V", (void *) gst_class_init} + { "classInit", "()V", (void *) gst_class_init}, + { "nativeSurfaceInit", "(Ljava/lang/Object;)V", (void *) gst_native_surface_init}, + { "nativeSurfaceFinalize", "()V", (void *) gst_native_surface_finalize} }; jint JNI_OnLoad(JavaVM *vm, void *reserved) { diff --git a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml index a6b9824c2b..651740ade8 100755 --- a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml +++ b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml @@ -31,4 +31,9 @@ android:text="@string/button_stop" /> + + \ No newline at end of file diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 809bd2c6e3..7df52e98c0 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -18,18 +18,22 @@ package com.gst_sdk_tutorials.tutorial_1; import android.app.Activity; import android.util.Log; import android.os.Bundle; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.TextView; -public class Tutorial1 extends Activity -{ +public class Tutorial1 extends Activity implements SurfaceHolder.Callback { private native void nativeInit(); private native void nativeFinalize(); private native void nativePlay(); private native void nativePause(); private static native void classInit(); + private native void nativeSurfaceInit(Object surface); + private native void nativeSurfaceFinalize(); private long native_custom_data; /* Called when the activity is first created. @@ -40,40 +44,44 @@ public class Tutorial1 extends Activity setContentView(R.layout.main); - ImageButton play = (ImageButton)this.findViewById(R.id.button_play); + ImageButton play = (ImageButton) this.findViewById(R.id.button_play); play.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - nativePlay(); - } + public void onClick(View v) { + nativePlay(); + } }); - ImageButton pause = (ImageButton)this.findViewById(R.id.button_stop); + ImageButton pause = (ImageButton) this.findViewById(R.id.button_stop); pause.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - nativePause(); - } + public void onClick(View v) { + nativePause(); + } }); + SurfaceView sv = (SurfaceView) this.findViewById(R.id.surface_video); + SurfaceHolder sh = sv.getHolder(); + sh.addCallback(this); + nativeInit(); } - protected void onDestroy () { - nativeFinalize(); - super.onDestroy(); + protected void onDestroy() { + nativeFinalize(); + super.onDestroy(); } - private void setMessage (final String message) { - final TextView tv = (TextView)this.findViewById(R.id.textview_message); - Log.d ("GStreamer", "Received message " + message); - try { - runOnUiThread (new Runnable() {@Override public void run() + private void setMessage(final String message) { + final TextView tv = (TextView) this.findViewById(R.id.textview_message); + Log.d("GStreamer", "Received message " + message); + try { + runOnUiThread (new Runnable() {public void run() { - tv.setText (message); - } - }); - } catch (Exception e) { - e.printStackTrace(); - } + tv.setText(message); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } } static { @@ -81,4 +89,20 @@ public class Tutorial1 extends Activity System.loadLibrary("tutorial-1"); classInit(); } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, + int height) { + Log.d("GStreamer", "Surface changed to format " + format + " width " + + width + " height " + height); + nativeSurfaceInit (holder.getSurface()); + } + + public void surfaceCreated(SurfaceHolder holder) { + Log.d("GStreamer", "Surface created: " + holder.getSurface()); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + Log.d("GStreamer", "Surface destroyed"); + nativeSurfaceFinalize (); + } } From a449e48aea86817e09b0c539932139c1ccf90e09 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 12 Sep 2012 18:45:03 +0200 Subject: [PATCH 25/90] Use a eglglessink (does not work yet) --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 7bf074de46..b94079089c 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse +GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 8bd7256620..1d42bec80e 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -4,6 +4,7 @@ #include #include #include +#include GST_DEBUG_CATEGORY_STATIC (debug_category); #define GST_CAT_DEFAULT debug_category @@ -89,7 +90,7 @@ static void *gst_app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); - data->pipeline = gst_parse_launch ("videotestsrc num-buffers=1000 ! fakesink", NULL); + data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink", NULL); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); @@ -163,6 +164,8 @@ void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { } data->native_window = ANativeWindow_fromSurface(env, surface); GST_DEBUG ("Got Native Window %p", data->native_window); + + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)data->native_window); } void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { @@ -170,6 +173,8 @@ void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { GST_DEBUG ("Releasing Native Window %p", data->native_window); ANativeWindow_release (data->native_window); data->native_window = NULL; + + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)NULL); } static JNINativeMethod native_methods[] = { From d6c101954bfd1ba3427d19be85827fa3d7a47051 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 12 Sep 2012 18:49:06 +0200 Subject: [PATCH 26/90] Add missing properties needed while testing --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 1d42bec80e..79391d280c 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -90,7 +90,7 @@ static void *gst_app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); - data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink", NULL); + data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0", NULL); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); From 48f9983fbdd7eec354bebcddb54250a2c9f513e0 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 13 Sep 2012 12:05:43 +0200 Subject: [PATCH 27/90] Formatting --- .../gst_sdk_tutorials/tutorial_1/Tutorial1.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 7df52e98c0..7bc71dca14 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -73,15 +73,11 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { private void setMessage(final String message) { final TextView tv = (TextView) this.findViewById(R.id.textview_message); Log.d("GStreamer", "Received message " + message); - try { - runOnUiThread (new Runnable() {public void run() - { - tv.setText(message); - } - }); - } catch (Exception e) { - e.printStackTrace(); - } + runOnUiThread (new Runnable() { + public void run() { + tv.setText(message); + } + }); } static { From 0156029e06f0e23d395bd8fcc01001ade7982768 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 13 Sep 2012 12:09:22 +0200 Subject: [PATCH 28/90] Remove unneeded import --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 7bc71dca14..36d4e48bb3 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -18,7 +18,6 @@ package com.gst_sdk_tutorials.tutorial_1; import android.app.Activity; import android.util.Log; import android.os.Bundle; -import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; From 8f8258e4b9e7d3996ef2a9ba76d43acf5e6a7190 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 13 Sep 2012 14:36:06 +0200 Subject: [PATCH 29/90] Report current position/duration back to the UI. Refactor. --- .../android-tutorial-1/AndroidManifest.xml | 1 + .../android-tutorial-1/jni/Android.mk | 2 +- .../android-tutorial-1/jni/tutorial-1.c | 104 +++++++++++++++--- .../android-tutorial-1/res/layout/main.xml | 6 + .../tutorial_1/Tutorial1.java | 17 ++- 5 files changed, 113 insertions(+), 17 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml index 88f60cefab..508f2f1b91 100755 --- a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -4,6 +4,7 @@ android:versionCode="1" android:versionName="1.0"> + diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index b94079089c..2e7a773692 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink +GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 79391d280c..c35141c312 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -26,6 +26,9 @@ typedef struct _CustomData { GstElement *pipeline; GMainLoop *main_loop; ANativeWindow *native_window; + gboolean playing; + gint64 position; + gint64 duration; } CustomData; static pthread_t gst_app_thread; @@ -33,11 +36,12 @@ 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; /* * Private methods */ -static JNIEnv *gst_attach_current_thread (void) { +static JNIEnv *attach_current_thread (void) { JNIEnv *env; JavaVMAttachArgs args; @@ -54,26 +58,26 @@ static JNIEnv *gst_attach_current_thread (void) { return env; } -static void gst_detach_current_thread (void *env) { +static void detach_current_thread (void *env) { GST_DEBUG ("Detaching thread %p", g_thread_self ()); (*java_vm)->DetachCurrentThread (java_vm); } -static JNIEnv *gst_get_jni_env (void) { +static JNIEnv *get_jni_env (void) { JNIEnv *env; if ((env = pthread_getspecific (current_jni_env)) == NULL) { - env = gst_attach_current_thread (); + env = attach_current_thread (); pthread_setspecific (current_jni_env, env); } return env; } -static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GST_DEBUG ("Message: %s", GST_MESSAGE_TYPE_NAME (msg)); - JNIEnv *env = gst_get_jni_env (); - jstring jmessage = (*env)->NewStringUTF(env, GST_MESSAGE_TYPE_NAME (msg)); +static void set_message (const gchar *message, CustomData *data) { + JNIEnv *env = get_jni_env (); + GST_DEBUG ("Setting message to: %s", message); + jstring jmessage = (*env)->NewStringUTF(env, message); (*env)->CallVoidMethod (env, data->app, set_message_method_id, jmessage); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); @@ -82,7 +86,67 @@ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { (*env)->DeleteLocalRef (env, jmessage); } -static void *gst_app_function (void *userdata) { +static void set_current_position (gint64 position, gint64 duration, CustomData *data) { + JNIEnv *env = get_jni_env (); + GST_DEBUG ("Setting current position/duration to: %lld / %lld (ms)", position, duration); + (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } +} + +static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GError *err; + gchar *debug_info; + gchar *message_string; + + gst_message_parse_error (msg, &err, &debug_info); + message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); + g_clear_error (&err); + g_free (debug_info); + set_message (message_string, data); + g_free (message_string); + gst_element_set_state (data->pipeline, GST_STATE_NULL); +} + +static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + set_message (GST_MESSAGE_TYPE_NAME (msg), data); + gst_element_set_state (data->pipeline, GST_STATE_NULL); +} + +static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { + set_message (gst_element_state_get_name (new_state), data); + data->playing = (new_state == GST_STATE_PLAYING); + } +} + +static gboolean refresh_ui (CustomData *data) { + GstFormat fmt = GST_FORMAT_TIME; + gint64 current = -1; + + /* We do not want to update anything unless we are in the PLAYING state */ + if (!data->playing) + return TRUE; + + /* If we didn't know it yet, query the stream duration */ + if (!GST_CLOCK_TIME_IS_VALID (data->duration)) { + if (!gst_element_query_duration (data->pipeline, &fmt, &data->duration)) { + GST_WARNING ("Could not query current duration"); + } + } + + if (gst_element_query_position (data->pipeline, &fmt, &data->position)) { + /* Java expects these values in milliseconds, and Gst provides nanoseconds */ + set_current_position (data->position/1000000, data->duration/1000000, data); + } + return TRUE; +} + +static void *app_function (void *userdata) { JavaVMAttachArgs args; GstBus *bus; GstMessage *msg; @@ -90,15 +154,22 @@ static void *gst_app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); - data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); + data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); - g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)error_cb, data); + g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); + g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); gst_object_unref (bus); - + + /* Register a function that GLib will call every second */ + g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); + /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop..."); data->main_loop = g_main_loop_new (NULL, FALSE); @@ -116,11 +187,12 @@ static void *gst_app_function (void *userdata) { */ void gst_native_init (JNIEnv* env, jobject thiz) { CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); + data->duration = GST_CLOCK_TIME_NONE; SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); data->app = (*env)->NewGlobalRef (env, thiz); GST_DEBUG ("Created GlobalRef for app object at %p", data->app); - pthread_create (&gst_app_thread, NULL, &gst_app_function, data); + pthread_create (&gst_app_thread, NULL, &app_function, data); } void gst_native_finalize (JNIEnv* env, jobject thiz) { @@ -144,7 +216,7 @@ void gst_native_play (JNIEnv* env, jobject thiz) { void gst_native_pause (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - GST_DEBUG ("Setting state to READY"); + GST_DEBUG ("Setting state to PAUSED"); gst_element_set_state (data->pipeline, GST_STATE_PAUSED); } @@ -153,6 +225,8 @@ void gst_class_init (JNIEnv* env, jclass klass) { GST_DEBUG ("The FieldID for the native_custom_data field is %p", custom_data_field_id); set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); + set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(JJ)V"); + GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id); } void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { @@ -202,7 +276,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_1/Tutorial1"); ret = (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); - pthread_key_create (¤t_jni_env, gst_detach_current_thread); + pthread_key_create (¤t_jni_env, detach_current_thread); return JNI_VERSION_1_4; } diff --git a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml index 651740ade8..edf04e3d53 100755 --- a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml +++ b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml @@ -29,6 +29,12 @@ android:contentDescription="@string/button_stop" android:src="@android:drawable/ic_media_pause" android:text="@string/button_stop" /> + + Date: Thu, 13 Sep 2012 16:35:51 +0200 Subject: [PATCH 30/90] Add a SeekBar to show current position / duration --- .../android-tutorial-1/jni/tutorial-1.c | 57 ++++++++++--------- .../android-tutorial-1/res/layout/main.xml | 12 +++- .../tutorial_1/Tutorial1.java | 6 +- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index c35141c312..c5d037d6ea 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -96,34 +96,6 @@ static void set_current_position (gint64 position, gint64 duration, CustomData * } } -static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GError *err; - gchar *debug_info; - gchar *message_string; - - gst_message_parse_error (msg, &err, &debug_info); - message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); - g_clear_error (&err); - g_free (debug_info); - set_message (message_string, data); - g_free (message_string); - gst_element_set_state (data->pipeline, GST_STATE_NULL); -} - -static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - set_message (GST_MESSAGE_TYPE_NAME (msg), data); - gst_element_set_state (data->pipeline, GST_STATE_NULL); -} - -static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { - set_message (gst_element_state_get_name (new_state), data); - data->playing = (new_state == GST_STATE_PLAYING); - } -} - static gboolean refresh_ui (CustomData *data) { GstFormat fmt = GST_FORMAT_TIME; gint64 current = -1; @@ -146,6 +118,35 @@ static gboolean refresh_ui (CustomData *data) { return TRUE; } +static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GError *err; + gchar *debug_info; + gchar *message_string; + + gst_message_parse_error (msg, &err, &debug_info); + message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); + g_clear_error (&err); + g_free (debug_info); + set_message (message_string, data); + g_free (message_string); + gst_element_set_state (data->pipeline, GST_STATE_NULL); +} + +static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + set_message (GST_MESSAGE_TYPE_NAME (msg), data); + refresh_ui (data); + gst_element_set_state (data->pipeline, GST_STATE_NULL); +} + +static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { + set_message (gst_element_state_get_name (new_state), data); + data->playing = (new_state == GST_STATE_PLAYING); + } +} + static void *app_function (void *userdata) { JavaVMAttachArgs args; GstBus *bus; diff --git a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml index edf04e3d53..4c3e1000c2 100755 --- a/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml +++ b/gst-sdk/tutorials/android-tutorial-1/res/layout/main.xml @@ -34,7 +34,17 @@ android:id="@+id/textview_time" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" /> + android:layout_gravity="center_vertical" + android:layout_marginLeft="5dip" + android:layout_marginRight="5dip" /> + + Date: Thu, 13 Sep 2012 18:29:02 +0200 Subject: [PATCH 31/90] Set the targetSDK to 14 (Gingerbread). This uses cooler (more recent) UI elements when available. --- gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml index 508f2f1b91..0d1f7f124b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -3,7 +3,7 @@ package="com.gst_sdk_tutorials.tutorial_1" android:versionCode="1" android:versionName="1.0"> - + Date: Fri, 14 Sep 2012 12:02:19 +0200 Subject: [PATCH 32/90] Display video via an appsink. --- .../android-tutorial-1/jni/tutorial-1.c | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index c5d037d6ea..6229c3b05d 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -147,18 +147,53 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } } +static void new_buffer (GstElement *sink, CustomData *data) { + GstBuffer *buffer; + + /* Retrieve the buffer */ + g_signal_emit_by_name (sink, "pull-buffer", &buffer); + if (buffer) { + if (data->native_window) { + int i; + ANativeWindow_Buffer nbuff; + GstStructure *str; + gint width, height; + + str = gst_caps_get_structure (GST_BUFFER_CAPS (buffer), 0); + gst_structure_get_int (str, "width", &width); + gst_structure_get_int (str, "height", &height); + + ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); + + ANativeWindow_lock(data->native_window, &nbuff, NULL); + GST_DEBUG ("Native buffer width:%d height:%d stride:%d format:%d", nbuff.width, nbuff.height, nbuff.stride, nbuff.format); + for (i=0; inative_window); + } + gst_buffer_unref (buffer); + } +} + static void *app_function (void *userdata) { JavaVMAttachArgs args; GstBus *bus; GstMessage *msg; CustomData *data = (CustomData *)userdata; + GstElement *vsink; GST_DEBUG ("Creating pipeline in CustomData at %p", data); // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0", NULL); // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); - data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); +// data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); + data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); + vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); + g_signal_connect (vsink, "new-buffer", G_CALLBACK (new_buffer), data); + gst_object_unref (vsink); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); From c892f3519334f223b12e92bf49bc8d690fc5e259 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 14 Sep 2012 12:45:54 +0200 Subject: [PATCH 33/90] Protect against surfaces being destroyed after the app is killed --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 6229c3b05d..5741f7a2e7 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -103,14 +103,14 @@ static gboolean refresh_ui (CustomData *data) { /* We do not want to update anything unless we are in the PLAYING state */ if (!data->playing) return TRUE; - + /* If we didn't know it yet, query the stream duration */ if (!GST_CLOCK_TIME_IS_VALID (data->duration)) { if (!gst_element_query_duration (data->pipeline, &fmt, &data->duration)) { GST_WARNING ("Could not query current duration"); } } - + if (gst_element_query_position (data->pipeline, &fmt, &data->position)) { /* Java expects these values in milliseconds, and Gst provides nanoseconds */ set_current_position (data->position/1000000, data->duration/1000000, data); @@ -166,7 +166,6 @@ static void new_buffer (GstElement *sink, CustomData *data) { ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); ANativeWindow_lock(data->native_window, &nbuff, NULL); - GST_DEBUG ("Native buffer width:%d height:%d stride:%d format:%d", nbuff.width, nbuff.height, nbuff.stride, nbuff.format); for (i=0; iDeleteGlobalRef (env, data->app); GST_DEBUG ("Freeing CustomData at %p", data); g_free (data); + SET_CUSTOM_DATA (env, thiz, custom_data_field_id, NULL); GST_DEBUG ("Done finalizing"); } @@ -280,6 +280,10 @@ void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) { + GST_WARNING ("Received surface finalize but there is no CustomData. Ignoring."); + return; + } GST_DEBUG ("Releasing Native Window %p", data->native_window); ANativeWindow_release (data->native_window); data->native_window = NULL; From f81f2c43470d72d556ad1374772616a0d1c600ad Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 14 Sep 2012 16:01:07 +0200 Subject: [PATCH 34/90] Send XOverlay messages directly to the sink. Try to resume playing in the place where it stopped. Assorted fixes. --- .../android-tutorial-1/jni/tutorial-1.c | 47 +++++++++++++------ .../tutorial_1/Tutorial1.java | 30 ++++++++++-- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 5741f7a2e7..7496a2a948 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -29,6 +29,7 @@ typedef struct _CustomData { gboolean playing; gint64 position; gint64 duration; + GstElement *vsink; } CustomData; static pthread_t gst_app_thread; @@ -86,9 +87,9 @@ static void set_message (const gchar *message, CustomData *data) { (*env)->DeleteLocalRef (env, jmessage); } -static void set_current_position (gint64 position, gint64 duration, CustomData *data) { +static void set_current_position (gint position, gint duration, CustomData *data) { JNIEnv *env = get_jni_env (); - GST_DEBUG ("Setting current position/duration to: %lld / %lld (ms)", position, duration); + GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration); (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); @@ -100,8 +101,8 @@ static gboolean refresh_ui (CustomData *data) { GstFormat fmt = GST_FORMAT_TIME; gint64 current = -1; - /* We do not want to update anything unless we are in the PLAYING state */ - if (!data->playing) + /* We do not want to update anything unless we have a working pipeline in the PLAYING state */ + if (!data || !data->pipeline || !data->playing) return TRUE; /* If we didn't know it yet, query the stream duration */ @@ -169,6 +170,7 @@ static void new_buffer (GstElement *sink, CustomData *data) { for (i=0; inative_window); } gst_buffer_unref (buffer); @@ -180,19 +182,19 @@ static void *app_function (void *userdata) { GstBus *bus; GstMessage *msg; CustomData *data = (CustomData *)userdata; - GstElement *vsink; + guint timeout_source_id; + GSource *timeout_source; GST_DEBUG ("Creating pipeline in CustomData at %p", data); -// data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0", NULL); + data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); - data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); - vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); - g_signal_connect (vsink, "new-buffer", G_CALLBACK (new_buffer), data); - gst_object_unref (vsink); + data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); +// g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); @@ -203,17 +205,23 @@ static void *app_function (void *userdata) { gst_object_unref (bus); /* Register a function that GLib will call every second */ - g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); + timeout_source_id = g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); /* Create a GLib Main Loop and set it to run */ - GST_DEBUG ("Entering main loop..."); + GST_DEBUG ("Entering main loop... (CustomData:%p)", data); data->main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data->main_loop); - GST_DEBUG ("Exitted main loop"); + GST_DEBUG ("Exited main loop"); + + /* Destroy the timeout source */ + timeout_source = g_main_context_find_source_by_id (NULL, timeout_source_id); + GST_DEBUG ("timeout_source:%p", timeout_source); + g_source_destroy (timeout_source); /* Free resources */ gst_object_unref (bus); gst_element_set_state (data->pipeline, GST_STATE_NULL); + gst_object_unref (data->vsink); gst_object_unref (data->pipeline); } @@ -228,6 +236,8 @@ void gst_native_init (JNIEnv* env, jobject thiz) { data->app = (*env)->NewGlobalRef (env, thiz); GST_DEBUG ("Created GlobalRef for app object at %p", data->app); pthread_create (&gst_app_thread, NULL, &app_function, data); + /* FIXME: Wait until thread has started and the main loop is runing */ + usleep (100000); } void gst_native_finalize (JNIEnv* env, jobject thiz) { @@ -256,12 +266,18 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { gst_element_set_state (data->pipeline, GST_STATE_PAUSED); } +void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + GST_DEBUG ("Setting position to %d milliseconds", milliseconds); + gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,(gint64)(milliseconds * GST_SECOND / 1000)); +} + void gst_class_init (JNIEnv* env, jclass klass) { custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); GST_DEBUG ("The FieldID for the native_custom_data field is %p", custom_data_field_id); set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); - set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(JJ)V"); + set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(II)V"); GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id); } @@ -288,7 +304,7 @@ void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { ANativeWindow_release (data->native_window); data->native_window = NULL; - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)NULL); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)NULL); } static JNINativeMethod native_methods[] = { @@ -296,6 +312,7 @@ static JNINativeMethod native_methods[] = { { "nativeFinalize", "()V", (void *) gst_native_finalize}, { "nativePlay", "()V", (void *) gst_native_play}, { "nativePause", "()V", (void *) gst_native_pause}, + { "nativeSetPosition", "(I)V", (void*) gst_native_set_position}, { "classInit", "()V", (void *) gst_class_init}, { "nativeSurfaceInit", "(Ljava/lang/Object;)V", (void *) gst_native_surface_init}, { "nativeSurfaceFinalize", "()V", (void *) gst_native_surface_finalize} diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 57dd455dd8..cffcf91f30 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -35,10 +35,15 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { private native void nativeFinalize(); private native void nativePlay(); private native void nativePause(); + private native void nativeSetPosition(int milliseconds); private static native void classInit(); private native void nativeSurfaceInit(Object surface); private native void nativeSurfaceFinalize(); private long native_custom_data; + + private boolean playing; + private int position; + private int duration; /* Called when the activity is first created. @Override */ @@ -52,6 +57,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { play.setOnClickListener(new OnClickListener() { public void onClick(View v) { nativePlay(); + playing = true; } }); @@ -59,6 +65,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { pause.setOnClickListener(new OnClickListener() { public void onClick(View v) { nativePause(); + playing = false; } }); @@ -67,6 +74,21 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { sh.addCallback(this); nativeInit(); + + playing = savedInstanceState==null ? false : savedInstanceState.getBoolean("playing"); + if (playing) { + int milliseconds = savedInstanceState.getInt("position"); + Log.i ("GStreamer", "Restoring to playing state at " + milliseconds + " ms."); + nativePlay(); + nativeSetPosition(milliseconds); + } + } + + protected void onSaveInstanceState (Bundle outState) { + Log.d ("GStreamer", "Saving state, playing:" + playing + " position:" + position); + outState.putBoolean("playing", playing); + outState.putInt("position", position); + outState.putInt("duration", duration); } protected void onDestroy() { @@ -83,7 +105,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { }); } - private void setCurrentPosition(final long position, final long duration) { + private void setCurrentPosition(final int position, final int duration) { final TextView tv = (TextView) this.findViewById(R.id.textview_time); final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); @@ -92,10 +114,12 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { runOnUiThread (new Runnable() { public void run() { tv.setText(message); - sb.setMax((int)duration); - sb.setProgress((int)position); + sb.setMax(duration); + sb.setProgress(position); } }); + this.position = position; + this.duration = duration; } static { From f780c13852be53e3649993d4527a7630ac847078 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 14 Sep 2012 16:08:37 +0200 Subject: [PATCH 35/90] Add missing fix --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 7496a2a948..5e88d2a3bc 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -291,7 +291,7 @@ void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { data->native_window = ANativeWindow_fromSurface(env, surface); GST_DEBUG ("Got Native Window %p", data->native_window); - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)data->native_window); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); } void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { From 1d7c2a6f875877cd9e3df74d328f5d86064427e2 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 14 Sep 2012 17:08:15 +0200 Subject: [PATCH 36/90] Add hardware decoding capabilities --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 2e7a773692..f077bcf6bd 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup +GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup amc matroska GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ include $(GSTREAMER_MK_PATH)/gstreamer.mk diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 5e88d2a3bc..629c1a2576 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -187,14 +187,14 @@ static void *app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); - data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); +// data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); + data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); -// g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); + g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); From ff9ff2c549e1c07f26286ec101d322290ddb52f0 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 11:54:45 +0200 Subject: [PATCH 37/90] Delay seeks if not in the playing state. Verify return value of ANativeWindow_Lock. --- .../android-tutorial-1/jni/tutorial-1.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 629c1a2576..75532a0227 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -30,6 +30,7 @@ typedef struct _CustomData { gint64 position; gint64 duration; GstElement *vsink; + gint64 desired_position; } CustomData; static pthread_t gst_app_thread; @@ -119,6 +120,13 @@ static gboolean refresh_ui (CustomData *data) { return TRUE; } +static void execute_seek (gint64 desired_position, CustomData *data) { + gboolean res; + GST_DEBUG ("Setting position to %lld milliseconds", desired_position / 1000000); + res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); + GST_DEBUG ("Seek returned %d", res); +} + static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GError *err; gchar *debug_info; @@ -145,6 +153,10 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { set_message (gst_element_state_get_name (new_state), data); data->playing = (new_state == GST_STATE_PLAYING); + if (data->playing && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { + execute_seek (data->desired_position, data); + data->desired_position = GST_CLOCK_TIME_NONE; + } } } @@ -166,12 +178,14 @@ static void new_buffer (GstElement *sink, CustomData *data) { ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); - ANativeWindow_lock(data->native_window, &nbuff, NULL); - for (i=0; inative_window, &nbuff, NULL) < 0) { + GST_ERROR ("Unable to lock Native Window, discarding buffer."); + } else { + for (i=0; inative_window); } - /* FIXME: Sometimes this segfaults. Maybe the native window has been destroyed while we were copying into it? */ - ANativeWindow_unlockAndPost (data->native_window); } gst_buffer_unref (buffer); } @@ -192,6 +206,8 @@ static void *app_function (void *userdata) { // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); +// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); @@ -231,6 +247,7 @@ static void *app_function (void *userdata) { void gst_native_init (JNIEnv* env, jobject thiz) { CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); data->duration = GST_CLOCK_TIME_NONE; + data->desired_position = GST_CLOCK_TIME_NONE; SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); data->app = (*env)->NewGlobalRef (env, thiz); @@ -268,8 +285,13 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - GST_DEBUG ("Setting position to %d milliseconds", milliseconds); - gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,(gint64)(milliseconds * GST_SECOND / 1000)); + gint64 desired_position = (gint64)(milliseconds * GST_SECOND / 1000); + if (data->playing) { + execute_seek(desired_position, data); + } else { + GST_DEBUG ("Scheduling seek to %d milliseconds for later", milliseconds); + data->desired_position = desired_position; + } } void gst_class_init (JNIEnv* env, jclass klass) { From 206415b27b288d0977400d6e4c10e57aeacc2a9c Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 12:31:23 +0200 Subject: [PATCH 38/90] Allow seeking from the SeekBar (video does not refresh until you release the SeekBar, though) --- .../android-tutorial-1/jni/tutorial-1.c | 14 +++++++------- .../tutorial_1/Tutorial1.java | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 75532a0227..0570a704e8 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -26,7 +26,7 @@ typedef struct _CustomData { GstElement *pipeline; GMainLoop *main_loop; ANativeWindow *native_window; - gboolean playing; + gboolean state; gint64 position; gint64 duration; GstElement *vsink; @@ -103,7 +103,7 @@ static gboolean refresh_ui (CustomData *data) { gint64 current = -1; /* We do not want to update anything unless we have a working pipeline in the PLAYING state */ - if (!data || !data->pipeline || !data->playing) + if (!data || !data->pipeline || data->state != GST_STATE_PLAYING) return TRUE; /* If we didn't know it yet, query the stream duration */ @@ -152,8 +152,8 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { set_message (gst_element_state_get_name (new_state), data); - data->playing = (new_state == GST_STATE_PLAYING); - if (data->playing && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { + data->state = new_state; + if (data->state == GST_STATE_PLAYING && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { execute_seek (data->desired_position, data); data->desired_position = GST_CLOCK_TIME_NONE; } @@ -205,9 +205,9 @@ static void *app_function (void *userdata) { // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); // data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); - data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); -// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); + data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); @@ -286,7 +286,7 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); gint64 desired_position = (gint64)(milliseconds * GST_SECOND / 1000); - if (data->playing) { + if (data->state == GST_STATE_PLAYING || data->state == GST_STATE_PAUSED) { execute_seek(desired_position, data); } else { GST_DEBUG ("Scheduling seek to %d milliseconds for later", milliseconds); diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index cffcf91f30..a344b75063 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -28,9 +28,10 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -public class Tutorial1 extends Activity implements SurfaceHolder.Callback { +public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSeekBarChangeListener { private native void nativeInit(); private native void nativeFinalize(); private native void nativePlay(); @@ -73,6 +74,9 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { SurfaceHolder sh = sv.getHolder(); sh.addCallback(this); + SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); + sb.setOnSeekBarChangeListener(this); + nativeInit(); playing = savedInstanceState==null ? false : savedInstanceState.getBoolean("playing"); @@ -143,4 +147,17 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback { Log.d("GStreamer", "Surface destroyed"); nativeSurfaceFinalize (); } + + public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) { + if (fromUser == false) return; + nativeSetPosition(progress); + } + + public void onStartTrackingTouch(SeekBar sb) { + nativePause(); + } + + public void onStopTrackingTouch(SeekBar sb) { + if (playing) nativePlay(); + } } From 425a23ef98182ef2903e41fdd56eed8bf1e0371b Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 12:53:53 +0200 Subject: [PATCH 39/90] Seeking in PAUSED updates the video --- .../android-tutorial-1/jni/tutorial-1.c | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 0570a704e8..92becffffb 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -160,33 +160,48 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } } +static void render_buffer (GstBuffer *buffer, CustomData *data) { + if (data->native_window) { + int i; + ANativeWindow_Buffer nbuff; + GstStructure *str; + gint width, height; + + str = gst_caps_get_structure (GST_BUFFER_CAPS (buffer), 0); + gst_structure_get_int (str, "width", &width); + gst_structure_get_int (str, "height", &height); + + ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); + + if (ANativeWindow_lock(data->native_window, &nbuff, NULL) < 0) { + GST_ERROR ("Unable to lock Native Window, discarding buffer."); + } else { + for (i=0; inative_window); + } + } +} + static void new_buffer (GstElement *sink, CustomData *data) { GstBuffer *buffer; /* Retrieve the buffer */ g_signal_emit_by_name (sink, "pull-buffer", &buffer); if (buffer) { - if (data->native_window) { - int i; - ANativeWindow_Buffer nbuff; - GstStructure *str; - gint width, height; + render_buffer (buffer, data); + gst_buffer_unref (buffer); + } +} - str = gst_caps_get_structure (GST_BUFFER_CAPS (buffer), 0); - gst_structure_get_int (str, "width", &width); - gst_structure_get_int (str, "height", &height); - - ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); - - if (ANativeWindow_lock(data->native_window, &nbuff, NULL) < 0) { - GST_ERROR ("Unable to lock Native Window, discarding buffer."); - } else { - for (i=0; inative_window); - } - } +static void new_preroll_buffer (GstElement *sink, CustomData *data) { + GstBuffer *buffer; + + /* Retrieve the preroll buffer */ + g_signal_emit_by_name (sink, "pull-preroll", &buffer); + if (buffer) { + render_buffer (buffer, data); gst_buffer_unref (buffer); } } @@ -211,6 +226,7 @@ static void *app_function (void *userdata) { data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); + g_signal_connect (data->vsink, "new-preroll", G_CALLBACK (new_preroll_buffer), data); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); From 0b6448389a50c87b78841f1fbe5ff1f91bd9ba10 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 12:59:33 +0200 Subject: [PATCH 40/90] Allow refreshing the ui (the timer, basically) when in PAUSED (when seeking, basically) --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 92becffffb..70c1662ab4 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -102,8 +102,8 @@ static gboolean refresh_ui (CustomData *data) { GstFormat fmt = GST_FORMAT_TIME; gint64 current = -1; - /* We do not want to update anything unless we have a working pipeline in the PLAYING state */ - if (!data || !data->pipeline || data->state != GST_STATE_PLAYING) + /* We do not want to update anything unless we have a working pipeline in the PAUSED or PLAYING state */ + if (!data || !data->pipeline || data->state < GST_STATE_PAUSED) return TRUE; /* If we didn't know it yet, query the stream duration */ From 392705a913ed602808704046b5434e623b89357d Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 13:31:24 +0200 Subject: [PATCH 41/90] Do not set the pipeline to NULL on EOS, as parse_launch pipelines are not reusable. --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 70c1662ab4..573212c76f 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -144,7 +144,8 @@ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { set_message (GST_MESSAGE_TYPE_NAME (msg), data); refresh_ui (data); - gst_element_set_state (data->pipeline, GST_STATE_NULL); + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + execute_seek (0, data); } static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { From 4874f001449003fdf5aa70c8f5ae822bbadd7031 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 13:48:08 +0200 Subject: [PATCH 42/90] Start in PAUSED so clip length is shown since the beginning. Allow orientation changes in PAUSED. --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 5 ++++- .../com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 10 ++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 573212c76f..038699a48c 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -154,7 +154,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { set_message (gst_element_state_get_name (new_state), data); data->state = new_state; - if (data->state == GST_STATE_PLAYING && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { + if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { execute_seek (data->desired_position, data); data->desired_position = GST_CLOCK_TIME_NONE; } @@ -240,6 +240,9 @@ static void *app_function (void *userdata) { /* Register a function that GLib will call every second */ timeout_source_id = g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); + /* Set state to PAUSE, so preroll occurrs and retrieve some information like clip length */ + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop... (CustomData:%p)", data); data->main_loop = g_main_loop_new (NULL, FALSE); diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index a344b75063..e82055a7bb 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -79,12 +79,14 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee nativeInit(); - playing = savedInstanceState==null ? false : savedInstanceState.getBoolean("playing"); - if (playing) { + if (savedInstanceState != null) { + playing = savedInstanceState.getBoolean("playing"); int milliseconds = savedInstanceState.getInt("position"); - Log.i ("GStreamer", "Restoring to playing state at " + milliseconds + " ms."); - nativePlay(); + Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); nativeSetPosition(milliseconds); + if (playing) { + nativePlay(); + } } } From bb2adae455713e91c8b4f17ff86da9041a3b5298 Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Mon, 17 Sep 2012 16:24:50 +0200 Subject: [PATCH 43/90] Update for multilib --- .../project.pbxproj | 1177 ----------------- .../contents.xcworkspacedata | 7 - .../project.pbxproj | 140 +- .../contents.xcworkspacedata | 0 4 files changed, 36 insertions(+), 1288 deletions(-) delete mode 100644 gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.pbxproj delete mode 100644 gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename gst-sdk/tutorials/xcode/{GStreamer Tutorials x86.xcodeproj => GStreamer Tutorials.xcodeproj}/project.pbxproj (87%) rename gst-sdk/tutorials/xcode/{GStreamer Tutorials x86.xcodeproj => GStreamer Tutorials.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) diff --git a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.pbxproj b/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.pbxproj deleted file mode 100644 index 8fcc1e7bd8..0000000000 --- a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1177 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 63118C62156D2AF10085CF03 /* basic-tutorial-3.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118C60156D2AA70085CF03 /* basic-tutorial-3.c */; }; - 63118C81156D2BAE0085CF03 /* basic-tutorial-4.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118C7F156D2BA30085CF03 /* basic-tutorial-4.c */; }; - 63118C93156D2D630085CF03 /* basic-tutorial-1.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118C92156D2D630085CF03 /* basic-tutorial-1.c */; }; - 63118CA3156D2E400085CF03 /* basic-tutorial-5.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118CA2156D2E400085CF03 /* basic-tutorial-5.c */; }; - 63118CC3156D31300085CF03 /* basic-tutorial-2.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118C4D156D29530085CF03 /* basic-tutorial-2.c */; }; - 63118CD4156D33040085CF03 /* playback-tutorial-1.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118CD2156D32FE0085CF03 /* playback-tutorial-1.c */; }; - 63118CE5156D35610085CF03 /* playback-tutorial-2.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118CE3156D35390085CF03 /* playback-tutorial-2.c */; }; - 63118CF6156D3ACB0085CF03 /* basic-tutorial-6.c in Sources */ = {isa = PBXBuildFile; fileRef = 63118CF4156D3AB60085CF03 /* basic-tutorial-6.c */; }; - 63DE883E156DAC18006F2D3B /* basic-tutorial-7.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE8838156DAC09006F2D3B /* basic-tutorial-7.c */; }; - 63DE883F156DAC1D006F2D3B /* basic-tutorial-8.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE883A156DAC0E006F2D3B /* basic-tutorial-8.c */; }; - 63DE8840156DAC21006F2D3B /* basic-tutorial-9.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE883C156DAC15006F2D3B /* basic-tutorial-9.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 63118C52156D29DE0085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118C73156D2B970085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118C86156D2D190085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118C96156D2E2F0085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118CB7156D31240085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118CC6156D32E20085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118CD7156D34BA0085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63118CE8156D3A870085CF03 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63DE8810156DABDF006F2D3B /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63DE881E156DABE6006F2D3B /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 63DE882C156DABEE006F2D3B /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 63118C4D156D29530085CF03 /* basic-tutorial-2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-2.c"; path = "../basic-tutorial-2.c"; sourceTree = SOURCE_ROOT; }; - 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86_64/share/xcode/gstreamer-0.10.xcconfig"; sourceTree = ""; }; - 63118C54156D29DE0085CF03 /* Turorial 3 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Turorial 3"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118C60156D2AA70085CF03 /* basic-tutorial-3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-3.c"; path = "../basic-tutorial-3.c"; sourceTree = SOURCE_ROOT; }; - 63118C75156D2B970085CF03 /* Tutorial 4 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 4"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118C7F156D2BA30085CF03 /* basic-tutorial-4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-4.c"; path = "../basic-tutorial-4.c"; sourceTree = SOURCE_ROOT; }; - 63118C88156D2D190085CF03 /* Tutorial 1 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 1"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118C92156D2D630085CF03 /* basic-tutorial-1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-1.c"; path = "../basic-tutorial-1.c"; sourceTree = SOURCE_ROOT; }; - 63118C98156D2E2F0085CF03 /* Tutorial 5 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 5"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118CA2156D2E400085CF03 /* basic-tutorial-5.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; name = "basic-tutorial-5.c"; path = "../basic-tutorial-5.c"; sourceTree = SOURCE_ROOT; }; - 63118CA4156D2EAC0085CF03 /* gstreamer-0.10-gtk+-2.0.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10-gtk+-2.0.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86_64/share/xcode/gstreamer-0.10-gtk+-2.0.xcconfig"; sourceTree = ""; }; - 63118CB9156D31240085CF03 /* Tutorial 2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 2"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118CC8156D32E20085CF03 /* Playback Tutorial 1 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Playback Tutorial 1"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118CD2156D32FE0085CF03 /* playback-tutorial-1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "playback-tutorial-1.c"; path = "../playback-tutorial-1.c"; sourceTree = SOURCE_ROOT; }; - 63118CD9156D34BA0085CF03 /* Playback Tutorial 2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Playback Tutorial 2"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118CE3156D35390085CF03 /* playback-tutorial-2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "playback-tutorial-2.c"; path = "../playback-tutorial-2.c"; sourceTree = SOURCE_ROOT; }; - 63118CEA156D3A870085CF03 /* Tutorial 6 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 6"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63118CF4156D3AB60085CF03 /* basic-tutorial-6.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-6.c"; path = "../basic-tutorial-6.c"; sourceTree = SOURCE_ROOT; }; - 63DE8812156DABDF006F2D3B /* Tutorial 7 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 7"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63DE8820156DABE6006F2D3B /* Tutorial 8 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 8"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63DE882E156DABEE006F2D3B /* Tutorial 9 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Tutorial 9"; sourceTree = BUILT_PRODUCTS_DIR; }; - 63DE8838156DAC09006F2D3B /* basic-tutorial-7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-7.c"; path = "../basic-tutorial-7.c"; sourceTree = SOURCE_ROOT; }; - 63DE883A156DAC0E006F2D3B /* basic-tutorial-8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-8.c"; path = "../basic-tutorial-8.c"; sourceTree = SOURCE_ROOT; }; - 63DE883C156DAC15006F2D3B /* basic-tutorial-9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-9.c"; path = "../basic-tutorial-9.c"; sourceTree = SOURCE_ROOT; }; - 63DE8841156DACB3006F2D3B /* gstreamer-0.10-all.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10-all.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86_64/share/xcode/gstreamer-0.10-all.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 63118C51156D29DE0085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C72156D2B970085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C85156D2D190085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C95156D2E2F0085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CB6156D31240085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CC5156D32E20085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CD6156D34BA0085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CE7156D3A870085CF03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE880F156DABDF006F2D3B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE881D156DABE6006F2D3B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE882B156DABEE006F2D3B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 63118C35156D29340085CF03 = { - isa = PBXGroup; - children = ( - 63DE8841156DACB3006F2D3B /* gstreamer-0.10-all.xcconfig */, - 63118CA4156D2EAC0085CF03 /* gstreamer-0.10-gtk+-2.0.xcconfig */, - 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */, - 63118C8A156D2D190085CF03 /* Tutorial 1 */, - 63118C43156D29340085CF03 /* Tutorial 2 */, - 63118C56156D29DE0085CF03 /* Tutorial 3 */, - 63118C77156D2B970085CF03 /* Tutorial 4 */, - 63118C9A156D2E2F0085CF03 /* Tutorial 5 */, - 63118CEC156D3A870085CF03 /* Tutorial 6 */, - 63DE8814156DABDF006F2D3B /* Tutorial 7 */, - 63DE8822156DABE6006F2D3B /* Tutorial 8 */, - 63DE8830156DABEE006F2D3B /* Tutorial 9 */, - 63118CCA156D32E20085CF03 /* Playback Tutorial 1 */, - 63118CDB156D34BA0085CF03 /* Playback Tutorial 2 */, - 63118C41156D29340085CF03 /* Products */, - ); - sourceTree = ""; - }; - 63118C41156D29340085CF03 /* Products */ = { - isa = PBXGroup; - children = ( - 63118C54156D29DE0085CF03 /* Turorial 3 */, - 63118C75156D2B970085CF03 /* Tutorial 4 */, - 63118C88156D2D190085CF03 /* Tutorial 1 */, - 63118C98156D2E2F0085CF03 /* Tutorial 5 */, - 63118CB9156D31240085CF03 /* Tutorial 2 */, - 63118CC8156D32E20085CF03 /* Playback Tutorial 1 */, - 63118CD9156D34BA0085CF03 /* Playback Tutorial 2 */, - 63118CEA156D3A870085CF03 /* Tutorial 6 */, - 63DE8812156DABDF006F2D3B /* Tutorial 7 */, - 63DE8820156DABE6006F2D3B /* Tutorial 8 */, - 63DE882E156DABEE006F2D3B /* Tutorial 9 */, - ); - name = Products; - sourceTree = SOURCE_ROOT; - }; - 63118C43156D29340085CF03 /* Tutorial 2 */ = { - isa = PBXGroup; - children = ( - 63118C4D156D29530085CF03 /* basic-tutorial-2.c */, - ); - name = "Tutorial 2"; - path = "GStreamer Tutorials"; - sourceTree = SOURCE_ROOT; - }; - 63118C56156D29DE0085CF03 /* Tutorial 3 */ = { - isa = PBXGroup; - children = ( - 63118C60156D2AA70085CF03 /* basic-tutorial-3.c */, - ); - name = "Tutorial 3"; - path = Turorial3; - sourceTree = SOURCE_ROOT; - }; - 63118C77156D2B970085CF03 /* Tutorial 4 */ = { - isa = PBXGroup; - children = ( - 63118C7F156D2BA30085CF03 /* basic-tutorial-4.c */, - ); - path = "Tutorial 4"; - sourceTree = ""; - }; - 63118C8A156D2D190085CF03 /* Tutorial 1 */ = { - isa = PBXGroup; - children = ( - 63118C92156D2D630085CF03 /* basic-tutorial-1.c */, - ); - path = "Tutorial 1"; - sourceTree = ""; - }; - 63118C9A156D2E2F0085CF03 /* Tutorial 5 */ = { - isa = PBXGroup; - children = ( - 63118CA2156D2E400085CF03 /* basic-tutorial-5.c */, - ); - path = "Tutorial 5"; - sourceTree = ""; - }; - 63118CCA156D32E20085CF03 /* Playback Tutorial 1 */ = { - isa = PBXGroup; - children = ( - 63118CD2156D32FE0085CF03 /* playback-tutorial-1.c */, - ); - path = "Playback Tutorial 1"; - sourceTree = ""; - }; - 63118CDB156D34BA0085CF03 /* Playback Tutorial 2 */ = { - isa = PBXGroup; - children = ( - 63118CE3156D35390085CF03 /* playback-tutorial-2.c */, - ); - path = "Playback Tutorial 2"; - sourceTree = ""; - }; - 63118CEC156D3A870085CF03 /* Tutorial 6 */ = { - isa = PBXGroup; - children = ( - 63118CF4156D3AB60085CF03 /* basic-tutorial-6.c */, - ); - path = "Tutorial 6"; - sourceTree = ""; - }; - 63DE8814156DABDF006F2D3B /* Tutorial 7 */ = { - isa = PBXGroup; - children = ( - 63DE8838156DAC09006F2D3B /* basic-tutorial-7.c */, - ); - path = "Tutorial 7"; - sourceTree = ""; - }; - 63DE8822156DABE6006F2D3B /* Tutorial 8 */ = { - isa = PBXGroup; - children = ( - 63DE883A156DAC0E006F2D3B /* basic-tutorial-8.c */, - ); - path = "Tutorial 8"; - sourceTree = ""; - }; - 63DE8830156DABEE006F2D3B /* Tutorial 9 */ = { - isa = PBXGroup; - children = ( - 63DE883C156DAC15006F2D3B /* basic-tutorial-9.c */, - ); - path = "Tutorial 9"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 63118C53156D29DE0085CF03 /* Turorial 3 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118C5B156D29DE0085CF03 /* Build configuration list for PBXNativeTarget "Turorial 3" */; - buildPhases = ( - 63118C50156D29DE0085CF03 /* Sources */, - 63118C51156D29DE0085CF03 /* Frameworks */, - 63118C52156D29DE0085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Turorial 3"; - productName = Turorial3; - productReference = 63118C54156D29DE0085CF03 /* Turorial 3 */; - productType = "com.apple.product-type.tool"; - }; - 63118C74156D2B970085CF03 /* Tutorial 4 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118C7C156D2B970085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 4" */; - buildPhases = ( - 63118C71156D2B970085CF03 /* Sources */, - 63118C72156D2B970085CF03 /* Frameworks */, - 63118C73156D2B970085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 4"; - productName = "Tutorial 4"; - productReference = 63118C75156D2B970085CF03 /* Tutorial 4 */; - productType = "com.apple.product-type.tool"; - }; - 63118C87156D2D190085CF03 /* Tutorial 1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118C8F156D2D190085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 1" */; - buildPhases = ( - 63118C84156D2D190085CF03 /* Sources */, - 63118C85156D2D190085CF03 /* Frameworks */, - 63118C86156D2D190085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 1"; - productName = "Tutorial 1"; - productReference = 63118C88156D2D190085CF03 /* Tutorial 1 */; - productType = "com.apple.product-type.tool"; - }; - 63118C97156D2E2F0085CF03 /* Tutorial 5 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118C9F156D2E2F0085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 5" */; - buildPhases = ( - 63118C94156D2E2F0085CF03 /* Sources */, - 63118C95156D2E2F0085CF03 /* Frameworks */, - 63118C96156D2E2F0085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 5"; - productName = "Tutorial 5"; - productReference = 63118C98156D2E2F0085CF03 /* Tutorial 5 */; - productType = "com.apple.product-type.tool"; - }; - 63118CB8156D31240085CF03 /* Tutorial 2 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118CC0156D31240085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 2" */; - buildPhases = ( - 63118CB5156D31240085CF03 /* Sources */, - 63118CB6156D31240085CF03 /* Frameworks */, - 63118CB7156D31240085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 2"; - productName = "Tutorial 2"; - productReference = 63118CB9156D31240085CF03 /* Tutorial 2 */; - productType = "com.apple.product-type.tool"; - }; - 63118CC7156D32E20085CF03 /* Playback Tutorial 1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118CCF156D32E20085CF03 /* Build configuration list for PBXNativeTarget "Playback Tutorial 1" */; - buildPhases = ( - 63118CC4156D32E20085CF03 /* Sources */, - 63118CC5156D32E20085CF03 /* Frameworks */, - 63118CC6156D32E20085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Playback Tutorial 1"; - productName = "Playback Tutorial 1"; - productReference = 63118CC8156D32E20085CF03 /* Playback Tutorial 1 */; - productType = "com.apple.product-type.tool"; - }; - 63118CD8156D34BA0085CF03 /* Playback Tutorial 2 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118CE0156D34BA0085CF03 /* Build configuration list for PBXNativeTarget "Playback Tutorial 2" */; - buildPhases = ( - 63118CD5156D34BA0085CF03 /* Sources */, - 63118CD6156D34BA0085CF03 /* Frameworks */, - 63118CD7156D34BA0085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Playback Tutorial 2"; - productName = "Playback Tutorial 2"; - productReference = 63118CD9156D34BA0085CF03 /* Playback Tutorial 2 */; - productType = "com.apple.product-type.tool"; - }; - 63118CE9156D3A870085CF03 /* Tutorial 6 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63118CF1156D3A870085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 6" */; - buildPhases = ( - 63118CE6156D3A870085CF03 /* Sources */, - 63118CE7156D3A870085CF03 /* Frameworks */, - 63118CE8156D3A870085CF03 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 6"; - productName = "Tutorial 6"; - productReference = 63118CEA156D3A870085CF03 /* Tutorial 6 */; - productType = "com.apple.product-type.tool"; - }; - 63DE8811156DABDF006F2D3B /* Tutorial 7 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63DE8819156DABDF006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 7" */; - buildPhases = ( - 63DE880E156DABDF006F2D3B /* Sources */, - 63DE880F156DABDF006F2D3B /* Frameworks */, - 63DE8810156DABDF006F2D3B /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 7"; - productName = "Tutorial 7"; - productReference = 63DE8812156DABDF006F2D3B /* Tutorial 7 */; - productType = "com.apple.product-type.tool"; - }; - 63DE881F156DABE6006F2D3B /* Tutorial 8 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63DE8827156DABE7006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 8" */; - buildPhases = ( - 63DE881C156DABE6006F2D3B /* Sources */, - 63DE881D156DABE6006F2D3B /* Frameworks */, - 63DE881E156DABE6006F2D3B /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 8"; - productName = "Tutorial 8"; - productReference = 63DE8820156DABE6006F2D3B /* Tutorial 8 */; - productType = "com.apple.product-type.tool"; - }; - 63DE882D156DABEE006F2D3B /* Tutorial 9 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 63DE8835156DABEE006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 9" */; - buildPhases = ( - 63DE882A156DABEE006F2D3B /* Sources */, - 63DE882B156DABEE006F2D3B /* Frameworks */, - 63DE882C156DABEE006F2D3B /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 9"; - productName = "Tutorial 9"; - productReference = 63DE882E156DABEE006F2D3B /* Tutorial 9 */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 63118C37156D29340085CF03 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0420; - }; - buildConfigurationList = 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials x86_64" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 63118C35156D29340085CF03; - productRefGroup = 63118C41156D29340085CF03 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 63118C53156D29DE0085CF03 /* Turorial 3 */, - 63118C74156D2B970085CF03 /* Tutorial 4 */, - 63118C87156D2D190085CF03 /* Tutorial 1 */, - 63118C97156D2E2F0085CF03 /* Tutorial 5 */, - 63118CB8156D31240085CF03 /* Tutorial 2 */, - 63118CC7156D32E20085CF03 /* Playback Tutorial 1 */, - 63118CD8156D34BA0085CF03 /* Playback Tutorial 2 */, - 63118CE9156D3A870085CF03 /* Tutorial 6 */, - 63DE8811156DABDF006F2D3B /* Tutorial 7 */, - 63DE881F156DABE6006F2D3B /* Tutorial 8 */, - 63DE882D156DABEE006F2D3B /* Tutorial 9 */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 63118C50156D29DE0085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118C62156D2AF10085CF03 /* basic-tutorial-3.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C71156D2B970085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118C81156D2BAE0085CF03 /* basic-tutorial-4.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C84156D2D190085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118C93156D2D630085CF03 /* basic-tutorial-1.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118C94156D2E2F0085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118CA3156D2E400085CF03 /* basic-tutorial-5.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CB5156D31240085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118CC3156D31300085CF03 /* basic-tutorial-2.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CC4156D32E20085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118CD4156D33040085CF03 /* playback-tutorial-1.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CD5156D34BA0085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118CE5156D35610085CF03 /* playback-tutorial-2.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63118CE6156D3A870085CF03 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63118CF6156D3ACB0085CF03 /* basic-tutorial-6.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE880E156DABDF006F2D3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63DE883E156DAC18006F2D3B /* basic-tutorial-7.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE881C156DABE6006F2D3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63DE883F156DAC1D006F2D3B /* basic-tutorial-8.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 63DE882A156DABEE006F2D3B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63DE8840156DAC21006F2D3B /* basic-tutorial-9.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 63118C48156D29340085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - VALID_ARCHS = x86_64; - }; - name = Debug; - }; - 63118C49156D29340085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; - SDKROOT = macosx; - VALID_ARCHS = x86_64; - }; - name = Release; - }; - 63118C5C156D29DE0085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118C5D156D29DE0085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118C7D156D2B970085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118C7E156D2B970085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118C90156D2D190085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118C91156D2D190085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118CA0156D2E2F0085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118CA4156D2EAC0085CF03 /* gstreamer-0.10-gtk+-2.0.xcconfig */; - buildSettings = { - OTHER_LDFLAGS = ( - "-framework", - Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_LDFLAGS = ( - "-framework", - Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstphotography-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", - ); - }; - name = Debug; - }; - 63118CA1156D2E2F0085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118CA4156D2EAC0085CF03 /* gstreamer-0.10-gtk+-2.0.xcconfig */; - buildSettings = { - OTHER_LDFLAGS = ( - "-framework", - Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - WARNING_LDFLAGS = ( - "-framework", - Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstphotography-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", - ); - }; - name = Release; - }; - 63118CC1156D31240085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118CC2156D31240085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118CD0156D32E20085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118CD1156D32E20085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118CE1156D34BA0085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118CE2156D34BA0085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63118CF2156D3A870085CF03 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63118CF3156D3A870085CF03 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63DE881A156DABDF006F2D3B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63DE881B156DABDF006F2D3B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63DE8828156DABE7006F2D3B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63DE8829156DABE7006F2D3B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63118C4F156D297B0085CF03 /* gstreamer-0.10.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 63DE8836156DABEE006F2D3B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8841156DACB3006F2D3B /* gstreamer-0.10-all.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 63DE8837156DABEE006F2D3B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8841156DACB3006F2D3B /* gstreamer-0.10-all.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials x86_64" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118C48156D29340085CF03 /* Debug */, - 63118C49156D29340085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118C5B156D29DE0085CF03 /* Build configuration list for PBXNativeTarget "Turorial 3" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118C5C156D29DE0085CF03 /* Debug */, - 63118C5D156D29DE0085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118C7C156D2B970085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 4" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118C7D156D2B970085CF03 /* Debug */, - 63118C7E156D2B970085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118C8F156D2D190085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118C90156D2D190085CF03 /* Debug */, - 63118C91156D2D190085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118C9F156D2E2F0085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 5" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118CA0156D2E2F0085CF03 /* Debug */, - 63118CA1156D2E2F0085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118CC0156D31240085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 2" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118CC1156D31240085CF03 /* Debug */, - 63118CC2156D31240085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118CCF156D32E20085CF03 /* Build configuration list for PBXNativeTarget "Playback Tutorial 1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118CD0156D32E20085CF03 /* Debug */, - 63118CD1156D32E20085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118CE0156D34BA0085CF03 /* Build configuration list for PBXNativeTarget "Playback Tutorial 2" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118CE1156D34BA0085CF03 /* Debug */, - 63118CE2156D34BA0085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63118CF1156D3A870085CF03 /* Build configuration list for PBXNativeTarget "Tutorial 6" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63118CF2156D3A870085CF03 /* Debug */, - 63118CF3156D3A870085CF03 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63DE8819156DABDF006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 7" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63DE881A156DABDF006F2D3B /* Debug */, - 63DE881B156DABDF006F2D3B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63DE8827156DABE7006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 8" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63DE8828156DABE7006F2D3B /* Debug */, - 63DE8829156DABE7006F2D3B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 63DE8835156DABEE006F2D3B /* Build configuration list for PBXNativeTarget "Tutorial 9" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 63DE8836156DABEE006F2D3B /* Debug */, - 63DE8837156DABEE006F2D3B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 63118C37156D29340085CF03 /* Project object */; -} diff --git a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 98cf3a3b7a..0000000000 --- a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86_64.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86.xcodeproj/project.pbxproj b/gst-sdk/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj similarity index 87% rename from gst-sdk/tutorials/xcode/GStreamer Tutorials x86.xcodeproj/project.pbxproj rename to gst-sdk/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj index cc362754db..c864446cae 100644 --- a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86.xcodeproj/project.pbxproj +++ b/gst-sdk/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj @@ -18,6 +18,17 @@ 63DE883E156DAC18006F2D3B /* basic-tutorial-7.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE8838156DAC09006F2D3B /* basic-tutorial-7.c */; }; 63DE883F156DAC1D006F2D3B /* basic-tutorial-8.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE883A156DAC0E006F2D3B /* basic-tutorial-8.c */; }; 63DE8840156DAC21006F2D3B /* basic-tutorial-9.c in Sources */ = {isa = PBXBuildFile; fileRef = 63DE883C156DAC15006F2D3B /* basic-tutorial-9.c */; }; + 63E2230116073E04001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230216075DFC001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230316075E05001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230416075E24001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230616075E34001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230716075E3A001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230816075E41001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230916075E48001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230A16075E4F001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230B16075E55001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; + 63E2230C16076969001954D7 /* GStreamer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E2230016073E04001954D7 /* GStreamer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -145,9 +156,7 @@ 63DE8838156DAC09006F2D3B /* basic-tutorial-7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-7.c"; path = "../basic-tutorial-7.c"; sourceTree = SOURCE_ROOT; }; 63DE883A156DAC0E006F2D3B /* basic-tutorial-8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-8.c"; path = "../basic-tutorial-8.c"; sourceTree = SOURCE_ROOT; }; 63DE883C156DAC15006F2D3B /* basic-tutorial-9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "basic-tutorial-9.c"; path = "../basic-tutorial-9.c"; sourceTree = SOURCE_ROOT; }; - 63DE8851156DAE94006F2D3B /* gstreamer-0.10-all.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10-all.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86/share/xcode/gstreamer-0.10-all.xcconfig"; sourceTree = ""; }; - 63DE8852156DAE94006F2D3B /* gstreamer-0.10-gtk+-2.0.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10-gtk+-2.0.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86/share/xcode/gstreamer-0.10-gtk+-2.0.xcconfig"; sourceTree = ""; }; - 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "gstreamer-0.10.xcconfig"; path = "/Library/Frameworks/GStreamer.framework/Versions/2012.5/x86/share/xcode/gstreamer-0.10.xcconfig"; sourceTree = ""; }; + 63E2230016073E04001954D7 /* GStreamer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GStreamer.framework; path = Library/Frameworks/GStreamer.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -155,6 +164,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230316075E05001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -162,6 +172,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230416075E24001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -169,6 +180,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230116073E04001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -176,6 +188,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230C16076969001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -183,6 +196,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230216075DFC001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -190,6 +204,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230B16075E55001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -197,6 +212,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230A16075E4F001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -204,6 +220,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230616075E34001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -211,6 +228,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230716075E3A001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -218,6 +236,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230816075E41001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -225,6 +244,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 63E2230916075E48001954D7 /* GStreamer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -234,9 +254,7 @@ 63118C35156D29340085CF03 = { isa = PBXGroup; children = ( - 63DE8851156DAE94006F2D3B /* gstreamer-0.10-all.xcconfig */, - 63DE8852156DAE94006F2D3B /* gstreamer-0.10-gtk+-2.0.xcconfig */, - 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */, + 63E2230016073E04001954D7 /* GStreamer.framework */, 63118C8A156D2D190085CF03 /* Tutorial 1 */, 63118C43156D29340085CF03 /* Tutorial 2 */, 63118C56156D29DE0085CF03 /* Tutorial 3 */, @@ -558,7 +576,7 @@ attributes = { LastUpgradeCheck = 0420; }; - buildConfigurationList = 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials x86" */; + buildConfigurationList = 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -681,8 +699,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = NO; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -698,10 +716,11 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "/Library/Frameworks/GStreamer.framework/Versions/0.10/Headers/**"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx10.7; - VALID_ARCHS = i386; + SDKROOT = macosx10.6; + VALID_ARCHS = "x86_64 i386"; }; name = Debug; }; @@ -709,8 +728,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = NO; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -720,15 +739,15 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = "/Library/Frameworks/GStreamer.framework/Versions/0.10/Headers/**"; MACOSX_DEPLOYMENT_TARGET = 10.6; - SDKROOT = macosx10.7; - VALID_ARCHS = i386; + SDKROOT = macosx10.6; + VALID_ARCHS = "x86_64 i386"; }; name = Release; }; 63118C5C156D29DE0085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -736,7 +755,6 @@ }; 63118C5D156D29DE0085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -744,7 +762,6 @@ }; 63118C7D156D2B970085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -752,7 +769,6 @@ }; 63118C7E156D2B970085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -760,7 +776,6 @@ }; 63118C90156D2D190085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -768,7 +783,6 @@ }; 63118C91156D2D190085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -776,44 +790,10 @@ }; 63118CA0156D2E2F0085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8852156DAE94006F2D3B /* gstreamer-0.10-gtk+-2.0.xcconfig */; buildSettings = { OTHER_LDFLAGS = ( "-framework", Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", ); PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -821,44 +801,10 @@ }; 63118CA1156D2E2F0085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8852156DAE94006F2D3B /* gstreamer-0.10-gtk+-2.0.xcconfig */; buildSettings = { OTHER_LDFLAGS = ( "-framework", Cocoa, - "-lgstpbutils-0.10", - "-lgstnetbuffer-0.10", - "-lgstvideo-0.10", - "-lgstriff-0.10", - "-lgstcheck-0.10", - "-lgstaudio-0.10", - "-lgstcontroller-0.10", - "-lgstdataprotocol-0.10", - "-lgstrtp-0.10", - "-lgstinterfaces-0.10", - "-lgstnet-0.10", - "-lgstcdda-0.10", - "-lgsttag-0.10", - "-lgstapp-0.10", - "-lgstrtsp-0.10", - "-lgstsdp-0.10", - "-lgstbase-0.10", - "-lgstfft-0.10", - "-lgstreamer-0.10", - "-lgthread-2.0", - "-lxml2", - "-lgtk-quartz-2.0", - "-lgdk-quartz-2.0", - "-latk-1.0", - "-lgio-2.0", - "-lpangocairo-1.0", - "-lgdk_pixbuf-2.0", - "-lpango-1.0", - "-lcairo", - "-lgmodule-2.0", - "-lgobject-2.0", - "-lglib-2.0", - "-lintl", ); PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -866,7 +812,6 @@ }; 63118CC1156D31240085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -874,7 +819,6 @@ }; 63118CC2156D31240085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -882,7 +826,6 @@ }; 63118CD0156D32E20085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -890,7 +833,6 @@ }; 63118CD1156D32E20085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -898,7 +840,6 @@ }; 63118CE1156D34BA0085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -906,7 +847,6 @@ }; 63118CE2156D34BA0085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -914,7 +854,6 @@ }; 63118CF2156D3A870085CF03 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -922,7 +861,6 @@ }; 63118CF3156D3A870085CF03 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -930,7 +868,6 @@ }; 63DE881A156DABDF006F2D3B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -939,7 +876,6 @@ }; 63DE881B156DABDF006F2D3B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -948,7 +884,6 @@ }; 63DE8828156DABE7006F2D3B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -957,7 +892,6 @@ }; 63DE8829156DABE7006F2D3B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8853156DAE94006F2D3B /* gstreamer-0.10.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -966,7 +900,6 @@ }; 63DE8836156DABEE006F2D3B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8851156DAE94006F2D3B /* gstreamer-0.10-all.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -975,7 +908,6 @@ }; 63DE8837156DABEE006F2D3B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 63DE8851156DAE94006F2D3B /* gstreamer-0.10-all.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -985,7 +917,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials x86" */ = { + 63118C3A156D29340085CF03 /* Build configuration list for PBXProject "GStreamer Tutorials" */ = { isa = XCConfigurationList; buildConfigurations = ( 63118C48156D29340085CF03 /* Debug */, diff --git a/gst-sdk/tutorials/xcode/GStreamer Tutorials x86.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/gst-sdk/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from gst-sdk/tutorials/xcode/GStreamer Tutorials x86.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to gst-sdk/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata From e1927aca1478edc8cf14a5d9da6a42ca0262b476 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 17:24:04 +0200 Subject: [PATCH 44/90] Typo in comment --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 038699a48c..5b9a1ff7b7 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -273,7 +273,7 @@ void gst_native_init (JNIEnv* env, jobject thiz) { data->app = (*env)->NewGlobalRef (env, thiz); GST_DEBUG ("Created GlobalRef for app object at %p", data->app); pthread_create (&gst_app_thread, NULL, &app_function, data); - /* FIXME: Wait until thread has started and the main loop is runing */ + /* FIXME: Wait until thread has started and the main loop is running */ usleep (100000); } From 7a8142417cbf1852843f06d974c53206dfe293fe Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 17:35:32 +0200 Subject: [PATCH 45/90] Remove invalid extra unref on the gst bus --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 5b9a1ff7b7..1256f4ce38 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -255,7 +255,6 @@ static void *app_function (void *userdata) { g_source_destroy (timeout_source); /* Free resources */ - gst_object_unref (bus); gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->vsink); gst_object_unref (data->pipeline); From 44a46337d7e757fc031a06aa93bb0684495a8e6e Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 18:14:28 +0200 Subject: [PATCH 46/90] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cae038aa75..ef401313af 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ obj .classpath .project .settings +.libs From 803622382ead0e3fcc90a7d1b70635312ff63ca9 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 18:24:00 +0200 Subject: [PATCH 47/90] Prevent successive orientation changes from moving the clip backwards in time due to gst-nanos / java-millis rounding errors plus seeking to keyframes. --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index e82055a7bb..6a35e2e4fb 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -83,7 +83,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee playing = savedInstanceState.getBoolean("playing"); int milliseconds = savedInstanceState.getInt("position"); Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); - nativeSetPosition(milliseconds); + nativeSetPosition(milliseconds + 1); if (playing) { nativePlay(); } From 336a85b92894e2b7a00b4bf1c71d2b836c7d5cd4 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 17 Sep 2012 18:26:55 +0200 Subject: [PATCH 48/90] Add comment regarding previoud rounding. --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 6a35e2e4fb..97ad13c86e 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -83,6 +83,10 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee playing = savedInstanceState.getBoolean("playing"); int milliseconds = savedInstanceState.getInt("position"); Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); + /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the + * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind + * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe + * backwards on each iteration. */ nativeSetPosition(milliseconds + 1); if (playing) { nativePlay(); From 4b7b9e01069fb596977d2c0f9b657e33ae92ee81 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 11:55:46 +0200 Subject: [PATCH 49/90] Remove video app sink now that there is a working egl sink. --- .../android-tutorial-1/AndroidManifest.xml | 1 + .../android-tutorial-1/jni/tutorial-1.c | 60 ++----------------- 2 files changed, 6 insertions(+), 55 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml index 0d1f7f124b..6116ace012 100755 --- a/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/gst-sdk/tutorials/android-tutorial-1/AndroidManifest.xml @@ -5,6 +5,7 @@ android:versionName="1.0"> + diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 1256f4ce38..9d6a702aaa 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -161,52 +161,6 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } } -static void render_buffer (GstBuffer *buffer, CustomData *data) { - if (data->native_window) { - int i; - ANativeWindow_Buffer nbuff; - GstStructure *str; - gint width, height; - - str = gst_caps_get_structure (GST_BUFFER_CAPS (buffer), 0); - gst_structure_get_int (str, "width", &width); - gst_structure_get_int (str, "height", &height); - - ANativeWindow_setBuffersGeometry(data->native_window, width, height, WINDOW_FORMAT_RGBX_8888); - - if (ANativeWindow_lock(data->native_window, &nbuff, NULL) < 0) { - GST_ERROR ("Unable to lock Native Window, discarding buffer."); - } else { - for (i=0; inative_window); - } - } -} - -static void new_buffer (GstElement *sink, CustomData *data) { - GstBuffer *buffer; - - /* Retrieve the buffer */ - g_signal_emit_by_name (sink, "pull-buffer", &buffer); - if (buffer) { - render_buffer (buffer, data); - gst_buffer_unref (buffer); - } -} - -static void new_preroll_buffer (GstElement *sink, CustomData *data) { - GstBuffer *buffer; - - /* Retrieve the preroll buffer */ - g_signal_emit_by_name (sink, "pull-preroll", &buffer); - if (buffer) { - render_buffer (buffer, data); - gst_buffer_unref (buffer); - } -} - static void *app_function (void *userdata) { JavaVMAttachArgs args; GstBus *bus; @@ -218,16 +172,11 @@ static void *app_function (void *userdata) { GST_DEBUG ("Creating pipeline in CustomData at %p", data); // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); -// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! fakesink", NULL); -// data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280,width=(int)320,height=(int)240,framerate=(fraction)30/1", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); - data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! appsink name=vsink emit-signals=1 caps=video/x-raw-rgb,bpp=(int)32,endianness=(int)4321,depth=(int)24,red_mask=(int)-16777216,green_mask=(int)16711680,blue_mask=(int)65280", NULL); + data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); - g_signal_connect (data->vsink, "new-buffer", G_CALLBACK (new_buffer), data); - g_signal_connect (data->vsink, "new-preroll", G_CALLBACK (new_preroll_buffer), data); /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); @@ -241,7 +190,8 @@ static void *app_function (void *userdata) { timeout_source_id = g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); /* Set state to PAUSE, so preroll occurrs and retrieve some information like clip length */ - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + // This line is commented out until we can guarantee that the window handle is passed before the sink goes to READY + //gst_element_set_state (data->pipeline, GST_STATE_PAUSED); /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop... (CustomData:%p)", data); From 2048b11b904ed356eef3092a8ddd6eecf8fddd6b Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 12:09:49 +0200 Subject: [PATCH 50/90] Rename some methods for clarity --- .../tutorials/android-tutorial-1/jni/tutorial-1.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 9d6a702aaa..1420cb41e5 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -76,7 +76,7 @@ static JNIEnv *get_jni_env (void) { return env; } -static void set_message (const gchar *message, CustomData *data) { +static void set_ui_message (const gchar *message, CustomData *data) { JNIEnv *env = get_jni_env (); GST_DEBUG ("Setting message to: %s", message); jstring jmessage = (*env)->NewStringUTF(env, message); @@ -88,7 +88,7 @@ static void set_message (const gchar *message, CustomData *data) { (*env)->DeleteLocalRef (env, jmessage); } -static void set_current_position (gint position, gint duration, CustomData *data) { +static void set_current_ui_position (gint position, gint duration, CustomData *data) { JNIEnv *env = get_jni_env (); GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration); (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); @@ -115,7 +115,7 @@ static gboolean refresh_ui (CustomData *data) { if (gst_element_query_position (data->pipeline, &fmt, &data->position)) { /* Java expects these values in milliseconds, and Gst provides nanoseconds */ - set_current_position (data->position/1000000, data->duration/1000000, data); + set_current_ui_position (data->position/1000000, data->duration/1000000, data); } return TRUE; } @@ -136,13 +136,13 @@ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); g_clear_error (&err); g_free (debug_info); - set_message (message_string, data); + set_ui_message (message_string, data); g_free (message_string); gst_element_set_state (data->pipeline, GST_STATE_NULL); } static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - set_message (GST_MESSAGE_TYPE_NAME (msg), data); + set_ui_message (GST_MESSAGE_TYPE_NAME (msg), data); refresh_ui (data); gst_element_set_state (data->pipeline, GST_STATE_PAUSED); execute_seek (0, data); @@ -151,8 +151,9 @@ static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GstState old_state, new_state, pending_state; gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + /* Only pay attention to messages coming from the pipeline, not its children */ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { - set_message (gst_element_state_get_name (new_state), data); + set_ui_message (gst_element_state_get_name (new_state), data); data->state = new_state; if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { execute_seek (data->desired_position, data); From c763636b979e4f309c4183d973e6e3c4a07ae424 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 12:36:17 +0200 Subject: [PATCH 51/90] Add a bit of resilience at class initialization --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 9 +++++++-- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 1420cb41e5..f5c8334036 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -264,13 +264,18 @@ void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { } } -void gst_class_init (JNIEnv* env, jclass klass) { +jboolean gst_class_init (JNIEnv* env, jclass klass) { custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); GST_DEBUG ("The FieldID for the native_custom_data field is %p", custom_data_field_id); set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(II)V"); GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id); + if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id) { + GST_ERROR ("The calling class does not implement all necessary interface methods"); + return JNI_FALSE; + } + return JNI_TRUE; } void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { @@ -305,7 +310,7 @@ static JNINativeMethod native_methods[] = { { "nativePlay", "()V", (void *) gst_native_play}, { "nativePause", "()V", (void *) gst_native_pause}, { "nativeSetPosition", "(I)V", (void*) gst_native_set_position}, - { "classInit", "()V", (void *) gst_class_init}, + { "classInit", "()Z", (void *) gst_class_init}, { "nativeSurfaceInit", "(Ljava/lang/Object;)V", (void *) gst_native_surface_init}, { "nativeSurfaceFinalize", "()V", (void *) gst_native_surface_finalize} }; diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 97ad13c86e..7c2fe3bbbd 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -37,7 +37,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private native void nativePlay(); private native void nativePause(); private native void nativeSetPosition(int milliseconds); - private static native void classInit(); + private static native boolean classInit(); private native void nativeSurfaceInit(Object surface); private native void nativeSurfaceFinalize(); private long native_custom_data; From 5e065f2b8972899adfc54129bf5bc0c2ea562a7b Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 12:39:39 +0200 Subject: [PATCH 52/90] Beautify hardcoded time values --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index f5c8334036..ef1528fc5b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -115,14 +115,14 @@ static gboolean refresh_ui (CustomData *data) { if (gst_element_query_position (data->pipeline, &fmt, &data->position)) { /* Java expects these values in milliseconds, and Gst provides nanoseconds */ - set_current_ui_position (data->position/1000000, data->duration/1000000, data); + set_current_ui_position (data->position / GST_MSECOND, data->duration / GST_MSECOND, data); } return TRUE; } static void execute_seek (gint64 desired_position, CustomData *data) { gboolean res; - GST_DEBUG ("Setting position to %lld milliseconds", desired_position / 1000000); + GST_DEBUG ("Setting position to %lld milliseconds", desired_position / GST_MSECOND); res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); GST_DEBUG ("Seek returned %d", res); } @@ -255,7 +255,7 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - gint64 desired_position = (gint64)(milliseconds * GST_SECOND / 1000); + gint64 desired_position = (gint64)(milliseconds * GST_MSECOND); if (data->state == GST_STATE_PLAYING || data->state == GST_STATE_PAUSED) { execute_seek(desired_position, data); } else { From e35be6e5df9ffe64f4ecc2d000fae8e651262a94 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 13:40:22 +0200 Subject: [PATCH 53/90] Remove unused variable --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index ef1528fc5b..01ae13ed0c 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -317,7 +317,6 @@ static JNINativeMethod native_methods[] = { jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = NULL; - int ret; GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-1", 0, "Android tutorial 1"); @@ -328,7 +327,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { return 0; } jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_1/Tutorial1"); - ret = (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); + (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); pthread_key_create (¤t_jni_env, detach_current_thread); From e7d13a9120eff21d9953b034e1ad12c2754c9a82 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 14:32:02 +0200 Subject: [PATCH 54/90] Revamp initialization code. Now the library informs java when initialization is complete (pipeline built and native window received). --- .../android-tutorial-1/jni/tutorial-1.c | 42 +++++++++++++++---- .../tutorial_1/Tutorial1.java | 38 ++++++++++------- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 01ae13ed0c..10d48e7f68 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -39,6 +39,7 @@ 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; /* * Private methods @@ -162,6 +163,20 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } } +static void check_initialization_complete (CustomData *data) { + JNIEnv *env = get_jni_env (); + /* Check if all conditions are met to report GStreamer as initialized. + * These conditions will change depending on the application */ + if (data->native_window && data->main_loop) { + GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%d", data->native_window,data->main_loop); + (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } + } +} + static void *app_function (void *userdata) { JavaVMAttachArgs args; GstBus *bus; @@ -178,6 +193,10 @@ static void *app_function (void *userdata) { // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); + if (data->native_window) { + GST_DEBUG ("Native window already received, notifying the vsink about it."); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); + } /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); @@ -190,15 +209,14 @@ static void *app_function (void *userdata) { /* Register a function that GLib will call every second */ timeout_source_id = g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); - /* Set state to PAUSE, so preroll occurrs and retrieve some information like clip length */ - // This line is commented out until we can guarantee that the window handle is passed before the sink goes to READY - //gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop... (CustomData:%p)", data); data->main_loop = g_main_loop_new (NULL, FALSE); + check_initialization_complete (data); g_main_loop_run (data->main_loop); GST_DEBUG ("Exited main loop"); + g_main_loop_unref (data->main_loop); + data->main_loop = NULL; /* Destroy the timeout source */ timeout_source = g_main_context_find_source_by_id (NULL, timeout_source_id); @@ -223,8 +241,6 @@ void gst_native_init (JNIEnv* env, jobject thiz) { data->app = (*env)->NewGlobalRef (env, thiz); GST_DEBUG ("Created GlobalRef for app object at %p", data->app); pthread_create (&gst_app_thread, NULL, &app_function, data); - /* FIXME: Wait until thread has started and the main loop is running */ - usleep (100000); } void gst_native_finalize (JNIEnv* env, jobject thiz) { @@ -271,7 +287,10 @@ jboolean gst_class_init (JNIEnv* env, jclass klass) { GST_DEBUG ("The MethodID for the setMessage method is %p", set_message_method_id); set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(II)V"); GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id); - if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id) { + on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V"); + GST_DEBUG ("The MethodID for the onGStreamerInitialized method is %p", on_gstreamer_initialized_method_id); + + if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id || ! on_gstreamer_initialized_method_id) { GST_ERROR ("The calling class does not implement all necessary interface methods"); return JNI_FALSE; } @@ -288,7 +307,14 @@ void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { data->native_window = ANativeWindow_fromSurface(env, surface); GST_DEBUG ("Got Native Window %p", data->native_window); - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); + if (data->vsink) { + GST_DEBUG ("Pipeline already created, notifying the vsink about the native window."); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); + } else { + GST_DEBUG ("Pipeline not created yet, vsink will later be notified about the native window."); + } + + check_initialization_complete (data); } void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 7c2fe3bbbd..54262c8460 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -45,6 +45,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private boolean playing; private int position; private int duration; + + private Bundle initialization_data; /* Called when the activity is first created. @Override */ @@ -77,21 +79,9 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); sb.setOnSeekBarChangeListener(this); - nativeInit(); + initialization_data = savedInstanceState; - if (savedInstanceState != null) { - playing = savedInstanceState.getBoolean("playing"); - int milliseconds = savedInstanceState.getInt("position"); - Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); - /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the - * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind - * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe - * backwards on each iteration. */ - nativeSetPosition(milliseconds + 1); - if (playing) { - nativePlay(); - } - } + nativeInit(); } protected void onSaveInstanceState (Bundle outState) { @@ -115,6 +105,26 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee }); } + private void onGStreamerInitialized () { + if (initialization_data != null) { + playing = initialization_data.getBoolean("playing"); + int milliseconds = initialization_data.getInt("position"); + Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); + /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the + * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind + * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe + * backwards on each iteration. */ + nativeSetPosition(milliseconds + 1); + if (playing) { + nativePlay(); + } else { + nativePause(); + } + } else { + nativePause(); + } + } + private void setCurrentPosition(final int position, final int duration) { final TextView tv = (TextView) this.findViewById(R.id.textview_time); final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); From 553978a030aac2762f2ab85f1d33e8dc465e4139 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 16:02:43 +0200 Subject: [PATCH 55/90] Prevent the C code from notifying Java too many times about GStreamer being initialized --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 10d48e7f68..6a61ba8066 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -31,6 +31,7 @@ typedef struct _CustomData { gint64 duration; GstElement *vsink; gint64 desired_position; + gboolean initialized; } CustomData; static pthread_t gst_app_thread; @@ -167,13 +168,14 @@ static void check_initialization_complete (CustomData *data) { JNIEnv *env = get_jni_env (); /* Check if all conditions are met to report GStreamer as initialized. * These conditions will change depending on the application */ - if (data->native_window && data->main_loop) { + if (!data->initialized && data->native_window && data->main_loop) { GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%d", data->native_window,data->main_loop); (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); } + data->initialized = TRUE; } } From 8876ada4ea477cdc07f9e5bade89fc9851cd42ad Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Tue, 18 Sep 2012 16:48:39 +0200 Subject: [PATCH 56/90] Remove compiler warning --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 6a61ba8066..8b70cbc73a 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -229,6 +229,8 @@ static void *app_function (void *userdata) { gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->vsink); gst_object_unref (data->pipeline); + + return NULL; } /* From 9cdcecf4f8da81bedf2583eb6461fecfa476eb80 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 19 Sep 2012 12:18:41 +0200 Subject: [PATCH 57/90] Use custom GMainContext to avoid potential interference with other libraries using GLib --- .../android-tutorial-1/jni/tutorial-1.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 8b70cbc73a..a4ae0a2929 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -184,11 +184,15 @@ static void *app_function (void *userdata) { GstBus *bus; GstMessage *msg; CustomData *data = (CustomData *)userdata; - guint timeout_source_id; GSource *timeout_source; + GSource *bus_source; + GMainContext *context; GST_DEBUG ("Creating pipeline in CustomData at %p", data); + /* create our own GLib Main Context, so we do not interfere with other libraries using GLib */ + context = g_main_context_new (); + // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); @@ -202,30 +206,34 @@ static void *app_function (void *userdata) { /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data->pipeline); - gst_bus_add_signal_watch (bus); + bus_source = gst_bus_create_watch (bus); + g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); + g_source_attach (bus_source, context); + g_source_unref (bus_source); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); gst_object_unref (bus); - /* Register a function that GLib will call every second */ - timeout_source_id = g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, data); + /* Register a function that GLib will call 4 times per second */ + timeout_source = g_timeout_source_new (250); + g_source_attach (timeout_source, context); + g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL); + g_source_unref (timeout_source); /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop... (CustomData:%p)", data); - data->main_loop = g_main_loop_new (NULL, FALSE); + data->main_loop = g_main_loop_new (context, FALSE); check_initialization_complete (data); g_main_loop_run (data->main_loop); GST_DEBUG ("Exited main loop"); g_main_loop_unref (data->main_loop); data->main_loop = NULL; - /* Destroy the timeout source */ - timeout_source = g_main_context_find_source_by_id (NULL, timeout_source_id); - GST_DEBUG ("timeout_source:%p", timeout_source); - g_source_destroy (timeout_source); - /* Free resources */ + g_source_destroy (timeout_source); + g_source_destroy (bus_source); + g_main_context_unref (context); gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->vsink); gst_object_unref (data->pipeline); From fa77581edc7b3aa3487f55b5d91b7524e1c04dd7 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 19 Sep 2012 13:16:45 +0200 Subject: [PATCH 58/90] Remove unnecessary destruction of GSources --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index a4ae0a2929..474ee31e1a 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -231,8 +231,6 @@ static void *app_function (void *userdata) { data->main_loop = NULL; /* Free resources */ - g_source_destroy (timeout_source); - g_source_destroy (bus_source); g_main_context_unref (context); gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->vsink); From 1fdad2d11225b79fed9654e94f6574691e27e178 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 19 Sep 2012 16:50:38 +0200 Subject: [PATCH 59/90] Use the new GStreamer.Init() method to initialize GStreamer. --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 54262c8460..e8f4d50c18 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -19,6 +19,8 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; +import com.gst_sdk.GStreamer; + import android.app.Activity; import android.util.Log; import android.os.Bundle; @@ -47,6 +49,11 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private int duration; private Bundle initialization_data; + + public Tutorial1() { + super(); + GStreamer.Init(this); + } /* Called when the activity is first created. @Override */ From 049ac0438b0ce717c02a2482f331d2b14ff13c80 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Wed, 19 Sep 2012 17:58:23 +0200 Subject: [PATCH 60/90] Add a queue to the test pipeline --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 474ee31e1a..594cc07eba 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -194,7 +194,7 @@ static void *app_function (void *userdata) { context = g_main_context_new (); // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); - data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); + data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); // data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); From 2baed2a80ce753b64aebcee21918f6a542caa505 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 20 Sep 2012 10:32:49 +0200 Subject: [PATCH 61/90] Whitespacey --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index e8f4d50c18..d49f63ff89 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -43,13 +43,13 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private native void nativeSurfaceInit(Object surface); private native void nativeSurfaceFinalize(); private long native_custom_data; - + private boolean playing; private int position; private int duration; - + private Bundle initialization_data; - + public Tutorial1() { super(); GStreamer.Init(this); From 56e49fac4edddfc5797134ed2e09f9ae8e63eb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 20 Sep 2012 11:11:23 +0200 Subject: [PATCH 62/90] Call GStreamer.Init() from onCreate(), otherwise the Context is not set up yet --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index d49f63ff89..a83d6aa124 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -52,7 +52,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee public Tutorial1() { super(); - GStreamer.Init(this); } /* Called when the activity is first created. @@ -61,6 +60,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee { super.onCreate(savedInstanceState); + GStreamer.Init(this); + setContentView(R.layout.main); ImageButton play = (ImageButton) this.findViewById(R.id.button_play); From 20ab7db117115489b9ae45235dd5e371abdcd6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 20 Sep 2012 11:13:21 +0200 Subject: [PATCH 63/90] It's GStreamer.init(), not Init() --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index a83d6aa124..5fd2e9ce1e 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -60,7 +60,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee { super.onCreate(savedInstanceState); - GStreamer.Init(this); + GStreamer.init(this); setContentView(R.layout.main); From d685fd9281f8ad129cdee56077ec90c253df01f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 20 Sep 2012 11:16:12 +0200 Subject: [PATCH 64/90] Use the WebM video by default --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 594cc07eba..7ce1c7ea9b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -194,9 +194,8 @@ static void *app_function (void *userdata) { context = g_main_context_new (); // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); - data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); -// data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); + data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); if (data->native_window) { From eb5a50c8517f0676abafac397ad71d552cd9d78f Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Thu, 20 Sep 2012 11:38:35 +0200 Subject: [PATCH 65/90] Remove unused constructor --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 5fd2e9ce1e..ecd548962b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -50,10 +50,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private Bundle initialization_data; - public Tutorial1() { - super(); - } - /* Called when the activity is first created. @Override */ public void onCreate(Bundle savedInstanceState) From ec83a11e33a414927a5746ad2a4cb4fe553af327 Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Thu, 20 Sep 2012 12:29:40 +0200 Subject: [PATCH 66/90] android-tutorial-1: update Android.mk with last changes --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index f077bcf6bd..6f32168b58 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,8 +22,10 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) -GSTREAMER_PLUGINS = coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup amc matroska -GSTREAMER_STATIC_PLUGINS_PATH=/home/fluendo/cerbero/dist/android_arm/lib/gstreamer-0.10/static -GSTREAMER_MK_PATH=/home/fluendo/cerbero/data/ndk-build/ -include $(GSTREAMER_MK_PATH)/gstreamer.mk - +ifndef +GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) +endif +GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ +GSTREAMER_PLUGINS := coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup amc matroska +G_IO_MODULES := gnutls +include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk From d7735e0f6d299d3a56f8d693a98ea1cb23e03695 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 21 Sep 2012 10:56:35 +0200 Subject: [PATCH 67/90] Reduce the number of gst plugins used, to approach what will be really needed. --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 6f32168b58..7716e934de 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -26,6 +26,6 @@ ifndef GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ -GSTREAMER_PLUGINS := coreelements audiotestsrc videotestsrc ogg theora vorbis ffmpegcolorspace playback app audioconvert audiorate audioresample adder coreindexers gdp gio uridecodebin videorate videoscale typefindfunctions libvisual pango subparse eglglessink soup amc matroska +GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect G_IO_MODULES := gnutls include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk From 56697bc5d583c3a1eed4fe21d3568499f3d01f20 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 21 Sep 2012 10:57:33 +0200 Subject: [PATCH 68/90] Add some resilience. In many occasions native methods can be called where Gst is not yet initialized or being re-initialized. --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 7ce1c7ea9b..aa7932c6d3 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -196,6 +196,7 @@ static void *app_function (void *userdata) { // data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); +// data->pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm name=vsink", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); if (data->native_window) { @@ -254,6 +255,7 @@ void gst_native_init (JNIEnv* env, jobject thiz) { void gst_native_finalize (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; GST_DEBUG ("Quitting main loop..."); g_main_loop_quit (data->main_loop); GST_DEBUG ("Waiting for thread to finish..."); @@ -268,18 +270,21 @@ void gst_native_finalize (JNIEnv* env, jobject thiz) { void gst_native_play (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; GST_DEBUG ("Setting state to PLAYING"); gst_element_set_state (data->pipeline, GST_STATE_PLAYING); } void gst_native_pause (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; GST_DEBUG ("Setting state to PAUSED"); gst_element_set_state (data->pipeline, GST_STATE_PAUSED); } void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; gint64 desired_position = (gint64)(milliseconds * GST_MSECOND); if (data->state == GST_STATE_PLAYING || data->state == GST_STATE_PAUSED) { execute_seek(desired_position, data); @@ -308,6 +313,7 @@ jboolean gst_class_init (JNIEnv* env, jclass klass) { void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; GST_DEBUG ("Received surface %p", surface); if (data->native_window) { GST_DEBUG ("Releasing previous native window %p", data->native_window); From 81bb469d72885fdf9ed46f91b743152409f2e6e5 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 21 Sep 2012 10:58:17 +0200 Subject: [PATCH 69/90] Catch the exception thrown by GStreamer.init() and terminate application. --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index ecd548962b..1d9cb34bb2 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -32,6 +32,7 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import android.widget.Toast; public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSeekBarChangeListener { private native void nativeInit(); @@ -56,7 +57,13 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee { 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); From a11dffbbc1d359b0671cc7e2b8435361fa3cc025 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 21 Sep 2012 14:29:11 +0200 Subject: [PATCH 70/90] Better handling of state tracking in the UI. It now tracks what gst does, instead of just guessing from the buttons the user pressed. --- .../android-tutorial-1/jni/tutorial-1.c | 16 ++++++++-- .../tutorial_1/Tutorial1.java | 31 ++++++++++++++++--- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index aa7932c6d3..66453c0ef2 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -40,6 +40,7 @@ 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 set_current_state_method_id; static jmethodID on_gstreamer_initialized_method_id; /* @@ -92,7 +93,7 @@ static void set_ui_message (const gchar *message, CustomData *data) { static void set_current_ui_position (gint position, gint duration, CustomData *data) { JNIEnv *env = get_jni_env (); - GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration); +// GST_DEBUG ("Setting current position/duration to: %d / %d (ms)", position, duration); (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); @@ -151,16 +152,22 @@ static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + JNIEnv *env = get_jni_env (); GstState old_state, new_state, pending_state; gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); /* Only pay attention to messages coming from the pipeline, not its children */ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { - set_ui_message (gst_element_state_get_name (new_state), data); data->state = new_state; if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { execute_seek (data->desired_position, data); data->desired_position = GST_CLOCK_TIME_NONE; } + GST_DEBUG ("State changed to %s, notifying application", gst_element_state_get_name(new_state)); + (*env)->CallVoidMethod (env, data->app, set_current_state_method_id, new_state); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } } } @@ -303,8 +310,11 @@ jboolean gst_class_init (JNIEnv* env, jclass klass) { GST_DEBUG ("The MethodID for the setCurrentPosition method is %p", set_current_position_method_id); on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V"); GST_DEBUG ("The MethodID for the onGStreamerInitialized method is %p", on_gstreamer_initialized_method_id); + set_current_state_method_id = (*env)->GetMethodID (env, klass, "setCurrentState", "(I)V"); + GST_DEBUG ("The MethodID for the setCurrentState method is %p", set_current_state_method_id); - if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id || ! on_gstreamer_initialized_method_id) { + if (!custom_data_field_id || !set_message_method_id || !set_current_position_method_id || + !on_gstreamer_initialized_method_id || !set_current_state_method_id) { GST_ERROR ("The calling class does not implement all necessary interface methods"); return JNI_FALSE; } diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 1d9cb34bb2..1a363bb98b 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -71,7 +71,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee play.setOnClickListener(new OnClickListener() { public void onClick(View v) { nativePlay(); - playing = true; } }); @@ -79,7 +78,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee pause.setOnClickListener(new OnClickListener() { public void onClick(View v) { nativePause(); - playing = false; } }); @@ -107,6 +105,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee super.onDestroy(); } + /* Called from native code */ private void setMessage(final String message) { final TextView tv = (TextView) this.findViewById(R.id.textview_message); runOnUiThread (new Runnable() { @@ -116,17 +115,18 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee }); } + /* Called from native code */ private void onGStreamerInitialized () { if (initialization_data != null) { - playing = initialization_data.getBoolean("playing"); + boolean should_play = initialization_data.getBoolean("playing"); int milliseconds = initialization_data.getInt("position"); - Log.i ("GStreamer", "Restoring state, playing:" + playing + " position:" + milliseconds + " ms."); + Log.i ("GStreamer", "Restoring state, playing:" + should_play + " position:" + milliseconds + " ms."); /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe * backwards on each iteration. */ nativeSetPosition(milliseconds + 1); - if (playing) { + if (should_play) { nativePlay(); } else { nativePause(); @@ -136,6 +136,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee } } + /* Called from native code */ private void setCurrentPosition(final int position, final int duration) { final TextView tv = (TextView) this.findViewById(R.id.textview_time); final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); @@ -153,6 +154,26 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee this.duration = duration; } + /* Called from native code */ + private void setCurrentState (int state) { + Log.d ("GStreamer", "State has changed to " + state); + switch (state) { + case 1: + setMessage ("NULL"); + break; + case 2: + setMessage ("READY"); + break; + case 3: + setMessage ("PAUSED"); + break; + case 4: + setMessage ("PLAYING"); + break; + } + playing = (state == 4); + } + static { System.loadLibrary("gstreamer_android"); System.loadLibrary("tutorial-1"); From 634bad5eddc07f17fce883b75b72f5ed8d05c1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Sep 2012 10:19:00 +0200 Subject: [PATCH 71/90] videofilter plugin is needed for playbin2 too --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 7716e934de..8893cbaf5a 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -26,6 +26,6 @@ ifndef GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ -GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect +GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter G_IO_MODULES := gnutls include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk From c37559201811b8a52d8b3506198ce0652e34ebe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Sep 2012 11:23:40 +0200 Subject: [PATCH 72/90] Make the playbin2 pipeline the default --- .../android-tutorial-1/default.properties | 14 -------------- .../tutorials/android-tutorial-1/jni/Android.mk | 2 +- .../tutorials/android-tutorial-1/jni/tutorial-1.c | 8 +++++--- 3 files changed, 6 insertions(+), 18 deletions(-) delete mode 100644 gst-sdk/tutorials/android-tutorial-1/default.properties diff --git a/gst-sdk/tutorials/android-tutorial-1/default.properties b/gst-sdk/tutorials/android-tutorial-1/default.properties deleted file mode 100644 index 85aac54016..0000000000 --- a/gst-sdk/tutorials/android-tutorial-1/default.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-8 diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 8893cbaf5a..a22b4451f9 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -26,6 +26,6 @@ ifndef GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ -GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter +GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc G_IO_MODULES := gnutls include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 66453c0ef2..e8937ec30e 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -200,12 +200,14 @@ static void *app_function (void *userdata) { /* create our own GLib Main Context, so we do not interfere with other libraries using GLib */ context = g_main_context_new (); -// data->pipeline = gst_parse_launch ("videotestsrc ! eglglessink force_rendering_slow=1 can_create_window=0 name=vsink", NULL); // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); - data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); -// data->pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm name=vsink", NULL); +// data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)Y444 ! eglglessink name=vsink", NULL); + //data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink", NULL); + data->pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); + if (!data->vsink) + data->vsink = gst_object_ref (data->pipeline); if (data->native_window) { GST_DEBUG ("Native window already received, notifying the vsink about it."); gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); From 4909c6489daff87f8831c97a81050162477afca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Sep 2012 11:29:39 +0200 Subject: [PATCH 73/90] Catch DURATION message and query new duration on the next UI refresh This makes sure we always show the latest, real duration. Might help with OGV streaming. --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index e8937ec30e..9c992e41ae 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -151,6 +151,10 @@ static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { execute_seek (0, data); } +static void duration_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + data->duration = GST_CLOCK_TIME_NONE; +} + static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { JNIEnv *env = get_jni_env (); GstState old_state, new_state, pending_state; @@ -222,6 +226,7 @@ static void *app_function (void *userdata) { g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); + g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, data); gst_object_unref (bus); /* Register a function that GLib will call 4 times per second */ From 5d66cfd40fe271701bbf4261a423593084a1a818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Sep 2012 13:50:06 +0200 Subject: [PATCH 74/90] Also link OpenSL ES plugin --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index a22b4451f9..5893596f52 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -26,6 +26,6 @@ ifndef GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ -GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc +GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc opensles G_IO_MODULES := gnutls include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk From a247dddc7145f9db68c31517ce1a0179f9d6cdd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 24 Sep 2012 14:06:15 +0200 Subject: [PATCH 75/90] The volume element is needed by playbin2 too --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 5893596f52..6529657f06 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -26,6 +26,6 @@ ifndef GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ -GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc opensles +GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc opensles volume G_IO_MODULES := gnutls include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk From 3e795c9a197a77645c9244490643c17c530617dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 26 Sep 2012 10:27:27 +0200 Subject: [PATCH 76/90] Implement handling of buffering and clock-lost messages --- .../android-tutorial-1/jni/tutorial-1.c | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 9c992e41ae..83694f8862 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -32,6 +32,7 @@ typedef struct _CustomData { GstElement *vsink; gint64 desired_position; gboolean initialized; + gboolean is_live; } CustomData; static pthread_t gst_app_thread; @@ -147,7 +148,7 @@ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { set_ui_message (GST_MESSAGE_TYPE_NAME (msg), data); refresh_ui (data); - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); execute_seek (0, data); } @@ -155,6 +156,24 @@ static void duration_cb (GstBus *bus, GstMessage *msg, CustomData *data) { data->duration = GST_CLOCK_TIME_NONE; } +static void buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + gint percent; + + if (data->is_live) + return; + + gst_message_parse_buffering (msg, &percent); + if (percent < 100) + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + else + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); +} + +static void clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); +} + static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { JNIEnv *env = get_jni_env (); GstState old_state, new_state, pending_state; @@ -227,6 +246,8 @@ static void *app_function (void *userdata) { g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, data); + g_signal_connect (G_OBJECT (bus), "message::buffering", (GCallback)buffering_cb, data); + g_signal_connect (G_OBJECT (bus), "message::clock-lost", (GCallback)clock_lost_cb, data); gst_object_unref (bus); /* Register a function that GLib will call 4 times per second */ @@ -286,14 +307,14 @@ void gst_native_play (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; GST_DEBUG ("Setting state to PLAYING"); - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); } void gst_native_pause (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; GST_DEBUG ("Setting state to PAUSED"); - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); } void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { From 6184907bbf2c1faac2a25e4b8b421bdfcfeec5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 26 Sep 2012 13:46:47 +0200 Subject: [PATCH 77/90] Make sure to not go out of the target state due to buffering messages E.g. go to PLAYING although we're only requested to PAUSED --- .../android-tutorial-1/jni/tutorial-1.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 83694f8862..a4157ca264 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -26,7 +26,7 @@ typedef struct _CustomData { GstElement *pipeline; GMainLoop *main_loop; ANativeWindow *native_window; - gboolean state; + GstState state, target_state; gint64 position; gint64 duration; GstElement *vsink; @@ -142,12 +142,14 @@ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { g_free (debug_info); set_ui_message (message_string, data); g_free (message_string); + data->target_state = GST_STATE_NULL; gst_element_set_state (data->pipeline, GST_STATE_NULL); } static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { set_ui_message (GST_MESSAGE_TYPE_NAME (msg), data); refresh_ui (data); + data->target_state = GST_STATE_PAUSED; data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); execute_seek (0, data); } @@ -163,15 +165,17 @@ static void buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data) { return; gst_message_parse_buffering (msg, &percent); - if (percent < 100) + if (percent < 100 && data->target_state >= GST_STATE_PAUSED) gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - else + else if (data->target_state >= GST_STATE_PLAYING) gst_element_set_state (data->pipeline, GST_STATE_PLAYING); } static void clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + if (data->target_state >= GST_STATE_PLAYING) { + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + } } static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { @@ -267,6 +271,7 @@ static void *app_function (void *userdata) { /* Free resources */ g_main_context_unref (context); + data->target_state = GST_STATE_NULL; gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->vsink); gst_object_unref (data->pipeline); @@ -307,6 +312,7 @@ void gst_native_play (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; GST_DEBUG ("Setting state to PLAYING"); + data->target_state = GST_STATE_PLAYING; data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); } @@ -314,6 +320,7 @@ void gst_native_pause (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; GST_DEBUG ("Setting state to PAUSED"); + data->target_state = GST_STATE_PAUSED; data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); } From 555c456e9e3b53dd954473f56d3bea39c104d85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 27 Sep 2012 14:18:05 +0200 Subject: [PATCH 78/90] Add some UI feedback for the buffering messages --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index a4157ca264..2d28176149 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -165,10 +165,17 @@ static void buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data) { return; gst_message_parse_buffering (msg, &percent); - if (percent < 100 && data->target_state >= GST_STATE_PAUSED) + if (percent < 100 && data->target_state >= GST_STATE_PAUSED) { + gchar * message_string = g_strdup_printf ("Buffering %d %%", percent); gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - else if (data->target_state >= GST_STATE_PLAYING) + set_ui_message (message_string, data); + g_free (message_string); + } else if (data->target_state >= GST_STATE_PLAYING) { gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + set_ui_message ("PLAYING", data); + } else if (data->target_state >= GST_STATE_PAUSED) { + set_ui_message ("PAUSED", data); + } } static void clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data) { From 2ca5b7356ca79bdf872d771a0db60af994a0c5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 28 Sep 2012 09:31:35 +0200 Subject: [PATCH 79/90] Use the OGV variant by default and use the fd.o server --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 2d28176149..329f55a08d 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -236,8 +236,8 @@ static void *app_function (void *userdata) { // data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); // data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)Y444 ! eglglessink name=vsink", NULL); - //data->pipeline = gst_parse_launch ("souphttpsrc location=http://docs.gstreamer.com/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink", NULL); - data->pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL); + //data->pipeline = gst_parse_launch ("souphttpsrc location=http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink", NULL); + data->pipeline = gst_parse_launch ("playbin2 uri=http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); if (!data->vsink) From 9eb55274bc24105d4c566186f9e1a1ba86430ad8 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 28 Sep 2012 12:12:21 +0200 Subject: [PATCH 80/90] Fix Android.mk and make it use GSTREAMER_SDK_ROOT_ANDROID --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 6529657f06..6ab806bd9c 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,9 +22,10 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -landroid include $(BUILD_SHARED_LIBRARY) -ifndef -GSTREAMER_SDK_ROOT := $(CERBERO_PREFIX) +ifndef GSTREAMER_SDK_ROOT_ANDROID +$(error GSTREAMER_SDK_ROOT_ANDROID is not defined!) endif +GSTREAMER_SDK_ROOT := $(GSTREAMER_SDK_ROOT_ANDROID) GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/ GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc opensles volume G_IO_MODULES := gnutls From 929f8eb55f052c7cf0c72ea5b183c26c249603a2 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 28 Sep 2012 15:27:33 +0200 Subject: [PATCH 81/90] Some debug output beautifying --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 329f55a08d..711e0c1d58 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -210,7 +210,7 @@ static void check_initialization_complete (CustomData *data) { /* Check if all conditions are met to report GStreamer as initialized. * These conditions will change depending on the application */ if (!data->initialized && data->native_window && data->main_loop) { - GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%d", data->native_window,data->main_loop); + GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%p", data->native_window,data->main_loop); (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); @@ -307,7 +307,7 @@ void gst_native_finalize (JNIEnv* env, jobject thiz) { g_main_loop_quit (data->main_loop); GST_DEBUG ("Waiting for thread to finish..."); pthread_join (gst_app_thread, NULL); - GST_DEBUG ("Deleting GlobalRef at %p", data->app); + GST_DEBUG ("Deleting GlobalRef for app object at %p", data->app); (*env)->DeleteGlobalRef (env, data->app); GST_DEBUG ("Freeing CustomData at %p", data); g_free (data); From 74543783c08f39279fd9ef592c6fe743f3f4889e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 1 Oct 2012 10:08:52 +0200 Subject: [PATCH 82/90] Only set GSTREAMER_SDK_ROOT if it wasn't set yet --- gst-sdk/tutorials/android-tutorial-1/jni/Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk index 6ab806bd9c..bed77fd797 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk +++ b/gst-sdk/tutorials/android-tutorial-1/jni/Android.mk @@ -22,10 +22,12 @@ LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -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/ GSTREAMER_PLUGINS := coreelements ogg theora vorbis ffmpegcolorspace playback audioconvert audiorate audioresample coreindexers gio uridecodebin videorate videoscale typefindfunctions eglglessink soup amc matroska autodetect videofilter videotestsrc opensles volume G_IO_MODULES := gnutls From cf083414f6e22e47a02ff1b75c81fc5d47d4122a Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 1 Oct 2012 10:40:51 +0200 Subject: [PATCH 83/90] Add API to set the URI instead of hardcoding it in the gst_launch --- .../tutorials/android-tutorial-1/jni/tutorial-1.c | 15 +++++++++++---- .../gst_sdk_tutorials/tutorial_1/Tutorial1.java | 4 ++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 711e0c1d58..2d961d89df 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -234,10 +234,7 @@ static void *app_function (void *userdata) { /* create our own GLib Main Context, so we do not interfere with other libraries using GLib */ context = g_main_context_new (); -// data->pipeline = gst_parse_launch ("filesrc location=/sdcard/Movies/sintel_trailer-480p.ogv ! oggdemux ! theoradec ! queue ! ffmpegcolorspace ! eglglessink name=vsink force_rendering_slow=1 can_create_window=0", NULL); -// data->pipeline = gst_parse_launch ("videotestsrc ! ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)Y444 ! eglglessink name=vsink", NULL); - //data->pipeline = gst_parse_launch ("souphttpsrc location=http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm ! matroskademux ! amcviddec-omxgooglevpxdecoder ! queue ! ffmpegcolorspace ! eglglessink name=vsink", NULL); - data->pipeline = gst_parse_launch ("playbin2 uri=http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv", NULL); + data->pipeline = gst_parse_launch ("playbin2", NULL); data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); if (!data->vsink) @@ -315,6 +312,15 @@ void gst_native_finalize (JNIEnv* env, jobject thiz) { GST_DEBUG ("Done finalizing"); } +void gst_native_set_uri (JNIEnv* env, jobject thiz, jstring uri) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + const jbyte *char_uri = (*env)->GetStringUTFChars (env, uri, NULL); + GST_DEBUG ("Setting URI to %s", char_uri); + g_object_set(data->pipeline, "uri", char_uri); + (*env)->ReleaseStringUTFChars (env, uri, char_uri); +} + void gst_native_play (JNIEnv* env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; @@ -400,6 +406,7 @@ void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { static JNINativeMethod native_methods[] = { { "nativeInit", "()V", (void *) gst_native_init}, { "nativeFinalize", "()V", (void *) gst_native_finalize}, + { "nativeSetUri", "(Ljava/lang/String;)V", (void *) gst_native_set_uri}, { "nativePlay", "()V", (void *) gst_native_play}, { "nativePause", "()V", (void *) gst_native_pause}, { "nativeSetPosition", "(I)V", (void*) gst_native_set_position}, diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index 1a363bb98b..e26ebd88b4 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -37,6 +37,7 @@ import android.widget.Toast; public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSeekBarChangeListener { private native void nativeInit(); private native void nativeFinalize(); + private native void nativeSetUri(String uri); private native void nativePlay(); private native void nativePause(); private native void nativeSetPosition(int milliseconds); @@ -50,6 +51,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private int duration; private Bundle initialization_data; + + private final String mediaUri = "http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv"; /* Called when the activity is first created. @Override */ @@ -117,6 +120,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee /* Called from native code */ private void onGStreamerInitialized () { + nativeSetUri (mediaUri); if (initialization_data != null) { boolean should_play = initialization_data.getBoolean("playing"); int milliseconds = initialization_data.getInt("position"); From ceaab451f2d29a5d587712f1054a21ba8ffe625f Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 1 Oct 2012 12:37:07 +0200 Subject: [PATCH 84/90] Fix Seeking: Disable scrubbing seek for remote files, remember playing state after seek. Use media from gstreamer.com instead of freedesktop.org (weird buffering from the later) --- .../tutorial_1/Tutorial1.java | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index e26ebd88b4..b849b67920 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -46,13 +46,15 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee private native void nativeSurfaceFinalize(); private long native_custom_data; - private boolean playing; + private boolean is_playing_desired; private int position; private int duration; + private boolean is_local_media; + private int desired_position; private Bundle initialization_data; - private final String mediaUri = "http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv"; + private final String mediaUri = "http://docs.gstreamer.com/media/sintel_trailer-480p.ogv"; /* Called when the activity is first created. @Override */ @@ -73,6 +75,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee ImageButton play = (ImageButton) this.findViewById(R.id.button_play); play.setOnClickListener(new OnClickListener() { public void onClick(View v) { + is_playing_desired = true; nativePlay(); } }); @@ -80,6 +83,7 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee ImageButton pause = (ImageButton) this.findViewById(R.id.button_stop); pause.setOnClickListener(new OnClickListener() { public void onClick(View v) { + is_playing_desired = false; nativePause(); } }); @@ -92,13 +96,16 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee sb.setOnSeekBarChangeListener(this); initialization_data = savedInstanceState; + + is_local_media = false; + is_playing_desired = false; nativeInit(); } protected void onSaveInstanceState (Bundle outState) { - Log.d ("GStreamer", "Saving state, playing:" + playing + " position:" + position); - outState.putBoolean("playing", playing); + Log.d ("GStreamer", "Saving state, playing:" + is_playing_desired + " position:" + position); + outState.putBoolean("playing", is_playing_desired); outState.putInt("position", position); outState.putInt("duration", duration); } @@ -121,6 +128,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee /* Called from native code */ private void onGStreamerInitialized () { nativeSetUri (mediaUri); + if (mediaUri.startsWith("file://")) is_local_media = true; + if (initialization_data != null) { boolean should_play = initialization_data.getBoolean("playing"); int milliseconds = initialization_data.getInt("position"); @@ -128,7 +137,8 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe - * backwards on each iteration. */ + * backwards on each iteration. + */ nativeSetPosition(milliseconds + 1); if (should_play) { nativePlay(); @@ -140,18 +150,32 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee } } - /* Called from native code */ - private void setCurrentPosition(final int position, final int duration) { + /* The text widget acts as an slave for the seek bar, so it reflects what the seek bar shows, whether + * it is an actual pipeline position or the position the user is currently dragging to. + */ + private void updateTimeWidget () { final TextView tv = (TextView) this.findViewById(R.id.textview_time); final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); + final int pos = sb.getProgress(); + SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); df.setTimeZone(TimeZone.getTimeZone("UTC")); - final String message = df.format(new Date (position)) + " / " + df.format(new Date (duration)); + final String message = df.format(new Date (pos)) + " / " + df.format(new Date (duration)); + tv.setText(message); + } + + /* Called from native code */ + private void setCurrentPosition(final int position, final int duration) { + final SeekBar sb = (SeekBar) this.findViewById(R.id.seek_bar); + + /* Ignore position messages from the pipeline if the seek bar is being dragged */ + if (sb.isPressed()) return; + runOnUiThread (new Runnable() { public void run() { - tv.setText(message); sb.setMax(duration); sb.setProgress(position); + updateTimeWidget(); } }); this.position = position; @@ -175,7 +199,6 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee setMessage ("PLAYING"); break; } - playing = (state == 4); } static { @@ -202,7 +225,12 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) { if (fromUser == false) return; - nativeSetPosition(progress); + desired_position = progress; + /* If this is a local file, allow scrub seeking, this is, seek soon as the slider + * is moved. + */ + if (is_local_media) nativeSetPosition(desired_position); + updateTimeWidget(); } public void onStartTrackingTouch(SeekBar sb) { @@ -210,6 +238,10 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee } public void onStopTrackingTouch(SeekBar sb) { - if (playing) nativePlay(); + /* If this is a remote file, scrub seeking is probably not going to work smoothly enough. + * Therefore, perform only the seek when the slider is released. + */ + if (!is_local_media) nativeSetPosition(desired_position); + if (is_playing_desired) nativePlay(); } } From b809b23b240a1dc30e2baed96156e3b92d58fa46 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 1 Oct 2012 12:37:57 +0200 Subject: [PATCH 85/90] Whitespacey --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 2d961d89df..d13532f251 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -342,10 +342,10 @@ void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { if (!data) return; gint64 desired_position = (gint64)(milliseconds * GST_MSECOND); if (data->state == GST_STATE_PLAYING || data->state == GST_STATE_PAUSED) { - execute_seek(desired_position, data); + execute_seek(desired_position, data); } else { - GST_DEBUG ("Scheduling seek to %d milliseconds for later", milliseconds); - data->desired_position = desired_position; + GST_DEBUG ("Scheduling seek to %d milliseconds for later", milliseconds); + data->desired_position = desired_position; } } From af9437ff7d961d6eff897036ba31216d4b01d1da Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 1 Oct 2012 12:47:09 +0200 Subject: [PATCH 86/90] Now that playbin2 is used, remove the vsink variable, and use factory_make instead of parse_launch. --- .../android-tutorial-1/jni/tutorial-1.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index d13532f251..bd8e0f1e8f 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -29,7 +29,6 @@ typedef struct _CustomData { GstState state, target_state; gint64 position; gint64 duration; - GstElement *vsink; gint64 desired_position; gboolean initialized; gboolean is_live; @@ -234,14 +233,11 @@ static void *app_function (void *userdata) { /* create our own GLib Main Context, so we do not interfere with other libraries using GLib */ context = g_main_context_new (); - data->pipeline = gst_parse_launch ("playbin2", NULL); + data->pipeline = gst_element_factory_make ("playbin2", NULL); - data->vsink = gst_bin_get_by_name (GST_BIN (data->pipeline), "vsink"); - if (!data->vsink) - data->vsink = gst_object_ref (data->pipeline); if (data->native_window) { - GST_DEBUG ("Native window already received, notifying the vsink about it."); - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); + GST_DEBUG ("Native window already received, notifying the pipeline about it."); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)data->native_window); } /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ @@ -277,7 +273,6 @@ static void *app_function (void *userdata) { g_main_context_unref (context); data->target_state = GST_STATE_NULL; gst_element_set_state (data->pipeline, GST_STATE_NULL); - gst_object_unref (data->vsink); gst_object_unref (data->pipeline); return NULL; @@ -380,11 +375,11 @@ void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { data->native_window = ANativeWindow_fromSurface(env, surface); GST_DEBUG ("Got Native Window %p", data->native_window); - if (data->vsink) { - GST_DEBUG ("Pipeline already created, notifying the vsink about the native window."); - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)data->native_window); + if (data->pipeline) { + GST_DEBUG ("Pipeline already created, notifying the it about the native window."); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)data->native_window); } else { - GST_DEBUG ("Pipeline not created yet, vsink will later be notified about the native window."); + GST_DEBUG ("Pipeline not created yet, it will later be notified about the native window."); } check_initialization_complete (data); @@ -400,7 +395,9 @@ void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { ANativeWindow_release (data->native_window); data->native_window = NULL; - gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->vsink), (guintptr)NULL); + if (data->pipeline) { + gst_x_overlay_set_window_handle (GST_X_OVERLAY (data->pipeline), (guintptr)NULL); + } } static JNINativeMethod native_methods[] = { From 76c883fb8b741767fef169fe4969012b61921ee0 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Mon, 1 Oct 2012 14:27:25 +0200 Subject: [PATCH 87/90] Fix restoration of playing state after orientation change --- .../src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java index b849b67920..666a77dcaf 100755 --- a/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java +++ b/gst-sdk/tutorials/android-tutorial-1/src/com/gst_sdk_tutorials/tutorial_1/Tutorial1.java @@ -131,16 +131,16 @@ public class Tutorial1 extends Activity implements SurfaceHolder.Callback, OnSee if (mediaUri.startsWith("file://")) is_local_media = true; if (initialization_data != null) { - boolean should_play = initialization_data.getBoolean("playing"); + is_playing_desired = initialization_data.getBoolean("playing"); int milliseconds = initialization_data.getInt("position"); - Log.i ("GStreamer", "Restoring state, playing:" + should_play + " position:" + milliseconds + " ms."); + Log.i ("GStreamer", "Restoring state, playing:" + is_playing_desired + " position:" + milliseconds + " ms."); /* Actually, move to one millisecond in the future. Otherwise, due to rounding errors between the * milliseconds used here and the nanoseconds used by GStreamer, we would be jumping a bit behind * where we were before. This, combined with seeking to keyframe positions, would skip one keyframe * backwards on each iteration. */ nativeSetPosition(milliseconds + 1); - if (should_play) { + if (is_playing_desired) { nativePlay(); } else { nativePause(); From 31235328417bafedddd8e8ba640f272c21f78f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 1 Oct 2012 14:43:01 +0200 Subject: [PATCH 88/90] Implement throttling of seeks, only one seek per 500ms --- .../android-tutorial-1/jni/tutorial-1.c | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index bd8e0f1e8f..c229bc40ec 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -24,12 +24,14 @@ GST_DEBUG_CATEGORY_STATIC (debug_category); typedef struct _CustomData { jobject app; GstElement *pipeline; + GMainContext *context; GMainLoop *main_loop; ANativeWindow *native_window; GstState state, target_state; gint64 position; gint64 duration; gint64 desired_position; + GstClockTime last_seek_time; gboolean initialized; gboolean is_live; } CustomData; @@ -123,11 +125,40 @@ static gboolean refresh_ui (CustomData *data) { return TRUE; } +static void execute_seek (gint64 desired_position, CustomData *data); +static gboolean +delayed_seek_cb (CustomData *data) +{ + execute_seek (data->desired_position, data); + return FALSE; +} + static void execute_seek (gint64 desired_position, CustomData *data) { gboolean res; - GST_DEBUG ("Setting position to %lld milliseconds", desired_position / GST_MSECOND); - res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); - GST_DEBUG ("Seek returned %d", res); + gint64 diff; + + if (desired_position == GST_CLOCK_TIME_NONE) + return; + + diff = gst_util_get_timestamp () - data->last_seek_time; + + if (GST_CLOCK_TIME_IS_VALID (data->last_seek_time) && diff < 500 * GST_MSECOND) { + GSource *timeout_source; + + data->desired_position = desired_position; + timeout_source = g_timeout_source_new (diff / GST_MSECOND); + g_source_attach (timeout_source, data->context); + g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL); + g_source_unref (timeout_source); + GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, + GST_TIME_ARGS (desired_position), GST_TIME_ARGS (500 * GST_MSECOND - diff)); + } else { + GST_DEBUG ("Setting position to %lld milliseconds", desired_position / GST_MSECOND); + res = gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); + data->last_seek_time = gst_util_get_timestamp (); + data->desired_position = GST_CLOCK_TIME_NONE; + GST_DEBUG ("Seek returned %d", res); + } } static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { @@ -226,12 +257,11 @@ static void *app_function (void *userdata) { CustomData *data = (CustomData *)userdata; GSource *timeout_source; GSource *bus_source; - GMainContext *context; GST_DEBUG ("Creating pipeline in CustomData at %p", data); /* create our own GLib Main Context, so we do not interfere with other libraries using GLib */ - context = g_main_context_new (); + data->context = g_main_context_new (); data->pipeline = gst_element_factory_make ("playbin2", NULL); @@ -244,7 +274,7 @@ static void *app_function (void *userdata) { bus = gst_element_get_bus (data->pipeline); bus_source = gst_bus_create_watch (bus); g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); - g_source_attach (bus_source, context); + g_source_attach (bus_source, data->context); g_source_unref (bus_source); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); @@ -256,13 +286,13 @@ static void *app_function (void *userdata) { /* Register a function that GLib will call 4 times per second */ timeout_source = g_timeout_source_new (250); - g_source_attach (timeout_source, context); + g_source_attach (timeout_source, data->context); g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL); g_source_unref (timeout_source); /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop... (CustomData:%p)", data); - data->main_loop = g_main_loop_new (context, FALSE); + data->main_loop = g_main_loop_new (data->context, FALSE); check_initialization_complete (data); g_main_loop_run (data->main_loop); GST_DEBUG ("Exited main loop"); @@ -270,7 +300,7 @@ static void *app_function (void *userdata) { data->main_loop = NULL; /* Free resources */ - g_main_context_unref (context); + g_main_context_unref (data->context); data->target_state = GST_STATE_NULL; gst_element_set_state (data->pipeline, GST_STATE_NULL); gst_object_unref (data->pipeline); @@ -282,9 +312,10 @@ static void *app_function (void *userdata) { * Java Bindings */ void gst_native_init (JNIEnv* env, jobject thiz) { - CustomData *data = (CustomData *)g_malloc0 (sizeof (CustomData)); + CustomData *data = g_new0 (CustomData, 1); data->duration = GST_CLOCK_TIME_NONE; data->desired_position = GST_CLOCK_TIME_NONE; + data->last_seek_time = GST_CLOCK_TIME_NONE; SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); GST_DEBUG ("Created CustomData at %p", data); data->app = (*env)->NewGlobalRef (env, thiz); From 5ad29d568ed0a626677ed5b3b53250f2843d64c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 1 Oct 2012 15:46:17 +0200 Subject: [PATCH 89/90] Don't queue multiple timeouts for delayed seeking --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index c229bc40ec..912667a0d4 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -145,11 +145,13 @@ static void execute_seek (gint64 desired_position, CustomData *data) { if (GST_CLOCK_TIME_IS_VALID (data->last_seek_time) && diff < 500 * GST_MSECOND) { GSource *timeout_source; + if (!GST_CLOCK_TIME_IS_VALID (data->desired_position)) { + timeout_source = g_timeout_source_new (diff / GST_MSECOND); + g_source_attach (timeout_source, data->context); + g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL); + g_source_unref (timeout_source); + } data->desired_position = desired_position; - timeout_source = g_timeout_source_new (diff / GST_MSECOND); - g_source_attach (timeout_source, data->context); - g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL); - g_source_unref (timeout_source); GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, GST_TIME_ARGS (desired_position), GST_TIME_ARGS (500 * GST_MSECOND - diff)); } else { From 9a4b1977d443444e15444e53d6764720017ed07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 1 Oct 2012 16:56:49 +0200 Subject: [PATCH 90/90] Fix seeking --- gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c index 912667a0d4..df74084563 100755 --- a/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c +++ b/gst-sdk/tutorials/android-tutorial-1/jni/tutorial-1.c @@ -129,6 +129,8 @@ static void execute_seek (gint64 desired_position, CustomData *data); static gboolean delayed_seek_cb (CustomData *data) { + GST_DEBUG ("Doing delayed seek %" GST_TIME_FORMAT, GST_TIME_ARGS (data->desired_position)); + data->last_seek_time = GST_CLOCK_TIME_NONE; execute_seek (data->desired_position, data); return FALSE; } @@ -224,10 +226,8 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { /* Only pay attention to messages coming from the pipeline, not its children */ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { data->state = new_state; - if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) { + if (data->state >= GST_STATE_PAUSED && GST_CLOCK_TIME_IS_VALID (data->desired_position)) execute_seek (data->desired_position, data); - data->desired_position = GST_CLOCK_TIME_NONE; - } GST_DEBUG ("State changed to %s, notifying application", gst_element_state_get_name(new_state)); (*env)->CallVoidMethod (env, data->app, set_current_state_method_id, new_state); if ((*env)->ExceptionCheck (env)) {