node-datachannel 0.30.0 → 0.32.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 (43) hide show
  1. package/CMakeLists.txt +13 -2
  2. package/dist/cjs/lib/index.cjs +24 -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 +17 -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 +64 -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 +16 -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 +31 -0
  25. package/src/cpp/media-mediahandler-helper.h +11 -0
  26. package/src/cpp/media-pacinghandler-wrapper.cpp +79 -0
  27. package/src/cpp/media-pacinghandler-wrapper.h +28 -0
  28. package/src/cpp/media-rtcpnackresponder-wrapper.cpp +68 -0
  29. package/src/cpp/media-rtcpnackresponder-wrapper.h +28 -0
  30. package/src/cpp/media-rtcpreceivingsession-wrapper.cpp +23 -6
  31. package/src/cpp/media-rtcpreceivingsession-wrapper.h +1 -1
  32. package/src/cpp/media-rtcpsrreporter-wrapper.cpp +93 -0
  33. package/src/cpp/media-rtcpsrreporter-wrapper.h +30 -0
  34. package/src/cpp/media-rtppacketizationconfig-wrapper.cpp +167 -0
  35. package/src/cpp/media-rtppacketizationconfig-wrapper.h +35 -0
  36. package/src/cpp/media-rtppacketizer-wrapper.cpp +95 -0
  37. package/src/cpp/media-rtppacketizer-wrapper.h +30 -0
  38. package/src/cpp/media-track-wrapper.cpp +9 -4
  39. package/src/cpp/media-video-wrapper.cpp +36 -1
  40. package/src/cpp/media-video-wrapper.h +2 -0
  41. package/src/lib/index.ts +76 -2
  42. package/src/lib/types.ts +6 -0
  43. 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,61 @@ 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 PacingHandler extends MediaHandler {
172
+ }
173
+ declare const PacingHandler: {
174
+ new (bitsPerSecond: number, sendInterval: number): PacingHandler;
175
+ };
176
+ interface RtcpReceivingSession extends MediaHandler {
157
177
  }
158
178
  declare const RtcpReceivingSession: {
159
179
  new (): RtcpReceivingSession;
160
180
  };
181
+ interface RtcpNackResponder extends MediaHandler {
182
+ }
183
+ declare const RtcpNackResponder: {
184
+ new (maxSize?: number): RtcpNackResponder;
185
+ };
186
+ interface RtcpSrReporter extends MediaHandler {
187
+ get rtpConfig(): RtpPacketizationConfig;
188
+ }
189
+ declare const RtcpSrReporter: {
190
+ new (rtpConfig: RtpPacketizationConfig): RtcpSrReporter;
191
+ };
192
+ interface RtpPacketizer extends MediaHandler {
193
+ get rtpConfig(): RtpPacketizationConfig;
194
+ }
195
+ declare const RtpPacketizer: {
196
+ new (rtpConfig: RtpPacketizationConfig): RtpPacketizer;
197
+ };
198
+ interface H264RtpPacketizer extends RtpPacketizer {
199
+ }
200
+ declare const H264RtpPacketizer: {
201
+ new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): H264RtpPacketizer;
202
+ };
203
+ interface H265RtpPacketizer extends RtpPacketizer {
204
+ }
205
+ declare const H265RtpPacketizer: {
206
+ new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): H265RtpPacketizer;
207
+ };
208
+ interface AV1RtpPacketizer extends RtpPacketizer {
209
+ }
210
+ declare const AV1RtpPacketizer: {
211
+ new (packetization: ObuPacketization, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number): AV1RtpPacketizer;
212
+ };
161
213
 
162
214
  declare const DataChannelStream: typeof DataChannelStream$1;
163
215
  declare const _default: {
@@ -166,7 +218,15 @@ declare const _default: {
166
218
  preload: typeof preload;
167
219
  setSctpSettings: typeof setSctpSettings;
168
220
  getLibraryVersion: typeof getLibraryVersion;
221
+ PacingHandler: new (bitsPerSecond: number, sendInterval: number) => PacingHandler;
169
222
  RtcpReceivingSession: new () => RtcpReceivingSession;
223
+ RtcpNackResponder: new (maxSize?: number) => RtcpNackResponder;
224
+ RtcpSrReporter: new (rtpConfig: RtpPacketizationConfig) => RtcpSrReporter;
225
+ RtpPacketizationConfig: new (ssrc: number, cname: string, payloadType: number, clockRate: number, videoOrientationId?: number) => RtpPacketizationConfig;
226
+ RtpPacketizer: new (rtpConfig: RtpPacketizationConfig) => RtpPacketizer;
227
+ H264RtpPacketizer: new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => H264RtpPacketizer;
228
+ H265RtpPacketizer: new (separator: NalUnitSeparator, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => H265RtpPacketizer;
229
+ AV1RtpPacketizer: new (packetization: ObuPacketization, rtpConfig: RtpPacketizationConfig, maxFragmentSize?: number) => AV1RtpPacketizer;
170
230
  Track: new () => Track;
171
231
  Video: new (mid: string, dir: Direction) => Video;
172
232
  Audio: new (mid: string, dir: Direction) => Audio;
@@ -178,4 +238,4 @@ declare const _default: {
178
238
  IceUdpMuxListener: new (port: number, address?: string) => IceUdpMuxListener;
179
239
  };
180
240
 
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 };
241
+ export { AV1RtpPacketizer, Audio, CertificateFingerprint, Channel, DataChannel, DataChannelInitConfig, DataChannelStream, DescriptionType, Direction, H264RtpPacketizer, H265RtpPacketizer, IceUdpMuxListener, IceUdpMuxRequest, LocalDescriptionInit, LogLevel, type MediaHandler, NalUnitSeparator, ObuPacketization, PacingHandler, 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.32.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,15 @@
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-pacinghandler-wrapper.h"
12
+ #include "media-rtcpnackresponder-wrapper.h"
8
13
  #include "media-rtcpreceivingsession-wrapper.h"
14
+ #include "media-rtcpsrreporter-wrapper.h"
15
+ #include "media-rtppacketizationconfig-wrapper.h"
16
+ #include "media-rtppacketizer-wrapper.h"
9
17
  #include "media-track-wrapper.h"
10
18
  #include "media-video-wrapper.h"
11
19
  #include "media-audio-wrapper.h"
@@ -21,7 +29,15 @@ Napi::Object InitAll(Napi::Env env, Napi::Object exports)
21
29
  RtcWrapper::Init(env, exports);
22
30
 
23
31
  #if RTC_ENABLE_MEDIA == 1
32
+ AV1RtpPacketizerWrapper::Init(env, exports);
33
+ H264RtpPacketizerWrapper::Init(env, exports);
34
+ H265RtpPacketizerWrapper::Init(env, exports);
35
+ PacingHandlerWrapper::Init(env, exports);
36
+ RtcpNackResponderWrapper::Init(env, exports);
24
37
  RtcpReceivingSessionWrapper::Init(env, exports);
38
+ RtcpSrReporterWrapper::Init(env, exports);
39
+ RtpPacketizationConfigWrapper::Init(env, exports);
40
+ RtpPacketizerWrapper::Init(env, exports);
25
41
  TrackWrapper::Init(env, exports);
26
42
  VideoWrapper::Init(env, exports);
27
43
  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
+ }