如何通過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
- 直播預告|OpenHarmony標準系統多媒體子系統之相機解讀
- 直播預告丨 OpenHarmony 標準系統多媒體子系統之相機解讀
- 流媒體軟體系統可實現哪些功能IPTV?
- Android-通過cmake整合ffmpegAndroid
- 載入更多 功能的實現
- Redis的記憶體和實現機制Redis記憶體
- OpenHarmony整合OCR三方庫實現文字提取
- 直播預告丨OpenHarmony標準系統多媒體子系統之視訊解讀
- 聊聊如何通過自定義註解實現springmvc和sentinel整合SpringMVC
- 教你如何通過自媒體變現!(建議收藏)
- OpenHarmony 3.2 Beta多媒體系列——影片錄製
- 通過 Git 來管理多媒體檔案Git
- 如何實現OpenHarmony的OTA升級
- 實現【檢視更多】功能的程式碼
- 通過Gradle Plugin實現Git Hooks檢測機制GradlePluginGitHook
- 六點概括短影片系統原始碼的實用功能機制原始碼
- OpenHarmony 3.2 Beta多媒體系列——音影片播放框架框架
- MySQL中的MVCC實現機制MySqlMVC
- 使用Html5 多媒體實現微信語音功能HTML
- 現代化數字展廳多媒體-智慧中控系統的優勢特點
- Swoole 中通過 process 模組實現多程式
- 如何基於Django中的WebSockets和非同步檢視來實現實時通訊功能DjangoWeb非同步
- 通過PureRender和Immutable實現React中的效能優化React優化
- JFrog 披露PJSIP開源多媒體通訊庫的五個漏洞JS
- 在Linux中,如何實現檔案系統的快照和克隆?Linux
- Windows 作業系統中的身份驗證機制非常多樣化且高度整合,以確保系統和網路環境的安全性。主要的身份驗證機制包括以下幾種:Windows作業系統
- Nginx accept鎖的機制和實現Nginx
- 從 FFmpeg 效能加速到端雲一體媒體系統優化優化
- 多頭注意力機制的python實現Python
- Redis 中的過期刪除策略和記憶體淘汰機制Redis記憶體
- 常見面試題之作業系統中的LRU快取機制實現面試題作業系統快取
- SpingBoot/JAVA實現給圖片加水印功能(通過thumbnailator庫)bootJavaAI
- 波卡的國庫機制如何更好地實現Web3.0?Web
- 多系統管理混亂?SAP系統整合其他系統實現統一管理
- 通過 Amazon API Gateway 和 Lambda 實現 CloudFront Distribution 克隆功能APIGatewayCloud
- 如何通過手機控制電視盒系統內容的播放?
- 數字展廳多媒體智慧中控系統常見的控制方式