Example #1
0
        private async Task RunLocal()
        {
            var ct      = ProcessCancel.Token;
            var taskSet = new HashSet <Task>();

            var blockSize = (int)(Param.SamplingRate * Param.SampleLength);

            Logger.LogInformation($"[loop5] blockSize {blockSize}");

            var audioInterval = (long)(10_000_000.0 * Param.SampleLength);

            Logger.LogInformation($"[loop5] audioInterval {audioInterval}");
            var videoInterval = (long)(10_000_000.0 / Param.MaxFrameRate);

            Logger.LogInformation($"[loop5] videoInterval {videoInterval}");

            var counter = new ElapsedTimeCounter();

            using var audioWaiter   = new Waiter(counter, audioInterval);
            using var videoWaiter   = new Waiter(counter, videoInterval);
            using var buf           = new IPCBuffer <float>(Param.EffectName, blockSize * 2 * Param.BufferCount, LoggerFactory);
            using var vstBufferPool = new BufferPool <VstBuffer2 <float> >(Param.BufferCount, () => new VstBuffer2 <float>(blockSize, 2, buf), LoggerFactory);
            using var pcmPool       = new BufferPool <PcmBuffer <float> >(Param.BufferCount, () => new PcmBuffer <float>(blockSize, 2), LoggerFactory);
            using var audioPool     = new BufferPool <OpusOutputBuffer>(Param.BufferCount, () => new OpusOutputBuffer(5000), LoggerFactory);
            using var pcmDrowPool   = new BufferPool <PcmBuffer <float> >(Param.BufferCount, () => new PcmBuffer <float>(blockSize, 2), LoggerFactory);
            using var bmpPool       = new BufferPool <H264InputBuffer>(Param.BufferCount, () => new H264InputBuffer(Param.Width, Param.Height), LoggerFactory);
            using var videoPool     = new BufferPool <H264OutputBuffer>(Param.BufferCount, () => new H264OutputBuffer(200000), LoggerFactory);
            using var vst           = new AudioMaster <float>(Param.SamplingRate, blockSize, LoggerFactory, counter, DllManager);
            using var toPcm         = new ToPcm <float>(LoggerFactory, counter);
            using var opus          = new OpusEncoder(SamplingRate.Sampling48000, Channels.Stereo, LoggerFactory, counter);
            using var fft           = new FFTEncoder(Param.Width, Param.Height, Param.MaxFrameRate, LoggerFactory, counter);
            using var h264          = new H264Encoder(Param.Width, Param.Height, Param.TargetBitrate, Param.MaxFrameRate, LoggerFactory, counter);
            var effect = vst.AddEffect(Param.EffectName);

            var options = new ExecutionDataflowBlockOptions
            {
                CancellationToken      = ct,
                MaxDegreeOfParallelism = 1,
                MaxMessagesPerTask     = DataflowBlockOptions.Unbounded
            };

            {
                var audioBlock =
                    new ActionBlock <VstBuffer2 <float> >(async buffer =>
                {
                    var pcmTask   = pcmPool.ReceiveAsync(ct);
                    var audioTask = audioPool.ReceiveAsync(ct);

                    buffer.Log.Clear();
                    audioWaiter.Wait();
                    buffer.Log.Add("[audio] start", counter.NowTicks);

                    //VST
                    var nowTime = counter.NowTicks / 10;
                    effect.ProcessEvent(nowTime, MidiEventInput);
                    effect.ProcessReplacing(nowTime, buffer);

                    //trans
                    var pcm = await pcmTask.ConfigureAwait(false);
                    buffer.Log.Add("[audio] opus input get", counter.NowTicks);
                    toPcm.Execute(buffer, pcm);
                    vstBufferPool.Post(buffer);

                    var audio = await audioTask.ConfigureAwait(false);
                    pcm.Log.Add("[audio] opus output get", counter.NowTicks);
                    opus.Execute(pcm, audio);

                    pcmDrowPool.Post(pcm);

                    //FTL
                    //   ftl.Execute(audio);

                    audioPool.Post(audio);
                }, options);
                taskSet.Add(audioBlock.Completion);
                vstBufferPool.LinkTo(audioBlock);
            }

            {
                var midiDataStoreBlock =
                    new ActionBlock <MIDIMessageEvent2>(buffer =>
                {
                    fft.Receive(buffer);
                }, options);
                taskSet.Add(midiDataStoreBlock.Completion);
                MidiEventOutput.LinkTo(midiDataStoreBlock);

                var pcmDataStoreBlock =
                    new ActionBlock <PcmBuffer <float> >(buffer =>
                {
                    fft.Receive(buffer);
                    pcmPool.Post(buffer);
                }, options);
                taskSet.Add(pcmDataStoreBlock.Completion);
                pcmDrowPool.LinkTo(pcmDataStoreBlock);

                var intraFrameCount = 0.0;

                var videoBlock =
                    new ActionBlock <H264InputBuffer>(async buffer =>
                {
                    var videoTask = videoPool.ReceiveAsync(ct);

                    buffer.Log.Clear();

                    videoWaiter.Wait();
                    buffer.Log.Add("[video] start", counter.NowTicks);

                    //FFT
                    fft.Execute(buffer);

                    //H264
                    var video = await videoTask.ConfigureAwait(false);
                    buffer.Log.Add("[video] h264 output get", counter.NowTicks);

                    var insertIntraFrame = (intraFrameCount <= 0);
                    h264.Execute(buffer, video, insertIntraFrame);

                    bmpPool.Post(buffer);
                    if (insertIntraFrame)
                    {
                        intraFrameCount = Param.IntraFrameIntervalUs;
                    }
                    intraFrameCount -= videoInterval;

                    //FTL
                    //ftl.Execute(video);

                    videoPool.Post(video);
                }, options);
                taskSet.Add(videoBlock.Completion);
                bmpPool.LinkTo(videoBlock);
            }

            while (taskSet.Count > 0)
            {
                var task = await Task.WhenAny(taskSet).ConfigureAwait(false);

                taskSet.Remove(task);
                if (task.IsFaulted)
                {
                    ProcessCancel.Cancel();
                    Logger.LogError(task.Exception, "Process Exception");
                }
            }
        }