vlc_demux.h 8.27 KB
Newer Older
1
/*****************************************************************************
2
 * vlc_demux.h: Demuxer descriptor, queries and methods
3
 *****************************************************************************
4
 * Copyright (C) 1999-2005 the VideoLAN team
5
 * $Id$
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 23
 *****************************************************************************/

24 25 26 27
#if !defined( __LIBVLC__ )
  #error You are not libvlc or one of its plugins. You cannot include this file
#endif

28 29 30
#ifndef _VLC_DEMUX_H
#define _VLC_DEMUX_H 1

Clément Stenac's avatar
Clément Stenac committed
31 32 33 34
#include <vlc_es.h>
#include <vlc_stream.h>
#include <vlc_es_out.h>

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/**
 * \defgroup demux Demux
 * @{
 */

struct demux_t
{
    VLC_COMMON_MEMBERS

    /* Module properties */
    module_t    *p_module;

    /* eg informative but needed (we can have access+demux) */
    char        *psz_access;
    char        *psz_demux;
    char        *psz_path;

    /* input stream */
    stream_t    *s;     /* NULL in case of a access+demux in one */

    /* es output */
56
    es_out_t    *out;   /* our p_es_out */
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

    /* set by demuxer */
    int (*pf_demux)  ( demux_t * );   /* demux one frame only */
    int (*pf_control)( demux_t *, int i_query, va_list args);

    /* Demux has to maintain them uptodate
     * when it is responsible of seekpoint/title */
    struct
    {
        unsigned int i_update;  /* Demux sets them on change,
                                   Input removes them once take into account*/
        /* Seekpoint/Title at demux level */
        int          i_title;       /* idem, start from 0 (could be menu) */
        int          i_seekpoint;   /* idem, start from 0 */
    } info;
    demux_sys_t *p_sys;
};

enum demux_query_e
{
    /* I. Common queries to access_demux and demux */
    /* POSITION double between 0.0 and 1.0 */
    DEMUX_GET_POSITION,         /* arg1= double *       res=    */
    DEMUX_SET_POSITION,         /* arg1= double         res=can fail    */

    /* LENGTH/TIME in microsecond, 0 if unknown */
    DEMUX_GET_LENGTH,           /* arg1= int64_t *      res=    */
    DEMUX_GET_TIME,             /* arg1= int64_t *      res=    */
    DEMUX_SET_TIME,             /* arg1= int64_t        res=can fail    */

    /* TITLE_INFO only if more than 1 title or 1 chapter */
    DEMUX_GET_TITLE_INFO,       /* arg1=input_title_t*** arg2=int* can fail */

    /* TITLE/SEEKPOINT, only when TITLE_INFO succeed */
    DEMUX_SET_TITLE,            /* arg1= int            can fail */
    DEMUX_SET_SEEKPOINT,        /* arg1= int            can fail */

94 95 96 97 98 99
    /* DEMUX_SET_GROUP only a hit for demuxer (mainly DVB) to allow not
     * reading everything (you should not use this to call es_out_Control)
     * if you don't know what to do with it, just IGNORE it, it is safe(r)
     * -1 means all group, 0 default group (first es added) */
    DEMUX_SET_GROUP,            /* arg1= int            can fail */

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    /* Ask the demux to demux until the given date at the next pf_demux call
     * but not more (and not less, at the precision avaiable of course).
     * XXX: not mandatory (except for subtitle demux) but I will help a lot
     * for multi-input
     */
    DEMUX_SET_NEXT_DEMUX_TIME,  /* arg1= int64_t *      can fail */
    /* FPS for correct subtitles handling */
    DEMUX_GET_FPS,              /* arg1= float *        res=can fail    */
    /* Meta data */
    DEMUX_GET_META,             /* arg1= vlc_meta_t **  res=can fail    */


    /* II. Specific access_demux queries */
    DEMUX_CAN_PAUSE,            /* arg1= vlc_bool_t*    cannot fail */
    DEMUX_CAN_CONTROL_PACE,     /* arg1= vlc_bool_t*    cannot fail */
    DEMUX_GET_PTS_DELAY,        /* arg1= int64_t*       cannot fail */
116 117
    DEMUX_SET_PAUSE_STATE,      /* arg1= vlc_bool_t     can fail */
    DEMUX_GET_ATTACHMENTS       /* arg1= int, arg2= attachment_t***   can fail */
118 119 120 121
};

VLC_EXPORT( int,       demux2_vaControlHelper, ( stream_t *, int64_t i_start, int64_t i_end, int i_bitrate, int i_align, int i_query, va_list args ) );

122 123 124 125
/*************************************************************************
 * Miscellaneous helpers for demuxers
 *************************************************************************/

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
126
static inline vlc_bool_t isExtension( demux_t *p_demux, const char *psz_requested )
127
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
128
    const char *psz_ext = strrchr ( p_demux->psz_path, '.' );
129 130 131 132
    if( !psz_ext || strcmp( psz_ext, psz_requested ) )
        return VLC_FALSE;
    return VLC_TRUE;
}
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
133 134

static inline vlc_bool_t isDemux( demux_t *p_demux, const char *psz_requested )
135 136 137 138 139 140 141 142 143
{
   if( !p_demux->psz_demux || strcmp( p_demux->psz_demux, psz_requested ) )
        return VLC_FALSE;
    return VLC_TRUE;
}

#define STANDARD_DEMUX_INIT \
    p_demux->pf_control = Control; \
    p_demux->pf_demux = Demux; \
144 145
    MALLOC_ERR( p_demux->p_sys, demux_sys_t ); \
    memset( p_demux->p_sys, 0, sizeof( demux_sys_t ) );
146 147 148 149 150

#define STANDARD_DEMUX_INIT_MSG( msg ) \
    p_demux->pf_control = Control; \
    p_demux->pf_demux = Demux; \
    MALLOC_ERR( p_demux->p_sys, demux_sys_t ); \
151
    memset( p_demux->p_sys, 0, sizeof( demux_sys_t ) ); \
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
    msg_Dbg( p_demux, msg ); \

#define DEMUX_BY_EXTENSION( ext ) \
    demux_t *p_demux = (demux_t *)p_this; \
    if( !isExtension( p_demux, ext ) ) \
        return VLC_EGENERIC; \
    STANDARD_DEMUX_INIT;

#define DEMUX_BY_EXTENSION_MSG( ext, msg ) \
    demux_t *p_demux = (demux_t *)p_this; \
    if( !isExtension( p_demux, ext ) ) \
        return VLC_EGENERIC; \
    STANDARD_DEMUX_INIT_MSG( msg );

#define DEMUX_BY_EXTENSION_OR_FORCED( ext, module ) \
    demux_t *p_demux = (demux_t *)p_this; \
    if( !isExtension( p_demux, ext ) && !isDemux( p_demux, module ) ) \
        return VLC_EGENERIC; \
    STANDARD_DEMUX_INIT;

#define DEMUX_BY_EXTENSION_OR_FORCED_MSG( ext, module, msg ) \
    demux_t *p_demux = (demux_t *)p_this; \
    if( !isExtension( p_demux, ext ) && !isDemux( p_demux, module ) ) \
        return VLC_EGENERIC; \
    STANDARD_DEMUX_INIT_MSG( msg );

#define CHECK_PEEK( zepeek, size ) \
    if( stream_Peek( p_demux->s , &zepeek, size ) < size ){ \
        msg_Dbg( p_demux, "not enough data" ); return VLC_EGENERIC; }

#define CHECK_PEEK_GOTO( zepeek, size ) \
    if( stream_Peek( p_demux->s , &zepeek, size ) < size ) { \
        msg_Dbg( p_demux, "not enough data" ); goto error; }

#define CHECK_DISCARD_PEEK( size ) { uint8_t *p_peek; \
    if( stream_Peek( p_demux->s , &p_peek, size ) < size ) return VLC_EGENERIC;}

#define POKE( peek, stuff, size ) (strncasecmp( (char *)peek, stuff, size )==0)
Clément Stenac's avatar
Clément Stenac committed
190 191

#define COMMON_INIT_PACKETIZER( location ) \
192
    location = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER ); \
Clément Stenac's avatar
Clément Stenac committed
193 194 195 196 197 198 199 200 201 202 203 204 205
    location->pf_decode_audio = 0; \
    location->pf_decode_video = 0; \
    location->pf_decode_sub = 0; \
    location->pf_packetize = 0; \

#define INIT_APACKETIZER( location, a,b,c,d ) \
    COMMON_INIT_PACKETIZER(location ); \
    es_format_Init( &location->fmt_in, AUDIO_ES, \
                    VLC_FOURCC( a, b, c, d ) );

#define INIT_VPACKETIZER( location, a,b,c,d ) \
    COMMON_INIT_PACKETIZER(location ); \
    es_format_Init( &location->fmt_in, VIDEO_ES, \
206 207 208
                    VLC_FOURCC( a, b, c, d ) );

/* BEWARE ! This can lead to memory leaks ! */
Clément Stenac's avatar
Clément Stenac committed
209 210 211 212
#define LOAD_PACKETIZER_OR_FAIL( location, msg ) \
    location->p_module = \
        module_Need( location, "packetizer", NULL, 0 ); \
    if( location->p_module == NULL ) \
213
    { \
Clément Stenac's avatar
Clément Stenac committed
214
        vlc_object_destroy( location ); \
215 216 217 218 219
        msg_Err( p_demux, "cannot find packetizer for " # msg ); \
        free( p_sys ); \
        return VLC_EGENERIC; \
    }

220 221 222 223
#define DESTROY_PACKETIZER( location ) \
    if( location->p_module ) module_Unneed( location, location->p_module ); \
    vlc_object_destroy( location );

224 225 226 227 228
/**
 * @}
 */

#endif