From 2ed3ca2ebd5eecfe1a43478ce16f03cbe202e828 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Thu, 23 Sep 2021 22:50:03 -0700 Subject: [PATCH] prebuffer: automatic pcm handling --- plugins/prebuffer-mixin/src/main.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/plugins/prebuffer-mixin/src/main.ts b/plugins/prebuffer-mixin/src/main.ts index 4a02df498..b22a9e671 100644 --- a/plugins/prebuffer-mixin/src/main.ts +++ b/plugins/prebuffer-mixin/src/main.ts @@ -8,8 +8,9 @@ import { SettingsMixinDeviceBase } from "../../../common/src/settings-mixin"; import { FFMpegRebroadcastSession, startRebroadcastSession } from '@scrypted/common/src/ffmpeg-rebroadcast'; import { probeVideoCamera } from '@scrypted/common/src/media-helpers'; import { createMpegTsParser, createFragmentedMp4Parser, MP4Atom, StreamChunk } from '@scrypted/common/src/stream-parser'; +import { AutoenableMixinProvider } from '@scrypted/common/src/autoenable-mixin-provider'; -const { mediaManager, log } = sdk; +const { mediaManager, log, systemManager } = sdk; const defaultPrebufferDuration = 15000; const PREBUFFER_DURATION_MS = 'prebufferDuration'; @@ -35,6 +36,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase implements Vid session: FFMpegRebroadcastSession; detectedIdrInterval = 0; prevIdr = 0; + unexpectedPCM = false; constructor(mixinDevice: VideoCamera & Settings, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: { [key: string]: any }, providerNativeId: string) { super(mixinDevice, mixinDeviceState, { @@ -118,7 +120,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase implements Vid const prebufferDurationMs = parseInt(this.storage.getItem(PREBUFFER_DURATION_MS)) || defaultPrebufferDuration; const ffmpegInput = JSON.parse((await mediaManager.convertMediaObjectToBuffer(await this.mixinDevice.getVideoStream(), ScryptedMimeTypes.FFmpegInput)).toString()) as FFMpegInput; - const reencodeAudio = this.storage.getItem(REENCODE_AUDIO) === 'true'; + const reencodeAudio = this.storage.getItem(REENCODE_AUDIO) === 'true' || this.unexpectedPCM; const probe = await probeVideoCamera(this.mixinDevice); @@ -159,8 +161,9 @@ class PrebufferMixin extends SettingsMixinDeviceBase implements Vid } else if (this.session.inputAudioCodec !== 'aac') { console.error(this.name, 'Detected audio codec was not AAC.'); - if (this.name?.indexOf('pcm') !== -1 && !reencodeAudio) { - log.a(`${this.name} is using PCM audio. You will need to enable Reencode Audio in Rebroadcast Settings for this stream.`); + if (session.inputAudioCodec && session.inputAudioCodec.indexOf('pcm') !== -1 && !reencodeAudio) { + log.a(`${this.name} is using PCM audio and will be reencoded. Enable Reencode Audio in Rebroadcast Settings to disable this alert.`); + this.unexpectedPCM = true; } } @@ -315,7 +318,19 @@ class PrebufferMixin extends SettingsMixinDeviceBase implements Vid } } -class PrebufferProvider extends ScryptedDeviceBase implements MixinProvider { +class PrebufferProvider extends AutoenableMixinProvider implements MixinProvider { + constructor(nativeId?: string) { + super(nativeId); + + // trigger the prebuffer. + for (const id of Object.keys(systemManager.getSystemState())) { + const device = systemManager.getDeviceById(id); + if (!device.mixins?.includes(this.id)) + continue; + device.getVideoStreamOptions(); + } + } + async canMixin(type: ScryptedDeviceType, interfaces: string[]): Promise { if (!interfaces.includes(ScryptedInterface.VideoCamera)) return null; @@ -323,6 +338,7 @@ class PrebufferProvider extends ScryptedDeviceBase implements MixinProvider { } async getMixin(mixinDevice: any, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: { [key: string]: any }) { + this.setHasEnabledMixin(mixinDeviceState.id); return new PrebufferMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState, this.nativeId); } async releaseMixin(id: string, mixinDevice: any) {