2014-03-24 8 views
5

Android bietet eine Möglichkeit, die unterstützten Kodierungsprofile abzufragen. Aber wenn ich einen Encoder einrichte, kann ich das gewünschte Profil nicht finden.Festlegen des AVC/H.264-Profils beim Kodieren von Videos in Android mithilfe der MediaCodec-API

Finding unterstützt Profil/Level Paare

Mit dem MediaCodec API in Android können Sie getCodecInfo() rufen, wenn Sie einen Encoder Komponente gewählt haben. Dies gibt ein MediaCodecInfo Objekt zurück, das Details über die verwendete Codec-Komponente bereitstellt. getCapabilitiesForType() gibt ein CodecCapabilities Objekt zurück, das detailliert beschreibt, zu was der Codec fähig ist. Dieser enthält ein Array von CodecProfileLevel, in dem die unterstützten Profile und Ebenen aufgeführt sind, die unterstützt werden.

um das Profil einzustellen Versuch

Ich kann kein Feld finden Sie im Profil für MedieCodec oder für die MediaFormat einzustellen.

Es gibt eine KEY_AAC_PROFILE für MediaFormat, aber in der Referenz heißt es ausdrücklich, dies ist nur für aac Audio.

In MediaCodec gibt es eine Möglichkeit, einen Bundle von zusätzlichen Parametern an den Codec unter Verwendung setParameters() zu übergeben. Dies sieht so aus, als hätte es keine generische Dokumentation, und die Parameter, die akzeptiert werden, werden zwischen Codecs (verschiedene Geräte) unterschiedlich sein.

Hintergrund

Profile eine Reihe von Codierungsmerkmale angeben, zu verwenden. Einfache Profile sind weniger rechenintensiv, opfern jedoch im Allgemeinen die Qualität für eine gegebene Bitrate. Die Ebenen geben die maximale Auflösung/Bitrate an, die für ein bestimmtes Profil unterstützt wird. Ich habe erwartet, dass die Pegel normalerweise mit der Decodierfähigkeit verbunden sind, aber da es einen Hardware-Encoder beschreibt, der in Echtzeit laufen muss, ist es für mich sinnvoll, eine maximale Einstellung zu haben.

META: (. Ich hatte ursprünglich viel mehr Links zu jeder Klasse + Funktion, die ich erwähnte, aber ich hatte sie zu entfernen, weil ich noch nicht die rep muß mehr als 2 Links posten)

Antwort

3

Es ist keine explizite Profilauswahl in der MediaCodec-API. Codec wählt ein eigenes Profil aus. Es wird auch eine Ebene basierend auf der Eingangsbreite/-höhe und den Bildfrequenznummern ausgewählt, aber es kann eine Ebene auswählen, die höher ist als das Minimum, das für die Konfiguration erforderlich ist.

Sie können den Encoder-Codec für die unterstützten Ebenen abfragen, um zu sehen, welche Profile generiert werden, aber Sie können keine bevorzugte auswählen. Höchstwahrscheinlich wählt der Codec das höchste Profil, das er für das gegebene Level verarbeiten kann, aber dafür gibt es keine Garantie.

3

Für Android Kitkat-Geräte können wir das gewünschte AVC-Profil und -Ebene gemäß dem Code-Schnipsel unten im Medienformat einstellen (legt die Grundlinie mit Stufe 1.3 fest). Bitte stellen Sie dies vor dem Start von MediaCodec ein.

+0

wenn ich Wählen Sie AVCProfileHigh, welches Level soll ich wählen? – dragonfly

0

Profil- und Level-Hinweise können von einem bestimmten AVC-Encoder ignoriert werden.

Um absolut sicher zu sein, welches Profil und welche Ebene der AVC-Encoder ausgewählt hat, können Sie das SPS in Echtzeit von seinem MediaFormat abfragen (wie beim ersten Formatwechsel).

Siehe Abschnitt 7 der spec.

Dieses Plakat zeigt das Profil und die Ebene von diesen base64-Strings (bitte upvote ihn!) Ziehen:

Can profile-level-id and sprop-parameter-sets be extracted from an RTP stream?

Hier sind die Base64 codiert SPS und PPS:

... 
mIndex = mMediaEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT); 

// First buffer encoded is the NAL frame metadata 
if (mIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
{ 
    Log.i("PPS: "+getParameterSetAsString(mMediaEncoder, "csd-0"); 
    Log.i("SPS: "+getParameterSetAsString(mMediaEncoder, "csd-1"); 
} 
... 

private String getParameterSetAsString(MediaCodec encoder, String csd) 
{ 
    MediaFormat mMediaFormat = encoder.getOutputFormat(); 
    ByteBuffer ps = mMediaFormat.getByteBuffer(csd); 

    // The actual SPS and PPS byte codes 
    byte[] mPS = new byte[ps.capacity()-4]; 
    ps.position(4); 
    ps.get(mPS,0,mPS.length); 

    //Covert to String 
    return Base64.encodeToString(mPS, 0, mPS.length, Base64.NO_WRAP); 
}