Multimedya tünelleme, sıkıştırılmış video verilerinin uygulama kodu veya Android çerçeve kodu tarafından işlenmeden doğrudan bir donanım video kod çözücüsü aracılığıyla bir ekrana tünellenmesini sağlar. Android yığınının altındaki cihaza özel kod, video çerçevesi sunum zaman damgalarını aşağıdaki dahili saat türlerinden biriyle karşılaştırarak hangi video çerçevelerinin ekrana gönderileceğini ve ne zaman gönderileceğini belirler:
Android 5 veya sonraki sürümlerde isteğe bağlı video oynatma için, uygulamada geçirilen sesli sunum zaman damgalarıyla senkronize edilmiş bir
AudioTrack
saatAndroid 11 veya sonraki sürümlerde canlı yayın oynatmak için tuner tarafından çalıştırılan bir program referans saati (PCR) veya sistem saati (STC)
Arka plan
Android'de geleneksel video oynatma, sıkıştırılmış bir video karesinin kodu çözüldüğünde uygulamayı bildirir. Ardından uygulama, doğru zamanlamayı hesaplamak için geçmişteki AudioTimestamps
örneklerini alarak kod çözümü yapılmış video karesini, karşılık gelen ses karesiyle aynı sistem saati zamanında oluşturulmak üzere ekrana yayınlar.
Tünellenmiş video oynatma, uygulama kodunu atlayıp video üzerinde işlem yapan süreçlerin sayısını azalttığı için OEM uygulamasına bağlı olarak daha verimli video oluşturma sağlayabilir. Ayrıca, Android'in video oluşturma isteklerinin zamanlaması ile gerçek donanım dikey senkronizasyonlarının zamanlaması arasındaki olası çarpıklığın neden olduğu zamanlama sorunlarını önleyerek seçilen saatle (PRC, STC veya ses) daha doğru video ritmi ve senkronizasyonu sağlayabilir. Ancak, arabellekler Android grafik yığınını atladığından tünel oluşturma, pencere içinde pencere (PiP) pencerelerinde bulanıklaştırma veya yuvarlak köşeler gibi GPU efektleri için desteği de azaltabilir.
Aşağıdaki şemada, tünellemenin video oynatma sürecini nasıl basitleştirdiği gösterilmektedir.
1. şekil. Geleneksel ve tünellenmiş video oynatma süreçlerinin karşılaştırması
Uygulama geliştiriciler için
Çoğu uygulama geliştirici, oynatma uygulaması için bir kitaplıkla entegrasyon yaptığından çoğu durumda uygulama için yalnızca bu kitaplığın tünellenmiş oynatma için yeniden yapılandırılması gerekir. Tünellenmiş video oynatıcının düşük düzeyde uygulanması için aşağıdaki talimatları kullanın.
Android 5 veya sonraki sürümlerde isteğe bağlı video oynatma için:
SurfaceView
örneği oluşturun.audioSessionId
örneği oluşturun.2. adımda oluşturulan
audioSessionId
örneğiyleAudioTrack
veMediaCodec
örneklerini oluşturun.Ses verilerindeki ilk ses karesinin sunum zaman damgasıyla birlikte
AudioTrack
'ya ses verilerini sıraya alın.
Android 11 veya sonraki sürümlerde canlı yayın oynatma için:
SurfaceView
örneği oluşturun.Tuner
'danavSyncHwId
örneği alın.2. adımda oluşturulan
avSyncHwId
örneğiyleAudioTrack
veMediaCodec
örnekleri oluşturun.
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 oynatmanın davranışı
Tünellenmiş seç-izle video oynatma işlemi AudioTrack
oynatma işlemine örtülü olarak bağlı olduğundan, tünellenmiş video oynatma işlemi ses oynatma işleminin davranışına bağlı olabilir.
Çoğu cihazda, varsayılan olarak ses oynatma başlayana kadar video karesi oluşturulmaz. Ancak uygulama, ses oynatmayı başlatmadan önce bir video karesi oluşturması gerekebilir. Örneğin, arama sırasında kullanıcının mevcut video konumunu göstermek için.
Kuyruğa alınan ilk video karesinin kodu çözülür çözülmez oluşturulması gerektiğini belirtmek için
PARAMETER_KEY_TUNNEL_PEEK
parametresini1
olarak ayarlayın. Sıkıştırılmış video kareleri kuyrukta yeniden sıralandığında (ör. B kareleri mevcut olduğunda) bu, görüntülenen ilk video karesinin her zaman bir I karesi olması gerektiği anlamına gelir.Sıraya alınan ilk video karesinin ses çalma işlemi başlayana kadar oluşturulmasını istemiyorsanız bu parametreyi
0
olarak ayarlayın.Bu parametre ayarlanmazsa cihazın davranışını OEM belirler.
AudioTrack
'ya ses verileri sağlanmadığında ve arabellekler boş olduğunda (ses yetersizliği) ses saati artık ilerlemediği için daha fazla ses verisi yazılana kadar video oynatma durur.Oynatma sırasında, uygulamanın düzeltemediği süreksizlikler ses sunumu zaman damgalarında görünebilir. Bu durumda OEM, geçerli video karesini duraklatarak negatif boşlukları, video karelerini bırakarak veya sessiz ses kareleri ekleyerek (OEM uygulamasına bağlı olarak) pozitif boşlukları düzeltir. Eklenen sessiz ses çerçeveleri için
AudioTimestamp
çerçeve konumu artmaz.
Cihaz üreticileri için
Yapılandırma
OEM'ler, tünellenmiş video oynatmayı desteklemek için ayrı bir video kod çözücü oluşturmalıdır.
Bu kod çözücü, media_codecs.xml
dosyasında tünellenmiş oynatma özelliğine sahip olduğunu bildirmelidir:
<Feature name="tunneled-playback" required="true"/>
Tünellenmiş bir MediaCodec
örneği ses oturumu kimliğiyle yapılandırıldığında AudioFlinger
, bu HW_AV_SYNC
kimliği için sorgu gönderir:
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
, birincil ses cihazından HW_AV_SYNC
kimliğini alır ve dahili olarak ses oturumu kimliğiyle ilişkilendirir:
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 zaten oluşturulmuşsa HW_AV_SYNC
kimliği, aynı ses oturumu kimliğine sahip çıkış akışına iletilir. Henüz oluşturulmadıysa HW_AV_SYNC
kimliği, AudioTrack
oluşturma sırasında çıkış akışına iletilir. Bu işlem, playback
thread tarafından yapılır:
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
HW_AV_SYNC
kimliği, ses çıkışı akışına veya Tuner
yapılandırmasına karşılık gelip gelmediğine bakılmaksızın, OEM kodu codec'i ilgili ses çıkışı akışıyla veya tuner akışıyla ilişkilendirebilmesi için OMX ya da Codec2 bileşenine iletilir.
Bileşen yapılandırması sırasında, OMX veya Codec2 bileşeni, codec'i bir Hardware Composer (HWC) katmanıyla ilişkilendirmek için kullanılabilecek bir bant dışı işleyici döndürmelidir. Uygulama bir yüzeyi MediaCodec
ile ilişkilendirdiğinde bu yan bant tutma yeri, SurfaceFlinger
aracılığıyla HWC'ye aktarılır. HWC, katmanı yan bant katmanı olarak yapılandırır.
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, uygun zamanda codec çıkışından yeni görüntü arabellekleri almaktan (ilişkili ses çıkış akışıyla veya tuner programı referans saatiyle senkronize edilmiş), arabellekleri diğer katmanların mevcut içerikleriyle birleştirmekten ve ortaya çıkan görüntüyü göstermekten sorumludur. Bu işlem, normal hazırlama ve ayarlama döngüsünden bağımsız olarak gerçekleşir. Hazırlama ve ayarlama çağrıları yalnızca diğer katmanlar değiştiğinde veya yan bant katmanının özellikleri (ör. konum veya boyut) değiştiğinde gerçekleşir.
OMX
Tünellenmiş bir kod çözücü bileşeni şunları desteklemelidir:
Ses çıkışı cihazıyla ilişkili
HW_AV_SYNC
kimliğini iletmek içinOMX.google.android.index.configureVideoTunnelMode
extended parametresini ayarlama. Bu parametre,ConfigureVideoTunnelModeParams
yapısını kullanır.Ses oynatma başlatılıp başlatılmadığına bakılmaksızın, codec'e ilk çözümlenen video karesini oluşturmasını veya oluşturmamasını söyleyen
OMX_IndexConfigAndroidTunnelPeek
parametresini yapılandırma.İlk tünellenmiş video karesinin kodu çözüldüğünde ve oluşturulmaya hazır olduğunda
OMX_EventOnFirstTunnelFrameReady
etkinliğini gönderme.
AOSP uygulaması, aşağıdaki kod snippet'inde gösterildiği gibi ACodec
üzerinden OMXNodeInstance
aracılığıyla tünel modunu yapılandırır:
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 bu codec'e bir yan bant tutma yeri ayırmalı ve HWC'nin ilişkili codec'i tanımlayabilmesi için pSidebandWindow
üyesi aracılığıyla geri iletmelidir. Bileşen bu yapılandırmayı desteklemiyorsa bTunneled
değerini OMX_FALSE
olarak ayarlamalıdır.
Codec2
Android 11 veya sonraki sürümlerde Codec2
, tünellenmiş oynatmayı destekler. Kod çözücü bileşeni aşağıdakileri desteklemelidir:
Tünel modunu yapılandıran ve ses çıkışı cihazından veya tuner yapılandırmasından alınan
HW_AV_SYNC
değerlerini iletenC2PortTunneledModeTuning
yapılandırılıyor.HWC için bant dışı tutma yerini ayırmak ve almak üzere
C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE
sorgulanır.C2_PARAMKEY_TUNNEL_HOLD_RENDER
,C2Work
öğesine eklendiğinde işleniyor. Bu durumda, codec'e kod çözme ve işin tamamlandığını bildirme talimatı veriliyor ancak 1) codec'e daha sonra oluşturma talimatı verilene veya 2) ses oynatma başlayana kadar çıkış arabelleğini oluşturma talimatı verilmiyor.C2_PARAMKEY_TUNNEL_START_RENDER
işleme: Bu, ses oynatma başlamamış olsa bile codec'eC2_PARAMKEY_TUNNEL_HOLD_RENDER
ile işaretlenen kareyi hemen oluşturma talimatı verir.debug.stagefright.ccodec_delayed_params
yapılandırılmamış olarak bırakın (önerilir). Yapılandırırsanızfalse
olarak ayarlayın.
AOSP uygulaması, aşağıdaki kod snippet'inde gösterildiği gibi C2PortTunnelModeTuning
üzerinden CCodec
içinde tünel modunu yapılandırır:
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;
}
Bileşen bu yapılandırmayı destekliyorsa bu codec'e bir yan bant tutma yeri ayırmalı ve HWC'nin ilişkili codec'i tanımlayabilmesi için C2PortTunnelHandlingTuning
üzerinden geri geçirmelidir.
Ses HAL
İsteğe bağlı video oynatma için Audio HAL, uygulamanın yazdığı her ses verisi bloğunun başında bulunan bir başlıkta büyük endian biçiminde ses verileriyle birlikte ses sunumu zaman damgalarını alır:
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 ilgili ses kareleriyle senkronize olarak oluşturması için Audio HAL'in senkronizasyon başlığını ayrıştırması ve oynatma saatini ses oluşturmayla yeniden senkronize etmek için sunum zaman damgasını kullanması gerekir. Sıkıştırılmış ses çalınırken yeniden senkronizasyon yapmak için Audio HAL'in, çalma süresini belirlemek üzere sıkıştırılmış ses verilerindeki meta verileri ayrıştırması gerekebilir.
Desteği duraklatma
Android 5 veya daha eski sürümlerde duraklatma özelliği desteklenmez. Tünellenmiş oynatmayı yalnızca A/V yetersizliği nedeniyle duraklatabilirsiniz. Ancak videonun dahili arabelleği büyükse (ör. OMX bileşeninde bir saniyelik veri varsa) duraklatma yanıt vermiyormuş gibi görünür.
Android 5.1 veya sonraki sürümlerde AudioFlinger
, doğrudan (tünellenmiş) ses çıkışlarında duraklatma ve devam ettirme işlemlerini destekler. HAL, duraklatma ve devam ettirme işlemlerini uyguluyorsa duraklatma ve devam ettirme isteği HAL'ye iletilir.
Duraklatma, temizleme, devam ettirme çağrı sırası, HAL çağrıları oynatma iş parçacığında (aynı boşaltma gibi) yürütülerek uygulanır.
Uygulama önerileri
Ses HAL
Android 11'de A/V senkronizasyonu için PCR veya STC'den alınan donanım senkronizasyon kimliği kullanılabilir. Bu nedenle, yalnızca video akışı desteklenir.
Android 10 veya önceki sürümlerde, tünellenmiş video oynatmayı destekleyen cihazların audio_policy.conf
dosyasında FLAG_HW_AV_SYNC
ve AUDIO_OUTPUT_FLAG_DIRECT
işaretlerini içeren en az bir ses çıkışı akış profili olmalıdır. Bu işaretler, sistem saatini ses saatinden ayarlamak için kullanılır.
OMX
Cihaz üreticileri, tünellenmiş video oynatma için ayrı bir OMX bileşenine sahip olmalıdır (üreticiler, güvenli oynatma gibi diğer ses ve video oynatma türleri için ek OMX bileşenlerine sahip olabilir). Tünellenmiş bileşen:
Çıkış bağlantı noktasında 0 arabellek (
nBufferCountMin
,nBufferCountActual
) belirtin.OMX.google.android.index.prepareForAdaptivePlayback setParameter
uzantısını uygulayın.media_codecs.xml
dosyasında özelliklerini belirtin ve tünellenmiş oynatma özelliğini beyan edin. Ayrıca, kare boyutu, hizalama veya bit hızıyla ilgili sınırlamalar da açıklanmalıdır. Aşağıda 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ünel ve tünel dışı kod çözme işlemlerini desteklemek için aynı OMX bileşeni kullanılıyorsa tünel dışı oynatma özelliği gerekli olmayan olarak bırakılmalıdır. Bu durumda, tünellenmiş ve tünellenmemiş kod çözücüler aynı özellik sınırlamalarına sahip olur. Aşağıda bir örnek 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 Bestecisi (HWC)
Bir ekranda tünellenmiş katman (HWC_SIDEBAND
compositionType
içeren bir katman) olduğunda, katmanın sidebandStream
değeri OMX video bileşeni tarafından ayrılan bant dışı tutamaçtır.
HWC, tünellenmiş OMX bileşeninden gelen kod çözülmüş video karelerini, ilişkili ses parçasıyla (audio-hw-sync
kimliğiyle) senkronize eder. Yeni bir video karesi geçerli hale geldiğinde HWC, bu kareyi son hazırlama veya ayarlama çağrısı sırasında alınan tüm katmanların mevcut içerikleriyle birleştirir ve ortaya çıkan görüntüyü gösterir.
Hazırlama veya ayarlama çağrıları yalnızca diğer katmanlar değiştiğinde ya da yan bant katmanının özellikleri (ör. konum veya boyut) değiştiğinde gerçekleşir.
Aşağıdaki şekil, video karelerini (7b) ses (7c) temelinde doğru zamanda görüntülemek için en son kompozisyonla (7a) birleştirmek üzere donanım (veya çekirdek ya da sürücü) senkronizasyon cihazıyla birlikte çalışan HWC'yi gösterir.
Şekil 2. HWC donanımı (veya çekirdek ya da sürücü) senkronizasyon aracı