コード例 #1
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public void Close()
        {
            int mmr;

            if (this.opened)
            {
                AcmInterop.acmStreamUnprepareHeader(this.pStream, ref this.header, 0);
            }
            if (headerGCHandle.IsAllocated)
            {
                headerGCHandle.Free();
            }
            if (this.header.pbDst != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(this.header.pbDst);
                this.header.pbDst = IntPtr.Zero;
            }
            if (this.header.pbSrc != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(this.header.pbSrc);
                this.header.pbSrc = IntPtr.Zero;
            }
            if (this.pStream != IntPtr.Zero)
            {
                mmr          = AcmInterop.acmStreamClose(this.pStream, 0);
                this.pStream = IntPtr.Zero;
            }
            this.opened = false;
        }
コード例 #2
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public void Open()
        {
            if (this.opened)
            {
                throw new InvalidOperationException();
            }
            if (this.inputFormat == null)
            {
                throw new InvalidOperationException("Input format is not specified.");
            }
            if (this.outputFormat == null)
            {
                throw new InvalidOperationException("Output format is not specified.");
            }
            this.pwfxSource   = this.inputFormat.ToPtr();
            this.pwfxDest     = this.outputFormat.ToPtr();
            this.outputFormat = new SoundFormat(this.pwfxDest);

            int mmr = AcmInterop.acmStreamOpen(out this.pStream, IntPtr.Zero, this.pwfxSource, this.pwfxDest,
                                               IntPtr.Zero, IntPtr.Zero, UIntPtr.Zero, 0);

            if (mmr != 0)
            {
                throw new SoundException("acmStreamOpen", mmr);
            }
            int cbSrcLength = (int)((this.bufferLength / 1000.0) * this.inputFormat.AverageBytesPerSecond);

            this.header             = new AcmInterop.ACMSTREAMHEADER();
            this.header.cbStruct    = Marshal.SizeOf(this.header);
            this.header.cbSrcLength = cbSrcLength;
            int suggestedDstLength;

            mmr = AcmInterop.acmStreamSize(this.pStream, cbSrcLength, out suggestedDstLength,
                                           AcmInterop.ACM_STREAMSIZEF_SOURCE);
            try {
                this.header.cbDstLength = suggestedDstLength;
                this.header.pbDst       = Marshal.AllocHGlobal(suggestedDstLength);
                this.header.pbSrc       = Marshal.AllocHGlobal(cbSrcLength);
                this.headerGCHandle     = GCHandle.Alloc(this.header, GCHandleType.Pinned);
                mmr = AcmInterop.acmStreamPrepareHeader(this.pStream, ref this.header, 0);
                if (mmr != 0)
                {
                    throw new SoundException("acmStreamPrepareHeader", mmr);
                }
                this.isStart = true;
                this.opened  = true;
            }
            finally {
                if (!this.opened)
                {
                    this.Close();
                }
            }
        }
コード例 #3
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public static int GetMaxFormatSize()
        {
            if (maxFormatSize > 0)
            {
                return(maxFormatSize);
            }
            // Get maximum size of WAVEFORMATEX
            int mmr = AcmInterop.acmMetrics(IntPtr.Zero, AcmInterop.ACM_METRIC_MAX_SIZE_FORMAT, out maxFormatSize);

            if (mmr != 0)
            {
                throw new SoundException("acmMetrics", mmr);
            }
            return(maxFormatSize);
        }
コード例 #4
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public static int[] GetDriverIds()
        {
            if (driverIds != null)
            {
                return(driverIds);
            }
            callbackDriverIdList = new List <int>();
            int mmr = AcmInterop.acmDriverEnum(DriverCallback, 0, 0);

            if (mmr != 0)
            {
                throw new SoundException("acmDriverEnum", mmr);
            }
            driverIds = callbackDriverIdList.ToArray();
            return(driverIds);
        }
コード例 #5
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public byte[] Convert(byte[] source, int offset, int length, bool isEnd)
        {
            if (!this.opened)
            {
                throw new InvalidOperationException();
            }
            // Copy data to source pointer
            this.header.cbSrcLength     = length;
            this.header.cbSrcLengthUsed = 0;
            this.header.cbDstLengthUsed = 0;
            Marshal.Copy(source, offset, this.header.pbSrc, length);

            // Convert source
            AcmConvertFlags flags = AcmConvertFlags.None;

            if (!isStart && !isEnd)
            {
                flags = AcmConvertFlags.BlockAlign;
            }
            if (this.isStart)
            {
                flags       |= AcmConvertFlags.Start;
                this.isStart = false;
            }
            if (isEnd)
            {
                flags |= AcmConvertFlags.End;
            }
            int mmr = AcmInterop.acmStreamConvert(this.pStream, ref this.header, (int)flags);

            if (mmr != 0)
            {
                throw new SoundException("acmStreamConvert", mmr);
            }
            // Copy data from source pointer to byte array
            int destLength = this.header.cbDstLengthUsed;

            byte[] dest = new byte[destLength];
            Marshal.Copy(this.header.pbDst, dest, 0, destLength);

            return(dest);
        }
コード例 #6
0
ファイル: AcmEncoder.cs プロジェクト: thaolt/screenrecorder
        public static AcmConvertionMap GetConvertionMap(SoundFormat[] inputFormats, SoundFormatTag tagFilter)
        {
            // First, we enumerate convertion formats
            AcmConvertionMap initConvertionMap = new AcmConvertionMap();
            int maxFormatSize = GetMaxFormatSize();

            // Enumerate acm drivers
            foreach (int driverId in GetDriverIds())
            {
                // Open driver
                IntPtr phDriver;
                int    mmr = AcmInterop.acmDriverOpen(out phDriver, driverId, 0);
                if (mmr != 0)
                {
                    continue;
                }
                // For each input format, we do enumeration
                foreach (SoundFormat inputFormat in inputFormats)
                {
                    // Fill format details struct
                    AcmInterop.ACMFORMATDETAILS fmtDetails = new AcmInterop.ACMFORMATDETAILS();
                    IntPtr pwfxFormat = inputFormat.ToPtr(maxFormatSize);
                    fmtDetails.cbStruct = Marshal.SizeOf(fmtDetails);
                    fmtDetails.pwfx     = pwfxFormat;
                    fmtDetails.cbwfx    = maxFormatSize;

                    // Enumerate convertion formats
                    callbackFormats = new List <SoundFormat>();
                    IntPtr pwfxInput = inputFormat.ToPtr();
                    mmr = AcmInterop.acmFormatEnum(phDriver, ref fmtDetails, FormatEnumCallback, IntPtr.Zero,
                                                   AcmInterop.ACM_FORMATENUMF_CONVERT);
                    Marshal.FreeHGlobal(pwfxInput);

                    // Add formats to the map (if succeed)
                    if (mmr == 0)
                    {
                        initConvertionMap.Add(inputFormat, callbackFormats);
                    }
                    callbackFormats = null;
                }

                // Close driver
                mmr = AcmInterop.acmDriverClose(phDriver, 0);
            }

            // Now we query ACM to make sure each convertion is supported
            AcmConvertionMap finalConvertionMap = new AcmConvertionMap();

            SoundFormat[] inputs = initConvertionMap.GetInputs();
            foreach (SoundFormat inputFormat in inputs)
            {
                IntPtr pwfxSrc = inputFormat.ToPtr();
                foreach (SoundFormat outputFormat in initConvertionMap.GetOutputs(inputFormat))
                {
                    // Filter tags
                    if (tagFilter != SoundFormatTag.UNKNOWN && outputFormat.Tag != tagFilter)
                    {
                        continue;
                    }
                    IntPtr phs;
                    IntPtr pwfxDst = outputFormat.ToPtr();
                    // Open acm stream using the query flag
                    int mmr = AcmInterop.acmStreamOpen(out phs, IntPtr.Zero, pwfxSrc, pwfxDst, IntPtr.Zero, IntPtr.Zero,
                                                       UIntPtr.Zero, AcmInterop.ACM_STREAMOPENF_QUERY);
                    Marshal.FreeHGlobal(pwfxDst);

                    // Add format to the final map if succeed
                    if (mmr == 0)
                    {
                        finalConvertionMap.Add(inputFormat, outputFormat);
                    }
                }
                Marshal.FreeHGlobal(pwfxSrc);
            }
            return(finalConvertionMap);
        }
コード例 #7
0
ファイル: AcmEncoder.cs プロジェクト: bspkrs/screenrecorder
 private static bool FormatEnumCallback(IntPtr had, ref AcmInterop.ACMFORMATDETAILS pafd, UIntPtr dwInstance,
                                      int fdwSupport)
 {
     if (pafd.cbwfx >= Marshal.SizeOf(typeof(MMInterop.WAVEFORMATEX))) {
     SoundFormat soundFormat = new SoundFormat(pafd.pwfx);
     callbackFormats.Add(soundFormat);
      }
      return true;
 }