作者:chengcheng,華為媒體技術工程師
過去開發者們在使用多媒體能力時,往往會遇到這樣的問題,比如:為什么我開發的相機不如系統相機的效果好?為什么我的應用和其他的音樂一起發聲了,我要怎么處理?以及我應該怎么做才能在系統的播控中心里可以看到呢?對于開發者的這些疑問,HarmonyOS通過提供簡單易用體驗一致的生態接口,使得開發者可以輕松解決上述問題。下面會按照不同模塊逐個進行介紹。一
相機
1.1問題背景
相機應用在早期的版本開發時,會發現三方相機和系統相機拍照的效果會有較明顯的不一致。如下圖對比,可以看到,在色彩/飽和度/紋理細節等方面有一些明顯的差異。
三方相機:
系統相機:
1.2問題原因
那么這一問題是怎么產生的呢?主要有兩個原因:
1、系統相機采用了私有通路,從而獲取了更好的效果
2、預覽流拍照效果差
1.3問題解決
針對以上問題,系統提出了如下的解決思路:
1、統一接口,統一流程,統一效果:通過統一開發接口和流程,從而使得三方相機和系統相機獲取一致的體驗
2、分離預覽、拍照、錄像,明確流定義,讓正確的流做正確的事
3、相機管道流水線模型
1.4代碼示例
1、相機基本控制流程如下:
2、示例參考:
使用PreviewOutput實現相機預覽:
//1.創建預覽視圖XComponent,獲取SurfaceId
surfaceId=xComponent.getXComponentSurfaceId();
//2.創建預覽數據流輸出PreviewOutput
previewOutput=createPreviewOutput(profile,surfaceId);
//3.添加預覽數據流輸出到相機會話
session.addOutput(previewOutput);
(左右滑動查看更多)
使用PhotoOutput實現相機拍照:
//1.創建圖片接收器ImageReceiver,獲取SurfaceId
surfaceId=imageReceiver.getReceivingSurfaceId();
//2.創建拍照數據流輸出PhotoOutput
photoOutput=createPhotoOutput(profile,surfaceId);
//3.添加拍照數據流輸出到相機會話
session.addOutput(photoOutput);
(左右滑動查看更多)
使用VideoOutput實現相機錄像:
//1.創建視頻編碼器AVRecorder,獲取SurfaceId
surfaceId=avRecorder.getInputSurface();
//2.創建錄像數據流輸出VideoOutput
videoOutput=createVideoOutput(profile,surfaceId);
//3.添加錄像數據流輸出到相機會話
session.addOutput(videoOutput);
(左右滑動查看更多)
更多詳細的代碼參考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/camera-overview.md
二
音視頻焦點
2.1問題背景
音視頻應用開發中遇到的很常見的一個場景,就是并發播放,而并發播放的一般解決思路是各個應用對焦點的申請和處理。
傳統的焦點管理方法,依賴應用遵守約定好的策略,如果有的應用不遵守,比如不響應或者濫用焦點,就可能會出現不發聲或者亂發聲的現象,影響了用戶的體驗。
2.2 解決思路
針對以上的問題,鴻蒙系統改進了焦點管理的設計,提供了統一的焦點處理策略,來規范應用對于焦點的使用,以達成統一的發聲體驗。
系統中的焦點管理模塊會存儲一個焦點策略表,定義了不同的場景下,哪些應用可以獲取焦點進行播放,哪些應用會失去焦點而停止播放,等等其他策略。
2.3代碼示例
可以通過接口的使用來看一下實際處理策略。
首先,在A應用創建并使用AudioRenderer播放的時候,系統會自動為其申請焦點,這個是系統的行為。
A應用播放后,系統的焦點策略會進行判斷,如果A應用可以搶到焦點,那就會使得失去焦點的應用暫停播放;同時被暫停的應用也會在INTERRUPT_FORCE的回調事件中,得到暫停的狀態,應用在收到這個事件后,就需要存儲并更新應用內的狀態。
當A應用停止播放,之前被暫停的應用也會收到一個恢復播放的事件,這個事件會在INTERRUPT_SHARE中,應用可以進行恢復播放的操作,或者忽略,這個非強制行為。
// 1.AudioRenderer進行播放時,系統會申請焦點
audioRenderer.start((err) => {});
// 2.注冊音頻打斷事件的回調
audioRenderer.on('audioInterrupt', (event) => {
if (event.forceType === audio.InterruptForceType.INTERRUPT_FORCE) {
// 3.強制打斷類型:音頻相關處理已由系統執行,應用需更新自身狀態
} else if (event.forceType === audio.InterruptForceType.INTERRUPT_SHARE) {
// 4.共享打斷類型:應用可自主選擇執行相關操作或忽略打斷事件
}});
(左右滑動查看更多)
更多詳細的代碼參考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/audio-playback-concurrency.md
三
低時延播放
3.1問題背景
游戲、K歌、樂器等應用,對于音頻的輸出時延要求很高,常規的播放通路一般只能達到60ms左右甚至更高的時延,無法滿足這些應用的使用訴求。
3.2解決思路
鴻蒙系統提供了低時延通路的設計。如下圖所示,在系統中的普通通路之外,新增了一條垂直打通硬件的低時延通路,通過bypass 框架層直接在DSP進行混音,可以達成最低20ms的音頻輸出時延。
同時,為了簡化應用的接入,通過在接口中提供不同的參數配置,使開發者可以用一套接口同時支持低時延和普通通路兩種播放模式。
3.3代碼示例
可以通過OH_AudioStreamXXX接口來進行低時延通路的創建,通過傳入不同參數可以設置低時延模式,亦可以設置普通模式,從而使用一套接口來適配不同場景。
同時,低時延模式一般采用來pull模式來獲取數據,這里提供了一個callback,需要應用創建并填入。
// 1.創建音頻流構造器,設置參數
OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
OH_AudioStreamBuilder_SetSamplingRate(builder, rate); // 其他參數設置…
// 2.設置低延時模式和數據回調
OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST) ;
OH_AudioStreamBuilder_SetRendererCallback(builder, callback, nullptr);
// 3.構造播放的音頻流并使用
OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
OH_AudioRenderer_Start(audioRenderer);?OH_AudioRenderer_Release(audioRenderer);
(左右滑動查看更多)
更多詳細的代碼參考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/using-ohaudio-for-playback.md
四
播控能力
4.1系統能力通過前面所說的焦點管理策略,系統解決了音視頻應用并發播放的問題;對于播放中的應用的控制,系統也提供了規范支持。
系統提供了C/S模式的播控管理的框架,應用作為客戶端,接入AVSession的會話端,設置必要的信息;系統的播控中心獲取與之對應的會話控制器,獲取信息進行展示,以及對應用發送控制命令。
通過標準接口的接入,規范了應用的播放行為;同時通過統一的播控中心的入口,使得用戶對于播放的控制做到一鍵直達。
4.2 代碼示例
import AVSessionManager from '@ohos.multimedia.avsession';
// 開始創建并激活媒體會話
// 創建session
let context: Context = getContext(this);
async function createSession() {
let type: AVSessionManager.AVSessionType = 'audio';
let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type);
await session.activate();
}
async function setSessionInfo() {
// 播放器邏輯··· 引發媒體信息與播放狀態的變更
// 設置必要的媒體信息
let metadata: AVSessionManager.AVMetadata = {
assetId: '0',
title: 'TITLE',
artist: 'ARTIST'
};
session.setAVMetadata(metadata).then(() => {
}).catch((err: BusinessError) => {
});
// 簡單設置一個播放狀態 - 暫停 未收藏
let playbackState: AVSessionManager.AVPlaybackState = {
state:AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE,
isFavorite:false
};
session.setAVPlaybackState(playbackState, (err) => {
});
}
async function setListenerForMesFromController() {
// 一般在監聽器中會對播放器做相應邏輯處理
// 不要忘記處理完后需要通過set接口同步播放相關信息,參考上面的用例
session.on('play', () => {
// do some tasks ···
});
session.on('pause', () => {
// do some tasks ···
});
}
(左右滑動查看更多)
更多詳細的代碼參考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/avsession-overview.md
更多推薦
-
HarmonyOS
+關注
關注
79文章
1977瀏覽量
30255
原文標題:【技術視界】學習指南:如何快速上手媒體生態一致體驗開發
文章出處:【微信號:HarmonyOS_Dev,微信公眾號:HarmonyOS開發者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論