From 2db554d34ad2bb8f2e892abf287343bdcbe9c862 Mon Sep 17 00:00:00 2001
From: Petri Hintukainen <phintuka@users.sourceforge.net>
Date: Thu, 30 Jan 2014 15:51:42 +0200
Subject: [PATCH 07/17] bluray: implement still image timing

---
 modules/access/bluray.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index e2dbdfa..867f508 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -136,6 +136,13 @@ struct  demux_sys_t
     bluray_overlay_t    *p_overlays[MAX_OVERLAY];
     int                 current_overlay; // -1 if no current overlay;
     bool                b_menu;
+    struct
+    {
+      bool         b_enabled;
+      bool         b_expired;
+      vlc_mutex_t  lock;
+      vlc_timer_t  timer;
+    } still;
 
     /* */
     input_thread_t      *p_input;
@@ -209,6 +216,7 @@ static int   bluraySetTitle(demux_t *p_demux, int i_title);
 static void  blurayOverlayProc(void *ptr, const BD_OVERLAY * const overlay);
 static void  blurayArgbOverlayProc(void *ptr, const BD_ARGB_OVERLAY * const overlay);
 
+static void  blurayStillTimer(void *);
 static int   onMouseEvent(vlc_object_t *p_vout, const char *psz_var,
                           vlc_value_t old, vlc_value_t val, void *p_data);
 
@@ -425,6 +433,14 @@ static int blurayOpen(vlc_object_t *object)
         goto error;
     }
 
+    p_sys->still.b_enabled = false;
+    p_sys->still.b_expired = false;
+    vlc_mutex_init(&p_sys->still.lock);
+    if (vlc_timer_create(&p_sys->still.timer, blurayStillTimer, p_sys)) {
+        msg_Err(p_demux, "Failed to create still image timer");
+        goto error;
+    }
+
     p_demux->pf_control = blurayControl;
     p_demux->pf_demux   = blurayDemux;
 
@@ -447,6 +463,10 @@ static void blurayClose(vlc_object_t *object)
     demux_t *p_demux = (demux_t*)object;
     demux_sys_t *p_sys = p_demux->p_sys;
 
+    /* Stop still image handler */
+    vlc_timer_destroy(p_sys->still.timer);
+    vlc_mutex_destroy(&p_sys->still.lock);
+
     /*
      * Close libbluray first.
      * This will close all the overlays before we release p_vout
@@ -1406,6 +1426,52 @@ static int blurayControl(demux_t *p_demux, int query, va_list args)
     return VLC_SUCCESS;
 }
 
+static void blurayStillTimer( void *p_data )
+{
+    demux_sys_t *p_sys = p_data;
+
+    vlc_mutex_lock(&p_sys->still.lock);
+    if (p_sys->still.b_enabled) {
+        p_sys->still.b_enabled = false;
+        /* do not call bd_read_skip_still() here (BD_EVENT_STILL_TIME may be being processed) */
+        p_sys->still.b_expired = true;
+    }
+    vlc_mutex_unlock( &p_sys->still.lock );
+}
+
+static void blurayStillImage( demux_t *p_demux, unsigned timeout )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    bool b_empty, b_sleep = true;
+
+    // display last frame as still image (timed / infinite)
+    //   * when got this event with non-zero time and still timer is not running, initialize still timer
+    //   * when timer times out, call bd_read_skip_still()
+    if (timeout) {
+        vlc_mutex_lock( &p_sys->still.lock );
+
+        if (p_sys->still.b_expired) {
+            msg_Dbg(p_demux, "Still image end");
+            bd_read_skip_still(p_sys->bluray);
+            b_sleep = false;
+
+        } else if (!p_sys->still.b_enabled) {
+            msg_Dbg(p_demux, "Still image (%d seconds)", timeout);
+            p_sys->still.b_enabled = true;
+            vlc_timer_schedule( p_sys->still.timer, false, timeout * CLOCK_FREQ, 0 );
+        }
+        p_sys->still.b_expired = false;
+        vlc_mutex_unlock( &p_sys->still.lock );
+    } else {
+        msg_Dbg(p_demux, "Still frame (infinite)");
+    }
+
+    /* avoid busy loops (read returns no data) */
+    if (b_sleep) {
+        msleep( 40000 );
+    }
+}
+
 static void blurayStreamSelect(demux_t *p_demux, unsigned type, unsigned id)
 {
     demux_sys_t *p_sys = p_demux->p_sys;
@@ -1502,6 +1568,12 @@ static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e)
     case BD_EVENT_IG_STREAM:
         break;
 
+    /*
+     * playback control events
+     */
+    case BD_EVENT_STILL_TIME:
+        blurayStillImage(p_demux, e->param);
+        break;
     case BD_EVENT_DISCONTINUITY:
         /* reset demuxer (partially decoded PES packets must be dropped) */
         blurayResetParser(p_demux);
-- 
1.8.3.2

