[Android] Media: add a new constructor from an AssetFileDescriptor
Thomas Guillem
git at videolan.org
Fri Aug 24 10:48:41 CEST 2018
vlc-android | branch: 4.0-glrenderer | Thomas Guillem <thomas at gllm.fr> | Fri Aug 24 09:46:22 2018 +0200| [6a39b3a468d6b4a2427cfa44f6cb5c1c9a09349f] | committer: Thomas Guillem
Media: add a new constructor from an AssetFileDescriptor
This can be used to open files from the apk asset folder.
Using the simple FileDescriptor constructor can't work since we need 2 extra
infos: the length and the offset of the file to read.
This new constructor uses the libvlc_media_new_callbacks() function.
> https://code.videolan.org/videolan/vlc-android/commit/6a39b3a468d6b4a2427cfa44f6cb5c1c9a09349f
---
libvlc/jni/libvlcjni-media.c | 119 +++++++++++++++++++++++++++++-
libvlc/src/org/videolan/libvlc/Media.java | 16 ++++
2 files changed, 133 insertions(+), 2 deletions(-)
diff --git a/libvlc/jni/libvlcjni-media.c b/libvlc/jni/libvlcjni-media.c
index f15fede05..33ecc5bfa 100644
--- a/libvlc/jni/libvlcjni-media.c
+++ b/libvlc/jni/libvlcjni-media.c
@@ -20,17 +20,31 @@
#include <stdlib.h>
#include <pthread.h>
+#include <unistd.h>
#include "libvlcjni-vlcobject.h"
#define META_MAX 25
+struct media_cb
+{
+ int fd;
+ uint64_t fd_offset;
+ uint64_t fd_length;
+ uint64_t offset;
+};
+
struct vlcjni_object_sys
{
pthread_mutex_t lock;
pthread_cond_t wait;
bool b_parsing_sync;
bool b_parsing_async;
+ struct {
+ int fd;
+ uint64_t offset;
+ uint64_t length;
+ } media_cb;
};
static const libvlc_event_type_t m_events[] = {
libvlc_MediaMetaChanged,
@@ -95,7 +109,7 @@ Media_event_cb(vlcjni_object *p_obj, const libvlc_event_t *p_ev,
return true;
}
-static void
+static int
Media_nativeNewCommon(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
{
p_obj->p_sys = calloc(1, sizeof(vlcjni_object_sys));
@@ -107,15 +121,17 @@ Media_nativeNewCommon(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
throw_Exception(env,
!p_obj->u.p_m ? VLCJNI_EX_ILLEGAL_STATE : VLCJNI_EX_OUT_OF_MEMORY,
"can't create Media instance");
- return;
+ return -1;
}
pthread_mutex_init(&p_obj->p_sys->lock, NULL);
pthread_cond_init(&p_obj->p_sys->wait, NULL);
+ p_obj->p_sys->media_cb.fd = -1;
VLCJniObject_attachEvents(p_obj, Media_event_cb,
libvlc_media_event_manager(p_obj->u.p_m),
m_events);
+ return 0;
}
static void
@@ -197,6 +213,105 @@ Java_org_videolan_libvlc_Media_nativeNewFromFd(JNIEnv *env, jobject thiz,
Media_nativeNewCommon(env, thiz, p_obj);
}
+static int
+media_cb_seek(void *opaque, uint64_t offset)
+{
+ struct media_cb *mcb = opaque;
+ if (lseek(mcb->fd, mcb->fd_offset + offset, SEEK_SET) == (off_t)-1)
+ return -1;
+ mcb->offset = offset;
+ return 0;
+}
+
+static int
+media_cb_open(void *opaque, void **datap, uint64_t *sizep)
+{
+ vlcjni_object *p_obj = opaque;
+ vlcjni_object_sys *p_sys = p_obj->p_sys;
+
+ struct media_cb *mcb = malloc(sizeof(*mcb));
+ if (!mcb)
+ return -1;
+
+ mcb->fd = dup(p_sys->media_cb.fd);
+ if (mcb->fd == -1)
+ {
+ free(mcb);
+ return -1;
+ }
+ mcb->fd_offset = p_sys->media_cb.offset;
+ mcb->fd_length = p_sys->media_cb.length;
+ mcb->offset = 0;
+
+ if (media_cb_seek(mcb, 0) != 0)
+ {
+ close(mcb->fd);
+ free(mcb);
+ return -1;
+ }
+
+ *sizep = p_sys->media_cb.length;
+ *datap = mcb;
+ return 0;
+}
+
+static ssize_t
+media_cb_read(void *opaque, unsigned char *buf, size_t len)
+{
+#define __MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
+
+ struct media_cb *mcb = opaque;
+ len = __MIN(len, mcb->fd_length - mcb->offset);
+ if (len == 0)
+ return 0;
+
+ ssize_t ret = read(mcb->fd, buf, len);
+ if (ret > 0)
+ mcb->offset += ret;
+ return ret;
+
+#undef __MIN
+}
+
+static void
+media_cb_close(void *opaque)
+{
+ struct media_cb *mcb = opaque;
+ close(mcb->fd);
+ free(mcb);
+}
+
+void
+Java_org_videolan_libvlc_Media_nativeNewFromFdWithOffsetLength(
+ JNIEnv *env, jobject thiz, jobject libVlc, jobject jfd, jlong offset, jlong length)
+{
+ vlcjni_object *p_obj;
+ int fd = FDObject_getInt(env, jfd);
+ if (fd == -1)
+ return;
+
+ p_obj = VLCJniObject_newFromJavaLibVlc(env, thiz, libVlc);
+ if (!p_obj)
+ return;
+
+ p_obj->u.p_m =
+ libvlc_media_new_callbacks(p_obj->p_libvlc,
+ media_cb_open,
+ media_cb_read,
+ media_cb_seek,
+ media_cb_close,
+ p_obj);
+
+
+ if (Media_nativeNewCommon(env, thiz, p_obj) == 0)
+ {
+ vlcjni_object_sys *p_sys = p_obj->p_sys;
+ p_sys->media_cb.fd = fd;
+ p_sys->media_cb.offset = offset;
+ p_sys->media_cb.length = length >= 0 ? length : UINT64_MAX;
+ }
+}
+
/* MediaList must be locked */
void
Java_org_videolan_libvlc_Media_nativeNewFromMediaList(JNIEnv *env, jobject thiz,
diff --git a/libvlc/src/org/videolan/libvlc/Media.java b/libvlc/src/org/videolan/libvlc/Media.java
index f297a3f39..0af51d6fb 100644
--- a/libvlc/src/org/videolan/libvlc/Media.java
+++ b/libvlc/src/org/videolan/libvlc/Media.java
@@ -20,6 +20,7 @@
package org.videolan.libvlc;
+import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.support.annotation.Nullable;
@@ -457,6 +458,20 @@ public class Media extends VLCObject<Media.Event> {
mUri = VLCUtil.UriFromMrl(nativeGetMrl());
}
+ /**
+ * Create a Media from libVLC and an AssetFileDescriptor
+ *
+ * @param libVLC a valid LibVLC
+ * @param afd asset file descriptor object
+ */
+ public Media(LibVLC libVLC, AssetFileDescriptor afd) {
+ super(libVLC);
+ long offset = afd.getStartOffset();
+ long length = afd.getLength();
+ nativeNewFromFdWithOffsetLength(libVLC, afd.getFileDescriptor(), offset, length);
+ mUri = VLCUtil.UriFromMrl(nativeGetMrl());
+ }
+
/**
*
* @param ml Should not be released and locked
@@ -862,6 +877,7 @@ public class Media extends VLCObject<Media.Event> {
private native void nativeNewFromPath(LibVLC libVLC, String path);
private native void nativeNewFromLocation(LibVLC libVLC, String location);
private native void nativeNewFromFd(LibVLC libVLC, FileDescriptor fd);
+ private native void nativeNewFromFdWithOffsetLength(LibVLC libVLC, FileDescriptor fd, long offset, long length);
private native void nativeNewFromMediaList(MediaList ml, int index);
private native void nativeRelease();
private native boolean nativeParseAsync(int flags, int timeout);
More information about the Android
mailing list