Exemple #1
0
/* PSResynch: resynch on a system startcode
 *  It doesn't skip more than 512 bytes
 *  -1 -> error, 0 -> not synch, 1 -> ok
 */
static int ps_pkt_resynch( stream_t *s, int format, bool b_pack )
{
    const uint8_t *p_peek;
    int     i_peek;
    int     i_skip;

    if( vlc_stream_Peek( s, &p_peek, 4 ) < 4 )
    {
        return -1;
    }
    if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
        p_peek[3] >= PS_STREAM_ID_END_STREAM )
    {
        return 1;
    }

    if( ( i_peek = vlc_stream_Peek( s, &p_peek, 512 ) ) < 4 )
    {
        return -1;
    }
    i_skip = 0;

    for( ;; )
    {
        if( i_peek < 4 )
        {
            break;
        }
        /* Handle mid stream 24 bytes padding+CRC creating emulated sync codes with incorrect
           PES sizes and frelling up to UINT16_MAX bytes followed by 24 bytes CDXA Header */
        if( format == CDXA_PS && i_skip == 0 && i_peek >= 48 )
        {
            const uint8_t cdxasynccode[12] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
                                               0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
            if( !memcmp( &p_peek[24], cdxasynccode, 12 ) )
            {
                i_peek -= 48;
                p_peek += 48;
                i_skip += 48;
                continue;
            }
        }

        if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
            p_peek[3] >= PS_STREAM_ID_END_STREAM &&
            ( !b_pack || p_peek[3] == PS_STREAM_ID_PACK_HEADER ) )
        {
            return vlc_stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1;
        }

        p_peek++;
        i_peek--;
        i_skip++;
    }
    return vlc_stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;
}
Exemple #2
0
Fichier : m3u.c Projet : etix/vlc
/*****************************************************************************
 * Import_M3U: main import function
 *****************************************************************************/
int Import_M3U( vlc_object_t *p_this )
{
    demux_t *p_demux = (demux_t *)p_this;
    const uint8_t *p_peek;
    char *(*pf_dup) (const char *) = GuessEncoding;
    int offset = 0;

    CHECK_FILE();
    if( vlc_stream_Peek( p_demux->s, &p_peek, 3 ) == 3
     && !memcmp( p_peek, "\xef\xbb\xbf", 3) )
    {
        pf_dup = CheckUnicode; /* UTF-8 Byte Order Mark */
        offset = 3;
    }

    if( demux_IsPathExtension( p_demux, ".m3u8" )
     || demux_IsForced( p_demux, "m3u8" )
     || CheckContentType( p_demux->s, "application/vnd.apple.mpegurl" ) )
        pf_dup = CheckUnicode; /* UTF-8 file type */
    else
    if( demux_IsPathExtension( p_demux, ".m3u" )
     || demux_IsPathExtension( p_demux, ".vlc" )
     || demux_IsForced( p_demux, "m3u" )
     || ContainsURL( p_demux )
     || CheckContentType( p_demux->s, "audio/x-mpegurl") )
        ; /* Guess encoding */
    else
    {
        if( vlc_stream_Peek( p_demux->s, &p_peek, 8 + offset ) < (8 + offset) )
            return VLC_EGENERIC;

        p_peek += offset;

        if( !strncasecmp( (const char *)p_peek, "RTSPtext", 8 ) ) /* QuickTime */
            pf_dup = CheckUnicode; /* UTF-8 */
        else
        if( !memcmp( p_peek, "#EXTM3U", 7 ) )
            ; /* Guess encoding */
        else
            return VLC_EGENERIC;
    }

    vlc_stream_Seek( p_demux->s, offset );

    STANDARD_DEMUX_INIT_MSG( "found valid M3U playlist" );
    p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
    p_demux->p_sys->pf_dup = pf_dup;

    return VLC_SUCCESS;
}
Exemple #3
0
bool ProbeArchiveFormat(stream_t *p_stream)
{
    struct
    {
        const uint16_t i_offset;
        const uint8_t  i_length;
        const char * const p_bytes;
    } const magicbytes[9] = {
        /* keep heaviest at top */
        { 257, 5, "ustar" },        //TAR
        { 0,   7, "Rar!\x1A\x07" }, //RAR
        { 0,   4, "xar!" },         //XAR
        { 2,   3, "-lh" },          //LHA/LHZ
        { 0,   3, "PAX" },          //PAX
        { 0,   6, "070707" },       //CPIO
        { 0,   6, "070701" },       //CPIO
        { 0,   6, "070702" },       //CPIO
        { 0,   4, "MSCH" },         //CAB
    };

    const uint8_t *p_peek;
    int i_peek = vlc_stream_Peek(p_stream, &p_peek, magicbytes[0].i_offset + magicbytes[0].i_length);

    for(int i=0; i<9;i++)
    {
        if (i_peek <= magicbytes[i].i_offset + magicbytes[i].i_length)
            continue;
        else if ( !memcmp(p_peek + magicbytes[i].i_offset,
                          magicbytes[i].p_bytes,
                          magicbytes[i].i_length) )
            return true;
    }

    return false;
}
Exemple #4
0
/*****************************************************************************
 * Peek: Helper function to peek data with incremental size.
 * \return false if peek no more data, true otherwise.
 *****************************************************************************/
static bool Peek( demux_t *p_demux, bool b_first )
{
    int i_data;
    demux_sys_t *p_sys = p_demux->p_sys;

    if( b_first )
    {
        p_sys->i_data_peeked = 0;
    }
    else if( p_sys->i_data_peeked == p_sys->i_frame_size_estimate )
    {
        p_sys->i_frame_size_estimate += 5120;
    }
    i_data = vlc_stream_Peek( p_demux->s, &p_sys->p_peek,
                          p_sys->i_frame_size_estimate );
    if( i_data == p_sys->i_data_peeked )
    {
        msg_Warn( p_demux, "no more data" );
        return false;
    }
    p_sys->i_data_peeked = i_data;
    if( i_data <= 0 )
    {
        msg_Warn( p_demux, "cannot peek data" );
        return false;
    }
    return true;
}
Exemple #5
0
/****************************************************************************
 *
 * Basics functions to manipulates chunks
 *
 ****************************************************************************/
static int AVI_ChunkReadCommon( stream_t *s, avi_chunk_t *p_chk )
{
    const uint8_t *p_peek;

    memset( p_chk, 0, sizeof( avi_chunk_t ) );

    if( vlc_stream_Peek( s, &p_peek, 8 ) < 8 )
        return VLC_EGENERIC;

    p_chk->common.i_chunk_fourcc = GetFOURCC( p_peek );
    p_chk->common.i_chunk_size   = GetDWLE( p_peek + 4 );
    p_chk->common.i_chunk_pos    = vlc_stream_Tell( s );

    p_chk->common.p_father = NULL;
    p_chk->common.p_next = NULL;
    p_chk->common.p_first = NULL;
    p_chk->common.p_next = NULL;

#ifdef AVI_DEBUG
    msg_Dbg( (vlc_object_t*)s,
             "found chunk, fourcc: %4.4s size:%"PRId64" pos:%"PRId64,
             (char*)&p_chk->common.i_chunk_fourcc,
             p_chk->common.i_chunk_size,
             p_chk->common.i_chunk_pos );
#endif
    return VLC_SUCCESS;
}
Exemple #6
0
Fichier : m3u.c Projet : etix/vlc
static bool ContainsURL( demux_t *p_demux )
{
    const uint8_t *p_peek, *p_peek_end;
    int i_peek;

    i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 1024 );
    if( i_peek <= 0 ) return false;
    p_peek_end = p_peek + i_peek;

    while( p_peek + sizeof( "https://" ) < p_peek_end )
    {
        /* One line starting with a URL is enough */
        if( !strncasecmp( (const char *)p_peek, "http://", 7 ) ||
            !strncasecmp( (const char *)p_peek, "mms://", 6 ) ||
            !strncasecmp( (const char *)p_peek, "rtsp://", 7 ) ||
            !strncasecmp( (const char *)p_peek, "https://", 8 ) ||
            !strncasecmp( (const char *)p_peek, "ftp://", 6 ) ||
            !strncasecmp( (const char *)p_peek, "ftps://", 7 ) ||
            !strncasecmp( (const char *)p_peek, "ftpes://", 8 ) )
        {
            return true;
        }
        /* Comments and blank lines are ignored */
        else if( *p_peek != '#' && *p_peek != '\n' && *p_peek != '\r')
        {
            return false;
        }

        while( p_peek < p_peek_end && *p_peek != '\n' )
            p_peek++;
        if ( *p_peek == '\n' )
            p_peek++;
    }
    return false;
}
Exemple #7
0
static int DemuxOpen( vlc_object_t * p_this )
{
    demux_t *p_demux = (demux_t *)p_this;
    const uint8_t *p_peek;
    int i_size;

    /* Lets check the content to see if this is a NSC file */
    i_size = vlc_stream_Peek( p_demux->s, &p_peek, MAX_LINE );
    i_size -= sizeof("NSC Format Version=") - 1;

    if ( i_size > 0 )
    {
        while ( i_size && strncasecmp( (char *)p_peek, "NSC Format Version=",
                                       (int) sizeof("NSC Format Version=") - 1 ) )
        {
            p_peek++;
            i_size--;
        }
        if ( !strncasecmp( (char *)p_peek, "NSC Format Version=",
                           (int) sizeof("NSC Format Version=") -1 ) )
        {
            p_demux->pf_demux = Demux;
            p_demux->pf_control = Control;
            return VLC_SUCCESS;
        }
    }
    return VLC_EGENERIC;
}
Exemple #8
0
/*****************************************************************************
 * Open: initializes demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    bool   b_forced = false;

    const uint8_t *p_peek;

    es_format_t  fmt;

    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
    {
        msg_Dbg( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    if( p_demux->obj.force )
        b_forced = true;

    if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 )
    {
        if( !b_forced ) return VLC_EGENERIC;

        msg_Err( p_demux, "this doesn't look like an MPEG ES stream, continuing" );
    }

    if( p_peek[3] > 0xb9 )
    {
        if( !b_forced ) return VLC_EGENERIC;
        msg_Err( p_demux, "this seems to be a system stream (PS plug-in ?), but continuing" );
    }

    p_demux->pf_demux  = Demux;
    p_demux->pf_control= Control;
    p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );
    p_sys->b_start     = true;
    p_sys->p_es        = NULL;

    /* Load the mpegvideo packetizer */
    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_MPGV );
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "mpeg video" );
    if( !p_sys->p_packetizer )
    {
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* create the output */
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( p_sys->p_es == NULL )
    {
        Close( p_this );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Exemple #9
0
static int vlclua_demux_peek( lua_State *L )
{
    stream_t *s = (stream_t *)vlclua_get_this(L);
    int n = luaL_checkinteger( L, 1 );
    const uint8_t *p_peek;

    ssize_t val = vlc_stream_Peek(s->s, &p_peek, n);
    if (val > 0)
        lua_pushlstring(L, (const char *)p_peek, val);
    else
        lua_pushnil( L );
    return 1;
}
Exemple #10
0
static int vlclua_demux_peek( lua_State *L )
{
    demux_t *p_demux = (demux_t *)vlclua_get_this( L );
    int n = (int)luaL_checkinteger( L, 1 );
    const uint8_t *p_peek;

    int i_peek = vlc_stream_Peek( p_demux->s, &p_peek, n );
    if( i_peek > 0 )
        lua_pushlstring( L, (const char *)p_peek, i_peek );
    else
        lua_pushnil( L );
    return 1;
}
Exemple #11
0
/*****************************************************************************
 * Import_podcast: main import function
 *****************************************************************************/
int Import_podcast( vlc_object_t *p_this )
{
    stream_t *p_demux = (stream_t *)p_this;

    CHECK_FILE(p_demux);
    if( stream_IsMimeType( p_demux->s, "text/xml" )
     || stream_IsMimeType( p_demux->s, "application/xml" ) )
    {
        /* XML: check if the root node is "rss". Use a specific peeked
         * probestream in order to not modify the source state while probing.
         * */
        const uint8_t *p_peek;
        ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 );
        if( unlikely( i_peek <= 0 ) )
            return VLC_EGENERIC;

        stream_t *p_probestream =
            vlc_stream_MemoryNew( p_demux, (uint8_t *)p_peek, i_peek, true );
        if( unlikely( !p_probestream ) )
            return VLC_EGENERIC;

        xml_reader_t *p_xml_reader = xml_ReaderCreate( p_demux, p_probestream );
        if( !p_xml_reader )
        {
            vlc_stream_Delete( p_probestream );
            return VLC_EGENERIC;
        }

        const char *node;
        int ret;
        if( ( ret = xml_ReaderNextNode( p_xml_reader, &node ) ) != XML_READER_STARTELEM
         || strcmp( node, "rss" ) )
        {
            vlc_stream_Delete( p_probestream );
            xml_ReaderDelete( p_xml_reader );
            return VLC_EGENERIC;
        }

        xml_ReaderDelete( p_xml_reader );
        vlc_stream_Delete( p_probestream );
        /* SUCCESS: this text/xml is a rss file */
    }
    else if( !stream_IsMimeType( p_demux->s, "application/rss+xml" ) )
        return VLC_EGENERIC;

    p_demux->pf_readdir = ReadDir;
    p_demux->pf_control = access_vaDirectoryControlHelper;
    msg_Dbg( p_demux, "using podcast reader" );

    return VLC_SUCCESS;
}
Exemple #12
0
static block_t *ps_pkt_read( stream_t *s )
{
    const uint8_t *p_peek;
    int i_peek = vlc_stream_Peek( s, &p_peek, 14 );
    if( i_peek < 4 )
        return NULL;

    int i_size = ps_pkt_size( p_peek, i_peek );
    if( i_size <= 6 && p_peek[3] > PS_STREAM_ID_PACK_HEADER )
    {
        /* Special case, search the next start code */
        i_size = 6;
        for( ;; )
        {
            i_peek = vlc_stream_Peek( s, &p_peek, i_size + 1024 );
            if( i_peek <= i_size + 4 )
            {
                return NULL;
            }
            while( i_size <= i_peek - 4 )
            {
                if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
                    p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= PS_STREAM_ID_END_STREAM )
                {
                    return vlc_stream_Block( s, i_size );
                }
                i_size++;
            }
        }
    }
    else
    {
        /* Normal case */
        return vlc_stream_Block( s, i_size );
    }

    return NULL;
}
Exemple #13
0
/*****************************************************************************
 * Activate: initializes m3u demux structures
 *****************************************************************************/
int Import_SGIMB( vlc_object_t * p_this )
{
    stream_t *p_demux = (stream_t *)p_this;
    const uint8_t *p_peek;
    int i_size;

    CHECK_FILE(p_demux);
    /* Lets check the content to see if this is a sgi mediabase file */
    i_size = vlc_stream_Peek( p_demux->p_source, &p_peek, MAX_LINE );
    i_size -= sizeof("sgiNameServerHost=") - 1;
    if ( i_size > 0 )
    {
        unsigned int i_len = sizeof("sgiNameServerHost=") - 1;
        while ( i_size && strncasecmp( (char *)p_peek, "sgiNameServerHost=", i_len ) )
        {
            p_peek++;
            i_size--;
        }
        if ( !strncasecmp( (char *)p_peek, "sgiNameServerHost=", i_len ) )
        {
            demux_sys_t *p_sys = malloc(sizeof (*p_sys));
            if( unlikely(p_sys == NULL) )
                return VLC_ENOMEM;

            msg_Dbg( p_demux, "using SGIMB playlist reader" );
            p_demux->pf_readdir = ReadDir;
            p_demux->pf_control = access_vaDirectoryControlHelper;
            p_demux->p_sys = p_sys;
            p_sys->psz_uri = NULL;
            p_sys->psz_server = NULL;
            p_sys->psz_location = NULL;
            p_sys->psz_name = NULL;
            p_sys->psz_user = NULL;
            p_sys->psz_password = NULL;
            p_sys->psz_mcast_ip = NULL;
            p_sys->i_mcast_port = 0;
            p_sys->i_packet_size = 0;
            p_sys->i_duration = 0;
            p_sys->i_port = 0;
            p_sys->i_sid = 0;
            p_sys->b_rtsp_kasenna = false;
            p_sys->b_concert = false;

            return VLC_SUCCESS;
        }
    }
    return VLC_EGENERIC;
}
Exemple #14
0
int Import_WMS(vlc_object_t *obj)
{
    stream_t *demux = (stream_t *)obj;
    const uint8_t *peek;

    CHECK_FILE(demux);

    if (vlc_stream_Peek(demux->s, &peek, 10) < 10
     || strncmp((const char *)peek, "[Reference]", 11))
        return VLC_EGENERIC;

    msg_Dbg(demux, "found WMS metafile");
    demux->pf_readdir = ReadDir;
    demux->pf_control = access_vaDirectoryControlHelper;
    return VLC_SUCCESS;
}
Exemple #15
0
/*****************************************************************************
 * Import_IFO: main import function
 *****************************************************************************/
int Import_IFO( vlc_object_t *p_this )
{
    stream_t *p_stream = (stream_t *)p_this;

    CHECK_FILE(p_stream);

    if( !stream_HasExtension( p_stream, ".IFO" ) )
        return VLC_EGENERIC;

    const char *psz_location = StreamLocation( p_stream );
    if( psz_location == NULL )
        return VLC_EGENERIC;

    size_t len = strlen( psz_location );
    if( len < 12 )
        return VLC_EGENERIC;

    const char *psz_probe;
    const char *psz_file = &psz_location[len - 12];
    /* Valid filenames are :
     *  - VIDEO_TS.IFO
     *  - VTS_XX_X.IFO where X are digits
     */
    if( !strncasecmp( psz_file, "VIDEO_TS", 8 ) ||
        !strncasecmp( psz_file, "VTS_", 4 ) )
    {
        psz_probe = "DVDVIDEO";
        p_stream->pf_readdir = ReadDVD;
    }
    /* Valid filename for DVD-VR is VR_MANGR.IFO */
    else if( !strncasecmp( psz_file, "VR_MANGR", 8 ) )
    {
        psz_probe = "DVD_RTR_";
        p_stream->pf_readdir = ReadDVD_VR;
    }
    else
        return VLC_EGENERIC;

    const uint8_t *p_peek;
    ssize_t i_peek = vlc_stream_Peek( p_stream->s, &p_peek, 8 );
    if( i_peek < 8 || memcmp( p_peek, psz_probe, 8 ) )
        return VLC_EGENERIC;

    p_stream->pf_control = access_vaDirectoryControlHelper;

    return VLC_SUCCESS;
}
Exemple #16
0
static int vlclua_demux_read( lua_State *L )
{
    demux_t *p_demux = (demux_t *)vlclua_get_this( L );
    const uint8_t *p_read;
    int n = (int)luaL_checkinteger( L, 1 );
    int i_read = vlc_stream_Peek( p_demux->s, &p_read, n );

    if( i_read > 0 )
    {
        lua_pushlstring( L, (const char *)p_read, i_read );
        int i_seek = vlc_stream_Read( p_demux->s, NULL, i_read );
        assert( i_read == i_seek );
    }
    else
        lua_pushnil( L );

    return 1;
}
Exemple #17
0
static int probe( stream_t* source )
{
    struct
    {
        uint16_t i_offset;
        uint8_t  i_length;
        char const * p_bytes;
    } const magicbytes[] = {
        /* keep heaviest at top */
        { 257, 5, "ustar" },              //TAR
        { 0,   7, "Rar!\x1A\x07" },       //RAR
        { 0,   6, "7z\xBC\xAF\x27\x1C" }, //7z
        { 0,   4, "xar!" },               //XAR
        { 0,   4, "PK\x03\x04" },         //ZIP
        { 0,   4, "PK\x05\x06" },         //ZIP
        { 0,   4, "PK\x07\x08" },         //ZIP
        { 2,   3, "-lh" },                //LHA/LHZ
        { 0,   3, "\x1f\x8b\x08" },       // Gzip
        { 0,   3, "PAX" },                //PAX
        { 0,   6, "070707" },             //CPIO
        { 0,   6, "070701" },             //CPIO
        { 0,   6, "070702" },             //CPIO
        { 0,   4, "MSCH" },               //CAB
    };

    const uint8_t *p_peek;

    int i_peek = vlc_stream_Peek( source, &p_peek,
      magicbytes[0].i_offset + magicbytes[0].i_length);

    for(unsigned i=0; i < ARRAY_SIZE( magicbytes ); i++)
    {
        if (i_peek < magicbytes[i].i_offset + magicbytes[i].i_length)
            continue;

        if ( !memcmp(p_peek + magicbytes[i].i_offset,
            magicbytes[i].p_bytes, magicbytes[i].i_length) )
            return VLC_SUCCESS;
    }

    return VLC_EGENERIC;
}
Exemple #18
0
Fichier : pls.c Projet : IAPark/vlc
/*****************************************************************************
 * Import_PLS: main import function
 *****************************************************************************/
int Import_PLS( vlc_object_t *p_this )
{
    stream_t *p_demux = (stream_t *)p_this;
    const uint8_t *p_peek;

    CHECK_FILE(p_demux);

    if( vlc_stream_Peek( p_demux->p_source , &p_peek, 10 ) < 10 ) {
        msg_Dbg( p_demux, "not enough data" );
        return VLC_EGENERIC;
    }

    if( strncasecmp( (const char *)p_peek, "[playlist]", 10 )
     && strncasecmp( (const char *)p_peek, "[Reference]", 10 )
     && !stream_HasExtension( p_demux, ".pls" ) )
        return VLC_EGENERIC;

    msg_Dbg( p_demux, "found valid PLS playlist file");
    p_demux->pf_readdir = ReadDir;
    p_demux->pf_control = access_vaDirectoryControlHelper;

    return VLC_SUCCESS;
}
Exemple #19
0
/**
 * Import_RAM: main import function
 * @param p_this: this demux object
 * @return VLC_SUCCESS if everything is okay
 */
int Import_RAM( vlc_object_t *p_this )
{
    demux_t *p_demux = (demux_t *)p_this;
    const uint8_t *p_peek;

    CHECK_FILE();
    if(! demux_IsPathExtension( p_demux, ".ram" ) ||
         demux_IsPathExtension( p_demux, ".rm" ) )
        return VLC_EGENERIC;

    /* Many Real Media Files are misdetected */
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
        return VLC_EGENERIC;
    if( !memcmp( p_peek, ".ra", 3 ) || !memcmp( p_peek, ".RMF", 4 ) )
    {
        return VLC_EGENERIC;
    }

    STANDARD_DEMUX_INIT_MSG( "found valid RAM playlist" );
    p_demux->p_sys->psz_prefix = FindPrefix( p_demux );

    return VLC_SUCCESS;
}
Exemple #20
0
/**
 * Import_RAM: main import function
 * @param p_this: this demux object
 * @return VLC_SUCCESS if everything is okay
 */
int Import_RAM( vlc_object_t *p_this )
{
    demux_t *p_demux = (demux_t *)p_this;
    const uint8_t *p_peek;

    CHECK_FILE();
    if(! demux_IsPathExtension( p_demux, ".ram" ) ||
         demux_IsPathExtension( p_demux, ".rm" ) )
        return VLC_EGENERIC;

    /* Many Real Media Files are misdetected */
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
        return VLC_EGENERIC;
    if( !memcmp( p_peek, ".ra", 3 ) || !memcmp( p_peek, ".RMF", 4 ) )
    {
        return VLC_EGENERIC;
    }

    msg_Dbg( p_demux, "found valid RAM playlist" );
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    return VLC_SUCCESS;
}
Exemple #21
0
/*****************************************************************************
 * Open: initializes matroska demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t            *p_demux = (demux_t*)p_this;
    demux_sys_t        *p_sys;
    matroska_stream_c  *p_stream;
    matroska_segment_c *p_segment;
    const uint8_t      *p_peek;
    std::string         s_path, s_filename;
    vlc_stream_io_callback *p_io_callback;
    EbmlStream         *p_io_stream;
    bool                b_need_preload = false;

    /* peek the begining */
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;

    /* is a valid file */
    if( p_peek[0] != 0x1a || p_peek[1] != 0x45 ||
        p_peek[2] != 0xdf || p_peek[3] != 0xa3 ) return VLC_EGENERIC;

    /* Set the demux function */
    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys = new demux_sys_t( *p_demux );

    p_io_callback = new vlc_stream_io_callback( p_demux->s, false );
    p_io_stream = new (std::nothrow) EbmlStream( *p_io_callback );

    if( p_io_stream == NULL )
    {
        msg_Err( p_demux, "failed to create EbmlStream" );
        delete p_io_callback;
        delete p_sys;
        return VLC_EGENERIC;
    }

    p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_io_stream, true );
    if( p_stream == NULL )
    {
        msg_Err( p_demux, "cannot find KaxSegment or missing mandatory KaxInfo" );
        goto error;
    }
    p_sys->streams.push_back( p_stream );

    p_stream->p_io_callback = p_io_callback;
    p_stream->p_estream = p_io_stream;

    for (size_t i=0; i<p_stream->segments.size(); i++)
    {
        p_stream->segments[i]->Preload();
        b_need_preload |= p_stream->segments[i]->b_ref_external_segments;
        if ( p_stream->segments[i]->translations.size() &&
             p_stream->segments[i]->translations[0]->codec_id == MATROSKA_CHAPTER_CODEC_DVD &&
             p_stream->segments[i]->families.size() )
            b_need_preload = true;
    }

    p_segment = p_stream->segments[0];
    if( p_segment->cluster == NULL && p_segment->stored_editions.size() == 0 )
    {
        msg_Err( p_demux, "cannot find any cluster or chapter, damaged file ?" );
        goto error;
    }

    if (b_need_preload && var_InheritBool( p_demux, "mkv-preload-local-dir" ))
    {
        msg_Dbg( p_demux, "Preloading local dir" );
        /* get the files from the same dir from the same family (based on p_demux->psz_path) */
        if ( p_demux->psz_file && !strcmp( p_demux->psz_access, "file" ) )
        {
            // assume it's a regular file
            // get the directory path
            s_path = p_demux->psz_file;
            if (s_path.at(s_path.length() - 1) == DIR_SEP_CHAR)
            {
                s_path = s_path.substr(0,s_path.length()-1);
            }
            else
            {
                if (s_path.find_last_of(DIR_SEP_CHAR) > 0)
                {
                    s_path = s_path.substr(0,s_path.find_last_of(DIR_SEP_CHAR));
                }
            }

            DIR *p_src_dir = vlc_opendir(s_path.c_str());

            if (p_src_dir != NULL)
            {
                const char *psz_file;
                while ((psz_file = vlc_readdir(p_src_dir)) != NULL)
                {
                    if (strlen(psz_file) > 4)
                    {
                        s_filename = s_path + DIR_SEP_CHAR + psz_file;

#if defined(_WIN32) || defined(__OS2__)
                        if (!strcasecmp(s_filename.c_str(), p_demux->psz_file))
#else
                        if (!s_filename.compare(p_demux->psz_file))
#endif
                        {
                            continue; // don't reuse the original opened file
                        }

                        if (!s_filename.compare(s_filename.length() - 3, 3, "mkv") ||
                            !s_filename.compare(s_filename.length() - 3, 3, "mka"))
                        {
                            // test whether this file belongs to our family
                            const uint8_t *p_peek;
                            bool          file_ok = false;
                            char          *psz_url = vlc_path2uri( s_filename.c_str(), "file" );
                            stream_t      *p_file_stream = vlc_stream_NewURL(
                                                            p_demux,
                                                            psz_url );
                            /* peek the begining */
                            if( p_file_stream &&
                                vlc_stream_Peek( p_file_stream, &p_peek, 4 ) >= 4
                                && p_peek[0] == 0x1a && p_peek[1] == 0x45 &&
                                p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true;

                            if ( file_ok )
                            {
                                vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, true );
                                EbmlStream *p_estream = new EbmlStream(*p_file_io);

                                p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_estream );

                                if ( p_stream == NULL )
                                {
                                    msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
                                    delete p_estream;
                                    delete p_file_io;
                                }
                                else
                                {
                                    p_stream->p_io_callback = p_file_io;
                                    p_stream->p_estream = p_estream;
                                    p_sys->streams.push_back( p_stream );
                                }
                            }
                            else
                            {
                                if( p_file_stream ) {
                                    vlc_stream_Delete( p_file_stream );
                                }
                                msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
                            }
                            free( psz_url );
                        }
                    }
                }
                closedir( p_src_dir );
            }
        }

        p_sys->PreloadFamily( *p_segment );
    }
    else if (b_need_preload)
        msg_Warn( p_demux, "This file references other files, you may want to enable the preload of local directory");

    if ( !p_sys->PreloadLinked() ||
         !p_sys->PreparePlayback( *p_sys->p_current_vsegment, 0 ) )
    {
        msg_Err( p_demux, "cannot use the segment" );
        goto error;
    }

    p_sys->FreeUnused();

    p_sys->InitUi();

    return VLC_SUCCESS;

error:
    delete p_sys;
    return VLC_EGENERIC;
}
Exemple #22
0
int OpenDemux( vlc_object_t* p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 );
    if( unlikely( i_peek <= 32 ) )
        return VLC_EGENERIC;

    const char *psz_xml = (const char *) p_peek;
    size_t i_xml  = i_peek;

    /* Try to probe without xml module/loading the full document */
    char *psz_alloc = NULL;
    switch( GetQWBE(p_peek) )
    {
        /* See RFC 3023 Part 4 */
        case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */
        case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */
        case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */
        case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */
            psz_alloc = FromCharset( "UTF-16", p_peek, i_peek );
            break;
        case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */
        case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */
            psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek );
            break;
        case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */
        case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */
            psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek );
            break;
        case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */
        case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */
        case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/
            break;
        default:
            if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */
                return VLC_EGENERIC;
    }

    if( psz_alloc )
    {
        psz_xml = psz_alloc;
        i_xml = strlen( psz_alloc );
    }

    /* Simplified probing. Valid TTML must have a namespace declaration */
    const char *psz_tt = strnstr( psz_xml, "tt ", i_xml );
    if( !psz_tt || psz_tt == psz_xml ||
        (psz_tt[-1] != ':' && psz_tt[-1] != '<') )
    {
        free( psz_alloc );
        return VLC_EGENERIC;
    }
    else
    {
        const char * const rgsz[] =
        {
            "=\"http://www.w3.org/ns/ttml\"",
            "=\"http://www.w3.org/2004/11/ttaf1\"",
            "=\"http://www.w3.org/2006/04/ttaf1\"",
            "=\"http://www.w3.org/2006/10/ttaf1\"",
        };
        const char *psz_ns = NULL;
        for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ )
        {
            psz_ns = strnstr( psz_xml, rgsz[i],
                              i_xml - (psz_tt - psz_xml) );
        }
        free( psz_alloc );
        if( !psz_ns )
            return VLC_EGENERIC;
    }

    p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    p_sys->b_first_time = true;
    p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL;
    tt_time_Init( &p_sys->temporal_extent.begin );
    tt_time_Init( &p_sys->temporal_extent.end );
    tt_time_Init( &p_sys->temporal_extent.dur );
    p_sys->temporal_extent.begin.base = 0;

    p_sys->p_xml = xml_Create( p_demux );
    if( !p_sys->p_xml )
        goto error;

    p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s );
    if( !p_sys->p_reader )
        goto error;

#ifndef TTML_DEMUX_DEBUG
    p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET;
#endif

    if( ReadTTML( p_demux ) != VLC_SUCCESS )
        goto error;

    tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent,
                        &p_sys->times.p_array, &p_sys->times.i_count );

#ifdef TTML_DEMUX_DEBUG
    {
        struct vlc_memstream stream;

        if( vlc_memstream_open( &stream ) )
            goto error;

        tt_time_t t;
        tt_time_Init( &t );
        tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ );

        vlc_memstream_putc( &stream, '\0' );

        if( vlc_memstream_close( &stream ) == VLC_SUCCESS )
        {
            msg_Dbg( p_demux, "%s", stream.ptr );
            free( stream.ptr );
        }
    }
#endif

    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    es_format_t fmt;
    es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML );
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( !p_sys->p_es )
        goto error;

    es_format_Clean( &fmt );

    return VLC_SUCCESS;

error:
    CloseDemux( p_demux );

    return VLC_EGENERIC;
}
Exemple #23
0
char *vlc_stream_ReadLine( stream_t *s )
{
    stream_priv_t *priv = (stream_priv_t *)s;
    char *p_line = NULL;
    int i_line = 0, i_read = 0;

    /* Let's fail quickly if this is a readdir access */
    if( s->pf_read == NULL )
        return NULL;

    for( ;; )
    {
        char *psz_eol;
        const uint8_t *p_data;
        int i_data;
        int64_t i_pos;

        /* Probe new data */
        i_data = vlc_stream_Peek( s, &p_data, STREAM_PROBE_LINE );
        if( i_data <= 0 ) break; /* No more data */

        /* BOM detection */
        i_pos = vlc_stream_Tell( s );
        if( i_pos == 0 && i_data >= 2 )
        {
            const char *psz_encoding = NULL;

            if( !memcmp( p_data, "\xFF\xFE", 2 ) )
            {
                psz_encoding = "UTF-16LE";
                priv->text.little_endian = true;
            }
            else if( !memcmp( p_data, "\xFE\xFF", 2 ) )
            {
                psz_encoding = "UTF-16BE";
            }

            /* Open the converter if we need it */
            if( psz_encoding != NULL )
            {
                msg_Dbg( s, "UTF-16 BOM detected" );
                priv->text.char_width = 2;
                priv->text.conv = vlc_iconv_open( "UTF-8", psz_encoding );
                if( priv->text.conv == (vlc_iconv_t)-1 )
                    msg_Err( s, "iconv_open failed" );
            }
        }

        if( i_data % priv->text.char_width )
        {
            /* keep i_char_width boundary */
            i_data = i_data - ( i_data % priv->text.char_width );
            msg_Warn( s, "the read is not i_char_width compatible");
        }

        if( i_data == 0 )
            break;

        /* Check if there is an EOL */
        if( priv->text.char_width == 1 )
        {
            /* UTF-8: 0A <LF> */
            psz_eol = memchr( p_data, '\n', i_data );
            if( psz_eol == NULL )
                /* UTF-8: 0D <CR> */
                psz_eol = memchr( p_data, '\r', i_data );
        }
        else
        {
            const uint8_t *p_last = p_data + i_data - priv->text.char_width;
            uint16_t eol = priv->text.little_endian ? 0x0A00 : 0x00A0;

            assert( priv->text.char_width == 2 );
            psz_eol = NULL;
            /* UTF-16: 000A <LF> */
            for( const uint8_t *p = p_data; p <= p_last; p += 2 )
            {
                if( U16_AT( p ) == eol )
                {
                     psz_eol = (char *)p + 1;
                     break;
                }
            }

            if( psz_eol == NULL )
            {   /* UTF-16: 000D <CR> */
                eol = priv->text.little_endian ? 0x0D00 : 0x00D0;
                for( const uint8_t *p = p_data; p <= p_last; p += 2 )
                {
                    if( U16_AT( p ) == eol )
                    {
                        psz_eol = (char *)p + 1;
                        break;
                    }
                }
            }
        }

        if( psz_eol )
        {
            i_data = (psz_eol - (char *)p_data) + 1;
            p_line = realloc_or_free( p_line,
                        i_line + i_data + priv->text.char_width ); /* add \0 */
            if( !p_line )
                goto error;
            i_data = vlc_stream_Read( s, &p_line[i_line], i_data );
            if( i_data <= 0 ) break; /* Hmmm */
            i_line += i_data - priv->text.char_width; /* skip \n */;
            i_read += i_data;

            /* We have our line */
            break;
        }

        /* Read data (+1 for easy \0 append) */
        p_line = realloc_or_free( p_line,
                          i_line + STREAM_PROBE_LINE + priv->text.char_width );
        if( !p_line )
            goto error;
        i_data = vlc_stream_Read( s, &p_line[i_line], STREAM_PROBE_LINE );
        if( i_data <= 0 ) break; /* Hmmm */
        i_line += i_data;
        i_read += i_data;

        if( i_read >= STREAM_LINE_MAX )
            goto error; /* line too long */
    }

    if( i_read > 0 )
    {
        memset(p_line + i_line, 0, priv->text.char_width);
        i_line += priv->text.char_width; /* the added \0 */

        if( priv->text.char_width > 1 )
        {
            int i_new_line = 0;
            size_t i_in = 0, i_out = 0;
            const char * p_in = NULL;
            char * p_out = NULL;
            char * psz_new_line = NULL;

            /* iconv */
            /* UTF-8 needs at most 150% of the buffer as many as UTF-16 */
            i_new_line = i_line * 3 / 2;
            psz_new_line = malloc( i_new_line );
            if( psz_new_line == NULL )
                goto error;
            i_in = (size_t)i_line;
            i_out = (size_t)i_new_line;
            p_in = p_line;
            p_out = psz_new_line;

            if( vlc_iconv( priv->text.conv, &p_in, &i_in, &p_out, &i_out ) == (size_t)-1 )
            {
                msg_Err( s, "iconv failed" );
                msg_Dbg( s, "original: %d, in %d, out %d", i_line, (int)i_in, (int)i_out );
            }
            free( p_line );
            p_line = psz_new_line;
            i_line = (size_t)i_new_line - i_out; /* does not include \0 */
        }

        /* Remove trailing LF/CR */
        while( i_line >= 2 && ( p_line[i_line-2] == '\r' ||
            p_line[i_line-2] == '\n') ) i_line--;

        /* Make sure the \0 is there */
        p_line[i_line-1] = '\0';

        return p_line;
    }

error:
    /* We failed to read any data, probably EOF */
    free( p_line );

    /* */
    if( priv->text.conv != (vlc_iconv_t)(-1) )
    {
        vlc_iconv_close( priv->text.conv );
        priv->text.conv = (vlc_iconv_t)(-1);
    }
    return NULL;
}
Exemple #24
0
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = NULL;
    es_format_t fmt;
    bool result = false;
    SidTune *tune = NULL;
    sidplay2 *player = NULL;
    ReSIDBuilder *builder = NULL;

    int64_t size = stream_Size (demux->s);
    if (size < 4 || size > LONG_MAX) /* We need to load the whole file for sidplay */
        return VLC_EGENERIC;

    const uint8_t *peek;
    if (vlc_stream_Peek (demux->s, &peek, 4) < 4)
        return VLC_EGENERIC;

    /* sidplay2 can read PSID and the newer RSID formats */
    if(memcmp(peek,"PSID",4)!=0 && memcmp(peek,"RSID",4)!=0)
        return VLC_EGENERIC;

    uint8_t *data = (uint8_t*) malloc(size);
    if (unlikely (data==NULL))
        goto error;

    if (vlc_stream_Read (demux->s,data,size) < size) {
        free (data);
        goto error;
    }

    tune = new (std::nothrow) SidTune(0);
    if (unlikely (tune==NULL)) {
        free (data);
        goto error;
    }

    result = tune->read (data, size);
    free (data);
    if (!result)
        goto error;

    player = new (std::nothrow) sidplay2();
    if (unlikely(player==NULL))
        goto error;

    sys = (demux_sys_t*) calloc (1, sizeof(demux_sys_t));
    if (unlikely(sys==NULL))
        goto error;

    sys->player = player;
    sys->tune = tune;

    tune->getInfo (sys->tuneInfo);

    sys->info = player->info();
    sys->config = player->config();

    builder = new (std::nothrow) ReSIDBuilder ("ReSID");
    if (unlikely(builder==NULL))
        goto error;

    builder->create (sys->info.maxsids);
    builder->sampling (sys->config.frequency);

    sys->config.sidEmulation = builder;
    sys->config.precision    = 16;
    sys->config.playback     = (sys->info.channels == 2 ? sid2_stereo : sid2_mono);

    player->config (sys->config);

    sys->bytes_per_frame = sys->info.channels * sys->config.precision / 8;
    sys->block_size = sys->config.frequency / 10 * sys->bytes_per_frame;

    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N);

    fmt.audio.i_channels        = sys->info.channels;
    fmt.audio.i_bitspersample   = sys->config.precision;
    fmt.audio.i_rate            = sys->config.frequency;
    fmt.audio.i_bytes_per_frame = sys->bytes_per_frame;
    fmt.audio.i_frame_length    = fmt.audio.i_bytes_per_frame;
    fmt.audio.i_blockalign      = fmt.audio.i_bytes_per_frame;

    fmt.i_bitrate = fmt.audio.i_rate * fmt.audio.i_bytes_per_frame;

    sys->es = es_out_Add (demux->out, &fmt);

    date_Init (&sys->pts, fmt.audio.i_rate, 1);
    date_Set (&sys->pts, 0);

    sys->tune->selectSong (0);
    result = (sys->player->load (sys->tune) >=0 );
    sys->player->fastForward (100);
    if (!result)
        goto error;

    /* Callbacks */
    demux->pf_demux = Demux;
    demux->pf_control = Control;
    demux->p_sys = sys;

    return VLC_SUCCESS;

error:
    msg_Err (demux, "An error occurred during sid demuxing" );
    delete player;
    delete builder;
    delete tune;
    free (sys);
    return VLC_EGENERIC;
}
Exemple #25
0
static bool PeekASX( demux_t *p_demux )
{
    const uint8_t *p_peek;
    return ( vlc_stream_Peek( p_demux->s, &p_peek, 12 ) == 12
             && !memcmp( p_peek, "<asx version", 12 ) );
}
Exemple #26
0
/*****************************************************************************
 * Open
 *****************************************************************************/
static int OpenCommon( vlc_object_t *p_this, bool b_force )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    ssize_t i_peek = 0;
    ssize_t i_offset = 0;
    ssize_t i_skip = 0;
    unsigned i_max_packets = PS_PACKET_PROBE;
    int format = MPEG_PS;
    int i_mux_rate = 0;
    vlc_tick_t i_length = VLC_TICK_INVALID;

    i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
    if( i_peek < 16 )
    {
        msg_Dbg( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    if( !memcmp( p_peek, "PSMF", 4 ) &&
        (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 )
    {
        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 );
        if( i_peek < 100 )
            return VLC_EGENERIC;
        i_skip = i_offset = GetWBE( &p_peek[10] );
        format = PSMF_PS;
        msg_Info( p_demux, "Detected PSMF-PS header");
        i_mux_rate = GetDWBE( &p_peek[96] );
        if( GetDWBE( &p_peek[86] ) > 0 )
            i_length = vlc_tick_from_samples( GetDWBE( &p_peek[92] ), GetDWBE( &p_peek[86] ));
    }
    else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
    {
        format = CDXA_PS;
        i_max_packets = 0; /* We can't probe here */
        i_skip = CDXA_HEADER_SIZE;
        msg_Info( p_demux, "Detected CDXA-PS" );
        /* FIXME: have a proper way to decap CD sectors or make an access stream filter */
    }
    else if( b_force )
    {
        msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
                  "continuing anyway" );
        i_max_packets = 0;
    }

    for( unsigned i=0; i<i_max_packets; i++ )
    {
        if( i_peek < i_offset + 16 )
        {
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_offset + 16 );
            if( i_peek < i_offset + 16 )
                return VLC_EGENERIC;
        }

        const uint8_t startcode[3] = { 0x00, 0x00, 0x01 };
        const uint8_t *p_header = &p_peek[i_offset];
        if( memcmp( p_header, startcode, 3 ) ||
           ( (p_header[3] & 0xB0) != 0xB0 &&
            !(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) &&
              p_header[3] != PS_STREAM_ID_EXTENDED &&
              p_header[3] != PS_STREAM_ID_DIRECTORY ) )
            return VLC_EGENERIC;

        ssize_t i_pessize = ps_pkt_size( p_header, 16 );
        if( i_pessize < 5 )
            return VLC_EGENERIC;
        i_offset += i_pessize;
    }

    if( i_skip > 0 && !p_demux->b_preparsing &&
        vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
        return VLC_EGENERIC;

    /* Fill p_demux field */
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys ) return VLC_ENOMEM;

    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    /* Init p_sys */
    p_sys->i_mux_rate = i_mux_rate;
    p_sys->i_pack_scr  = VLC_TICK_INVALID;
    p_sys->i_first_scr = VLC_TICK_INVALID;
    p_sys->i_scr = VLC_TICK_INVALID;
    p_sys->i_scr_track_id = 0;
    p_sys->i_length   = i_length;
    p_sys->i_current_pts = VLC_TICK_INVALID;
    p_sys->i_time_track_index = -1;
    p_sys->i_aob_mlp_count = 0;
    p_sys->i_start_byte = i_skip;
    p_sys->i_lastpack_byte = i_skip;

    p_sys->b_lost_sync = false;
    p_sys->b_have_pack = false;
    p_sys->b_bad_scr   = false;
    p_sys->b_seekable  = false;
    p_sys->format      = format;
    p_sys->current_title = 0;
    p_sys->current_seekpoint = 0;
    p_sys->updates = 0;

    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );

    ps_psm_init( &p_sys->psm );
    ps_track_init( p_sys->tk );

    /* TODO prescanning of ES */

    return VLC_SUCCESS;
}
Exemple #27
0
/*****************************************************************************
 * Open: initializes ES structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    const uint8_t *p_peek;
    es_format_t fmt;

    /* Have a peep at the show. */
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;

    if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
    {
        if( !p_demux->obj.force
         && !demux_IsContentType( p_demux, "audio/flac" ) )
            return VLC_EGENERIC;

        /* User forced */
        msg_Err( p_demux, "this doesn't look like a flac stream, "
                 "continuing anyway" );
    }

    p_sys = malloc( sizeof( demux_sys_t ) );
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    p_sys->b_start = true;
    p_sys->i_next_block_flags = 0;
    p_sys->p_packetizer = NULL;
    p_sys->p_meta = NULL;
    p_sys->i_length = 0;
    p_sys->i_pts = VLC_TS_INVALID;
    p_sys->p_es = NULL;
    p_sys->p_current_block = NULL;
    TAB_INIT( p_sys->i_seekpoint, p_sys->seekpoint );
    TAB_INIT( p_sys->i_attachments, p_sys->attachments);
    TAB_INIT( p_sys->i_title_seekpoints, p_sys->pp_title_seekpoints );
    p_sys->i_cover_idx = 0;
    p_sys->i_cover_score = 0;

    es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC );

    /* We need to read and store the STREAMINFO metadata into fmt extra */
    if( ParseHeaders( p_demux, &fmt ) )
        goto error;

    /* Load the FLAC packetizer */
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "flac" );
    if( !p_sys->p_packetizer )
        goto error;

    if( p_sys->i_cover_idx < p_sys->i_attachments )
    {
        char psz_url[128];
        if( !p_sys->p_meta )
            p_sys->p_meta = vlc_meta_New();
        snprintf( psz_url, sizeof(psz_url), "attachment://%s",
                  p_sys->attachments[p_sys->i_cover_idx]->psz_name );
        vlc_meta_Set( p_sys->p_meta, vlc_meta_ArtworkURL, psz_url );
    }

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
    if( !p_sys->p_es )
        goto error;

    return VLC_SUCCESS;
error:
    Close( p_this );
    return VLC_EGENERIC;
}
Exemple #28
0
/*****************************************************************************
 * Validate: try to ensure it is really a mod file.
 * The tests are not robust enough to replace extension checks in the general
 * cases.
 * TODO: maybe it should return a score, which will be used to bypass the
 * extension checks when high enough.
 *****************************************************************************/
static int Validate( demux_t *p_demux, const char *psz_ext )
{
    static const struct
    {
        int i_offset;
        const char *psz_marker;
    } p_marker[] = {
        {  0, "ziRCONia" },             /* MMCMP files */
        {  0, "Extended Module" },      /* XM */
        { 44, "SCRM" },                 /* S3M */
        {  0, "IMPM" },                 /* IT */
        {  0, "GF1PATCH110" },          /* PAT */
        { 20, "!SCREAM!" },             /* STM */
        { 20, "!Scream!" },             /* STM */
        { 20, "BMOD2STM" },             /* STM */
        {  0, "MMD0" },                 /* MED v0 */
        {  0, "MMD1" },                 /* MED v1 */
        {  0, "MMD2" },                 /* MED v2 */
        {  0, "MMD3" },                 /* MED v3 */
        {  0, "MTM" },                  /* MTM */
        {  0, "DMDL" },                 /* MDL */
        {  0, "DBM0" },                 /* DBM */
        {  0, "if" },                   /* 669 */
        {  0, "JN" },                   /* 669 */
        {  0, "FAR\xfe" },              /* FAR */
        {  0, "Extreme" },              /* AMS */
        {  0, "OKTASONGCMOD" },         /* OKT */
        { 44, "PTMF" },                 /* PTM */
        {  0, "MAS_UTrack_V00" },       /* Ult */
        {  0, "DDMF" },                 /* DMF */
        {  8, "DSMFSONG" },             /* DSM */
        {  0, "\xc1\x83\x2a\x9e" },     /* UMX */
        {  0, "ASYLUM Music Format V1.0" }, /* AMF Type 0 */
        {  0, "AMF" },                  /* AMF */
        {  0, "PSM\xfe" },              /* PSM */
        {  0, "PSM " },                 /* PSM */
        {  0, "MT20" },                 /* MT2 */

        { 1080, "M.K." },               /* MOD */
        { 1080, "M!K!" },
        { 1080, "M&K!" },
        { 1080, "N.T." },
        { 1080, "CD81" },
        { 1080, "OKTA" },
        { 1080, "16CN" },
        { 1080, "32CN" },
        { 1080, "FLT4" },
        { 1080, "FLT8" },
        { 1080, "6CHN" },
        { 1080, "8CHN" },
        { 1080, "FLT" },
        { 1080, "TDZ" },
        { 1081, "CHN" },
        { 1082, "CH" },

        {  -1, NULL }
    };
    static const char *ppsz_mod_ext[] =
    {
        "mod", "s3m", "xm",  "it",  "669", "amf", "ams", "dbm", "dmf", "dsm",
        "far", "mdl", "med", "mtm", "okt", "ptm", "stm", "ult", "umx", "mt2",
        "psm", "abc", NULL
    };
    bool has_valid_extension = false;
    if( psz_ext )
    {
        for( int i = 0; ppsz_mod_ext[i] != NULL; i++ )
        {
            has_valid_extension |= !strcasecmp( psz_ext, ppsz_mod_ext[i] );
            if( has_valid_extension )
                break;
        }
    }

    const uint8_t *p_peek;
    const int i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 );
    if( i_peek < 4 )
        return VLC_EGENERIC;

    for( int i = 0; p_marker[i].i_offset >= 0; i++ )
    {
        const char *psz_marker = p_marker[i].psz_marker;
        const int i_size = strlen( psz_marker );
        const int i_offset = p_marker[i].i_offset;

        if( i_peek < i_offset + i_size )
            continue;

        if( !memcmp( &p_peek[i_offset], psz_marker, i_size ) )
        {
            if( i_size >= 4 || has_valid_extension )
                return VLC_SUCCESS;
        }
    }

    /* The only two format left untested are ABC and MOD(old version)
     * ant they are difficult to test :( */

    /* Check for ABC
     * TODO i_peek = 2048 is too big for such files */
    if( psz_ext && !strcasecmp( psz_ext, "abc" ) )
    {
        bool b_k = false;
        bool b_tx = false;

        for( int i = 0; i < i_peek-1; i++ )
        {
            b_k |= p_peek[i+0] == 'K' && p_peek[i+1] == ':';
            b_tx |= ( p_peek[i+0] == 'X' || p_peek[i+0] == 'T') && p_peek[i+1] == ':';
        }
        if( !b_k || !b_tx )
            return VLC_EGENERIC;
        return VLC_SUCCESS;
    }

    /* Check for MOD */
    if( psz_ext && !strcasecmp( psz_ext, "mod" ) && i_peek >= 20 + 15 * 30 )
    {
        /* Check that the name is correctly null padded */
        const uint8_t *p = memchr( p_peek, '\0', 20 );
        if( p )
        {
            for( ; p < &p_peek[20]; p++ )
            {
                if( *p )
                    return VLC_EGENERIC;
            }
        }

        for( int i = 0; i < 15; i++ )
        {
            const uint8_t *p_sample = &p_peek[20 + i*30];

            /* Check correct null padding */
            p = memchr( &p_sample[0], '\0', 22 );
            if( p )
            {
                for( ; p < &p_sample[22]; p++ )
                {
                    if( *p )
                        return VLC_EGENERIC;
                }
            }

            if( p_sample[25] > 64 ) /* Volume value */
                return VLC_EGENERIC;
        }
        return VLC_SUCCESS;
    }
    return VLC_EGENERIC;
}
Exemple #29
0
static int Open(vlc_object_t *object)
{
    demux_t *demux = (demux_t*)object;

    const uint8_t *peek;
    if (vlc_stream_Peek(demux->s, &peek, 11) != 11)
        return VLC_EGENERIC;

    bool is_stl_25 = !memcmp(&peek[3], "STL25.01", 8);
    bool is_stl_30 = !memcmp(&peek[3], "STL30.01", 8);
    if (!is_stl_25 && !is_stl_30)
        return VLC_EGENERIC;
    const double fps = is_stl_25 ? 25 : 30;

    uint8_t header[1024];
    if (vlc_stream_Read(demux->s, header, sizeof(header)) != sizeof(header)) {
        msg_Err(demux, "Incomplete EBU STL header");
        return VLC_EGENERIC;
    }
    const int cct = ParseInteger(&header[12], 2);
    const mtime_t program_start = ParseTextTimeCode(&header[256], fps);
    const int tti_count = ParseInteger(&header[238], 5);
    msg_Dbg(demux, "Detected EBU STL : CCT=%d TTI=%d start=%8.8s %"PRId64, cct, tti_count, &header[256], program_start);

    demux_sys_t *sys = xmalloc(sizeof(*sys));
    sys->next_date = 0;
    sys->current   = 0;
    sys->count     = 0;
    sys->index     = xcalloc(tti_count, sizeof(*sys->index));


    bool comment = false;
    stl_entry_t *s = &sys->index[0];
    s->count = 0;

    for (int i = 0; i < tti_count; i++) {
        uint8_t tti[16];
        if (vlc_stream_Read(demux->s, tti, 16) != 16 ||
            vlc_stream_Read(demux->s, NULL, 112) != 112) {
            msg_Warn(demux, "Incomplete EBU STL file");
            break;
        }
        const int ebn = tti[3];
        if (ebn >= 0xf0 && ebn <= 0xfd)
            continue;
        if (ebn == 0xfe)
            continue;

        if (s->count <= 0) {
            comment  = tti[15] != 0;
            s->start = ParseTimeCode(&tti[5], fps) - program_start;
            s->stop  = ParseTimeCode(&tti[9], fps) - program_start;
            s->index = i;
        }
        s->count++;
        if (ebn == 0xff && !comment)
            s = &sys->index[++sys->count];
        if (ebn == 0xff && sys->count < tti_count)
            s->count = 0;
    }
    if (sys->count > 0)
        vlc_stream_Seek(demux->s, 1024 + 128LL * sys->index[0].index);

    es_format_t fmt;
    es_format_Init(&fmt, SPU_ES, VLC_CODEC_EBU_STL);
    fmt.i_extra = sizeof(header);
    fmt.p_extra = header;

    sys->es = es_out_Add(demux->out, &fmt);

    fmt.i_extra = 0;
    fmt.p_extra = NULL;
    es_format_Clean(&fmt);

    demux->p_sys      = sys;
    demux->pf_demux   = Demux;
    demux->pf_control = Control;
    return VLC_SUCCESS;
}
Exemple #30
0
static int avformat_ProbeDemux( vlc_object_t *p_this,
                                AVInputFormat **pp_fmt, const char *psz_url )
{
    demux_t       *p_demux = (demux_t*)p_this;
    AVProbeData   pd = { 0 };
    const uint8_t *peek;

    /* Init Probe data */
    pd.buf_size = vlc_stream_Peek( p_demux->s, &peek, 2048 + 213 );
    if( pd.buf_size <= 0 )
    {
        msg_Warn( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    pd.buf = malloc( pd.buf_size + AVPROBE_PADDING_SIZE );
    if( unlikely(pd.buf == NULL) )
        return VLC_ENOMEM;

    memcpy( pd.buf, peek, pd.buf_size );
    memset( pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE );

    if( psz_url != NULL )
        msg_Dbg( p_demux, "trying url: %s", psz_url );

    pd.filename = psz_url;

    vlc_init_avformat(p_this);

    /* Guess format */
    char *psz_format = var_InheritString( p_this, "avformat-format" );
    if( psz_format )
    {
        if( (*pp_fmt = av_find_input_format(psz_format)) )
            msg_Dbg( p_demux, "forcing format: %s", (*pp_fmt)->name );
        free( psz_format );
    }

    if( *pp_fmt == NULL )
        *pp_fmt = av_probe_input_format( &pd, 1 );

    free( pd.buf );

    if( *pp_fmt == NULL )
    {
        msg_Dbg( p_demux, "couldn't guess format" );
        return VLC_EGENERIC;
    }

    if( !p_demux->obj.force )
    {
        static const char ppsz_blacklist[][16] = {
            /* Don't handle MPEG unless forced */
            "mpeg", "vcd", "vob", "mpegts",
            /* libavformat's redirector won't work */
            "redir", "sdp",
            /* Don't handle subtitles format */
            "ass", "srt", "microdvd",
            /* No timestamps at all */
            "hevc", "h264",
            ""
        };

        for( int i = 0; *ppsz_blacklist[i]; i++ )
        {
            if( !strcmp( (*pp_fmt)->name, ppsz_blacklist[i] ) )
                return VLC_EGENERIC;
        }
    }

    /* Don't trigger false alarms on bin files */
    if( !p_demux->obj.force && !strcmp( (*pp_fmt)->name, "psxstr" ) )
    {
        int i_len;

        if( !p_demux->psz_filepath )
            return VLC_EGENERIC;

        i_len = strlen( p_demux->psz_filepath );
        if( i_len < 4 )
            return VLC_EGENERIC;

        if( strcasecmp( &p_demux->psz_filepath[i_len - 4], ".str" ) &&
            strcasecmp( &p_demux->psz_filepath[i_len - 4], ".xai" ) &&
            strcasecmp( &p_demux->psz_filepath[i_len - 3], ".xa" ) )
        {
            return VLC_EGENERIC;
        }
    }

    msg_Dbg( p_demux, "detected format: %s", (*pp_fmt)->name );

    return VLC_SUCCESS;
}