示例#1
0
        private static IntPtr GetCompressor(VfwApi.BitmapInfoHeader inBitmapInfo, VfwApi.BitmapInfoHeader outBitmapInfo, out VfwApi.CompressorInfo compressorInfo)
        {
            // Using ICLocate is time-consuming. Besides, it does not clean up something, so the process does not terminate on exit.
            // Instead open a specific codec and query it for needed features.

            var compressorHandle = VfwApi.ICOpen((uint)KnownFourCCs.CodecTypes.Video, outBitmapInfo.Compression, VfwApi.ICMODE_COMPRESS);

            if (compressorHandle != IntPtr.Zero)
            {
                var inHeader  = inBitmapInfo;
                var outHeader = outBitmapInfo;
                var result    = VfwApi.ICSendMessage(compressorHandle, VfwApi.ICM_COMPRESS_QUERY, ref inHeader, ref outHeader);

                if (result == VfwApi.ICERR_OK)
                {
                    var infoSize = VfwApi.ICGetInfo(compressorHandle, out compressorInfo, Marshal.SizeOf(typeof(VfwApi.CompressorInfo)));
                    if (infoSize > 0 && compressorInfo.SupportsFastTemporalCompression)
                    {
                        return(compressorHandle);
                    }
                }

                VfwApi.ICClose(compressorHandle);
            }

            compressorInfo = new VfwApi.CompressorInfo();
            return(IntPtr.Zero);
        }
示例#2
0
        /// <summary>
        /// Creates a new instance of <see cref="Mpeg4VcmVideoEncoder"/>.
        /// </summary>
        /// <param name="width">Frame width.</param>
        /// <param name="height">Frame height.</param>
        /// <param name="fps">Frame rate.</param>
        /// <param name="frameCount">
        /// Number of frames to be encoded.
        /// If not known, specify 0.
        /// </param>
        /// <param name="quality">
        /// Compression quality in the range [1..100].
        /// Less values mean less size and lower image quality.
        /// </param>
        /// <param name="codecPreference">
        /// List of codecs that can be used by this encoder, in preferred order.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// No compatible codec was found in the system.
        /// </exception>
        /// <exception cref="PlatformNotSupportedException">
        /// Running not on Windows.
        /// </exception>
        /// <remarks>
        /// <para>
        /// It is not guaranteed that the codec will respect the specified <paramref name="quality"/> value.
        /// This depends on its implementation.
        /// </para>
        /// <para>
        /// If no preferred codecs are specified, then <see cref="DefaultCodecPreference"/> is used.
        /// MPEG-4 codecs that are not explicitly supported can be specified. However, in this case
        /// the encoder is not guaranteed to work properly.
        /// </para>
        /// </remarks>
        public Mpeg4VcmVideoEncoder(int width, int height, double fps, int frameCount, int quality, params FourCC[] codecPreference)
        {
            Argument.IsPositive(width, nameof(width));
            Argument.IsPositive(height, nameof(height));
            Argument.IsPositive(fps, nameof(fps));
            Argument.IsNotNegative(frameCount, nameof(frameCount));
            Argument.IsInRange(quality, 1, 100, nameof(quality));

            CheckSupportedPlatform();

            this.width   = width;
            this.height  = height;
            sourceBuffer = new byte[width * height * 4];

            inBitmapInfo           = CreateBitmapInfo(width, height, 32, CodecIds.Uncompressed);
            inBitmapInfo.ImageSize = (uint)sourceBuffer.Length;

            if (codecPreference == null || codecPreference.Length == 0)
            {
                codecPreference = DefaultCodecPreference.ToArray();
            }
            foreach (var codec in codecPreference)
            {
                outBitmapInfo    = CreateBitmapInfo(width, height, 24, codec);
                compressorHandle = GetCompressor(inBitmapInfo, outBitmapInfo, out compressorInfo);
                if (compressorHandle != IntPtr.Zero)
                {
                    break;
                }
            }

            if (compressorHandle == IntPtr.Zero)
            {
                throw new InvalidOperationException("No compatible MPEG-4 encoder found.");
            }

            try
            {
                maxEncodedSize = GetMaxEncodedSize();

                // quality for ICM ranges from 0 to 10000
                this.quality = compressorInfo.SupportsQuality ? quality * 100 : 0;

                // typical key frame rate ranges from FPS to 2*FPS
                keyFrameRate = (int)Math.Round((2 - 0.01 * quality) * fps);

                if (compressorInfo.RequestsCompressFrames)
                {
                    InitCompressFramesInfo(fps, frameCount);
                }

                StartCompression();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
示例#3
0
        /// <summary>
        /// Creates a new instance of <see cref="Mpeg4VideoEncoderVcm"/>.
        /// </summary>
        /// <param name="width">Frame width.</param>
        /// <param name="height">Frame height.</param>
        /// <param name="fps">Frame rate.</param>
        /// <param name="frameCount">
        /// Number of frames to be encoded.
        /// If not known, specify 0.
        /// </param>
        /// <param name="quality">
        /// Compression quality in the range [1..100].
        /// Less values mean less size and lower image quality.
        /// </param>
        /// <param name="codecPreference">
        /// List of codecs that can be used by this encoder, in preferred order.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// No compatible codec was found in the system.
        /// </exception>
        /// <remarks>
        /// <para>
        /// It is not guaranteed that the codec will respect the specified <paramref name="quality"/> value.
        /// This depends on its implementation.
        /// </para>
        /// <para>
        /// If no preferred codecs are specified, then <see cref="DefaultCodecPreference"/> is used.
        /// MPEG-4 codecs that are not explicitly supported can be specified. However, in this case
        /// the encoder is not guaranteed to work properly.
        /// </para>
        /// </remarks>
        public Mpeg4VideoEncoderVcm(int width, int height, double fps, int frameCount, int quality, params FourCC[] codecPreference)
        {
            Contract.Requires(width > 0);
            Contract.Requires(height > 0);
            Contract.Requires(fps > 0);
            Contract.Requires(frameCount >= 0);
            Contract.Requires(1 <= quality && quality <= 100);

            this.width   = width;
            this.height  = height;
            sourceBuffer = new byte[width * height * 4];

            inBitmapInfo           = CreateBitmapInfo(width, height, 32, KnownFourCCs.Codecs.Uncompressed);
            inBitmapInfo.ImageSize = (uint)sourceBuffer.Length;

            if (codecPreference == null || codecPreference.Length == 0)
            {
                codecPreference = DefaultCodecPreference.ToArray();
            }
            foreach (var codec in codecPreference)
            {
                outBitmapInfo    = CreateBitmapInfo(width, height, 24, codec);
                compressorHandle = GetCompressor(inBitmapInfo, outBitmapInfo, out compressorInfo);
                if (compressorHandle != IntPtr.Zero)
                {
                    break;
                }
            }

            if (compressorHandle == IntPtr.Zero)
            {
                throw new InvalidOperationException("No compatible MPEG-4 encoder found.");
            }

            try
            {
                maxEncodedSize = GetMaxEncodedSize();

                // quality for ICM ranges from 0 to 10000
                this.quality = compressorInfo.SupportsQuality ? quality * 100 : 0;

                // typical key frame rate ranges from FPS to 2*FPS
                keyFrameRate = (int)Math.Round((2 - 0.01 * quality) * fps);

                if (compressorInfo.RequestsCompressFrames)
                {
                    InitCompressFramesInfo(fps, frameCount);
                }

                StartCompression();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
示例#4
0
        /// <summary>
        /// Creates a new instance of <see cref="Mpeg4VideoEncoderVcm"/>.
        /// </summary>
        /// <param name="width">Frame width.</param>
        /// <param name="height">Frame height.</param>
        /// <param name="fps">Frame rate.</param>
        /// <param name="frameCount">
        /// Number of frames to be encoded.
        /// If not known, specify 0.
        /// </param>
        /// <param name="quality">
        /// Compression quality in the range [1..100].
        /// Less values mean less size and lower image quality.
        /// </param>
        /// <param name="codecPreference">
        /// List of codecs that can be used by this encoder, in preferred order.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// No compatible codec was found in the system.
        /// </exception>
        /// <remarks>
        /// <para>
        /// It is not guaranteed that the codec will respect the specified <paramref name="quality"/> value.
        /// This depends on its implementation.
        /// </para>
        /// <para>
        /// If no preferred codecs are specified, then <see cref="DefaultCodecPreference"/> is used.
        /// MPEG-4 codecs that are not explicitly supported can be specified. However, in this case
        /// the encoder is not guaranteed to work properly.
        /// </para>
        /// </remarks>
        public Mpeg4VideoEncoderVcm(int width, int height, double fps, int frameCount, int quality, params FourCC[] codecPreference)
        {
            Contract.Requires(width > 0);
            Contract.Requires(height > 0);
            Contract.Requires(fps > 0);
            Contract.Requires(frameCount >= 0);
            Contract.Requires(1 <= quality && quality <= 100);

            this.width = width;
            this.height = height;
            sourceBuffer = new byte[width * height * 4];

            inBitmapInfo = CreateBitmapInfo(width, height, 32, KnownFourCCs.Codecs.Uncompressed);
            inBitmapInfo.ImageSize = (uint)sourceBuffer.Length;

            if (codecPreference == null || codecPreference.Length == 0)
            {
                codecPreference = DefaultCodecPreference.ToArray();
            }
            foreach (var codec in codecPreference)
            {
                outBitmapInfo = CreateBitmapInfo(width, height, 24, codec);
                compressorHandle = GetCompressor(inBitmapInfo, outBitmapInfo, out compressorInfo);
                if (compressorHandle != IntPtr.Zero)
                    break;
            }

            if (compressorHandle == IntPtr.Zero)
            {
                throw new InvalidOperationException("No compatible MPEG-4 encoder found.");
            }

            try
            {
                maxEncodedSize = GetMaxEncodedSize();

                // quality for ICM ranges from 0 to 10000
                this.quality = compressorInfo.SupportsQuality ? quality * 100 : 0;

                // typical key frame rate ranges from FPS to 2*FPS
                keyFrameRate = (int)Math.Round((2 - 0.01 * quality) * fps);

                if (compressorInfo.RequestsCompressFrames)
                {
                    InitCompressFramesInfo(fps, frameCount);
                }

                StartCompression();
            }
            catch
            {
                Dispose();
                throw;
            }
        }