Ticket #1291: speex.c.patch

File speex.c.patch, 10.8 kB (added by hawkinsw, 1 year ago)
  • vlc-0.9.0-svn-spx/modules/codec/speex.c

    old new  
    5656    SpeexHeader *p_header; 
    5757    SpeexStereoState stereo; 
    5858    void *p_state; 
     59    unsigned int rtp_rate; 
    5960 
    6061    /* 
    6162     * Common properties 
     
    8384static void CloseDecoder  ( vlc_object_t * ); 
    8485 
    8586static void *DecodeBlock  ( decoder_t *, block_t ** ); 
     87static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *, block_t **); 
    8688static int  ProcessHeaders( decoder_t * ); 
    8789static int  ProcessInitialHeader ( decoder_t *, ogg_packet * ); 
    8890static void *ProcessPacket( decoder_t *, ogg_packet *, block_t ** ); 
     
    126128    decoder_t *p_dec = (decoder_t*)p_this; 
    127129    decoder_sys_t *p_sys = p_dec->p_sys; 
    128130 
    129     if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ') ) 
     131    if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ')  
     132        && p_dec->fmt_in.i_codec != VLC_FOURCC('s', 'p', 'x', 'r') ) 
    130133    { 
    131134        return VLC_EGENERIC; 
    132135    } 
     
    138141        msg_Err( p_dec, "out of memory" ); 
    139142        return VLC_EGENERIC; 
    140143    } 
     144    p_dec->p_sys->bits.buf_size = 0; 
    141145    p_dec->p_sys->b_packetizer = VLC_FALSE; 
     146    p_dec->p_sys->rtp_rate = p_dec->fmt_in.audio.i_rate; 
    142147 
    143148    aout_DateSet( &p_sys->end_date, 0 ); 
    144149 
     
    146151    p_dec->fmt_out.i_cat = AUDIO_ES; 
    147152    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE; 
    148153 
    149     /* Set callbacks */ 
    150     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
    151         DecodeBlock; 
     154    /* 
     155      Set callbacks 
     156      If the codec is spxr then this decoder is  
     157      being invoked on a Speex stream arriving via RTP.  
     158      A special decoder callback is used. 
     159    */ 
     160    if (p_dec->fmt_in.i_codec == VLC_FOURCC('s', 'p', 'x', 'r')) 
     161    { 
     162        msg_Dbg( p_dec, "Using RTP version of Speex decoder @ rate %d.",  
     163            p_dec->fmt_in.audio.i_rate ); 
     164        p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
     165            DecodeRtpSpeexPacket; 
     166    } 
     167    else 
     168    { 
     169        p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) 
     170            DecodeBlock; 
     171    } 
    152172    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **)) 
    153173        DecodeBlock; 
    154174 
     
    210230    /* Check for headers */ 
    211231    if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra ) 
    212232    { 
    213         /* Headers already available as extra data */ 
    214233        p_sys->i_headers = 2; 
    215234    } 
    216235    else if( oggpacket.bytes && p_sys->i_headers < 2 ) 
    217236    { 
    218         /* Backup headers as extra data */ 
    219237        uint8_t *p_extra; 
    220238 
    221239        p_dec->fmt_in.p_extra = 
     
    414432    block_t *p_block = *pp_block; 
    415433 
    416434    /* Date management */ 
    417     if( p_block && p_block->i_pts > 0 && 
     435    if( p_block && p_block->i_pts > 0 &&  
    418436        p_block->i_pts != aout_DateGet( &p_sys->end_date ) ) 
    419437    { 
    420438        aout_DateSet( &p_sys->end_date, p_block->i_pts ); 
     
    431449 
    432450    if( p_sys->b_packetizer ) 
    433451    { 
    434          return SendPacket( p_dec, p_oggpacket, p_block ); 
     452        if ( p_sys->p_header->frames_per_packet > 1 ) 
     453        { 
     454            short *p_frame_holder = NULL; 
     455            int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0, 
     456                i_pcm_output_size = 0, i_bits_in_speex_frame = 0; 
     457            block_t *p_new_block = NULL; 
     458 
     459            i_pcm_output_size = p_sys->p_header->frame_size; 
     460            p_frame_holder = (short*)malloc( sizeof(short)*i_pcm_output_size ); 
     461 
     462            speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet, 
     463                p_oggpacket->bytes); 
     464            i_bits_before = speex_bits_remaining( &p_sys->bits ); 
     465            speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder); 
     466            i_bits_after = speex_bits_remaining( &p_sys->bits ); 
     467 
     468            i_bits_in_speex_frame = i_bits_before - i_bits_after; 
     469            i_bytes_in_speex_frame = ( i_bits_in_speex_frame +  
     470                (8 - (i_bits_in_speex_frame % 8)) ) 
     471                / 8; 
     472 
     473            p_new_block = block_New( p_dec, i_bytes_in_speex_frame ); 
     474            memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame ); 
     475 
     476            /* 
     477             * Copy the first frame in this packet to a new packet. 
     478             */ 
     479            speex_bits_rewind( &p_sys->bits ); 
     480            speex_bits_write( &p_sys->bits,  
     481                p_new_block->p_buffer,  
     482                i_bytes_in_speex_frame ); 
     483 
     484            /* 
     485             * Move the remaining part of the original packet (subsequent 
     486             * frames, if there are any) into the beginning  
     487             * of the original packet so 
     488             * they are preserved following the realloc.  
     489             * Note: Any bits that 
     490             * remain in the initial packet 
     491             * are "filler" if they do not constitute 
     492             * an entire byte.  
     493             */ 
     494            if ( i_bits_after > 7 ) 
     495            { 
     496                /* round-down since we rounded-up earlier (to include 
     497                 * the speex terminator code.  
     498                 */ 
     499                i_bytes_in_speex_frame--; 
     500                speex_bits_write( &p_sys->bits,  
     501                    p_block->p_buffer,  
     502                    p_block->i_buffer - i_bytes_in_speex_frame ); 
     503                p_block = block_Realloc( p_block,  
     504                    0,  
     505                    p_block->i_buffer-i_bytes_in_speex_frame ); 
     506                *pp_block = p_block; 
     507            } 
     508            else 
     509            { 
     510                speex_bits_reset( &p_sys->bits ); 
     511            } 
     512 
     513            free( p_frame_holder ); 
     514            return SendPacket( p_dec, p_oggpacket /*Not used*/, p_new_block); 
     515        } 
     516        else 
     517        { 
     518            return SendPacket( p_dec, p_oggpacket, p_block ); 
     519        } 
    435520    } 
    436521    else 
    437522    { 
     
    447532    } 
    448533} 
    449534 
     535static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block ) 
     536{ 
     537    block_t *p_speex_bit_block = *pp_block; 
     538    decoder_sys_t *p_sys = p_dec->p_sys; 
     539    aout_buffer_t *p_aout_buffer; 
     540    int i_decode_ret; 
     541    unsigned int i_speex_frame_size; 
     542 
     543    if ( !p_speex_bit_block || p_speex_bit_block->i_pts == 0 ) return NULL; 
     544 
     545    /*  
     546      If the SpeexBits buffer size is 0 (a default value), 
     547      we know that a proper initialization has not yet been done. 
     548    */ 
     549    if ( p_sys->bits.buf_size==0 ) 
     550    { 
     551        p_sys->p_header = (SpeexHeader *)malloc(sizeof(SpeexHeader)); 
     552        if ( !p_sys->p_header ) 
     553        { 
     554            msg_Err( p_dec, "Could not allocate a Speex header."); 
     555            return NULL; 
     556        } 
     557        speex_init_header( p_sys->p_header,p_sys->rtp_rate,1,&speex_nb_mode ); 
     558        speex_bits_init( &p_sys->bits ); 
     559        p_sys->p_state = speex_decoder_init( &speex_nb_mode ); 
     560        if ( !p_sys->p_state ) 
     561        { 
     562            msg_Err( p_dec, "Could not allocate a Speex decoder." ); 
     563            free( p_sys->p_header ); 
     564            return NULL; 
     565        } 
     566 
     567        /* 
     568          Assume that variable bit rate is enabled. Also assume 
     569          that there is only one frame per packet.  
     570        */ 
     571        p_sys->p_header->vbr = 1; 
     572        p_sys->p_header->frames_per_packet = 1; 
     573 
     574        p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels; 
     575        p_dec->fmt_out.audio.i_physical_channels =  
     576        p_dec->fmt_out.audio.i_original_channels =  
     577            pi_channels_maps[p_sys->p_header->nb_channels]; 
     578        p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate; 
     579 
     580        if ( speex_mode_query( &speex_nb_mode,  
     581            SPEEX_MODE_FRAME_SIZE,  
     582            &i_speex_frame_size ) ) 
     583        { 
     584            msg_Err( p_dec, "Could not determine the frame size." ); 
     585            speex_decoder_destroy( p_sys->p_state ); 
     586            free( p_sys->p_header ); 
     587            return NULL; 
     588        } 
     589        p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size; 
     590 
     591        aout_DateInit(&p_sys->end_date, p_sys->p_header->rate); 
     592    } 
     593 
     594    /*  
     595      If the SpeexBits are initialized but there is  
     596      still no header, an error must be thrown. 
     597    */ 
     598    if ( !p_sys->p_header ) 
     599    { 
     600        msg_Err( p_dec, "There is no valid Speex header found." ); 
     601        return NULL; 
     602    } 
     603    *pp_block = NULL; 
     604 
     605    if ( !aout_DateGet( &p_sys->end_date ) ) 
     606        aout_DateSet( &p_sys->end_date, p_speex_bit_block->i_dts ); 
     607 
     608    /* 
     609      Ask for a new audio output buffer and make sure 
     610      we get one.  
     611    */ 
     612    p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec,  
     613        p_sys->p_header->frame_size ); 
     614    if ( !p_aout_buffer || p_aout_buffer->i_nb_bytes == 0 ) 
     615    { 
     616        msg_Err(p_dec, "Oops: No new buffer was returned!"); 
     617        return NULL; 
     618    } 
     619 
     620    /* 
     621      Read the Speex payload into the SpeexBits buffer. 
     622    */ 
     623    speex_bits_read_from( &p_sys->bits,  
     624        (char*)p_speex_bit_block->p_buffer,  
     625        p_speex_bit_block->i_buffer ); 
     626     
     627    /*  
     628      Decode the input and ensure that no errors  
     629      were encountered. 
     630    */ 
     631    i_decode_ret =  
     632        speex_decode_int( p_sys->p_state,&p_sys->bits,p_aout_buffer->p_buffer ); 
     633    if ( i_decode_ret < 0 ) 
     634    { 
     635        msg_Err( p_dec, "Decoding failed. Perhaps we have a bad stream?" ); 
     636        return NULL; 
     637    } 
     638 
     639    /*  
     640      Handle date management on the audio output buffer.  
     641    */ 
     642    p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date ); 
     643    p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,  
     644        p_sys->p_header->frame_size ); 
     645     
     646     
     647    p_sys->i_frame_in_packet++; 
     648    block_Release( p_speex_bit_block ); 
     649 
     650    return p_aout_buffer; 
     651} 
     652 
    450653/***************************************************************************** 
    451654 * DecodePacket: decodes a Speex packet. 
    452655 *****************************************************************************/ 
     
    485688 
    486689        if( i_ret== -2 ) 
    487690        { 
    488             msg_Warn( p_dec, "decoding error: corrupted stream?" ); 
     691            msg_Err( p_dec, "decoding error: corrupted stream?" ); 
    489692            return NULL; 
    490693        } 
    491694 
    492695        if( speex_bits_remaining( &p_sys->bits ) < 0 ) 
    493696        { 
    494             msg_Warn( p_dec, "decoding overflow: corrupted stream?" ); 
    495         } 
     697            msg_Err( p_dec, "decoding overflow: corrupted stream?" ); 
     698        }  
    496699 
    497700        if( p_sys->p_header->nb_channels == 2 ) 
    498701            speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer, 
     
    502705        /* Date management */ 
    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++; 
    508711 
     
    526729    p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date ); 
    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; 
    535740 
     
    563768 
    564769    if( p_oggpacket->bytes < 8 ) 
    565770    { 
    566         msg_Warn( p_dec, "invalid/corrupted comments" ); 
     771        msg_Err( p_dec, "invalid/corrupted comments" ); 
    567772        return; 
    568773    } 
    569774 
    570775    i_len = readint( p_buf, 0 ); p_buf += 4; 
    571776    if( i_len > p_oggpacket->bytes - 4 ) 
    572777    { 
    573         msg_Warn( p_dec, "invalid/corrupted comments" ); 
     778        msg_Err( p_dec, "invalid/corrupted comments" ); 
    574779        return; 
    575780    } 
    576781