I would say (2) is the right approach and will find us the root problem.

I am sure using getOutputLatency() will take care of the a/v sync variation on different devices but the question is whether you are doing the right amount of delay (will be device-independent now).

The (one_full_buffer + output_latency) can make sense if the link between AudioTrack and AudioFlinger runs in double buffer mode (most likely it will have to be so to maintain non-interrupt playback).

I am only puzzled by why that latency value doesn't work for us. Maybe the original logic in _GetBytesActualyPlayed is wrong but just happens to work fine to a certain degree so far.

If you don't care to find out why and only want a quick fix though, go ahead using the getOutputLatency().

fxd

On 09/22/2011 10:32 PM, Qiang Luo wrote:
Sheldon,

Stagefright audio player uses the latency to offset the playback time line:

mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
and then
int64_t AudioPlayer::getRealTimeUsLocked() const {
      return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
}

Equivalently, I use the latency to offset the u64BytesPlayed, which in
turn drives the limeline:

   UINT64 CAudioOutAndroid::_GetBytesActualyPlayed(void) const
   {
       /* Get current playback position in device DMA. */
-     return m_ulTotalWritten - (m_nBytesPending -
_BytesPlayedFromLastTimeStamp(GetTickCount()));
+    UINT64 u64BytesPlayed = m_ulTotalWritten - (m_nBytesPending -
_BytesPlayedFromLastTimeStamp(GetTickCount()));
+    if (u64BytesPlayed>  m_u64LantencyInBytes)
+    {
+        u64BytesPlayed -= m_u64LantencyInBytes;
+    }
+    return u64BytesPlayed;
   }
where
m_u64LantencyInBytes = (UINT64)( (float)ulLantency *
(float)m_unNumChannels * m_unSampleRate * m_uSampFrameSize / 1000.0 );

In helix case, if I use ulLantency=AudioSystem::getOutputLatency(), it
takes care of the a/v sync variation issue.  If I use
ulLantency=AudioSink::latency(), the audio is early even if I zero out
the decoder GetDelay().  We seem to have other places that may
compensate the buffer delay...

Here are the options
1) try to identify error in m_u64LantencyInBytes calculation and
2) try to identify any double counts of the same delay.  if we can't
find any error, then
3) keep my current fix or
4) use m_pAudioSink->latency() and modify the value with an empirical
factor(less then one) or
5) do not fix this a/v sync variation for now.

Qiang

On 9/22/2011 5:50 PM, Sheldon Fu wrote:
Well.  AudioTrack::latency() doesn't make the audio earlier. The way we
use it makes the audio earlier. Can you study how stagefright uses the
latency() call? I assume Google knows what they are doing.

fxd


On 09/22/2011 08:22 PM, Qiang Luo wrote:
Sheldon,

The GetDelay() counts for the silent priming samples at start.  It is
usually around 30ms.  Even if I set it to zero, the
AudioTrack::latency() can still make the audio early because of its long
delay value:
AudioTrack::latency() = 138 for on HTC evo
AudioTrack::latency() = 184 for Samsung Nexus S

Qiang

On 9/22/2011 4:49 PM, Sheldon Fu wrote:
That's why we should look into how stagefright player uses the latency()
call properly. There should be no reason we can not use it to get the
correct A/V sync if stagefright can. The renderer pushdown has nothing
to do with this.

     From the equation, it seems that the AudioTrack assume that there is at
least one full buffer of delay. I am not sure why it is so but unless we
can prove that this is a bug in AudioTrack, we should trust it.

Are we sure that the 'audio will be a little bit too early' can not be
caused by something else -- e.g. the GetDelay experimental value in the
AAC decoder itself is off?

fxd

On 09/22/2011 06:37 PM, Qiang Luo wrote:
Sheldon,

I can get the latency with m_pAudioSink->latency() which calls
AudioTrack::latency().  The issue here is that a part of the latency is
track dependent, ie:

AudioTrack_latency = audio_flinger_Latency + (1000*mFrameCount) /
sampleRate.

I only care about compensate for the "audio_flinger_Latency" because the
other part is already counted for by the render as pushdown I think.  If
I use the entire value of AudioTrack::latency(), the audio will be a
little bit too early.

Qiang

On 9/22/2011 2:51 PM, Sheldon Fu wrote:
I don't think we should call AudioSystem::getOutputLatency() directly.
AudioSystem is a service that should hide beyond the AudioTrack
completely. We should use AudioTrack::latency().

If you need an example of how to use AudioTrack::latency() correctly
(compensating for the addition of frame buffer duration in the latency
calculation e.g), have a look at the stagefright player
(libstagefright/AudioPlayer.cpp). We should closely follow how
stagefright does it for better chance of future compatibility.

fxd

On 09/22/2011 05:26 PM, Qiang Luo wrote:
Overview:
It is well known that there are wide variations in audio system latency
among android devices.  In this CR, we query for audio flinger latency
via AudioSystem::getOutputLatency() in the android audio device
initialization function and convert the delay to bytes.  We then
compensate for the driver delay in function
CAudioOutAndroid::_GetBytesActualyPlayed().  This takes care of the
device dependent a/v sync issues.

Suggested reviewer: Sheldon

Branches:
380, 310, head

Files modified:
/cvsroot/audio/device/platform/unix/audAndroid.cpp
/cvsroot/audio/device/pub/platform/unix/audAndroid.h

Please review attached diff.

Thanks,
Qiang
.

.

.

.

.

.



_______________________________________________
Audio-dev mailing list
Audio-dev@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/audio-dev

Reply via email to