简介

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的方式来对外提供接口,以此实现更多功能。

开发工作是一条漫长的道路,开发者唯有举一反三、触类旁通,才能在未来的开发工作中达到事半功倍的效果。

如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多的多媒体功能?的更多相关文章

  1. 如何在CRM系统中集成ActiveReports最终报表设计器

    有时候,将ActiveReports设计器集成到业务系统中,为用户提供一些自定义的数据表,用户不需要了解如何底层的逻辑关系和后台代码,只需要选择几张关联的数据表,我们会根据用户的选择生成可供用户直接使 ...

  2. 在Cloudreve网盘系统中集成kkFileView在线预览(暂时)

    服务器:WindowsServer 2016 Cloudreve 需求方想整一个在小团队内部使用的网盘系统,最终在千挑万选之下选中了Cloudreve. Github地址:https://github ...

  3. 用minGW编译ffmpeg(供替换opencv中引用的ffmpeg库)

    在安装好的opencv文件夹下找到路径:opencv245\opencv\3rdparty\ffmpeg,此路径下有一个readme.txt文件,内容例如以下所看到的: The build scrip ...

  4. Android系统中的6种模式

    Android系统中的6种模式 1:一般启动模式(normal mode):    功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode):    此模式和正常启动一样 ...

  5. Android中集成ffmpeg(一):编译ffmpeg

    方案选择 Android中集成ffmpeg的codec功能无非两种方式: JNI直接调用,主要用于App开发(无权限修改系统底层),如EXOPlayer,JPlayer等. 集成ffmpeg到OMX, ...

  6. android系统中对ffmpeg封装最好的免费SDK

    android系统中对ffmpeg封装最好的免费SDK; 无论个人还是公司,都免费商用, 欢迎下载. https://github.com/LanSoSdk/LanSoEditor_common 可能 ...

  7. FineReport集成到AWS系统中的方案

    本人实施了北京炎黄盈动的BPM及OA系统,主要目标是对业务流程进行控制和管理,加快Oracle JDE的业务前端录单速度和弥补JDE在流程控制方面的不足,实现BPM数据能与JDE无缝互相结合,经过3个 ...

  8. 在Windows系统中安装集成的PHP开发环境

    原文:在Windows系统中安装集成的PHP开发环境 刚想学php的,又不会配置复杂php的环境,可以使用集成的,目前网上提供常用的PHP集成环境主要有AppServ.phpStudy.WAMP和XA ...

  9. SpringBoot集成PageHelper时出现“在系统中发现了多个分页插件,请检查系统配置!”

    近日在项目中使用SpringBoot集成PageHelper后,跑单元测试时出现了"在系统中发现了多个分页插件,请检查系统配置!"这个问题. 如下图所示: org.mybatis. ...

  10. linux系统中Nginx+FFmPeg+vlc实现网页视频播放配置过程

    linux系统中Nginx+FFmPeg实现网页监控视频播放配置过程 1.安装好的nginx上添加模块nginx-http-fiv-module-master 此模块是rtmp模块的升级版,有它所有的 ...

随机推荐

  1. 【ACM专项练习#03】打印图形、栈的合法性、链表操作、dp实例

    运营商活动 题目描述 小明每天的话费是1元,运营商做活动,手机每充值K元就可以获赠1元,一开始小明充值M元,问最多可以用多少天? 注意赠送的话费也可以参与到奖励规则中 输入 输入包括多个测试实例.每个 ...

  2. 【Azure Fabric Service】怎样关闭 Azure Service Fabric?

    问题描述 怎样关闭Azure Service Fabric服务呢?在Azure门户上没有找到 Stop 按钮. 问题回答 Azure Service Fabric 默认是无法停止的,可以删除. 虽然可 ...

  3. 【Azure 环境】Update-MgEntitlementManagementAccessPackageAssignmentPolicy 命令执行时候遇见的 No HTTP Resource was found 问题分析

    Microsoft Graph PowerShell SDK: acts as an API wrapper for the Microsoft Graph APIs, exposing the en ...

  4. [爬坑] termux ssh 设置总是 permission denied

    问题 设置ssh之后,客户端登录会提示 permission denied 的问题,经过排查最终确定是 shell设置错误的问题,解决方法如下 http://new.aidlearning.net/d ...

  5. 解密Spring中的Bean实例化:推断构造方法(上)

    在Spring中,一个bean需要通过实例化来获取一个对象,而实例化的过程涉及到构造方法的调用.本文将主要探讨简单的构造推断和实例化过程,让我们首先深入了解实例化的步骤. 实例化源码 protecte ...

  6. SpringCloud Ribbon和Feign 的使用和源码分析

    1. Ribbon 介绍 Ribbon 是 Netflix 公司开源的一款 客户端 负载均衡软件,并被SpringCloud集成 作为SpringCloud 负载均衡的工具 服务端负载均衡 : 即在服 ...

  7. Java 异常整合练习

    1 package com.bytezero.throwable2; 2 3 /** 4 * 5 * @Description 异常练习 6 * @author Bytezero·zhenglei! ...

  8. Java 异常处理(1) :try-catch-finally的使用

    1 package com.bytezero.throwable; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 impor ...

  9. CPN Tools 系统建模分析工具(持续更新)

    一直想把之前看有关CPN的文献资料做一个综合性的整理,所以最近花了些时间,把乌克兰敖德萨国家电信科学院交通运输部学院的讲义做一个翻译.本课程的翻译不具授权(如有侵权请及时联系,做删除处理) 本课程的标 ...

  10. C++ Qt开发:QHostInfo主机地址查询组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QHo ...