Repository: xbmc/xbmc
File: xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp (C++)

Code before:
  const uint32_t minwrapvalue = UINT32_MAX - m_sink_sampleRate / 10;
  const uint32_t remain = static_cast<uint32_t>(m_headPos & UINT64_LOWER_BYTES);
  if ((remain > head_pos) && (remain >= minwrapvalue))
    m_headPos += (1ULL << 32); // add wraparound, e.g. 0x0000 FFFF FFFF -> 0x0001 FFFF FFFF
  // clear lower 32 bit values, e.g. 0x0001 FFFF FFFF -> 0x0001 0000 0000
  // and add head_pos which wrapped around, e.g. 0x0001 0000 0000 -> 0x0001 0000 0004
  m_headPos = (m_headPos & UINT64_UPPER_BYTES) | (uint64_t)head_pos;
  // check if sink is stuck
  if (m_headPos == m_headPosOld)
    m_stuckCounter++;
  else
  {
    m_stuckCounter = 0;
    m_headPosOld = m_headPos;
  }

  double gone = static_cast<double>(m_headPos) / m_sink_sampleRate;

  // if sink is run dry without buffer time written anymore
  if (gone > m_duration_written)
    gone = m_duration_written;

  double delay = m_duration_written - gone;

  // latency works way better but is not available everyhwere
  int latency = m_at_jni->getLatency();
  const bool isRawPt = m_passthrough && !m_info.m_wantsIECPassthrough;
  if (!isRawPt && latency != -1)
  {
    m_hw_delay = latency / 1000.0;
    // would include entire pipeline including audiotrack buffer
    // when rerouting this might change, so ask for it again
    int atbuffer = m_at_jni->getBufferSizeInFrames();
    double buffertime = static_cast<double>(atbuffer) / m_sink_sampleRate;
    m_hw_delay -= buffertime;
  }
  else // use timestamp api
  {
    if (m_stampTimer.IsTimePast())
    {
      if (!m_at_jni->getTimestamp(m_timestamp))
      {
        CLog::Log(LOGDEBUG, "Could not acquire timestamp");
        m_stampTimer.Set(100ms);
      }
      else
      {
        // check if frameposition is valid and nano timer less than 50 ms outdated
        if (m_timestamp.get_framePosition() > 0 &&
            (CurrentHostCounter() - m_timestamp.get_nanoTime()) < 50 * 1000 * 1000)
          m_stampTimer.Set(1000ms);

Review comment (performance):
```suggestion
  const int latency = m_at_jni->getLatency();
```

Code after:
  const uint32_t minwrapvalue = UINT32_MAX - m_sink_sampleRate / 10;
  const uint32_t remain = static_cast<uint32_t>(m_headPos & UINT64_LOWER_BYTES);
  if ((remain > head_pos) && (remain >= minwrapvalue))
    m_headPos += (1ULL << 32); // add wraparound, e.g. 0x0000 FFFF FFFF -> 0x0001 FFFF FFFF
  // clear lower 32 bit values, e.g. 0x0001 FFFF FFFF -> 0x0001 0000 0000
  // and add head_pos which wrapped around, e.g. 0x0001 0000 0000 -> 0x0001 0000 0004
  m_headPos = (m_headPos & UINT64_UPPER_BYTES) | (uint64_t)head_pos;
  // check if sink is stuck
  if (m_headPos == m_headPosOld)
    m_stuckCounter++;
  else
  {
    m_stuckCounter = 0;
    m_headPosOld = m_headPos;
  }

  double gone = static_cast<double>(m_headPos) / m_sink_sampleRate;

  // if sink is run dry without buffer time written anymore
  if (gone > m_duration_written)
    gone = m_duration_written;

  double delay = m_duration_written - gone;

  // latency works way better but is not available everyhwere
  const int latency = m_at_jni->getLatency();
  const bool isRawPt = m_passthrough && !m_info.m_wantsIECPassthrough;
  if (!isRawPt && latency != -1)
  {
    m_hw_delay = latency / 1000.0;
    // would include entire pipeline including audiotrack buffer
    // when rerouting this might change, so ask for it again
    const int atbuffer = m_at_jni->getBufferSizeInFrames();
    double buffertime = static_cast<double>(atbuffer) / m_sink_sampleRate;
    m_hw_delay -= buffertime;
  }
  else // use timestamp api
  {
    if (m_stampTimer.IsTimePast())
    {
      if (!m_at_jni->getTimestamp(m_timestamp))
      {
        CLog::Log(LOGDEBUG, "Could not acquire timestamp");
        m_stampTimer.Set(100ms);
      }
      else
      {
        // check if frameposition is valid and nano timer less than 50 ms outdated
        if (m_timestamp.get_framePosition() > 0 &&
            (CurrentHostCounter() - m_timestamp.get_nanoTime()) < 50 * 1000 * 1000)
          m_stampTimer.Set(1000ms);