

如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多-开源基础软件社区-51C...
source link: https://ost.51cto.com/posts/14554
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多 精华
如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多的多媒体功能?
简介
OpenAtom OpenHarmony(以下简称“OpenHarmony”)作为“开源”世界的“连接器”,不断为智能社会的发展提供源源不断的“源动力”。深开鸿一直以来积极投身于OpenHarmony社区建设,不断推动开源事业的发展。
身为深开鸿的一名OS框架开发工程师,我在OpenHarmony 开源项目成立伊始便积极加入OpenHarmony 社区建设,负责OpenHarmony框架和结构的研发工作,此次我将带来OpenHarmony多媒体子系统的源码分析,希望能为广大的开发者提供参考。
OpenHarmony多媒体子系统,是OpenHarmony系统框架中的其中一个比较重要的子系统。OpenHarmony中集成了ffmpeg的第三方库,多媒体的很多功能实现需要ffmpeg库。另外,媒体文件的处理包含了对音视频裁剪、音视频分离等应用场景的处理,有些功能多媒体子系统没有提供给外部相应的接口,对此可以通过NAPI的机制实现一套JS接口,提供给应用层去调用,以此实现更多的多媒体功能 。
效果展示
本文通过实现音视频文件裁剪的功能,让开发者熟悉实现该功能的整个操作流程。以下是效果图:

首先选择源文件,在裁剪设置中设定裁剪的起始时间和结束时间(单位为秒),参数设定完以后,我们点击裁剪按钮,进而对源文件进行裁剪,裁剪成功后,会显示播放按钮。
在整个操作过程中,源文件选择模块的播放按钮是对源文件进行播放,裁剪模块的播放按钮是对裁剪后文件的播放,我们可以通过播放视频文件来查看裁剪前后的效果对比。
代码已经上传至SIG仓库,链接如下:
https://gitee.com/openharmony-sig/knowledge_demo_entainment/tree/master/FA/MediaCuteDemo
https://gitee.com/openharmony-sig/knowledge_demo_entainment/tree/master/docs/MediaCuteDemo
源码分析
源码分析分为两个部分,一部分是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的方式来对外提供接口,以此实现更多功能。
开发工作是一条漫长的道路,开发者唯有举一反三、触类旁通,才能在未来的开发工作中达到事半功倍的效果。

Recommend
-
37
// code_041_sync_WaitGroup project main.go package main import ( "fmt" "sync" ) func main() { fmt.Println("Hello World!") var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done()...
-
24
下载地址: https://www.yanxishe.com/resourceDetail/2528?from=leiphonecolumn_res1014
-
3
随着诸如物联网(IoT),人工智能(AI),增强现实/虚拟现实(AR / VR)以及区块链等技术的兴起,电商行业也因此受益良多。 在与电商相关的数十种技术中,有一种可以将所有行业发展优势汇集到电商业务上的技术。那就是通过API服务相互连接各种技术来改...
-
8
通过ffmpeg下载在线HTTP Live Stream视频 前几天收到一个老婆的在线视频下载的任务,上去看了下,是标准的h5的HTTP Live...
-
8
作者:郭岳峰 Tesseract (Apache 2.0 License)是一个可以进行图像OCR识别的C++库,可以跨平台运行 。本样例基于Tesseract 库进行适配,使其可以运行在 OpenAtom OpenHarmony(以下简称“OpenHarmony”)上,并新增N-API接口供上层应用调用,...
-
7
OpenHarmony集成OCR三方库实现文字提取 作者:郭岳峰 2022-11-16 14:05:06 本样例基于Tesseract 库进行适配,使其可以运行在 OpenAtom OpenHarmony(以下简称“OpenHarmony”)上,并新增N-API接口供上层应用调用,...
-
8
如何将应用内置到OpenHarmony系统中 作者:Haoc_小源同学 2022-11-25 16:27:07 为笔者开发过程中的一些经验分享,旨在解决官方文档过于晦涩难懂或者示例代码不够详细的问题,同时方便笔者日后回顾以及其他开发者更...
-
3
想了解更多关于开源的内容,请访问:...
-
8
想了解更多关于开源的内容,请访问:
-
5
FFmpeg内置了aac音频格式,在《FFmpeg开发实战:从零基础到短视频上线》一书的“5.2.2 Linux环境集成mp3lame”又介绍了如何给FFmpeg集成mp3格式,常见的音频文件除了这两种之外,还有ogg和amr两种格式也较常用。其中ogg格式的编解码依赖于libogg和libvorbis,而amr格式...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK