コード例 #1
0
void AmJbPlayout::prepare_buffer(unsigned int audio_buffer_ts, unsigned int ms)
{
  ShortSample buf[AUDIO_BUFFER_SIZE];
  unsigned int ts;
  unsigned int nb_samples;
  /**
   * Get all RTP packets that correspond to the required interval,
   * decode them and put into playout buffer.
   */
  while (m_jb.get(audio_buffer_ts, ms, buf, &nb_samples, &ts))
    {
      direct_write_buffer(ts, buf, nb_samples);
      m_plcbuffer->add_to_history(buf, PCM16_S2B(nb_samples));
      /* Conceal the gap between previous and current RTP packets */
      if (last_ts_i && ts_less()(m_last_rtp_endts, ts))
       	{
	  int concealed_size = m_plcbuffer->conceal_loss(ts - m_last_rtp_endts, (unsigned char *)buf);
	  if (concealed_size > 0)
	    direct_write_buffer(m_last_rtp_endts, buf, PCM16_B2S(concealed_size));
	}
      m_last_rtp_endts = ts + nb_samples;
      last_ts_i = true;
    }
  if (!last_ts_i) {
    return;
  }
  if (ts_less()(m_last_rtp_endts, audio_buffer_ts + ms))
    {
      /* Last packets have been lost. Conceal them */
      int concealed_size = m_plcbuffer->conceal_loss(audio_buffer_ts + ms - m_last_rtp_endts, (unsigned char *)buf);
      if (concealed_size > 0)
	direct_write_buffer(m_last_rtp_endts, buf, PCM16_B2S(concealed_size));
      m_last_rtp_endts = audio_buffer_ts + ms;
    }
}
コード例 #2
0
ファイル: RtmpAudio.cpp プロジェクト: Chocolatbuddha/sems
// returns bytes read, else -1 if error (0 is OK)
int RtmpAudio::get(unsigned long long system_ts, unsigned char* buffer, 
		   int output_sample_rate, unsigned int nb_samples)
{
  // - buffer RTMP audio
  // - read from RTMP recv buffer

  unsigned int user_ts = scaleSystemTS(system_ts);

  //DBG("get(%u, %u)\n",user_ts,nb_samples);
  process_recv_queue(user_ts);

  nb_samples = (unsigned int)((float)nb_samples * (float)getSampleRate()
			     / (float)output_sample_rate);

  u_int32_t size =
    PCM16_S2B(playout_buffer.read(user_ts,
				  (ShortSample*)((unsigned char*)samples),
				  nb_samples));

  if(output_sample_rate != getSampleRate()) {
    size = resampleOutput((unsigned char*)samples, size,
			  getSampleRate(), output_sample_rate);
  }
  
  memcpy(buffer,(unsigned char*)samples,size);

  return size;
}
コード例 #3
0
int AmBufferedAudio::get(unsigned int user_ts, unsigned char* buffer, unsigned int nb_samples) {
  if (!output_buffer_size) 
    return AmAudio::get(user_ts, buffer, nb_samples);

  if (w-r < low_buffer_thresh && !eof) {
    input_get_audio(user_ts);
  }
  
  size_t nget = PCM16_S2B(nb_samples);
  if (w-r < nget) 
    nget = w-r;

  if (!nget) {
    // empty buffer and input error
    if (eof)
      return err_code;

    // empty buffer but no input error
    return 0;
  }
 
  memcpy(buffer, &output_buffer[r], nget);

  r+=nget;
  return nget;
}
コード例 #4
0
ファイル: AmRtpAudio.cpp プロジェクト: sems-server/sems
int AmRtpAudio::get(unsigned long long system_ts, unsigned char* buffer, 
		    int output_sample_rate, unsigned int nb_samples)
{
  if (!(receiving || getPassiveMode())) return 0; // like nothing received

  int ret = receive(system_ts);
  if(ret < 0)
    return ret; // like nothing received?

  if (!active) return 0;

  unsigned int user_ts = scaleSystemTS(system_ts);

  nb_samples = (unsigned int)((float)nb_samples * (float)getSampleRate()
			     / (float)output_sample_rate);

  u_int32_t size =
    PCM16_S2B(playout_buffer->read(user_ts,
				   (ShortSample*)((unsigned char*)samples),
				   nb_samples));
  if(output_sample_rate != getSampleRate()) {
    size = resampleOutput((unsigned char*)samples, size,
			  getSampleRate(), output_sample_rate);
  }
  
  memcpy(buffer,(unsigned char*)samples,size);

  return size;
}
コード例 #5
0
ファイル: AmAudio.cpp プロジェクト: BackupTheBerlios/sems-svn
unsigned int AmAudio::downMix(unsigned int size)
{
  unsigned int s = size;
  if(fmt->channels == 2){
    stereo2mono(samples.back_buffer(),(unsigned char*)samples,s);
    samples.swap();
  }

#ifdef USE_LIBSAMPLERATE 
  if (fmt->rate != SYSTEM_SAMPLERATE) {
    if (!resample_state) {
      int src_error;
      // for better quality but more CPU usage, use SRC_SINC_ converters
      resample_state = src_new(SRC_LINEAR, 1, &src_error);
      if (!resample_state) {
	ERROR("samplerate initialization error: ");
      }
    }

    if (resample_state) {
      if (resample_buf_samples + PCM16_B2S(s) > PCM16_B2S(AUDIO_BUFFER_SIZE) * 2) {
	WARN("resample input buffer overflow! (%d)\n",
	     resample_buf_samples + PCM16_B2S(s));
      } else {
	signed short* samples_s = (signed short*)(unsigned char*)samples;
	src_short_to_float_array(samples_s, &resample_in[resample_buf_samples], PCM16_B2S(s));
	resample_buf_samples += PCM16_B2S(s);
      }
      
      SRC_DATA src_data;
      src_data.data_in = resample_in;
      src_data.input_frames = resample_buf_samples;
      src_data.data_out = resample_out;
      src_data.output_frames = PCM16_B2S(AUDIO_BUFFER_SIZE);
      src_data.src_ratio = (double)SYSTEM_SAMPLERATE / (double)fmt->rate;
      src_data.end_of_input = 0;

      int src_err = src_process(resample_state, &src_data);
      if (src_err) {
	DBG("resample error: '%s'\n", src_strerror(src_err));
      }else {
	signed short* samples_s = (signed short*)(unsigned char*)samples;
	src_float_to_short_array(resample_out, samples_s, src_data.output_frames_gen);
	s = PCM16_S2B(src_data.output_frames_gen);

	if (resample_buf_samples !=  (unsigned int)src_data.input_frames_used) {
	  memmove(resample_in, &resample_in[src_data.input_frames_used], 
		  (resample_buf_samples - src_data.input_frames_used) * sizeof(float));
	}
	resample_buf_samples = resample_buf_samples - src_data.input_frames_used;
      }
    }
  }
#endif
 

  return s;
}
コード例 #6
0
void Packet::init(const ShortSample *data, unsigned int size, unsigned int ts)
{
  size = PCM16_S2B(size);
  if (size > sizeof(m_data))
    size = sizeof(m_data);
  m_size = PCM16_B2S(size);
  memcpy(m_data, data, size);
  m_ts = ts;
}
コード例 #7
0
void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t rtp_ts, 
			    int16_t* buf, u_int32_t len, bool begin_talk)
{  
  unsigned int mapped_ts;
  if(!recv_offset_i)
    {
      recv_offset = rtp_ts - ref_ts;
      recv_offset_i = true;
      DBG("initialized recv_offset with %u (%u - %u)\n",
	  recv_offset, ref_ts, rtp_ts);
      mapped_ts = r_ts = w_ts = ref_ts;
    }
  else {
    mapped_ts = rtp_ts - recv_offset;

    // resync
    if( ts_less()(mapped_ts, ref_ts - MAX_DELAY/2) || 
	!ts_less()(mapped_ts, ref_ts + MAX_DELAY) ){

      DBG("resync needed: reference ts = %u; write ts = %u\n",
	  ref_ts, mapped_ts);
      recv_offset = rtp_ts - ref_ts;
      mapped_ts = r_ts = w_ts = ref_ts;
    }
  }

  if(!last_ts_i)
    {
      last_ts = mapped_ts;
      last_ts_i = true;
    }

  if(ts_less()(last_ts, mapped_ts) && !begin_talk
     && (mapped_ts - last_ts <= PLC_MAX_SAMPLES))
    {
      unsigned char tmp[AUDIO_BUFFER_SIZE * 2];
      int l_size = m_plcbuffer->conceal_loss(mapped_ts - last_ts, tmp);
      if (l_size>0)
        {
	  direct_write_buffer(last_ts, (ShortSample*)tmp, PCM16_B2S(l_size));
        }
    }
  write_buffer(ref_ts, mapped_ts, buf, len);

  m_plcbuffer->add_to_history(buf, PCM16_S2B(len));

  // update last_ts to end of received packet 
  // if not out-of-sequence
  if (ts_less()(last_ts, mapped_ts) || last_ts == mapped_ts)
    last_ts = mapped_ts + len;
}
コード例 #8
0
ファイル: AmAudio.cpp プロジェクト: FihlaTV/sems-amr
unsigned int AmInternalResamplerState::resample(unsigned char *samples, unsigned int s, double ratio)
{
  if (rstate == NULL) {
    ERROR("Uninitialized resampling state");
    return s;
  }

  //DBG("Resampling with ration %f", ratio);
  //DBG("Putting %d samples in the buffer", PCM16_B2S(s));
  rstate->put_samples((signed short *)samples, PCM16_B2S(s));
  s = rstate->resample((signed short *)samples, ratio, PCM16_B2S(s) * ratio);
  //DBG("Returning %d samples", s);
  return PCM16_S2B(s);
}
コード例 #9
0
ファイル: AmRtpAudio.cpp プロジェクト: sems-server/sems
unsigned int AmRtpAudio::conceal_loss(unsigned int ts_diff, unsigned char *buffer)
{
  int s=0;
  if(!use_default_plc){

    amci_codec_t* codec = fmt->getCodec();
    long h_codec = fmt->getHCodec();

    assert(codec && codec->plc);
    s = (*codec->plc)(buffer, PCM16_S2B(ts_diff),
		      fmt->channels,getSampleRate(),h_codec);

    DBG("codec specific PLC (ts_diff = %i; s = %i)\n",ts_diff,s);
  }
  else {
    s = default_plc(buffer, PCM16_S2B(ts_diff),
		    fmt->channels,getSampleRate());

    DBG("default PLC (ts_diff = %i; s = %i)\n",ts_diff,s);
  }
    
  return s;
}
コード例 #10
0
void AmMultiPartyMixer::GetChannelPacket(unsigned int   channel_id,
					 unsigned long long system_ts, 
					 unsigned char* buffer, 
					 unsigned int&  size,
					 unsigned int&  output_sample_rate)
{
  if (!size)
    return;
  assert(size <= AUDIO_BUFFER_SIZE);

  unsigned int last_ts = system_ts + (PCM16_B2S(size) * (WALLCLOCK_RATE/100) / (GetCurrentSampleRate()/100));
  std::deque<MixerBufferState>::iterator bstate = findBufferStateForReading(GetCurrentSampleRate(), last_ts);

  SampleArrayShort* channel = 0;
  if(bstate != buffer_state.end() && (channel = bstate->get_channel(channel_id)) != 0) {

    unsigned int samples = PCM16_B2S(size) * (bstate->sample_rate/100) / (GetCurrentSampleRate()/100);
    assert(samples <= PCM16_B2S(AUDIO_BUFFER_SIZE));

    unsigned long long cur_ts = system_ts * (bstate->sample_rate/100) / (WALLCLOCK_RATE/100);
    bstate->mixed_channel->get(cur_ts,tmp_buffer,samples);
    channel->get(cur_ts,(short*)buffer,samples);

    mix_sub(tmp_buffer,tmp_buffer,(short*)buffer,samples);
    scale((short*)buffer,tmp_buffer,samples);
    size = PCM16_S2B(samples);
    output_sample_rate = bstate->sample_rate;
  } else if (bstate != buffer_state.end()) {
    memset(buffer,0,size);
    output_sample_rate = GetCurrentSampleRate();
    //DBG("XXDebugMixerXX: GetChannelPacket returned zeroes, ts=%u, last_ts=%u, output_sample_rate=%u", ts, last_ts, output_sample_rate);
  } else {
    /*
    ERROR("XXDebugMixerXX: MultiPartyMixer::GetChannelPacket: "
	  "channel #%i doesn't exist\n",channel_id);
    DBG("XXDebugMixerXX: GetChannelPacket failed, ts=%u", ts);
    for (std::deque<MixerBufferState>::iterator it = buffer_state.begin(); it != buffer_state.end(); it++) {
      DEBUG_MIXER_BUFFER_STATE(*it, "on GetChannelPacket failure");
      }*/
  }

  cleanupBufferStates(last_ts);
}
コード例 #11
0
ファイル: AmRtpAudio.cpp プロジェクト: sems-server/sems
unsigned int AmRtpAudio::default_plc(unsigned char* out_buf,
				     unsigned int   size,
				     unsigned int   channels,
				     unsigned int   sample_rate)
{
  short* buf_offset = (short*)out_buf;

#ifdef USE_SPANDSP_PLC
  plc_fillin(plc_state, buf_offset, PCM16_B2S(size));
#else
  for(unsigned int i=0; i<(PCM16_B2S(size)/FRAMESZ); i++){

    fec->dofe(buf_offset);
    buf_offset += FRAMESZ;
  }
#endif // USE_SPANDSP_PLC

  return PCM16_S2B(buf_offset - (short*)out_buf);
}
コード例 #12
0
/**
 * This method will return from zero to several packets.
 * To get all the packets for the single ts the caller must call this
 * method with the same ts till the return value will become false.
 */
bool AmJitterBuffer::get(unsigned int ts, unsigned int ms, ShortSample *out_buf, 
			 unsigned int *out_size, unsigned int *out_ts)
{
  bool retval = true;

  m_mutex.lock();
  if (!m_tsInited) {
    m_mutex.unlock();
    return false;
  }
  if (!m_tsDeltaInited || m_forceResync) {
    m_tsDelta = m_lastTs - ts + ms;
    m_tsDeltaInited = true;
    m_lastAudioTs = ts;
    m_forceResync = false;
#ifdef DEBUG_PLAYOUTBUF
    DBG("Jitter buffer: initialized tsDelta with %u\n", m_tsDelta);
    m_tsDeltaStart = m_tsDelta;
#endif
  }
  else if (m_lastAudioTs != ts && m_lastResyncTs != m_lastTs) {
    if (ts_less()(ts + m_tsDelta, m_lastTs)) {
      /* 
       * New packet arrived earlier than expected -
       *  immediate resync required 
       */
      m_tsDelta += m_lastTs - ts + ms;
#ifdef DEBUG_PLAYOUTBUF
      DBG("Jitter buffer resynced forward (-> %d rel)\n", 
	  m_tsDelta - m_tsDeltaStart);
#endif
      m_delayCount = 0;
    } else if (ts_less()(m_lastTs, ts + m_tsDelta - m_jitter / 2)) {
      /* New packet hasn't arrived yet */
      if (m_delayCount > RESYNC_THRESHOLD) {
	unsigned int d = m_tsDelta -(m_lastTs - ts + ms);
	m_tsDelta -= d / 2;
#ifdef DEBUG_PLAYOUTBUF
	DBG("Jitter buffer resynced backward (-> %d rel)\n", 
	    m_tsDelta - m_tsDeltaStart);
#endif
      }
      else
	++m_delayCount;
    }
    else {
      /* New packet arrived at proper time */
      m_delayCount = 0;
    }
    m_lastResyncTs = m_lastTs;
  }
  m_lastAudioTs = ts;
  unsigned int get_ts = ts + m_tsDelta - m_jitter;
  //    DBG("Getting pkt at %u, res ts = %u\n", get_ts / m_frameSize, p.timestamp);
  // First of all throw away all too old packets from the head
  Packet *tmp;
  for (tmp = m_head; tmp && ts_less()(tmp->ts() + tmp->size(), get_ts); )
    {
      m_head = tmp->m_next;
      if (m_head == NULL)
	m_tail = NULL;
      else
	m_head->m_prev = NULL;
      m_allocator.free(tmp);
      tmp = m_head;
    }
  // Get the packet from the head
  if (m_head && ts_less()(m_head->ts(), get_ts + ms))
    {
      tmp = m_head;
      m_head = tmp->m_next;
      if (m_head == NULL)
	m_tail = NULL;
      else
	m_head->m_prev = NULL;
      memcpy(out_buf, tmp->data(), PCM16_S2B(tmp->size()));
      // Map RTP timestamp to internal audio timestamp
      *out_ts = tmp->ts() - m_tsDelta + m_jitter;
      *out_size = tmp->size();
      m_allocator.free(tmp);
    }
  else
    retval = false;

  m_mutex.unlock();
  return retval;
}