如何透過OpenHarmony系統中整合的ffmpeg庫和NAPI機制,實現更多的多媒體功能?
簡介
OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)作為“開源”世界的“聯結器”,不斷為智慧社會的發展提供源源不斷的“源動力”。深開鴻一直以來積極投身於OpenHarmony社群建設,不斷推動開源事業的發展。
身為深開鴻的一名OS框架開發工程師,我在OpenHarmony 開源專案成立伊始便積極加入OpenHarmony 社群建設,負責OpenHarmony框架和結構的研發工作,此次我將帶來OpenHarmony多媒體子系統的原始碼分析,希望能為廣大的開發者提供參考。
OpenHarmony多媒體子系統,是OpenHarmony系統框架中的其中一個比較重要的子系統。OpenHarmony中整合了ffmpeg的第三方庫,多媒體的很多功能實現需要ffmpeg庫。另外,媒體檔案的處理包含了對音影片裁剪、音影片分離等應用場景的處理,有些功能多媒體子系統沒有提供給外部相應的介面,對此可以透過NAPI的機制實現一套JS介面,提供給應用層去呼叫,以此實現更多的多媒體功能 。
效果展示
本文透過實現音影片檔案裁剪的功能,讓開發者熟悉實現該功能的整個操作流程。以下是效果圖:
首先選擇原始檔,在裁剪設定中設定裁剪的起始時間和結束時間(單位為秒),引數設定完以後,我們點選裁剪按鈕,進而對原始檔進行裁剪,裁剪成功後,會顯示播放按鈕。
在整個操作過程中,原始檔選擇模組的播放按鈕是對原始檔進行播放,裁剪模組的播放按鈕是對裁剪後檔案的播放,我們可以透過播放影片檔案來檢視裁剪前後的效果對比。
程式碼已經上傳至SIG倉庫,連結如下:
原始碼分析
原始碼分析分為兩個部分,一部分是NAPI實現的本地功能,另一部分是JS實現的應用功能。 一、NAPI實現
以下是原始碼分析的內容,核心的模組主要程式碼是myffmpegsys,為應用端提供了js的介面。
1. myffmpegsys作為一個新的子系統整合到OpenHarmony原始碼中,放置在OpenHarmony原始碼的根目錄下,和foundation在同一目錄下。
2. 配置build/subsystem_config.json。
"myffmpegsys": {
"path": "myffmpegsys",
"name": "myffmpegsys"
},
3. 配置產品的productdefine/common/products/XXXX.json(其中XXXX對應的裝置型號)。
"parts":{
"myffmpegsys:myffmpegpart":{},
"ace:ace_engine_standard":{},
......
}
4. 配置好子系統以及對應的元件後,下面再對myffmpegsys子系統的原始碼進行分析。
(1)目錄結構
myffmpegdemo中主要處理napi相關的介面轉換,ffmpeg_utils透過呼叫ffmpeg三方庫處理實際的影片檔案裁剪功能。
(2)OpenHarmony整合的ffmpeg三方庫的路徑是third_party/ffmpeg,myffmpegdemo會依賴ffmpeg,並且標頭檔案也會引用ffmpeg標頭檔案,所以在BUILD.gn檔案中會新增相關的依賴和路徑。
import("//build/ohos.gni")
ohos_shared_library("myffmpegdemo") {
include_dirs = [
"//foundation/ace/napi/interfaces/kits",
"//myffmpegsys/myffmpegpart/myffmpegdemo/include",
"//third_party/ffmpeg",
]
sources = [
"myffmpegdemo.cpp",
"ffmpeg_utils.cpp",
]
public_deps = [
"//foundation/ace/napi:ace_napi",
"//third_party/ffmpeg:libohosffmpeg"
]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
]
relative_install_dir = "module"
subsystem_name = "myffmpegsys"
part_name = "myffmpegpart"
}
(3)流程圖
(4)程式碼分析
Napi介面註冊:
/***********************************************
* Module export and register
***********************************************/
static napi_value registerMyffmpegdemo(napi_env env, napi_value exports)
{
static napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("videoCute", videoCute),
DECLARE_NAPI_FUNCTION("videoToAacH264", videoToAacH264),
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
NAPI實現videoCute介面,將NAPI型別轉換成C++型別,然後呼叫FfmpegUtils的videoCute介面:
static void executeVideoCute(napi_env env, void* data) {
VideoCuteAddOnData *addonData = (VideoCuteAddOnData *) data;
//呼叫影片剪下的功能
addonData->result = FfmpegUtils::videoCute((const char*)addonData->args0.c_str(), \
addonData->args1, \
addonData->args2, \
(const char*)addonData->args3.c_str());
}
FfmpegUtils初始化輸入,輸出格式上下文:
//初始化上下文
ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0);
if (ret < 0) {
ERROR_BUF(ret);
HiLog::Error(LABEL, "gyf avformat_open_input error = %{public}s", errbuf);
return ret;
}
ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
if (ret < 0) {
ERROR_BUF(ret);
HiLog::Error(LABEL, "gyf avformat_alloc_output_context2 error = %{public}s", errbuf);
goto end;
}
ofmt = ofmt_ctx->oformat;
根據輸入流建立輸出流,並且複製codec引數:
//建立流以及引數複製
for (int i = 0; i < (int)ifmt_ctx->nb_streams; i++) {
in_stream = ifmt_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
ret = AVERROR_UNKNOWN;
goto end;
}
avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
out_stream->codecpar->codec_tag = 0;
}
開啟輸出檔案,並寫入標頭檔案:
//開啟輸出檔案
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
if (ret < 0) {
ERROR_BUF(ret);
HiLog::Error(LABEL, "gyf avio_open error = %{public}s", errbuf);
goto end;
} // 寫頭資訊
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
ERROR_BUF(ret);
HiLog::Error(LABEL, "gyf avformat_write_header error = %{public}s", errbuf);
goto end;
}
根據設定的擷取時間段,跳轉到指定幀:
//跳轉到指定幀
ret = av_seek_frame(ifmt_ctx, -1, start_seconds * AV_TIME_BASE, AVSEEK_FLAG_ANY);
if (ret < 0) {
ERROR_BUF(ret);
HiLog::Error(LABEL, "gyf av_seek_frame error = %{public}s", errbuf);
goto end;
}
迴圈讀取幀資料,當達到擷取時間點後,退出迴圈:
//讀取資料
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0) {
break;
}
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
// 時間超過要擷取的時間,就退出迴圈
if (av_q2d(in_stream->time_base) * pkt.pts > end_seconds) {
av_packet_unref(&pkt);
break;
}
寫入檔案尾部資訊:
//寫檔案尾資訊
ret = av_write_trailer(ofmt_ctx);
二、JS應用實現
目錄結構
程式碼主要包含兩部分,index主要是裁剪相關的設定,player是針對影片檔案進行播放的頁面。
index中設定了原始檔,裁剪的起始時間,結束時間以後,透過裁剪按鈕,進行影片的裁剪功能,這一部分的程式碼是透過底層NAPI提供的介面進行的。
cutevideo() {
globalThis.isCuteSuccess = false;
console.log('gyf cutevideo');
myffmpegdemo.videoCute(this.src, this.startTime, this.endTime, this.srcOut,
function (result) {
console.log('gyf cutevideo callback result = ' + result);
globalThis.showPrompt('videoCute finished!');
if (0 === result) {
globalThis.isCuteSuccess = true;
} else {
globalThis.isCuteSuccess = false;
}
}
);
},
影片一旦裁剪成功以後,頁面就會出現播放的按鈕,點選播放按鈕後,便可對裁剪後的檔案進行觀看。
總結
本文透過NAPI方式給大家講解了如何利用OpenHarmony系統能力實現更多的功能。開發者可以利用OpenHarmony自帶的三方庫,實現音影片分離、音影片轉碼、音影片編解碼等多媒體處理功能,而且這些功能都可以在系統層實現,並透過NAPI的方式提供對應的介面進行呼叫。對於OpenHarmony整合的其他內在的能力,也可以透過NAPI的方式來對外提供介面,以此實現更多功能。
開發工作是一條漫長的道路,開發者唯有舉一反三、觸類旁通,才能在未來的開發工作中達到事半功倍的效果。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011554/viewspace-2905417/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何通過OpenHarmony系統中整合的ffmpeg庫和NAPI機制,實現更多的多媒體功能?API
- 【史上最全】Nginx+ffmpeg實現流媒體系統Nginx
- 直播預告|OpenHarmony標準系統多媒體子系統之相機解讀
- 直播預告丨 OpenHarmony 標準系統多媒體子系統之相機解讀
- 流媒體軟體系統可實現哪些功能IPTV?
- 帶貨直播系統,透過ffmpeg推流實現首屏秒開
- 如何透過CRM系統獲取更多銷售線索?
- 直播預告丨OpenHarmony標準系統多媒體子系統之視訊解讀
- 透過 Git 來管理多媒體檔案Git
- OpenHarmony整合OCR三方庫實現文字提取
- 載入更多 功能的實現
- Redis的記憶體和實現機制Redis記憶體
- 如何透過 Rancher 輕鬆實現多雲部署
- 如何實現OpenHarmony的OTA升級
- 教你如何透過vue實現echarts中的儀表盤VueEcharts
- 使用Html5 多媒體實現微信語音功能HTML
- OpenHarmony 3.2 Beta多媒體系列——音影片播放框架框架
- 如何透過Zoho Mail實現網易、騰訊等多郵箱的管理AI
- 透過整合行業的光纖認證功能實現光纖認證智慧化行業
- 在繼承和多型中的記憶體分配機制繼承多型記憶體
- FFmpeg 2.6.1 釋出,多媒體處理工具
- 實現【檢視更多】功能的程式碼
- 透過websocket,實現遊戲陪玩系統的聊天室Web遊戲
- MySQL中的MVCC實現機制MySqlMVC
- 現代化數字展廳多媒體-智慧中控系統的優勢特點
- 六點概括短影片系統原始碼的實用功能機制原始碼
- Windows10系統怎麼透過聯機獲取更多主題【圖文】Windows
- 常見面試題之作業系統中的LRU快取機制實現面試題作業系統快取
- 從 FFmpeg 效能加速到端雲一體媒體系統優化優化
- 軟體系統的設計和實現
- 有沒有人真正搞過weblogic portal?如何實現與原有業務系統的整合?Web
- 如何透過SK整合chatGPT實現DotNet專案工程化?ChatGPT
- Redis 中的過期刪除策略和記憶體淘汰機制Redis記憶體
- 數字展廳多媒體智慧中控系統常見的控制方式
- Nginx accept鎖的機制和實現Nginx
- 報警機制如何用多執行緒實現執行緒
- 如何透過Scikit-Learn實現多類別文字分類?文字分類
- 如何透過CRM系統進行銷售機會管理?