stream_extractor.c 5.24 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/*****************************************************************************
 * stream_extractor.c
 *****************************************************************************
 * Copyright (C) 2016 VLC authors and VideoLAN
 *
 * 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.
 *****************************************************************************/

#ifndef STREAM_EXTRACTOR_H
#define STREAM_EXTRACTOR_H

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_stream.h>
#include <vlc_stream_extractor.h>
#include <vlc_modules.h>
#include <vlc_url.h>
#include <vlc_memstream.h>
#include <libvlc.h>
#include <assert.h>

#include "stream.h"

/**
 * \defgroup stream_extractor_Private Stream Extractor Private
 * \ingroup stream_extractor
 * \internal
 * @{
 * \file
 **/

struct stream_extractor_private {
    stream_extractor_t public;
    stream_t* stream;
    module_t* module;

    vlc_object_t* owner;
};

/**
 * Release the private data associated with a stream-extractor
 *
 * \param priv pointer to the private section
 */
static void se_Release( struct stream_extractor_private* priv )
{
    free( priv->public.identifier );

    if( priv->module )
    {
        module_unneed( &priv->public, priv->module );
        vlc_stream_Delete( priv->public.source );
    }

    vlc_object_release( &priv->public );
}

/**
 * \defgroup stream_extractor_Callbacks Stream Extractor Callbacks
 * \ingroup stream_extractor
 * @{
 *   \file
 *   These functions simply forwards the relevant stream-request to
 *   the underlying stream-extractor. They are a basic form of
 *   type-erasure in that the outside world sees a stream_t, but the
 *   work is actually done by a stream_extractor_t.
 */

static void
se_StreamDelete( stream_t* stream )
{
    se_Release( stream->p_sys );
}

static ssize_t
se_StreamRead( stream_t* stream, void* buf, size_t len )
{
    struct stream_extractor_private* priv = stream->p_sys;
    stream_extractor_t* extractor = &priv->public;
    return extractor->stream.pf_read( extractor, buf, len );
}

static block_t*
se_StreamBlock( stream_t* stream, bool* eof )
{
    struct stream_extractor_private* priv = stream->p_sys;
    stream_extractor_t* extractor = &priv->public;
    return extractor->stream.pf_block( extractor, eof );
}

static int
se_StreamSeek( stream_t* stream, uint64_t offset )
{
    struct stream_extractor_private* priv = stream->p_sys;
    stream_extractor_t* extractor = &priv->public;
    return extractor->stream.pf_seek( extractor, offset );
}

static int
se_StreamReadDir( stream_t* stream, input_item_node_t* node )
{
    struct stream_extractor_private* priv = stream->p_sys;
    stream_extractor_t* extractor = &priv->public;
    return extractor->directory.pf_readdir( extractor, node );
}

static int
se_StreamControl( stream_t* stream, int req, va_list args )
{
    struct stream_extractor_private* priv = stream->p_sys;
    stream_extractor_t* extractor = &priv->public;

    if( extractor->identifier )
        return extractor->stream.pf_control( extractor, req, args );

    if( req == STREAM_IS_DIRECTORY )
    {
        *va_arg( args, bool* ) = true;
        return VLC_SUCCESS;
    }

    return VLC_EGENERIC;
}
/**
 * @}
 **/

/**
 * Initialize the public stream_t for a stream_extractor_t
 *
 * This function simply initializes the relevant data-members of the
 * public stream_t which is a handle to the internal
 * stream_extractor_t.
 *
 * \param obj the private section of the stream_extractor_t
 * \param source the source stream which the stream_extractor_t should
 *        will read from
 * \return VLC_SUCCESS on success, an error-code on failure.
 **/
static int
se_InitStream( struct stream_extractor_private* priv, stream_t* source )
{
    stream_t* s = vlc_stream_CommonNew( priv->public.obj.parent,
                                        se_StreamDelete );
    if( unlikely( !s ) )
        return VLC_EGENERIC;

    if( priv->public.identifier )
    {
        if( priv->public.stream.pf_read ) s->pf_read = se_StreamRead;
        else                              s->pf_block = se_StreamBlock;

        s->pf_seek = se_StreamSeek;
        s->psz_url = NULL;
    }
    else
    {
        s->pf_readdir = se_StreamReadDir;
        s->psz_url = source->psz_url ? strdup( source->psz_url ) : NULL;
    }


    if( source->psz_url && unlikely( !s->psz_url ) )
    {
        stream_CommonDelete( s );
        return VLC_EGENERIC;
    }

    priv->stream = s;
    priv->stream->pf_control = se_StreamControl;
    priv->stream->p_input = source->p_input;
    priv->stream->p_sys = priv;

    return VLC_SUCCESS;
}

/**
 * @}
 **/

#endif /* include-guard */