Changeset 6e94863269db988d825289b149755c4cae969cd8

Show
Ignore:
Timestamp:
20/11/03 19:27:44 (5 years ago)
Author:
Laurent Aimar <fenrir@videolan.org>
git-committer:
Laurent Aimar <fenrir@videolan.org> 1069352864 +0000
git-parent:

[05d8c3ba408d1b70e3a707c529a1280eae857618]

git-author:
Laurent Aimar <fenrir@videolan.org> 1069352864 +0000
Message:
  • copy: ported to new API.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/packetizer/copy.c

    r1e9f16e r6e94863  
    33 ***************************************************************************** 
    44 * Copyright (C) 2001, 2002 VideoLAN 
    5  * $Id: copy.c,v 1.18 2003/11/16 21:07:31 gbazin Exp $ 
     5 * $Id: copy.c,v 1.19 2003/11/20 18:27:44 fenrir Exp $ 
    66 * 
    77 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     
    3131#include <vlc/decoder.h> 
    3232#include <vlc/input.h> 
    33 #include <vlc/sout.h> 
    34  
    35 #include "codecs.h" 
    3633 
    3734/***************************************************************************** 
    3835 * Module descriptor 
    3936 *****************************************************************************/ 
    40 static int  Open    ( vlc_object_t * ); 
     37static int  Open ( vlc_object_t * ); 
     38static void Close( vlc_object_t * ); 
    4139 
    4240vlc_module_begin(); 
    4341    set_description( _("Copy packetizer") ); 
    4442    set_capability( "packetizer", 1 ); 
    45     set_callbacks( Open, NULL ); 
     43    set_callbacks( Open, Close ); 
    4644vlc_module_end(); 
    4745 
     
    4947 * Local prototypes 
    5048 *****************************************************************************/ 
    51 static int  Run         ( decoder_fifo_t * ); 
    52  
    53 typedef struct packetizer_thread_s 
    54 
    55     /* Input properties */ 
    56     decoder_fifo_t          *p_fifo; 
    57  
    58     /* Output properties */ 
    59     sout_packetizer_input_t *p_sout_input; 
    60     sout_format_t           output_format; 
    61  
    62     void                    (*pf_packetize)( struct packetizer_thread_s * ); 
    63  
    64 } packetizer_thread_t; 
    65  
    66 static int  Init        ( packetizer_thread_t * ); 
    67 static void PacketizeStd( packetizer_thread_t * ); 
    68 static void PacketizeSPU( packetizer_thread_t * ); 
    69 static void End         ( packetizer_thread_t * ); 
    70  
    71  
    72 static void AppendPEStoSoutBuffer( sout_instance_t *,sout_buffer_t **,pes_packet_t *); 
    73 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ); 
     49struct decoder_sys_t 
     50
     51    int i_spu_size; 
     52    int i_spu; 
     53 
     54    block_t *p_block; 
     55}; 
     56 
     57static block_t *PacketizeAV ( decoder_t *, block_t ** ); 
     58static block_t *PacketizeSPU( decoder_t *, block_t ** ); 
    7459 
    7560/***************************************************************************** 
     
    8166static int Open( vlc_object_t *p_this ) 
    8267{ 
    83     decoder_t *p_dec = (decoder_t*)p_this; 
    84  
    85     p_dec->pf_run = Run; 
    86  
    87     return VLC_SUCCESS; 
    88 
    89  
    90 /***************************************************************************** 
    91  * Run: this function is called just after the thread is created 
    92  *****************************************************************************/ 
    93 static int Run( decoder_fifo_t *p_fifo ) 
    94 
    95     packetizer_thread_t *p_pack; 
    96     int i_ret; 
    97  
    98     msg_Dbg( p_fifo, "Running copy packetizer (fcc=%4.4s)", 
    99              (char*)&p_fifo->i_fourcc ); 
    100  
    101     p_pack = malloc( sizeof( packetizer_thread_t ) ); 
    102     memset( p_pack, 0, sizeof( packetizer_thread_t ) ); 
    103  
    104     p_pack->p_fifo = p_fifo; 
    105  
    106     if( Init( p_pack ) ) 
    107     { 
    108         DecoderError( p_fifo ); 
     68    decoder_t     *p_dec = (decoder_t*)p_this; 
     69    decoder_sys_t *p_sys; 
     70 
     71    if( p_dec->fmt_in.i_cat == AUDIO_ES || p_dec->fmt_in.i_cat == VIDEO_ES ) 
     72    { 
     73        p_dec->pf_packetize = PacketizeAV; 
     74    } 
     75    else if( p_dec->fmt_in.i_cat == SPU_ES ) 
     76    { 
     77        if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', ' ' ) || 
     78            p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ) 
     79        { 
     80            p_dec->pf_packetize = PacketizeSPU; 
     81        } 
     82        else 
     83        { 
     84            p_dec->pf_packetize = PacketizeAV; 
     85        } 
     86    } 
     87    else 
     88    { 
     89        msg_Err( p_dec, "invalid ES type" ); 
    10990        return VLC_EGENERIC; 
    11091    } 
    11192 
    112     while( !p_pack->p_fifo->b_die && !p_pack->p_fifo->b_error ) 
    113     { 
    114         p_pack->pf_packetize( p_pack ); 
    115     } 
    116  
    117     if( p_pack->p_fifo->b_error ) 
    118     { 
    119         DecoderError( p_pack->p_fifo ); 
    120     } 
    121  
    122     i_ret = p_pack->p_fifo->b_error ? VLC_EGENERIC : VLC_SUCCESS; 
    123     End( p_pack ); 
    124  
    125     return( i_ret ); 
    126 
    127  
    128 /***************************************************************************** 
    129  * Init: initialize data before entering main loop 
    130  *****************************************************************************/ 
    131 static int Init( packetizer_thread_t *p_pack ) 
    132 
    133  
    134     p_pack->pf_packetize = PacketizeStd; 
    135  
    136     switch( p_pack->p_fifo->i_fourcc ) 
     93    /* Create the output format */ 
     94    memcpy( &p_dec->fmt_out, &p_dec->fmt_in, sizeof( es_format_t ) ); 
     95    if( p_dec->fmt_in.i_extra > 0 ) 
     96    { 
     97        p_dec->fmt_out.p_extra = malloc( p_dec->fmt_in.i_extra ); 
     98        memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, 
     99                p_dec->fmt_in.i_extra ); 
     100    } 
     101 
     102    /* Fix the value of the fourcc */ 
     103    switch( p_dec->fmt_in.i_codec ) 
    137104    { 
    138105        /* video */ 
     
    141108        case VLC_FOURCC( 'm', 'p', '4', 's'): 
    142109        case VLC_FOURCC( 'M', 'P', '4', 'S'): 
    143         case VLC_FOURCC( 'm', 'p', '4', 'v'): 
    144110        case VLC_FOURCC( 'D', 'I', 'V', 'X'): 
    145111        case VLC_FOURCC( 'd', 'i', 'v', 'x'): 
     
    150116        case VLC_FOURCC( 0x04, 0,   0,   0): 
    151117        case VLC_FOURCC( '3', 'I', 'V', '2'): 
    152             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', '4', 'v'); 
    153             p_pack->output_format.i_cat = VIDEO_ES; 
    154             break; 
    155         case VLC_FOURCC( 'm', 'p', 'g', 'v' ): 
     118            p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v'); 
     119            break; 
     120 
    156121        case VLC_FOURCC( 'm', 'p', 'g', '1' ): 
    157122        case VLC_FOURCC( 'm', 'p', 'g', '2' ): 
    158123        case VLC_FOURCC( 'm', 'p', '1', 'v' ): 
    159124        case VLC_FOURCC( 'm', 'p', '2', 'v' ): 
    160             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'v' ); 
    161             p_pack->output_format.i_cat = VIDEO_ES; 
     125            p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' ); 
    162126            break; 
    163127 
    164128        case VLC_FOURCC( 'd', 'i', 'v', '1' ): 
    165         case VLC_FOURCC( 'D', 'I', 'V', '1' ): 
    166129        case VLC_FOURCC( 'M', 'P', 'G', '4' ): 
    167130        case VLC_FOURCC( 'm', 'p', 'g', '4' ): 
    168             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '1' ); 
    169             p_pack->output_format.i_cat = VIDEO_ES
    170             break; 
     131            p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '1' ); 
     132            break
     133 
    171134        case VLC_FOURCC( 'd', 'i', 'v', '2' ): 
    172         case VLC_FOURCC( 'D', 'I', 'V', '2' ): 
    173135        case VLC_FOURCC( 'M', 'P', '4', '2' ): 
    174136        case VLC_FOURCC( 'm', 'p', '4', '2' ): 
    175             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '2' ); 
    176             p_pack->output_format.i_cat = VIDEO_ES
    177             break; 
     137            p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '2' ); 
     138            break
     139 
    178140        case VLC_FOURCC( 'd', 'i', 'v', '3' ): 
    179         case VLC_FOURCC( 'D', 'I', 'V', '3' ): 
    180141        case VLC_FOURCC( 'd', 'i', 'v', '4' ): 
    181142        case VLC_FOURCC( 'D', 'I', 'V', '4' ): 
     
    189150        case VLC_FOURCC( 'M', 'P', 'G', '3' ): 
    190151        case VLC_FOURCC( 'A', 'P', '4', '1' ): 
    191             p_pack->output_format.i_fourcc = VLC_FOURCC( 'D', 'I', 'V', '3' ); 
    192             p_pack->output_format.i_cat = VIDEO_ES; 
    193             break; 
    194         case VLC_FOURCC( 'H', '2', '6', '3' ): 
     152            p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' ); 
     153            break; 
     154 
    195155        case VLC_FOURCC( 'h', '2', '6', '3' ): 
    196156        case VLC_FOURCC( 'U', '2', '6', '3' ): 
    197157        case VLC_FOURCC( 'u', '2', '6', '3' ): 
    198             p_pack->output_format.i_fourcc = VLC_FOURCC( 'H', '2', '6', '3' ); 
    199             p_pack->output_format.i_cat = VIDEO_ES; 
    200             break; 
    201         case VLC_FOURCC( 'I', '2', '6', '3' ): 
     158            p_dec->fmt_out.i_codec = VLC_FOURCC( 'H', '2', '6', '3' ); 
     159            break; 
     160 
    202161        case VLC_FOURCC( 'i', '2', '6', '3' ): 
    203             p_pack->output_format.i_fourcc = VLC_FOURCC( 'I', '2', '6', '3' ); 
    204             p_pack->output_format.i_cat = VIDEO_ES; 
    205             break; 
    206         case VLC_FOURCC( 'W', 'M', 'V', '1' ): 
    207             p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '1' ); 
    208             p_pack->output_format.i_cat = VIDEO_ES; 
    209             break; 
    210         case VLC_FOURCC( 'W', 'M', 'V', '2' ): 
    211             p_pack->output_format.i_fourcc = VLC_FOURCC( 'W', 'M', 'V', '2' ); 
    212             p_pack->output_format.i_cat = VIDEO_ES; 
    213             break; 
    214         case VLC_FOURCC( 'M', 'J', 'P', 'G' ): 
     162            p_dec->fmt_out.i_codec = VLC_FOURCC( 'I', '2', '6', '3' ); 
     163            break; 
     164 
    215165        case VLC_FOURCC( 'm', 'j', 'p', 'g' ): 
    216166        case VLC_FOURCC( 'm', 'j', 'p', 'a' ): 
     
    218168        case VLC_FOURCC( 'J', 'P', 'E', 'G' ): 
    219169        case VLC_FOURCC( 'J', 'F', 'I', 'F' ): 
    220             p_pack->output_format.i_fourcc = VLC_FOURCC( 'M', 'J', 'P', 'G' ); 
    221             p_pack->output_format.i_cat = VIDEO_ES; 
    222             break; 
    223         case VLC_FOURCC( 'm', 'j', 'p', 'b' ): 
    224             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'j', 'p', 'b' ); 
    225             p_pack->output_format.i_cat = VIDEO_ES; 
    226             break; 
    227         case VLC_FOURCC( 'd', 'v', 's', 'l' ): 
     170            p_dec->fmt_out.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' ); 
     171            break; 
     172 
    228173        case VLC_FOURCC( 'd', 'v', 's', 'd' ): 
    229174        case VLC_FOURCC( 'D', 'V', 'S', 'D' ): 
    230175        case VLC_FOURCC( 'd', 'v', 'h', 'd' ): 
    231             p_pack->output_format.i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' ); 
    232             p_pack->output_format.i_cat = VIDEO_ES; 
    233             break; 
    234         case VLC_FOURCC( 'S', 'V', 'Q', '1' ): 
    235             p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '1' ); 
    236             p_pack->output_format.i_cat = VIDEO_ES; 
    237             break; 
    238         case VLC_FOURCC( 'S', 'V', 'Q', '3' ): 
    239             p_pack->output_format.i_fourcc = VLC_FOURCC( 'S', 'V', 'Q', '3' ); 
    240             p_pack->output_format.i_cat = VIDEO_ES; 
     176            p_dec->fmt_out.i_codec = VLC_FOURCC( 'd', 'v', 's', 'l' ); 
    241177            break; 
    242178 
    243179        /* audio */ 
    244         case VLC_FOURCC( 'm', 'p', 'g', 'a' ): 
    245             p_pack->output_format.i_fourcc = VLC_FOURCC( 'm', 'p', 'g', 'a' ); 
    246             p_pack->output_format.i_cat = AUDIO_ES; 
    247             break; 
    248         case VLC_FOURCC( 'w', 'm', 'a', '1' ): 
    249             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '1' ); 
    250             p_pack->output_format.i_cat = AUDIO_ES; 
    251             break; 
    252         case VLC_FOURCC( 'w', 'm', 'a', '2' ): 
    253             p_pack->output_format.i_fourcc = VLC_FOURCC( 'w', 'm', 'a', '2' ); 
    254             p_pack->output_format.i_cat = AUDIO_ES; 
    255             break; 
    256180        case VLC_FOURCC( 'a', 'r', 'a', 'w' ): 
     181            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) 
     182            { 
     183                case 1: 
     184                    p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' '); 
     185                    break; 
     186                case 2: 
     187                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); 
     188                    break; 
     189                case 3: 
     190                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); 
     191                    break; 
     192                case 4: 
     193                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); 
     194                    break; 
     195                default: 
     196                    msg_Err( p_dec, "unknown raw audio sample size !!" ); 
     197                    return VLC_EGENERIC; 
     198            } 
     199            break; 
     200 
     201        case VLC_FOURCC( 't', 'w', 'o', 's' ): 
     202            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) 
     203            { 
     204                case 1: 
     205                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); 
     206                    break; 
     207                case 2: 
     208                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b'); 
     209                    break; 
     210                case 3: 
     211                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b'); 
     212                    break; 
     213                case 4: 
     214                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b'); 
     215                    break; 
     216                default: 
     217                    msg_Err( p_dec, "unknown raw audio sample size !!" ); 
     218                    return VLC_EGENERIC; 
     219            } 
     220            break; 
     221 
     222        case VLC_FOURCC( 's', 'o', 'w', 't' ): 
     223            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) 
     224            { 
     225                case 1: 
     226                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); 
     227                    break; 
     228                case 2: 
     229                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); 
     230                    break; 
     231                case 3: 
     232                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); 
     233                    break; 
     234                case 4: 
     235                    p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); 
     236                    break; 
     237                default: 
     238                    msg_Err( p_dec, "unknown raw audio sample size !!" ); 
     239                    return VLC_EGENERIC; 
     240            } 
     241            break; 
     242 
     243        /* subtitles */ 
     244        case VLC_FOURCC( 's', 'p', 'u', 'b' ): 
     245            p_dec->fmt_out.i_codec = VLC_FOURCC( 's', 'p', 'u', ' ' ); 
     246            break; 
     247    } 
     248 
     249    p_dec->p_sys = p_sys = malloc( sizeof( block_t ) ); 
     250    p_sys->i_spu_size = 0; 
     251    p_sys->i_spu      = 0; 
     252    p_sys->p_block    = NULL; 
     253 
     254    return VLC_SUCCESS; 
     255} 
     256 
     257/***************************************************************************** 
     258 * Close: 
     259 *****************************************************************************/ 
     260static void Close( vlc_object_t *p_this ) 
     261{ 
     262    decoder_t     *p_dec = (decoder_t*)p_this; 
     263 
     264    if( p_dec->p_sys->p_block ) 
     265    { 
     266        block_ChainRelease( p_dec->p_sys->p_block ); 
     267    } 
     268 
     269    free( p_dec->p_sys ); 
     270} 
     271 
     272/***************************************************************************** 
     273 * PacketizeStd: packetize an unit (here copy a complete block ) 
     274 *****************************************************************************/ 
     275static block_t *PacketizeAV ( decoder_t *p_dec, block_t **pp_block ) 
     276{ 
     277    block_t *p_block; 
     278    block_t *p_ret = p_dec->p_sys->p_block; 
     279 
     280    if( pp_block == NULL || *pp_block == NULL ) 
     281    { 
     282        return NULL; 
     283    } 
     284    p_block = *pp_block; 
     285    *pp_block = NULL; 
     286 
     287    if( p_block->i_pts <= 0 ) 
     288    { 
     289        msg_Dbg( p_dec, "need pts > 0" ); 
     290        block_Release( p_block ); 
     291        return NULL; 
     292    } 
     293 
     294    if( p_ret != NULL && p_block->i_pts > p_ret->i_pts ) 
     295    { 
     296        p_ret->i_length = p_block->i_pts - p_ret->i_pts; 
     297    } 
     298    p_dec->p_sys->p_block = p_block; 
     299 
     300    return p_ret; 
     301} 
     302 
     303/***************************************************************************** 
     304 * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle) 
     305 *****************************************************************************/ 
     306static block_t *PacketizeSPU( decoder_t *p_dec, block_t **pp_block ) 
     307{ 
     308    decoder_sys_t *p_sys = p_dec->p_sys; 
     309    block_t *p_block; 
     310 
     311    if( pp_block == NULL || *pp_block == NULL ) 
     312    { 
     313        return NULL; 
     314    } 
     315    p_block = *pp_block; 
     316    *pp_block = NULL; 
     317 
     318    if( p_sys->i_spu_size <= 0 && 
     319        ( p_block->i_pts <= 0 || p_block->i_buffer < 4 ) ) 
     320    { 
     321        msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" ); 
     322        block_Release( p_block ); 
     323        return NULL; 
     324    } 
     325 
     326    block_ChainAppend( &p_sys->p_block, p_block ); 
     327    p_sys->i_spu += p_block->i_buffer; 
     328 
     329    if( p_sys->i_spu_size <= 0 ) 
     330    { 
     331        int i_rle = ( ( p_block->p_buffer[2] << 8 )| p_block->p_buffer[3] ) - 4; 
     332 
     333        p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )| p_block->p_buffer[1]; 
     334 
     335        msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d", p_sys->i_spu_size, i_rle ); 
     336 
     337        if( p_sys->i_spu_size <= 0 || i_rle >= p_sys->i_spu_size ) 
    257338        { 
    258             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; 
    259             if( p_wf ) 
    260             { 
    261                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) 
    262                 { 
    263                     case 1: 
    264                         p_pack->output_format.i_fourcc = VLC_FOURCC('u','8',' ',' '); 
    265                         break; 
    266                     case 2: 
    267                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l'); 
    268                         break; 
    269                     case 3: 
    270                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l'); 
    271                         break; 
    272                     case 4: 
    273                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l'); 
    274                         break; 
    275                     default: 
    276                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    277                         return VLC_EGENERIC; 
    278                 } 
    279             } 
    280             else 
    281             { 
    282                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    283                 return VLC_EGENERIC; 
    284             } 
    285             p_pack->output_format.i_cat = AUDIO_ES; 
    286             break; 
     339            p_sys->i_spu_size = 0; 
     340            p_sys->i_spu      = 0; 
     341            p_sys->p_block    = NULL; 
     342 
     343            block_Release( p_block ); 
     344            return NULL; 
    287345        } 
    288         case VLC_FOURCC( 't', 'w', 'o', 's' ): 
    289         { 
    290             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; 
    291             if( p_wf ) 
    292             { 
    293                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) 
    294                 { 
    295                     case 1: 
    296                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' '); 
    297                         break; 
    298                     case 2: 
    299                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','b'); 
    300                         break; 
    301                     case 3: 
    302                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','b'); 
    303                         break; 
    304                     case 4: 
    305                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','b'); 
    306                         break; 
    307                     default: 
    308                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    309                         return VLC_EGENERIC; 
    310                 } 
    311             } 
    312             else 
    313             { 
    314                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    315                 return VLC_EGENERIC; 
    316             } 
    317             p_pack->output_format.i_cat = AUDIO_ES; 
    318             break; 
    319         } 
    320         case VLC_FOURCC( 's', 'o', 'w', 't' ): 
    321         { 
    322             WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; 
    323             if( p_wf ) 
    324             { 
    325                 switch( ( p_wf->wBitsPerSample + 7 ) / 8 ) 
    326                 { 
    327                     case 1: 
    328                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','8',' ',' '); 
    329                         break; 
    330                     case 2: 
    331                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','1','6','l'); 
    332                         break; 
    333                     case 3: 
    334                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','2','4','l'); 
    335                         break; 
    336                     case 4: 
    337                         p_pack->output_format.i_fourcc = VLC_FOURCC('s','3','2','l'); 
    338                         break; 
    339                     default: 
    340                         msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    341                         return VLC_EGENERIC; 
    342                 } 
    343             } 
    344             else 
    345             { 
    346                 msg_Err( p_pack->p_fifo, "unknown raw audio sample size !!" ); 
    347                 return VLC_EGENERIC; 
    348             } 
    349             p_pack->output_format.i_cat = AUDIO_ES; 
    350             break; 
    351         } 
    352  
    353         /* subtitles */ 
    354         case VLC_FOURCC( 's', 'p', 'u', ' ' ):  /* DVD */ 
    355         case VLC_FOURCC( 's', 'p', 'u', 'b' ): 
    356             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'p', 'u', ' ' ); 
    357             p_pack->output_format.i_cat = SPU_ES; 
    358             p_pack->pf_packetize = PacketizeSPU; 
    359             break; 
    360  
    361         case VLC_FOURCC( 's', 'u', 'b', 't' ): 
    362             p_pack->output_format.i_fourcc = VLC_FOURCC( 's', 'u', 'b', 't' ); 
    363             p_pack->output_format.i_cat = SPU_ES; 
    364             break; 
    365  
    366         default: 
    367             msg_Err( p_pack->p_fifo, "unknown es type !!" ); 
    368             return VLC_EGENERIC; 
    369     } 
    370  
    371     switch( p_pack->output_format.i_cat ) 
    372     { 
    373         case AUDIO_ES: 
    374             { 
    375                 WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_pack->p_fifo->p_waveformatex; 
    376                 if( p_wf ) 
    377                 { 
    378                     p_pack->output_format.i_sample_rate = p_wf->nSamplesPerSec; 
    379                     p_pack->output_format.i_channels    = p_wf->nChannels; 
    380                     p_pack->output_format.i_block_align = p_wf->nBlockAlign; 
    381                     p_pack->output_format.i_bitrate     = p_wf->nAvgBytesPerSec * 8; 
    382                     p_pack->output_format.i_extra_data  = p_wf->cbSize; 
    383                     if( p_wf->cbSize  > 0 ) 
    384                     { 
    385                         p_pack->output_format.p_extra_data = 
    386                             malloc( p_pack->output_format.i_extra_data ); 
    387                         memcpy( p_pack->output_format.p_extra_data, 
    388                                 &p_wf[1], 
    389                                 p_pack->output_format.i_extra_data ); 
    390                     } 
    391                     else 
    392                     { 
    393                         p_pack->output_format.p_extra_data = NULL; 
    394                     } 
    395                 } 
    396                 else 
    397                 { 
    398                     p_pack->output_format.i_sample_rate = 0; 
    399                     p_pack->output_format.i_channels    = 0; 
    400                     p_pack->output_format.i_block_align = 0; 
    401                     p_pack->output_format.i_bitrate     = 0; 
    402                     p_pack->output_format.i_extra_data  = 0; 
    403                     p_pack->output_format.p_extra_data  = NULL; 
    404                 } 
    405             } 
    406             break; 
    407  
    408         case VIDEO_ES: 
    409             { 
    410                 BITMAPINFOHEADER *p_bih = (BITMAPINFOHEADER*)p_pack->p_fifo->p_bitmapinfoheader; 
    411  
    412                 p_pack->output_format.i_bitrate = 0; 
    413                 if( p_bih ) 
    414                 { 
    415                     p_pack->output_format.i_width  = p_bih->biWidth; 
    416                     p_pack->output_format.i_height = p_bih->biHeight; 
    417                     p_pack->output_format.i_extra_data  = p_bih->biSize - sizeof( BITMAPINFOHEADER ); 
    418                     if( p_pack->output_format.i_extra_data > 0 ) 
    419                     { 
    420                         p_pack->output_format.p_extra_data = 
    421                             malloc( p_pack->output_format.i_extra_data ); 
    422                         memcpy( p_pack->output_format.p_extra_data, 
    423                                 &p_bih[1], 
    424                                 p_pack->output_format.i_extra_data ); 
    425                     } 
    426                 } 
    427                 else 
    428                 { 
    429                     p_pack->output_format.i_width  = 0; 
    430                     p_pack->output_format.i_height = 0; 
    431                     p_pack->output_format.i_extra_data  = 0; 
    432                     p_pack->output_format.p_extra_data  = NULL; 
    433                 } 
    434             } 
    435             break; 
    436  
    437         case SPU_ES: 
    438             p_pack->output_format.i_extra_data  = 0; 
    439             p_pack->output_format.p_extra_data  = NULL; 
    440             break; 
    441  
    442         default: 
    443             return VLC_EGENERIC; 
    444     } 
    445  
    446     p_pack->p_sout_input = 
    447         sout_InputNew( p_pack->p_fifo, 
    448                        &p_pack->output_format ); 
    449  
    450     if( !p_pack->p_sout_input ) 
    451     { 
    452         msg_Err( p_pack->p_fifo, "cannot add a new stream" ); 
    453         return VLC_EGENERIC; 
    454     } 
    455  
    456     return( VLC_SUCCESS ); 
     346    } 
     347 
     348    if( p_sys->i_spu >= p_sys->i_spu_size ) 
     349    { 
     350        /* We have a complete sub */ 
     351        block_t *p_ret = p_sys->p_block; 
     352 
     353        msg_Dbg( p_dec, "SPU packets size=%d should be %d", 
     354                 p_sys->i_spu, p_sys->i_spu_size ); 
     355 
     356        p_sys->i_spu_size = 0; 
     357        p_sys->i_spu      = 0; 
     358        p_sys->p_block    = NULL; 
     359        return p_ret; 
     360    } 
     361    return NULL; 
    457362} 
    458363 
    459 /***************************************************************************** 
    460  * PacketizeStd: packetize an unit (here copy a complete pes) 
    461  *****************************************************************************/ 
    462 static void PacketizeStd( packetizer_thread_t *p_pack ) 
    463 { 
    464     sout_buffer_t   *p_out = NULL; 
    465     pes_packet_t    *p_pes; 
    466  
    467     input_ExtractPES( p_pack->p_fifo, &p_pes ); 
    468     if( !p_pes ) 
    469     { 
    470         p_pack->p_fifo->b_error = 1; 
    471         return; 
    472     } 
    473 #if 0 
    474     msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd, 
    475              p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts ); 
    476 #endif 
    477  
    478     if( p_pes->i_pts <= 0 ) 
    479     { 
    480         msg_Dbg( p_pack->p_fifo, "need pts != 0" ); 
    481         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); 
    482         return; 
    483     } 
    484  
    485     if( p_pes->i_pes_size > 0 ) 
    486     { 
    487         pes_packet_t    *p_next; 
    488  
    489         AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes ); 
    490  
    491         input_ShowPES( p_pack->p_fifo, &p_next ); 
    492         if( p_next && p_next->i_pts > 0 ) 
    493         { 
    494             p_out->i_length = p_next->i_pts - p_pes->i_pts; 
    495         } 
    496  
    497         sout_InputSendBuffer( p_pack->p_sout_input, 
    498                                p_out ); 
    499     } 
    500  
    501     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); 
    502 } 
    503  
    504 /***************************************************************************** 
    505  * PacketizeSPU: packetize an SPU unit (so gather all PES of one subtitle) 
    506  *****************************************************************************/ 
    507 static void PacketizeSPU( packetizer_thread_t *p_pack ) 
    508 { 
    509     sout_buffer_t   *p_out = NULL; 
    510     pes_packet_t    *p_pes; 
    511  
    512     int     i_spu_size = 0; 
    513  
    514     for( ;; ) 
    515     { 
    516         input_ExtractPES( p_pack->p_fifo, &p_pes ); 
    517         if( !p_pes ) 
    518         { 
    519             p_pack->p_fifo->b_error = 1; 
    520             return; 
    521         } 
    522 #if 0 
    523         msg_Dbg( p_pack->p_fifo, "pes size:%d dts="I64Fd" pts="I64Fd, 
    524                  p_pes->i_pes_size, p_pes->i_dts, p_pes->i_pts ); 
    525 #endif 
    526  
    527         if( p_out == NULL && 
    528             ( p_pes->i_pts <= 0 || p_pes->i_pes_size < 4 ) ) 
    529         { 
    530             msg_Dbg( p_pack->p_fifo, "invalid starting packet (size < 4 or pts <=0)" ); 
    531             input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); 
    532             return; 
    533         } 
    534  
    535         if( p_pes->i_pes_size > 0 ) 
    536         { 
    537             AppendPEStoSoutBuffer( p_pack->p_sout_input->p_sout, &p_out, p_pes ); 
    538  
    539             if( i_spu_size <= 0 ) 
    540             { 
    541                 int i_rle; 
    542                 i_spu_size = ( p_out->p_buffer[0] << 8 )| p_out->p_buffer[1]; 
    543                 i_rle      = ( ( p_out->p_buffer[2] << 8 )| p_out->p_buffer[3] ) - 4; 
    544  
    545                 msg_Dbg( p_pack->p_fifo, "i_spu_size=%d i_rle=%d", i_spu_size, i_rle ); 
    546                 if( i_spu_size == 0 || i_rle >= i_spu_size ) 
    547                 { 
    548                     sout_BufferDelete( p_pack->p_sout_input->p_sout, p_out ); 
    549                     input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); 
    550                     return; 
    551                 } 
    552             } 
    553         } 
    554  
    555         input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); 
    556  
    557         if( (int)p_out->i_size >= i_spu_size ) 
    558         { 
    559             break; 
    560         } 
    561     } 
    562     msg_Dbg( p_pack->p_fifo, 
    563              "SPU packets size=%d should be %d", 
    564              p_out->i_size, i_spu_size ); 
    565  
    566     sout_InputSendBuffer( p_pack->p_sout_input, p_out ); 
    567 } 
    568  
    569  
    570 /***************************************************************************** 
    571  * End : packetizer thread destruction 
    572  *****************************************************************************/ 
    573 static void End ( packetizer_thread_t *p_pack) 
    574 { 
    575     if( p_pack->p_sout_input ) 
    576     { 
    577         sout_InputDelete( p_pack->p_sout_input ); 
    578     } 
    579     free( p_pack ); 
    580 } 
    581  
    582 /***************************************************************************** 
    583  * AppendPEStoSoutBuffer: copy/cat one pes into a sout_buffer_t. 
    584  *****************************************************************************/ 
    585 static void AppendPEStoSoutBuffer( sout_instance_t *p_sout, 
    586                                    sout_buffer_t **pp_out, 
    587                                    pes_packet_t *p_pes ) 
    588 { 
    589     sout_buffer_t *p_out = *pp_out; 
    590     unsigned int  i_out; 
    591  
    592     data_packet_t   *p_data; 
    593  
    594     if( p_out == NULL ) 
    595     { 
    596         i_out = 0; 
    597         p_out = *pp_out = sout_BufferNew( p_sout, p_pes->i_pes_size ); 
    598         p_out->i_dts = p_pes->i_pts; 
    599         p_out->i_pts = p_pes->i_pts; 
    600     } 
    601     else 
    602     { 
    603         i_out = p_out->i_size; 
    604         sout_BufferRealloc( p_sout, p_out, i_out + p_pes->i_pes_size ); 
    605     } 
    606     p_out->i_size = i_out + p_pes->i_pes_size; 
    607  
    608     for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next) 
    609     { 
    610         int i_copy; 
    611  
    612         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start, 
    613                         p_out->i_size - i_out ); 
    614         if( i_copy > 0 ) 
    615         { 
    616             memcpy( &p_out->p_buffer[i_out], 
    617                     p_data->p_payload_start, 
    618                     i_copy ); 
    619         } 
    620         i_out += i_copy; 
    621     } 
    622     p_out->i_size = i_out; 
    623 } 
    624  
    625 /***************************************************************************** 
    626  * input_ShowPES: Show the next PES in the fifo 
    627  *****************************************************************************/ 
    628 static void input_ShowPES( decoder_fifo_t *p_fifo, pes_packet_t **pp_pes ) 
    629 { 
    630     vlc_mutex_lock( &p_fifo->data_lock ); 
    631  
    632     if( p_fifo->p_first == NULL ) 
    633     { 
    634         if( p_fifo->b_die ) 
    635         { 
    636             vlc_mutex_unlock( &p_fifo->data_lock ); 
    637             *pp_pes = NULL; 
    638             return; 
    639         } 
    640  
    641         /* Signal the input thread we're waiting. This is only 
    642          * needed in case of slave clock (ES plug-in) but it won't 
    643          * harm. */ 
    644         vlc_cond_signal( &p_fifo->data_wait ); 
    645  
    646         /* Wait for the input to tell us when we received a packet. */ 
    647         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock ); 
    648     } 
    649     *pp_pes = p_fifo->p_first; 
    650     vlc_mutex_unlock( &p_fifo->data_lock ); 
    651 }