[vlc-commits] dmxmus: compute length and position

Rémi Denis-Courmont git at videolan.org
Sun Dec 22 15:38:46 CET 2019


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Dec 21 20:07:38 2019 +0200| [ec491b8e28512aff0ba7f2cfe949f4a336fff2d4] | committer: Rémi Denis-Courmont

dmxmus: compute length and position

This only works if the stream is seekable, since the only way to
compute the length is to read the whole file.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ec491b8e28512aff0ba7f2cfe949f4a336fff2d4
---

 modules/demux/dmxmus.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 76 insertions(+), 5 deletions(-)

diff --git a/modules/demux/dmxmus.c b/modules/demux/dmxmus.c
index 21c1d327d0..84110bdf1c 100644
--- a/modules/demux/dmxmus.c
+++ b/modules/demux/dmxmus.c
@@ -36,6 +36,8 @@ typedef struct
     es_out_id_t *es;
     date_t pts; /*< Play timestamp */
     vlc_tick_t tick; /*< Last tick timestamp */
+    vlc_tick_t length; /*< Total length */
+    uint16_t start_offset; /*< Start byte offset of music events */
     unsigned end_offset:17; /*< End byte offset of music events */
     unsigned primaries:4; /*< Number of primary channels (0-9) */
     unsigned secondaries:3; /*< Number of secondary channels (10-14) */
@@ -310,6 +312,45 @@ static int Demux(demux_t *demux)
     return VLC_DEMUXER_SUCCESS;
 }
 
+static int SeekSet0(demux_t *demux)
+{
+    demux_sys_t *sys = demux->p_sys;
+
+    if (vlc_stream_Seek(demux->s, sys->start_offset))
+        return -1;
+
+    date_Set(&sys->pts, VLC_TICK_0);
+    return 0;
+}
+
+/**
+ * Gets the total length in ticks.
+ *
+ * @note This function clobbers the read offset of the byte stream.
+ */
+static vlc_tick_t GetLength(demux_t *demux)
+{
+    demux_sys_t *sys = demux->p_sys;
+    unsigned parts = 0;
+
+    if (SeekSet0(demux))
+        return VLC_TICK_INVALID;
+
+    for (;;) {
+        unsigned char buf[3];
+        unsigned delay;
+
+        if (ReadEvent(demux, buf, &delay)
+         || MUS_EV(buf[0]) == MUS_EV_TRACK_END
+         || vlc_stream_Tell(demux->s) >= sys->end_offset)
+            break;
+
+        parts += delay;
+    }
+
+    return vlc_tick_from_samples(parts, MUS_FREQ);
+}
+
 static int Control(demux_t *demux, int query, va_list args)
 {
     demux_sys_t *sys = demux->p_sys;
@@ -319,11 +360,26 @@ static int Control(demux_t *demux, int query, va_list args)
             *va_arg(args, bool *) = false; /* TODO */
             break;
 
-        case DEMUX_GET_POSITION:
+        case DEMUX_GET_POSITION: {
+            double pos = 0.;
+
+            static_assert(VLC_TICK_INVALID <= 0, "Oops");
+            if (sys->length > 0)
+                pos = (date_Get(&sys->pts) - VLC_TICK_0) * 1. / sys->length;
+
+            *va_arg(args, double *) = pos;
+            break;
+        }
+
         case DEMUX_SET_POSITION:
-        case DEMUX_GET_LENGTH:
             return VLC_EGENERIC;
 
+        case DEMUX_GET_LENGTH:
+            if (sys->length == VLC_TICK_INVALID)
+                return VLC_EGENERIC;
+            *va_arg(args, vlc_tick_t *) = sys->length;
+            break;
+
         case DEMUX_GET_TIME:
             *va_arg(args, vlc_tick_t *) = date_Get(&sys->pts) - VLC_TICK_0;
             break;
@@ -366,8 +422,7 @@ static int Open(vlc_object_t *obj)
     size_t instc = GetWLE(hdr + 12);
     size_t hdrlen = 16 + 2 * instc;
 
-    if (offset < hdrlen
-     || vlc_stream_Read(stream, NULL, offset) < (ssize_t)offset)
+    if (offset < hdrlen)
         return VLC_EGENERIC;
 
     msg_Dbg(demux, "MIDI channels: %u primary, %u secondary",
@@ -377,11 +432,28 @@ static int Open(vlc_object_t *obj)
     if (unlikely(sys == NULL))
         return VLC_ENOMEM;
 
+    demux->p_sys = sys;
+    sys->start_offset = offset;
     sys->end_offset = (uint_fast32_t)offset + (uint_fast32_t)length;
     sys->primaries = primaries;
     sys->secondaries = secondaries;
     memset(sys->volume, 0, sizeof (sys->volume));
 
+    bool can_seek;
+    vlc_stream_Control(demux->s, STREAM_CAN_SEEK, &can_seek);
+    if (can_seek) {
+        sys->length = GetLength(demux);
+
+        if (SeekSet0(demux))
+            return VLC_EGENERIC;
+    } else {
+        sys->length = VLC_TICK_INVALID;
+        offset -= hdrlen;
+
+        if (vlc_stream_Read(stream, NULL, offset) < (ssize_t)offset)
+            return VLC_EGENERIC;
+    }
+
     es_format_t fmt;
 
     es_format_Init(&fmt, AUDIO_ES, VLC_CODEC_MIDI);
@@ -393,7 +465,6 @@ static int Open(vlc_object_t *obj)
     date_Set(&sys->pts, VLC_TICK_0);
     sys->tick = VLC_TICK_0;
 
-    demux->p_sys = sys;
     demux->pf_demux = Demux;
     demux->pf_control = Control;
     return VLC_SUCCESS;



More information about the vlc-commits mailing list