WebRTC unter Android: Aktivieren der Hardware-Codierung auf mehreren GerÀten

FĂŒr Videoanrufe in Badoo verwenden wir den WebRTC-Standard und den H.264-Codec. Wenn Sie der Dokumentation glauben, sollte dieser Codec auf jedem Android-GerĂ€t seit Android 5.0 problemlos funktionieren. In der Praxis stellte sich jedoch heraus, dass nicht alles so war. In diesem Artikel werde ich ĂŒber die Funktionen zum Implementieren der Hardware-Codierung fĂŒr den H.264-Codec in WebRTC und darĂŒber sprechen, wie er auf mehr GerĂ€ten funktioniert.



Warum H.264?


Bei einer Verbindung ĂŒber WebRTC ĂŒbertragen alle an der Sitzung teilnehmenden GerĂ€te verschiedene Kommunikationsparameter, einschließlich Video- und Audio-Codecs. Wenn GerĂ€te mehrere Codecs unterstĂŒtzen (z. B. VP8 und H.264), werden zuerst PrioritĂ€tscodecs fĂŒr die Plattform aufgelistet. Diese Daten werden in der Abstimmungsphase in WebRTC verwendet. Danach verbleiben nur noch Codecs, die von allen GerĂ€ten unterstĂŒtzt werden. Ein Beispiel fĂŒr solche Daten mit EntschlĂŒsselung finden Sie in diesem Dokument .

Wenn bei Videoanrufen eines der GerĂ€te den H.264-Codec nicht unterstĂŒtzt, können beide GerĂ€te beispielsweise auf den VP8-Codec umschalten, der nicht von der Hardware-Implementierung auf dem GerĂ€t abhĂ€ngt. Unsere Anwendung ist jedoch auf einer Vielzahl von GerĂ€ten verfĂŒgbar, einschließlich Smartphones frĂŒherer Generationen. Daher wollten wir fĂŒr die Videokommunikation nach Möglichkeit die Hardware-Codierung verwenden: Sie entlastet den Prozessor und verbraucht den Akku nicht so stark, was fĂŒr veraltete GerĂ€te von entscheidender Bedeutung ist. Die UnterstĂŒtzung der H.264-Hardwarecodierung ist im Gegensatz zum gleichen VP8 auf einer großen Anzahl von GerĂ€ten implementiert .

H.264-UnterstĂŒtzung fĂŒr Android


Wenn Sie der Meinung sind, dass die Beschreibung der UnterstĂŒtzung fĂŒr Multimedia-Formate die Dekodierung des H.264-Basisprofils auf allen Android-GerĂ€ten und die Codierung - beginnend mit Android 3.0 - funktionieren sollte. In Badoo unterstĂŒtzen wir GerĂ€te ab Android 5.0, daher sollten wir keine Probleme haben. Aber es war nicht so einfach: Selbst in Gadgets mit der fĂŒnften Version fanden wir eine große Anzahl von Funktionen.

Womit kann es verbunden werden?

Wie Sie wissen, muss jeder Hersteller bei der Entwicklung eines neuen GerĂ€ts unter Android die Compatibility Test Suite bestehen. Es wird auf einem mit dem GerĂ€t verbundenen PC ausgefĂŒhrt. Die Ergebnisse mĂŒssen an Google gesendet werden, um zu bestĂ€tigen, dass das GerĂ€t die Anforderungen des Android-Betriebssystems der angegebenen Version erfĂŒllt. Erst danach kann das Gadget auf den Markt gebracht werden.

Wir sind an Multimedia-Tests in dieser Testsuite interessiert, insbesondere an Videokodierungs- und -decodierungstests. Ich habe beschlossen, die Tests EncodeDecodeTest , MediaCodecTest , DecoderTest und EncoderTest zu beenden , da sie seit 4.3 auf allen Android-Versionen vorhanden sind. Das Diagramm der Anzahl der Codezeilen in diesen Tests sieht folgendermaßen aus:



Vor Version 4.3 existierten die meisten dieser Tests einfach nicht und ihr signifikanter Anstieg fiel auf die Versionen 5 und 7. Daher können wir sagen, dass Google vor der Version Android 4.3 nicht die KonformitĂ€t der GerĂ€te mit den Spezifikationen fĂŒr das Codieren und Decodieren von Videos ĂŒberprĂŒft hat, sondern in der Version 5.0 hat diese PrĂŒfung erheblich verbessert.

Es scheint, dass dies darauf hinweist, dass ab Version 5.0 mit Codierung alles in Ordnung sein sollte. Aufgrund meiner frĂŒheren Erfahrungen mit dem Dekodieren von Streaming-Videos auf Android war ich mir jedoch sicher, dass dies nicht der Fall war. Es genĂŒgte, die Anzahl der Themen zum Thema Codierung in der Google-Gruppe " Diskussion-Webrtc" zu betrachten .

WebRTC-Quelldateien, die gemeinfrei sind, haben uns bei der Suche nach Fallstricken geholfen. Betrachten wir sie genauer.

H.264-UnterstĂŒtzung in WebRTC


Beginnen wir mit der HardwareVideoEncoderFactory .

Es gibt eine Methode mit dem sprechenden Namen isHardwareSupportedInCurrentSdkH264:

private boolean isHardwareSupportedInCurrentSdkH264(MediaCodecInfo info) {
  // First, H264 hardware might perform poorly on this model.
  if (H264_HW_EXCEPTION_MODELS.contains(Build.MODEL)) {
    return false;
  }
  String name = info.getName();
  // QCOM H264 encoder is supported in KITKAT or later.
  return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
      // Exynos H264 encoder is supported in LOLLIPOP or later.
      || (name.startsWith(EXYNOS_PREFIX)
             && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
}

Wie wir sehen können, wird die UnterstĂŒtzung fĂŒr die Hardware-Codierung unter Android nur fĂŒr Qualcomm- und Exynos-ChipsĂ€tze implementiert. Warum werden andere ChipsĂ€tze in der Standard-WebRTC-Implementierung nicht unterstĂŒtzt? Dies ist höchstwahrscheinlich auf die Besonderheiten der Implementierung von Hardware-Codec-Herstellern zurĂŒckzufĂŒhren. Und es ist oft möglich, diese Merkmale nur in der Produktion zu identifizieren, da es nicht immer möglich ist, bestimmte GerĂ€te zu finden.

Alle Codec-Beschreibungen auf dem GerĂ€t werden in der Datei media_codecs.xml gespeichert. Hier ist zum Beispiel diese Datei fĂŒr das Pixel XL und fĂŒr das HUAWEI P8 lite . Wenn Sie eine Liste von Codecs mit der Methode getCodecInfos () des MediaCodecList-Objekts erhalten, wird diese Datei analysiert - und die darin gespeicherten Codecs werden zurĂŒckgegeben. Dieser Vorgang und das korrekte AusfĂŒllen dieser Datei durch den Hersteller werden im CTS-Test behandelt.MediaCodecListTest , die auch aus 160 Zeilen Code in Android 4,3 bis 740 Linien in Android 10 erhöht

In Badoo, Ă€nderten wir den isHardwareSupportedInCurrentSdkH264 Methodencode, die „weiße“ Codec - Liste zurĂŒckgewiesen und es mit einer „schwarzen“ Liste des Programms ersetzen Codec PrĂ€fixen, sind aufgelistet in WebRTC:

static final String[] SOFTWARE_IMPLEMENTATION_PREFIXES = {"OMX.google.", "OMX.SEC."};

Sie können jedoch nicht einfach alle Codecs unterstĂŒtzen und implementieren, ohne auf die Funktionen der Hersteller zu achten. Anhand der Namen der Themen, die der Hardware-Codierung unter Android in der Diskussion-webrtc-Gruppe gewidmet sind , können wir verstehen, dass in diesem Fall definitiv Fehler auftreten werden. GrundsĂ€tzlich werden sie in der Codec-Konfigurationsphase angezeigt.

Codec-Konfigurationsoptionen


Die Initialisierung des Codecs fĂŒr die Codierung lautet wie folgt:

MediaCodec mediaCodec = createByCodecName(codecName);
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
format.setInteger(MediaFormat.KEY_BIT_RATE, targetBitrateBps);
format.setInteger(MediaFormat.KEY_BITRATE_MODE, VIDEO_ControlRateConstant);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
format.setInteger(MediaFormat.KEY_FRAME_RATE, targetFps);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec);
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

Bei einigen dieser Parameter kann es leicht zu Fehlern kommen, die beim Konfigurieren des Codecs eine Ausnahme auslösen und die Anwendung stören. Wenn Sie mit einem Codec arbeiten, mĂŒssen Sie möglicherweise die Bitrate in AbhĂ€ngigkeit von verschiedenen Faktoren anpassen, da der Codec selbst dies falsch macht. DafĂŒr ist in WebRTC die BaseBitrateAdjuster- Klasse verantwortlich , die zwei Nachkommen hat:


Dementsprechend mĂŒssen Sie fĂŒr jeden Codec Ihren eigenen Bitratenanpassungsmechanismus auswĂ€hlen. Lassen Sie uns die Funktionen zum Festlegen der Initialisierungsparameter fĂŒr Hardware-Codecs genauer betrachten.

Stream-Auflösung


Nachdem Sie das MediaCodecInfo- Objekt fĂŒr den Codec erhalten haben, können Sie den Codec genauer untersuchen, indem Sie seine Funktionen in der CodecCapabilities- Klasse abrufen . Anhand dieser Informationen können Sie herausfinden, ob der Codec die ausgewĂ€hlte Auflösung und Bildrate unterstĂŒtzt. Wenn diese Parameter unterstĂŒtzt werden, können sie sicher eingestellt werden.

Manchmal funktioniert diese Regel jedoch nicht. Wir sind mit der Tatsache konfrontiert, dass Codecs mit dem PrĂ€fix "OMX.MARVELL". falsch codiert, zeigt grĂŒne Streifen an den RĂ€ndern des Bildschirms, wenn die Auflösung des Streams von 4: 3 abweicht. Gleichzeitig behauptete der Codec selbst, dass die ausgewĂ€hlte Auflösung und Bildrate unterstĂŒtzt werden.

Bitratenmodus


Der Standardmodus fĂŒr alle Video-Codecs ist eine konstante Bitrate. Einmal mussten wir jedoch eine variable Bitrate verwenden:

format.setInteger(MediaFormat.KEY_BITRATE_MODE, VIDEO_ControlRateVariable);

Dies geschah auf einem Lenovo A1000-GerĂ€t mit dem Spreadtrum-Chipsatz (jetzt Unisoc), beginnend mit dem PrĂ€fix „OMX.sprd.“. Eine Suche im Internet fĂŒhrte uns zu einem sechs Jahre alten Beitrag ĂŒber Firefox OS, in dem dieses Problem und seine Lösung beschrieben werden.

Farbformat


Wenn Sie den Codec im Byte-Puffer-Modus verwenden, mĂŒssen Sie das richtige Format auswĂ€hlen. Dies erfolgt normalerweise mit einer Funktion der folgenden Form:

@Nullable
static Integer selectColorFormat(int[] supportedColorFormats, CodecCapabilities capabilities) {
  for (int supportedColorFormat : supportedColorFormats) {
    for (int codecColorFormat : capabilities.colorFormats) {
      if (codecColorFormat == supportedColorFormat) {
        return codecColorFormat;
      }
    }
  }
  return null;
}

Grob gesagt wird immer das erste der unterstĂŒtzten Farbformate ausgewĂ€hlt.

Bei HUAWEI-Codecs, die mit den PrĂ€fixen "OMX.IMG.TOPAZ.", "OMX.hisi" beginnen. und "OMX.k3." funktionierte nicht und nach langer Suche fanden wir eine Lösung: UnabhĂ€ngig davon, welches Format diese Codecs zurĂŒckgeben, mĂŒssen Sie das Format COLOR_FormatYUV420SemiPlanar verwenden . Der Thread hat uns geholfen, dies in einem chinesischen Forum herauszufinden .

Bitrate-Einstellung


Der Standard-WebRTC-Code enthÀlt Folgendes :

private BitrateAdjuster createBitrateAdjuster(VideoCodecMimeType type, String codecName) {
  if (codecName.startsWith(EXYNOS_PREFIX)) {
    if (type == VideoCodecMimeType.VP8) {
        // Exynos VP8 encoders need dynamic bitrate adjustment.
        return new DynamicBitrateAdjuster();
      } else {
        // Exynos VP9 and H264 encoders need framerate-based bitrate adjustment.
        return new FramerateBitrateAdjuster();
    }
  }
  // Other codecs don't need bitrate adjustment.
  return new BaseBitrateAdjuster();
}

Wie Sie diesem Code entnehmen können, ist die Bitratenanpassung fĂŒr alle ChipsĂ€tze außer Exynos deaktiviert. Dies gilt jedoch nur fĂŒr Qualcomm, da im Standardcode nur Exynos und Qualcomm unterstĂŒtzt werden. Beim Experimentieren mit verschiedenen Werten dieser Einstellung sowie beim Durchsuchen des Internets haben wir festgestellt, dass Codecs mit den PrĂ€fixen „OMX.MTK“ verwendet werden. es muss auch eingeschaltet sein. Dies ist auch fĂŒr HUAWEI-Codecs erforderlich, die mit dem PrĂ€fix "OMX.IMG.TOPAZ.", "OMX.hisi" beginnen. oder "OMX.k3.". Dies liegt an der Tatsache, dass diese Codecs keine Zeitstempel von Frames verwenden, um die Bitrate anzupassen, vorausgesetzt, dass alle Frames bei der Konfiguration des Codecs dieselbe Frequenz haben.

Abschließend werde ich eine Liste der Codecs geben, die wir fĂŒr GerĂ€te unter Android 5.0 und 5.1 erhalten haben. Sie waren fĂŒr uns vor allem deshalb von Interesse, weil sich die Situation bei neueren Android-Versionen verbessert und nicht standardmĂ€ĂŸige Codecs kleiner werden.

Dies ist in der folgenden Grafik zu sehen. Die logarithmische Skala zur besseren Darstellung seltener FĂ€lle.


Wie wir sehen können, hatten die meisten GerĂ€te Spreadtrum-, MediaTek-, HUAWEI- und MARVELL-ChipsĂ€tze. Daher haben unsere Änderungen dazu beigetragen, die Hardware-Codierung fĂŒr diese GerĂ€te zu ermöglichen.

Ergebnis


Obwohl wir davon ausgegangen sind, dass einige GerĂ€te Probleme mit H.264 haben wĂŒrden, konnte uns Android erneut ĂŒberraschen. Wie aus den Badoo-Benutzerstatistiken hervorgeht, befinden sich 2014-2016 noch einige GerĂ€te in den HĂ€nden der Benutzer, die sie nicht aktualisieren möchten oder können. Und obwohl die Situation mit der Veröffentlichung von Android-Updates fĂŒr neue GerĂ€te bereits viel besser ist als vor einigen Jahren, nimmt der Anteil der Gadgets der vorherigen Generation nur langsam ab und muss noch einige Zeit beibehalten werden.

Jetzt wird WebRTC aufgrund seiner Verwendung im Stadia-Projekt von Google aktiv entwickelt (hier das Video)mit Details zu diesem Thema), so dass es immer besser wird und höchstwahrscheinlich zum Standard fĂŒr die Implementierung von Videokommunikation wird. Ich hoffe, dass dieser Artikel Ihnen hilft, die Funktionen der Arbeit mit H.264 in WebRTC zu verstehen und in Ihren Projekten zu verwenden.

All Articles