import { clContext as nodenCLContext , OpenCLBuffer } from 'nodencl' ; import { MacadamConsumerFactory } from './macadamConsumer' ; import { ScreenConsumerFactory } from './screenConsumer' ; import { FFmpegConsumerFactory } from './ffmpegConsumer' ; import { RedioPipe , RedioEnd } from 'redioactive' ; import { Frame } from 'beamcoder' ; import { Channel } from '../channel' ; import { ConfigParams , VideoFormat , DeviceConfig , ConsumerConfig } from '../config' ; import { ClJobs } from '../clJobQueue' ; export interface Consumer { initialise ( ) : Promise < void > ; deviceConfig ( ) : DeviceConfig ; connect ( combineAudio , combineVideo ) : void ; release ( combineAudio , combineVideo ) : void ; } export interface ConsumerFactory < T extends Consumer > { createConsumer ( chanID , params , format , device , clJobs ) : T ; } export class ConsumerRegistry { private readonly consumerFactories : Map < string , ConsumerFactory < Consumer > > ; private readonly consumers : Map < number , Consumer > ; private readonly chanIDs : Map < number , string > ; private readonly formats : Map < number , VideoFormat > ; private consumerIndex = 1 ; constructor ( clContext ) { this . consumerFactories = new Map ( ) ; this . consumerFactories . set ( 'decklink' , new MacadamConsumerFactory ( clContext ) ) ; this . consumerFactories . set ( 'screen' , new ScreenConsumerFactory ( clContext ) ) ; this . consumerFactories . set ( 'ffmpeg' , new FFmpegConsumerFactory ( clContext ) ) ; this . consumers = new Map ( ) ; this . chanIDs = new Map ( ) ; this . formats = new Map ( ) ; } createConsumer ( chanNum , consumerIndex , params , device , clJobs ) { if ( this . consumers . get ( consumerIndex ) ) throw new Error ( `${ device . name } consumer device ${ device . deviceIndex } consumerIndex ${ consumerIndex } is already registered` ) ; if ( consumerIndex === 0 ) consumerIndex = ++ this . consumerIndex ; else this . consumerIndex = consumerIndex ; const factory = this . consumerFactories . get ( device . name . toLowerCase ( ) ) ; if ( ! factory ) throw new Error ( `device name '${ device . name }' not recognised` ) ; const chanID = this . chanIDs . get ( chanNum ) ; if ( ! chanID ) throw new Error ( `channel ID not registered` ) ; const format = this . formats . get ( chanNum ) ; if ( ! format ) throw new Error ( `channel format not registered` ) ; const consumer = factory . createConsumer ( chanID , params , format , { name : device . name . toLowerCase ( ) , deviceIndex : device . deviceIndex } , clJobs ) ; this . consumers . set ( consumerIndex , consumer ) ; return consumer ; } removeConsumer ( chanNum , channel , consumerIndex , device ) { const chanID = this . chanIDs . get ( chanNum ) ; if ( ! chanID ) throw new Error ( `channel not found` ) ; let consumer = undefined ; if ( consumerIndex === 0 ) { if ( device . name != '' ) { console . log ( 'Remove consumer with device' , device ) ; this . consumers . forEach ( ( c , i ) => { const config = c . deviceConfig ( ) ; if ( ! consumerIndex && config . name === device . name && config . deviceIndex === device . deviceIndex ) { consumer = c ; consumerIndex = i ; } } ) ; if ( ! consumer ) throw new Error ( `cannot find consumer with device ${ device }` ) ; } else throw new Error ( `no consumerIndex and no parameters` ) ; } else { consumer = this . consumers . get ( consumerIndex ) ; if ( ! consumer ) throw new Error ( `consumer index ${ consumerIndex } not found` ) ; } if ( consumerIndex && consumer ) { channel . removeConsumer ( consumer ) ; this . consumers . delete ( consumerIndex ) ; } else throw new Error ( `consumerIndex ${ consumerIndex } and device ${ device }` ) ; } createConsumers ( chanNum , chanID , config , clJobs ) { this . chanIDs . set ( chanNum , chanID ) ; this . formats . set ( chanNum , config . format ) ; return config . devices . map ( ( device ) => this . createConsumer ( chanNum , this . consumerIndex ++ , { } , device , clJobs ) ) ; } }