Skip to content
This repository was archived by the owner on Oct 23, 2024. It is now read-only.

Commit 88e75ff

Browse files
authored
Implement selective top K audio mixer (#687)
* Implement selective top K audio mixer (#566) * Fix rebase issue
1 parent 1222300 commit 88e75ff

23 files changed

+1297
-2
lines changed

scripts/build.json

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"logger",
99
"media-frame-multicaster",
1010
"audio",
11+
"audio-ranker",
1112
"webrtc",
1213
"avstream",
1314
"gst-pipeline",
@@ -22,6 +23,7 @@
2223
"logger",
2324
"media-frame-multicaster",
2425
"audio",
26+
"audio-ranker",
2527
"webrtc",
2628
"avstream",
2729
"sip"
@@ -96,6 +98,12 @@
9698
},
9799
"logger" : {
98100
"path" : "source/agent/addons/logger"
101+
},
102+
"audio-ranker" : {
103+
"path" : "source/agent/addons/audioRanker"
104+
},
105+
"audio-ranker-test" : {
106+
"path" : "source/agent/addons/audioRanker/test"
99107
}
100108
,
101109
"quicIO" : {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (C) <2019> Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "AudioRankerWrapper.h"
6+
#include "MediaFramePipelineWrapper.h"
7+
8+
using namespace v8;
9+
10+
Nan::Persistent<Function> AudioRanker::constructor;
11+
12+
AudioRanker::AudioRanker() {}
13+
AudioRanker::~AudioRanker() {}
14+
15+
NAN_MODULE_INIT(AudioRanker::Init) {
16+
// Prepare constructor template
17+
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
18+
tpl->SetClassName(Nan::New("AudioRanker").ToLocalChecked());
19+
tpl->InstanceTemplate()->SetInternalFieldCount(1);
20+
21+
// Prototype
22+
Nan::SetPrototypeMethod(tpl, "close", close);
23+
Nan::SetPrototypeMethod(tpl, "addOutput", addOutput);
24+
Nan::SetPrototypeMethod(tpl, "addInput", addInput);
25+
Nan::SetPrototypeMethod(tpl, "removeInput", removeInput);
26+
27+
constructor.Reset(tpl->GetFunction());
28+
Nan::Set(target, Nan::New("AudioRanker").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
29+
}
30+
31+
NAN_METHOD(AudioRanker::New) {
32+
if (info.Length() < 1) {
33+
Nan::ThrowError("Wrong number of arguments");
34+
}
35+
36+
if (info.IsConstructCall()) {
37+
AudioRanker* obj = new AudioRanker();
38+
39+
obj->asyncResource_ = new Nan::AsyncResource("RankChange");
40+
obj->callback_ = new Nan::Callback(info[0].As<Function>());
41+
uv_async_init(uv_default_loop(), &obj->async_, &AudioRanker::Callback);
42+
43+
if (info.Length() > 2) {
44+
bool detectMute = Nan::To<bool>(info[1]).FromJust();
45+
int changeInterval = Nan::To<int>(info[2]).FromJust();
46+
obj->me = new owt_base::AudioRanker(obj, detectMute, changeInterval);
47+
} else {
48+
obj->me = new owt_base::AudioRanker(obj);
49+
}
50+
51+
obj->Wrap(info.This());
52+
info.GetReturnValue().Set(info.This());
53+
} else {
54+
// Not construct call
55+
}
56+
}
57+
58+
NAN_METHOD(AudioRanker::close) {
59+
AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder());
60+
61+
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&obj->async_))) {
62+
uv_close(reinterpret_cast<uv_handle_t*>(&obj->async_), NULL);
63+
}
64+
65+
delete obj->me;
66+
obj->me = nullptr;
67+
delete obj->callback_;
68+
delete obj->asyncResource_;
69+
}
70+
71+
NAN_METHOD(AudioRanker::addOutput) {
72+
AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder());
73+
owt_base::AudioRanker* me = obj->me;
74+
75+
FrameDestination* param = node::ObjectWrap::Unwrap<FrameDestination>(info[0]->ToObject());
76+
owt_base::FrameDestination* dest = param->dest;
77+
78+
me->addOutput(dest);
79+
}
80+
81+
NAN_METHOD(AudioRanker::addInput) {
82+
AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder());
83+
owt_base::AudioRanker* me = obj->me;
84+
85+
FrameSource* param = node::ObjectWrap::Unwrap<FrameSource>(info[0]->ToObject());
86+
owt_base::FrameSource* src = param->src;
87+
88+
Nan::Utf8String streamIdPara(Nan::To<v8::String>(info[1]).ToLocalChecked());
89+
std::string streamId = std::string(*streamIdPara);
90+
91+
Nan::Utf8String ownerIdPara(Nan::To<v8::String>(info[2]).ToLocalChecked());
92+
std::string ownerId = std::string(*ownerIdPara);
93+
94+
me->addInput(src, streamId, ownerId);
95+
}
96+
97+
NAN_METHOD(AudioRanker::removeInput) {
98+
AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder());
99+
owt_base::AudioRanker* me = obj->me;
100+
101+
Nan::Utf8String streamIdPara(Nan::To<v8::String>(info[0]).ToLocalChecked());
102+
std::string streamId = std::string(*streamIdPara);
103+
104+
me->removeInput(streamId);
105+
}
106+
107+
void AudioRanker::onRankChange(std::vector<std::pair<std::string, std::string>> updates) {
108+
boost::mutex::scoped_lock lock(mutex);
109+
std::ostringstream jsonChange;
110+
/*
111+
* The JS callback json
112+
* [
113+
* ["streamID0", "ownerID0"],
114+
* ["streamID1", "ownerID1"],
115+
* ......
116+
* ["streamIDn", "ownerIDn"]
117+
* ]
118+
*/
119+
jsonChange.str("");
120+
jsonChange << "[";
121+
for (size_t i = 0; i < updates.size(); i++) {
122+
jsonChange << "[\"" << updates[i].first << "\",\""
123+
<< updates[i].second << "\"]";
124+
if (i + 1 < updates.size()) {
125+
jsonChange << ",";
126+
}
127+
}
128+
jsonChange << "]";
129+
this->jsonChanges.push(jsonChange.str());
130+
async_.data = this;
131+
uv_async_send(&async_);
132+
}
133+
134+
NAUV_WORK_CB(AudioRanker::Callback) {
135+
Nan::HandleScope scope;
136+
AudioRanker* obj = reinterpret_cast<AudioRanker*>(async->data);
137+
if (!obj || obj->me == NULL)
138+
return;
139+
boost::mutex::scoped_lock lock(obj->mutex);
140+
while (!obj->jsonChanges.empty()) {
141+
Local<Value> args[] = {Nan::New(obj->jsonChanges.front().c_str()).ToLocalChecked()};
142+
obj->asyncResource_->runInAsyncScope(
143+
Nan::GetCurrentContext()->Global(), obj->callback_->GetFunction(), 1, args);
144+
obj->jsonChanges.pop();
145+
}
146+
}
147+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (C) <2019> Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef AUDIORANKERWRAPPER_H
6+
#define AUDIORANKERWRAPPER_H
7+
8+
#include <AudioRanker.h>
9+
#include <nan.h>
10+
11+
12+
/*
13+
* Wrapper class of owt_base::AudioRanker
14+
*/
15+
class AudioRanker : public Nan::ObjectWrap,
16+
public owt_base::AudioRanker::Visitor {
17+
public:
18+
static NAN_MODULE_INIT(Init);
19+
owt_base::AudioRanker* me;
20+
21+
boost::mutex mutex;
22+
std::queue<std::string> jsonChanges;
23+
24+
void onRankChange(
25+
std::vector<std::pair<std::string, std::string>> updates) override;
26+
27+
private:
28+
AudioRanker();
29+
~AudioRanker();
30+
31+
Nan::Callback *callback_;
32+
uv_async_t async_;
33+
Nan::AsyncResource *asyncResource_;
34+
35+
static Nan::Persistent<v8::Function> constructor;
36+
37+
static NAN_METHOD(New);
38+
39+
static NAN_METHOD(close);
40+
41+
static NAN_METHOD(addOutput);
42+
43+
static NAN_METHOD(addInput);
44+
45+
static NAN_METHOD(removeInput);
46+
47+
static NAUV_WORK_CB(Callback);
48+
49+
};
50+
51+
#endif
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (C) <2019> Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "AudioRankerWrapper.h"
6+
#include <nan.h>
7+
8+
using namespace v8;
9+
10+
NODE_MODULE(addon, AudioRanker::Init)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
'targets': [{
3+
'target_name': 'audioRanker',
4+
'sources': [
5+
'addon.cc',
6+
'AudioRankerWrapper.cc',
7+
'../../../core/owt_base/selector/AudioRanker.cpp',
8+
'../../../core/owt_base/MediaFramePipeline.cpp',
9+
'../../../core/common/IOService.cpp',
10+
],
11+
'include_dirs': [
12+
"<!(node -e \"require('nan')\")",
13+
'../common',
14+
'../../../core/common/',
15+
'../../../core/owt_base/',
16+
'../../../core/owt_base/selector/',
17+
],
18+
'libraries': [
19+
'-lboost_thread',
20+
'-llog4cxx',
21+
],
22+
'conditions': [
23+
[ 'OS=="mac"', {
24+
'xcode_settings': {
25+
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', # -fno-exceptions
26+
'MACOSX_DEPLOYMENT_TARGET': '10.7', # from MAC OS 10.7
27+
'OTHER_CFLAGS': ['-g -O$(OPTIMIZATION_LEVEL) -stdlib=libc++']
28+
},
29+
}, { # OS!="mac"
30+
'cflags!': ['-fno-exceptions'],
31+
'cflags_cc': ['-Wall', '-O$(OPTIMIZATION_LEVEL)', '-g', '-std=c++11'],
32+
'cflags_cc!': ['-fno-exceptions']
33+
}],
34+
]
35+
}]
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
'targets': [{
3+
'target_name': 'audioRankerTest',
4+
'type': 'executable',
5+
'sources': [
6+
'../../../../core/owt_base/selector/AudioRankerTest.cpp',
7+
'../../../../core/owt_base/selector/AudioRanker.cpp',
8+
'../../../../core/owt_base/MediaFramePipeline.cpp',
9+
'../../../../core/common/IOService.cpp',
10+
],
11+
'include_dirs': [
12+
"<!(node -e \"require('nan')\")",
13+
'../../common',
14+
'../../../../core/common/',
15+
'../../../../core/owt_base/',
16+
'../../../../core/owt_base/selector/',
17+
],
18+
'libraries': [
19+
'-lboost_thread',
20+
'-lboost_system',
21+
'-lboost_exception',
22+
'-llog4cxx',
23+
'-lboost_unit_test_framework'
24+
],
25+
'conditions': [
26+
[ 'OS=="mac"', {
27+
'xcode_settings': {
28+
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', # -fno-exceptions
29+
'MACOSX_DEPLOYMENT_TARGET': '10.7', # from MAC OS 10.7
30+
'OTHER_CFLAGS': ['-g -O$(OPTIMIZATION_LEVEL) -stdlib=libc++']
31+
},
32+
}, { # OS!="mac"
33+
'cflags!': ['-fno-exceptions'],
34+
'cflags_cc': ['-Wall', '-O$(OPTIMIZATION_LEVEL)', '-g', '-std=c++11'],
35+
'cflags_cc!': ['-fno-exceptions'],
36+
'cflags_cc!' : ['-fno-rtti']
37+
}],
38+
]
39+
}]
40+
}

source/agent/addons/mediaFrameMulticaster/MediaFrameMulticasterWrapper.cc

+45
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,38 @@
1010

1111
using namespace v8;
1212

13+
Persistent<Function> MulticasterSource::constructor;
14+
15+
MulticasterSource::MulticasterSource() {};
16+
MulticasterSource::~MulticasterSource() {};
17+
18+
void MulticasterSource::Init(Handle<Object> exports, Handle<Object> module) {
19+
Isolate* isolate = exports->GetIsolate();
20+
21+
// Constructor for FrameSource
22+
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
23+
tpl->SetClassName(String::NewFromUtf8(isolate, "MulticasterSource"));
24+
tpl->InstanceTemplate()->SetInternalFieldCount(1);
25+
26+
constructor.Reset(isolate, tpl->GetFunction());
27+
}
28+
29+
void MulticasterSource::New(const FunctionCallbackInfo<Value>& args) {
30+
Isolate* isolate = Isolate::GetCurrent();
31+
HandleScope scope(isolate);
32+
33+
if (args.Length() > 0) {
34+
MediaFrameMulticaster* parent = ObjectWrap::Unwrap<MediaFrameMulticaster>(args[0]->ToObject());
35+
MulticasterSource* obj = new MulticasterSource();
36+
obj->me = parent->me;
37+
obj->src = obj->me;
38+
obj->Wrap(args.This());
39+
args.GetReturnValue().Set(args.This());
40+
}
41+
}
42+
1343
Persistent<Function> MediaFrameMulticaster::constructor;
44+
1445
MediaFrameMulticaster::MediaFrameMulticaster() {};
1546
MediaFrameMulticaster::~MediaFrameMulticaster() {};
1647

@@ -24,9 +55,13 @@ void MediaFrameMulticaster::Init(Handle<Object> exports, Handle<Object> module)
2455
NODE_SET_PROTOTYPE_METHOD(tpl, "close", close);
2556
NODE_SET_PROTOTYPE_METHOD(tpl, "addDestination", addDestination);
2657
NODE_SET_PROTOTYPE_METHOD(tpl, "removeDestination", removeDestination);
58+
NODE_SET_PROTOTYPE_METHOD(tpl, "source", source);
2759

2860
constructor.Reset(isolate, tpl->GetFunction());
2961
module->Set(String::NewFromUtf8(isolate, "exports"), tpl->GetFunction());
62+
63+
// Init MulticasterSource
64+
MulticasterSource::Init(exports, module);
3065
}
3166

3267
void MediaFrameMulticaster::New(const FunctionCallbackInfo<Value>& args) {
@@ -89,3 +124,13 @@ void MediaFrameMulticaster::removeDestination(const FunctionCallbackInfo<Value>&
89124
}
90125
}
91126

127+
void MediaFrameMulticaster::source(const FunctionCallbackInfo<Value>& args) {
128+
Isolate* isolate = Isolate::GetCurrent();
129+
HandleScope scope(isolate);
130+
131+
const int argc = 1;
132+
v8::Local<v8::Value> argv[argc] = {args.Holder()};
133+
v8::Local<v8::Function> cons = Nan::New(MulticasterSource::constructor);
134+
args.GetReturnValue().Set(Nan::NewInstance(cons, 1, argv).ToLocalChecked());
135+
}
136+

0 commit comments

Comments
 (0)