import { clContext as nodenCLContext , OpenCLBuffer } from 'nodencl' ; import { VideoFormat } from './config' ; import redio , { RedioPipe , RedioEnd , isValue , Valve , nil , end } from 'redioactive' ; import { Filterer , filterer , Frame , frame } from 'beamcoder' ; export class Silence { private readonly consumerFormat : VideoFormat ; private running : boolean ; constructor ( consumerFormat ) { this . consumerFormat = consumerFormat ; this . running = true ; } async initialise ( ) { const sampleRate = this . consumerFormat . audioSampleRate ; const numAudChannels = this . consumerFormat . audioChannels ; const audLayout = `${ numAudChannels }c` ; const silenceArr = new Float32Array ( 1024 * numAudChannels ) ; const silence = frame ( { nb_samples : 1024 , format : 'flt' , pts : 0 , sample_rate : sampleRate , channels : numAudChannels , channel_layout : audLayout , data : [ Buffer . from ( silenceArr . buffer ) ] } ) ; let audSilenceFilterer = await filterer ( { filterType : 'audio' , inputParams : [ { name : 'in0:a' , timeBase : [ 1 , sampleRate ] , sampleRate : sampleRate , sampleFormat : 'flt' , channelLayout : audLayout } ] , outputParams : [ { name : 'out0:a' , sampleRate : sampleRate , sampleFormat : 'fltp' , channelLayout : audLayout } ] , filterSpec : '[in0:a] asetpts=N/SR/TB [out0:a]' } ) ; const silencePipe = redio ( ( ) => ( this . running ? silence : end ) , { bufferSizeMax : 1 } ) ; const silenceAudValve = async ( frame ) => { if ( isValue ( frame ) ) { const ff = await audSilenceFilterer ?. filter ( [ { name : 'in0:a' , frames : [ frame ] } ] ) ; return ff && ff [ 0 ] . frames . length > 0 ? ff [ 0 ] . frames : nil ; } else { audSilenceFilterer = null ; return frame ; } } ; return silencePipe . valve ( silenceAudValve , { oneToMany : true } ) ; } release ( ) { this . running = false ; } } export class Black { private readonly clContext : nodenCLContext ; private readonly consumerFormat : VideoFormat ; private readonly id : string ; private running : boolean ; constructor ( clContext , consumerFormat , id ) { this . clContext = clContext ; this . consumerFormat = consumerFormat ; this . id = id ; this . running = true ; } async initialise ( ) { const numBytesRGBA = this . consumerFormat . width * this . consumerFormat . height * 4 * 4 ; let black = await this . clContext . createBuffer ( numBytesRGBA , 'readwrite' , 'coarse' , { width : this . consumerFormat . width , height : this . consumerFormat . height } , `black-${ this . id }` ) ; let off = 0 ; const blackFloat = new Float32Array ( numBytesRGBA / 4 ) ; for ( let y = 0 ; y < this . consumerFormat . height ; ++ y ) { for ( let x = 0 ; x < this . consumerFormat . width * 4 ; x += 4 ) { blackFloat [ off + x + 0 ] = 0.0 ; blackFloat [ off + x + 1 ] = 0.0 ; blackFloat [ off + x + 2 ] = 0.0 ; blackFloat [ off + x + 3 ] = 0.0 ; } off += this . consumerFormat . width * 4 ; } await black . hostAccess ( 'writeonly' ) ; Buffer . from ( blackFloat . buffer ) . copy ( black ) ; const blackPipe = redio ( ( ) => { if ( this . running ) { black ?. addRef ( ) ; return black ; } else { if ( black ) { black . release ( ) ; black = null ; } return end ; } } , { bufferSizeMax : 1 } ) ; return blackPipe ; } release ( ) { this . running = false ; } }