[Android] thumbnails: wait until seek succeeded

Rafaël Carré git at videolan.org
Wed Oct 31 21:16:09 CET 2012


vlc-ports/android | branch: master | Rafaël Carré <funman at videolan.org> | Wed Oct 31 21:14:21 2012 +0100| [7c581f5314a367549e0ae661a13aeceec7de1345] | committer: Rafaël Carré

thumbnails: wait until seek succeeded

we drop the first frame coming after seek, it might come from the start of the stream

> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=7c581f5314a367549e0ae661a13aeceec7de1345
---

 vlc-android/jni/thumbnailer.c |   62 ++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/vlc-android/jni/thumbnailer.c b/vlc-android/jni/thumbnailer.c
index 817ac5c..05bebba 100644
--- a/vlc-android/jni/thumbnailer.c
+++ b/vlc-android/jni/thumbnailer.c
@@ -57,11 +57,16 @@
    └————————————————————————————————————————————————————┘
 */
 
+enum {
+    THUMB_SEEKING,
+    THUMB_SEEKED,
+    THUMB_DROP_FIRST_FRAME,
+    THUMB_DONE,
+};
+
 typedef struct
 {
-    libvlc_media_player_t *mp;
-
-    bool hasThumb;
+    int state;
 
     char *thumbData;
     char *frameData;
@@ -71,8 +76,6 @@ typedef struct
     unsigned thumbHeight;
     unsigned thumbPitch;
 
-    unsigned nbReceivedFrames;
-
     pthread_mutex_t doneMutex;
     pthread_cond_t doneCondVar;
 } thumbnailer_sys_t;
@@ -96,18 +99,17 @@ static void thumbnailer_unlock(void *opaque, void *picture, void *const *pixels)
 {
     thumbnailer_sys_t *sys = opaque;
 
-    /* If we have already received a thumbnail, we skip this frame. */
+    /* If we have already received a thumbnail, or we are still seeking,
+     * we skip this frame. */
     pthread_mutex_lock(&sys->doneMutex);
-    bool hasThumb = sys->hasThumb;
+    int state = sys->state;
+    if (state == THUMB_SEEKED)
+        sys->state = THUMB_DROP_FIRST_FRAME;
     pthread_mutex_unlock(&sys->doneMutex);
-    if (hasThumb)
-        return;
-
-    /* Wait a few frames, to be sure they come after the seek succeeded */
-    if (++sys->nbReceivedFrames < 6)
+    if (state != THUMB_DROP_FIRST_FRAME)
         return;
 
-    /* Else we have received our first thumbnail and we can exit. */
+    /* we have received our first thumbnail and we can exit. */
     const char *dataSrc = sys->thumbData;
     char *dataDest = sys->frameData + sys->blackBorders * PIXEL_SIZE;
 
@@ -121,7 +123,7 @@ static void thumbnailer_unlock(void *opaque, void *picture, void *const *pixels)
 
     /* Signal that the thumbnail was created. */
     pthread_mutex_lock(&sys->doneMutex);
-    sys->hasThumb = true;
+    sys->state = THUMB_DONE;
     pthread_cond_signal(&sys->doneCondVar);
     pthread_mutex_unlock(&sys->doneMutex);
 }
@@ -151,7 +153,7 @@ jbyteArray Java_org_videolan_vlc_LibVLC_getThumbnail(JNIEnv *env, jobject thiz,
     pthread_cond_init(&sys->doneCondVar, NULL);
 
     /* Create a media player playing environment */
-    sys->mp = libvlc_media_player_new(libvlc);
+    libvlc_media_player_t *mp = libvlc_media_player_new(libvlc);
 
     libvlc_media_t *m = new_media(instance, env, thiz, filePath, true, false);
     if (m == NULL)
@@ -165,7 +167,7 @@ jbyteArray Java_org_videolan_vlc_LibVLC_getThumbnail(JNIEnv *env, jobject thiz,
     libvlc_media_add_option( m, ":no-spu" );
     libvlc_media_add_option( m, ":no-osd" );
 
-    libvlc_media_player_set_media(sys->mp, m);
+    libvlc_media_player_set_media(mp, m);
 
     /* Get the size of the video with the tracks information of the media. */
     libvlc_media_track_info_t *tracks;
@@ -243,31 +245,41 @@ jbyteArray Java_org_videolan_vlc_LibVLC_getThumbnail(JNIEnv *env, jobject thiz,
     }
 
     /* Set the video format and the callbacks. */
-    libvlc_video_set_format(sys->mp, "RGBA", thumbWidth, thumbHeight, sys->thumbPitch);
-    libvlc_video_set_callbacks(sys->mp, thumbnailer_lock, thumbnailer_unlock,
+    libvlc_video_set_format(mp, "RGBA", thumbWidth, thumbHeight, sys->thumbPitch);
+    libvlc_video_set_callbacks(mp, thumbnailer_lock, thumbnailer_unlock,
                                NULL, (void*)sys);
+    sys->state = THUMB_SEEKING;
 
     /* Play the media. */
-    libvlc_media_player_play(sys->mp);
-    libvlc_media_player_set_position(sys->mp, THUMBNAIL_POSITION);
+    libvlc_media_player_play(mp);
+    libvlc_media_player_set_position(mp, THUMBNAIL_POSITION);
+
+    int loops = 100;
+    for (;;) {
+        float pos = libvlc_media_player_get_position(mp);
+        if (pos < THUMBNAIL_POSITION || !loops--)
+            break;
+        usleep(50000);
+    }
 
     /* Wait for the thumbnail to be generated. */
     pthread_mutex_lock(&sys->doneMutex);
+    sys->state = THUMB_SEEKED;
     struct timespec deadline;
     clock_gettime(CLOCK_REALTIME, &deadline);
     deadline.tv_sec += 10; /* amount of seconds before we abort thumbnailer */
-    while (!sys->hasThumb) {
+    do {
         int ret = pthread_cond_timedwait(&sys->doneCondVar, &sys->doneMutex, &deadline);
         if (ret == ETIMEDOUT)
             break;
-    }
+    } while (sys->state != THUMB_DONE);
     pthread_mutex_unlock(&sys->doneMutex);
 
     /* Stop and release the media player. */
-    libvlc_media_player_stop(sys->mp);
-    libvlc_media_player_release(sys->mp);
+    libvlc_media_player_stop(mp);
+    libvlc_media_player_release(mp);
 
-    if (sys->hasThumb) {
+    if (sys->state == THUMB_DONE) {
         /* Create the Java byte array to return the create thumbnail. */
         byteArray = (*env)->NewByteArray(env, frameSize);
         if (byteArray == NULL)



More information about the Android mailing list