0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于OpenHarmony 3.2 Beta1版本的媒體能力

OpenAtom OpenHarmony ? 來(lái)源:OpenAtom OpenHarmony ? 作者:OpenAtom OpenHarmony ? 2022-07-01 10:58 ? 次閱讀

一、背景

全民直播時(shí)代,人們每天刷著五花八門(mén)的短視頻,每分每秒都有無(wú)數(shù)的視頻文件被生成、播放。但你可曾想過(guò)這些電視劇、電影、視頻廣告、短視頻等影音是以怎樣的數(shù)據(jù)形式在我們的顯示設(shè)備中播放出來(lái)的?本文將基于 OpenHarmony 3.2 Beta1 版本的媒體能力,為你詳細(xì)解讀一個(gè)視頻文件(本文以 MP4 封裝格式、H264 壓縮格式的視頻文件為例)是怎么在基于 OpenHarmony 標(biāo)準(zhǔn)系統(tǒng)的設(shè)備上播放出來(lái)的。同時(shí)也帶你一窺“播放一個(gè)視頻文件”這件對(duì) OpenHarmony 3.2 Beta1 版本系統(tǒng)能力很輕松的事,是由多少服務(wù)層、功能接口、工具、插件、命令行及代碼等共同協(xié)作完成的。

二、OpenHarmony 3.2媒體能力全景

OpenHarmony 技術(shù)架構(gòu)如下圖所示,完成視頻文件播放功能的是多媒體子系統(tǒng)。

7b5704ea-f875-11ec-ba43-dac502259ad0.png

下圖所示為多媒體子系統(tǒng)框架圖

7b6c7064-f875-11ec-ba43-dac502259ad0.png

如圖所示,OpenHarmony 多媒體子系統(tǒng)拉起了一個(gè)叫 mediaserver 的服務(wù)來(lái)處理媒體事務(wù),并且封裝了接口層包括JS接口、native 接口提供給 APP 調(diào)用,mediaserver 的核心則是引入了 gstreamer(以下簡(jiǎn)稱 gst)框架來(lái)完成媒體功能(注:gstreamer 是一套功能強(qiáng)大、兼容性好、結(jié)構(gòu)清晰的開(kāi)源媒體框架,這里不做贅述,后面有專文解析)。OpenHarmony 也在 gst 的基礎(chǔ)上開(kāi)發(fā)了 player engine 來(lái)實(shí)現(xiàn)播放,同時(shí)也利用 gst 豐富的插件資源實(shí)現(xiàn)幾乎所有的媒體功能。截至目前,已移植進(jìn)來(lái)的開(kāi)源插件包括 file source、demuxer、video decoder、libav 插件等,當(dāng)然也包括 OpenHarmony 自研的 video sink、memsink、codec hdi 插件等。

三、把大象裝冰箱(H264視頻播放)總共分幾步?

視頻播放流程圖如下:

7b9cdb1e-f875-11ec-ba43-dac502259ad0.png

如圖所示,播放一個(gè)視頻大致分為 4 步:

解協(xié)議->解封裝->解壓縮->送顯

播放pipeline

根據(jù)視頻播放的步驟,我們?cè)?OpenHarmony 上每一個(gè)環(huán)節(jié)都能找到對(duì)應(yīng)的插件來(lái)完成,同時(shí)參考 media_standard 代碼倉(cāng)的代碼目錄,相關(guān)的代碼都可以找到對(duì)應(yīng)的實(shí)現(xiàn)邏輯。

7bc0cef2-f875-11ec-ba43-dac502259ad0.png

1、對(duì)于一個(gè)本地視頻文件(比如/data/h264-640x480.mp4),對(duì)應(yīng)的 filesrc 插件來(lái)完成文件的解析,拿到MP4文件流;

OpenHarmony 處理本地視頻文件 URI 的 SetSource 邏輯代碼如下:

int32_t PlayerEngineGstImpl::SetSource(const std::string &url){ std::unique_lock lock(mutex_); CHECK_AND_RETURN_RET_LOG(!url.empty(), MSERR_INVALID_VAL, "input url is empty!"); CHECK_AND_RETURN_RET_LOG(url.length() <= MAX_URI_SIZE, MSERR_INVALID_VAL, "input url length is invalid!"); std::string realUriPath; int32_t ret = MSERR_OK; if (IsFileUrl(url)) { ret = GetRealPath(url, realUriPath); if (ret != MSERR_OK) { return ret; } url_ = "file://" + realUriPath; } else { url_ = url; } MEDIA_LOGD("set player source: %{public}s", url_.c_str()); return ret;}?

這樣就會(huì)得到一個(gè) URI:file:///data/h264-640x480.mp4,gst 正是通過(guò) URI 前綴來(lái)判斷是否是本地視頻文件,然后獲取文件內(nèi)容。

2、拿到 MP4 文件流后,對(duì)應(yīng)的 qtdemux 插件來(lái)解封裝,完成音視頻分流,輸出 H264 裸碼流和音頻流;

3、拿到 H264 碼流后,h264parse 插件開(kāi)始切片,輸出 H264 幀數(shù)據(jù);

4、處理 H264 幀數(shù)據(jù),就由 avdec_h264 插件來(lái)完成,一般情況會(huì)輸出 NV12 的像素?cái)?shù)據(jù),當(dāng)然這個(gè)解碼器是基于 ffmpeg 的軟解插件,相信不久各個(gè)芯片廠商硬件加速解碼器都會(huì)加進(jìn)來(lái);

可以使用 gst-inspect 工具查看 avdec_h264 解碼插件,使用 ffmpeg 的解碼能力,支持的格式非常豐富。

7bf6923a-f875-11ec-ba43-dac502259ad0.png

5、至此解碼的工作已經(jīng)完成,后面就要根據(jù)顯示的像素格式、size 來(lái)對(duì)解碼輸出數(shù)據(jù)進(jìn)行后處理(轉(zhuǎn)換、縮放、裁剪等),會(huì)由 Converter、Scaler、Clip 插件來(lái)完成;

6、滿足顯示要求后就會(huì)使用 surfacesink 插件完成合成送顯。

送顯需要先申請(qǐng)顯示 surface buffer,申請(qǐng)邏輯代碼如下:

GstSurfaceMemory *gst_surface_allocator_alloc(GstSurfaceAllocator *allocator, GstSurfaceAllocParam param){ g_return_val_if_fail(allocator != nullptr && allocator->surface != nullptr, nullptr); static constexpr int32_t stride_alignment = 8; int32_t wait_time = param.dont_wait ? 0 : INT_MAX; // wait forever or no wait. OHOS::BufferRequestConfig request_config = { param.width, param.height, stride_alignment, param.format, static_cast(param.usage) | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA, wait_time }; int32_t release_fence = -1; OHOS::sptr surface_buffer = nullptr; OHOS::SurfaceError ret = allocator->surface->RequestBuffer(surface_buffer, release_fence, request_config); if (ret == OHOS::SURFACE_ERROR_NO_BUFFER) { GST_INFO("there is no more buffers"); } if (ret != OHOS::SURFACE_ERROR_OK || surface_buffer == nullptr) { return nullptr; } ret = surface_buffer->Map(); if (ret != OHOS::SURFACE_ERROR_OK) { GST_ERROR("surface_buffer Map failed"); return nullptr; } OHOS::sptr autoFence = new(std::nothrow) OHOS::SyncFence(release_fence); if (autoFence != nullptr) { autoFence->Wait(100); // 100ms } GstSurfaceMemory *memory = reinterpret_cast(g_slice_alloc0(sizeof(GstSurfaceMemory))); if (memory == nullptr) { GST_ERROR("alloc GstSurfaceMemory slice failed"); allocator->surface->CancelBuffer(surface_buffer); return nullptr; } gst_memory_init(GST_MEMORY_CAST(memory), (GstMemoryFlags)0, GST_ALLOCATOR_CAST(allocator), nullptr, surface_buffer->GetSize(), 0, 0, surface_buffer->GetSize()); memory->buf = surface_buffer; memory->fence = -1; memory->need_render = FALSE; GST_DEBUG("alloc surface buffer for width: %d, height: %d, format: %d, size: %u", param.width, param.height, param.format, surface_buffer->GetSize()); return memory;}

申請(qǐng)好的 buffer 會(huì)放入 buffer pool,形成一個(gè) buffer 隊(duì)列。

解碼器解完一幀會(huì)將數(shù)據(jù)放入 buffer pool,sink 插件會(huì)從 buffer pool 中拿到數(shù)據(jù)送顯,代碼邏輯如下:

static GstFlowReturn gst_surface_mem_sink_do_app_render(GstMemSink *memsink, GstBuffer *buffer, bool is_preroll){ g_return_val_if_fail(memsink != nullptr && buffer != nullptr, GST_FLOW_ERROR); GstSurfaceMemSink *surface_sink = GST_SURFACE_MEM_SINK_CAST(memsink); g_return_val_if_fail(surface_sink != nullptr, GST_FLOW_ERROR); GstSurfaceMemSinkPrivate *priv = surface_sink->priv; GST_OBJECT_LOCK(surface_sink); if (gst_surface_mem_sink_drop_frame_check(surface_sink) == FALSE) { GST_OBJECT_UNLOCK(surface_sink); GST_DEBUG_OBJECT(surface_sink, "user set rate, drop same frame"); return GST_FLOW_OK; } if (surface_sink->firstRenderFrame) { GST_WARNING_OBJECT(surface_sink, "KPI-TRACE: first render frame"); surface_sink->firstRenderFrame = FALSE; } for (guint i = 0; i < gst_buffer_n_memory(buffer); i++) { GstMemory *memory = gst_buffer_peek_memory(buffer, i); if (!gst_is_surface_memory(memory)) { GST_WARNING_OBJECT(surface_sink, "not surface buffer !, 0x%06" PRIXPTR, FAKE_POINTER(memory)); continue; } GstSurfaceMemory *surface_mem = reinterpret_cast(memory); surface_mem->need_render = TRUE; gboolean needFlush = TRUE; if (is_preroll) { surface_sink->prerollBuffer = buffer; } else { if (surface_sink->prerollBuffer == buffer) { // if it's paused, then play, this buffer is render by preroll surface_sink->prerollBuffer = nullptr; needFlush = FALSE; } } if (needFlush) { OHOS::BufferFlushConfig flushConfig = { { 0, 0, surface_mem->buf->GetWidth(), surface_mem->buf->GetHeight() }, }; gst_surface_mem_sink_dump_buffer(surface_sink, buffer); OHOS::SurfaceError ret = priv->surface->FlushBuffer(surface_mem->buf, surface_mem->fence, flushConfig); if (ret != OHOS::SURFACE_ERROR_OK) { surface_mem->need_render = FALSE; GST_ERROR_OBJECT(surface_sink, "flush buffer to surface failed, %d", ret); } } } GST_OBJECT_UNLOCK(surface_sink); GST_DEBUG_OBJECT(surface_sink, "End gst_surface_mem_sink_do_app_render"); return GST_FLOW_OK;}

再加上 audio 的插件解碼出音頻數(shù)據(jù),OpenHarmony 的 player 會(huì)完成音視頻同步,至此一個(gè)視頻文件就會(huì)播放顯示在屏幕上。

OpenHarmony 為了實(shí)現(xiàn)更好的用戶體驗(yàn),同時(shí)也引入了一些解決性能問(wèn)題的插件,比如 multiqueue 插件來(lái)實(shí)現(xiàn) buffer 隊(duì)列,也使用 decodebin 高級(jí)插件來(lái)完成解碼 element 的選擇。

通過(guò)梳理,我們最終可以得到一條播放的 pipeline:

7c148362-f875-11ec-ba43-dac502259ad0.png

而通過(guò)播放 OpenHarmony 自帶的圖庫(kù)播放本地 H264 視頻,抓取 log,搜索 OnElementSetupCb 關(guān)鍵字也可以得到播放的 pipeline,這也進(jìn)一步驗(yàn)證了本文的分析。

7c2e4784-f875-11ec-ba43-dac502259ad0.png

另外,我們也可以使用 gst-launch 手動(dòng)創(chuàng)建 pipeline 來(lái)驗(yàn)證:

gst-launch--gst-plugin-path=/system/lib/media/pluginsfilesrclocation=/data/media/h264.mp4!qtdemux!h264parse!avdec_h264!videoconvert!videoscale!video/x-raw,width=640,height=480!surfacememsink

附錄:

OpenHarmony標(biāo)準(zhǔn)系統(tǒng)media組件介紹

https://gitee.com/openharmony/multimedia_media_standardhttps://gitee.com/openharmony/multimedia_media_standard

MP4封裝格式介紹

https://wenku.baidu.com/view/b4f52a376ddb6f1aff00bed5b9f3f90f76c64dbd.htmlhttps://wenku.baidu.com/view/b4f52a376ddb6f1aff00bed5b9f3f90f76c64dbd.html

gst介紹

https://gstreamer.freedesktop.org/documentation/tutorials/index.html?gi-language=chttps://gstreamer.freedesktop.org/documentation/tutorials/index.html?gi-language=c

https://blog.csdn.net/qq_45662588/article/details/120763198https://blog.csdn.net/qq_45662588/article/details/120763198

OpenHarmony 3.2 Beta1 版本路書(shū)

https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-v3.2-beta1.md

OpenHarmony媒體子系統(tǒng)框架介紹

https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%AA%92%E4%BD%93%E5%AD%90%E7%B3%BB%E7%BB%9F.mdhttps://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%AA%92%E4%BD%93%E5%AD%90%E7%B3%BB%E7%BB%9F.md

OpenHarmony視頻播放應(yīng)用開(kāi)發(fā)指導(dǎo)

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/video-playback.md

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 視頻
    +關(guān)注

    關(guān)注

    6

    文章

    1930

    瀏覽量

    72774
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3641

    瀏覽量

    16066

原文標(biāo)題:基于OpenHarmony 3.2 Beta1版本的H264視頻播放之路詳解

文章出處:【微信號(hào):gh_e4f28cfa3159,微信公眾號(hào):OpenAtom OpenHarmony】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    蘋(píng)果推送iOS 18.2 Beta 1,Siri接入ChatGPT技術(shù)

    10月24日最新報(bào)道,蘋(píng)果公司于今日向開(kāi)發(fā)人員發(fā)布了iOS 18.2 Beta 1版本,此版本專為支持Apple Intelligence的設(shè)備設(shè)計(jì),涵蓋iPhone 15 Pro系列
    的頭像 發(fā)表于 10-24 14:24 ?394次閱讀

    HarmonyOS NEXT Developer Beta1最新術(shù)語(yǔ)表

    UIAbility Stage模型中的組件類型名,即UIAbility組件,包含UI,提供展示UI的能力,主要用于和用戶交互。 本文根據(jù)HarmonyOS NEXT Developer Beta1官方公開(kāi)的開(kāi)發(fā)文檔整理而成。
    發(fā)表于 06-27 16:16

    HarmonyOS NEXT Developer Beta1中的Kit

    從HarmonyOS NEXT Developer Preview1(API 11)版本開(kāi)始,HarmonyOS SDK以Kit維度提供豐富、完備的開(kāi)放能力,涵蓋應(yīng)用框架、系統(tǒng)、媒體、
    發(fā)表于 06-26 10:47

    鴻蒙開(kāi)發(fā):【OpenHarmony 4.0 Release指導(dǎo)】

    OpenHarmony 4.0版本如期而至,開(kāi)發(fā)套件同步升級(jí)到API 10。相比3.2 Release版本,新增4000多個(gè)API,應(yīng)用開(kāi)發(fā)能力
    的頭像 發(fā)表于 05-14 09:59 ?1253次閱讀
    鴻蒙開(kāi)發(fā):【<b class='flag-5'>OpenHarmony</b> 4.0 Release指導(dǎo)】

    【開(kāi)源鴻蒙】下載OpenHarmony 4.1 Release源代碼

    本文介紹了如何下載開(kāi)源鴻蒙(OpenHarmony)操作系統(tǒng) 4.1 Release版本的源代碼,該方法同樣可以用于下載OpenHarmony最新開(kāi)發(fā)版本(master分支)或者4.0
    的頭像 發(fā)表于 04-27 23:16 ?781次閱讀
    【開(kāi)源鴻蒙】下載<b class='flag-5'>OpenHarmony</b> 4.1 Release源代碼

    OpenHarmony南向能力征集令

    1、適配過(guò)程中缺少哪些接口能力或者南向能力,需要OpenHarmony去補(bǔ)齊的?例如內(nèi)核、編譯、器件適配、單板適配等; 2、對(duì)標(biāo)linux,需要Op
    發(fā)表于 04-09 15:32

    OpenAtom OpenHarmony 4.1 Release版本正式發(fā)布

    近日,OpenAtom OpenHarmony(以下簡(jiǎn)稱“OpenHarmony”)4.1 Release版本如期而至,開(kāi)發(fā)套件同步升級(jí)到API 11 Release。
    的頭像 發(fā)表于 04-07 11:43 ?625次閱讀

    開(kāi)源大師兄開(kāi)發(fā)板通過(guò) OpenHarmony 3.2 Release版本兼容性測(cè)評(píng)

    近期,江蘇潤(rùn)開(kāi)鴻數(shù)字科技有限公司(以下簡(jiǎn)稱“潤(rùn)開(kāi)鴻”)開(kāi)源?師兄開(kāi)發(fā)板順利通過(guò)OpenHarmony3.2.1Release版本兼容性測(cè)評(píng),為基于開(kāi)源大師兄開(kāi)發(fā)板研發(fā)更多可釋放該系統(tǒng)版本新特性的?態(tài)
    的頭像 發(fā)表于 01-20 08:02 ?829次閱讀
    開(kāi)源大師兄開(kāi)發(fā)板通過(guò) <b class='flag-5'>OpenHarmony</b> <b class='flag-5'>3.2</b> Release<b class='flag-5'>版本</b>兼容性測(cè)評(píng)

    搭載KaihongOS的高動(dòng)態(tài)人形機(jī)器人“夸父”通過(guò)OpenHarmony 3.2 Release版本兼容性測(cè)評(píng)

    OpenHarmony”)3.2 Release版本兼容性測(cè)評(píng)并獲頒兼容性證書(shū) 。這體現(xiàn)了深圳開(kāi)鴻數(shù)字產(chǎn)業(yè)發(fā)展有限公司(以下簡(jiǎn)稱”深開(kāi)鴻“)OpenHarmony生 態(tài)建設(shè)
    的頭像 發(fā)表于 12-20 09:45 ?441次閱讀
    搭載KaihongOS的高動(dòng)態(tài)人形機(jī)器人“夸父”通過(guò)<b class='flag-5'>OpenHarmony</b> <b class='flag-5'>3.2</b> Release<b class='flag-5'>版本</b>兼容性測(cè)評(píng)

    高動(dòng)態(tài)人形機(jī)器人“夸父”通過(guò)OpenHarmony 3.2 Release版本兼容性測(cè)評(píng)

    近日, 搭載KaihongOS的“夸父”人形機(jī)器人通過(guò)OpenAtom OpenHarmony(以下簡(jiǎn)稱“OpenHarmony”)3.2 Release版本兼容性測(cè)評(píng)并獲頒兼容性證書(shū)
    發(fā)表于 12-20 09:31

    搭載KaihongOS的高動(dòng)態(tài)人形機(jī)器人“夸父”通過(guò)OpenHarmony3.2 Release版本兼容性測(cè)評(píng)

      近日,搭載KaihongOS的國(guó)內(nèi)首款可跳躍、可適應(yīng)多地形行走的開(kāi)源鴻蒙人形機(jī)器人通過(guò)OpenAtom OpenHarmony(以下簡(jiǎn)稱“OpenHarmony”)3.2 Release
    的頭像 發(fā)表于 12-07 18:15 ?507次閱讀

    OpenHarmony社區(qū)運(yùn)營(yíng)報(bào)告(2023年10月)

    OpenHarmony社區(qū)共有51家共建單位,累計(jì)超過(guò)6200名貢獻(xiàn)者產(chǎn)生24.2萬(wàn)多個(gè)PR,2.3萬(wàn)多個(gè)Star,6.1萬(wàn)多個(gè)Fork,59個(gè)SIG。●OpenHarmony4.0版本如期而至
    的頭像 發(fā)表于 11-18 08:02 ?442次閱讀
    <b class='flag-5'>OpenHarmony</b>社區(qū)運(yùn)營(yíng)報(bào)告(2023年10月)

    OpenHarmony 4.0 Release版本發(fā)布

    與業(yè)務(wù)場(chǎng)景的終端商用設(shè)備操作系統(tǒng)發(fā)行版及解決方案。以下正文轉(zhuǎn)自O(shè)penAtomOpenHarmony微信公眾號(hào)。OpenHarmony4.0Release版本如期而
    的頭像 發(fā)表于 11-18 08:02 ?474次閱讀
    <b class='flag-5'>OpenHarmony</b> 4.0 Release<b class='flag-5'>版本</b>發(fā)布

    OpenHarmony 4.0 Release版本發(fā)布,邀您體驗(yàn)

    OpenHarmony4.0Release版本如期而至,開(kāi)發(fā)套件同步升級(jí)到API10。相比3.2Release版本,新增4000+個(gè)API,應(yīng)用開(kāi)發(fā)
    的頭像 發(fā)表于 11-16 08:30 ?413次閱讀
    <b class='flag-5'>OpenHarmony</b> 4.0 Release<b class='flag-5'>版本</b>發(fā)布,邀您體驗(yàn)

    OpenHarmony 4.0 Release版本發(fā)布,新增4000+ API

    近日,OpenHarmony 4.0 Release版本如期發(fā)布,開(kāi)發(fā)套件同步升級(jí)到API 10。相比3.2 Release版本,OpenHarmo
    的頭像 發(fā)表于 11-13 11:31 ?790次閱讀