[vlc-commits] input: add chained demux functions

Rémi Denis-Courmont git at videolan.org
Thu Jun 30 20:28:25 CEST 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu Jun 30 21:10:22 2016 +0300| [4bc7a87939eac8ca9475823f7bd3c835eda2838b] | committer: Rémi Denis-Courmont

input: add chained demux functions

This provides the same functionality as stream_Demux using stream FIFO
underneath.

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

 include/vlc_demux.h       |   79 ++++++++++++++++++++++
 src/Makefile.am           |    1 +
 src/input/demux_chained.c |  161 +++++++++++++++++++++++++++++++++++++++++++++
 src/libvlccore.sym        |    4 ++
 4 files changed, 245 insertions(+)

diff --git a/include/vlc_demux.h b/include/vlc_demux.h
index 9200a64..4af382c 100644
--- a/include/vlc_demux.h
+++ b/include/vlc_demux.h
@@ -441,6 +441,85 @@ VLC_API void demux_PacketizerDestroy( decoder_t *p_packetizer );
     } while(0)
 
 /**
+ * \defgroup chained_demux Chained demultiplexer
+ * Demultiplexers wrapped by another demultiplexer
+ * @{
+ */
+
+typedef struct vlc_demux_chained_t vlc_demux_chained_t;
+
+/**
+ * Creates a chained demuxer.
+ *
+ * This creates a thread running a demuxer whose input stream is generated
+ * directly by the caller. This typically handles some sort of stream within a
+ * stream, e.g. MPEG-TS within something else.
+ *
+ * \note There are a number of limitations to this approach. The chained
+ * demuxer is run asynchronously in a separate thread. Most demuxer controls
+ * are synchronous and therefore unavailable in this case. Also the input
+ * stream is a simple FIFO, so the chained demuxer cannot perform seeks.
+ * Lastly, most errors cannot be detected.
+ *
+ * \param parent parent VLC object
+ * \param name chained demux module name (e.g. "ts")
+ * \param out elementary stream output for the chained demux
+ * \return a non-NULL pointer on success, NULL on failure.
+ */
+VLC_API vlc_demux_chained_t *vlc_demux_chained_New(vlc_object_t *parent,
+                                                   const char *name,
+                                                   es_out_t *out);
+
+/**
+ * Destroys a chained demuxer.
+ *
+ * Sends an end-of-stream to the chained demuxer, and releases all underlying
+ * allocated resources.
+ */
+VLC_API void vlc_demux_chained_Delete(vlc_demux_chained_t *);
+
+/**
+ * Sends data to a chained demuxer.
+ *
+ * This queues data for a chained demuxer to consume.
+ *
+ * \param block data block to queue
+ */
+VLC_API void vlc_demux_chained_Send(vlc_demux_chained_t *, block_t *block);
+
+/**
+ * Controls a chained demuxer.
+ *
+ * This performs a <b>demux</b> (i.e. DEMUX_...) control request on a chained
+ * demux.
+ *
+ * \note In most cases, vlc_demux_chained_Control() should be used instead.
+ * \warning As per vlc_demux_chained_New(), most demux controls are not, and
+ * cannot be, supported; VLC_EGENERIC is returned.
+ *
+ * \param query demux control (see \ref demux_query_e)
+ * \param args variable arguments (depending on the query)
+ */
+VLC_API int vlc_demux_chained_ControlVa(vlc_demux_chained_t *, int query,
+                                        va_list args);
+
+static inline int vlc_demux_chained_Control(vlc_demux_chained_t *dc, int query,
+                                            ...)
+{
+    va_list ap;
+    int ret;
+
+    va_start(ap, query);
+    ret = vlc_demux_chained_ControlVa(dc, query, ap);
+    va_end(ap);
+    return ret;
+}
+
+/**
+ * @}
+ */
+
+/**
  * @}
  */
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 2720564..6f387f9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -358,6 +358,7 @@ SOURCES_libvlc_common = \
 	input/decoder.c \
 	input/decoder_synchro.c \
 	input/demux.c \
+	input/demux_chained.c \
 	input/es_out.c \
 	input/es_out_timeshift.c \
 	input/event.c \
diff --git a/src/input/demux_chained.c b/src/input/demux_chained.c
new file mode 100644
index 0000000..270c603
--- /dev/null
+++ b/src/input/demux_chained.c
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * demux_chained.c
+ *****************************************************************************
+ * Copyright (C) 1999-2016 VLC authors and VideoLAN
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *          Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vlc_common.h>
+#include <vlc_demux.h>
+#include "demux.h"
+
+struct vlc_demux_chained_t
+{
+    stream_t *fifo;
+
+    vlc_thread_t thread;
+    vlc_mutex_t  lock;
+
+    struct
+    {
+        double  position;
+        int64_t length;
+        int64_t time;
+    } stats;
+
+    es_out_t *out;
+    char name[];
+};
+
+static void *vlc_demux_chained_Thread(void *data)
+{
+    vlc_demux_chained_t *dc = data;
+    demux_t *demux = demux_NewAdvanced(dc->fifo, NULL, "", dc->name, "",
+                                       dc->fifo, dc->out, false);
+    if (demux == NULL)
+        return NULL;
+
+    /* Stream FIFO cannot apply DVB filters.
+     * Get all programs and let the E/S output sort them out. */
+    demux_Control(demux, DEMUX_SET_GROUP, -1, NULL);
+
+    /* Main loop */
+    mtime_t next_update = 0;
+
+    do
+        if (demux_TestAndClearFlags(demux, UINT_MAX) || mdate() >= next_update)
+        {
+            double newpos;
+            int64_t newlen, newtime;
+
+            if (demux_Control(demux, DEMUX_GET_POSITION, &newpos))
+                newpos = 0.;
+            if (demux_Control(demux, DEMUX_GET_LENGTH, &newlen))
+                newlen = 0;
+            if (demux_Control(demux, DEMUX_GET_TIME, &newtime))
+                newtime = 0;
+
+            vlc_mutex_lock(&dc->lock);
+            dc->stats.position = newpos;
+            dc->stats.length = newlen;
+            dc->stats.time = newtime;
+            vlc_mutex_unlock(&dc->lock);
+
+            next_update = mdate() + (CLOCK_FREQ / 4);
+        }
+    while (demux_Demux(demux) > 0);
+
+    demux_Delete(demux);
+    return NULL;
+}
+
+vlc_demux_chained_t *vlc_demux_chained_New(vlc_object_t *parent,
+                                           const char *name, es_out_t *out)
+{
+    vlc_demux_chained_t *dc = malloc(sizeof (*dc) + strlen(name) + 1);
+    if (unlikely(dc == NULL))
+        return NULL;
+
+    dc->fifo = vlc_stream_fifo_New(parent);
+    if (dc->fifo == NULL)
+    {
+        free(dc);
+        return NULL;
+    }
+
+    dc->stats.position = 0.;
+    dc->stats.length = 0;
+    dc->stats.time = 0;
+    dc->out = out;
+    strcpy(dc->name, name);
+
+    if (vlc_clone(&dc->thread, vlc_demux_chained_Thread, dc,
+                  VLC_THREAD_PRIORITY_INPUT))
+    {
+        stream_Delete(dc->fifo);
+        vlc_stream_fifo_Close(dc->fifo);
+        free(dc);
+        dc = NULL;
+    }
+    return dc;
+}
+
+void vlc_demux_chained_Send(vlc_demux_chained_t *dc, block_t *block)
+{
+    vlc_stream_fifo_Queue(dc->fifo, block);
+}
+
+int vlc_demux_chained_ControlVa(vlc_demux_chained_t *dc, int query, va_list ap)
+{
+    switch (query)
+    {
+        case DEMUX_GET_POSITION:
+            vlc_mutex_lock(&dc->lock);
+            *va_arg(ap, double *) = dc->stats.position;
+            vlc_mutex_unlock(&dc->lock);
+            break;
+        case DEMUX_GET_LENGTH:
+            vlc_mutex_lock(&dc->lock);
+            *va_arg(ap, int64_t *) = dc->stats.length;
+            vlc_mutex_unlock(&dc->lock);
+            break;
+        case DEMUX_GET_TIME:
+            vlc_mutex_lock(&dc->lock);
+            *va_arg(ap, int64_t *) = dc->stats.time;
+            vlc_mutex_unlock(&dc->lock);
+            break;
+        default:
+            return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+void vlc_demux_chained_Delete(vlc_demux_chained_t *dc)
+{
+    vlc_stream_fifo_Close(dc->fifo);
+    vlc_join(dc->thread, NULL);
+    free(dc);
+}
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index c2f270b..ba9f581 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -97,6 +97,10 @@ demux_PacketizerNew
 demux_New
 demux_vaControl
 demux_vaControlHelper
+vlc_demux_chained_New
+vlc_demux_chained_Send
+vlc_demux_chained_ControlVa
+vlc_demux_chained_Delete
 EndMD5
 es_format_Clean
 es_format_Copy



More information about the vlc-commits mailing list