vlc_stream.h 16.1 KB
Newer Older
1
/*****************************************************************************
2
 * vlc_stream.h: Stream (between access and demux) descriptor and methods
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1999-2004 VLC authors and VideoLAN
5
 * $Id$
6 7 8
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
9 10 11
 * 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
12 13 14 15
 * (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
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
16 17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
18
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
19 20 21
 * 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.
22 23
 *****************************************************************************/

24 25
#ifndef VLC_STREAM_H
#define VLC_STREAM_H 1
26

Clément Stenac's avatar
Clément Stenac committed
27 28
#include <vlc_block.h>

29 30 31 32
# ifdef __cplusplus
extern "C" {
# endif

33 34
/**
 * \defgroup stream Stream
35 36
 * \ingroup input
 * Buffered input byte streams
37
 * @{
38 39
 * \file
 * Byte streams and byte stream filter modules interface
40 41
 */

Laurent Aimar's avatar
Laurent Aimar committed
42 43 44 45 46 47
/**
 * stream_t definition
 */

struct stream_t
{
48
    struct vlc_common_members obj;
Laurent Aimar's avatar
Laurent Aimar committed
49

50
    /* Module properties for stream filter */
Laurent Aimar's avatar
Laurent Aimar committed
51 52
    module_t    *p_module;

53
    char        *psz_name;
54
    char        *psz_url; /**< Full URL or MRL (can be NULL) */
55 56 57
    const char  *psz_location; /**< Location (URL with the scheme stripped) */
    char        *psz_filepath; /**< Local file path (if applicable) */
    bool         b_preparsing; /**< True if this access is used to preparse */
58

59
    /* Stream source for stream filter */
60
    stream_t    *s;
Laurent Aimar's avatar
Laurent Aimar committed
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
    /**
     * Read data.
     *
     * Callback to read data from the stream into a caller-supplied buffer.
     *
     * This may be NULL if the stream is actually a directory rather than a
     * byte stream, or if \ref stream_t.pf_block is non-NULL.
     *
     * \param buf buffer to read data into
     * \param len buffer length (in bytes)
     *
     * \retval -1 no data available yet
     * \retval 0 end of stream (incl. fatal error)
     * \retval positive number of bytes read (no more than len)
     */
    ssize_t     (*pf_read)(stream_t *, void *buf, size_t len);

    /**
     * Read data block.
     *
     * Callback to read a block of data. The data is read into a block of
     * memory allocated by the stream. For some streams, data can be read more
     * efficiently in block of a certain size, and/or using a custom allocator
     * for buffers. In such case, this callback should be provided instead of
     * \ref stream_t.pf_read; otherwise, this should be NULL.
     *
     * \param eof storage space for end-of-stream flag [OUT]
     * (*eof is always false when invoking pf_block(); pf_block() should set
     *  *eof to true if it detects the end of the stream)
     *
     * \return a data block,
     * NULL if no data available yet, on error and at end-of-stream
     */
    block_t    *(*pf_block)(stream_t *, bool *eof);

    /**
     * Read directory.
     *
     * Callback to fill an item node from a directory
     * (see doc/browsing.txt for details).
     *
     * NULL if the stream is not a directory.
     */
    int         (*pf_readdir)(stream_t *, input_item_node_t *);

    /**
     * Seek.
     *
     * Callback to set the stream pointer (in bytes from start).
     *
     * May be NULL if seeking is not supported.
     */
114
    int         (*pf_seek)(stream_t *, uint64_t);
115

116 117 118 119 120 121 122 123 124 125 126 127
    /**
     * Stream control.
     *
     * Cannot be NULL.
     *
     * \see stream_query_e
     */
    int         (*pf_control)(stream_t *, int i_query, va_list);

    /**
     * Private data pointer
     */
128
    void *p_sys;
Laurent Aimar's avatar
Laurent Aimar committed
129

130 131
    /* Weak link to parent input */
    input_thread_t *p_input;
Laurent Aimar's avatar
Laurent Aimar committed
132 133
};

134
/**
135
 * Possible commands to send to vlc_stream_Control() and vlc_stream_vaControl()
136 137 138 139
 */
enum stream_query_e
{
    /* capabilities */
140 141
    STREAM_CAN_SEEK,            /**< arg1= bool *   res=cannot fail*/
    STREAM_CAN_FASTSEEK,        /**< arg1= bool *   res=cannot fail*/
142 143
    STREAM_CAN_PAUSE,           /**< arg1= bool *   res=cannot fail*/
    STREAM_CAN_CONTROL_PACE,    /**< arg1= bool *   res=cannot fail*/
144
    /* */
145
    STREAM_GET_SIZE=6,          /**< arg1= uint64_t *     res=can fail */
146
    STREAM_IS_DIRECTORY,        /**< res=can fail */
147

148
    /* */
149 150
    STREAM_GET_PTS_DELAY = 0x101,/**< arg1= int64_t* res=cannot fail */
    STREAM_GET_TITLE_INFO, /**< arg1=input_title_t*** arg2=int* res=can fail */
151 152
    STREAM_GET_TITLE,       /**< arg1=unsigned * res=can fail */
    STREAM_GET_SEEKPOINT,   /**< arg1=unsigned * res=can fail */
153
    STREAM_GET_META,        /**< arg1= vlc_meta_t *       res=can fail */
154
    STREAM_GET_CONTENT_TYPE,    /**< arg1= char **         res=can fail */
155
    STREAM_GET_SIGNAL,      /**< arg1=double *pf_quality, arg2=double *pf_strength   res=can fail */
156
    STREAM_GET_TAGS,        /**< arg1=const block_t ** res=can fail */
157

158
    STREAM_SET_PAUSE_STATE = 0x200, /**< arg1= bool        res=can fail */
159 160
    STREAM_SET_TITLE,       /**< arg1= int          res=can fail */
    STREAM_SET_SEEKPOINT,   /**< arg1= int          res=can fail */
161

162
    /* XXX only data read through vlc_stream_Read/Block will be recorded */
163
    STREAM_SET_RECORD_STATE,     /**< arg1=bool, arg2=const char *psz_ext (if arg1 is true)  res=can fail */
164 165 166 167

    STREAM_SET_PRIVATE_ID_STATE = 0x1000, /* arg1= int i_private_data, bool b_selected    res=can fail */
    STREAM_SET_PRIVATE_ID_CA,             /* arg1= int i_program_number, uint16_t i_vpid, uint16_t i_apid1, uint16_t i_apid2, uint16_t i_apid3, uint8_t i_length, uint8_t *p_data */
    STREAM_GET_PRIVATE_ID_STATE,          /* arg1=int i_private_data arg2=bool *          res=can fail */
168 169
};

170 171 172 173 174 175 176 177 178 179 180 181 182
/**
 * Reads data from a byte stream.
 *
 * This function always waits for the requested number of bytes, unless a fatal
 * error is encountered or the end-of-stream is reached first.
 *
 * If the buffer is NULL, data is skipped instead of read. This is effectively
 * a relative forward seek, but it works even on non-seekable streams.
 *
 * \param buf start of buffer to read data into [OUT]
 * \param len number of bytes to read
 * \return the number of bytes read or a negative value on error.
 */
183
VLC_API ssize_t vlc_stream_Read(stream_t *, void *buf, size_t len) VLC_USED;
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
/**
 * Reads partial data from a byte stream.
 *
 * This function waits until some data is available for reading from the
 * stream, a fatal error is encountered or the end-of-stream is reached.
 *
 * Unlike vlc_stream_Read(), this function does not wait for the full requested
 * bytes count. It can return a short count even before the end of the stream
 * and in the absence of any error.
 *
 * \param buf start of buffer to read data into [OUT]
 * \param len buffer size (maximum number of bytes to read)
 * \return the number of bytes read or a negative value on error.
 */
VLC_API ssize_t vlc_stream_ReadPartial(stream_t *, void *buf, size_t len)
VLC_USED;

202 203 204 205
/**
 * Peeks at data from a byte stream.
 *
 * This function buffers for the requested number of bytes, waiting if
206 207
 * necessary. Then it stores a pointer to the buffer. Unlike vlc_stream_Read()
 * or vlc_stream_Block(), this function does not modify the stream read offset.
208 209 210 211 212 213 214 215 216 217
 *
 * \note
 * The buffer remains valid until the next read/peek or seek operation on the
 * same stream. In case of error, the buffer address is undefined.
 *
 * \param bufp storage space for the buffer address [OUT]
 * \param len number of bytes to peek
 * \return the number of bytes actually available (shorter than requested if
 * the end-of-stream is reached), or a negative value on error.
 */
218
VLC_API ssize_t vlc_stream_Peek(stream_t *, const uint8_t **, size_t) VLC_USED;
219

220 221 222 223 224 225 226 227 228 229 230
/**
 * Reads a data block from a byte stream.
 *
 * This function dequeues the next block of data from the byte stream. The
 * byte stream back-end decides on the size of the block; the caller cannot
 * make any assumption about it.
 *
 * The function might also return NULL spuriously - this does not necessarily
 * imply that the stream is ended nor that it has encountered a nonrecoverable
 * error.
 *
231 232
 * This function should be used instead of vlc_stream_Read() or
 * vlc_stream_Peek() when the caller can handle reads of any size.
233 234 235
 *
 * \return either a data block or NULL
 */
236
VLC_API block_t *vlc_stream_ReadBlock(stream_t *) VLC_USED;
237

238 239 240
/**
 * Tells the current stream position.
 *
241 242 243 244 245
 * This function tells the current read offset (in bytes) from the start of
 * the start of the stream.
 * @note The read offset may be larger than the stream size, either because of
 * a seek past the end, or because the stream shrank asynchronously.
 *
246 247
 * @return the byte offset from the beginning of the stream (cannot fail)
 */
248
VLC_API uint64_t vlc_stream_Tell(const stream_t *) VLC_USED;
249

250 251 252 253 254
/**
 * Checks for end of stream.
 *
 * Checks if the last attempt to reads data from the stream encountered the
 * end of stream before the attempt could be fully satisfied.
255
 * The value is initially false, and is reset to false by vlc_stream_Seek().
256 257 258 259 260 261 262 263 264 265 266 267 268 269
 *
 * \note The function can return false even though the current stream position
 * is equal to the stream size. It will return true after the following attempt
 * to read more than zero bytes.
 *
 * \note It might be possible to read after the end of the stream.
 * It implies the size of the stream increased asynchronously in the mean time.
 * Streams of most types cannot trigger such a case,
 * but regular local files notably can.
 *
 * \note In principles, the stream size should match the stream offset when
 * the end-of-stream is reached. But that rule is not enforced; it is entirely
 * dependent on the underlying implementation of the stream.
 */
270
VLC_API bool vlc_stream_Eof(const stream_t *) VLC_USED;
271

272 273 274
/**
 * Sets the current stream position.
 *
275 276 277 278 279
 * This function changes the read offset within a stream, if the stream
 * supports seeking. In case of error, the read offset is not changed.
 *
 * @note It is possible (but not useful) to seek past the end of a stream.
 *
280 281 282
 * @param offset byte offset from the beginning of the stream
 * @return zero on success, a negative value on error
 */
283
VLC_API int vlc_stream_Seek(stream_t *, uint64_t offset) VLC_USED;
284

285
VLC_API int vlc_stream_vaControl(stream_t *s, int query, va_list args);
286

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
static inline int vlc_stream_Control(stream_t *s, int query, ...)
{
    va_list ap;
    int ret;

    va_start(ap, query);
    ret = vlc_stream_vaControl(s, query, ap);
    va_end(ap);
    return ret;
}

VLC_API block_t *vlc_stream_Block(stream_t *s, size_t);
VLC_API char *vlc_stream_ReadLine(stream_t *);
VLC_API int vlc_stream_ReadDir(stream_t *, input_item_node_t *);

/**
 * Closes a byte stream.
 * \param s byte stream to close
 */
VLC_API void vlc_stream_Delete(stream_t *s);

VLC_API stream_t *vlc_stream_CommonNew(vlc_object_t *, void (*)(stream_t *));
François Cartegnie's avatar
François Cartegnie committed
309

310 311 312
/**
 * Get the size of the stream.
 */
313
VLC_USED static inline int vlc_stream_GetSize( stream_t *s, uint64_t *size )
314
{
315
    return vlc_stream_Control( s, STREAM_GET_SIZE, size );
316 317
}

318 319
static inline int64_t stream_Size( stream_t *s )
{
320
    uint64_t i_pos;
321

322
    if( vlc_stream_GetSize( s, &i_pos ) )
323
        return 0;
324 325
    if( i_pos >> 62 )
        return (int64_t)1 << 62;
326 327
    return i_pos;
}
328

329 330 331 332 333 334 335 336 337
VLC_USED
static inline bool stream_HasExtension( stream_t *s, const char *extension )
{
    const char *name = (s->psz_filepath != NULL) ? s->psz_filepath
                                                 : s->psz_url;
    const char *ext = strrchr( name, '.' );
    return ext != NULL && !strcasecmp( ext, extension );
}

338 339 340 341 342 343 344
/**
 * Get the Content-Type of a stream, or NULL if unknown.
 * Result must be free()'d.
 */
static inline char *stream_ContentType( stream_t *s )
{
    char *res;
345
    if( vlc_stream_Control( s, STREAM_GET_CONTENT_TYPE, &res ) )
346 347 348 349
        return NULL;
    return res;
}

350 351 352 353 354 355
/**
 * Get the mime-type of a stream
 *
 * \warning the returned resource is to be freed by the caller
 * \return the mime-type, or `NULL` if unknown
 **/
356
VLC_USED
357 358 359 360 361 362 363 364 365 366
static inline char *stream_MimeType( stream_t *s )
{
    char* mime_type = stream_ContentType( s );

    if( mime_type ) /* strip parameters */
        mime_type[strcspn( mime_type, " ;" )] = '\0';

    return mime_type;
}

367 368 369 370 371 372 373 374 375 376 377 378
/**
 * Checks for a MIME type.
 *
 * Checks if the stream has a specific MIME type.
 */
VLC_USED
static inline bool stream_IsMimeType(stream_t *s, const char *type)
{
    char *mime = stream_MimeType(s);
    if (mime == NULL)
        return false;

379
    bool ok = !strcasecmp(mime, type);
380 381 382 383
    free(mime);
    return ok;
}

384
/**
385 386 387 388 389 390 391
 * Create a stream from a memory buffer.
 *
 * \param obj parent VLC object
 * \param base start address of the memory buffer to read from
 * \param size size in bytes of the memory buffer
 * \param preserve if false, free(base) will be called when the stream is
 *                 destroyed; if true, the memory buffer is preserved
392
 */
393 394 395 396
VLC_API stream_t *vlc_stream_MemoryNew(vlc_object_t *obj, uint8_t *base,
                                       size_t size, bool preserve) VLC_USED;
#define vlc_stream_MemoryNew(a, b, c, d) \
        vlc_stream_MemoryNew(VLC_OBJECT(a), b, c, d)
397 398

/**
Pierre Ynard's avatar
Pierre Ynard committed
399
 * Create a stream_t reading from a URL.
400
 * You must delete it using vlc_stream_Delete.
401
 */
402
VLC_API stream_t * vlc_stream_NewURL(vlc_object_t *obj, const char *url)
403
VLC_USED;
404
#define vlc_stream_NewURL(a, b) vlc_stream_NewURL(VLC_OBJECT(a), b)
405

406 407 408 409 410 411 412 413 414 415 416 417 418 419
/**
 * \defgroup stream_fifo FIFO stream
 * In-memory anonymous pipe
  @{
 */

/**
 * Creates a FIFO stream.
 *
 * Creates a non-seekable byte stream object whose byte stream is generated
 * by another thread in the process. This is the LibVLC equivalent of an
 * anonymous pipe/FIFO.
 *
 * On the reader side, the normal stream functions are used,
420
 * e.g. vlc_stream_Read() and vlc_stream_Delete().
421 422
 *
 * The created stream object is automatically destroyed when both the reader
423
 * and the writer sides have been closed, with vlc_stream_Delete() and
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
 * vlc_stream_fifo_Close() respectively.
 *
 * \param parent parent VLC object for the stream
 * \return a stream object or NULL on memory error.
 */
VLC_API stream_t *vlc_stream_fifo_New(vlc_object_t *parent);

/**
 * Writes a block to a FIFO stream.
 *
 * \param s FIFO stream created by vlc_stream_fifo_New()
 * \param block data block to write to the stream
 * \return 0 on success. -1 if the reader end has already been closed
 * (errno is then set to EPIPE, and the block is deleted).
 *
 * \bug No congestion control is performed. If the reader end is not keeping
 * up with the writer end, buffers will accumulate in memory.
 */
VLC_API int vlc_stream_fifo_Queue(stream_t *s, block_t *block);

/**
 * Writes data to a FIFO stream.
 *
 * This is a convenience helper for vlc_stream_fifo_Queue().
 * \param s FIFO stream created by vlc_stream_fifo_New()
 * \param buf start address of data to write
 * \param len length of data to write in bytes
 * \return len on success, or -1 on error (errno is set accordingly)
 */
VLC_API ssize_t vlc_stream_fifo_Write(stream_t *s, const void *buf,
                                      size_t len);

/**
 * Terminates a FIFO stream.
 *
 * Marks the end of the FIFO stream and releases any underlying resources.
 * \param s FIFO stream created by vlc_stream_fifo_New()
 */
VLC_API void vlc_stream_fifo_Close(stream_t *s);

/**
 * @}
 */
467

468 469 470 471
/**
 * Try to add a stream filter to an open stream.
 * @return New stream to use, or NULL if the filter could not be added.
 **/
472
VLC_API stream_t* vlc_stream_FilterNew( stream_t *p_source, const char *psz_stream_filter );
473 474 475 476 477

/**
 * Default ReadDir implementation for stream Filter. This implementation just
 * forward the pf_readdir call to the p_source stream.
 */
478 479
VLC_API int vlc_stream_FilterDefaultReadDir(stream_t *s,
                                            input_item_node_t *p_node);
480 481

/**
482 483
 * Sets vlc_stream_FilterDefaultReadDir as the pf_readdir callback for this
 * stream filter.
484
 */
485 486 487 488
#define stream_FilterSetDefaultReadDir(stream) \
do { \
    (stream)->pf_readdir = vlc_stream_FilterDefaultReadDir; \
} while (0)
489

490 491 492 493
/**
 * @}
 */

494 495 496 497
# ifdef __cplusplus
}
# endif

498
#endif