public Preferences(string sData) { XmlDocument cXmlDocument = new XmlDocument(); cXmlDocument.LoadXml(sData); XmlNode cXmlNode = cXmlDocument.NodeGet("data"); XmlNode cNodeChild = cXmlNode.NodeGet("playlist"); _bCuda = cNodeChild.AttributeGet<bool>("cuda"); _nLayer = cNodeChild.AttributeGet<ushort>("layer"); cNodeChild = cNodeChild.NodeGet("area"); _stArea = new Area( cNodeChild.AttributeGet<short>("left"), cNodeChild.AttributeGet<short>("top"), cNodeChild.AttributeGet<ushort>("width"), cNodeChild.AttributeGet<ushort>("height") ); }
internal EffectVideo(EffectType eType) : base(eType) { try { bCUDA = Preferences.bCUDA; nFrameCurrent = 0; stArea = new Area(0, 0, 0, 0); nMaxOpacity = 255; nInDissolve = 0; nOutDissolve = 0; } catch { Fail(); throw; } }
public Preferences(string sData) { XmlDocument cXmlDocument = new XmlDocument(); cXmlDocument.LoadXml(sData); XmlNode cXmlNode = cXmlDocument.NodeGet("data"); sRequest = cXmlNode.AttributeValueGet("request"); nTemplate = cXmlNode.AttributeGet<byte>("template"); sValue = cXmlNode.AttributeValueGet("value", false); _nCheckInterval = cXmlNode.AttributeGet<int>("interval"); XmlNode cNodeChild = cXmlNode.NodeGet("roll"); _eDirection = cNodeChild.AttributeGet<btl.Roll.Direction>("direction"); _nSpeed = cNodeChild.AttributeGet<float>("speed"); _bRollCuda = cNodeChild.AttributeGet<bool>("cuda"); _nLayer = cNodeChild.AttributeGet<ushort>("layer"); _nQueueLength = cNodeChild.AttributeGet<byte>("queue"); if (int.MaxValue == (_nPause = cNodeChild.AttributeGet<int>("pause", false))) _nPause = 0; cNodeChild = cNodeChild.NodeGet("area"); _stArea = new Area( cNodeChild.AttributeGet<short>("left"), cNodeChild.AttributeGet<short>("top"), cNodeChild.AttributeGet<ushort>("width"), cNodeChild.AttributeGet<ushort>("height") ); _aItems = cXmlNode.NodesGet("item").Select(o => Item.Parse(o)).ToList(); }
public Baetylus() { (new Logger()).WriteDebug3("in"); lock (_cSyncRoot) { if (1 > _nReferencesQty) { (new Logger()).WriteDebug4("baetylus:constructor:init"); _aqContainerActions = new Queue<Dictionary<IEffect, ContainerAction>>(); _aEffects = new List<IEffect>(); _stFullFrameArea = cBoard.stArea; _aqBufferFrame = new ThreadBufferQueue<Device.Frame>(Preferences.nQueueBaetylusLength, true, false); _aqPixelsMapsDisposed = new Queue<PixelsMap>(); _bNeedEffectsReorder = false; _cThreadWorker = new System.Threading.Thread(Worker); _cThreadWorker.IsBackground = true; _cThreadWorker.Priority = System.Threading.ThreadPriority.AboveNormal; _cThreadWorker.Start(); _bDoWritingFrames = false; _aqWritingFrames = new Queue<byte[]>(); _cThreadWritingFramesWorker = new System.Threading.Thread(WritingFramesWorker); _cThreadWritingFramesWorker.IsBackground = true; _cThreadWritingFramesWorker.Priority = System.Threading.ThreadPriority.Normal; _cThreadWritingFramesWorker.Start(); cBoard.NextFrame += new NextFrameCallback(OnNextFrame); cBoard.TurnOn(); } _nReferencesQty++; } (new Logger()).WriteDebug4("return [refqty:" + _nReferencesQty + "]"); }
private DisCom.LayerInfo Intersect(Area stBase) //v: Даёт размерность, ширину, высоту кропа и относительные координаты его лев верх угла от бэка и от фора и ширину кропа. { //в целях оптимизации убраны все проверки, т.к. они уже были в FramesMerge... DisCom.LayerInfo cRetVal = new DisCom.LayerInfo(); cRetVal.nShiftPosition = _nShiftPosition; cRetVal.bShiftVertical = _bShiftVertical; Area stCrop = _stArea.CropOnBase(stBase); cRetVal.nWidth = stArea.nWidth; cRetVal.nCropWidth = stCrop.nWidth; cRetVal.nCropHeight = stCrop.nHeight; cRetVal.nCropLeft = stCrop.nLeft - stBase.nLeft; //отступ кропа слева COL int nBGIndxStart = (stCrop.nTop - stBase.nTop) * stBase.nWidth + cRetVal.nCropLeft; //BGIndxStart=COT*BW+COL; //формула вычисления FI=BI+M*(FW-BW)-(FOT*FW+FOL); M=(int)(BI/BW); cRetVal.nWidthDiff = _stArea.nWidth - stBase.nWidth; //5/ константа 1 - (FW-BW) cRetVal.nForegroundStart = (_stArea.nTop - stBase.nTop) * _stArea.nWidth + _stArea.nLeft - stBase.nLeft; //6/ константа 2 - (FOT*FW+FOL) cRetVal.nBackgroundStart = nBGIndxStart; //7/ начальный индекс по BG cRetVal.nBackgroundStop = nBGIndxStart + (stCrop.nHeight - 1) * stBase.nWidth + stCrop.nWidth - 1;//8/ конечный индекс по BG cRetVal.nCropRight = cRetVal.nCropLeft + stCrop.nWidth - 1; //10/ константа COL+CW-1 cRetVal.nAlphaConstant = nAlphaConstant; //11/ константная альфа cRetVal.nAlphaType = (byte)eAlpha; cRetVal.nShiftTotal = _nShiftTotal; cRetVal.nTop = stArea.nTop; cRetVal.nLeft = stArea.nLeft; if (null != _cShiftOffset) { cRetVal.nOffsetLeft = _cShiftOffset.nLeft; cRetVal.nOffsetTop = _cShiftOffset.nTop & 1; if (stBase.nTop > _stArea.nTop && ((stBase.nTop - _stArea.nTop) & 1) == 1) cRetVal.nOffsetTop = ~cRetVal.nOffsetTop; } return cRetVal; }
public Area CropOnBase(Area stBase) //Valikoo. Возвращает обрезанную область если она вышла за рамки образца stBase { Area stRetVal = new Area(); stRetVal.nLeft = stBase.nLeft > nLeft ? stBase.nLeft : nLeft; stRetVal.nTop = stBase.nTop > nTop ? stBase.nTop : nTop; stRetVal.nRight = stBase.nRight > nRight ? nRight : stBase.nRight; stRetVal.nBottom = stBase.nBottom > nBottom ? nBottom : stBase.nBottom; if (0 == stRetVal.nWidth || 0 == stRetVal.nHeight) { stRetVal.nWidth = 0; stRetVal.nHeight = 0; } return stRetVal; }
public Composite(ushort nDimensionTargetMax, Type enType) :this() { switch (enType) { case Type.Vertical: _nWidth = nDimensionTargetMax; _aLines = new List<Line>(); enType = Type.Vertical; break; case Type.Horizontal: //это конструктор горизонтальный. TODO. ДОДЕЛАТЬ ДОБАВЛЕНИЕ !!!!!!!!! _nHeight = nDimensionTargetMax; _aColumns = new List<Column>(); enType = Type.Horizontal; break; case Type.Fixed: _nHeight = _nWidth = nDimensionTargetMax; stArea = new Area(0, 0, _nWidth, _nHeight); enType = Type.Fixed; break; default: break; } }
override public void Prepare() { try { if (EffectStatus.Idle != ((IEffect)this).eStatus) return; if (bResize && Area.stEmpty != stArea) { stArea = AreaResize(_cFile.stDimensions.Width, _cFile.stDimensions.Height, stArea.nWidth, stArea.nHeight, nPixelAspectRatio); _cFile.stDimensionsResized = new Size(stArea.nWidth, stArea.nHeight); } else if (bResize && Area.stEmpty == stArea) { stArea = AreaResize(_cFile.stDimensions.Width, _cFile.stDimensions.Height, _cFile.stDimensions.Width, _cFile.stDimensions.Height, nPixelAspectRatio); _cFile.stDimensionsResized = new Size(stArea.nWidth, stArea.nHeight); stArea = new Area(0, 0, stArea.nWidth, stArea.nHeight); } else stArea = new Area(stArea.nLeft, stArea.nTop, (ushort)_cFile.stDimensions.Width, (ushort)_cFile.stDimensions.Height); if (null == _cPixelsMap) { _cFile.Open(); if (bKeepAlive) _cFile.Cache(); //#if DEBUG else _cFile.DynamicQueueStart(); //DNF //#endif _cPixelsMap = new PixelsMap(bCUDA, new Area(0, 0, stArea.nWidth, stArea.nHeight), PixelsMap.Format.ARGB32); _cPixelsMap.bKeepAlive = true; if (1 > _cPixelsMap.nLength) (new Logger()).WriteNotice("1 > _cPixelMap.nLength. animation.prepare"); _cPixelsMap.Allocate(); nDuration = nFramesTotal; } else { nFrameCurrentPhysical = 0; //это если препаре делают после стопа. nLoopCurrent = 0; } base.Prepare(); } catch (Exception ex) { (new Logger()).WriteError(ex); (new Logger()).WriteWarning("[bKeepAlive = " + (null == _cPixelsMap ? "null" : "" + _cPixelsMap.bKeepAlive) + "][nDuration = " + nDuration + "]"); throw; } }
public PixelsMap(Area stArea, Format ePixelFormat) : this(true, stArea, ePixelFormat) { }
private DisCom.LayerInfo Intersect(Area stBase) //v: Даёт размерность, ширину, высоту кропа и относительные координаты его лев верх угла от бэка и от фора и ширину кропа. { //в целях оптимизации убраны все проверки, т.к. они уже были в FramesMerge... DisCom.LayerInfo cRetVal = new DisCom.LayerInfo(); Area stCrop = _stArea.CropOnBase(stBase); // если кроп нулевой, то w == h == 0 if (stCrop.nWidth == 0) //не пересеклись { cRetVal.nCropTopLineInBG = -1; cRetVal.nCropBottomLineInBG = -1; } else { cRetVal.nWidth_4 = 4 * stArea.nWidth; cRetVal.nCropWidth_4 = 4 * stCrop.nWidth; int nCropLeft = stCrop.nLeft - stBase.nLeft; //отступ кропа слева COL cRetVal.nCropLeft_4 = 4 * nCropLeft; int nBGIndxStart = (stCrop.nTop - stBase.nTop) * stBase.nWidth + nCropLeft; //BGIndxStart=COT*BW+COL; начальный индекс по бг //формула вычисления FI=BI+M*(FW-BW)-(FOT*FW+FOL); M=(int)(BI/BW); cRetVal.nAlphaConstant = nAlphaConstant; //11/ константная альфа cRetVal.nAlphaType = (byte)eAlpha; cRetVal.nTop = stArea.nTop; cRetVal.nLeft_4 = 4 * stArea.nLeft; cRetVal.nCropTopLineInBG = nBGIndxStart / stBase.nWidth; cRetVal.nCropBottomLineInBG = cRetVal.nCropTopLineInBG + stCrop.nHeight - 1; int nFloorX = (int)Math.Floor(_stPosition.X); int nFloorY = (int)Math.Floor(_stPosition.Y); float nShift = _stPosition.X - nFloorX; // т.е. всегда теперь 0 <= S < 1 if ((cRetVal.nShiftPositionByteX = (byte)Math.Abs(255 * nShift)) == 255) { cRetVal.nShiftPositionByteX = 254; } nShift = _stPosition.Y - nFloorY; if ((cRetVal.nShiftPositionByteY = (byte)Math.Abs(255 * nShift)) == 255) { cRetVal.nShiftPositionByteY = 254; } cRetVal.nShiftTotalX = _nShiftTotalX; if (0 < Math.Abs(_nShiftTotalX)) // то делаем поля { int nFloorHalfX = (int)Math.Floor(_stHalfPosition.X); int nFloorHalfY = (int)Math.Floor(_stHalfPosition.Y); nShift = _stHalfPosition.X - nFloorHalfX; cRetVal.nHalfPathShiftPositionByteX = nShift == 0 ? (byte)0 : (byte)Math.Abs(255 * nShift); nShift = _stHalfPosition.Y - nFloorHalfY; cRetVal.nHalfPathShiftPositionByteY = nShift == 0 ? (byte)0 : (byte)Math.Abs(255 * nShift); // (для диагональных смещений с полями) // знак узнаем из nDeltaPxX_4 cRetVal.nHalfDeltaPxX_4 = (nFloorX - nFloorHalfX) * 4; cRetVal.nHalfDeltaPxY_4 = (nFloorY - nFloorHalfY) * 4; if (null != _cShiftOffset) { cRetVal.nOffsetTop = _cShiftOffset.nTop & 1; if (stBase.nTop > _stArea.nTop && ((stBase.nTop - _stArea.nTop) & 1) == 1) { cRetVal.nOffsetTop = ~cRetVal.nOffsetTop; } } } } return(cRetVal); }
private Area AreaResize(int nImageWidth, int nImageHeight, int nCanvasWidth, int nCanvasHeight, float nPixelAspectRatio) { Area stRetVal; nImageWidth = (int)Math.Round(((double)nImageWidth) * nPixelAspectRatio, 0); int nCrop; if (nImageWidth * nCanvasHeight > nImageHeight * nCanvasWidth) { nCrop = (int)Math.Round((double)(nImageHeight * nCanvasWidth) / (double)nImageWidth, 0); stRetVal = new Area(0, (short)Math.Round((double)(nCanvasHeight - nCrop) / 2, 0), (ushort)nCanvasWidth, (ushort)nCrop); _cFile.stDimensionsResized = new Size(nCanvasWidth, nCrop); } else { nCrop = (int)Math.Round((double)(nImageWidth * nCanvasHeight) / (double)nImageHeight, 0); stRetVal = new Area((short)Math.Round((double)(nCanvasWidth - nCrop) / 2, 0), 0, (ushort)nCrop, (ushort)nCanvasHeight); _cFile.stDimensionsResized = new Size(nCrop, nCanvasHeight); } return stRetVal; }
public PixelsMap(MergingMethod stMergingMethod, Area stArea, Format ePixelFormat) : this(stMergingMethod, stArea, ePixelFormat, false) { }
override public void Prepare() { try { float nK; ushort nNewSize; short nHalfDelta; (new Logger()).WriteDebug2("video prepare [old area:" + stArea.nWidth + " " + stArea.nHeight + "]"); (new Logger()).WriteDebug2("video prepare [file area:" + _cFile.stArea.nWidth + " " + _cFile.stArea.nHeight + "]"); (new Logger()).WriteDebug2("video prepare [file w h:" + _cFile.nWidthOriginal + " " + _cFile.nHeightOriginal + "]"); //DNF FitIn eFitIn = FitIn.Crop; // типа из настроек пришло )) if (_cFile.nHeightOriginal != stArea.nHeight || _cFile.nWidthOriginal != stArea.nWidth) // если видео не совпало с контейнером { if (_cFile.nHeightOriginal == 576 && _cFile.nWidthOriginal == 720) // if video format is PAL = 768x576 in square pixels рассмотрим частный случай, т.к. он восновном и будет только. { if (eFitIn == FitIn.Crop) { nK = (float)stArea.nWidth / 768; // коэффициент (делаем правильно именно дл¤ пала с учетом аспекта пиксел¤ у пала) nNewSize = (ushort)Math.Round(nK * _cFile.nHeightOriginal); // нова¤ высота при раст¤гивании по ширине nHalfDelta = (short)Math.Round(((float)(stArea.nHeight - nNewSize) / 2)); stArea = new Area(0, nHalfDelta, stArea.nWidth, nNewSize); //stArea = new Area(0, -180, 1920, 1440); должно быть так, если правильно посчитано будет... } } else // if video is not container's size and not PAL { if (eFitIn == FitIn.Crop) { if (_cFile.nWidthOriginal > _cFile.nHeightOriginal) { nK = (float)stArea.nWidth / _cFile.nWidthOriginal; // коэффициент nNewSize = (ushort)Math.Round(nK * _cFile.nHeightOriginal); // нова¤ высота при раст¤гивании по ширине nHalfDelta = (short)Math.Round((float)(stArea.nHeight - nNewSize) / 2); stArea = new Area(0, nHalfDelta, stArea.nWidth, nNewSize); } else { nK = (float)stArea.nHeight / _cFile.nHeightOriginal; // коэффициент nNewSize = (ushort)Math.Round(nK * _cFile.nWidthOriginal); // нова¤ высота при раст¤гивании по ширине nHalfDelta = (short)Math.Round((float)(stArea.nWidth - nNewSize) / 2); stArea = new Area(nHalfDelta, 0, nNewSize, stArea.nHeight); } } } } //DNF (new Logger()).WriteDebug2("video prepare [new area:" + stArea.nWidth + " " + stArea.nHeight + "]"); _cFile.stArea = stArea; _cFile.Open(bCUDA); if (ulong.MaxValue == nDuration) nDuration = _cFile.nFramesTotal - nFrameStart; (new Logger()).WriteDebug2("video prepared [video_hc:" + GetHashCode() + "][file_hc:" + _cFile.GetHashCode() + "]"); base.Prepare(); } catch { Fail(); throw; } }
static public Area SumOfAreas(Area a1, Area a2) { Area aRetVal = new Area(); aRetVal.nLeft = 0; // a1.nLeft < a2.nLeft ? a1.nLeft : a2.nLeft; aRetVal.nTop = 0; // a1.nTop < a2.nTop ? a1.nTop : a2.nTop; aRetVal.nWidth = a1.nRight < a2.nRight ? (ushort)(a2.nRight - aRetVal.nLeft + 1) : (ushort)(a1.nRight - aRetVal.nLeft + 1); aRetVal.nWidth += a1.nLeft < 0 || a2.nLeft < 0 ? (ushort)0 : (ushort)Math.Min(a1.nLeft, a2.nLeft); aRetVal.nHeight = a1.nBottom < a2.nBottom ? (ushort)(a2.nBottom - aRetVal.nTop + 1) : (ushort)(a1.nBottom - aRetVal.nTop + 1); aRetVal.nHeight += a1.nTop <= 0 || a2.nTop <= 0 ? (ushort)0 : (ushort)Math.Min(a1.nTop, a2.nTop); return aRetVal; }
protected void AreaSet(Area stArea) { if (null != _cEffect) ((shared.EffectVideo)_cEffect).stArea = stArea; this.stArea = stArea; }
public PixelsMap(bool bIsCUDA, Area stArea, Format ePixelFormat) { _dt = DateTime.Now; _bTemp = false; _bProcessing = false; _bDisposed = false; _cSyncRoot = new object(); if (bCUDA = bIsCUDA && 1 > Preferences.nCUDAVersion) throw new Exception("There is no CUDA version in preferences"); #else public PixelsMap() :this(false, new Area(0, 0, 1, 1), Format.BGRA32) { }
public EffectVideo() : base() { cDock = new Dock(Dock.Corner.upper_left, new Dock.Offset(0, 0)); bOpacity = true; stArea = Area.stEmpty; }
public PixelsMap(bool bCUDA, Area stArea, Format ePixelFormat) { #endif _nID = 0; nAlphaConstant = byte.MaxValue; bBackgroundClear = false; bKeepAlive = false; _cException = null; _nBytesQty = 0; _ePixelFormat = ePixelFormat; _stArea = stArea; _nBytesQty = (uint)(_stArea.nWidth * _stArea.nHeight * Math.Abs((int)((int)ePixelFormat / 100)) / 8); _nShiftPosition = 0; _cSyncRoot = new object(); }
public Area Dock(Area stBase, Dock cDock) { Area stRetVal = this; if (null != cDock) { switch (cDock.eCorner) { case helpers.Dock.Corner.upper_left: stRetVal.nLeft = 0; stRetVal.nTop = 0; break; case helpers.Dock.Corner.upper_right: stRetVal.nLeft = (short)(stBase.nWidth - nWidth); stRetVal.nTop = 0; break; case helpers.Dock.Corner.bottom_left: stRetVal.nLeft = 0; stRetVal.nTop = (short)(stBase.nHeight - nHeight); break; case helpers.Dock.Corner.bottom_right: stRetVal.nLeft = (short)(stBase.nWidth - nWidth); stRetVal.nTop = (short)(stBase.nHeight - nHeight); break; case helpers.Dock.Corner.center: stRetVal.nLeft = (short)Math.Round((float)stBase.nWidth / 2 - (float)nWidth / 2); stRetVal.nTop = (short)Math.Round((float)stBase.nHeight / 2 - (float)nHeight / 2); break; } stRetVal.nLeft += cDock.cOffset.nLeft; stRetVal.nTop += cDock.cOffset.nTop; } return stRetVal; }
static public PixelsMap Merge(Area stBase, List<PixelsMap> aPMs) { if (1 == aPMs.Count && 0 == aPMs[0]._nShiftPosition && stBase == aPMs[0].stArea && byte.MaxValue == aPMs[0].nAlphaConstant) return aPMs[0]; #if CUDA PixelsMap cRetVal = new PixelsMap(aPMs[0].bCUDA, stBase, Format.ARGB32); cRetVal._bTemp = true; Command cCmd = null; if (aPMs[0].bCUDA) { //cRetVal._nBytesQty = (uint)(stBase.nWidth * stBase.nHeight * 4); //UNDONE нужно определять кол-во байт по ePixelFormat //FIXED cCmd = new Command(Command.ID.Allocate, cRetVal); _aqCommands.Enqueue(cCmd); } else cRetVal.Allocate(); #else PixelsMap cRetVal = new PixelsMap(false, stBase, Format.ARGB32); cRetVal._bTemp = true; cRetVal.Allocate(); #endif cRetVal.Merge(aPMs); return cRetVal; }
public Composite(ushort nWidth, ushort nHeight) //это конструктор для пустышки или константного размера : this() { stArea = new Area(0, 0, nWidth, nHeight); _nWidth = nWidth; _nHeight = nHeight; _eType = Type.Fixed; }
private Decklink(IDeckLink cDevice) { (new Logger()).WriteDebug3("in"); try { nAudioQueueLength = nAudioQueueLengthPrevious = 0; nBTLAudioQueueLengthPrevious = nBTLVideoQueueLengthPrevious = nVideoQueueLengthPrevious = 0; _iDLDevice = cDevice; if(Preferences.bDeviceInput) _iDLInput = (IDeckLinkInput)_iDLDevice; else _iDLOutput = (IDeckLinkOutput)_iDLDevice; IDeckLinkDisplayModeIterator cDisplayModeIterator; IDeckLinkDisplayMode cNextDLDisplayMode; string sDisplayModeName = ""; string sMessage = "decklink supported modes:<br>"; if (Preferences.bDeviceInput) { _iDLInputDisplayMode = null; _iDLInput.GetDisplayModeIterator(out cDisplayModeIterator); while (true) { cDisplayModeIterator.Next(out cNextDLDisplayMode); if (cNextDLDisplayMode == null) break; cNextDLDisplayMode.GetName(out sDisplayModeName); if (null == _iDLInputDisplayMode && sDisplayModeName.ToLower().Contains(Preferences.sVideoFormat)) { sMessage += "selected:"; _iDLInputDisplayMode = cNextDLDisplayMode; } else sMessage += "\t"; sMessage += sDisplayModeName + "<br>"; } (new Logger()).WriteNotice(sMessage); if (null == _iDLInputDisplayMode) throw new Exception("can't find " + Preferences.sVideoFormat + " mode within specified device for input"); } else { _nFramesAudioDropped = 0; _iDLOutputDisplayMode = null; _iDLOutput.GetDisplayModeIterator(out cDisplayModeIterator); while (true) { cDisplayModeIterator.Next(out cNextDLDisplayMode); if (cNextDLDisplayMode == null) break; cNextDLDisplayMode.GetName(out sDisplayModeName); if (null == _iDLOutputDisplayMode && sDisplayModeName.ToLower().Contains(Preferences.sVideoFormat)) { sMessage += "selected:"; _iDLOutputDisplayMode = cNextDLDisplayMode; } else sMessage += "\t"; sMessage += sDisplayModeName + "<br>"; } (new Logger()).WriteNotice(sMessage); if (null == _iDLOutputDisplayMode) throw new Exception("can't find " + Preferences.sVideoFormat + " mode within specified device for output"); stArea = new Area(0, 0, (ushort)_iDLOutputDisplayMode.GetWidth(), (ushort)_iDLOutputDisplayMode.GetHeight()); long nFrameDuration, nFrameTimescale; _iDLOutputDisplayMode.GetFrameRate(out nFrameDuration, out nFrameTimescale); _nFPS = (ushort)((nFrameTimescale + (nFrameDuration - 1)) / nFrameDuration); //до ближайшего целого - взято из примера деклинка _bDoWritingFrames = false; _aqWritingFrames = new Queue<byte[]>(); _cThreadWritingFramesWorker = new System.Threading.Thread(WritingFramesWorker); _cThreadWritingFramesWorker.IsBackground = true; _cThreadWritingFramesWorker.Priority = System.Threading.ThreadPriority.Normal; _cThreadWritingFramesWorker.Start(); if (Preferences.bAudio) { switch (Preferences.nAudioBitDepth) { case 32: _eAudioSampleDepth = _BMDAudioSampleType.bmdAudioSampleType32bitInteger; break; case 16: default: _eAudioSampleDepth = _BMDAudioSampleType.bmdAudioSampleType16bitInteger; break; } switch (Preferences.nAudioSamplesRate) { case 48000: _eAudioSampleRate = _BMDAudioSampleRate.bmdAudioSampleRate48kHz; break; default: throw new Exception("unsupported audio sample rate [" + Preferences.nAudioSamplesRate + "]"); } //_pAudioSamplesBuffer = Marshal.AllocCoTaskMem((int)_nAudioFrameSize_InBytes); _cAudioBuffer = new AudioBuffer(); _nAudioBufferCapacity_InSamples = Preferences.nAudioSamplesPerFrame * Preferences.nQueueDeviceLength; //for (int nIndx = 0; _nAudioFrameSize_InBytes > nIndx; nIndx++) // Marshal.WriteByte(_pAudioSamplesBuffer, nIndx, 0); _nTimescale = (ushort)_eAudioSampleRate; _nFrameDuration = (ushort)(_nTimescale / _nFPS); } if (null != Preferences.cDownStreamKeyer) _iDeckLinkKeyer = (IDeckLinkKeyer)_iDLDevice; } } catch (Exception ex) { (new Logger()).WriteError(ex); throw; } (new Logger()).WriteDebug4("return"); }