📄 audio_sdl_old.cpp
字号:
fill_index++; fill_index %= DECODE_BUFFERS_MAX; m_fill_index++; m_fill_index %= DECODE_BUFFERS_MAX; if (locked) Our_SDL_UnlockAudio(); audio_message(LOG_NOTICE, "Filling timestamp "U64" with silence", m_last_fill_timestamp); m_last_fill_timestamp += m_msec_per_frame + 1; // fill plus extra ts_diff = ts - m_last_fill_timestamp; audio_message(LOG_DEBUG, "diff is "D64, ts_diff); } while (ts_diff > 0); locked = 0; if (m_audio_initialized != 0) { Our_SDL_LockAudio(); locked = 1; } } } else { if (m_last_fill_timestamp == ts) { audio_message(LOG_NOTICE, "Repeat timestamp with audio "U64, ts); if (locked) Our_SDL_UnlockAudio(); return; } } } m_last_fill_timestamp = ts; m_buffer_filled[fill_index] = 1; m_buffer_bytes_loaded += m_buffer_size; m_buffer_time[fill_index] = ts; if (resync) { m_resync_required = 1; m_resync_buffer = fill_index;#ifdef DEBUG_AUDIO_FILL audio_message(LOG_DEBUG, "Resync from filled_audio_buffer");#endif } if (locked) Our_SDL_UnlockAudio(); // Check this - we might not want to do this unless we're resyncing if (resync) m_psptr->wake_sync_thread();#ifdef DEBUG_AUDIO_FILL audio_message(LOG_DEBUG, "Filling " U64 " %u %u", ts, fill_index, m_buffer_bytes_loaded);#endif}void CSDLAudioSync::set_eof(void) { uint8_t *to; if (m_buffer_offset_on != 0) { to = get_audio_buffer(); if (to != NULL) { uint32_t left; left = m_buffer_size - m_buffer_offset_on; memset(to + m_buffer_offset_on, 0, left); m_buffer_offset_on = 0; filled_audio_buffer(m_buffer_ts, 0); m_buffer_ts += m_msec_per_frame; } } CAudioSync::set_eof();}// Sync task api - initialize the sucker.// May need to check out non-standard frequencies, see about conversion.// returns 0 for not yet, 1 for initialized, -1 for errorint CSDLAudioSync::initialize_audio (int have_video) { if (m_audio_initialized == 0) { if (m_config_set) { SDL_AudioSpec wanted; m_do_sync = have_video; memset(&wanted, 0, sizeof(wanted)); wanted.freq = m_freq; wanted.channels = m_channels; switch (m_format) { case AUDIO_FMT_U8: wanted.format = AUDIO_U8; break; case AUDIO_FMT_S8: wanted.format = AUDIO_S8; break; case AUDIO_FMT_U16LSB: wanted.format = AUDIO_U16LSB; break; case AUDIO_FMT_U16MSB: wanted.format = AUDIO_U16MSB; break; case AUDIO_FMT_S16LSB: wanted.format = AUDIO_S16LSB; break; case AUDIO_FMT_S16MSB: wanted.format = AUDIO_S16MSB; break; case AUDIO_FMT_U16: wanted.format = AUDIO_U16SYS; break; case AUDIO_FMT_S16: wanted.format = AUDIO_S16SYS; break; case AUDIO_FMT_FLOAT: wanted.format = AUDIO_S16SYS; break; case AUDIO_FMT_HW_AC3: wanted.format = AUDIO_FORMAT_HW_AC3; break; } int sample_size; sample_size = m_buffer_size / (m_channels * m_bytes_per_sample_input);#ifndef _WIN32 uint32_t ix; for (ix = 2; ix <= 0x8000; ix <<= 1) { if ((sample_size & ~(ix - 1)) == 0) { break; } } ix >>= 1; audio_message(LOG_DEBUG, "Sample size is %d", ix); m_sample_size = ix;#else m_sample_size = 4096;#endif if ((m_do_sync == 0) && m_sample_size < 4096) m_sample_size = 4096; if (config.get_config_value(CONFIG_LIMIT_AUDIO_SDL_BUFFER) > 0 && m_sample_size > 4096) m_sample_size = 4096; wanted.samples = m_sample_size; wanted.callback = c_audio_callback; wanted.userdata = this;#if 1 audio_message(LOG_INFO, "requested f %d chan %d format %x samples %d", wanted.freq, wanted.channels, wanted.format, wanted.samples);#endif int ret = Our_SDL_OpenAudio(&wanted, &m_obtained); if (ret < 0) { if (wanted.channels > 2) { wanted.channels = 2; ret = Our_SDL_OpenAudio(&wanted, &m_obtained); } if (ret < 0) { audio_message(LOG_CRIT, "Couldn't open audio, %s", SDL_GetError()); return (-1); } }#if 1 char buffer[128]; if (Our_SDL_AudioDriverName(buffer, sizeof(buffer)) == NULL) { strcpy(buffer, "no audio driver"); } audio_message(LOG_INFO, "got f %d chan %d format %x samples %d size %u %s", m_obtained.freq, m_obtained.channels, m_obtained.format, m_obtained.samples, m_obtained.size, buffer);#endif#ifdef TEST_MONO_TO_STEREO#define CHECK_SDL_CHANS_RETURNED TRUE#define OBTAINED_CHANS 2#else#define CHECK_SDL_CHANS_RETURNED m_obtained.channels != m_channels#define OBTAINED_CHANS m_obtained.channels#endif bool need_convert = false; if (CHECK_SDL_CHANS_RETURNED) { Our_SDL_CloseAudio(); wanted.channels = OBTAINED_CHANS; wanted.format = AUDIO_S16SYS; // we're converting, so always choose m_bytes_per_sample_output = 2; ret = Our_SDL_OpenAudio(&wanted, &m_obtained); audio_message(LOG_INFO, "requested f %d chan %d format %x samples %d", wanted.freq, wanted.channels, wanted.format, wanted.samples); if (ret < 0) { audio_message(LOG_CRIT, "Couldn't reopen audio, %s", SDL_GetError()); return (-1); } audio_message(LOG_INFO, "got f %d chan %d format %x samples %d size %u %s", m_obtained.freq, m_obtained.channels, m_obtained.format, m_obtained.samples, m_obtained.size, buffer); need_convert = true; } m_got_channels = m_obtained.channels; if (m_format == AUDIO_FMT_FLOAT || need_convert) { audio_message(LOG_DEBUG, "convert buffer size is %d", m_obtained.size); audio_convert_init(m_obtained.size, m_obtained.samples); } m_audio_initialized = 1; m_use_SDL_delay = Our_SDL_HasAudioDelayMsec(); 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 Our_SDL_LockAudio(); if (m_use_SDL_delay) { current_time += Our_SDL_AudioDelayMsec(); } else { 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); Our_SDL_UnlockAudio(); 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.void CSDLAudioSync::audio_callback (Uint8 *outStream, int ilen){ int freed_buffer = 0; uint32_t outBufferTotalBytes = (uint32_t)ilen; uint64_t this_time; int delay = 0; uint64_t index_time; if (m_resync_required) { // resync required from codec side. Shut down, and notify sync task if (m_resync_buffer == m_play_index) { Our_SDL_PauseAudio(1); m_audio_paused = 1; m_psptr->wake_sync_thread();#ifdef DEBUG_SYNC audio_message(LOG_DEBUG, "sempost");#endif return; } } m_play_time = m_psptr->get_current_time(); if (m_use_SDL_delay != 0) { delay = Our_SDL_AudioDelayMsec(); if (delay < 0) delay = 0;#ifdef DEBUG_DELAY audio_message(LOG_DEBUG, "Audio delay is %d "U64, delay, m_play_time);#endif } if ((m_first_time == 0) && (m_use_SDL_delay == 0)) { /* * If we're not the first time, see if we're about a frame or more * around the current time, with latency built in. If not, skip * the buffer. This prevents us from playing past-due buffers. */ int time_okay = 0; this_time = 0; while ((m_buffer_filled[m_play_index] == 1) && (time_okay == 0)) { uint64_t buffertime, playtime; buffertime = m_buffer_time[m_play_index]; if (m_play_sample_index != 0) { uint64_t temp; temp = (uint64_t) m_play_sample_index * (uint64_t)m_msec_per_frame; temp /= (uint64_t) m_buffer_size; buffertime += temp; } if (m_use_SDL_delay != 0) playtime = m_play_time + delay; // m_buffer_latency; else playtime = m_play_time + m_buffer_latency; if (m_play_time != 0 && buffertime + m_msec_per_frame < playtime) { audio_message(LOG_DEBUG, "Skipped audio buffer " U64 "("U64") at " U64, m_buffer_time[m_play_index], buffertime, playtime); m_buffer_filled[m_play_index] = 0; m_play_index++; m_play_index %= DECODE_BUFFERS_MAX; m_skipped_buffers++; m_buffer_latency = 0; // recalculate... m_first_time = 0; m_play_sample_index = 0; uint32_t diff; diff = m_buffer_size - m_play_sample_index; if (m_buffer_bytes_loaded >= diff) { m_buffer_bytes_loaded -= diff; } else { m_buffer_bytes_loaded = 0; } m_consec_wrong_latency = 0; // reset all latency calcs.. m_wrong_latency_total = 0; } else { time_okay = 1; this_time = buffertime; } } } else { 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()) { Our_SDL_PauseAudio(1); m_audio_paused = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -