node-datachannel 0.30.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CMakeLists.txt +12 -2
  2. package/dist/cjs/lib/index.cjs +21 -0
  3. package/dist/cjs/lib/index.cjs.map +1 -1
  4. package/dist/cjs/polyfill/RTCPeerConnection.cjs.map +1 -1
  5. package/dist/esm/lib/index.mjs +15 -1
  6. package/dist/esm/lib/index.mjs.map +1 -1
  7. package/dist/esm/polyfill/RTCPeerConnection.mjs.map +1 -1
  8. package/dist/types/lib/index.d.ts +58 -4
  9. package/dist/types/lib/types.d.ts +3 -1
  10. package/dist/types/polyfill/RTCPeerConnection.d.ts +2 -1
  11. package/package.json +1 -1
  12. package/rollup.config.mjs +1 -1
  13. package/src/cpp/main.cpp +14 -0
  14. package/src/cpp/media-av1packetization.cpp +24 -0
  15. package/src/cpp/media-av1packetization.h +11 -0
  16. package/src/cpp/media-av1rtppacketizer-wrapper.cpp +126 -0
  17. package/src/cpp/media-av1rtppacketizer-wrapper.h +29 -0
  18. package/src/cpp/media-h264rtppacketizer-wrapper.cpp +126 -0
  19. package/src/cpp/media-h264rtppacketizer-wrapper.h +30 -0
  20. package/src/cpp/media-h265rtppacketizer-wrapper.cpp +126 -0
  21. package/src/cpp/media-h265rtppacketizer-wrapper.h +30 -0
  22. package/src/cpp/media-h26xseparator.cpp +32 -0
  23. package/src/cpp/media-h26xseparator.h +11 -0
  24. package/src/cpp/media-mediahandler-helper.cpp +28 -0
  25. package/src/cpp/media-mediahandler-helper.h +11 -0
  26. package/src/cpp/media-rtcpnackresponder-wrapper.cpp +68 -0
  27. package/src/cpp/media-rtcpnackresponder-wrapper.h +28 -0
  28. package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +23 -6
  29. package/src/cpp/media-rtcpreceivingsession-wrapper.h +1 -1
  30. package/src/cpp/media-rtcpsrreporter-wrapper.cpp +93 -0
  31. package/src/cpp/media-rtcpsrreporter-wrapper.h +30 -0
  32. package/src/cpp/media-rtppacketizationconfig-wrapper.cpp +167 -0
  33. package/src/cpp/media-rtppacketizationconfig-wrapper.h +35 -0
  34. package/src/cpp/media-rtppacketizer-wrapper.cpp +95 -0
  35. package/src/cpp/media-rtppacketizer-wrapper.h +30 -0
  36. package/src/cpp/media-track-wrapper.cpp +9 -4
  37. package/src/cpp/media-video-wrapper.cpp +36 -1
  38. package/src/cpp/media-video-wrapper.h +2 -0
  39. package/src/lib/index.ts +69 -2
  40. package/src/lib/types.ts +6 -0
  41. package/src/polyfill/RTCPeerConnection.ts +1 -1
@@ -1,4 +1,4 @@
1
- import { LogLevel, SctpSettings, Direction, Channel, DescriptionType, LocalDescriptionInit, CertificateFingerprint, DataChannelInitConfig, RTCPeerConnectionState, RTCIceConnectionState, RTCSignalingState, RTCIceGatheringState, SelectedCandidateInfo, RtcConfig, IceUdpMuxRequest, WebSocketServerConfiguration } from './types.js';
1
+ import { LogLevel, SctpSettings, Direction, Channel, DescriptionType, LocalDescriptionInit, CertificateFingerprint, DataChannelInitConfig, RTCPeerConnectionState, RTCIceConnectionState, RTCSignalingState, RTCIceGatheringState, SelectedCandidateInfo, RtcConfig, IceUdpMuxRequest, NalUnitSeparator, ObuPacketization, WebSocketServerConfiguration } from './types.js';
2
2
  export { IceServer, ProxyServer, ProxyServerType, RTCIceGathererState, RTCIceTransportState, RTCSdpType, RelayType, TransportPolicy } from './types.js';
3
3
  import DataChannelStream$1 from './datachannel-stream.js';
4
4
  import { WebSocketServer } from './websocket-server.js';
@@ -37,8 +37,10 @@ declare const Audio: {
37
37
  interface Video {
38
38
  addVideoCodec(payloadType: number, codec: string, profile?: string): void;
39
39
  addH264Codec(payloadType: number, profile?: string): void;
40
+ addH265Codec(payloadType: number): void;
40
41
  addVP8Codec(payloadType: number): void;
41
42
  addVP9Codec(payloadType: number): void;
43
+ addAV1Codec(payloadType: number): void;
42
44
  direction(): Direction;
43
45
  generateSdp(eol: string, addr: string, port: number): string;
44
46
  mid(): string;
@@ -75,7 +77,7 @@ interface Track {
75
77
  requestBitrate(bitRate: number): boolean;
76
78
  setBufferedAmountLowThreshold(newSize: number): void;
77
79
  requestKeyframe(): boolean;
78
- setMediaHandler(handler: RtcpReceivingSession): void;
80
+ setMediaHandler(handler: MediaHandler): void;
79
81
  onOpen(cb: () => void): void;
80
82
  onClosed(cb: () => void): void;
81
83
  onError(cb: (err: string) => void): void;
@@ -153,11 +155,56 @@ interface IceUdpMuxListener {
153
155
  declare const IceUdpMuxListener: {
154
156
  new (port: number, address?: string): IceUdpMuxListener;
155
157
  };
156
- interface RtcpReceivingSession {
158
+ interface RtpPacketizationConfig {
159
+ playoutDelayId: number;
160
+ playoutDelayMin: number;
161
+ playoutDelayMax: number;
162
+ timestamp: number;
163
+ get clockRate(): number;
164
+ }
165
+ declare const RtpPacketizationConfig: {
166
+ new (ssrc: number, cname: string, payloadType: number, clockRate: number, videoOrientationId?: number): RtpPacketizationConfig;
167
+ };
168
+ interface MediaHandler {
169
+ addToChain(handler: MediaHandler): void;
170
+ }
171
+ interface RtcpReceivingSession extends MediaHandler {
157
172
  }
158
173
  declare const RtcpReceivingSession: {
159
174
  new (): RtcpReceivingSession;
160
175
  };
176
+ interface RtcpNackResponder extends MediaHandler {
177
+ }
178
+ declare const RtcpNackResponder: {
179
+ new (maxSize?: number): RtcpNackResponder;
180
+ };
181
+ interface RtcpSrReporter extends MediaHandler {
182
+ get rtpConfig(): RtpPacketizationConfig;
183
+ }
184
+ declare const RtcpSrReporter: {
185
+ new (rtpConfig: RtpPacketizationConfig): RtcpSrReporter;
186
+ };
187
+ interface RtpPacketizer extends MediaHandler {
188
+ get rtpConfig(): RtpPacketizationConfig;
189
+ }
190
+ declare const RtpPacketizer: {
191
+ new (rtpConfig: RtpPacketizationConfig): RtpPacketizer;
192
+ };
193
+ interface H264RtpPacketizer extends RtpPacketizer {
194
+ }
195
+ declare const H264RtpPacketizer: {
196
+ new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): H264RtpPacketizer;
197
+ };
198
+ interface H265RtpPacketizer extends RtpPacketizer {
199
+ }
200
+ declare const H265RtpPacketizer: {
201
+ new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): H265RtpPacketizer;
202
+ };
203
+ interface AV1RtpPacketizer extends RtpPacketizer {
204
+ }
205
+ declare const AV1RtpPacketizer: {
206
+ new (packetization: ObuPacketization, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): AV1RtpPacketizer;
207
+ };
161
208
 
162
209
  declare const DataChannelStream: typeof DataChannelStream$1;
163
210
  declare const _default: {
@@ -167,6 +214,13 @@ declare const _default: {
167
214
  setSctpSettings: typeof setSctpSettings;
168
215
  getLibraryVersion: typeof getLibraryVersion;
169
216
  RtcpReceivingSession: new () => RtcpReceivingSession;
217
+ RtcpNackResponder: new (maxSize?: number) => RtcpNackResponder;
218
+ RtcpSrReporter: new (rtpConfig: RtpPacketizationConfig) => RtcpSrReporter;
219
+ RtpPacketizationConfig: new (ssrc: number, cname: string, payloadType: number, clockRate: number, videoOrientationId?: number) => RtpPacketizationConfig;
220
+ RtpPacketizer: new (rtpConfig: RtpPacketizationConfig) => RtpPacketizer;
221
+ H264RtpPacketizer: new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => H264RtpPacketizer;
222
+ H265RtpPacketizer: new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => H265RtpPacketizer;
223
+ AV1RtpPacketizer: new (packetization: ObuPacketization, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => AV1RtpPacketizer;
170
224
  Track: new () => Track;
171
225
  Video: new (mid: string, dir: Direction) => Video;
172
226
  Audio: new (mid: string, dir: Direction) => Audio;
@@ -178,4 +232,4 @@ declare const _default: {
178
232
  IceUdpMuxListener: new (port: number, address?: string) => IceUdpMuxListener;
179
233
  };
180
234
 
181
- export { Audio, CertificateFingerprint, Channel, DataChannel, DataChannelInitConfig, DataChannelStream, DescriptionType, Direction, IceUdpMuxListener, IceUdpMuxRequest, LocalDescriptionInit, LogLevel, PeerConnection, RTCIceConnectionState, RTCIceGatheringState, RTCPeerConnectionState, RTCSignalingState, RtcConfig, RtcpReceivingSession, SctpSettings, SelectedCandidateInfo, Track, Video, WebSocket, WebSocketServer, WebSocketServerConfiguration, cleanup, _default as default, getLibraryVersion, initLogger, preload, setSctpSettings };
235
+ export { AV1RtpPacketizer, Audio, CertificateFingerprint, Channel, DataChannel, DataChannelInitConfig, DataChannelStream, DescriptionType, Direction, H264RtpPacketizer, H265RtpPacketizer, IceUdpMuxListener, IceUdpMuxRequest, LocalDescriptionInit, LogLevel, type MediaHandler, NalUnitSeparator, ObuPacketization, PeerConnection, RTCIceConnectionState, RTCIceGatheringState, RTCPeerConnectionState, RTCSignalingState, RtcConfig, RtcpNackResponder, RtcpReceivingSession, RtcpSrReporter, RtpPacketizationConfig, RtpPacketizer, SctpSettings, SelectedCandidateInfo, Track, Video, WebSocket, WebSocketServer, WebSocketServerConfiguration, cleanup, _default as default, getLibraryVersion, initLogger, preload, setSctpSettings };
@@ -112,5 +112,7 @@ interface IceUdpMuxRequest {
112
112
  host: string;
113
113
  port: number;
114
114
  }
115
+ type NalUnitSeparator = 'Length' | 'ShortStartSequence' | 'LongStartSequence' | 'StartSequence';
116
+ type ObuPacketization = 'Obu' | 'TemporalUnit';
115
117
 
116
- export type { CertificateFingerprint, Channel, DataChannelInitConfig, DescriptionType, Direction, IceServer, IceUdpMuxRequest, LocalDescriptionInit, LogLevel, ProxyServer, ProxyServerType, RTCIceConnectionState, RTCIceGathererState, RTCIceGatheringState, RTCIceTransportState, RTCPeerConnectionState, RTCSdpType, RTCSignalingState, RelayType, RtcConfig, SctpSettings, SelectedCandidateInfo, TransportPolicy, WebSocketServerConfiguration };
118
+ export type { CertificateFingerprint, Channel, DataChannelInitConfig, DescriptionType, Direction, IceServer, IceUdpMuxRequest, LocalDescriptionInit, LogLevel, NalUnitSeparator, ObuPacketization, ProxyServer, ProxyServerType, RTCIceConnectionState, RTCIceGathererState, RTCIceGatheringState, RTCIceTransportState, RTCPeerConnectionState, RTCSdpType, RTCSignalingState, RelayType, RtcConfig, SctpSettings, SelectedCandidateInfo, TransportPolicy, WebSocketServerConfiguration };
@@ -1,6 +1,7 @@
1
1
  import { SelectedCandidateInfo } from '../lib/types';
2
2
  import { PeerConnection } from '../lib/index';
3
3
  import RTCDataChannel from './RTCDataChannel.js';
4
+ import { RTCDataChannelEvent } from './Events.js';
4
5
  import RTCCertificate from './RTCCertificate.js';
5
6
 
6
7
  interface RTCConfiguration extends globalThis.RTCConfiguration {
@@ -11,7 +12,7 @@ declare class RTCPeerConnection extends EventTarget implements globalThis.RTCPee
11
12
  #private;
12
13
  static generateCertificate(): Promise<RTCCertificate>;
13
14
  onconnectionstatechange: globalThis.RTCPeerConnection['onconnectionstatechange'];
14
- ondatachannel: ((this: globalThis.RTCPeerConnection, ev: globalThis.RTCDataChannelEvent) => any) | null;
15
+ ondatachannel: ((this: globalThis.RTCPeerConnection, ev: RTCDataChannelEvent) => any) | null;
15
16
  onicecandidate: globalThis.RTCPeerConnection['onicecandidate'];
16
17
  onicecandidateerror: globalThis.RTCPeerConnection['onicecandidateerror'];
17
18
  oniceconnectionstatechange: globalThis.RTCPeerConnection['oniceconnectionstatechange'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-datachannel",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "WebRTC For Node.js and Electron. libdatachannel node bindings.",
5
5
  "main": "./dist/cjs/lib/index.cjs",
6
6
  "module": "./dist/esm/lib/index.mjs",
package/rollup.config.mjs CHANGED
@@ -10,7 +10,7 @@ const external = (id) => {
10
10
  const bundle = (config) => ({
11
11
  ...config,
12
12
  input: 'src/index.ts',
13
- external,
13
+ external: ['events','stream'] // <-- suppresses the warning for these built-in modules
14
14
  });
15
15
 
16
16
  export default [
package/src/cpp/main.cpp CHANGED
@@ -5,7 +5,14 @@
5
5
  #include "ice-udp-mux-listener-wrapper.h"
6
6
 
7
7
  #if RTC_ENABLE_MEDIA == 1
8
+ #include "media-av1rtppacketizer-wrapper.h"
9
+ #include "media-h264rtppacketizer-wrapper.h"
10
+ #include "media-h265rtppacketizer-wrapper.h"
11
+ #include "media-rtcpnackresponder-wrapper.h"
8
12
  #include "media-rtcpreceivingsession-wrapper.h"
13
+ #include "media-rtcpsrreporter-wrapper.h"
14
+ #include "media-rtppacketizationconfig-wrapper.h"
15
+ #include "media-rtppacketizer-wrapper.h"
9
16
  #include "media-track-wrapper.h"
10
17
  #include "media-video-wrapper.h"
11
18
  #include "media-audio-wrapper.h"
@@ -21,7 +28,14 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports)
21
28
  RtcWrapper::Init(env, exports);
22
29
 
23
30
  #if RTC_ENABLE_MEDIA == 1
31
+ AV1RtpPacketizerWrapper::Init(env, exports);
32
+ H264RtpPacketizerWrapper::Init(env, exports);
33
+ H265RtpPacketizerWrapper::Init(env, exports);
34
+ RtcpNackResponderWrapper::Init(env, exports);
24
35
  RtcpReceivingSessionWrapper::Init(env, exports);
36
+ RtcpSrReporterWrapper::Init(env, exports);
37
+ RtpPacketizationConfigWrapper::Init(env, exports);
38
+ RtpPacketizerWrapper::Init(env, exports);
25
39
  TrackWrapper::Init(env, exports);
26
40
  VideoWrapper::Init(env, exports);
27
41
  AudioWrapper::Init(env, exports);
@@ -0,0 +1,24 @@
1
+ #include "media-av1packetization.h"
2
+
3
+ using Packetization = rtc::AV1RtpPacketizer::Packetization;
4
+
5
+ std::optional<Packetization> strToPacketization(const std::string &packAsStr)
6
+ {
7
+ if (packAsStr == "Obu")
8
+ return Packetization::Obu;
9
+ if (packAsStr == "TemporalUnit")
10
+ return Packetization::TemporalUnit;
11
+ return {};
12
+ }
13
+
14
+ std::string packetizationToStr(rtc::AV1RtpPacketizer::Packetization pack)
15
+ {
16
+ switch (pack)
17
+ {
18
+ case Packetization::Obu:
19
+ return "Obu";
20
+ case Packetization::TemporalUnit:
21
+ return "TemporalUnit";
22
+ }
23
+ return "Unknown";
24
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef MEDIA_AV1PACKETIZATION_H
2
+ #define MEDIA_AV1PACKETIZATION_H
3
+
4
+ #include <napi.h>
5
+ #include <rtc/rtc.hpp>
6
+ #include <optional>
7
+
8
+ std::optional<rtc::AV1RtpPacketizer::Packetization> strToPacketization(const std::string &pktAsStr);
9
+ std::string packetizationToStr(rtc::AV1RtpPacketizer::Packetization pkt);
10
+
11
+ #endif // MEDIA_AV1PACKETIZATION_H
@@ -0,0 +1,126 @@
1
+ #include "media-av1rtppacketizer-wrapper.h"
2
+ #include "media-av1packetization.h"
3
+ #include "media-rtppacketizationconfig-wrapper.h"
4
+ #include "media-mediahandler-helper.h"
5
+
6
+ Napi::FunctionReference AV1RtpPacketizerWrapper::constructor = Napi::FunctionReference();
7
+
8
+ Napi::Object AV1RtpPacketizerWrapper::Init(Napi::Env env, Napi::Object exports)
9
+ {
10
+ Napi::HandleScope scope(env);
11
+
12
+ Napi::Function func = Napi::ObjectWrap<AV1RtpPacketizerWrapper>::DefineClass(env, "AV1RtpPacketizer",
13
+ {
14
+ // Instance Methods
15
+ InstanceMethod("addToChain", &AV1RtpPacketizerWrapper::addToChain),
16
+ // Accessors
17
+ InstanceAccessor("rtpConfig", &AV1RtpPacketizerWrapper::getRtpPacketizationConfig, nullptr),
18
+ });
19
+
20
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
21
+ if (constructor.IsEmpty())
22
+ {
23
+ constructor = Napi::Persistent(func);
24
+ constructor.SuppressDestruct();
25
+ }
26
+
27
+ exports.Set("AV1RtpPacketizer", func);
28
+ return exports;
29
+ }
30
+
31
+ AV1RtpPacketizerWrapper::AV1RtpPacketizerWrapper(const Napi::CallbackInfo &info)
32
+ : Napi::ObjectWrap<AV1RtpPacketizerWrapper>(info)
33
+ {
34
+ Napi::Env env = info.Env();
35
+
36
+ if (info.Length() < 2)
37
+ {
38
+ Napi::Error::New(env, "Expected 2 or 3 parameters").ThrowAsJavaScriptException();
39
+ return;
40
+ }
41
+
42
+ if (!info[0].IsString())
43
+ {
44
+ Napi::TypeError::New(env, "packetization must be \"Obu\" or \"TemporalUnit\"")
45
+ .ThrowAsJavaScriptException();
46
+ return;
47
+ }
48
+ auto packetizationOpt = strToPacketization(info[0].As<Napi::String>().Utf8Value());
49
+ if (!packetizationOpt.has_value())
50
+ {
51
+ Napi::TypeError::New(env, "packetization must be \"Obu\" or \"TemporalUnit\"")
52
+ .ThrowAsJavaScriptException();
53
+ return;
54
+ }
55
+ auto packetization = packetizationOpt.value();
56
+
57
+ if (!info[1].IsObject())
58
+ {
59
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
60
+ return;
61
+ }
62
+ auto obj = info[1].As<Napi::Object>();
63
+ if (!obj.InstanceOf(RtpPacketizationConfigWrapper::constructor.Value()))
64
+ {
65
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
66
+ return;
67
+ }
68
+ // store original JS object so we can return it later
69
+ mRtpConfigObject = Napi::Persistent(obj);
70
+ mRtpConfigObject.SuppressDestruct();
71
+ auto rtpConfig = RtpPacketizationConfigWrapper::Unwrap(obj)->getConfigInstance();
72
+
73
+ size_t maxFragmentSize = rtc::RtpPacketizer::DefaultMaxFragmentSize;
74
+ if (info.Length() >= 3)
75
+ {
76
+ if (!info[2].IsNumber())
77
+ {
78
+ Napi::TypeError::New(env, "maxFragmentSize must be a number").ThrowAsJavaScriptException();
79
+ return;
80
+ }
81
+ maxFragmentSize = info[2].As<Napi::Number>().Uint32Value();
82
+ }
83
+
84
+ mPacketizerPtr = std::make_unique<rtc::AV1RtpPacketizer>(packetization, rtpConfig, maxFragmentSize);
85
+ }
86
+
87
+ AV1RtpPacketizerWrapper::~AV1RtpPacketizerWrapper()
88
+ {
89
+ mPacketizerPtr.reset();
90
+ mRtpConfigObject.Reset();
91
+ }
92
+
93
+ std::shared_ptr<rtc::AV1RtpPacketizer> AV1RtpPacketizerWrapper::getPacketizerInstance() { return mPacketizerPtr; }
94
+
95
+ void AV1RtpPacketizerWrapper::addToChain(const Napi::CallbackInfo &info)
96
+ {
97
+ auto env = info.Env();
98
+ if (info.Length() < 1 || !info[0].IsObject())
99
+ {
100
+ Napi::TypeError::New(env, "Expected a MediaHandler instance").ThrowAsJavaScriptException();
101
+ return;
102
+ }
103
+ auto mediaHandler = asMediaHandler(info[0].As<Napi::Object>());
104
+ if (!mediaHandler)
105
+ {
106
+ Napi::TypeError::New(env, "Expected a MediaHandler instance. If this error is unexpected, please report a bug!")
107
+ .ThrowAsJavaScriptException();
108
+ return;
109
+ }
110
+ mPacketizerPtr->addToChain(mediaHandler);
111
+ }
112
+
113
+ Napi::Value AV1RtpPacketizerWrapper::getRtpPacketizationConfig(const Napi::CallbackInfo &info)
114
+ {
115
+ Napi::Env env = info.Env();
116
+ if (!mPacketizerPtr)
117
+ {
118
+ Napi::Error::New(env, "getRtpPacketizationConfig() called on destroyed packetizer").ThrowAsJavaScriptException();
119
+ return env.Null();
120
+ }
121
+
122
+ if (mRtpConfigObject.IsEmpty())
123
+ return env.Null();
124
+
125
+ return mRtpConfigObject.Value();
126
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef MEDIA_AV1RTPPACKETIZER_WRAPPER_H
2
+ #define MEDIA_AV1RTPPACKETIZER_WRAPPER_H
3
+
4
+ #include <memory>
5
+ #include <unordered_set>
6
+
7
+ #include <napi.h>
8
+ #include <rtc/rtc.hpp>
9
+
10
+ class AV1RtpPacketizerWrapper : public Napi::ObjectWrap<AV1RtpPacketizerWrapper>
11
+ {
12
+ public:
13
+ static Napi::FunctionReference constructor;
14
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
15
+ AV1RtpPacketizerWrapper(const Napi::CallbackInfo &info);
16
+ ~AV1RtpPacketizerWrapper();
17
+ std::shared_ptr<rtc::AV1RtpPacketizer> getPacketizerInstance();
18
+
19
+ // Functions
20
+ Napi::Value getRtpPacketizationConfig(const Napi::CallbackInfo &info);
21
+ void addToChain(const Napi::CallbackInfo &info);
22
+ // Callbacks
23
+
24
+ private:
25
+ std::shared_ptr<rtc::AV1RtpPacketizer> mPacketizerPtr = nullptr;
26
+ Napi::ObjectReference mRtpConfigObject;
27
+ };
28
+
29
+ #endif // MEDIA_AV1RTPPACKETIZER_WRAPPER_H
@@ -0,0 +1,126 @@
1
+ #include "media-h264rtppacketizer-wrapper.h"
2
+ #include "media-h26xseparator.h"
3
+ #include "media-rtppacketizationconfig-wrapper.h"
4
+ #include "media-mediahandler-helper.h"
5
+
6
+ Napi::FunctionReference H264RtpPacketizerWrapper::constructor = Napi::FunctionReference();
7
+
8
+ Napi::Object H264RtpPacketizerWrapper::Init(Napi::Env env, Napi::Object exports)
9
+ {
10
+ Napi::HandleScope scope(env);
11
+
12
+ Napi::Function func = Napi::ObjectWrap<H264RtpPacketizerWrapper>::DefineClass(env, "H264RtpPacketizer",
13
+ {
14
+ // Instance Methods
15
+ InstanceMethod("addToChain", &H264RtpPacketizerWrapper::addToChain),
16
+ // Accessors
17
+ InstanceAccessor("rtpConfig", &H264RtpPacketizerWrapper::getRtpPacketizationConfig, nullptr),
18
+ });
19
+
20
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
21
+ if (constructor.IsEmpty())
22
+ {
23
+ constructor = Napi::Persistent(func);
24
+ constructor.SuppressDestruct();
25
+ }
26
+
27
+ exports.Set("H264RtpPacketizer", func);
28
+ return exports;
29
+ }
30
+
31
+ H264RtpPacketizerWrapper::H264RtpPacketizerWrapper(const Napi::CallbackInfo &info)
32
+ : Napi::ObjectWrap<H264RtpPacketizerWrapper>(info)
33
+ {
34
+ Napi::Env env = info.Env();
35
+
36
+ if (info.Length() < 2)
37
+ {
38
+ Napi::Error::New(env, "Expected 2 or 3 parameters").ThrowAsJavaScriptException();
39
+ return;
40
+ }
41
+
42
+ if (!info[0].IsString())
43
+ {
44
+ Napi::TypeError::New(env, "separator must be \"Length\", \"ShortStartSequence\", \"LongStartSequence\" or \"StartSequence\"")
45
+ .ThrowAsJavaScriptException();
46
+ return;
47
+ }
48
+ auto separatorOpt = strToSeparator(info[0].As<Napi::String>().Utf8Value());
49
+ if (!separatorOpt.has_value())
50
+ {
51
+ Napi::TypeError::New(env, "separator must be \"Length\", \"ShortStartSequence\", \"LongStartSequence\" or \"StartSequence\"")
52
+ .ThrowAsJavaScriptException();
53
+ return;
54
+ }
55
+ auto separator = separatorOpt.value();
56
+
57
+ if (!info[1].IsObject())
58
+ {
59
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
60
+ return;
61
+ }
62
+ auto obj = info[1].As<Napi::Object>();
63
+ if (!obj.InstanceOf(RtpPacketizationConfigWrapper::constructor.Value()))
64
+ {
65
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
66
+ return;
67
+ }
68
+ // store original JS object so we can return it later
69
+ mRtpConfigObject = Napi::Persistent(obj);
70
+ mRtpConfigObject.SuppressDestruct();
71
+ auto rtpConfig = RtpPacketizationConfigWrapper::Unwrap(obj)->getConfigInstance();
72
+
73
+ size_t maxFragmentSize = rtc::RtpPacketizer::DefaultMaxFragmentSize;
74
+ if (info.Length() >= 3)
75
+ {
76
+ if (!info[2].IsNumber())
77
+ {
78
+ Napi::TypeError::New(env, "maxFragmentSize must be a number").ThrowAsJavaScriptException();
79
+ return;
80
+ }
81
+ maxFragmentSize = info[2].As<Napi::Number>().Uint32Value();
82
+ }
83
+
84
+ mPacketizerPtr = std::make_unique<rtc::H264RtpPacketizer>(separator, rtpConfig, maxFragmentSize);
85
+ }
86
+
87
+ H264RtpPacketizerWrapper::~H264RtpPacketizerWrapper()
88
+ {
89
+ mPacketizerPtr.reset();
90
+ mRtpConfigObject.Reset();
91
+ }
92
+
93
+ std::shared_ptr<rtc::H264RtpPacketizer> H264RtpPacketizerWrapper::getPacketizerInstance() { return mPacketizerPtr; }
94
+
95
+ void H264RtpPacketizerWrapper::addToChain(const Napi::CallbackInfo &info)
96
+ {
97
+ auto env = info.Env();
98
+ if (info.Length() < 1 || !info[0].IsObject())
99
+ {
100
+ Napi::TypeError::New(env, "Expected a MediaHandler instance").ThrowAsJavaScriptException();
101
+ return;
102
+ }
103
+ auto mediaHandler = asMediaHandler(info[0].As<Napi::Object>());
104
+ if (!mediaHandler)
105
+ {
106
+ Napi::TypeError::New(env, "Expected a MediaHandler instance. If this error is unexpected, please report a bug!")
107
+ .ThrowAsJavaScriptException();
108
+ return;
109
+ }
110
+ mPacketizerPtr->addToChain(mediaHandler);
111
+ }
112
+
113
+ Napi::Value H264RtpPacketizerWrapper::getRtpPacketizationConfig(const Napi::CallbackInfo &info)
114
+ {
115
+ Napi::Env env = info.Env();
116
+ if (!mPacketizerPtr)
117
+ {
118
+ Napi::Error::New(env, "getRtpPacketizationConfig() called on destroyed packetizer").ThrowAsJavaScriptException();
119
+ return env.Null();
120
+ }
121
+
122
+ if (mRtpConfigObject.IsEmpty())
123
+ return env.Null();
124
+
125
+ return mRtpConfigObject.Value();
126
+ }
@@ -0,0 +1,30 @@
1
+ #ifndef MEDIA_H264RTPPACKETIZER_WRAPPER_H
2
+ #define MEDIA_H264RTPPACKETIZER_WRAPPER_H
3
+
4
+ #include <memory>
5
+ #include <unordered_set>
6
+
7
+ #include <napi.h>
8
+ #include <rtc/rtc.hpp>
9
+
10
+ class H264RtpPacketizerWrapper : public Napi::ObjectWrap<H264RtpPacketizerWrapper>
11
+ {
12
+ public:
13
+ static Napi::FunctionReference constructor;
14
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
15
+ H264RtpPacketizerWrapper(const Napi::CallbackInfo &info);
16
+ ~H264RtpPacketizerWrapper();
17
+ std::shared_ptr<rtc::H264RtpPacketizer> getPacketizerInstance();
18
+
19
+ // Functions
20
+ Napi::Value getRtpPacketizationConfig(const Napi::CallbackInfo &info);
21
+ void addToChain(const Napi::CallbackInfo &info);
22
+
23
+ // Callbacks
24
+
25
+ private:
26
+ std::shared_ptr<rtc::H264RtpPacketizer> mPacketizerPtr = nullptr;
27
+ Napi::ObjectReference mRtpConfigObject;
28
+ };
29
+
30
+ #endif // MEDIA_H264RTPPACKETIZER_WRAPPER_H
@@ -0,0 +1,126 @@
1
+ #include "media-h265rtppacketizer-wrapper.h"
2
+ #include "media-h26xseparator.h"
3
+ #include "media-rtppacketizationconfig-wrapper.h"
4
+ #include "media-mediahandler-helper.h"
5
+
6
+ Napi::FunctionReference H265RtpPacketizerWrapper::constructor = Napi::FunctionReference();
7
+
8
+ Napi::Object H265RtpPacketizerWrapper::Init(Napi::Env env, Napi::Object exports)
9
+ {
10
+ Napi::HandleScope scope(env);
11
+
12
+ Napi::Function func = Napi::ObjectWrap<H265RtpPacketizerWrapper>::DefineClass(env, "H265RtpPacketizer",
13
+ {
14
+ // Instance Methods
15
+ InstanceMethod("addToChain", &H265RtpPacketizerWrapper::addToChain),
16
+ // Accessors
17
+ InstanceAccessor("rtpConfig", &H265RtpPacketizerWrapper::getRtpPacketizationConfig, nullptr),
18
+ });
19
+
20
+ // If this is not the first call, we don't want to reassign the constructor (hot-reload problem)
21
+ if (constructor.IsEmpty())
22
+ {
23
+ constructor = Napi::Persistent(func);
24
+ constructor.SuppressDestruct();
25
+ }
26
+
27
+ exports.Set("H265RtpPacketizer", func);
28
+ return exports;
29
+ }
30
+
31
+ H265RtpPacketizerWrapper::H265RtpPacketizerWrapper(const Napi::CallbackInfo &info)
32
+ : Napi::ObjectWrap<H265RtpPacketizerWrapper>(info)
33
+ {
34
+ Napi::Env env = info.Env();
35
+
36
+ if (info.Length() < 2)
37
+ {
38
+ Napi::Error::New(env, "Expected 2 or 3 parameters").ThrowAsJavaScriptException();
39
+ return;
40
+ }
41
+
42
+ if (!info[0].IsString())
43
+ {
44
+ Napi::TypeError::New(env, "separator must be \"Length\", \"ShortStartSequence\", \"LongStartSequence\" or \"StartSequence\"")
45
+ .ThrowAsJavaScriptException();
46
+ return;
47
+ }
48
+ auto separatorOpt = strToSeparator(info[0].As<Napi::String>().Utf8Value());
49
+ if (!separatorOpt.has_value())
50
+ {
51
+ Napi::TypeError::New(env, "separator must be \"Length\", \"ShortStartSequence\", \"LongStartSequence\" or \"StartSequence\"")
52
+ .ThrowAsJavaScriptException();
53
+ return;
54
+ }
55
+ auto separator = separatorOpt.value();
56
+
57
+ if (!info[1].IsObject())
58
+ {
59
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
60
+ return;
61
+ }
62
+ auto obj = info[1].As<Napi::Object>();
63
+ if (!obj.InstanceOf(RtpPacketizationConfigWrapper::constructor.Value()))
64
+ {
65
+ Napi::TypeError::New(env, "rtpConfig must be a RtpPacketizationConfig instance").ThrowAsJavaScriptException();
66
+ return;
67
+ }
68
+ // store original JS object so we can return it later
69
+ mRtpConfigObject = Napi::Persistent(obj);
70
+ mRtpConfigObject.SuppressDestruct();
71
+ auto rtpConfig = RtpPacketizationConfigWrapper::Unwrap(obj)->getConfigInstance();
72
+
73
+ size_t maxFragmentSize = rtc::RtpPacketizer::DefaultMaxFragmentSize;
74
+ if (info.Length() >= 3)
75
+ {
76
+ if (!info[2].IsNumber())
77
+ {
78
+ Napi::TypeError::New(env, "maxFragmentSize must be a number").ThrowAsJavaScriptException();
79
+ return;
80
+ }
81
+ maxFragmentSize = info[2].As<Napi::Number>().Uint32Value();
82
+ }
83
+
84
+ mPacketizerPtr = std::make_unique<rtc::H265RtpPacketizer>(separator, rtpConfig, maxFragmentSize);
85
+ }
86
+
87
+ H265RtpPacketizerWrapper::~H265RtpPacketizerWrapper()
88
+ {
89
+ mPacketizerPtr.reset();
90
+ mRtpConfigObject.Reset();
91
+ }
92
+
93
+ std::shared_ptr<rtc::H265RtpPacketizer> H265RtpPacketizerWrapper::getPacketizerInstance() { return mPacketizerPtr; }
94
+
95
+ void H265RtpPacketizerWrapper::addToChain(const Napi::CallbackInfo &info)
96
+ {
97
+ auto env = info.Env();
98
+ if (info.Length() < 1 || !info[0].IsObject())
99
+ {
100
+ Napi::TypeError::New(env, "Expected a MediaHandler instance").ThrowAsJavaScriptException();
101
+ return;
102
+ }
103
+ auto mediaHandler = asMediaHandler(info[0].As<Napi::Object>());
104
+ if (!mediaHandler)
105
+ {
106
+ Napi::TypeError::New(env, "Expected a MediaHandler instance. If this error is unexpected, please report a bug!")
107
+ .ThrowAsJavaScriptException();
108
+ return;
109
+ }
110
+ mPacketizerPtr->addToChain(mediaHandler);
111
+ }
112
+
113
+ Napi::Value H265RtpPacketizerWrapper::getRtpPacketizationConfig(const Napi::CallbackInfo &info)
114
+ {
115
+ Napi::Env env = info.Env();
116
+ if (!mPacketizerPtr)
117
+ {
118
+ Napi::Error::New(env, "getRtpPacketizationConfig() called on destroyed packetizer").ThrowAsJavaScriptException();
119
+ return env.Null();
120
+ }
121
+
122
+ if (mRtpConfigObject.IsEmpty())
123
+ return env.Null();
124
+
125
+ return mRtpConfigObject.Value();
126
+ }