Multimedia-Tunneling ermöglicht komprimierte Videodaten für das Tunneling durch eine Hardware Videodecoder direkt an ein Display übertragen, ohne durch App-Code oder Android-Framework-Code Der gerätespezifische Code unterhalb des Android-Stacks bestimmt, welche Videoframes wann an den Bildschirm gesendet werden, Vergleichen der Zeitstempel der Präsentation des Videoframes mit einem der folgenden Werte Arten der internen Uhr:
Für die On-Demand-Videowiedergabe unter Android 5 oder höher muss
AudioTrack
Mit Zeitstempeln der Audiopräsentation synchronisierte Uhr Bestanden durch die AppFür die Wiedergabe von Liveübertragungen unter Android 11 oder höher eine Programmreferenzuhr oder Systemzeituhr (STC), die von einem Tuner
Hintergrund
Herkömmliche Videowiedergabe auf Android benachrichtigt
wenn ein komprimierter Videoframe decodiert wurde. Die App
Releases
Der decodierte Videoframe wird zur Anzeige übertragen, damit er mit derselben Systemuhr gerendert wird.
als entsprechenden Audioframe,
Bisherige Daten abrufen
AudioTimestamps
um das richtige Timing zu berechnen.
Da bei der getunnelten Videowiedergabe der App-Code umgangen und die Anzahl der Prozesse, die auf das Video reagieren, können ein effizienteres je nach OEM-Implementierung. Außerdem können Sie damit genauere Videos liefern, Kadenz und Synchronisierung mit der ausgewählten Uhr (PRC, STC oder Audio), indem die Zeitprobleme, die durch eine potenzielle Verzerrung zwischen dem Timing von Android zum Rendern von Videos sowie das Timing echter vSync-Hardware. Sie können jedoch Tunneling kann auch die Unterstützung von GPU-Effekten wie Unkenntlich machen abgerundete Ecken in Bild-im-Bild-Fenstern (BiB), da der Zwischenspeicher den Android-Grafikstapel umgehen.
Das folgende Diagramm zeigt, wie Tunneling die Videowiedergabe vereinfacht.
Abbildung 1: Vergleich zwischen herkömmlicher und getunnelter Videowiedergabe
Für App-Entwickler
Die meisten App-Entwickler integrieren müssen Sie in den meisten Fällen lediglich für die getunnelte Wiedergabe. Zur Low-Level-Implementierung eines getunnelten Videos Player verwenden, folgen Sie der Anleitung unten.
On-Demand-Videowiedergabe unter Android 5 oder höher:
Erstellen Sie eine
SurfaceView
-Instanz.Erstellen Sie eine
audioSessionId
-Instanz.Instanzen
AudioTrack
undMediaCodec
mit demaudioSessionId
erstellen die in Schritt 2 erstellt wurde.Audiodaten mit dem Präsentationszeitstempel für
AudioTrack
in die Warteschlange stellen: ersten Audioframe in den Audiodaten.
Für die Wiedergabe von Liveübertragungen unter Android 11 oder höher:
Erstellen Sie eine
SurfaceView
-Instanz.Rufen Sie eine
avSyncHwId
-Instanz ausTuner
ab.Instanzen
AudioTrack
undMediaCodec
mit der InstanzavSyncHwId
erstellen die in Schritt 2 erstellt wurden.
Der API-Aufruffluss wird in den folgenden Code-Snippets gezeigt:
aab.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE);
// configure for audio clock sync
aab.setFlag(AudioAttributes.FLAG_HW_AV_SYNC);
// or, for tuner clock sync (Android 11 or higher)
new tunerConfig = TunerConfiguration(0, avSyncId);
aab.setTunerConfiguration(tunerConfig);
if (codecName == null) {
return FAILURE;
}
// configure for audio clock sync
mf.setInteger(MediaFormat.KEY_AUDIO_SESSION_ID, audioSessionId);
// or, for tuner clock sync (Android 11 or higher)
mf.setInteger(MediaFormat.KEY_HARDWARE_AV_SYNC_ID, avSyncId);
Verhalten der On-Demand-Videowiedergabe
Weil die getunnelte On-Demand-Videowiedergabe implizit an AudioTrack
gebunden ist
kann das Verhalten der getunnelten Videowiedergabe
der Audiowiedergabe.
Auf den meisten Geräten wird ein Videoframe standardmäßig erst gerendert, wenn Audio wiedergegeben wird die Wiedergabe beginnt. Die App muss jedoch möglicherweise einen Videoframe rendern, bevor Starten der Audiowiedergabe, z. B. um dem Nutzer das aktuelle Video zu zeigen Position beim Suchen angezeigt.
Um zu signalisieren, dass der erste Videoframe in der Warteschlange gerendert werden soll, sobald wenn es decodiert wird,
PARAMETER_KEY_TUNNEL_PEEK
auf1
setzen. Wenn komprimierte Videoframes in der Warteschlange neu angeordnet werden (zum Beispiel wenn B-Frames vorhanden sind, bedeutet dies, dass der erste angezeigte Videoframe immer ein iFrameWenn Sie nicht möchten, dass der erste Frame aus der Warteschlange bis zum Wiedergabe beginnt, setze diesen Parameter auf
0
.Wenn dieser Parameter nicht festgelegt ist, bestimmt der OEM das Verhalten für das Gerät.
Wenn
AudioTrack
keine Audiodaten erhält und die Zwischenspeicher leer sind (Audiounterschreitung), die Videowiedergabe wird angehalten, bis weitere Audiodaten geschrieben wurden. weil die Audiouhr nicht mehr weiterläuft.Während der Wiedergabe können Unterbrechungen, die durch die App nicht korrigiert werden können, in die Zeitstempel der Audiopräsentation. In diesem Fall korrigiert der OEM negative Lücken, indem der aktuelle Video-Frame verzögert wird, und positive Lücken, indem oder stille Audioframes einzufügen (je nach OEM Implementierung). Die Frame-Position
AudioTimestamp
erhöht sich für stille Audioframes eingefügt.
Für Gerätehersteller
Konfiguration
OEMs sollten einen separaten Videodecoder erstellen, um eine getunnelte Videowiedergabe zu unterstützen.
Dieser Decoder sollte bekannt geben, dass er im
media_codecs.xml
-Datei:
<Feature name="tunneled-playback" required="true"/>
Wenn eine getunnelte MediaCodec
-Instanz mit einer Audiositzungs-ID konfiguriert ist,
fragt AudioFlinger
für diese HW_AV_SYNC
-ID ab:
if (entry.getKey().equals(MediaFormat.KEY_AUDIO_SESSION_ID)) {
int sessionId = 0;
try {
sessionId = (Integer)entry.getValue();
}
catch (Exception e) {
throw new IllegalArgumentException("Wrong Session ID Parameter!");
}
keys[i] = "audio-hw-sync";
values[i] = AudioSystem.getAudioHwSyncForSession(sessionId);
}
Bei dieser Abfrage
AudioFlinger
ruft die HW_AV_SYNC
-ID ab
vom primären Audiogerät erstellt und intern mit dem
Sitzungs-ID:
audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
char *reply = dev->get_parameters(dev, AUDIO_PARAMETER_HW_AV_SYNC);
AudioParameter param = AudioParameter(String8(reply));
int hwAVSyncId;
param.getInt(String8(AUDIO_PARAMETER_HW_AV_SYNC), hwAVSyncId);
Wenn bereits eine AudioTrack
-Instanz erstellt wurde, lautet die HW_AV_SYNC
-ID
die mit derselben Audiositzungs-ID an den Ausgabestream übergeben werden. Falls noch nicht
erstellt wurde, wird die HW_AV_SYNC
-ID während
AudioTrack
-Erstellung. Dies geschieht durch die Wiedergabe
Thread:
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
Die HW_AV_SYNC
-ID, ob sie einem Audioausgabestream oder einem
Tuner
-Konfiguration an die OMX- oder Codec2-Komponente übergeben wird,
Der OEM-Code kann den Codec mit dem entsprechenden Audioausgabestream oder
den Tuner-Stream.
Während der Komponentenkonfiguration sollte die OMX- oder Codec2-Komponente eine
Seitenband-Handle, mit dem der Codec mit einem Hardware-Composer verknüpft werden kann
HWC-Ebene. Wenn die App eine Oberfläche mit MediaCodec
verknüpft, wird dieses Seitenband
Handle wird über SurfaceFlinger
an HWC übergeben, wodurch die
Ebene als
sideband-Schicht.
err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
if (err != OK) {
ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", sidebandHandle, err);
return err;
}
HWC ist für den Empfang neuer Bildpuffer aus der Codec-Ausgabe am entsprechende Zeit, die entweder mit dem zugehörigen Audioausgabestream synchronisiert ist oder der Programmreferenzuhr des Tuner-Programms, wobei die Puffer mit dem aktuellen anderer Layers und die Anzeige des resultierenden Bildes. Das passiert und zwar unabhängig vom normalen Vorbereitungs- und Einstellzyklus. Anrufe vorbereiten und einrichten treten nur auf, wenn sich andere Schichten ändern oder wenn die Eigenschaften der Seitenbandschicht wie Position oder Größe.
Logo: OMX
Eine Tunneled-Decoder-Komponente sollte Folgendes unterstützen:
Erweiterte
OMX.google.android.index.configureVideoTunnelMode
festlegen Parameter, der dieConfigureVideoTunnelModeParams
-Struktur zur Übergabe in derHW_AV_SYNC
-ID, die dem Audioausgabegerät zugeordnet ist.Den Parameter
OMX_IndexConfigAndroidTunnelPeek
konfigurieren, der den Codec verwendet, um den ersten decodierten Videoframe unabhängig von ob die Audiowiedergabe gestartet wurde.Das Ereignis
OMX_EventOnFirstTunnelFrameReady
wird gesendet, wenn die erste getunnelte Videoframe wurde decodiert und kann gerendert werden.
Die AOSP-Implementierung konfiguriert den Tunnelmodus in
ACodec
bis
OMXNodeInstance
Dies wird im folgenden Code-Snippet gezeigt:
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.configureVideoTunnelMode");
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
ConfigureVideoTunnelModeParams tunnelParams;
InitOMXParams(&tunnelParams);
tunnelParams.nPortIndex = portIndex;
tunnelParams.bTunneled = tunneled;
tunnelParams.nAudioHwSync = audioHwSync;
err = OMX_SetParameter(mHandle, index, &tunnelParams);
err = OMX_GetParameter(mHandle, index, &tunnelParams);
sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
Wenn die Komponente diese Konfiguration unterstützt, sollte ein Seitenband zugewiesen werden.
Handle an diesen Codec und übergib ihn durch das pSidebandWindow
-Mitglied,
damit die HWC den zugehörigen Codec identifizieren kann. Wenn die Komponente nicht
diese Konfiguration unterstützen, sollte bTunneled
auf OMX_FALSE
festgelegt werden.
Codec2
Ab Android 11 unterstützt Codec2
die getunnelte Wiedergabe. Der Decoder
-Komponente sollte Folgendes unterstützen:
Konfigurieren von
C2PortTunneledModeTuning
, um den Tunnelmodus und Karten/Tickets imHW_AV_SYNC
, das entweder vom Audioausgabegerät oder vom die Tuner-Konfiguration.Abfrage von
C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE
zum Zuweisen und Abrufen des Seitenband-Handle für HWC.Verarbeitung von
C2_PARAMKEY_TUNNEL_HOLD_RENDER
, wenn sie an eineC2Work
angehängt ist, die weist den Codec an, den Abschluss der Arbeit zu decodieren und zu signalisieren, aber nicht zu rendern Ausgabepuffer, bis 1) der Codec später angewiesen wird, ihn zu rendern. oder 2) die Audiowiedergabe beginnt.Verarbeitung von
C2_PARAMKEY_TUNNEL_START_RENDER
, die den Codec anweist, den mit der KennzeichnungC2_PARAMKEY_TUNNEL_HOLD_RENDER
, auch wenn die Audiowiedergabe nicht gestartet wurde.debug.stagefright.ccodec_delayed_params
nicht konfiguriert lassen (empfohlen). Wenn legen Sie für die Konfigurationfalse
fest.
Die AOSP-Implementierung konfiguriert den Tunnelmodus in
CCodec
über C2PortTunnelModeTuning
, wie im folgenden Code-Snippet gezeigt:
if (msg->findInt32("audio-hw-sync", &tunneledPlayback->m.syncId[0])) {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::AUDIO_HW_SYNC;
} else if (msg->findInt32("hw-av-sync-id", &tunneledPlayback->m.syncId[0])) {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::HW_AV_SYNC;
} else {
tunneledPlayback->m.syncType =
C2PortTunneledModeTuning::Struct::sync_type_t::REALTIME;
tunneledPlayback->setFlexCount(0);
}
c2_status_t c2err = comp->config({ tunneledPlayback.get() }, C2_MAY_BLOCK,
failures);
std::vector<std::unique_ptr<C2Param>> params;
c2err = comp->query({}, {C2PortTunnelHandleTuning::output::PARAM_TYPE},
C2_DONT_BLOCK, ¶ms);
if (c2err == C2_OK && params.size() == 1u) {
C2PortTunnelHandleTuning::output *videoTunnelSideband =
C2PortTunnelHandleTuning::output::From(params[0].get());
return OK;
}
Wenn die Komponente diese Konfiguration unterstützt, sollte ein Seitenband zugewiesen werden.
an diesen Codec übergeben und über C2PortTunnelHandlingTuning
zurückgegeben,
damit die HWC den zugehörigen Codec identifizieren kann.
Audio-HAL
Bei der On-Demand-Videowiedergabe empfängt der Audio-HAL die Audiopräsentation. Zeitstempel in Übereinstimmung mit den Audiodaten im Big-Endian-Format in einem Header, der gefunden wurde zu Beginn jedes Blocks an Audiodaten, die die App schreibt:
struct TunnelModeSyncHeader {
// The 32-bit data to identify the sync header (0x55550002)
int32 syncWord;
// The size of the audio data following the sync header before the next sync
// header might be found.
int32 sizeInBytes;
// The presentation timestamp of the first audio sample following the sync
// header.
int64 presentationTimestamp;
// The number of bytes to skip after the beginning of the sync header to find the
// first audio sample (20 bytes for compressed audio, or larger for PCM, aligned
// to the channel count and sample size).
int32 offset;
}
Damit HWC Videoframes synchron mit den entsprechenden Audioframes rendern kann, Audio-HAL sollte den Synchronisierungs-Header parsen und den Präsentationszeitstempel verwenden, um die Wiedergabeuhr mit dem Audiorendering neu zu synchronisieren. Um neu zu synchronisieren, wenn wenn komprimierte Audio-Inhalte wiedergegeben werden, muss der Audio-HAL unter Umständen Metadaten parsen. in den komprimierten Audiodaten, um die Wiedergabedauer zu bestimmen.
Support pausieren
Android 5 oder niedriger bietet keine Unterstützung für Pausen. Sie können „Tunnel“ pausieren Wiedergabe nur bei geringer Qualität, aber der interne Puffer für das Video ist groß z. B. wenn die OMX-Komponente eine Sekunde lang Daten enthält, wird eine Pause gemacht, reagiert nicht.
Ab Android 5.1 unterstützt AudioFlinger
das Pausieren und Fortsetzen für den direkten Zugriff
(getunnelte) Audioausgaben. Wenn der HAL „Pause“ und „Resume“ implementiert, wird „Pause“ verfolgt
und Fortsetzen an den HAL weitergeleitet.
Die Aufrufsequenz zum Anhalten, Leeren und Fortsetzen wird durch Ausführen der HAL-Aufrufe berücksichtigt im Wiedergabe-Thread (wie Auslagerung).
Implementierungsvorschläge
Audio-HAL
Bei Android 11 kann die Hardwaresynchronisierungs-ID von PCR oder STC für die A/V-Synchronisierung verwendet werden. der reine Videostream unterstützt wird.
Für Geräte mit Android 10 oder niedriger, die die getunnelte Videowiedergabe unterstützen, sollten
mindestens ein Audioausgabestreamprofil mit FLAG_HW_AV_SYNC
und
AUDIO_OUTPUT_FLAG_DIRECT
-Flags in der zugehörigen audio_policy.conf
-Datei. Diese Flags
werden verwendet, um die Systemuhr von der Audiozeit aus einzustellen.
Logo: OMX
Gerätehersteller sollten eine separate OMX-Komponente für getunnelte Videos haben. Wiedergabe (Hersteller können zusätzliche OMX-Komponenten für andere Audio- und Videowiedergabe, z. B. sichere Wiedergabe). Tunneled-Komponente sollte:
Geben Sie 0 Zwischenspeicher (
nBufferCountMin
,nBufferCountActual
) für die Ausgabe an Port.Implementieren Sie die Erweiterung
OMX.google.android.index.prepareForAdaptivePlayback setParameter
.Geben Sie die Funktionen in der Datei
media_codecs.xml
an und deklarieren Sie die getunnelte Wiedergabe. Außerdem sollten etwaige Einschränkungen bei Frames verdeutlicht werden. Größe, Ausrichtung oder Bitrate. Hier ein Beispiel:<MediaCodec name="OMX.OEM_NAME.VIDEO.DECODER.AVC.tunneled" type="video/avc" > <Feature name="adaptive-playback" /> <Feature name="tunneled-playback" required=”true” /> <Limit name="size" min="32x32" max="3840x2160" /> <Limit name="alignment" value="2x2" /> <Limit name="bitrate" range="1-20000000" /> ... </MediaCodec>
Wenn für die Decodierung dieselbe OMX-Komponente und die nicht getunnelte Decodierung verwendet werden, sollte die getunnelte Wiedergabefunktion nicht erforderlich sein. Sowohl getunnelt als auch Decoder ohne Tunnel haben dann dieselben Funktionsbeschränkungen. Ein Beispiel: (siehe unten):
<MediaCodec name="OMX._OEM\_NAME_.VIDEO.DECODER.AVC" type="video/avc" >
<Feature name="adaptive-playback" />
<Feature name="tunneled-playback" />
<Limit name="size" min="32x32" max="3840x2160" />
<Limit name="alignment" value="2x2" />
<Limit name="bitrate" range="1-20000000" />
...
</MediaCodec>
Hardware-Komponisten (HWC)
Wenn eine Tunnelebene vorhanden ist (eine Ebene mit HWC_SIDEBAND
compositionType
)
ein Display ist, ist der sidebandStream
der Ebene der vom
OMX-Videokomponente.
Die HWC synchronisiert decodierte Videoframes (von der getunnelten OMX-Komponente) mit
Den verknüpften Audiotrack (mit der audio-hw-sync
-ID). Wenn ein neuer Videoframe
aktualisiert wird, setzt die HWC sie mit den aktuellen Inhalten aller Ebenen zusammen.
erhalten haben, und zeigt das resultierende Bild an.
Die Aufrufe zum Vorbereiten oder Festlegen erfolgen nur, wenn sich andere Ebenen ändern oder wenn
der Seitenband-Layer ändern, wie z. B. Position oder Größe.
Die folgende Abbildung zeigt die HWC, die mit der Hardware (oder dem Kernel oder Treiber)-Synchronisierer, um Videoframes (7b) mit der neuesten Komposition (7a) für die Anzeige zum richtigen Zeitpunkt, basierend auf den Audiodaten (7c).
Abbildung 2: HWC-Hardware- (oder Kernel- oder Treiber-)Synchronisierer