• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

frameworks/av


Commit MetaInfo

Revisãoc4e90131d8cdb2bef34bc1edea784efe36bd3c86 (tree)
Hora2019-11-12 02:10:42
AutorKevin Rocard <krocard@goog...>
CommiterEric Laurent

Mensagem de Log

Fix secondary output under&over run

There were three issues with the implementation
of Audio Playback Capture patches on secondary outputs.

1) Patch tracks were always forced to be ready, even if there were not
enough audio to be played. That led to playing partial buffers if the
source output had smaller (time wise) buffer than the secondary output.

This is fixed by avoiding setting CBLK_FORCEREADY on every buffer push
from the primary output thread.

2) After 1 is fixed, the patch tracks now behave like regular (non fast)
tracks. This means that the track only starts when it is full.
That leads to overrun on startup as the primary and secondary outputs
usually do not have the same write period.

What makes the issue worst is that Remote submix has a fixed buffer in bytes,
so its write period changes depending on sample rate contrary to the
primary HAL which pulls with fixed time periods (usually 20/40ms).

This patch solution is to introduce a ready threshold. The track will be
considered ready to be active if there are more than frames in its buffer.

To avoid changing previous latency behaviour except for APC,
legacy tracks have this threshold set to their buffer size and
non APC patch tracks have it set to 1, similar to setting
CBLK_FORCEREADY.

3) The patch track buffer size calculation of the patch track did not take
into account primary and secondary output could be of different sampling
rate.
This mean that the patch track buffer was usually too small as the
secondary output usually had smaller sampling rate (Live caption
requests 16kHz) than the track (music usually plays in 48kHz).
This made the two problems even worst.

This was easily fixed by scaling the buffer size with each side sample rate.

Bug: 136691300
Test: play audio

adb shell audiorecorder --target /data/file1.raw
# Check that the recorded file has no underrun

Change-Id: Ib2846b2827afd1b953d4a25acb18c7cadf57cd3e
Signed-off-by: Kevin Rocard <krocard@google.com>
(cherry picked from commit 01c7d9ee1b170a516e20b9c7aad3f9d1db982c55)

Mudança Sumário

Diff

--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -810,7 +810,33 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
810810 continue;
811811 }
812812
813- size_t frameCount = std::lcm(thread->frameCount(), secondaryThread->frameCount());
813+ size_t sourceFrameCount = thread->frameCount() * output.sampleRate
814+ / thread->sampleRate();
815+ size_t sinkFrameCount = secondaryThread->frameCount() * output.sampleRate
816+ / secondaryThread->sampleRate();
817+ // If the secondary output has just been opened, the first secondaryThread write
818+ // will not block as it will fill the empty startup buffer of the HAL,
819+ // so a second sink buffer needs to be ready for the immediate next blocking write.
820+ // Additionally, have a margin of one main thread buffer as the scheduling jitter
821+ // can reorder the writes (eg if thread A&B have the same write intervale,
822+ // the scheduler could schedule AB...BA)
823+ size_t frameCountToBeReady = 2 * sinkFrameCount + sourceFrameCount;
824+ // Total secondary output buffer must be at least as the read frames plus
825+ // the margin of a few buffers on both sides in case the
826+ // threads scheduling has some jitter.
827+ // That value should not impact latency as the secondary track is started before
828+ // its buffer is full, see frameCountToBeReady.
829+ size_t frameCount = frameCountToBeReady + 2 * (sourceFrameCount + sinkFrameCount);
830+ // The frameCount should also not be smaller than the secondary thread min frame
831+ // count
832+ size_t minFrameCount = AudioSystem::calculateMinFrameCount(
833+ [&] { Mutex::Autolock _l(secondaryThread->mLock);
834+ return secondaryThread->latency_l(); }(),
835+ secondaryThread->mNormalFrameCount,
836+ secondaryThread->mSampleRate,
837+ output.sampleRate,
838+ input.speed);
839+ frameCount = std::max(frameCount, minFrameCount);
814840
815841 using namespace std::chrono_literals;
816842 auto inChannelMask = audio_channel_mask_out_to_in(input.config.channel_mask);
@@ -843,7 +869,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
843869 patchRecord->buffer(),
844870 patchRecord->bufferSize(),
845871 outputFlags,
846- 0ns /* timeout */);
872+ 0ns /* timeout */,
873+ frameCountToBeReady);
847874 status = patchTrack->initCheck();
848875 if (status != NO_ERROR) {
849876 ALOGE("Secondary output patchTrack init failed: %d", status);
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -74,7 +74,10 @@ public:
7474 uid_t uid,
7575 audio_output_flags_t flags,
7676 track_type type,
77- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
77+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
78+ /** default behaviour is to start when there are as many frames
79+ * ready as possible (aka. Buffer is full). */
80+ size_t frameCountToBeReady = SIZE_MAX);
7881 virtual ~Track();
7982 virtual status_t initCheck() const;
8083
@@ -263,6 +266,8 @@ protected:
263266 };
264267 sp<AudioVibrationController> mAudioVibrationController;
265268 sp<os::ExternalVibration> mExternalVibration;
269+ /** How many frames should be in the buffer before the track is considered ready */
270+ const size_t mFrameCountToBeReady;
266271
267272 private:
268273 void interceptBuffer(const AudioBufferProvider::Buffer& buffer);
@@ -384,7 +389,11 @@ public:
384389 void *buffer,
385390 size_t bufferSize,
386391 audio_output_flags_t flags,
387- const Timeout& timeout = {});
392+ const Timeout& timeout = {},
393+ size_t frameCountToBeReady = 1 /** Default behaviour is to start
394+ * as soon as possible to have
395+ * the lowest possible latency
396+ * even if it might glitch. */);
388397 virtual ~PatchTrack();
389398
390399 virtual status_t start(AudioSystem::sync_event_t event =
@@ -402,5 +411,4 @@ public:
402411
403412 private:
404413 void restartIfDisabled();
405-
406414 }; // end of PatchTrack
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -511,7 +511,8 @@ AudioFlinger::PlaybackThread::Track::Track(
511511 uid_t uid,
512512 audio_output_flags_t flags,
513513 track_type type,
514- audio_port_handle_t portId)
514+ audio_port_handle_t portId,
515+ size_t frameCountToBeReady)
515516 : TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
516517 (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
517518 (sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
@@ -530,6 +531,7 @@ AudioFlinger::PlaybackThread::Track::Track(
530531 mVolumeHandler(new media::VolumeHandler(sampleRate)),
531532 mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr, id(), streamType)),
532533 // mSinkTimestamp
534+ mFrameCountToBeReady(frameCountToBeReady),
533535 mFastIndex(-1),
534536 mCachedVolume(1.0),
535537 /* The track might not play immediately after being active, similarly as if its volume was 0.
@@ -837,7 +839,7 @@ void AudioFlinger::PlaybackThread::Track::interceptBuffer(
837839 auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
838840 using namespace std::chrono_literals;
839841 // Average is ~20us per track, this should virtually never be logged (Logging takes >200us)
840- ALOGD_IF(spent > 200us, "%s: took %lldus to intercept %zu tracks", __func__,
842+ ALOGD_IF(spent > 500us, "%s: took %lldus to intercept %zu tracks", __func__,
841843 spent.count(), mTeePatches.size());
842844 }
843845
@@ -910,8 +912,12 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
910912 return true;
911913 }
912914
913- if (framesReady() >= mServerProxy->getBufferSizeInFrames() ||
914- (mCblk->mFlags & CBLK_FORCEREADY)) {
915+ size_t bufferSizeInFrames = mServerProxy->getBufferSizeInFrames();
916+ size_t framesToBeReady = std::min(mFrameCountToBeReady, bufferSizeInFrames);
917+
918+ if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
919+ ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
920+ __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
915921 mFillingUpStatus = FS_FILLED;
916922 android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
917923 return true;
@@ -1413,6 +1419,7 @@ void AudioFlinger::PlaybackThread::Track::invalidate()
14131419
14141420 void AudioFlinger::PlaybackThread::Track::disable()
14151421 {
1422+ // TODO(b/142394888): the filling status should also be reset to filling
14161423 signalClientFlag(CBLK_DISABLED);
14171424 }
14181425
@@ -1790,12 +1797,14 @@ AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThr
17901797 void *buffer,
17911798 size_t bufferSize,
17921799 audio_output_flags_t flags,
1793- const Timeout& timeout)
1800+ const Timeout& timeout,
1801+ size_t frameCountToBeReady)
17941802 : Track(playbackThread, NULL, streamType,
17951803 audio_attributes_t{} /* currently unused for patch track */,
17961804 sampleRate, format, channelMask, frameCount,
17971805 buffer, bufferSize, nullptr /* sharedBuffer */,
1798- AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH),
1806+ AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH,
1807+ AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
17991808 PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
18001809 *playbackThread, timeout)
18011810 {
@@ -1869,7 +1878,6 @@ void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buff
18691878 {
18701879 mProxy->releaseBuffer(buffer);
18711880 restartIfDisabled();
1872- android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
18731881 }
18741882
18751883 void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()