@homebridge/camera-utils
Version:
Utilities to simplify homebridge camera plugin development
63 lines • 2.05 kB
JavaScript
import { createSocket } from 'node:dgram';
import { fromEvent, merge, ReplaySubject } from 'rxjs';
import { map, share, takeUntil } from 'rxjs/operators';
import { bindToPort } from './ports.js';
import { getPayloadType, isRtpMessagePayloadType } from './rtp.js';
export class RtpSplitter {
socket = createSocket('udp4');
portPromise = bindToPort(this.socket);
onClose = new ReplaySubject();
onMessage = fromEvent(this.socket, 'message').pipe(map(([message, info]) => {
const payloadType = getPayloadType(message);
return {
message,
info,
isRtpMessage: isRtpMessagePayloadType(payloadType),
payloadType,
};
}), takeUntil(this.onClose), share());
constructor(messageHandler) {
if (messageHandler) {
this.addMessageHandler(messageHandler);
}
merge(fromEvent(this.socket, 'close'), fromEvent(this.socket, 'error'))
.pipe(takeUntil(this.onClose))
.subscribe(() => {
this.cleanUp();
});
}
addMessageHandler(handler) {
this.onMessage.subscribe((description) => {
const forwardingTarget = handler(description);
if (forwardingTarget) {
this.send(description.message, forwardingTarget);
}
});
}
async send(message, sendTo) {
await this.portPromise;
if (this.closed) {
// If we send a message on a closed socket, it will throw an ERR_SOCKET_DGRAM_NOT_RUNNING error
return;
}
this.socket.send(message, sendTo.port, sendTo.address || '127.0.0.1');
}
cleanedUp = false;
cleanUp() {
this.closed = true;
if (this.cleanedUp) {
return;
}
this.cleanedUp = true;
this.onClose.next(null);
}
closed = false;
close() {
if (this.closed) {
return;
}
this.socket.close();
this.cleanUp();
}
}
//# sourceMappingURL=rtp-splitter.js.map