Skip to content

Commit

Permalink
MediaStream support
Browse files Browse the repository at this point in the history
  • Loading branch information
markandrus committed Jun 12, 2018
1 parent 9aaa9c1 commit 83ad156
Show file tree
Hide file tree
Showing 21 changed files with 950 additions and 56 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Expand Up @@ -22,6 +22,7 @@ list(REMOVE_ITEM MODULE_SRC_WITHOUT_WEBRTC

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${MODULE} PRIVATE -DDEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
endif()

target_include_directories(${MODULE} PRIVATE ${CMAKE_SOURCE_DIR})
Expand Down Expand Up @@ -74,7 +75,8 @@ if(APPLE)
-DWEBRTC_POSIX=1)

target_link_libraries(${MODULE} PRIVATE
"-framework AppKit")
"-framework AppKit"
"-framework AVFoundation")
elseif(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
target_compile_definitions(${MODULE} PRIVATE
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -2,6 +2,7 @@

var binding = require('./binding');

exports.MediaStream = binding.MediaStream;
exports.MediaStreamTrack = binding.MediaStreamTrack;
exports.RTCDataChannel = require('./datachannel');
exports.RTCDataChannelEvent = require('./datachannelevent');
Expand Down
5 changes: 3 additions & 2 deletions lib/peerconnection.js
Expand Up @@ -20,11 +20,12 @@ function RTCPeerConnection() {
//
// Attach events to the native PeerConnection object
//
pc.ontrack = function ontrack(receiver) {
pc.ontrack = function ontrack(receiver, streams) {
self.dispatchEvent({
type: 'track',
track: receiver.track,
receiver: receiver
receiver: receiver,
streams: streams
});
};

Expand Down
202 changes: 202 additions & 0 deletions src/bidimap.h
@@ -0,0 +1,202 @@
/* Copyright (c) 2018 The node-webrtc project authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license that can be found
* in the LICENSE.md file in the root of the source tree. All contributing
* project authors may be found in the AUTHORS file in the root of the source
* tree.
*/
#ifndef SRC_BIDIMAP_H_
#define SRC_BIDIMAP_H_

#include <functional>
#include <map>
#include <utility>

#include "src/functional/maybe.h"
#include "src/functional/operators.h"

namespace node_webrtc {

/**
* A BidiMap is a "bidirectional map" supporting get and set operations on both
* keys and values.
* @tparam K the type of keys
* @tparam V the type of values
*/
template <typename K, typename V>
class BidiMap {
public:
/**
* Construct an empty BidiMap.
*/
BidiMap() = default;

/**
* Remove all keys and values from the BidiMap.
*/
void clear() {
_keyToValue.clear();
_valueToKey.clear();
}

/**
* Compute, set, and return a key's value if it's absent; otherwise, return
* the key's value.
* @param key
* @param computeValue
* @return the existing or newly set value
*/
V computeIfAbsent(K key, std::function<V()> computeValue) {
return get(key).Or([this, key, computeValue]() {
auto value = computeValue();
this->set(key, value);
return value;
});
}

/**
* Get the key's value from the BidiMap.
* @param key
* @return Nothing if the key was not present
*/
Maybe<V> get(K key) const {
return has(key)
? Maybe<V>::Just(_keyToValue.at(key))
: Maybe<V>::Nothing();
}

/**
* Check if the BidiMap contains a value for the key.
* @param key
* @return true if the BidiMap contains a value for the key
*/
bool has(K key) const {
return _keyToValue.count(key) > 0;
}

/**
* Remove the key and its value from the BidiMap.
* @param key
* @return Nothing if the key was not present
*/
Maybe<V> remove(K key) {
return [this, key](V value) {
this->_keyToValue.erase(key);
this->_valueToKey.erase(value);
return value;
} % get(key);
}

/**
* Return a BidiMap with its keys and values swapped.
* @return a BidiMap with its keys and values swapped
*/
BidiMap<V, K> reverse() const {
return BidiMap<V, K>(_valueToKey, _keyToValue);
}

/**
* Compute, set, and return a value's key if it's absent; otherwise, return
* the value's key.
* @param value
* @param computeKey
* @return the existing or newly set key
*/
K reverseComputeIfAbsent(V value, std::function<K()> computeKey) {
return reverseGet(value).Or([this, value, computeKey]() {
auto key = computeKey();
this->reverseSet(value, key);
return key;
});
}

/**
* Get the value's key from the BidiMap.
* @param value
* @return Nothing if the value was not present
*/
Maybe<K> reverseGet(V value) const {
return reverseHas(value)
? Maybe<K>::Just(_valueToKey.at(value))
: Maybe<K>::Nothing();
}

/**
* Check if the BidiMap contains a key for the value.
* @param value
* @return true if the BidiMap contains a key for the value
*/
bool reverseHas(V value) const {
return _valueToKey.count(value) > 0;
}

/**
* Remove a value and its key from the BidiMap.
* @param value
* @return Nothing if the value was not present
*/
Maybe<K> reverseRemove(V value) {
return [this, value](K key) {
this->_keyToValue.erase(key);
this->_valueToKey.erase(value);
return key;
} % reverseGet(value);
}

/**
* Set a value and its key in the BidiMap.
* @param value
* @param key
* @return a pair of the previously set key (if any) and the previously set
* value (if any)
*/
std::pair<Maybe<K>, Maybe<V>> reverseSet(V value, K key) {
auto pair = std::make_pair(reverseGet(value), get(key));
remove(key);
_valueToKey[value] = key;
_keyToValue[key] = value;
return pair;
}

/**
* Set a key and its value in the BidiMap.
* @param key
* @param value
* @return a pair of the previously set value (if any) and the previously set
* key (if any)
*/
std::pair<Maybe<V>, Maybe<K>> set(K key, V value) {
auto pair = std::make_pair(get(key), reverseGet(value));
reverseRemove(value);
_keyToValue[key] = value;
_valueToKey[value] = key;
return pair;
}

/**
* Construct a BidiMap from a map.
* @param map
* @return Nothing if the map contains duplicate values
*/
static Maybe<BidiMap<K, V>> FromMap(std::map<K, V> map) {
BidiMap<K, V> bidiMap;
for (auto pair : map) {
auto previousKey = bidiMap.reverseSet(pair.second, pair.first);
if (previousKey.IsJust()) {
return Maybe<BidiMap<K, V>>::Nothing();
}
}
return Maybe<BidiMap<K, V>>::Just(bidiMap);
}

private:
BidiMap(const std::map<K, V>& keyToValue, const std::map<V, K>& valueToKey)
: _keyToValue(keyToValue), _valueToKey(valueToKey) {}

std::map<K, V> _keyToValue;
std::map<V, K> _valueToKey;
};

} // namespace node_webrtc

#endif // SRC_BIDIMAP_H_
2 changes: 2 additions & 0 deletions src/binding.cc
Expand Up @@ -8,6 +8,7 @@
#include "node.h"

#include "datachannel.h"
#include "mediastream.h"
#include "mediastreamtrack.h"
#include "rtcrtpreceiver.h"
#include "rtcstatsreport.h"
Expand All @@ -26,6 +27,7 @@ void init(Handle<Object> exports) {
node_webrtc::PeerConnectionFactory::Init(exports);
node_webrtc::PeerConnection::Init(exports);
node_webrtc::DataChannel::Init(exports);
node_webrtc::MediaStream::Init(exports);
node_webrtc::MediaStreamTrack::Init(exports);
node_webrtc::RTCRtpReceiver::Init(exports);
node_webrtc::RTCStatsReport::Init(exports);
Expand Down
37 changes: 25 additions & 12 deletions src/converters/arguments.h
Expand Up @@ -23,10 +23,23 @@

namespace node_webrtc {

struct Arguments {
Nan::NAN_METHOD_ARGS_TYPE info;
explicit Arguments(Nan::NAN_METHOD_ARGS_TYPE info): info(info) {}
};

template <typename A>
struct Converter<Nan::NAN_METHOD_ARGS_TYPE, A> {
static Validation<A> Convert(Nan::NAN_METHOD_ARGS_TYPE info) {
return From<A>(info[0]);
struct Converter<Arguments, A> {
static Validation<A> Convert(Arguments args) {
return From<A>(args.info[0]);
}
};

template <typename L, typename R>
struct Converter<Arguments, Either<L, R>> {
static Validation<Either<L, R>> Convert(Arguments args) {
return From<L>(args).Map(&Either<L, R>::Left)
| (From<R>(args).Map(&Either<L, R>::Right));
}
};

Expand All @@ -36,11 +49,11 @@ static std::tuple<A, B> Make2Tuple(A a, B b) {
}

template <typename A, typename B>
struct Converter<Nan::NAN_METHOD_ARGS_TYPE, std::tuple<A, B>> {
static Validation<std::tuple<A, B>> Convert(Nan::NAN_METHOD_ARGS_TYPE info) {
struct Converter<Arguments, std::tuple<A, B>> {
static Validation<std::tuple<A, B>> Convert(Arguments args) {
return curry(Make2Tuple<A, B>)
% From<A>(info[0])
* From<B>(info[1]);
% From<A>(args.info[0])
* From<B>(args.info[1]);
}
};

Expand All @@ -50,12 +63,12 @@ static std::tuple<A, B> Make3Tuple(A a, B b, C c) {
}

template <typename A, typename B, typename C>
struct Converter<Nan::NAN_METHOD_ARGS_TYPE, std::tuple<A, B, C>> {
static Validation<std::tuple<A, B, C>> Convert(Nan::NAN_METHOD_ARGS_TYPE info) {
struct Converter<Arguments, std::tuple<A, B, C>> {
static Validation<std::tuple<A, B, C>> Convert(Arguments args) {
return curry(Make3Tuple<A, B, C>)
% From<A>(info[0])
* From<B>(info[1])
* From<C>(info[2]);
% From<A>(args.info[0])
* From<B>(args.info[1])
* From<C>(args.info[2]);
}
};

Expand Down
10 changes: 10 additions & 0 deletions src/converters/v8.h
Expand Up @@ -226,6 +226,16 @@ struct Converter<v8::Local<v8::Value>, v8::Local<v8::Object>> {
}
};

template <>
struct Converter<v8::Local<v8::Value>, v8::Local<v8::External>> {
static Validation<v8::Local<v8::External>> Convert(const v8::Local<v8::Value> value) {
Nan::EscapableHandleScope scope;
return !value.IsEmpty() && value->IsExternal()
? Validation<v8::Local<v8::External>>::Valid(scope.Escape(v8::Local<v8::External>::Cast(value)))
: Validation<v8::Local<v8::External>>::Invalid("Expected an external");
}
};

} // namespace node_webrtc

#endif // SRC_CONVERTERS_V8_H_

0 comments on commit 83ad156

Please sign in to comment.