UNPKG

@homebridge/camera-utils

Version:

Utilities to simplify homebridge camera plugin development

63 lines 2.05 kB
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