Commit 4bc7a879 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

input: add chained demux functions

This provides the same functionality as stream_Demux using stream FIFO
underneath.
parent c5143849
......@@ -440,6 +440,85 @@ VLC_API void demux_PacketizerDestroy( decoder_t *p_packetizer );
if( !p_demux->p_sys ) return VLC_ENOMEM;\
} 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;
}
/**
* @}
*/
/**
* @}
*/
......
......@@ -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 \
......
/*****************************************************************************
* 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);
}
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment