JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
Beauty of Programming
Beauty of Programming

Nodejs C++ addon开发简介

目前OWT服务端使用了两种方式开发C++ addon: 使用内部的V8、libuv 和 Node.js 库 第三方NAN库 OWT服务端更新最频繁的数WebRTC agent代码了,目前WebRTC agent用的是NAN方式开发C++ addon,其他agent用的是内部的V8、libuv 和 Node.js 库开发C++ addon,开发起来会比较复杂,需要熟悉Nodejs各个组件的知识以及libuv、V8相关API调用。所以对于新开发的C++ addon,推荐使用NAN方式开发,简单,而且不用考虑Nodejs升级后的兼容性问题。 1. NAN简介 NAN的全称为**Native Abstraction for Node.js** , 其表现上是一个Node.js包。安装后,就得到一堆C++头文件,里面是一堆宏。它主要为Node.js和V8跨版本提供了封装的宏,使得开发者不用关心各个版本之间的API的差异。 NAN官方地址为:https://github.com/nodejs/nan。 NAN的优势在于可以屏蔽不同版本Node的API,使得C++ addon可以wirte once, compile anywhere,一份C++ addon可以适用于不同版本的Nodejs。 接下来我们以WebRTC agent中的代码简单讲解下如何使用NAN开发一个C++ addon。 2. NAN C++ addon开发 这里我们以WebRTC agent中的rtcConn addon作为示例,代码位于source/agent/webrtc/rtcConn中。 2.1 使用 安装NAN包: [crayon-69c6dd952e57d858682831/] 编写binding.gyp,将NAN路径添加到binding.gyp中: [crayon-69c6dd952e588393059632/] NAN的路径会通过node -e "require('nan')"获取。 2.2 目录结构 如下是rtcConn addon的目录结构: [crayon-69c6dd952e58c186918414/] 在每个C++ addon中都包含:binding.gyp,addon.cc。 binding.gyp。使用JSON风格,包含当前addon的编译配置,例如用到的文件以及库 addon.cc。类似于main函数入口,调用包含的各个C++类的Init接口 binding.gyp 如下是rtcConn addon中,binding.gyp部分内容。 首先通过target_name定义了该C++ addon名称,这样会在build目录下生成target_name.node文件。接着包含相关源码文件以及链接用到的第三方库。 [crayon-69c6dd952e58f053908137/] addon.cc 调用用到的各个C++类的Init方法,这些C++类都是按照NAN规定的方式进行wrap,这样我们就可以将这些C++类导出,以addon.cppclass方式调用各个C++类。 [crayon-69c6dd952e593132545720/] 目录中除了binding.gyp,addon.cc,剩下的都是用到的各个C++类NAN方式wrap后的文件。 OWT服务端不同agent代码文件命名,以及代码规范比较乱。这里规定新代码中wrap后的文件名最好加上Wrapper修饰,便于区分。可以参照WebRTC agent中最新的rtcFrame addon(基于WebRTC SDK 实现的一个C++ addon)。 2.3 NAN wrap C++类 我们的C++类都要按照NAN规定的方式wrap,这样Nodejs层才可以调用。 我们有个licode中的erizo::WebRtcConnection(third_party/licode/erizo/src/erizo/WebRtcConnection.h)类,用于处理WebRTC连接相关的配置信息,我们要将它提供给Nodejs层调用。我们可以通过如下方式进行wrap,这里看下wrap后的类头文件大概内容。 [crayon-69c6dd952e597517020151/] 对于C++类要导出的接口使用NAN_METHOD进行修饰。我们要wrap的类作为me成员。 2.3.1 NAN_MODULE_INIT 用于定义该模块的入口函数。在这里注册要使用的C++类接口,这样Nodejs层才可以调用。当Nodejs层执行require('path/xxx.node')的时候,就会执行该函数。 [crayon-69c6dd952e59b294395526/] 2.3.2 NAN_METHOD(New) 构造函数入口,在Nodejs层New一个该C++ wrap类时,就会进入这里。在这里可通过判断Nodejs层传入的参数个数,调用不同的构造函数。 我们通过info.Length()判断传入的参数个数。 2.3.3 NAN_METHOD(setRemoteSdp) 通过这个函数讲下怎么传递参数到C++。这个函数主要传递Nodejs层的字符串参数到C++底层。 [crayon-69c6dd952e59e442715179/] 2.3.4 NAUV_WORK_CB 通过这个函数讲下怎么将C++底层的数据回调到Nodejs层。大概函数调用层次如下: [crayon-69c6dd952e5a2798930063/] 首先按NAN方式定义一个回调 [crayon-69c6dd952e5b1292733245/] 定义一个抽象类,在这里定义回调接口,其实就是常见的观察者模式 [crayon-69c6dd952e5b4200720383/] NAN方式wrap后的类继承前一步定义的抽象类 [crayon-69c6dd952e5b7327806919/] 实现抽象类的回调接口 [crayon-69c6dd952e5ba246421306/] NAN_METHOD(New)中构造对象时,将wrap的类对象传递进去 [crayon-69c6dd952e5bd592640641/] 看下erizo::WebRtcConnection中的实现: [crayon-69c6dd952e5c0299206212/] 通过conn_event_listener_进行各种事件回调: [crayon-69c6dd952e5c2151356587/] 这样回调的信息就会传到NAN这一层,NAN这一层再调用Nodejs层的回调函数,即可将信息回调到Nodejs层。 Nodejs层回调 函数这里我们通过调用定义的init接口获取Nodejs层的回调函数 [crayon-69c6dd952e5c5300604360/] 这里看下Nodejs层代码调用: [crayon-69c6dd952e5c9018735530/] 回调事件队列处理 [crayon-69c6dd952e5cc753516793/] eventsCallback与libuv的绑定在NAN_METHOD(WebRtcConnection::New)中: [crayon-69c6dd952e5cf584019932/] 这样调用uv_async_send(&async_)就会异步执行eventsCallback。 退出时关闭处理 [crayon-69c6dd952e5d3314824659/] 2.4 Nodejs层调用 编译后如下方式引入: [crayon-69c6dd952e5d6761870831/] 构造: [crayon-69c6dd952e5d9802831177/] 传入回调函数: [crayon-69c6dd952e5dc329426242/] 相关接口调用: [crayon-69c6dd952e5de641521257/] 3. 总结 本文简单介绍了目前服务端Nodejs c++ addon开发,通过列举的参数传递,回调例子,对着相关代码过一遍,基本能快速上手。

2020年9月25日 0comments 9hotness 1likes Jeff Read all
Beauty of Programming

Google ProtoBuf协议介绍

Protocol buffers(简称protobuf)是谷歌提供的一种轻便高效的结构化数据存储格式,类似于xml与json,可用于结构化数据的序列化。protobuf是一种二进制格式,比xml更小,更快,更简洁。适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式,能够减少数据传输量。据了解微信(例如微信客户端蓝牙外设协议)与QQ也在使用protobuf,我目前在学习的百度开源的rpc框架brpc也在使用。protobuf目前提供了 C++、Java、Python、Go、C#五种语言的 API。 protobuf原理以及使用官方文档写的很详细了,我就不啰嗦了。具体可以参考谷歌开发者相关文档: 1)protobuf编码原理:https://developers.google.com/protocol-buffers/docs/encoding 2)protobuf使用教程:https://developers.google.com/protocol-buffers/docs/tutorials

2017年11月26日 0comments 2623hotness 3likes Jeff Read all
A/V

Intel Media SDK 内存优化(转)

简介 Media SDK 是一个软件开发库,包含解码、视频处理和编码三大模块。利用 Intel 平台的硬件加速能力, Media SDK 为低端用户提供了优秀的高清视频质量,极大的降低了播放高清视频的硬件门槛。此外,强大的视频 APIs 也减轻了程序开发者的工作负担,使他们能够集中精力去处理程序的逻辑模块,而不必关心于 Media SDK 内部的复杂编解码逻辑及其如何提高效率。 本篇文章将着重讲述如何利用 Media SDK 提高程序的效率,面对的读者主要是视音频程序开发人员。 本文以下内容为: - 初始化设置之优化 - 内存选择之优化 - 多线程之优化 - 异步方式之优化 初始化设置之优化 在讨论优化之前,首先要了解一下 Media SDK 是如何初始化编解码器的。 1. 创建和初始化一个编解码 Session。Media SDK 提供了 mfxStatus MFXInit(mfxIMPL impl,mfxVersion *ver, mfxSession *session)函数来完成这个创建和初始化工作。 2. 使 用 已 创 建 的 Session 来 创 建 它 的 解 码 器 。 Media SDK 提 供 了 mfxStatus MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par)来完成解码器的创建和初始化工作。 3. 使 用 已 创 建 的 Session 来 创 建 它 的 编 码 器 。 Media SDK 提 供 了 mfxStatus MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par)来完成编码器的创建和初始化工作。 在创建和初始化编解码 Session 时,我们需要制定编解码的实现方式:硬件方式还是软件方式。最简单的方法是强制使用硬件方式。这会带来一个问题,在非 Intel 显卡支持的平台,应用程序将无法正常工作。当然,如果强制使用软件方式,虽然应用程序能够工作于其他平台,但是在 Intel 显卡平台,硬件加速特性将荡然无存!虽然应用程序可以外加代码检测平台硬件来决定如何选择,但是程序的复杂度和效率将受到影响。Media SDK 内部提供了自动选择功能,它会根据当前运行系统来选择何种方式。这样就能够兼顾不同平台及其性能。 在 MFXInit 函数中,枚举类型 mfxIMPL 定义 AUTO 功能: [crayon-69c6dd952fd76044073818/] 相应的简单实用方式如下: [crayon-69c6dd952fd7f365129284/] 通过 MFX_IMPL_AUTO 的设置,问题迎刃而解。 那么如何获知当前的编解码实用方法呢?Media SDK 已经考虑到了这种需求,它提供了mfxStatus MFXQueryIMPL(mfxSession session, mfxIMPL *impl)来查询当前采用的方法。 此外,在优化编码器初始化时,程序必须注意 mfxInfoMFX 结构中 TargetUsage 变量的选择,它的定义如下: [crayon-69c6dd952fd83250692962/] TargetUsage 值的选择决定了编码的性能和图像质量,它的值从 0~7,值越高效率越好,但图像质量会有所下降。最佳值应该和用户选择需求挂钩,原则上是略比最小用户需求高 1 级。 本节小结: 1. 初始化 Session 时,要使用 MFX_IMPL_AUTO。它有利于跨越硬件平台,并提高编解码效率。 2. TargetUsage 的选择应该和用户需求相结合。为了提高性能,选择略高于用户最小需求的值为佳。 内存选择之优化 Media SDK 使用内存缓冲来输入/输出视频数据,内存缓冲的不同种类将会直接影响编解码的效率。内存缓冲可以是一块在系统内存中的连续块(通过 malloc 或者 new 来分配),也可以是显卡内存的连续块(通过 Microsoft Direct3D9 Surface 函数来分配)。那么内存缓冲的 种类由谁来决定呢?本节就是以此为基础,讨论在不同情况下程序如何选择内存缓冲种类的问题。 在讨论内存缓冲对编解码影响之前,先讨论下面三种情况下的内存数据传送问题。 - 系统内存间数据如何传送? 对于程序员而言,这个是最为简单的日常编程事项。一般的使用方式是 memcpy,在一些数据较大情况下(超过 L3 的 cache 尺寸时候,用 movntqa 等指令)。不管何种方式,都是CPU-BASED 的代码,在 SIMD 下效率很高。 - 显存间数据是如何传送的? 它类似于系统内存之间的数据传送,并且显存的带宽和速率都很高,传送速度更快。 - 显存和系统内存间数据是如何传送的? 通过 DMA 方式传送内存数据,速度依赖于 DMA 的带宽和速率(普通 DMA 的传送速率在33.3MB/s,而 Ultra DMA 最高也不过 100MB/s)。相比与上述两种情况,它的传送速度明显慢。 从上面的三种情况可以看出,程序一定要尽量避免出现系统内存和显存之间的数据传送,那么 Media SDK 在什么配置下会出现此类尴尬状态呢? 初始化设置之优化小节中,程序通过 MFX_IMPL_AUTO 参数根据当前平台来自动选择硬件或软件编解码,并能通过 mfxStatus MFXQueryIMPL(mfxSession session, mfxIMPL *impl)函数来获取当前平台的编解码方式,在此将获取的编码方式分别讨论。 a)使用硬件编解码方式 硬件编解码方式主要是通过显卡的硬件加速达到高效编解码的作用,也就是说它的核心是显卡。如果我们使用系统内存为其提供缓存,会出现什么情况呢?显然,在数据输出/输出时,程序必将会有显存和系统内存之间的数据传送作用,效能将受到严重影响。在此情况下,程序的最好选择就是显存,否则必将受到性能惩罚! b)使用软件编解码方式 很显然,软件编解码的核心是 CPU。如果我们使用显存作为其缓冲,那么必将导致显存和系统内存之间的数据交互,也就会导致速度低下的程序出现,故此,系统内存是它的不二选择! 本节小结: Media SDK 中内存类型的选择分两步走: 1. 使用 MFXQueryIMPL 函数来查询当前的编解码方式。 2. 根据编解码方式(MFX_IMPL_SOFTWARE 为软件;MFX_IMPL_HARDWARE 为硬件)来决定内存选用类型。为了便于日后方便查询,笔者建立了一个小表格,如表 1 所示,以供参考。 此外,笔者对 Media SDK 的两种不同内存类型在解码器下做了一个简单的比较。在软件解码方式下,显存选取要比内存选取慢了近 1 倍,这个是相当可观的数字!切忌,正确选取内存是高效程序的基本点! 多线程之优化 初始化设置之优化小节和内存选择之优化小节中,已经对 Media SDK 的两个重要配置部分进行了分析和总结。本节,我们将着重讨论如何使用多线程技术提高视频 Converter 的效能(一种视频的常用应用)。 在运用 Media SDK 进行格式转换时,一般要涉及三大模块,他们是 Decoder,VPP 和 Encoder,数据输入输出如图 1 所示。 从图 1 可以看出,每经过一个模块,都要对数据进行同步操作。在此期间,其他两个模块是处于空闲状态,是一个典型的串行处理过程。对于英特尔的多核技术,它的多核利用率是最低的,相应的效率也较差。 那么如何对现有流程进行多线程化呢? 本节提供了一种最简单的方法,即对每个模块线程化。请参考图 2 所示。 图 2 将 Decoder,VPP 和 Encoder 三个模块分别线程化,在彼此之间以队列(queue)为数据交换。 简单的工作模式如下: - 若队列为空,后级模块等待数据。 -…

2016年10月7日 0comments 3052hotness 5likes Jeff Read all
Beauty of Programming

网络字节转换到本地字节的函数模板

在做视频文件解析开发时,经常需要进行网络字节到本地字节的转换。在视频文件中,相关数据是以网络字节存储的,比如视频的宽,定义为uint_32类型,读取时我们需要转换为本地字节序才可以得到正确结果。 操作系统自带api可以帮助我们进行字节序的转换,如下所示函数与具体平台无关: [crayon-69c6dd9530818048431664/] 我们也可以用c++函数模板实现一个,方便使用,我一般都是用自己的函数模板的: [crayon-69c6dd9530820601705058/]

2016年5月28日 0comments 1483hotness 0likes Jeff Read all
Beauty of Programming

解决Ubuntu下vlc无法播放文件

最近在linux下使用VLC播放器,之前都可以好好播放的,可是手贱卸载重装了一次,之后都无法播放任何文件,总是如下提示: [crayon-69c6dd95311b7446022238/] 后来使用了: [crayon-69c6dd95311c0035961239/] 卸载也是不行,重新安装还是会报Your input can't be opened:VLC is unable to open the MRL的错误,后来通过如下命令卸载解决: [crayon-69c6dd95311c4201555226/] 之后重新sudo apt-get install vlc就可以正常播放了。

2015年12月25日 0comments 3854hotness 11likes Jeff Read all
Beauty of Programming

MFC WebBrowser控件如何实现滚动条滑动

最近在写一个自动刷流量的程序,用到了WebBrowser 控件,通过该控件往程序嵌入一个IE浏览器,MFC中如何嵌入该控件可以看下参考链接1。 由于要自动刷流量,所以就要模仿用户平时浏览网页的习惯,也就是打开网页,然后慢慢向下滚动鼠标。在程序中我是通过滑动右侧滚动条实现的。刚开始我的代码是参照链接3给的,不过该代码在有些网页下实现不了滚动条滑动,也就是没反应。我上网Google了下,发现好多人也遇到类似情况,比如链接2与链接4中的内容,不过都没人给出答案。我自己也试了好多种方法,比如修改WebBrowser的IE版本,最后也都是以失败告终。 过了几天在Google上搜索,无意间看到一段代码,试了下,有效果,在不同类型网页下都可以顺利滚动。哈哈哈。废话不多说,直接上代码: [crayon-69c6dd9531b4b870000288/] 通过上面函数的代码我们就可以实现WebBrowser向下滑动100像素。需要提醒的是,如果编译器提示undeclared identifier错误,我们需要包含mshtml.h文件。 [crayon-69c6dd9531b54696888219/] 到此就大功告成了,用定时器结合该代码就可以实现一个自动刷流量的程序,详细的我就不说了。 参考链接: 1)VC中调用WebBrowser简单的实现过程(图解过程) 2)如何获得webBrowser控件滚动条滑块的位置问题补充 - VC/MFC / 界面 3)Programmatically scrolling WebBrowser control from Visual C/C++ 4)webbrowser control: auto scroll + total webpage size

2015年7月21日 0comments 2150hotness 0likes Jeff Read all
Beauty of Programming

PortAudio捕获输出音频

记得前面说到使用PortAudio抓取声卡输出音频,通过PortAudio确实可以实现,但是我研究发现无法基于PortAudio使用Wasapi抓取计算机输出音频,PortAudio只能使用Wasapi抓取麦克风的输入音频,而不能抓取计算机播放的声音。 先说下PortAudio如何抓取声卡输出: 1)条件:不开启立体声混音。首先我们要枚举所有设备,然后获取各个设备信息,得到设备的HostApiType,代码实现如下: [crayon-69c6dd95324e1952316806/] 在上述代码中我们传入设备Index参数获取HostApi类型,PortAudio中定义的HostApi有如下几种类型: [crayon-69c6dd95324e8929942254/] 通过枚举所有设备我们获取ApiType为paWDMKS的设备,并且该设备的maxInputChannels参数不能为0,接下来在Pa_OpenStream函数传入的参数中设置该设备为目标设备即可,在回调函数中实现录音即可抓取计算机输出的音频,即Capture what we hear from the speaker. 2)开启立体声混音。同样要枚举所有设备,这次我们要获取ApiType为paWASAPI的设备,该设备的maxInputChannels参数不能为0(不开启立体声混音只有麦克风满足这两个条件),而且通过Pa_GetDeviceInfo( deviceIndex )->name获取到的设备名不能含有麦克风字样,最后按前面所说方法传入该设备Index即可抓取音频。 真正通过Wasapi 抓取音频是无所谓开不开启立体声混音的,通过Wasapi捕获音频有个条件是被捕获的设备要工作在loopback模式下,可以看下MSDN上的这篇文章:Loopback Recording。 通过Wasapi如何捕获音频,微软给出了示例代码:https://code.msdn.microsoft.com/windowsapps/Windows-Audio-Session-22dcab6b#content。由于我的系统不是win8,VS版本达不到要求,故没去编译这个示例代码。 这个链接是微软员工写的通过Wasapi捕获音频代码:http://blogs.msdn.com/b/matthew_van_eerde/archive/2014/11/05/draining-the-wasapi-capture-buffer-fully.aspx。这个代码确实可以捕获输出音频。

2015年7月15日 0comments 2983hotness 3likes Jeff Read all
Beauty of Programming

MFC自绘带背景颜色标题栏

最近在写一个EDID文件生成器,可以根据输入的一些参数生成EDID文件,大多数字节是固定的,主要是详细时序这几个字节的计算,界面用的是MFC,不过我重绘了,因为MFC原生界面太丑了。下图是EDID生成器初步的效果: 本文主要讲怎么绘制带颜色的标题栏,就像上图的蓝色背景标题栏。 1)首先是根据向导创建一个普通对话框程序,然后修改对话框Border属性为None。 2)在void XXXXDlg::OnPaint()函数中加入如下绘制代码: [crayon-69c6dd9532e50483510893/] 代码中我除了绘制标题栏,还绘制了程序底部的边框。 3)响应鼠标点击标题栏消息,实现鼠标拖动。在对话框的OnLButtonDown消息中添加如下代码: [crayon-69c6dd9532e57488993742/] 到此就大功告成了,实现了一个蓝色背景的标题栏。在后面的文章中我还会介绍如何完善该标题栏,加入关闭,最小化按钮。

2015年6月25日 4comments 5210hotness 8likes Jeff Read all
12345…7
Copyright Statement

Unauthorized reproduction or plagiarism in any form is strictly prohibited. For reprint requests, please contact via email.

Recent Comments
snail Published at 10 hours ago(03 03202633105 27 27pm26) 多谢,大佬。醍醐灌顶!
Bramsnawl Published at 17 hours ago(03 03202633110 27 27am26) Proper blood collection playing cards are measure ...
NasibDepdrotte Published at 1 days ago(03 03202633110 26 26pm26) Inf ect isC linNo rth A m viiiix, Sm ets o urgo is...
Pereplanirovka kvartir_cvsr Published at 2 days ago(03 03202633105 25 25pm26) перепланировка услуги [url=https://pereplanirovka-...
Mirzoemele Published at 3 months ago(01 01202613104 06 06pm26) Double blind randomised controlled trial of two to...
Ad

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang