示例#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
        private int GetMaxEncodedSize()
        {
            var inHeader  = inBitmapInfo;
            var outHeader = outBitmapInfo;

            return(VfwApi.ICSendMessage(compressorHandle, VfwApi.ICM_COMPRESS_GET_SIZE, ref inHeader, ref outHeader));
        }
示例#3
0
        private int EncodeFrame(IntPtr sourcePtr, IntPtr destinationPtr, uint destinationSize, out bool isKeyFrame)
        {
            var outInfo = outBitmapInfo;

            outInfo.ImageSize = destinationSize;
            var inInfo = inBitmapInfo;
            var flags  = framesFromLastKey >= keyFrameRate ? VfwApi.ICCOMPRESS_KEYFRAME : 0;

            var result = VfwApi.ICCompress(compressorHandle, flags,
                                           ref outInfo, destinationPtr, ref inInfo, sourcePtr,
                                           out _, out var outFlags, frameIndex,
                                           0, quality, IntPtr.Zero, IntPtr.Zero);

            CheckICResult(result);
            frameIndex++;


            isKeyFrame = (outFlags & VfwApi.AVIIF_KEYFRAME) == VfwApi.AVIIF_KEYFRAME;
            if (isKeyFrame)
            {
                framesFromLastKey = 1;
            }
            else
            {
                framesFromLastKey++;
            }

            return((int)outInfo.ImageSize);
        }
示例#4
0
        private void StartCompression()
        {
            var inHeader  = inBitmapInfo;
            var outHeader = outBitmapInfo;
            var result    = VfwApi.ICSendMessage(compressorHandle, VfwApi.ICM_COMPRESS_BEGIN, ref inHeader, ref outHeader);

            CheckICResult(result);

            needEnd           = true;
            framesFromLastKey = keyFrameRate;
        }
        private void CheckICResult(int result)
        {
            if (result != VfwApi.ICERR_OK)
            {
                var errorDesc = VfwApi.GetErrorDescription(result);
                var resultStr = errorDesc == null
                    ? result.ToString()
                    : string.Format("{0} ({1})", result, errorDesc);

                throw new InvalidOperationException(string.Format("Encoder operation returned an error: {0}.", resultStr));
            }
        }
示例#6
0
        private void InitCompressFramesInfo(double fps, int frameCount)
        {
            var info = new VfwApi.CompressFramesInfo
            {
                StartFrame = 0,
                FrameCount = frameCount,
                Quality    = quality,
                KeyRate    = keyFrameRate,
            };

            AviUtils.SplitFrameRate((decimal)fps, out info.FrameRateNumerator, out info.FrameRateDenominator);

            var result = VfwApi.ICSendMessage(compressorHandle, VfwApi.ICM_COMPRESS_FRAMES_INFO, ref info, Marshal.SizeOf(typeof(VfwApi.CompressFramesInfo)));

            CheckICResult(result);
        }
示例#7
0
        /// <summary>Encodes a frame.</summary>
        /// <seealso cref="IVideoEncoder.EncodeFrame"/>
        public int EncodeFrame(byte[] source, int srcOffset, byte[] destination, int destOffset, out bool isKeyFrame)
        {
            // TODO: Introduce Width and Height in IVideoRecorder and add Requires to EncodeFrame contract
            Contract.Assert(srcOffset + 4 * width * height <= source.Length);

            BitmapUtils.FlipVertical(source, srcOffset, sourceBuffer, 0, height, width * 4);

            var sourceHandle  = GCHandle.Alloc(sourceBuffer, GCHandleType.Pinned);
            var encodedHandle = GCHandle.Alloc(destination, GCHandleType.Pinned);

            try
            {
                var outInfo = outBitmapInfo;
                outInfo.ImageSize = (uint)destination.Length;
                var inInfo = inBitmapInfo;
                int outFlags;
                int chunkID;
                var flags = framesFromLastKey >= keyFrameRate ? VfwApi.ICCOMPRESS_KEYFRAME : 0;

                var result = VfwApi.ICCompress(compressorHandle, flags,
                                               ref outInfo, encodedHandle.AddrOfPinnedObject(), ref inInfo, sourceHandle.AddrOfPinnedObject(),
                                               out chunkID, out outFlags, frameIndex,
                                               0, quality, IntPtr.Zero, IntPtr.Zero);
                CheckICResult(result);
                frameIndex++;


                isKeyFrame = (outFlags & VfwApi.AVIIF_KEYFRAME) == VfwApi.AVIIF_KEYFRAME;
                if (isKeyFrame)
                {
                    framesFromLastKey = 1;
                }
                else
                {
                    framesFromLastKey++;
                }

                return((int)outInfo.ImageSize);
            }
            finally
            {
                sourceHandle.Free();
                encodedHandle.Free();
            }
        }
示例#8
0
        /// <summary>
        /// Releases all unmanaged resources used by the encoder.
        /// </summary>
        public void Dispose()
        {
            if (!isDisposed)
            {
                if (needEnd)
                {
                    EndCompression();
                }

                if (compressorHandle != IntPtr.Zero)
                {
                    VfwApi.ICClose(compressorHandle);
                }

                isDisposed = true;
                GC.SuppressFinalize(this);
            }
        }
示例#9
0
        /// <summary>
        /// Gets info about the supported codecs that are installed on the system.
        /// </summary>
        public static CodecInfo[] GetAvailableCodecs()
        {
            var result = new List <CodecInfo>();

            var inBitmapInfo = CreateBitmapInfo(8, 8, 32, KnownFourCCs.Codecs.Uncompressed);

            inBitmapInfo.ImageSize = (uint)4;

            foreach (var codec in DefaultCodecPreference)
            {
                var outBitmapInfo = CreateBitmapInfo(8, 8, 24, codec);
                VfwApi.CompressorInfo compressorInfo;
                var compressorHandle = GetCompressor(inBitmapInfo, outBitmapInfo, out compressorInfo);
                if (compressorHandle != IntPtr.Zero)
                {
                    VfwApi.ICClose(compressorHandle);
                    result.Add(new CodecInfo(codec, compressorInfo.Description));
                }
            }

            return(result.ToArray());
        }
示例#10
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;
        }
示例#11
0
        private void EndCompression()
        {
            var result = VfwApi.ICSendMessage(compressorHandle, VfwApi.ICM_COMPRESS_END, IntPtr.Zero, IntPtr.Zero);

            CheckICResult(result);
        }