Changeset 06ef387db9f271a96d600e423633018fe5c2fcd7

Show
Ignore:
Timestamp:
09/22/07 16:53:54 (10 months ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1190472834 +0000
git-parent:

[4112e0fd7e4c7cc33552fb0bf26e2a38470150f6]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1190472834 +0000
Message:

Support for decoding Speex from RTP - refs #1291
Patch by Williams Hawkins

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • THANKS

    rb184f95 r06ef387  
    207207Watanabe Go <go at dsl.gr.jp> - fix for non-ASCII filenames 
    208208Wei Mingzhi <whistler_wmz at users.sourceforge.net> - Simplied Chinese translation 
     209William Hawkins - Speex RTP payload format 
    209210Xavier Maillard <zedek at fxgsproject.org> - audio converters 
    210211Xavier Marchesini <xav at alarue.net> - Win32 fixes 
  • modules/codec/speex.c

    r593ef6c r06ef387  
    5959    SpeexStereoState stereo; 
    6060    void *p_state; 
     61    unsigned int rtp_rate; 
    6162 
    6263    /* 
     
    8687 
    8788static void *DecodeBlock  ( decoder_t *, block_t ** ); 
     89static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *, block_t **); 
    8890static int  ProcessHeaders( decoder_t * ); 
    8991static int  ProcessInitialHeader ( decoder_t *, ogg_packet * ); 
     
    129131    decoder_sys_t *p_sys = p_dec->p_sys; 
    130132 
    131     if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ') ) 
     133    if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ')  
     134        && p_dec->fmt_in.i_codec != VLC_FOURCC('s', 'p', 'x', 'r') ) 
    132135    { 
    133136        return VLC_EGENERIC; 
     
    141144        return VLC_EGENERIC; 
    142145    } 
     146    p_dec->p_sys->bits.buf_size = 0; 
    143147    p_dec->p_sys->b_packetizer = VLC_FALSE; 
     148    p_dec->p_sys->rtp_rate = p_dec->fmt_in.audio.i_rate; 
    144149 
    145150    aout_DateSet( &p_sys->end_date, 0 ); 
     
    149154    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; 
    150155 
    151     /* Set callbacks */ 
    152     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
    153         DecodeBlock; 
     156    /* 
     157      Set callbacks 
     158      If the codec is spxr then this decoder is  
     159      being invoked on a Speex stream arriving via RTP.  
     160      A special decoder callback is used. 
     161    */ 
     162    if (p_dec->fmt_in.i_codec == VLC_FOURCC('s', 'p', 'x', 'r')) 
     163    { 
     164        msg_Dbg( p_dec, "Using RTP version of Speex decoder @ rate %d.",  
     165        p_dec->fmt_in.audio.i_rate ); 
     166        p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
     167            DecodeRtpSpeexPacket; 
     168    } 
     169    else 
     170    { 
     171        p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
     172            DecodeBlock; 
     173    } 
    154174    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **)) 
    155175        DecodeBlock; 
     
    213233    if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra ) 
    214234    { 
    215         /* Headers already available as extra data */ 
    216235        p_sys->i_headers = 2; 
    217236    } 
    218237    else if( oggpacket.bytes && p_sys->i_headers < 2 ) 
    219238    { 
    220         /* Backup headers as extra data */ 
    221239        uint8_t *p_extra; 
    222240 
     
    419437 
    420438    /* Date management */ 
    421     if( p_block && p_block->i_pts > 0 && 
     439    if( p_block && p_block->i_pts > 0 &&  
    422440        p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) 
    423441    { 
     
    436454    if( p_sys->b_packetizer ) 
    437455    { 
    438          return SendPacket( p_dec, p_oggpacket, p_block ); 
     456    if ( p_sys->p_header->frames_per_packet > 1 ) 
     457    { 
     458        short *p_frame_holder = NULL; 
     459        int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0, 
     460            i_pcm_output_size = 0, i_bits_in_speex_frame = 0; 
     461        block_t *p_new_block = NULL; 
     462 
     463        i_pcm_output_size = p_sys->p_header->frame_size; 
     464        p_frame_holder = (short*)malloc( sizeof(short)*i_pcm_output_size ); 
     465 
     466            speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet, 
     467            p_oggpacket->bytes); 
     468            i_bits_before = speex_bits_remaining( &p_sys->bits ); 
     469        speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder); 
     470        i_bits_after = speex_bits_remaining( &p_sys->bits ); 
     471 
     472            i_bits_in_speex_frame = i_bits_before - i_bits_after; 
     473        i_bytes_in_speex_frame = ( i_bits_in_speex_frame +  
     474            (8 - (i_bits_in_speex_frame % 8)) ) 
     475                / 8; 
     476 
     477            p_new_block = block_New( p_dec, i_bytes_in_speex_frame ); 
     478        memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame ); 
     479 
     480        /* 
     481         * Copy the first frame in this packet to a new packet. 
     482         */ 
     483        speex_bits_rewind( &p_sys->bits ); 
     484        speex_bits_write( &p_sys->bits,  
     485            p_new_block->p_buffer,  
     486        i_bytes_in_speex_frame ); 
     487 
     488        /* 
     489         * Move the remaining part of the original packet (subsequent 
     490         * frames, if there are any) into the beginning  
     491         * of the original packet so 
     492         * they are preserved following the realloc.  
     493         * Note: Any bits that 
     494         * remain in the initial packet 
     495         * are "filler" if they do not constitute 
     496         * an entire byte.  
     497         */ 
     498        if ( i_bits_after > 7 ) 
     499        { 
     500            /* round-down since we rounded-up earlier (to include 
     501         * the speex terminator code.  
     502         */ 
     503            i_bytes_in_speex_frame--; 
     504            speex_bits_write( &p_sys->bits,  
     505            p_block->p_buffer,  
     506            p_block->i_buffer - i_bytes_in_speex_frame ); 
     507                p_block = block_Realloc( p_block,  
     508                0,  
     509            p_block->i_buffer-i_bytes_in_speex_frame ); 
     510            *pp_block = p_block; 
     511        } 
     512        else 
     513        { 
     514            speex_bits_reset( &p_sys->bits ); 
     515        } 
     516 
     517        free( p_frame_holder ); 
     518        return SendPacket( p_dec, p_oggpacket /*Not used*/, p_new_block); 
     519    } 
     520    else 
     521    { 
     522            return SendPacket( p_dec, p_oggpacket, p_block ); 
     523    } 
    439524    } 
    440525    else 
     
    450535        return p_aout_buffer; 
    451536    } 
     537} 
     538 
     539static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block ) 
     540{ 
     541    block_t *p_speex_bit_block = *pp_block; 
     542    decoder_sys_t *p_sys = p_dec->p_sys; 
     543    aout_buffer_t *p_aout_buffer; 
     544    int i_decode_ret; 
     545    unsigned int i_speex_frame_size; 
     546 
     547    if ( !p_speex_bit_block || p_speex_bit_block->i_pts == 0 ) return NULL; 
     548 
     549    /*  
     550      If the SpeexBits buffer size is 0 (a default value), 
     551      we know that a proper initialization has not yet been done. 
     552    */ 
     553    if ( p_sys->bits.buf_size==0 ) 
     554    { 
     555    p_sys->p_header = (SpeexHeader *)malloc(sizeof(SpeexHeader)); 
     556    if ( !p_sys->p_header ) 
     557    { 
     558        msg_Err( p_dec, "Could not allocate a Speex header."); 
     559        return NULL; 
     560    } 
     561    speex_init_header( p_sys->p_header,p_sys->rtp_rate,1,&speex_nb_mode ); 
     562        speex_bits_init( &p_sys->bits ); 
     563    p_sys->p_state = speex_decoder_init( &speex_nb_mode ); 
     564    if ( !p_sys->p_state ) 
     565    { 
     566        msg_Err( p_dec, "Could not allocate a Speex decoder." ); 
     567        free( p_sys->p_header ); 
     568        return NULL; 
     569    } 
     570 
     571        /* 
     572      Assume that variable bit rate is enabled. Also assume 
     573      that there is only one frame per packet.  
     574    */ 
     575    p_sys->p_header->vbr = 1; 
     576    p_sys->p_header->frames_per_packet = 1; 
     577 
     578        p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels; 
     579    p_dec->fmt_out.audio.i_physical_channels =  
     580    p_dec->fmt_out.audio.i_original_channels =  
     581        pi_channels_maps[p_sys->p_header->nb_channels]; 
     582        p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate; 
     583 
     584        if ( speex_mode_query( &speex_nb_mode,  
     585        SPEEX_MODE_FRAME_SIZE,  
     586        &i_speex_frame_size ) ) 
     587    { 
     588        msg_Err( p_dec, "Could not determine the frame size." ); 
     589        speex_decoder_destroy( p_sys->p_state ); 
     590        free( p_sys->p_header ); 
     591        return NULL; 
     592    } 
     593    p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size; 
     594 
     595    aout_DateInit(&p_sys->end_date, p_sys->p_header->rate); 
     596    } 
     597 
     598    /*  
     599      If the SpeexBits are initialized but there is  
     600      still no header, an error must be thrown. 
     601    */ 
     602    if ( !p_sys->p_header ) 
     603    { 
     604        msg_Err( p_dec, "There is no valid Speex header found." ); 
     605    return NULL; 
     606    } 
     607    *pp_block = NULL; 
     608 
     609    if ( !aout_DateGet( &p_sys->end_date ) ) 
     610        aout_DateSet( &p_sys->end_date, p_speex_bit_block->i_dts ); 
     611 
     612    /* 
     613      Ask for a new audio output buffer and make sure 
     614      we get one.  
     615    */ 
     616    p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec,  
     617        p_sys->p_header->frame_size ); 
     618    if ( !p_aout_buffer || p_aout_buffer->i_nb_bytes == 0 ) 
     619    { 
     620        msg_Err(p_dec, "Oops: No new buffer was returned!"); 
     621    return NULL; 
     622    } 
     623 
     624    /* 
     625      Read the Speex payload into the SpeexBits buffer. 
     626    */ 
     627    speex_bits_read_from( &p_sys->bits,  
     628        (char*)p_speex_bit_block->p_buffer,  
     629        p_speex_bit_block->i_buffer ); 
     630     
     631    /*  
     632      Decode the input and ensure that no errors  
     633      were encountered. 
     634    */ 
     635    i_decode_ret =  
     636        speex_decode_int( p_sys->p_state,&p_sys->bits,p_aout_buffer->p_buffer ); 
     637    if ( i_decode_ret < 0 ) 
     638    { 
     639        msg_Err( p_dec, "Decoding failed. Perhaps we have a bad stream?" ); 
     640    return NULL; 
     641    } 
     642 
     643    /*  
     644      Handle date management on the audio output buffer.  
     645    */ 
     646    p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); 
     647    p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,  
     648        p_sys->p_header->frame_size ); 
     649     
     650     
     651    p_sys->i_frame_in_packet++; 
     652    block_Release( p_speex_bit_block ); 
     653 
     654    return p_aout_buffer; 
    452655} 
    453656 
     
    485688        { 
    486689            case -2: 
    487                 msg_Warn( p_dec, "decoding error: corrupted stream?" ); 
     690                msg_Err( p_dec, "decoding error: corrupted stream?" ); 
    488691            case -1: /* End of stream */ 
    489692                return NULL; 
     
    492695        if( speex_bits_remaining( &p_sys->bits ) < 0 ) 
    493696        { 
    494             msg_Warn( p_dec, "decoding overflow: corrupted stream?" ); 
     697            msg_Err( p_dec, "decoding overflow: corrupted stream?" ); 
    495698        } 
    496699 
     
    503706        p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); 
    504707        p_aout_buffer->end_date = 
    505             aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size); 
     708            aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size ); 
    506709 
    507710        p_sys->i_frame_in_packet++; 
     
    527730 
    528731    if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 ) 
     732    { 
    529733        p_block->i_length = 
    530734            aout_DateIncrement( &p_sys->end_date, 
    531735                                p_sys->p_header->frame_size ) - 
    532736            p_block->i_pts; 
     737    } 
    533738    else 
    534739        p_block->i_length = 0; 
     
    567772    if( p_oggpacket->bytes < 8 ) 
    568773    { 
    569         msg_Warn( p_dec, "invalid/corrupted comments" ); 
     774        msg_Err( p_dec, "invalid/corrupted comments" ); 
    570775        return; 
    571776    } 
     
    574779    if( i_len > p_oggpacket->bytes - 4 ) 
    575780    { 
    576         msg_Warn( p_dec, "invalid/corrupted comments" ); 
     781        msg_Err( p_dec, "invalid/corrupted comments" ); 
    577782        return; 
    578783    }