From ec62b2f190f0489733713fc967b6bb20b5e60e80 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Fri, 11 Mar 2022 11:08:09 -0800 Subject: [PATCH] rebroadcast: fix scrypted parser being used when it shouldnt. add rtsp teardown. --- plugins/prebuffer-mixin/package-lock.json | 4 ++-- plugins/prebuffer-mixin/package.json | 2 +- plugins/prebuffer-mixin/src/main.ts | 22 +++++++++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/prebuffer-mixin/package-lock.json b/plugins/prebuffer-mixin/package-lock.json index 3540c151e..eaee81398 100644 --- a/plugins/prebuffer-mixin/package-lock.json +++ b/plugins/prebuffer-mixin/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/prebuffer-mixin", - "version": "0.1.194", + "version": "0.1.196", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@scrypted/prebuffer-mixin", - "version": "0.1.194", + "version": "0.1.196", "license": "Apache-2.0", "dependencies": { "@scrypted/common": "file:../../common", diff --git a/plugins/prebuffer-mixin/package.json b/plugins/prebuffer-mixin/package.json index a7ab789bf..6f41a2267 100644 --- a/plugins/prebuffer-mixin/package.json +++ b/plugins/prebuffer-mixin/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/prebuffer-mixin", - "version": "0.1.194", + "version": "0.1.196", "description": "Rebroadcast and Prebuffer for VideoCameras.", "author": "Scrypted", "license": "Apache-2.0", diff --git a/plugins/prebuffer-mixin/src/main.ts b/plugins/prebuffer-mixin/src/main.ts index 8cf132a74..f2515ca74 100644 --- a/plugins/prebuffer-mixin/src/main.ts +++ b/plugins/prebuffer-mixin/src/main.ts @@ -15,6 +15,7 @@ import net from 'net'; import { readLength } from '@scrypted/common/src/read-stream'; import { addTrackControls } from '@scrypted/common/src/sdp-utils'; import { connectRFC4571Parser, startRFC4571Parser } from './rfc4571'; +import { sleep } from '@scrypted/common/src/sleep'; const { mediaManager, log, systemManager, deviceManager } = sdk; @@ -137,9 +138,11 @@ class PrebufferSession { } } - canUseRtspParser(muxingMp4: boolean) { + canUseRtspParser(muxingMp4: boolean, mediaStreamOptions: MediaStreamOptions) { if (muxingMp4) return false; + if (mediaStreamOptions?.container !== 'rtsp') + return false; // The RTSP demuxer can only be used when not transcoding audio. const { isUsingDefaultAudioConfig, compatibleAudio, aacAudio } = this.getAudioConfig(); const canUseRtspParser = isUsingDefaultAudioConfig || compatibleAudio || aacAudio; @@ -147,10 +150,11 @@ class PrebufferSession { } getParser(rtspMode: boolean, muxingMp4: boolean, mediaStreamOptions: MediaStreamOptions) { - if (!this.canUseRtspParser(muxingMp4)) + if (!this.canUseRtspParser(muxingMp4, mediaStreamOptions)) return FFMPEG_PARSER; - const defaultValue = rtspMode && mediaStreamOptions?.tool === 'scrypted' ? + const defaultValue = rtspMode + && mediaStreamOptions?.tool === 'scrypted' ? SCRYPTED_PARSER : FFMPEG_PARSER; const rtspParser = this.storage.getItem(this.rtspParserKey); if (!rtspParser || rtspParser === STRING_DEFAULT) @@ -242,7 +246,7 @@ class PrebufferSession { }; - if (this.canUseRtspParser(muxingMp4) + if (this.canUseRtspParser(muxingMp4, this.advertisedMediaStreamOptions) && rtspMode && this.advertisedMediaStreamOptions?.container === 'rtsp') { @@ -544,10 +548,11 @@ class PrebufferSession { if (parser === SCRYPTED_PARSER) { usingScryptedParser = true; this.console.log('bypassing ffmpeg: using scrypted rtsp/rfc4571 parser') - const rtspClient = new RtspClient(ffmpegInput.url); + const rtspClient = new RtspClient(ffmpegInput.url, this.console); await rtspClient.options(); const sdpResponse = await rtspClient.describe(); const sdp = sdpResponse.body.toString().trim(); + this.console.log('sdp', sdp); this.sdp = Promise.resolve(sdp); const { audio, video } = parseTrackIds(sdp); let channel = 0; @@ -558,6 +563,13 @@ class PrebufferSession { await rtspClient.setup(channel, video); const socket = await rtspClient.play(); session = await startRFC4571Parser(this.console, socket, sdp, ffmpegInput.mediaStreamOptions, true, rbo); + const sessionKill = session.kill.bind(session); + session.kill = async () => { + // issue a teardown to upstream to close gracefully but don't rely on it responding. + rtspClient.teardown().finally(sessionKill); + await sleep(500); + sessionKill(); + } } else { // create missing pts from dts so mpegts and mp4 muxing does not fail