2012-03-06 6 views
2

speex 라이브러리를 사용하여 오디오 데이터를 인코딩, 디코딩 및 전처리합니다. 나는 speex 라이브러리가 매우 유용하다고 생각하지만, speex 지터 버퍼을 사용하면 몇 가지 문제점이 있습니다. 멀티 스레드를 사용하고 하나의 스레드가 수신 된 데이터를 지터 버퍼에 넣고 다른 스레드가 활성 지터 버퍼에서 데이터를 가져옵니다. 때로는 '점점'스레드가 유효한 데이터를 얻을 수없는 경우가 있는데 특히 ' 퍼팅 데이터 '스레드. 또한 지터 버퍼를 보호하기 위해 뮤텍스를 사용하고 있습니다.speex 지터 버퍼 사용 방법

정확하게 지터 버퍼를 사용하는 방법을 모르겠습니다. 누군가가 나를 도울 수 있기를 바랍니다.

speex_jitter_buffer.h 

#include <speex/speex_jitter.h> 
#include <speex/speex.h> 

/** @defgroup SpeexJitter SpeexJitter: Adaptive jitter buffer specifically for Speex 
* This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size 
* to maintain good quality and low latency. This is a simplified version that works only 
* with Speex, but is much easier to use. 
* @{ 
*/ 

/** Speex jitter-buffer state. Never use it directly! */ 
typedef struct SpeexJitter { 
    SpeexBits current_packet;   /**< Current Speex packet */ 
    int valid_bits;     /**< True if Speex bits are valid */ 
    JitterBuffer *packets;   /**< Generic jitter buffer state */ 
    void *dec;      /**< Pointer to Speex decoder */ 
    spx_int32_t frame_size;   /**< Frame size of Speex decoder */ 
} SpeexJitter; 

/** Initialise jitter buffer 
* 
* @param jitter State of the Speex jitter buffer 
* @param decoder Speex decoder to call 
* @param sampling_rate Sampling rate used by the decoder 
*/ 
void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate); 

/** Destroy jitter buffer */ 
void speex_jitter_destroy(SpeexJitter *jitter); 

/** Put one packet into the jitter buffer */ 
void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp); 

/** Get one packet from the jitter buffer */ 
void speex_jitter_get(SpeexJitter *jitter, spx_int16_t *out, int *start_offset); 

/** Get pointer timestamp of jitter buffer */ 
int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter); 

#ifdef __cplusplus 
} 
#endif 

speex_jitter_buffer.cpp 그리고 나는 "speex_jitter_buffer.h"헤더 파일을 사용하고

#include <speex/speex_jitter.h> 
#include "speex_jitter_buffer.h" 

#ifndef NULL 
#define NULL 0 
#endif 


void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate) 
{ 
    jitter->dec = decoder; 
    speex_decoder_ctl(decoder, SPEEX_GET_FRAME_SIZE, &jitter->frame_size); 

    jitter->packets = jitter_buffer_init(jitter->frame_size); 

    speex_bits_init(&jitter->current_packet); 
    jitter->valid_bits = 0; 

} 

void speex_jitter_destroy(SpeexJitter *jitter) 
{ 
    jitter_buffer_destroy(jitter->packets); 
    speex_bits_destroy(&jitter->current_packet); 
} 

void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp) 
{ 
    JitterBufferPacket p; 
    p.data = packet; 
    p.len = len; 
    p.timestamp = timestamp; 
    p.span = jitter->frame_size; 
    jitter_buffer_put(jitter->packets, &p); 
} 

void speex_jitter_get(SpeexJitter *jitter, spx_int16_t *out, int *current_timestamp) 
{ 
    int i; 
    int ret; 
    spx_int32_t activity; 
    char data[2048]; 
    JitterBufferPacket packet; 
    packet.data = data; 

    if (jitter->valid_bits) 
    { 
     /* Try decoding last received packet */ 
     ret = speex_decode_int(jitter->dec, &jitter->current_packet, out); 
     if (ret == 0) 
     { 
     jitter_buffer_tick(jitter->packets); 
     return; 
     } else { 
     jitter->valid_bits = 0; 
     } 
    } 

    ret = jitter_buffer_get(jitter->packets, &packet, jitter->frame_size, NULL); 

    if (ret != JITTER_BUFFER_OK) 
    { 
     /* No packet found */ 

     /*fprintf (stderr, "lost/late frame\n");*/ 
     /*Packet is late or lost*/ 
     speex_decode_int(jitter->dec, NULL, out); 
    } else { 
     speex_bits_read_from(&jitter->current_packet, packet.data, packet.len); 
     /* Decode packet */ 
     ret = speex_decode_int(jitter->dec, &jitter->current_packet, out); 
     if (ret == 0) 
     { 
     jitter->valid_bits = 1; 
     } else { 
     /* Error while decoding */ 
     for (i=0;i<jitter->frame_size;i++) 
      out[i]=0; 
     } 
    } 
    speex_decoder_ctl(jitter->dec, SPEEX_GET_ACTIVITY, &activity); 
    if (activity < 30) 
     jitter_buffer_update_delay(jitter->packets, &packet, NULL); 
    jitter_buffer_tick(jitter->packets); 
} 

int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter) 
{ 
    return jitter_buffer_get_pointer_timestamp(jitter->packets); 
} 

:

이 내 코드입니다.

'퍼팅'스레드 코드 :

m_jitter_mutex.lock(); 
speex_jitter_put(&jitter, recvBuf, payloadLength, timestamp); 
m_jitter_mutex.unlock(); 

'점점'스레드 코드 :

while(true) 
{ 
    Sleep(20); 

    m_jitter_mutex.lock(); 
    speex_jitter_get(&jitter, (spx_int16_t*)pcm_short, NULL); 
    m_pOut->Play(pcm_char, pcm_data_length); // play the pcm data 
    m_jitter_mutex.lock(); 
} 

나는 또한 에코 제거 작업을 수행 할 Speex가 라이브러리를 사용하고 싶지만, 그렇게하지 정확히 어떻게 우리에게 그것을 알지. 많이 고마워.

답변