关于nodejs通过ffi调用多线程库
发布于 10 年前 作者 peterfuture 10635 次浏览 最后一次编辑是 8 年前

遇到个问题,哪位大牛给个解决方法 应用:nodejs 通过 ffi调用 c库,c库为多播放器(多线程库) 贴一下部分代码: var dtplib =ffi.Library(‘vendor/linux_x64/libdtp’, { “player_register_all”:[‘void’,[]], “dtplayer_init”:[‘pointer’,[dtp_para_ptr]], “dtplayer_start”:[‘int’,[voidptr]], } );

var dtp_cb = ffi.Callback(‘void’,[dtp_state_ptr],function(state) { }); function dtplayer§ { var para = p; var priv; if(!para.update_cb) para.update_cb = dtp_cb;

this.bindEvents();
events.EventEmitter.call(this);
console.log('[node-js] : dtplayer constructer');

} dtplayer.prototype.play = function() { var self = this; dtplib.player_register_all(); priv = dtplib.dtplayer_init(para.ref()); dtplib.dtplayer_start(priv); this.emit(‘playing’); } dtplayer.prototype.bindEvents = function() { this.on(‘playing’,function(){console.log(“receive playing signal”)}); this.on(‘update_info’,function(state) { console.log(“cur time:” + state.deref().cur_time); }
); } 这里调用start启动播放后,播放器内部会启动多个线程进行解码播放,但上层play执行完毕后就退出了 这里有个函数指针 dtp_cb传递进去,经过测试可以调用到,但dtp_cb并不属于dtplayer这个类,因此不能通过this.emit等定时触发回调 完整代码:https://github.com/peterfuture/node-dtplayer/blob/node-demo/libs/dtplayer.js

12 回复

https://github.com/rbranson/node-ffi/wiki/Node-FFI-Tutorial#async-library-calls

這個教程看來有幫助 ?

<pre> dtplib.dtplayer_start.async(???, function (err, res) { //empty });

dtplib.dtplayer_start(priv, function callback(err, res) { if (err) throw new Error(“oops”) //code here… }); </pre>

非常感谢 @mondwan 通过上面调用方式可以保证线程不退出了 这里还有个问题就是:当async方式调用之后,就不能继续发送命令了 如再加上一个dtplib.dtplayer_pause() 在start之后若需要pause,则不会执行 对于此种case,有没有好的办法呢?

不太清楚你的意思. codes on github? <pre> dtplib.dtplayer_start(priv, function callback(err, res) { if (err) throw new Error(“oops”) dtplib.dtplayer_pause() // Pause after start callback fired }); </pre>

@mondwan 对于播放视频来讲,当启动播放之后,还有可能会暂停 现在的调用我感觉是 当调用dtplayer_start.async()之后会一直等待播放结束 也就是说我若这样调用: dtplib.dtplayer_start.async(priv,function(err,res){}); dtplib.dtplayer_pause(priv); 那么pause调用是不会执行到的。除非播放完成。 不知这样描述 你能否明白我的意思 github上代码 我刚更新了下, 还在开发中,比较乱 :)

@mondwan 是否可以做到这样: 本身是有个回调 dtp_cb会定期 执行的 但现在并不是dtplayer的成员,导致不能重复emit事件,若能将此回调函数修改成dtplayer的成员 那么每次回调执行的时候emit一个事件 是否可以 1 保持底层线程不退出 2 还可以接受其他的调用如pause等

@mondwan https://github.com/peterfuture/node-dtplayer/tree/node-demo 刚做了些修改,github下的目录 看example/player.js,现在调用方式如下: var ply = new dtplayer(); var dtp_cb = ffi.Callback(‘void’,[dtp_state_ptr],function(state) { console.log(‘update info’); ply.emit(‘update_info’); }); var para = new dtp_para(); para.file_name = “…/1.aac”; para.no_audio = -1; para.no_video = -1; para.width = 720; para.width = 720; para.height = 480; para.update_cb = dtp_cb;

ply.init(para); ply.start();

在dtplayer类定义里监听update_info事件, 在调用的地方的回调dtp_cb中 会触 发emit(‘update_info’) 由于回调定期会来,因此可以通过事件不停的触发来维持程序的运转。

但实际情况是 会触发依次,但后面就退出了,应该还是某个地方没做好

沒用過這個library 以下只是猜測…

我想 <pre> this.priv = dtplib.dtplayer_init(this.para.ref()); dtplib.dtplayer_start(this.priv); </pre> 這兩句 把dtp_cb() 和 dtplayer_start() 勾起來 觸發數次 後面退出 應該是都播放完了吧? 你可以用async() 掛一個 onEnd Handler() 驗證一下 <pre><code> dtplib.dtplayer_start.async(???, function (err, res) { //empty });

dtplib.dtplayer_start(priv, function callback(err, res) { if (err) throw new Error(“oops”) console.log(“player end”);. }); </code></pre>

這兩句 把dtp_cb() 和 dtplayer_start() 勾起來 觸發數次 後面退出 re: 是的,启动后在dtp_cb是可以通过emit触发 dtplayer类监听的 events

你可以用async() 掛一個 onEnd Handler() 驗證一下 re: 这个具体是什么意思,我之前是这样写的 dtplib.dtplayer_start.async(priv, function(err,res){ console.log(‘play_end’); }); 但你上面 两个 dtplib.dtplayer_start.async(???, function (err, res) 。。。 dtplib.dtplayer_start(priv, function callback(err, res) {。。。 我不太清楚,需要这样定义两次吗 还有一旦用了async ,是需要一直播放到结束,期间你再调用其他函数,是不会响应的吧

问题解决了: 添加了个定时器,定时触发事件,保证进程不退出,当播放结束后,清除定时器,代码如下 dtplayer.prototype.startTimer = function() { this.beat_timer = setInterval(function() { // do nothing },1000); // exec 1/1s } dtplayer.prototype.stopTimer = function() { if(beat_timer) clearInterval(beat_timer); }

处理方式太土了, 哪位同学有更好的办法,请告知,谢谢!
Thanks again @mondwan

能提供一個網址讓我測試嗎? 我想從GitHub上clone 來測試 但我不知道應該填什麼url在 player.js?

https://github.com/peterfuture/node-dtplayer 最新的更新已经可以跑起来了 但由于本身需要依赖ffmpeg和 alsa, 因此可能跑不起来不大容易 简单步骤如下 1 install alsa & ffmpeg 2 git clone https://github.com/peterfuture/node-dtplayer 3 test: node example/player.js url (url是与音频文件的本地目录) 说明:目前只支持Linux系统 和 audio , 稍后会支持video 若跑不起来,请告诉错误,谢谢!

node-dtplayer的目标是做一个nodejs封装的播放器: 同时支持 在线视频 和 本地视频

回到顶部