⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio_macosx_old.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	need_convert = true;      }      PaError err;      audio_message(LOG_DEBUG, "pa_open default %lx", format);      err = Pa_OpenDefaultStream(&m_pa_stream,				 0,				 m_channels,				 format,				 freq,				 m_sample_size,				 0,				 c_audio_callback,				 this);      m_got_channels = m_channels;      if (err != paNoError) {	if (err == paInvalidChannelCount) {	  format = paInt16;	  err = Pa_OpenDefaultStream(&m_pa_stream,				     0,				     2,				     format,				     freq,				     m_sample_size,				     0,				     c_audio_callback,				     this);	  m_got_channels = 2;	  need_convert = true;	}	if (err != paNoError) {	  audio_message(LOG_CRIT, "Couldn't open audio, %s", 			Pa_GetErrorText(err));	  return (-1);	}      }      if (need_convert) {	m_convert_buffer = malloc(m_sample_size);	audio_message(LOG_DEBUG, "convert buffer size is %d", m_sample_size);	m_fmt_buffer = (int16_t *)malloc(m_sample_size * 2 * m_channels);      }      m_audio_initialized = 1;      //if (m_use_SDL_delay)      //audio_message(LOG_NOTICE, "Using delay measurement from SDL");    } else {      return 0; // check again pretty soon...    }  }  return (1);}// This is used by the sync thread to determine if a valid amount of// buffers are ready, and what time they start.  It is used to determine// when we should start.int CSDLAudioSync::is_audio_ready (uint64_t &disptime){  disptime = m_buffer_time[m_play_index];  return (m_dont_fill == 0 && m_buffer_filled[m_play_index] == 1);}// Used by the sync thread to see if resync is needed.// 0 - in sync.  > 0 - sync time we need. -1 - need to do sync uint64_t CSDLAudioSync::check_audio_sync (uint64_t current_time, int &have_eof){  if (get_eof() != 0) {    have_eof = m_audio_paused;    return (0);  }  // audio is initialized.  if (m_resync_required) {    if (m_audio_paused && m_buffer_filled[m_resync_buffer]) {      // Calculate the current time based on the latency      SDL_LockMutex(m_pa_mutex);	current_time += m_buffer_latency;      uint64_t cmptime;      int freed = 0;      // Compare with times in buffer - we may need to skip if we fell      // behind.      do {	cmptime = m_buffer_time[m_resync_buffer];	if (cmptime < current_time) {#ifdef DEBUG_SYNC	  audio_message(LOG_INFO, "Passed time " U64 " " U64 " %u", 			       cmptime, current_time, m_resync_buffer);#endif	  m_buffer_filled[m_resync_buffer] = 0;	  m_resync_buffer++;	  m_resync_buffer %= DECODE_BUFFERS_MAX;	  freed = 1;	}      } while (m_buffer_filled[m_resync_buffer] == 1 && 	       cmptime < current_time - 2);      SDL_UnlockMutex(m_pa_mutex);      if (m_buffer_filled[m_resync_buffer] == 0) {	cmptime = 0;      } else {	if (cmptime >= current_time) {	  m_play_index = m_resync_buffer;	  m_resync_required = 0;	  play_audio();#ifdef DEBUG_SYNC	  audio_message(LOG_INFO, "Resynced audio at " U64 " %u %u", current_time, m_resync_buffer, m_play_index);#endif	  cmptime = 0;	}       }      if (freed != 0 && m_audio_waiting_buffer) {	m_audio_waiting_buffer = 0;	SDL_SemPost(m_audio_waiting);	//	audio_message(LOG_DEBUG, "post free passed time");      }      return cmptime;    } else {      return (0);    }  }  return (0);}// Audio callback from SDL.int CSDLAudioSync::audio_callback (void *oStream, 				   unsigned long bLen,				   PaTimestamp outtime){  uint8_t *outStream = (uint8_t *)oStream;  int freed_buffer = 0;  uint32_t outBufferTotalBytes =     bLen * m_got_channels * m_bytes_per_sample_output;  uint64_t this_time;  uint64_t index_time;  uint64_t delay;  //  audio_message(LOG_DEBUG,"bytes %u %lu outtime %g",   //	outBufferTotalBytes, bLen, outtime);  if (m_resync_required) {    // resync required from codec side.  Shut down, and notify sync task    if (m_resync_buffer == m_play_index) {      //Pa_StopStream(m_pa_stream);      m_audio_paused = 1;      m_psptr->wake_sync_thread();#ifdef DEBUG_SYNC      audio_message(LOG_DEBUG, "sempost");#endif      return 1;    }  }  m_play_time = m_psptr->get_current_time();  delay = 0;  PaTimestamp realtime = Pa_StreamTime(m_pa_stream);  delay = (uint64_t)(outtime - realtime);  delay *= TO_U64(1000);  delay /= m_freq;#ifdef DEBUG_DELAY  audio_message(LOG_DEBUG, "cur time %llu delay %llu %12f %12f", 		m_play_time, delay, outtime, realtime);#endif  uint64_t temp = 0;  this_time = m_buffer_time[m_play_index];  if ((m_first_time == 0) && (m_play_sample_index != 0)) {    temp = (uint64_t) m_play_sample_index * (uint64_t)m_msec_per_frame;    temp /= (uint64_t) m_buffer_size;    this_time += temp;  }#if 0    audio_message(LOG_DEBUG, "time "U64" "U64, m_buffer_time[m_play_index],		  temp);#endif  // Do we have a buffer ?  If no, see if we need to stop.  if (m_buffer_bytes_loaded == 0) {    if (get_eof()) {      //Pa_StopStream(m_pa_stream);      m_audio_paused = 1;      m_psptr->wake_sync_thread();      return 1;    }#ifdef DEBUG_SYNC    audio_message(LOG_DEBUG, "No buffer in audio callback %u %u", 		  m_buffer_bytes_loaded, outBufferTotalBytes);#endif    m_consec_no_buffers++;    int ret = 0;    if (m_consec_no_buffers > 10) {      //Pa_StopStream(m_pa_stream);      m_audio_paused = 1;      m_resync_required = 1;      m_resync_buffer = m_play_index;      m_psptr->wake_sync_thread();      ret = 1;    }    if (m_audio_waiting_buffer) {      m_audio_waiting_buffer = 0;      SDL_SemPost(m_audio_waiting);      //audio_message(LOG_DEBUG, "post no data");    }    audio_message(LOG_DEBUG, "return - no samples");    return ret;  }  // We have a valid buffer.  Push it to SDL.  m_consec_no_buffers = 0;  while (outBufferTotalBytes > 0) {    uint32_t outBufferSamples, outBufferBytes;    uint32_t decodedBufferBytes, decodedBufferSamples;    // calculate number of bytes left in the decoded bytes ring    decodedBufferBytes = m_buffer_size - m_play_sample_index;    // samples from bytes    decodedBufferSamples =       decodedBufferBytes / (m_channels * m_bytes_per_sample_input);        // See how many samples we can write into SDL buffers    outBufferSamples = outBufferTotalBytes /       (m_got_channels * m_bytes_per_sample_output);    // Adjust bytes from decoded ring accordingly    if (outBufferSamples < decodedBufferSamples) {      decodedBufferBytes = 	outBufferSamples * m_channels * m_bytes_per_sample_input;      decodedBufferSamples = outBufferSamples;    }    // Adjust bytes to copy    outBufferBytes =       decodedBufferSamples * m_got_channels * m_bytes_per_sample_output;#ifdef DEBUG_SYNC    audio_message(LOG_DEBUG, "Playing "U64" offset %d",		  m_buffer_time[m_play_index], m_play_sample_index);#endif    if (m_convert_buffer) {      // Convert the buffer based on the number of samples      audio_convert_data(&m_sample_buffer[m_play_index][m_play_sample_index],			 decodedBufferSamples);      // Mix based on the number of bytes      // need to adjust for volume      memcpy(outStream, m_convert_buffer, outBufferBytes);    } else {      memcpy(outStream, &m_sample_buffer[m_play_index][m_play_sample_index],	     outBufferBytes);    }    outBufferTotalBytes -= outBufferBytes;    outStream += outBufferBytes;    if (decodedBufferBytes <= m_buffer_bytes_loaded)      m_buffer_bytes_loaded -= decodedBufferBytes;    else       m_buffer_bytes_loaded = 0;    m_play_sample_index += decodedBufferBytes;    if (m_play_sample_index >= m_buffer_size) {#ifdef DEBUG_SYNC      audio_message(LOG_DEBUG, "finished with buffer %d %d", 		    m_play_index, m_buffer_bytes_loaded);#endif      m_buffer_filled[m_play_index] = 0;      m_play_index++;      m_play_index %= DECODE_BUFFERS_MAX;      m_play_sample_index = 0;      freed_buffer = 1;      if (m_resync_required) {	// resync required from codec side.  Shut down, and notify sync task	if (m_resync_buffer == m_play_index) {	  Pa_StopStream(m_pa_stream);	  m_audio_paused = 1;	  m_psptr->wake_sync_thread();#ifdef DEBUG_SYNC	  audio_message(LOG_DEBUG, "sempost");#endif	  outBufferTotalBytes = 0;	}      }    }  }        // Increment past this buffer.  if (m_first_time != 0) {    // First time through - tell the sync task we've started, so it can    // keep sync time.    m_first_time = 0;    m_buffer_latency = delay;    m_psptr->audio_is_ready(m_buffer_latency, this_time);    m_consec_wrong_latency = 0;    m_wrong_latency_total = 0;  }   else if (m_do_sync) {#define ALLOWED_LATENCY 2      // Here, we're using the delay value from the audio buffers,      // rather than the calculated time...      // Okay - now we check for latency changes.      index_time = delay + m_play_time;      if (this_time > index_time + ALLOWED_LATENCY || 	  this_time < index_time - ALLOWED_LATENCY) {#ifdef DEBUG_SYNC_CHANGES	audio_message(LOG_DEBUG, 		      "potential change - index time "U64" time "U64" delay "U64, 		      index_time, this_time, delay);#endif	if (m_consec_wrong_latency == 0) {	  m_consec_wrong_latency = 1;	} else {	  m_consec_wrong_latency++;	  int64_t test;	  test = this_time - index_time;	  m_wrong_latency_total += test;	  int64_t div;	  div = m_wrong_latency_total / (int64_t)(m_consec_wrong_latency - 1);#ifdef DEBUG_SYNC_CHANGES	  audio_message(LOG_DEBUG, "values are "D64" "D64" %d", 			test, div, m_consec_wrong_latency);#endif	  if (test > ALLOWED_LATENCY || test < -ALLOWED_LATENCY) {	    if (m_consec_wrong_latency > 5) {	      m_consec_wrong_latency = 0;	      m_wrong_latency_total = 0;	      if (test < -10000) {		audio_message(LOG_ERR, "Latency error - test is "D64,			      test);	      } else {		m_psptr->adjust_start_time(test);		m_buffer_latency -= test;	      }	    }	  } else {	    // average wrong latency is not greater than allowed latency	    m_consec_wrong_latency = 0;	    m_wrong_latency_total = 0;	  }	}      } else {	m_consec_wrong_latency = 0;	m_wrong_latency_total = 0;      }  } else {#ifdef DEBUG_SYNC    audio_message(LOG_DEBUG, "playing "U64" "U64" latency "U64, 		  this_time, m_play_time, m_buffer_latency);#endif  }  // If we had the decoder task waiting, signal it.  if (freed_buffer != 0 && m_audio_waiting_buffer) {    m_audio_waiting_buffer = 0;    SDL_SemPost(m_audio_waiting);    //audio_message(LOG_DEBUG, "post freed");  }  return 0;}void CSDLAudioSync::play_audio (void){  m_first_time = 1;  //m_resync_required = 0;  m_audio_paused = 0;  m_play_sample_index = 0;  audio_message(LOG_DEBUG, "Starting pa");  Pa_StartStream(m_pa_stream);}// Called from the sync thread when we want to stop.  Pause the audio,// and indicate that we're not to fill any more buffers - this should let// the decode thread get back to receive the pause message.  Only called// when pausing - could cause m_dont_fill race conditions if called on playvoid CSDLAudioSync::flush_sync_buffers (void){  // we don't need to signal the decode task right now -   // Go ahead   clear_eof();  Pa_StopStream(m_pa_stream);  m_dont_fill = 1;  if (m_audio_waiting_buffer) {    m_audio_waiting_buffer = 0;    SDL_SemPost(m_audio_waiting);    //audio_message(LOG_DEBUG, "post flush sync");      }  player_debug_message("Flushed sync");}// this is called from the decode thread.  It gets called on entry into pause,// and entry into play.  This way, m_dont_fill race conditions are resolved.void CSDLAudioSync::flush_decode_buffers (void){  int locked = 0;  if (m_audio_initialized != 0) {    locked = 1;    SDL_LockMutex(m_pa_mutex);  }  m_dont_fill = 0;  m_first_filled = 1;  for (int ix = 0; ix < DECODE_BUFFERS_MAX; ix++) {    m_buffer_filled[ix] = 0;  }  m_buffer_offset_on = 0;  m_play_index = m_fill_index = 0;  m_audio_paused = 1;  m_resync_buffer = 0;  m_buffer_bytes_loaded = 0;  if (locked)    SDL_UnlockMutex(m_pa_mutex);  //player_debug_message("flushed decode");}void CSDLAudioSync::set_volume (int volume){  m_volume = (volume * SDL_MIX_MAXVOLUME)/100;}static void c_audio_config (void *ifptr, int freq, 			    int chans, audio_format_t format, uint32_t max_buffer_size){  ((CSDLAudioSync *)ifptr)->set_config(freq,				    chans,				    format,				    max_buffer_size);}static uint8_t *c_get_audio_buffer (void *ifptr){  return ((CSDLAudioSync *)ifptr)->get_audio_buffer();}static void c_filled_audio_buffer (void *ifptr,				   uint32_t freq_ts,				   uint64_t ts,				   int resync_req){  ((CSDLAudioSync *)ifptr)->filled_audio_buffer(ts, 					     resync_req);}static void c_load_audio_buffer (void *ifptr, 				     uint8_t *from, 				     uint32_t bytes,				 uint32_t freq_ts,				     uint64_t ts, 				     int resync){  ((CSDLAudioSync *)ifptr)->load_audio_buffer(from,					      bytes,					      ts, 					      resync);}  static audio_vft_t audio_vft = {  message,  c_audio_config,  c_get_audio_buffer,  c_filled_audio_buffer,  c_load_audio_buffer,  NULL,};CAudioSync *create_audio_sync (CPlayerSession *psptr, int volume){  return new CSDLAudioSync(psptr, volume);}audio_vft_t *get_audio_vft (void){  audio_vft.pConfig = &config;  return &audio_vft;}int do_we_have_audio (void) {    PaError err;  err = Pa_Initialize();  if (err != paNoError) {    audio_message(LOG_ERR, "No audio - %d %s", err, 		  Pa_GetErrorText(err));    return 0;  }   Pa_Terminate();  //  Our_SDL_CloseAudio();  return (1);}/* end audio.cpp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -