Multimedya tünelleme

Multimedya tünellemesi, sıkıştırılmış video verilerinin bir donanım aracılığıyla tünellenmesine olanak tanır video kod çözücüyü uygulama kodu tarafından işlenmeden veya doğrudan bir ekrana Android çerçeve kodu. Android yığınının altındaki cihaza özel kod Hangi video karelerinin ekrana gönderileceğini ve bunların ne zaman gönderileceğini belirler video karesi sunu zaman damgalarını aşağıdakilerden biriyle karşılaştırarak iç saat türleri:

  • Android 5 veya sonraki sürümlerde isteğe bağlı video oynatma için AudioTrack saat sesli sunu zaman damgalarıyla senkronize edildi geçti uygulama tarafından

  • Android 11 veya sonraki sürümlerde canlı yayın oynatma için program referans saati (PCR) veya sistem saati (STC) kanal tarayıcı

Arka plan

Android'de geleneksel video oynatma için bildirim alır Sıkıştırılmış bir video karesinin kodu çözüldüğünde uygulama. Ardından, uygulama sürümler kodu çözülmüş video karesini, aynı sistem saatinde oluşturulacak şekilde ekrana konuşma süresini seçerek geçmiş alma AudioTimestamps doğru zamanlamayı hesaplamak için örneklerden yararlanırız.

Tünelli video oynatma, uygulama kodunu atlayıp işleme koymazsanız, videonun daha etkili bir şekilde oluşturulması için farklılık gösterebilir. Ayrıca daha doğru videolar sunabilir ritmi ve senkronizasyonu ayarlayarak, her zaman Android'in zamanlaması arasında olası bir sapma nedeniyle zamanlama sorunları istekleri ve gerçek donanım vsync'lerinin zamanlamasını kontrol edin. Ancak, tünel kullanımı, trafik izleme gibi GPU efektlerine yönelik desteği de bulanıklaştırma pencere içinde pencere (PiP) pencerelerinde yuvarlatılmış köşeler veya yuvarlatılmış köşeler olduğundan Android grafik grubunu atla.

Aşağıdaki şemada, tünellemenin video oynatma sürecini nasıl basitleştirdiği gösterilmektedir.

gelenek ve tünel modlarının karşılaştırması

Şekil 1. Geleneksel ve tünelli video oynatma süreçlerinin karşılaştırılması

Uygulama geliştiriciler için

Çoğu uygulama geliştirici, oynatmak için bir kitaplıkla entegre olduğundan çoğu durumda, uygulama sürecinin tamamlanması için kitaplığını kullanabilirsiniz. Tünelli videonun alt düzey uygulaması için oynatıcıda kullanmak için aşağıdaki talimatları uygulayın.

Android 5 veya sonraki sürümlerde isteğe bağlı video oynatma için:

  1. SurfaceView örneği oluşturun.

  2. audioSessionId örneği oluşturun.

  3. audioSessionId ile AudioTrack ve MediaCodec örnekleri oluşturun örneği oluşturulur.

  4. Ses verilerini AudioTrack için sunu zaman damgasıyla ses verilerindeki ilk ses karesi.

Android 11 veya sonraki sürümlerde canlı yayın oynatma için:

  1. SurfaceView örneği oluşturun.

  2. Tuner sitesinden bir avSyncHwId örneği alın.

  3. avSyncHwId örneğiyle AudioTrack ve MediaCodec örnekleri oluşturma otomatik olarak oluşturulur.

API çağrısı akışı aşağıdaki kod snippet'lerinde gösterilmektedir:

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);

İsteğe bağlı video oynatma davranışı

Tünel ile seç-izle video oynatma özelliği AudioTrack ile dolaylı olarak bağlantılı olduğu için veya tünelle video oynatmanın davranışı mevcut.

  • Çoğu cihazda varsayılan olarak sese kadar video karesi oluşturulmaz oynatma başlar. Ancak, uygulamanın video karesi oluşturmadan önce ses çalmayı başlatma (örneğin, kullanıcıya mevcut videoyu göstermek için) konumunu izleyebilirsiniz.

    • Sıraya alınan ilk video karesinin en kısa sürede oluşturulması gerektiğini belirtmek için kodu çözülmüşse PARAMETER_KEY_TUNNEL_PEEK parametresini 1 olarak ayarlayın. Sıkıştırılmış video kareleri sırada yeniden sıralandığında (örneğin, B-kareler varsa, bu, gösterilen ilk video karesinin her zaman I-çerçeve.

    • Sese kadar sıraya alınan ilk video karesinin oluşturulmasını istemiyorsanız oynatma başladığında bu parametreyi 0 olarak ayarlayın.

    • Bu parametre ayarlanmazsa cihazın davranışını OEM belirler.

  • Ses verileri AudioTrack adlı cihaza sağlanmadığında ve arabellekler boş olduğunda (ses az ses), daha fazla ses verisi yazılana kadar video oynatma durur çünkü ses saati artık ileri sürmüyor.

  • Oynatma sırasında, uygulamanın düzeltemeyeceği kesintiler şurada görünebilir: ses sunumu zaman damgalarını kapsıyor. Böyle bir durumda OEM, negatif anahtar kelimeleri düzeltir durmadan oluşan mevcut video karesini ve videonun sonlarına doğru video karesini durdurarak video kareleri ekleme veya sessiz ses kareleri ekleme (OEM'ye bağlı olarak) bakın). AudioTimestamp kare konumu sessiz ses kareleri eklendi.

Cihaz üreticileri için

Yapılandırma

OEM'ler, tünelli video oynatmayı desteklemek için ayrı bir video kod çözücü oluşturmalıdır. Bu kod çözücü, media_codecs.xml dosyası:

<Feature name="tunneled-playback" required="true"/>

Tünelli MediaCodec örneği, ses oturum kimliğiyle yapılandırıldığında bu HW_AV_SYNC kimliği için AudioFlinger sorgusu:

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);
}

Bu sorgu sırasında AudioFlinger, HW_AV_SYNC kimliğini alır birincil ses cihazından çıkarır ve bunu dahili olarak sesle ilişkilendirir oturum kimliği:

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);

AudioTrack örneği oluşturulmuşsa HW_AV_SYNC kimliği aynı ses oturum kimliğiyle çıkış akışına iletilir. Görmediyse oluşturulursa HW_AV_SYNC kimliği, sırasında çıkış akışına iletilir AudioTrack oluşturuldu. Bu işlem, oynatma tarafından ileti dizisi:

mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);

HW_AV_SYNC kimliği (ses çıkış akışına karşılık gelir veya Tuner yapılandırması, OMX veya Codec2 bileşenine aktarılır. Böylece, OEM kodu, codec'i ilgili ses çıkış akışıyla ilişkilendirebilir veya akarsulara ulaşabilirsiniz.

Bileşen yapılandırması sırasında OMX veya Codec2 bileşeni, codec'i Donanım Oluşturucu ile ilişkilendirmek için kullanılabilecek yan bant işleyici (HWC) katmanını kapsayabilir. Uygulama bir yüzeyi MediaCodec ile ilişkilendirdiğinde, bu yan bant herkese açık kullanıcı adı, SurfaceFlinger aracılığıyla HWC'ye geçirilir ve bu işlem katmanını yan bant katmanını kullanın.

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, ya da ses çıkışı akışıyla senkronize edilmelidir. tarayıcı programı referans saatine göre, tamponları mevcut ve sonuçta elde edilen resmi görüntüleyebilirsiniz. Bu durum normal hazırlama ve ayarlama döngüsünden bağımsızdır. Görüşmeleri hazırlama ve belirleme yalnızca diğer katmanlar değiştiğinde veya yan bant katmanının özellikleri değiştiğinde ortaya çıkar (konum veya boyut gibi) değişikliğine neden olabilir.

OMX

Tünelli kod çözücü bileşeni aşağıdakileri desteklemelidir:

  • Genişletilmiş OMX.google.android.index.configureVideoTunnelMode ayarlanıyor parametresini içeren bir ConfigureVideoTunnelModeParams ses çıkış cihazıyla ilişkilendirilen HW_AV_SYNC kimliğinde.

  • Şuna bildiren OMX_IndexConfigAndroidTunnelPeek parametresini yapılandırmak: ilk kodu çözülmüş video karesini oluşturmaya veya oluşturmamaya başlatılıp başlatılmadığı anlamına gelir.

  • İlk tünel protokolü alındığında OMX_EventOnFirstTunnelFrameReady etkinliği gönderiliyor video karesinin kodu çözüldü ve oluşturulmaya hazır.

AOSP uygulaması, tünel modunu ACodec - OMXNodeInstance aşağıdaki kod snippet'inde gösterildiği gibidir:

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;

Bileşen bu yapılandırmayı destekliyorsa bir yan bant ayırması gerekir. bu codec'i işleyebilir ve pSidebandWindow üyesi üzerinden geri iletebilirsiniz. için, HWC'nin ilişkili codec'i tanımlayabilmesini sağlar. Bileşen çalışmazsa bTunneled, OMX_FALSE olarak ayarlanmalıdır.

Codec2

Codec2, Android 11 veya sonraki sürümlerde tünelli oynatmayı destekler. Kod çözücü bileşeni aşağıdakileri desteklemelidir:

  • Tünel modunu yapılandıran C2PortTunneledModeTuning yapılandırılıyor ve ses çıkış cihazından alınan HW_AV_SYNC içinde geçer veya kanal ayarlayıcı konfigürasyonunu içerir.

  • C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE sorgusu sorgulanıyor, HWC için yan bant tutma yeri.

  • Bir C2Work öğesine eklendiğinde C2_PARAMKEY_TUNNEL_HOLD_RENDER işleniyor. codec'e işin tamamlandığına dair kodu çözmesi ve bunu belirtmek için talimat verir, ancak kodu işleme 1) codec'e daha sonra kodu oluşturma talimatı verilir veya 2) ses çalmaya başlar.

  • codec'e şu komutu veren C2_PARAMKEY_TUNNEL_START_RENDER işleniyor: işaretli kareyi hemen oluşturur Ses çalma başlamamış olsa bile C2_PARAMKEY_TUNNEL_HOLD_RENDER.

  • debug.stagefright.ccodec_delayed_params ürününü yapılandırılmamış olarak bırakın (önerilir). Eğer yapılandırdıysanız false olarak ayarlayın.

AOSP uygulaması, tünel modunu CCodec aşağıdaki kod snippet'inde gösterildiği gibi C2PortTunnelModeTuning aracılığıyla:

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, &params);
if (c2err == C2_OK && params.size() == 1u) {
    C2PortTunnelHandleTuning::output *videoTunnelSideband =
            C2PortTunnelHandleTuning::output::From(params[0].get());
    return OK;
}

Bileşen bu yapılandırmayı destekliyorsa bir yan bant ayırması gerekir. bu codec'i işleyip C2PortTunnelHandlingTuning üzerinden geri aktarın. için, HWC'nin ilişkili codec'i tanımlayabilmesini sağlar.

Ses HAL'si

Ses HAL, isteğe bağlı video oynatımı için ses sunumunu alır bir başlık içinde büyük-endian biçiminde ses verileriyle satır içi zaman damgaları bulundu uygulamanın yazdığı her ses verisi bloğunun başında:

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;
}

HWC'nin video karelerini karşılık gelen ses kareleriyle senkronize olarak oluşturması için Ses HAL'nin, senkronizasyon başlığını ayrıştırarak ve sunum zaman damgasını kullanarak oynatma saatini ses oluşturma ile yeniden senkronize eder. Yeniden senkronize etmek için sıkıştırılmış ses çalınıyorsa Ses HAL'nin meta verileri ayrıştırması gerekebilir. sıkıştırılmış ses verilerinin içine girerek oynatma süresini belirleyebilirsiniz.

Desteği duraklat

Android 5 veya önceki sürümlerde duraklatma desteği yoktur. Tünel kullanımını duraklatabilirsiniz yalnızca A/V açıldıktan sonra oynatılabilir, ancak videonun dahili arabelleği büyükse (örneğin, OMX bileşeninde bir saniyelik veri vardır), bu da tepki vermez.

Android 5.1 veya sonraki sürümlerde AudioFlinger, doğrudan erişim için duraklatma ve devam ettirmeyi destekler (tünelli) ses çıkışları oluşturun. HAL'de duraklatma ve devam ettirme uyguluyorsa izleme işlemini duraklat ve öz geçmiş HAL’ye yönlendirilir.

Duraklatma, boşaltma ve devam ettirme çağrısı sırası, HAL çağrıları yürütülerek uygulanır oynatma ileti dizisinde de (boşlukla aynı) yer alır.

Uygulama önerileri

Ses HAL'si

Android 11'de PCR veya STC'deki HW senkronizasyon kimliği, A/V senkronizasyonu için kullanılabilir. yalnızca video akışı desteklenir.

Android 10 veya önceki sürümler için tünelli video oynatmayı destekleyen cihazlarda FLAG_HW_AV_SYNC içeren en az bir ses çıkış yayın profili ve audio_policy.conf dosyasında AUDIO_OUTPUT_FLAG_DIRECT işareti mevcut. Bu işaretler sistem saatini ses saatinden ayarlamak için kullanılır.

OMX

Cihaz üreticileri, tünelli video için ayrı bir OMX bileşenine sahip olmalıdır. (üreticiler, diğer türler için ek OMX bileşenlerine ses ve video oynatma (ör. güvenli oynatma) Tünelli bileşen gereken:

  • Çıkışında 0 arabellek (nBufferCountMin, nBufferCountActual) belirtin bağlantı noktası.

  • OMX.google.android.index.prepareForAdaptivePlayback setParameter uzantısını uygulayın.

  • media_codecs.xml dosyasında özelliklerini belirtin ve tünelle oynatma özelliğini kullanabilirsiniz. Aynı zamanda kareyle ilgili sınırlamaları da net bir şekilde veya bit hızı gibi sorunları çözmek için kullanılabilir. Aşağıda bununla ilgili bir örnek gösterilmektedir:

    <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>
    

Tünelli ve tünelsiz kod çözmeyi desteklemek için aynı OMX bileşeni kullanılıyorsa tünelli oynatma özelliğini gerekli değil olarak bırakır. Hem tünelli hem de Tünelsiz kod çözücüler de aynı kapasite sınırlamalarına sahiptir. Örneğin, aşağıda gösterilmiştir:

<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>

Donanım Oluşturucu (HWC)

üzerinde tünel protokolü (compositionType HWC_SIDEBAND içeren katman) olduğunda katmanın sidebandStream özelliği, OMX video bileşeni.

HWC, kodu çözülmüş video karelerini (tünelli OMX bileşeninden) ilişkilendirilmiş ses parçası (audio-hw-sync kimliğiyle birlikte). Yeni bir video karesi güncel hale geldiğinde, HWC bunu tüm katmanların mevcut içeriğiyle birleştirir. sırasında alınan kararları belirtir ve elde edilen resmi gösterir. Hazırlama veya ayarlama çağrıları yalnızca diğer katmanlar değiştiğinde veya özellikleri (konum veya boyut gibi) değişir.

Aşağıdaki şekilde, donanım (veya çekirdek ya da video karelerini (7b) en son besteyle birleştirmek için senkronizasyon aracı (7a) Ses'e göre (7c) doğru zamanda gösterilmesi için.

Sese göre video karelerini birleştiren HWC

Şekil 2. HWC donanım (veya çekirdek ya da sürücü) senkronize edici