Commit 6a8b0988 authored by Rémi Duraffort's avatar Rémi Duraffort

Merging the git repositories

parent fb6802dc
......@@ -57,14 +57,14 @@ $(APK_MK):
printf "include \$$(CLEAR_VARS)\n" >> $(APK_MK); \
printf "LOCAL_MODULE := libvlcjni\n" >> $(APK_MK); \
printf "LOCAL_SRC_FILES := libvlcjni.c aout.c thumbnailer.c\n" >> $(APK_MK); \
printf "LOCAL_C_INCLUDES := \$$(LOCAL_PATH)/../../../../../include\n" >> $(APK_MK); \
printf "LOCAL_C_INCLUDES := \$$(LOCAL_PATH)/../../vlc/include\n" >> $(APK_MK); \
printf "LOCAL_LDLIBS := -L$$vlc_contrib/lib \\\\\n" >> $(APK_MK); \
printf "\t-L$$ANDROID_NDK/platforms/android-8/arch-arm/usr/lib \\\\\n" >> $(APK_MK); \
printf "$$LDFLAGS" >> $(APK_MK); \
printf "\t$$prefix$$VLC_BUILD_DIR/compat/.libs/libcompat.a \\\\\n" >> $(APK_MK); \
printf "\t$$prefix$$VLC_BUILD_DIR/src/.libs/libvlc.a \\\\\n" >> $(APK_MK); \
printf "\t$$prefix$$VLC_BUILD_DIR/src/.libs/libvlccore.a \\\\\n" >> $(APK_MK); \
printf "\t-ldl -lz -lm -logg -lvorbisenc -lvorbis -lFLAC -lspeex -ltheora -lavformat -lavcodec -lavcore -lavutil -lpostproc -lswscale -lmpeg2 -lgcc -lpng -ldca -ldvbpsi -ltwolame -lkate -llog -la52 -lliveMedia -lUsageEnvironment -lBasicUsageEnvironment -lgroupsock -lebml -lmatroska -ltag\\\\\n" >> $(APK_MK); \
printf "\t-ldl -lz -lm -logg -lvorbisenc -lvorbis -lFLAC -lspeex -ltheora -lavformat -lavcodec -lavcore -lavutil -lpostproc -lswscale -lmpeg2 -lgcc -lpng -ldca -ldvbpsi -ltwolame -lkate -llog -la52 -lebml -lmatroska -ltag\\\\\n" >> $(APK_MK); \
printf "\t$$ANDROID_STDCPP\n" >> $(APK_MK); \
printf "include \$$(BUILD_SHARED_LIBRARY)\n" >> $(APK_MK)
......
#! /bin/sh
GIT=git
if [ -z "$ANDROID_NDK" -o -z "$ANDROID_SDK" ]; then
echo "You must define ANDROID_NDK and ANDROID_SDK before starting";
exit 1;
fi;
echo "Cloning and updating VLC"
$GIT clone git://git.videolan.org/vlc.git
echo "Applying the patches"
cd vlc
$GIT am ../patches/*.patch
echo "Building the contribs"
cd extras/contrib && ./bootstrap -t arm-eabi -d android && make
cd ../.. && mkdir -p android && cd android
echo "Bootstraping"
../bootstrap
echo "Configuring"
sh ../extras/package/android/configure.sh
make
From 56c79fcabbc45febfaa6ad2839eba5a6946e8b59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-Philippe=20Andr=C3=A9?= <jpeg@videolan.org>
Date: Thu, 2 Jun 2011 15:15:57 +0200
Subject: [PATCH 1/6] Android: add compatibility pthread_cancel
Original-code: c1ee19f63a6c6773400e98a9265b0a7e49fd528c
7884ed8d407647a1523afb8be6a2859477d54fd7
42336426297a2f0e38964f238208681a2b54d6d8
497c810426c2fc3d414ef8d98dd1ed321d86ece0
96cd0d6dbc510f656a9b962b2b17c68e7f19d02e
bbf4bd81aa2ba5fef271b537ccc0ae9285ad6169
fd3a78c13899095f75021b1aeb38b68e6c1f0164
497c810426c2fc3d414ef8d98dd1ed321d86ece0
Modified and ported-by: Jean-Baptiste Kempf <jb@videolan.org>
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
---
compat/pthread_cancel.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 4 +
include/vlc_fixups.h | 22 ++++
src/control/error.c | 16 +++
src/posix/thread.c | 20 ++++
5 files changed, 353 insertions(+), 0 deletions(-)
create mode 100644 compat/pthread_cancel.c
diff --git a/compat/pthread_cancel.c b/compat/pthread_cancel.c
new file mode 100644
index 0000000..8a39f5d
--- /dev/null
+++ b/compat/pthread_cancel.c
@@ -0,0 +1,291 @@
+/*****************************************************************************
+ * pthread_cancel.c: pthread deferred cancellation replacement
+ *****************************************************************************
+ * Copyright © 2011 VideoLAN
+ *
+ * Author: Jean-Philippe André <jpeg # videolan.org>
+ *
+ * License: LGPLv2.1+
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <vlc_common.h>
+#include <vlc_fixups.h>
+#include <pthread.h>
+#include <assert.h>
+
+/*
+ * This file provide fixups for the following functions:
+ * - pthread_cancel
+ * - pthread_testcancel
+ * - pthread_setcancelstate
+ * As a result of the implementation design, we must also wrap
+ * pthread_create into a cancellation-aware function
+ */
+
+static void* thread_wrapper_routine (void *arg);
+static void thread_cancel_handler (int signal);
+static void thread_cancel_destructor (void *data);
+
+// Functions used by LibVLC
+void pthread_cancel_initialize (void);
+void pthread_cancel_deinitialize (void);
+
+/*
+ * Some static variables used for initialization
+ */
+static pthread_key_t cancel_key = 0; /// Key for the thread-local variable
+
+/*
+ * These objects define the thread-local variable tracking the thread's
+ * cancellation status (cancellable, cancelled)
+ */
+typedef struct cancel_t cancel_t;
+struct cancel_t
+{
+ int state; /// PTHREAD_CANCEL_ENABLE (0) or PTHREAD_CANCEL_DISABLE (1)
+ pthread_cond_t *cond; /// Non-null if thread waiting on cond
+
+ /* Booleans at the end for packing purposes */
+ bool cancelled; /// Non-zero means this thread has been cancelled
+};
+
+/*
+ * This is the thread wrapper data
+ */
+typedef struct thread_wrapper_t thread_wrapper_t;
+struct thread_wrapper_t
+{
+ void *(*routine) (void*); /// Main thread routine to call
+ void *arg; /// Argument to pass to the thread routine
+ cancel_t *cancel; /// The cancel structure is allocated before the thread
+};
+
+/**
+ * Initialize pthread cancellation
+ * Creates thread-local variable's key and catches SIGRTMIN in main thread
+ **/
+void pthread_cancel_initialize (void)
+{
+ // Set up signal handler
+ struct sigaction act;
+ memset (&act, 0, sizeof (act));
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = thread_cancel_handler;
+ sigaction (SIGRTMIN, &act, NULL);
+
+ // Create thread-local variable key
+ pthread_key_create (&cancel_key, thread_cancel_destructor);
+}
+
+/**
+ * Deinitialize pthread cancellation
+ **/
+void pthread_cancel_deinitialize (void)
+{
+ struct sigaction act;
+ memset (&act, 0, sizeof (act));
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGRTMIN, &act, NULL);
+ pthread_key_delete (cancel_key);
+ cancel_key = 0;
+}
+
+/**
+ * Replacement for pthread_cancel
+ * Sends a SIGRTMIN signal to the thread
+ **/
+int pthread_cancel (pthread_t thread_id)
+{
+ return pthread_kill (thread_id, SIGRTMIN);
+}
+
+/**
+ * Replacement for pthread_create with support for cancellation
+ **/
+int pthread_create_cancel (pthread_t *thread_id,
+ const pthread_attr_t *attr,
+ void *(*routine) (void *),
+ void *arg)
+{
+ thread_wrapper_t *wrapper_data =
+ (thread_wrapper_t*) calloc (1, sizeof (thread_wrapper_t));
+ if (unlikely (!wrapper_data))
+ return -1;
+
+ wrapper_data->routine = routine;
+ wrapper_data->arg = arg;
+ wrapper_data->cancel = (cancel_t*) calloc (1, sizeof (cancel_t));
+
+ if (unlikely (!wrapper_data->cancel))
+ {
+ free (wrapper_data);
+ return -1;
+ }
+
+ int ret = pthread_create (thread_id, attr, thread_wrapper_routine,
+ wrapper_data);
+ if (unlikely (ret != 0))
+ {
+ // The thread wrapper should free these variables but it didn't start
+ free (wrapper_data->cancel);
+ free (wrapper_data);
+ }
+ return ret;
+}
+
+/**
+ * Thread wrapper
+ * Sets up signal handlers and thread-local data before running the routine
+ **/
+static void* thread_wrapper_routine (void *arg)
+{
+ thread_wrapper_t *wrapper_data = (thread_wrapper_t*) arg;
+
+ // Set up signal handler
+ struct sigaction act;
+ memset (&act, 0, sizeof (act));
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = thread_cancel_handler;
+ sigaction (SIGRTMIN, &act, NULL);
+
+ // Place specific data (cancel state stack)
+ cancel_t *canc = wrapper_data->cancel;
+ memset (canc, 0, sizeof (cancel_t));
+ if (unlikely (pthread_setspecific (cancel_key, canc) != 0))
+ return NULL;
+
+ void *ret = wrapper_data->routine (wrapper_data->arg);
+ // Don't free wrapper_data->cancel. It will be destroyed automatically.
+ free (wrapper_data);
+ return ret;
+}
+
+/**
+ * Change thread's cancellation state (enable/disable)
+ **/
+int pthread_setcancelstate (int state, int *oldstate)
+{
+ cancel_t *canc = pthread_getspecific (cancel_key);
+ if (unlikely (canc == NULL))
+ {
+ /// FIXME
+ // Let's just add this missing variable since the main thread
+ // uses these features but wasn't created by pthread_create_cancel
+ canc = (cancel_t*) calloc (1, sizeof (cancel_t));
+ pthread_setspecific (cancel_key, canc);
+ }
+
+ if (oldstate)
+ *oldstate = canc->state;
+ canc->state = state;
+
+ if (state == PTHREAD_CANCEL_ENABLE)
+ pthread_testcancel ();
+
+ return 0;
+}
+
+/**
+ * Create a cancellation point
+ **/
+void pthread_testcancel (void)
+{
+ cancel_t *canc = pthread_getspecific (cancel_key);
+ if (unlikely (!canc))
+ return; // Don't mess with the main thread
+
+ assert (canc->cond == NULL);
+
+ if (canc->cancelled) // Don't check PTHREAD_CANCEL_ENABLE
+ pthread_exit (NULL);
+}
+
+/**
+ * Cancellation signal handler
+ **/
+static void thread_cancel_handler (int signal)
+{
+ assert (signal == SIGRTMIN);
+
+ cancel_t *canc = (cancel_t*) pthread_getspecific (cancel_key);
+ if (unlikely (!canc))
+ return; // Main thread, can't be cancelled
+
+ canc->cancelled = true;
+ if (canc->cond)
+ {
+ /* Wakeup all threads waiting on cond. As we are supposed to expect
+ * spurious wakeups, this should not be an issue
+ */
+ pthread_cond_t *cond = canc->cond;
+ canc->cond = NULL;
+ pthread_cond_broadcast (cond);
+ /* FIXME: not calling pthread_exit (crashes in input thread). Why? */
+ // pthread_exit (NULL);
+ return;
+ }
+ if (canc->state == PTHREAD_CANCEL_ENABLE)
+ pthread_exit (NULL);
+}
+
+/**
+ * Destroy a cancel_t variable. Nothing fancy.
+ **/
+static void thread_cancel_destructor (void *data)
+{
+ cancel_t *canc = (cancel_t*) data;
+ free (canc);
+}
+
+int pthread_cond_wait_cancel( pthread_cond_t *cond,
+ pthread_mutex_t *mutex )
+{
+ int oldstate;
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
+ cancel_t *canc = pthread_getspecific (cancel_key);
+ if (canc)
+ {
+ assert (!canc->cond);
+ canc->cond = cond;
+ }
+
+ int ret = pthread_cond_wait (cond, mutex);
+
+ if (canc)
+ canc->cond = NULL;
+
+ /// FIXME: We should call testcancel() here, but it leads to crashes.
+ // pthread_testcancel ();
+ pthread_setcancelstate (oldstate, NULL);
+ return ret;
+}
+
+int pthread_cond_timedwait_cancel( pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime )
+{
+ int oldstate;
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
+ cancel_t *canc = pthread_getspecific (cancel_key);
+ if (canc)
+ {
+ assert (!canc->cond);
+ canc->cond = cond;
+ }
+
+ int ret = pthread_cond_timedwait (cond, mutex, abstime);
+
+ if (canc)
+ canc->cond = NULL;
+
+ /// FIXME: We should call testcancel() here, but it leads to crashes.
+ // pthread_testcancel ();
+ pthread_setcancelstate (oldstate, NULL);
+ return ret;
+}
diff --git a/configure.ac b/configure.ac
index ccc77f9..574f7f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -530,6 +530,10 @@ if test "${SYS}" = "mingw32" -a "${CXX}" != "" ; then
AC_LANG_POP(C++)
fi
+if test "${HAVE_ANDROID}" = "1"; then
+ AC_REPLACE_FUNCS([pthread_cancel])
+fi
+
dnl
dnl Buggy glibc prevention. Purposedly not cached.
dnl See sourceware.org bugs 5058 and 5443.
diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
index c694578..35c526c 100644
--- a/include/vlc_fixups.h
+++ b/include/vlc_fixups.h
@@ -342,6 +342,28 @@ long nrand48 (unsigned short subi[3]);
# undef __cplusplus
# endif
char *tempnam(const char *, const char *);
+
+#ifndef HAVE_PTHREAD_CANCEL
+enum
+{
+ PTHREAD_CANCEL_ENABLE,
+ PTHREAD_CANCEL_DISABLE
+};
+extern void pthread_cancel_initialize (void);
+extern void pthread_cancel_deinitialize (void);
+extern int pthread_create_cancel( pthread_t *thread,
+ const pthread_attr_t *attr,
+ void *( *routine ) ( void* ),
+ void *arg );
+extern int pthread_setcancelstate( int state, int *oldstate );
+extern int pthread_cancel( pthread_t thread_id );
+extern void pthread_testcancel( void );
+extern int pthread_cond_wait_cancel( pthread_cond_t *cond,
+ pthread_mutex_t *mutex );
+extern int pthread_cond_timedwait_cancel( pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime );
+#endif // PTHREAD_CANCEL
#endif // ANDROID
#ifdef __OS2__
diff --git a/src/control/error.c b/src/control/error.c
index e3f7051..f6827e7 100644
--- a/src/control/error.c
+++ b/src/control/error.c
@@ -25,6 +25,11 @@
#include <assert.h>
#include <vlc/libvlc.h>
+#if !defined(HAVE_PTHREAD_CANCEL) && defined(__ANDROID__)
+// Functions implemented in compat/pthread_cancel.c
+extern void pthread_cancel_initialize( void );
+extern void pthread_cancel_deinitialize( void );
+#endif
static const char oom[] = "Out of memory";
/* TODO: use only one thread-specific key for whole libvlc */
@@ -39,13 +44,24 @@ static void libvlc_setup_threads (bool init)
if (init)
{
if (refs++ == 0)
+ {
vlc_threadvar_create (&context, free);
+
+#if !defined(HAVE_PTHREAD_CANCEL) && defined(__ANDROID__)
+ pthread_cancel_initialize ();
+#endif
+ }
}
else
{
assert (refs > 0);
if (--refs == 0)
+ {
vlc_threadvar_delete (&context);
+#if !defined(HAVE_PTHREAD_CANCEL) && defined(__ANDROID__)
+ pthread_cancel_deinitialize ();
+#endif
+ }
}
vlc_mutex_unlock (&lock);
}
diff --git a/src/posix/thread.c b/src/posix/thread.c
index 561f93a..64b4fd3 100644
--- a/src/posix/thread.c
+++ b/src/posix/thread.c
@@ -371,7 +371,11 @@ void vlc_cond_broadcast (vlc_cond_t *p_condvar)
*/
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
+#ifdef __ANDROID__
+ int val = pthread_cond_wait_cancel( p_condvar, p_mutex );
+#else
int val = pthread_cond_wait( p_condvar, p_mutex );
+#endif
VLC_THREAD_ASSERT ("waiting on condition");
}
@@ -411,7 +415,11 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
#else
lldiv_t d = lldiv( deadline, CLOCK_FREQ );
struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };
+#ifdef __ANDROID__
+ int val = pthread_cond_timedwait_cancel (p_condvar, p_mutex, &ts);
+#else
int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
+#endif
if (val != ETIMEDOUT)
VLC_THREAD_ASSERT ("timed-waiting on condition");
return val;
@@ -451,6 +459,14 @@ void vlc_sem_destroy (vlc_sem_t *sem)
val = errno;
#endif
+#ifdef __ANDROID__
+ /* Bionic is so broken that it will return EBUSY on sem_destroy
+ * if the semaphore has never been used...
+ */
+ if (likely(val == EBUSY))
+ return; // It may be a real error, but there's no way to know
+#endif
+
VLC_THREAD_ASSERT ("destroying semaphore");
}
@@ -681,7 +697,11 @@ static int vlc_clone_attr (vlc_thread_t *th, pthread_attr_t *attr,
assert (ret == 0); /* fails iif VLC_STACKSIZE is invalid */
#endif
+#ifndef __ANDROID__
ret = pthread_create (th, attr, entry, data);
+#else
+ ret = pthread_create_cancel (th, attr, entry, data);
+#endif
pthread_sigmask (SIG_SETMASK, &oldset, NULL);
pthread_attr_destroy (attr);
return ret;
--
1.7.5.4
From 42ebdedb4367d621ac573089d9bf692ee069caf8 Mon Sep 17 00:00:00 2001
From: Dominique Martinet <asmadeus@codewreck.org>
Date: Thu, 2 Jun 2011 12:50:50 +0200
Subject: [PATCH 2/6] Android: use a custom poll(), fixes HTTP playback
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
---
include/vlc_fixups.h | 2 +-
src/network/poll.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 1 deletions(-)
diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
index 35c526c..c86fc3d 100644
--- a/include/vlc_fixups.h
+++ b/include/vlc_fixups.h
@@ -276,7 +276,7 @@ struct pollfd
};
# define poll(a, b, c) vlc_poll(a, b, c)
-#elif defined (HAVE_MAEMO)
+#elif defined (HAVE_MAEMO) || defined (__ANDROID__)
# include <poll.h>
# define poll(a, b, c) vlc_poll(a, b, c)
int vlc_poll (struct pollfd *, unsigned, int);
diff --git a/src/network/poll.c b/src/network/poll.c
index c1ca900..46ec3b5 100644
--- a/src/network/poll.c
+++ b/src/network/poll.c
@@ -60,6 +60,77 @@ int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
return ret;
}
+#elif defined (__ANDROID__)
+# include <vlc_network.h>
+# include <errno.h>
+
+int vlc_poll(struct pollfd *fds, nfds_t numfds, int timeout)
+{
+
+ /* On Android, an interruption (any signal) will cancel a call to poll,
+ * setting errno to EINTR. As a consequence, no need to do anything special
+ * to cancel poll().
+ * Since the cancellation mechanism should call pthread_exit() we just
+ * need to make sure this thread is not cancellable now.
+ */
+ int canc = vlc_savecancel ();
+
+ fd_set read_set;
+ fd_set write_set;
+ fd_set exception_set;
+ nfds_t i;
+ int n;
+ int rc;
+
+ FD_ZERO(&read_set);
+ FD_ZERO(&write_set);
+ FD_ZERO(&exception_set);
+ n = -1;
+ for (i = 0; i < numfds; i++)
+ {
+ if (fds[i].fd < 0)
+ continue;
+ if (fds[i].fd >= FD_SETSIZE) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (fds[i].events & POLLIN) FD_SET(fds[i].fd, &read_set);
+ if (fds[i].events & POLLOUT) FD_SET(fds[i].fd, &write_set);
+ if (fds[i].events & POLLERR) FD_SET(fds[i].fd, &exception_set);
+
+ if (fds[i].fd > n)
+ n = fds[i].fd;
+ };
+ if (n == -1)
+ /* Hey!? Nothing to poll, in fact!!! */
+ return 0;
+
+ if (timeout < 0)
+ rc = select(n+1, &read_set, &write_set, &exception_set, NULL);
+ else
+ {
+ struct timeval tv;
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = 1000 * (timeout % 1000);
+ rc = select(n+1, &read_set, &write_set, &exception_set, &tv);
+ }
+ if (rc < 0)
+ return rc;
+ for (i = 0; i < numfds; i++)
+ {
+ fds[i].revents = 0;
+ if (FD_ISSET(fds[i].fd, &read_set)) fds[i].revents |= POLLIN;
+ if (FD_ISSET(fds[i].fd, &write_set)) fds[i].revents |= POLLOUT;
+ if (FD_ISSET(fds[i].fd, &exception_set)) fds[i].revents |= POLLERR;
+ }
+
+ vlc_restorecancel (canc);
+ vlc_testcancel ();
+
+ return rc;
+}
+
#elif defined (HAVE_POLL)
# include <vlc_network.h>
--
1.7.5.4
From 59b79884f34229a3afbdaf64e43be73a0bc5ffa9 Mon Sep 17 00:00:00 2001
From: Jean-Baptiste Kempf <jb@videolan.org>
Date: Fri, 10 Jun 2011 16:48:26 +0200
Subject: [PATCH 3/6] No dtv on Android
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
---
modules/access/Modules.am | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/modules/access/Modules.am b/modules/access/Modules.am
index 3183db7..7578d88 100644
--- a/modules/access/Modules.am
+++ b/modules/access/Modules.am
@@ -133,6 +133,7 @@ libdtv_plugin_la_CFLAGS = $(AM_CFLAGS)
libdtv_plugin_la_LIBADD = $(AM_LIBADD)
libdtv_plugin_la_DEPENDENCIES =
+if !HAVE_ANDROID
if HAVE_LINUX
libdtv_plugin_la_SOURCES += dtv/linux.c