Changeset 07c2bef65b14a837755f3f17d4ac0c2250d8f590

Show
Ignore:
Timestamp:
02/04/04 18:17:15 (5 years ago)
Author:
Laurent Aimar <fenrir@videolan.org>
git-committer:
Laurent Aimar <fenrir@videolan.org> 1080922635 +0000
git-parent:

[d8f54d49fb3254183481e62918deedbbfa3dcee7]

git-author:
Laurent Aimar <fenrir@videolan.org> 1080922635 +0000
Message:
  • ogg: cosmetics + converted PCR to micro-second unit. (I may

introduced bugs).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/demux/ogg.c

    r5aedd62 r07c2bef  
    3434#include "vlc_bits.h" 
    3535 
    36 #define OGG_BLOCK_SIZE 4096 
     36/***************************************************************************** 
     37 * Module descriptor 
     38 *****************************************************************************/ 
     39static int  Open ( vlc_object_t * ); 
     40static void Close( vlc_object_t * ); 
     41 
     42vlc_module_begin(); 
     43    set_description( _("Ogg stream demuxer" ) ); 
     44    set_capability( "demux", 50 ); 
     45    set_callbacks( Open, Close ); 
     46    add_shortcut( "ogg" ); 
     47vlc_module_end(); 
     48 
    3749 
    3850/***************************************************************************** 
     
    8294     * the sub-streams */ 
    8395    mtime_t i_pcr; 
    84     int     i_old_synchro_state; 
    8596 
    8697    /* stream state */ 
     
    125136} stream_header; 
    126137 
     138#define OGG_BLOCK_SIZE 4096 
     139 
    127140/* Some defines from OggDS */ 
    128141#define PACKET_TYPE_HEADER   0x01 
     
    135148 * Local prototypes 
    136149 *****************************************************************************/ 
    137 static int  Activate  ( vlc_object_t * ); 
    138 static void Deactivate( vlc_object_t * ); 
    139 static int  Demux     ( input_thread_t * ); 
    140 static int  Control   ( input_thread_t *, int, va_list ); 
     150static int  Demux  ( input_thread_t * ); 
     151static int  Control( input_thread_t *, int, va_list ); 
    141152 
    142153/* Bitstream manipulation */ 
    143 static int  Ogg_Check        ( input_thread_t *p_input ); 
    144 static int  Ogg_ReadPage     ( input_thread_t *, demux_sys_t *, ogg_page * ); 
     154static int  Ogg_ReadPage     ( input_thread_t *, ogg_page * ); 
    145155static void Ogg_UpdatePCR    ( logical_stream_t *, ogg_packet * ); 
    146 static void Ogg_DecodePacket ( input_thread_t *p_input, 
    147                                logical_stream_t *p_stream, ogg_packet * ); 
    148  
    149 static int Ogg_BeginningOfStream( input_thread_t *p_input, demux_sys_t *p_ogg); 
    150 static int Ogg_FindLogicalStreams( input_thread_t *p_input,demux_sys_t *p_ogg); 
    151 static void Ogg_EndOfStream( input_thread_t *p_input, demux_sys_t *p_ogg ); 
     156static void Ogg_DecodePacket ( input_thread_t *, logical_stream_t *, ogg_packet * ); 
     157 
     158static int Ogg_BeginningOfStream( input_thread_t *p_input ); 
     159static int Ogg_FindLogicalStreams( input_thread_t *p_input ); 
     160static void Ogg_EndOfStream( input_thread_t *p_input ); 
    152161 
    153162/* Logical bitstream headers */ 
     
    160169 
    161170/***************************************************************************** 
    162  * Module descriptor 
     171 * Open: initializes ogg demux structures 
    163172 *****************************************************************************/ 
    164 vlc_module_begin(); 
    165     set_description( _("Ogg stream demuxer" ) ); 
    166     set_capability( "demux", 50 ); 
    167     set_callbacks( Activate, Deactivate ); 
    168     add_shortcut( "ogg" ); 
    169 vlc_module_end(); 
    170  
    171 /**************************************************************************** 
    172  * Ogg_Check: Check we are dealing with an ogg stream. 
    173  ****************************************************************************/ 
    174 static int Ogg_Check( input_thread_t *p_input ) 
    175 
    176     uint8_t *p_peek; 
    177     int i_size = input_Peek( p_input, &p_peek, 4 ); 
    178  
    179     /* Check for the Ogg capture pattern */ 
    180     if( !(i_size>3) || !(p_peek[0] == 'O') || !(p_peek[1] == 'g') || 
    181         !(p_peek[2] == 'g') || !(p_peek[3] == 'S') ) 
     173static int Open( vlc_object_t * p_this ) 
     174
     175    input_thread_t *p_input = (input_thread_t *)p_this; 
     176    demux_sys_t    *p_sys; 
     177    uint8_t        *p_peek; 
     178 
     179 
     180    /* Check if we are dealing with an ogg stream */ 
     181    if( stream_Peek( p_input->s, &p_peek, 4 ) < 4 ) 
     182    { 
     183        msg_Err( p_input, "cannot peek" ); 
    182184        return VLC_EGENERIC; 
    183  
    184     /* FIXME: Capture pattern might not be enough so we can also check for the 
    185      * the first complete page */ 
     185    } 
     186    if( strcmp( p_input->psz_demux, "ogg" ) && strncmp( p_peek, "OggS", 4 ) ) 
     187    { 
     188        msg_Warn( p_input, "ogg module discarded (invalid header)" ); 
     189        return VLC_EGENERIC; 
     190    } 
     191 
     192    /* Create one program */ 
     193    vlc_mutex_lock( &p_input->stream.stream_lock ); 
     194    if( input_InitStream( p_input, 0 ) == -1) 
     195    { 
     196        vlc_mutex_unlock( &p_input->stream.stream_lock ); 
     197        msg_Err( p_input, "cannot init stream" ); 
     198        return VLC_EGENERIC; 
     199    } 
     200    vlc_mutex_unlock( &p_input->stream.stream_lock ); 
     201 
     202    /* Set exported functions */ 
     203    p_input->pf_demux = Demux; 
     204    p_input->pf_demux_control = Control; 
     205    p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) ); 
     206 
     207    memset( p_sys, 0, sizeof( demux_sys_t ) ); 
     208    p_sys->pp_stream = NULL; 
     209 
     210    /* Begnning of stream, tell the demux to look for elementary streams. */ 
     211    p_sys->i_eos = 0; 
     212 
     213    /* Initialize the Ogg physical bitstream parser */ 
     214    ogg_sync_init( &p_sys->oy ); 
    186215 
    187216    return VLC_SUCCESS; 
     217} 
     218 
     219/***************************************************************************** 
     220 * Close: frees unused data 
     221 *****************************************************************************/ 
     222static void Close( vlc_object_t *p_this ) 
     223{ 
     224    input_thread_t *p_input = (input_thread_t *)p_this; 
     225    demux_sys_t *p_sys = p_input->p_demux_data  ; 
     226 
     227    /* Cleanup the bitstream parser */ 
     228    ogg_sync_clear( &p_sys->oy ); 
     229 
     230    Ogg_EndOfStream( p_input ); 
     231 
     232    free( p_sys ); 
     233} 
     234 
     235/***************************************************************************** 
     236 * Demux: reads and demuxes data packets 
     237 ***************************************************************************** 
     238 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise 
     239 *****************************************************************************/ 
     240static int Demux( input_thread_t * p_input ) 
     241{ 
     242    demux_sys_t *p_sys = p_input->p_demux_data; 
     243    ogg_page    oggpage; 
     244    ogg_packet  oggpacket; 
     245    int         i_stream; 
     246 
     247 
     248    if( p_sys->i_eos == p_sys->i_streams ) 
     249    { 
     250        if( p_sys->i_eos ) 
     251        { 
     252            msg_Dbg( p_input, "end of a group of logical streams" ); 
     253            Ogg_EndOfStream( p_input ); 
     254        } 
     255 
     256        if( Ogg_BeginningOfStream( p_input ) != VLC_SUCCESS ) return 0; 
     257        p_sys->i_eos = 0; 
     258 
     259        msg_Dbg( p_input, "beginning of a group of logical streams" ); 
     260        es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR ); 
     261    } 
     262 
     263    /* 
     264     * Demux an ogg page from the stream 
     265     */ 
     266    if( Ogg_ReadPage( p_input, &oggpage ) != VLC_SUCCESS ) 
     267    { 
     268        return 0; /* EOF */ 
     269    } 
     270 
     271    /* Test for End of Stream */ 
     272    if( ogg_page_eos( &oggpage ) ) p_sys->i_eos++; 
     273 
     274 
     275    for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) 
     276    { 
     277        logical_stream_t *p_stream = p_sys->pp_stream[i_stream]; 
     278 
     279        if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 ) 
     280            continue; 
     281 
     282        while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) 
     283        { 
     284            /* Read info from any secondary header packets, if there are any */ 
     285            if( p_stream->secondary_header_packets > 0 ) 
     286            { 
     287                if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) && 
     288                        oggpacket.bytes >= 7 && 
     289                        ! strncmp( &oggpacket.packet[1], "theora", 6 ) ) 
     290                { 
     291                    Ogg_ReadTheoraHeader( p_stream, &oggpacket ); 
     292                    p_stream->secondary_header_packets = 0; 
     293                } 
     294                else if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) && 
     295                        oggpacket.bytes >= 7 && 
     296                        ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) ) 
     297                { 
     298                    Ogg_ReadVorbisHeader( p_stream, &oggpacket ); 
     299                    p_stream->secondary_header_packets = 0; 
     300                } 
     301                else if ( p_stream->fmt.i_codec == VLC_FOURCC( 'c','m','m','l' ) ) 
     302                { 
     303                    p_stream->secondary_header_packets = 0; 
     304                } 
     305 
     306                p_stream->secondary_header_packets--; 
     307            } 
     308 
     309            if( p_stream->b_reinit ) 
     310            { 
     311                /* If synchro is re-initialized we need to drop all the packets 
     312                 * until we find a new dated one. */ 
     313                Ogg_UpdatePCR( p_stream, &oggpacket ); 
     314 
     315                if( p_stream->i_pcr >= 0 ) 
     316                { 
     317                    p_stream->b_reinit = 0; 
     318                } 
     319                else 
     320                { 
     321                    p_stream->i_interpolated_pcr = -1; 
     322                    continue; 
     323                } 
     324 
     325                /* An Ogg/vorbis packet contains an end date granulepos */ 
     326                if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) || 
     327                    p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) || 
     328                    p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) ) 
     329                { 
     330                    if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) 
     331                    { 
     332                        Ogg_DecodePacket( p_input, p_stream, &oggpacket ); 
     333                    } 
     334                    else 
     335                    { 
     336                        es_out_Control( p_input->p_es_out, ES_OUT_SET_PCR, p_stream->i_pcr ); 
     337                    } 
     338                    continue; 
     339                } 
     340            } 
     341 
     342            Ogg_DecodePacket( p_input, p_stream, &oggpacket ); 
     343        } 
     344        break; 
     345    } 
     346 
     347    i_stream = 0; p_sys->i_pcr = -1; 
     348    for( ; i_stream < p_sys->i_streams; i_stream++ ) 
     349    { 
     350        logical_stream_t *p_stream = p_sys->pp_stream[i_stream]; 
     351 
     352        if( p_stream->fmt.i_cat == SPU_ES ) 
     353            continue; 
     354        if( p_stream->i_interpolated_pcr < 0 ) 
     355            continue; 
     356 
     357        if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr ) 
     358            p_sys->i_pcr = p_stream->i_interpolated_pcr; 
     359    } 
     360 
     361    if( p_sys->i_pcr >= 0 ) 
     362    { 
     363        es_out_Control( p_input->p_es_out, ES_OUT_SET_PCR, p_sys->i_pcr ); 
     364    } 
     365 
     366 
     367    return 1; 
     368} 
     369 
     370/***************************************************************************** 
     371 * Control: 
     372 *****************************************************************************/ 
     373static int Control( input_thread_t *p_input, int i_query, va_list args ) 
     374{ 
     375    demux_sys_t *p_sys  = p_input->p_demux_data; 
     376    int64_t *pi64; 
     377    int i; 
     378 
     379    switch( i_query ) 
     380    { 
     381        case DEMUX_GET_TIME: 
     382            pi64 = (int64_t*)va_arg( args, int64_t * ); 
     383            *pi64 = p_sys->i_pcr; 
     384            return VLC_SUCCESS; 
     385 
     386        case DEMUX_SET_TIME: 
     387            return VLC_EGENERIC; 
     388 
     389        case DEMUX_SET_POSITION: 
     390            for( i = 0; i < p_sys->i_streams; i++ ) 
     391            { 
     392                logical_stream_t *p_stream = p_sys->pp_stream[i]; 
     393 
     394                /* we'll trash all the data until we find the next pcr */ 
     395                p_stream->b_reinit = 1; 
     396                p_stream->i_pcr = -1; 
     397                p_stream->i_interpolated_pcr = -1; 
     398                ogg_stream_reset( &p_stream->os ); 
     399            } 
     400            ogg_sync_reset( &p_sys->oy ); 
     401 
     402        default: 
     403            return demux_vaControlDefault( p_input, i_query, args ); 
     404    } 
    188405} 
    189406 
     
    194411 * are at the end of stream. 
    195412 ****************************************************************************/ 
    196 static int Ogg_ReadPage( input_thread_t *p_input, demux_sys_t *p_ogg, 
    197                          ogg_page *p_oggpage ) 
    198 
     413static int Ogg_ReadPage( input_thread_t *p_input, ogg_page *p_oggpage ) 
     414
     415    demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
    199416    int i_read = 0; 
    200417    data_packet_t *p_data; 
     
    228445        if( p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) ) 
    229446        { 
    230             p_stream->i_pcr = p_oggpacket->granulepos * 90000 
     447            p_stream->i_pcr = p_oggpacket->granulepos * I64C(1000000) 
    231448                              / p_stream->f_rate; 
    232449        } 
     
    238455              ( iframe << p_stream->i_theora_keyframe_granule_shift ); 
    239456 
    240             p_stream->i_pcr = ( iframe + pframe ) * 90000 
     457            p_stream->i_pcr = ( iframe + pframe ) * I64C(1000000) 
    241458                              / p_stream->f_rate; 
    242459        } 
     
    252469        if( p_stream->fmt.i_cat == VIDEO_ES ) 
    253470            /* 1 frame per packet */ 
    254             p_stream->i_interpolated_pcr += (90000 / p_stream->f_rate); 
     471            p_stream->i_interpolated_pcr += (I64C(1000000) / p_stream->f_rate); 
    255472        else if( p_stream->fmt.i_bitrate ) 
    256             p_stream->i_interpolated_pcr += ( p_oggpacket->bytes * 90000 
     473            p_stream->i_interpolated_pcr += ( p_oggpacket->bytes * I64C(1000000) 
    257474                                              / p_stream->fmt.i_bitrate / 8 ); 
    258475    } 
     
    405622                /* Set correct starting date in header packets */ 
    406623                p_stream->p_packets_backup[i].granulepos = 
    407                     p_stream->i_interpolated_pcr * p_stream->f_rate / 90000
     624                    p_stream->i_interpolated_pcr * p_stream->f_rate / I64C(1000000)
    408625 
    409626                Ogg_DecodePacket( p_input, p_stream, 
     
    423640             * doesn't match these of the data packets (eg. ogg web radios). */ 
    424641            if( p_stream->i_previous_pcr == 0 && 
    425                 p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY * 9/100 ) 
    426                 p_input->stream.p_selected_program->i_synchro_state = 
    427                     SYNCHRO_REINIT; 
     642                p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY ) 
     643            { 
     644                es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR ); 
     645 
     646                /* Call the pace control */ 
     647                es_out_Control( p_input->p_es_out, ES_OUT_SET_PCR, p_stream->i_pcr ); 
     648            } 
    428649 
    429650            p_stream->i_previous_pcr = p_stream->i_pcr; 
    430651 
    431             /* Call the pace control */ 
    432             if( p_input->stream.p_selected_program->i_synchro_state == 
    433                 SYNCHRO_REINIT ) 
    434             input_ClockManageRef( p_input, 
    435                                   p_input->stream.p_selected_program, 
    436                                   p_stream->i_pcr ); 
    437  
    438652            /* The granulepos is the end date of the sample */ 
    439             i_pts =  input_ClockGetTS( p_input, 
    440                                        p_input->stream.p_selected_program, 
    441                                        p_stream->i_pcr ); 
     653            i_pts =  p_stream->i_pcr; 
    442654        } 
    443655    } 
     
    451663         * doesn't match these of the data packets (eg. ogg web radios). */ 
    452664        if( p_stream->i_previous_pcr == 0 && 
    453             p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY * 9/100 ) 
    454             p_input->stream.p_selected_program->i_synchro_state = 
    455                 SYNCHRO_REINIT; 
    456  
    457         /* Call the pace control */ 
    458         if( p_input->stream.p_selected_program->i_synchro_state == 
    459             SYNCHRO_REINIT ) 
    460           input_ClockManageRef( p_input, p_input->stream.p_selected_program, 
    461                                 p_stream->i_pcr ); 
     665            p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY ) 
     666        { 
     667            es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR ); 
     668 
     669            /* Call the pace control */ 
     670            es_out_Control( p_input->p_es_out, ES_OUT_SET_PCR, p_stream->i_pcr ); 
     671        } 
    462672    } 
    463673 
     
    470680 
    471681        /* The granulepos is the start date of the sample */ 
    472         i_pts = input_ClockGetTS( p_input, p_input->stream.p_selected_program, 
    473                                   p_stream->i_pcr ); 
     682        i_pts = p_stream->i_pcr; 
    474683    } 
    475684 
     
    561770 * On success this function returns VLC_SUCCESS. 
    562771 ****************************************************************************/ 
    563 static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) 
    564 
     772static int Ogg_FindLogicalStreams( input_thread_t *p_input ) 
     773
     774    demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
    565775    ogg_packet oggpacket; 
    566776    ogg_page oggpage; 
     
    569779#define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1] 
    570780 
    571     while( Ogg_ReadPage( p_input, p_ogg, &oggpage ) == VLC_SUCCESS ) 
     781    while( Ogg_ReadPage( p_input, &oggpage ) == VLC_SUCCESS ) 
    572782    { 
    573783        if( ogg_page_bos( &oggpage ) ) 
     
    9481158                } 
    9491159 
    950                 if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS ) 
     1160                if( Ogg_ReadPage( p_input, &oggpage ) != VLC_SUCCESS ) 
    9511161                    return VLC_EGENERIC; 
    9521162            } 
     
    9721182} 
    9731183 
    974 /***************************************************************************** 
    975  * Activate: initializes ogg demux structures 
    976  *****************************************************************************/ 
    977 static int Activate( vlc_object_t * p_this ) 
    978 { 
    979     input_thread_t *p_input = (input_thread_t *)p_this; 
    980     demux_sys_t    *p_ogg; 
    981     int            b_forced; 
    982  
    983     p_input->p_demux_data = NULL; 
    984     b_forced = ( ( *p_input->psz_demux )&& 
    985                  ( !strncmp( p_input->psz_demux, "ogg", 10 ) ) ) ? 1 : 0; 
    986  
    987     /* Check if we are dealing with an ogg stream */ 
    988     if( !b_forced && ( Ogg_Check( p_input ) != VLC_SUCCESS ) ) 
    989         return -1; 
    990  
    991     /* Allocate p_ogg */ 
    992     if( !( p_ogg = malloc( sizeof( demux_sys_t ) ) ) ) 
    993     { 
    994         msg_Err( p_input, "out of memory" ); 
    995         goto error; 
    996     } 
    997     memset( p_ogg, 0, sizeof( demux_sys_t ) ); 
    998     p_input->p_demux_data = p_ogg; 
    999     p_ogg->pp_stream = NULL; 
    1000  
    1001     /* Initialize the Ogg physical bitstream parser */ 
    1002     ogg_sync_init( &p_ogg->oy ); 
    1003  
    1004     /* Set exported functions */ 
    1005     p_input->pf_demux = Demux; 
    1006     p_input->pf_demux_control = Control; 
    1007  
    1008     /* Initialize access plug-in structures. */ 
    1009     if( p_input->i_mtu == 0 ) 
    1010     { 
    1011         /* Improve speed. */ 
    1012         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE; 
    1013     } 
    1014  
    1015     /* Create one program */ 
    1016     vlc_mutex_lock( &p_input->stream.stream_lock ); 
    1017     if( input_InitStream( p_input, 0 ) == -1) 
    1018     { 
    1019         vlc_mutex_unlock( &p_input->stream.stream_lock ); 
    1020         msg_Err( p_input, "cannot init stream" ); 
    1021         goto error; 
    1022     } 
    1023     if( input_AddProgram( p_input, 0, 0) == NULL ) 
    1024     { 
    1025         vlc_mutex_unlock( &p_input->stream.stream_lock ); 
    1026         msg_Err( p_input, "cannot add program" ); 
    1027         goto error; 
    1028     } 
    1029     p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; 
    1030     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
    1031  
    1032     /* Begnning of stream, tell the demux to look for elementary streams. */ 
    1033     p_ogg->i_eos = 0; 
    1034  
    1035     p_ogg->i_old_synchro_state = !SYNCHRO_REINIT; 
    1036  
    1037     return 0; 
    1038  
    1039  error: 
    1040     Deactivate( (vlc_object_t *)p_input ); 
    1041     return -1; 
    1042  
    1043 } 
    1044  
    10451184/**************************************************************************** 
    10461185 * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add 
    10471186 *                        Elementary streams. 
    10481187 ****************************************************************************/ 
    1049 static int Ogg_BeginningOfStream( input_thread_t *p_input, demux_sys_t *p_ogg) 
    1050 
     1188static int Ogg_BeginningOfStream( input_thread_t *p_input ) 
     1189
     1190    demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
    10511191    int i_stream; 
    10521192 
    10531193    /* Find the logical streams embedded in the physical stream and 
    10541194     * initialize our p_ogg structure. */ 
    1055     if( Ogg_FindLogicalStreams( p_input, p_ogg ) != VLC_SUCCESS ) 
     1195    if( Ogg_FindLogicalStreams( p_input ) != VLC_SUCCESS ) 
    10561196    { 
    10571197        msg_Warn( p_input, "couldn't find any ogg logical stream" ); 
     
    10931233 * Ogg_EndOfStream: clean up the ES when an End of Stream is detected. 
    10941234 ****************************************************************************/ 
    1095 static void Ogg_EndOfStream( input_thread_t *p_input, demux_sys_t *p_ogg ) 
    1096 
     1235static void Ogg_EndOfStream( input_thread_t *p_input ) 
     1236
     1237    demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
    10971238    int i_stream, j; 
    10981239 
     
    11251266    p_ogg->pp_stream = NULL; 
    11261267    p_ogg->i_streams = 0; 
    1127 } 
    1128  
    1129 /***************************************************************************** 
    1130  * Deactivate: frees unused data 
    1131  *****************************************************************************/ 
    1132 static void Deactivate( vlc_object_t *p_this ) 
    1133 { 
    1134     input_thread_t *p_input = (input_thread_t *)p_this; 
    1135     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
    1136  
    1137     if( p_ogg ) 
    1138     { 
    1139         /* Cleanup the bitstream parser */ 
    1140         ogg_sync_clear( &p_ogg->oy ); 
    1141  
    1142         Ogg_EndOfStream( p_input, p_ogg ); 
    1143  
    1144         free( p_ogg ); 
    1145     } 
    1146 } 
    1147  
    1148 /***************************************************************************** 
    1149  * Demux: reads and demuxes data packets 
    1150  ***************************************************************************** 
    1151  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise 
    1152  *****************************************************************************/ 
    1153 static int Demux( input_thread_t * p_input ) 
    1154 { 
    1155     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data; 
    1156     ogg_page    oggpage; 
    1157     ogg_packet  oggpacket; 
    1158     int         i_stream; 
    1159  
    1160 #define p_stream p_ogg->pp_stream[i_stream] 
    1161  
    1162     if( p_ogg->i_eos == p_ogg->i_streams ) 
    1163     { 
    1164         if( p_ogg->i_eos ) 
    1165         { 
    1166             msg_Dbg( p_input, "end of a group of logical streams" ); 
    1167             Ogg_EndOfStream( p_input, p_ogg ); 
    1168         } 
    1169  
    1170         if( Ogg_BeginningOfStream( p_input, p_ogg ) != VLC_SUCCESS ) return 0; 
    1171         p_ogg->i_eos = 0; 
    1172  
    1173         msg_Dbg( p_input, "beginning of a group of logical streams" ); 
    1174  
    1175         p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_REINIT; 
    1176         input_ClockManageRef( p_input, p_input->stream.p_selected_program, 0 ); 
    1177     } 
    1178  
    1179     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT ) 
    1180     { 
    1181         msg_Warn( p_input, "synchro reinit" ); 
    1182  
    1183         if( p_ogg->i_old_synchro_state != SYNCHRO_REINIT ) 
    1184         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ ) 
    1185         { 
    1186             /* we'll trash all the data until we find the next pcr */ 
    1187             p_stream->b_reinit = 1; 
    1188             p_stream->i_pcr = -1; 
    1189             p_stream->i_interpolated_pcr = -1; 
    1190             ogg_stream_reset( &p_stream->os ); 
    1191         } 
    1192         if( p_ogg->i_old_synchro_state != SYNCHRO_REINIT ) 
    1193         ogg_sync_reset( &p_ogg->oy ); 
    1194     } 
    1195  
    1196     /* 
    1197      * Demux an ogg page from the stream 
    1198      */ 
    1199     if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS ) 
    1200     { 
    1201         return 0; /* EOF */ 
    1202     } 
    1203  
    1204     /* Test for End of Stream */ 
    1205     if( ogg_page_eos( &oggpage ) ) p_ogg->i_eos++; 
    1206  
    1207  
    1208     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ ) 
    1209     { 
    1210         if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 ) 
    1211             continue; 
    1212  
    1213         while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) 
    1214         { 
    1215             /* Read info from any secondary header packets, if there are any */ 
    1216             if( p_stream->secondary_header_packets > 0 ) 
    1217             { 
    1218                 if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) && 
    1219                         oggpacket.bytes >= 7 && 
    1220                         ! strncmp( &oggpacket.packet[1], "theora", 6 ) ) 
    1221                 { 
    1222                     Ogg_ReadTheoraHeader( p_stream, &oggpacket ); 
    1223                     p_stream->secondary_header_packets = 0; 
    1224                 } 
    1225                 else if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) && 
    1226                         oggpacket.bytes >= 7 && 
    1227                         ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) ) 
    1228                 { 
    1229                     Ogg_ReadVorbisHeader( p_stream, &oggpacket ); 
    1230                     p_stream->secondary_header_packets = 0; 
    1231                 } 
    1232                 else if ( p_stream->fmt.i_codec == VLC_FOURCC( 'c','m','m','l' ) ) 
    1233                 { 
    1234                     p_stream->secondary_header_packets = 0; 
    1235                 } 
    1236  
    1237                 p_stream->secondary_header_packets--; 
    1238             } 
    1239  
    1240             if( p_stream->b_reinit ) 
    1241             { 
    1242                 /* If synchro is re-initialized we need to drop all the packets 
    1243                  * until we find a new dated one. */ 
    1244                 Ogg_UpdatePCR( p_stream, &oggpacket ); 
    1245  
    1246                 if( p_stream->i_pcr >= 0 ) 
    1247                 { 
    1248                     p_stream->b_reinit = 0; 
    1249                 } 
    1250                 else 
    1251                 { 
    1252                     p_stream->i_interpolated_pcr = -1; 
    1253                     continue; 
    1254                 } 
    1255  
    1256                 /* An Ogg/vorbis packet contains an end date granulepos */ 
    1257                 if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) || 
    1258                     p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) || 
    1259                     p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) ) 
    1260                 { 
    1261                     if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) 
    1262                     { 
    1263                         Ogg_DecodePacket( p_input, p_stream, &oggpacket ); 
    1264                     } 
    1265                     else 
    1266                     { 
    1267                         input_ClockManageRef( p_input, 
    1268                                       p_input->stream.p_selected_program, 
    1269                                       p_stream->i_pcr ); 
    1270                     } 
    1271                     continue; 
    1272                 } 
    1273             } 
    1274  
    1275             Ogg_DecodePacket( p_input, p_stream, &oggpacket ); 
    1276         } 
    1277         break; 
    1278     } 
    1279  
    1280     i_stream = 0; p_ogg->i_pcr = -1; 
    1281     for( ; i_stream < p_ogg->i_streams; i_stream++ ) 
    1282     { 
    1283         if( p_stream->fmt.i_cat == SPU_ES ) 
    1284             continue; 
    1285         if( p_stream->i_interpolated_pcr < 0 ) 
    1286             continue; 
    1287  
    1288         if( p_ogg->i_pcr < 0 || p_stream->i_interpolated_pcr < p_ogg->i_pcr ) 
    1289             p_ogg->i_pcr = p_stream->i_interpolated_pcr; 
    1290     } 
    1291  
    1292     if( p_ogg->i_pcr >= 0 ) 
    1293     { 
    1294         input_ClockManageRef( p_input, p_input->stream.p_selected_program, 
    1295                               p_ogg->i_pcr ); 
    1296     } 
    1297  
    1298 #undef p_stream 
    1299  
    1300     p_ogg->i_old_synchro_state = 
    1301         p_input->stream.p_selected_program->i_synchro_state; 
    1302  
    1303     return 1; 
    1304 } 
    1305  
    1306 /***************************************************************************** 
    1307  * Control: 
    1308  *****************************************************************************/ 
    1309 static int Control( input_thread_t *p_input, int i_query, va_list args ) 
    1310 { 
    1311     demux_sys_t *p_ogg  = (demux_sys_t *)p_input->p_demux_data; 
    1312     int64_t *pi64; 
    1313  
    1314     switch( i_query ) 
    1315     { 
    1316         case DEMUX_GET_TIME: 
    1317             pi64 = (int64_t*)va_arg( args, int64_t * ); 
    1318             *pi64 = p_ogg->i_pcr * 100 / 9; 
    1319             return VLC_SUCCESS; 
    1320  
    1321         default: 
    1322             return demux_vaControlDefault( p_input, i_query, args ); 
    1323     } 
    13241268} 
    13251269