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

📄 timed_sync.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2005.  All Rights Reserved. *  * Contributor(s):  *              Bill May        wmay@cisco.com */#include "sync.h"#include "mpeg4ip_utils.h"CTimedSync::CTimedSync (const char *name, 			CPlayerSession *psptr) : CSync(psptr){  m_next = NULL;  m_name = name;  m_consec_skipped = 0;  m_behind_frames = 0;  m_total_frames = 0;  m_filled_frames = 0;  m_behind_time = 0;  m_behind_time_max = 0;  m_skipped_render = 0;  m_msec_per_frame = 0;  m_max_buffers = 0;  m_buffer_filled = NULL;  m_last_filled_time = TO_U64(0x7fffffffffffffff);  m_config_set = false;  m_initialized = false;  m_decode_waiting = false;  m_dont_fill = false;  m_fill_index = m_play_index = m_max_buffers = 0;}CTimedSync::~CTimedSync (void){  message(LOG_NOTICE, m_name, "%s Sync Stats:", m_name);  message(LOG_NOTICE, m_name, "Displayed-behind frames %d", m_behind_frames);  message(LOG_NOTICE, m_name, "Total frames displayed %d", m_total_frames);  message(LOG_NOTICE, m_name, "Max behind time " U64, m_behind_time_max);  if (m_behind_frames > 0)     message(LOG_NOTICE, m_name, "Average behind time "U64, m_behind_time / m_behind_frames);  message(LOG_NOTICE, m_name, "Skipped rendering %u", m_skipped_render);  message(LOG_NOTICE, m_name, "Filled frames %u", m_filled_frames);  CHECK_AND_FREE(m_buffer_filled);  CHECK_AND_FREE(m_play_this_at);}void CTimedSync::initialize_indexes (uint32_t num_buffers) {  void *temp = malloc(sizeof(bool) * num_buffers);  memset(temp, false, sizeof(bool) * num_buffers);  m_buffer_filled = (volatile bool *)temp;  temp = malloc(sizeof(uint64_t) * num_buffers);  m_play_this_at = (uint64_t *)temp;  m_max_buffers = num_buffers;}void CTimedSync::increment_fill_index (void) {  m_buffer_filled[m_fill_index] = true;  m_fill_index++;  m_fill_index %= m_max_buffers;  m_filled_frames++;} void CTimedSync::increment_play_index (void) {  m_buffer_filled[m_play_index] = false;  m_play_index++;  m_play_index %= m_max_buffers;  m_total_frames++;} void CTimedSync::notify_decode_thread (void) {  if (m_decode_waiting) {    // If the decode thread is waiting, signal it.    m_decode_waiting = false;    SDL_SemPost(m_decode_sem);  }}bool CTimedSync::have_buffer_to_fill (void) {  if (dont_fill()) return false;  if (m_buffer_filled[m_fill_index]) {    m_decode_waiting = true;    SDL_SemWait(m_decode_sem);    if (dont_fill()) return false;    if (m_buffer_filled[m_fill_index]) {#ifdef VIDEO_SYNC_FILL      video_message(LOG_DEBUG, "Wait but filled %d", m_fill_index);#endif      return false;    }  }    return true;}void CTimedSync::save_last_filled_time (uint64_t ts) {  if (ts > m_last_filled_time) {    uint64_t temp;    temp = ts - m_last_filled_time;    if (temp < m_msec_per_frame) {      m_msec_per_frame = temp;    }  }  m_last_filled_time = ts;}bool CTimedSync::play_at (uint64_t current_time, 			    bool have_audio_resync,			    uint64_t &next_time,			    bool &have_eof){  uint64_t play_this_at = 0;  bool done = false;  bool used_frame = false;  bool have_next_time = true;  while (done == false) {    /*     * m_buffer_filled is ring buffer of YUV data from decoders, with     * timestamps.     * If the next buffer is not filled, indicate that, as well     */    //message(LOG_DEBUG, "ts", "play %d", m_buffer_filled[m_play_index]);    if (m_buffer_filled[m_play_index] == false) {      /*       * If we have end of file, indicate it       */      have_eof = get_eof();      done = true;      have_next_time = false;      continue;    }      /*     * we have a buffer.  If it is in the future, don't play it now     */    play_this_at = m_play_this_at[m_play_index];#if 0    message(LOG_DEBUG, "ts", "play "U64" at "U64 " %d "U64, play_this_at, current_time,		  m_play_index, m_msec_per_frame);#endif    if (play_this_at > current_time) {      have_next_time = true;      done = true;      continue;    }    /*     * If we're behind - see if we should just skip it     */    if (play_this_at < current_time) {      uint64_t behind = current_time - play_this_at;      if (have_audio_resync && behind > TO_U64(1000)) {	have_next_time = true;	done = true;	continue;      }      m_behind_frames++;      m_behind_time += behind;      if (behind > m_behind_time_max) m_behind_time_max = behind;#if 0      if ((m_behind_frames % 64) == 0) {	video_message(LOG_DEBUG, "behind "U64" avg "U64" max "U64,		      behind, m_behind_time / m_behind_frames,		      m_behind_time_max);      }#endif    }    /*     * If we're within 1/2 of the frame time, go ahead and display     * this frame     */#if 1    // a new thought (2005-03-18, wmay) - if we don't have the next    // frame filled, or the current time is less than the next time,     // go ahead and render.    uint32_t play_index = m_play_index;    increment_play_index();#if 0    message(LOG_DEBUG, "ts", "next %d "U64" "U64,	    m_buffer_filled[m_play_index],	    m_play_this_at[m_play_index],	    current_time);#endif    if (m_buffer_filled[m_play_index] == false ||	m_play_this_at[m_play_index] > current_time) {      render(play_index);    } else {      m_skipped_render++;      m_consec_skipped++;#if 0      message(LOG_DEBUG, "ts", "skipped "U64" current "U64,	      m_play_this_at[m_play_index], current_time);#endif    }#else    if ((play_this_at + m_msec_per_frame) > current_time) {      m_consec_skipped = 0;      render(m_play_index);    } else {      /*       * Else - we're lagging - just skip and hope we catch up...       */      m_skipped_render++;      m_consec_skipped++;    }    /*     * Advance the ring buffer, indicating that the decoder can fill this     * buffer.     */    increment_play_index();#endif    used_frame = true;  }  // end of loop - notify decode thread outside loop  if (used_frame) {    notify_decode_thread();  }  next_time = play_this_at;  return have_next_time;}void CTimedSync::flush_sync_buffers (void){  // Just restart decode thread if waiting...  m_dont_fill = true;  flush();  clear_eof();  notify_decode_thread();}// called from decode thread on both stop/start.void CTimedSync::flush_decode_buffers (void){  if (m_buffer_filled != NULL) {    for (uint32_t ix = 0; ix < m_max_buffers; ix++) {      m_buffer_filled[ix] = false;    }  }  m_fill_index = m_play_index = 0;  m_dont_fill = false;}

⌨️ 快捷键说明

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