Exemplo n.º 1
0
        /// <summary>
        /// Creates a new instance of <see cref="FFmpegWriter"/>.
        /// </summary>
        public FFmpegWriter(FFmpegVideoWriterArgs Args)
        {
            if (!FFmpegService.FFmpegExists)
            {
                throw new FFmpegNotFoundException();
            }

            var nv12 = Args.ImageProvider.DummyFrame is INV12Frame;

            var settings = ServiceProvider.Get <FFmpegSettings>();

            var w = Args.ImageProvider.Width;
            var h = Args.ImageProvider.Height;

            _videoBuffer = new byte[(int)(w * h * (nv12 ? 1.5 : 4))];

            Console.WriteLine($"Video Buffer Allocated: {_videoBuffer.Length}");

            var videoPipeName = GetPipeName();

            var argsBuilder = new FFmpegArgsBuilder();

            argsBuilder.AddInputPipe(videoPipeName)
            .AddArg("thread_queue_size", 512)
            .AddArg("framerate", Args.FrameRate)
            .SetFormat("rawvideo")
            .AddArg("pix_fmt", nv12 ? "nv12" : "rgb32")
            .SetVideoSize(w, h);

            var output = argsBuilder.AddOutputFile(Args.FileName)
                         .SetFrameRate(Args.FrameRate);

            Args.VideoCodec.Apply(settings, Args, output);

            if (settings.Resize)
            {
                var width  = settings.ResizeWidth;
                var height = settings.ResizeHeight;

                if (width % 2 == 1)
                {
                    ++width;
                }

                if (height % 2 == 1)
                {
                    ++height;
                }

                output.AddArg("vf", $"scale={width}:{height}");
            }

            if (Args.AudioProvider != null)
            {
                var audioPipeName = GetPipeName();

                argsBuilder.AddInputPipe(audioPipeName)
                .AddArg("thread_queue_size", 512)
                .SetFormat("s16le")
                .SetAudioCodec("pcm_s16le")
                .SetAudioFrequency(Args.Frequency)
                .SetAudioChannels(Args.Channels);

                Args.VideoCodec.AudioArgsProvider(Args.AudioQuality, output);

                var wf = Args.AudioProvider.WaveFormat;

                _audioBytesPerFrame = (int)((1.0 / Args.FrameRate)
                                            * wf.SampleRate
                                            * wf.Channels
                                            * (wf.BitsPerSample / 8.0));

                // UpdatePeriod * Frequency * (Bytes per Second) * Channels * 2
                var audioBufferSize = (int)((1000.0 / Args.FrameRate) * 44.1 * 2 * 2 * 2);

                _audioPipe = new NamedPipeServerStream(audioPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 0, audioBufferSize);
            }

            _ffmpegIn = new NamedPipeServerStream(videoPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 0, _videoBuffer.Length);

            _ffmpegProcess = FFmpegService.StartFFmpeg(argsBuilder.GetArgs(), Args.FileName, out _);
        }