示例#1
0
        /// <summary>
        /// Create new AVI file and open it for writing.
        /// </summary>
        ///
        /// <param name="fileName">AVI file name to create.</param>
        /// <param name="width">Video width.</param>
        /// <param name="height">Video height.</param>
        ///
        /// <remarks><para>The method opens (creates) a video files, configure video codec and prepares
        /// the stream for saving video frames with a help of <see cref="AddFrame"/> method.</para></remarks>
        ///
        /// <exception cref="System.IO.IOException">Failed opening the specified file.</exception>
        /// <exception cref="VideoException">A error occurred while creating new video file. See exception message.</exception>
        /// <exception cref="OutOfMemoryException">Insufficient memory for internal buffer.</exception>
        /// <exception cref="ArgumentException">Video file resolution must be a multiple of two.</exception>
        public void Open(string fileName, int width, int height, bool showOptions = false)
        {
            // close previous file
            Close();

            // check width and height
            if (((width & 1) != 0) || ((height & 1) != 0))
            {
                throw new ArgumentException("Video file resolution must be a multiple of two.");
            }

            bool success = false;

            try
            {
                lock (sync)
                {
                    // calculate stride
                    stride = width * 3;
                    if ((stride % 4) != 0)
                    {
                        stride += (4 - stride % 4);
                    }

                    // create new file
                    if (NativeMethods.AVIFileOpen(out file, fileName, OpenFileMode.Create | OpenFileMode.Write, IntPtr.Zero) != 0)
                    {
                        throw new IOException("Failed opening the specified file.");
                    }

                    this.width  = width;
                    this.height = height;

                    // describe new stream
                    AVISTREAMINFO info = new AVISTREAMINFO();

                    info.type                = NativeMethods.mmioFOURCC("vids");
                    info.handler             = NativeMethods.mmioFOURCC(codec);
                    info.scale               = 1;
                    info.rate                = rate;
                    info.suggestedBufferSize = stride * height;

                    // create stream
                    if (NativeMethods.AVIFileCreateStream(file, out stream, ref info) != 0)
                    {
                        throw new Exception("Failed creating stream.");
                    }

                    // describe compression options
                    AVICOMPRESSOPTIONS options = new AVICOMPRESSOPTIONS();

                    options.handler = NativeMethods.mmioFOURCC(codec);
                    options.quality = quality;

                    if (showOptions)
                    {
                        NativeMethods.AVISaveOptions(stream, ref options);
                    }

                    // create compressed stream
                    if (NativeMethods.AVIMakeCompressedStream(out streamCompressed, stream, ref options, IntPtr.Zero) != 0)
                    {
                        throw new Exception("Failed creating compressed stream.");
                    }

                    // describe frame format
                    BITMAPINFOHEADER bitmapInfoHeader = new BITMAPINFOHEADER();

                    bitmapInfoHeader.size        = Marshal.SizeOf(bitmapInfoHeader.GetType());
                    bitmapInfoHeader.width       = width;
                    bitmapInfoHeader.height      = height;
                    bitmapInfoHeader.planes      = 1;
                    bitmapInfoHeader.bitCount    = 24;
                    bitmapInfoHeader.sizeImage   = 0;
                    bitmapInfoHeader.compression = 0; // BI_RGB

                    // set frame format
                    if (NativeMethods.AVIStreamSetFormat(streamCompressed, 0, ref bitmapInfoHeader, Marshal.SizeOf(bitmapInfoHeader.GetType())) != 0)
                    {
                        throw new Exception("Failed setting format of the compressed stream.");
                    }

                    // alloc unmanaged memory for frame
                    buffer = Marshal.AllocHGlobal(stride * height);

                    if (buffer == IntPtr.Zero)
                    {
                        throw new OutOfMemoryException("Insufficient memory for internal buffer.");
                    }

                    position = 0;
                    success  = true;
                }
            }
            finally
            {
                if (!success)
                {
                    Close();
                }
            }
        }