// Write/Read buffers to/from a Recorder container

using System;
using System.IO;
using Euresys.EGrabber;
using Euresys.EGrabberRecorder;

namespace _260_egrabber_recorder
{
    internal class Program
    {
        static void ProcessRecorderBuffer(RecorderBufferInfo info, byte[] data)
        {
            // processing code
        }

        static void Main(string[] args)
        {
            using (var gentl = new EGenTL())    // load GenTL producer
            {
                using (var recorderLib = new RecorderLibrary())     // load Recorder library
                {
                    // get an existing directory where the recorder container will be stored
                    var containerPath = Path.Combine(Environment.CurrentDirectory, "output");
                    Directory.CreateDirectory(containerPath);

                    // the following block shows how to write a few buffers to a recorder
                    // container opened in write mode
                    // create a new recorder container for writing
                    using (var recorder = recorderLib.OpenRecorder(containerPath, RECORDER_OPEN_MODE.WRITE))
                    {
                        using (var grabber = new EGrabber(gentl))   // create grabber
                        {
                            // configure the grabber data stream to allocate and announce buffers
                            // with optimal alignment for better recorder performance
                            var alignment = recorder.Get<long>(RECORDER_PARAMETER.BUFFER_OPTIMAL_ALIGNMENT);
                            grabber.Stream.Set("BufferAllocationAlignmentControl", "Enable");
                            grabber.Stream.Set("BufferAllocationAlignment", alignment);
                            grabber.ReallocBuffers(3);  // allocate and announce aligned buffers

                            var bufferSize = grabber.GetBufferInfo<long>(0, BUFFER_INFO_CMD.BUFFER_INFO_SIZE);
                            const long N = 10;
                            // allocate recorder container space for N buffers
                            recorder.Set(RECORDER_PARAMETER.CONTAINER_SIZE, N * bufferSize);

                            grabber.Start(N);
                            for (var frame = 0; frame < N; frame++)
                            {
                                using (var buffer = new ScopedBuffer(grabber))
                                {
                                    // write the buffer with its metadata to the recorder container
                                    var info = recorder.Write(buffer, (ulong)frame);
                                    Console.WriteLine($"Buffer #{frame} ({info.width} x {info.height} {gentl.ImageGetPixelFormat(info.pixelFormat)}, userdata= {info.userdata}) has been written to the container");
                                }
                            }
                        }
                    } // the recorder is automatically closed when going out of scope

                    // the following block shows how to read buffers from the existing recorder
                    // container opened in read mode
                    using (var recorder = recorderLib.OpenRecorder(containerPath, RECORDER_OPEN_MODE.READ)) // open the recorder container for reading
                    {
                        // query the number of available buffers in the recorder container
                        var count = recorder.Get<long>(RECORDER_PARAMETER.RECORD_COUNT);

                        // the RECORDER_PARAMETER.RECORD_INDEX is set to 0 by default so the first
                        // buffer of the container can be read immediately
                        for (var i = 0; i < count; i++)
                        {
                            RecorderBufferInfo info;
                            // read buffer info & data from the recorder container
                            var buffer = recorder.Read(out info);
                            // the RECORDER_PARAMETER.RECORD_INDEX is automatically incremented
                            // so the next read will get the next buffer
                            Console.WriteLine($"Buffer #{i} ({info.width} x {info.height} {gentl.ImageGetPixelFormat(info.pixelFormat)}, userdata= {info.userdata}) has been read from the container");

                            ProcessRecorderBuffer(info, buffer);
                        }
                    }
                }
            }
        }
    }
}
