Design für reduzierte Latenz

Mit der Veröffentlichung von Android 4.1 wurden interne Framework-Änderungen für einen Audioausgabepfad mit niedrigerer Latenz eingeführt. Es gab nur geringfügige Änderungen an der öffentlichen Client API oder HAL API. In diesem Dokument wird das ursprüngliche Design beschrieben, das sich im Laufe der Zeit weiterentwickelt hat. Ein gutes Verständnis dieses Designs sollte Geräte-OEMs und SoC-Anbietern helfen, das Design richtig auf ihren jeweiligen Geräten und Chipsätzen zu implementieren. Dieser Artikel richtet sich nicht an Anwendungsentwickler.

Titel erstellen

Der Client kann Bit AUDIO_OUTPUT_FLAG_FAST optional im Parameter audio_output_flags_t des C++-Konstruktors von AudioTrack oder in AudioTrack::set() festlegen. Derzeit sind das nur die folgenden Kunden:

Die C++-Implementierung von AudioTrack prüft die AUDIO_OUTPUT_FLAG_FAST-Anfrage und kann sie optional auf Clientebene ablehnen. Wenn er sich dazu entschließt, die Anfrage weiterzuleiten, geschieht dies mit dem TRACK_FAST-Bit des track_flags_t-Parameters der IAudioTrack-Fabrikmethode IAudioFlinger::createTrack().

Der AudioFlinger-Audioserver prüft die TRACK_FAST-Anfrage und kann sie optional auf Serverebene ablehnen. Über Bit CBLK_FAST des Shared-Memory-Kontrollblocks informiert er den Client darüber, ob die Anfrage akzeptiert wurde oder nicht.

Zu den Faktoren, die sich auf die Entscheidung auswirken, gehören:

  • Vorhandensein eines schnellen Mixer-Threads für diese Ausgabe (siehe unten)
  • Abtastrate des Tracks
  • Vorhandensein eines Client-Threads zum Ausführen von Callback-Handlern für diesen Track
  • Puffergröße des Titels
  • Verfügbare Fast-Track-Plätze (siehe unten)

Wenn der Antrag des Kunden akzeptiert wurde, wird er als „Fast Track“ bezeichnet. Andernfalls wird er als „normaler Track“ bezeichnet.

Mixer-Threads

Wenn AudioFlinger einen normalen Mixer-Thread erstellt, entscheidet es, ob auch ein schneller Mixer-Thread erstellt werden soll. Sowohl der normale Mixer als auch der schnelle Mixer sind nicht einem bestimmten Titel, sondern mehreren Titeln zugeordnet. Es gibt immer einen normalen Mixer-Thread. Der schnelle Mixer-Thread, falls vorhanden, ist dem normalen Mixer-Thread untergeordnet und wird von diesem gesteuert.

Schnellmixer

Funktionen

Der schnelle Mixer-Thread bietet folgende Funktionen:

  • Mischung des Submixes des normalen Mixers und bis zu sieben Client-Schnelltracks
  • Dämpfung pro Titel

Ausgelassene Funktionen:

  • Umwandlung der Abtastrate pro Titel
  • Effekte pro Titel
  • Effekte pro Mix

Punkt

Der schnelle Mixer wird regelmäßig ausgeführt, mit einem empfohlenen Intervall von zwei bis drei Millisekunden (ms) oder einem etwas längeren Intervall von fünf ms, falls dies für die Planungsstabilität erforderlich ist. Diese Zahl wurde so gewählt, dass die Gesamtlatenz unter Berücksichtigung der gesamten Pufferpipeline etwa 10 ms beträgt. Kleinere Werte sind möglich, können aber je nach Vorhersagbarkeit der CPU-Planung zu einem erhöhten Stromverbrauch und zu einer erhöhten Wahrscheinlichkeit von Störungen führen. Größere Werte sind möglich, bis zu 20 ms, führen aber zu einer höheren Gesamtlatenz und sollten daher vermieden werden.

Planung

Der schnelle Mixer wird mit einer erhöhten SCHED_FIFO-Priorität ausgeführt. Sie benötigt nur sehr wenig CPU-Zeit, muss aber häufig und mit wenig Planungsjitter ausgeführt werden. Der Jitter gibt die Abweichung bei der Zykluszeit an: Er ist die Differenz zwischen der tatsächlichen und der erwarteten Zykluszeit. Wenn die Wiedergabe zu spät beginnt, kommt es zu Störungen durch Unterlauf. Wenn die Ausführung zu früh erfolgt, kommt es zu Störungen, da Daten aus einem schnellen Track abgerufen werden, bevor der Track Daten bereitgestellt hat.

Blockierungen

Idealerweise blockiert der schnelle Mixer-Thread nur bei HALwrite(). Andere Blockierungen im schnellen Mixer gelten als Fehler. Insbesondere werden Mutexe vermieden. Stattdessen werden nicht blockierende Algorithmen (auch als sperrenfreie Algorithmen bezeichnet) verwendet. Weitere Informationen zu diesem Thema finden Sie unter Prioritätsinversion vermeiden.

Beziehung zu anderen Komponenten

Der schnelle Mixer hat wenig direkten Kontakt mit den Kunden. Insbesondere werden keine Vorgänge auf Binderebene erkannt, aber es wird auf den Steuerblock für den gemeinsamen Arbeitsspeicher des Clients zugegriffen.

Der schnelle Mixer empfängt Befehle vom normalen Mixer über eine Statuswarteschlange.

Abgesehen vom Abrufen von Titeldaten erfolgt die Interaktion mit Kunden über den normalen Mixer.

Der primäre Sink des schnellen Mixers ist die Audio-HAL.

Normaler Mixer

Funktionen

Alle Funktionen sind aktiviert:

  • Bis zu 32 Tracks
  • Dämpfung pro Titel
  • Umwandlung der Abtastrate pro Titel
  • Effektverarbeitung

Punkt

Die Periode wird als erstes ganzzahliges Vielfaches der Fast-Mixer-Periode berechnet, das mindestens 20 ms beträgt.

Planung

Der normale Mixer wird mit erhöhter SCHED_OTHER-Priorität ausgeführt.

Blockierungen

Der normale Mixer darf blockieren und tut dies häufig an verschiedenen Mutexes sowie an einer blockierenden Pipe, um seinen Submix zu schreiben.

Beziehung zu anderen Komponenten

Der normale Mixer interagiert intensiv mit der Außenwelt, einschließlich Binder-Threads, Audio Policy Manager, Fast Mixer-Thread und Client-Tracks.

Der Sink des normalen Mixers ist eine blockierende Pipe zum Track 0 des schnellen Mixers.

Flaggen

AUDIO_OUTPUT_FLAG_FAST Bit ist ein Hinweis. Es kann nicht garantiert werden, dass der Antrag erfüllt wird.

AUDIO_OUTPUT_FLAG_FAST ist ein Konzept auf Kundenebene. Er wird nicht auf dem Server angezeigt.

TRACK_FAST ist ein Client-zu-Server-Konzept.