多媒體通道讓壓縮的影片資料能夠穿過硬體 不必由應用程式程式碼處理 Android 架構程式碼。Android 堆疊下方的裝置特定程式碼 決定要傳送至螢幕的影片影格和傳送時間 比較影片影格顯示時間戳記與下列任一項 內部時鐘的類型:
如要在 Android 5 以上版本中隨選播放影片,
AudioTrack
敬上 與音訊簡報時間戳記同步的時鐘 通過 應用程式中的檔案如要在 Android 11 以上版本中播放即時直播,請參閱節目的參考時鐘 (PCR) 或系統時間 (STC), 調音器
背景
在 Android 裝置上播放傳統影片播放功能通知
應用程式會載入經過壓縮的影片影格。接著
版本
以相同系統時鐘轉譯顯示至螢幕上的已解碼影片影格
對應音訊影格的時間
擷取歷來資料
AudioTimestamps
例項來計算正確時間。
通道式影片播放時,可略過應用程式的程式碼,因此能減少 與影片相關的處理程序,因此能更有效率地顯示影片 會視原始設備製造商 (OEM) 實作而定。還能提供更準確的影片 調整頻率和與所選時鐘 (PRC、STC 或音訊) 的同步 從 Android 更新時間之間可能存在偏差所造成的時間問題 轉譯影片的要求,以及實際硬體 Vsync 的時間。不過 此外,通道設定也有助於減少對 GPU 效果的支援,例如: 模糊處理 子母畫面 (PiP) 視窗中的緩衝區或圓角,因為緩衝區會 繞過 Android 圖形堆疊。
下圖顯示通道簡化了影片播放程序。
圖 1. 比較傳統與通道影片播放程序
應用程式開發人員專區
大多數應用程式開發人員都會整合用於播放的程式庫 在大多數情況下 只需重新設定 每個通道都需要程式庫用於低階導入通道 請依照下列指示進行。
在 Android 5 以上版本中,隨選播放影片:
建立
SurfaceView
執行個體。建立
audioSessionId
執行個體。使用
audioSessionId
建立AudioTrack
和MediaCodec
執行個體 執行個體已建立於步驟 2 中。使用
AudioTrack
的顯示時間戳記,將音訊資料排入佇列 產生的第一個音訊影格
如要在 Android 11 以上版本中播放即時播送內容:
建立
SurfaceView
執行個體。從
Tuner
取得avSyncHwId
執行個體。使用
avSyncHwId
執行個體建立AudioTrack
和MediaCodec
執行個體
API 呼叫流程如以下程式碼片段所示:
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);
隨選影片播放的行為
因為通道式隨選影片播放是隱含與 AudioTrack
的關聯
通道影片播放時,通道播放行為的運作模式可能取決於行為
以及音訊播放等等
在大多數裝置上,系統預設會在播放音訊後顯示影片影格 即開始播放。不過,應用程式可能需要在 開始播放音訊,例如顯示使用者目前的影片 繼續跳轉時的位置和位置
表示應盡快算繪第一個待播影片影格 解碼器則會產生
PARAMETER_KEY_TUNNEL_PEEK
敬上 參數傳送至1
。對壓縮過的影片在佇列中重新排序時 (例如 B 框架 也就是說,第一個顯示的影片影格一律應為 I-Frame。如果不想在音訊前顯示第一個加入佇列的影片影格 就開始播放,請將這個參數設為
0
。如未設定這項參數,原始設備製造商 (OEM) 會判斷裝置的行為。
未將音訊資料提供給
AudioTrack
且緩衝區為空白時 (音訊不足),影片播放中斷,直到寫入更多音訊資料為止 因為音訊時鐘不再繼續前進在播放過程中,出現應用程式無法正確修正的停滯情形,可能會顯示在 輸出音訊的時間戳記在這種情況下,原始設備製造商 (OEM) 會修正負值 落差、因為停滯目前影片畫面而造成落差 影片影格或插入無聲音訊影格 (視原始設備製造商 (OEM) 而定) )。應用程式的
AudioTimestamp
影格位置並未增加 已插入無聲音訊影格。
裝置製造商專用
設定
原始設備製造商 (OEM) 應建立個別的影片解碼器,用來支援通道影片播放。
這個解碼器應公告
media_codecs.xml
檔案:
<Feature name="tunneled-playback" required="true"/>
如果經過通道的 MediaCodec
執行個體設定了音訊工作階段 ID,
對這個 HW_AV_SYNC
ID 的查詢為 AudioFlinger
:
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);
}
執行這項查詢時
AudioFlinger
會擷取 HW_AV_SYNC
ID
再於內部將該裝置與音訊內容建立關聯
工作階段 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);
如果已建立 AudioTrack
執行個體,則 HW_AV_SYNC
ID 為
傳遞到具有相同音訊工作階段 ID 的輸出串流。如果還未
HW_AV_SYNC
ID 會傳遞至輸出串流
建立「AudioTrack
」。使用者必須透過播放
執行緒:
mOutput->stream->common.set_parameters(&mOutput->stream->common, AUDIO_PARAMETER_STREAM_HW_AV_SYNC, hwAVSyncId);
HW_AV_SYNC
ID,無論是對應至音訊輸出串流或
Tuner
設定會傳遞至 OMX 或 Codec2 元件,讓
原始設備製造商 (OEM) 代碼可以將轉碼器與對應的音訊輸出串流建立關聯,或是
調整器串流
在元件設定期間,OMX 或 Codec2 元件應傳回
可用來將轉碼器與 Hardware Composer 建立關聯的側邊頻帶控點
(HWC) 層當應用程式將途徑與 MediaCodec
建立關聯時,此側邊頻帶
帳號代碼會透過 SurfaceFlinger
向下傳遞至 HWC,以設定
視為
「sideband」層。
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 負責接收來自 與相關的音訊輸出串流同步,或者 調音器程式參考時鐘,將緩衝區與目前的 並顯示產生的圖片。發生這種情況 獨立於正常的準備和設定的週期準備與設定呼叫 只有在其他圖層變更,或側邊頻層的屬性時 (例如位置或大小) 變動。
OMX
通道解碼器元件應支援下列項目:
設定擴充的
OMX.google.android.index.configureVideoTunnelMode
參數,該參數使用ConfigureVideoTunnelModeParams
結構將 (與音訊輸出裝置相關聯的HW_AV_SYNC
ID)。設定
OMX_IndexConfigAndroidTunnelPeek
參數,指出 要顯示或不算繪第一個已解碼的影片影格,無論如何 是否開始播放音訊。在第一個通道時傳送
OMX_EventOnFirstTunnelFrameReady
事件 影片影格已經過解碼,隨時可以顯示。
Android 開放原始碼計畫實作項目會在
ACodec
敬上
到
OMXNodeInstance
。
如以下程式碼片段所示:
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;
如果元件支援這項設定,就應分配側邊頻
處理到這個轉碼器,並透過 pSidebandWindow
成員傳回,
HWC 可識別相關聯的轉碼器。如果元件並未
支援這項設定,應將 bTunneled
設為 OMX_FALSE
。
轉碼器 2
在 Android 11 以上版本中,Codec2
支援通道播放。解碼器
元件應支援下列項目:
設定
C2PortTunneledModeTuning
,可設定通道模式並 傳入從音訊輸出裝置所擷取的HW_AV_SYNC
,或 調整調音器設定查詢
C2_PARAMKEY_OUTPUT_TUNNEL_HANDLE
來分配及擷取 HWC 的側頻控點在附加
C2Work
時處理C2_PARAMKEY_TUNNEL_HOLD_RENDER
, 會指示轉碼器解碼並表示工作完成,但不表示轉譯成功 輸出緩衝區直到 1) 稍後會指示轉碼器進行轉譯 或 2) 開始播放音訊。處理
C2_PARAMKEY_TUNNEL_START_RENDER
,指示轉碼器 就會立即顯示C2_PARAMKEY_TUNNEL_HOLD_RENDER
(即使尚未開始播放音訊)。保留
debug.stagefright.ccodec_delayed_params
的設定 (建議選項)。如果 那就設定在false
中。
Android 開放原始碼計畫實作項目會在
CCodec
敬上
透過 C2PortTunnelModeTuning
執行,如以下程式碼片段所示:
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;
}
如果元件支援這項設定,就應分配側邊頻
處理到這個轉碼器,並透過 C2PortTunnelHandlingTuning
傳回,
HWC 可識別相關聯的轉碼器。
音訊 HAL
如果是隨選影片播放,音訊 HAL 會收到音訊簡報 內嵌於標頭中的音訊資料時間戳記 在應用程式寫入的每個音訊資料區塊的開頭處加入下列程式碼:
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 轉譯視訊影格與對應的音訊影格同步, 音訊 HAL 應剖析同步處理標頭,並使用顯示時間戳記來 重新同步處理播放時鐘與音訊算繪。如要重新同步處理 正在播放壓縮的音訊,音訊 HAL 可能需要剖析中繼資料 來判斷播放時間。
暫停支援
Android 5 以下版本不支援暫停功能。您可以暫停通道 只能用 A/V 飢餓來播放,但如果影片內部緩衝區較大 (例如 OMX 元件有 1 秒資料),此動作會暫停 看起來沒有回應
在 Android 5.1 以上版本中,AudioFlinger
支援直接暫停和繼續播放功能
(通道) 音訊輸出。如果 HAL 導入了暫停和繼續作業,則追蹤暫停
履歷轉送到 HAL
執行 HAL 呼叫時,系統會遵循暫停、清除、繼續呼叫序列 播放執行緒的記錄 (與卸載相同)。
導入方式建議
音訊 HAL
在 Android 11 中,PCR 或 STC 的 HW 同步 ID 可用於影音同步, 支援純視訊串流。
如果裝置搭載 Android 10 以下版本,支援通道影片播放的裝置應符合以下條件:
至少有一個具有 FLAG_HW_AV_SYNC
的音訊輸出串流設定檔
audio_policy.conf
檔案中的 AUDIO_OUTPUT_FLAG_DIRECT
旗標。這些旗標
用於從音訊時鐘設定系統時鐘。
OMX
裝置製造商應使用獨立的 OMX 元件製作通道影片 播放 (製造商可針對其他類型的 OMX 元件提供額外的 OMX 元件) 例如安全播放)。通道元件 應:
在其輸出內容中指定 0 個緩衝區 (
nBufferCountMin
、nBufferCountActual
) 通訊埠。實作
OMX.google.android.index.prepareForAdaptivePlayback setParameter
擴充功能。在
media_codecs.xml
檔案中指定其功能,並宣告 循環播放功能此外,也應清楚說明影格限制 大小、對齊或位元率。範例如下所示:<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>
如果使用相同的 OMX 元件支援通道和非通道解碼 讓通道播放功能維持非必要狀態無論是通道或端點 就會有相同的功能限制例如 如下所示:
<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>
硬體 Composer (HWC)
有隧道圖層 (HWC_SIDEBAND
compositionType
的圖層) 時
螢幕,圖層的 sidebandStream
是
OMX 影片元件。
HWC 會將已解碼的視訊影格 (從通道 OMX 元件) 同步到
相關的音軌 (含 audio-hw-sync
ID)。開啟新影片影格時
而 HWC 會將該模型與所有圖層的目前內容相結合
並顯示產生的圖片。
準備或設定呼叫只會在其他層變更,或發生下列情況時
變更側邊頻寬圖層的屬性 (例如位置或大小) 的變更。
下圖代表與硬體 (或核心或 驅動程式) 同步器,將影片影格 (7b) 與最新的組合結合 (7a) 根據音訊 (7c) 技術,在正確的時間顯示。
圖 2. HWC 硬體 (或核心或驅動程式) 同步器