public VideoFrame(byte[] pixelBytes, int width, int height, int bpp, int frameNo, bool variant, double ccdTemp) { m_FrameNo = frameNo; m_Header = new ImageHeader(m_FrameNo, pixelBytes, bpp); if (variant) { pixelsVariant = new object[height, width]; pixels = null; } else { pixels = new int[height, width]; pixelsVariant = null; } m_PreviewBitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb); ImageUtils.ProduceBitmap(pixelBytes, width, height, bpp, m_PreviewBitmap); if (m_Header.Latitude != 0 && m_Header.Longitude != 0) { Longitude = m_Header.ParseLongitude; Latitude = m_Header.ParseLatitude; ImageInfo = string.Format("LAT:{0};LONG:{1};", AstroConvert.ToStringValue(Latitude, "+DD°MM'SS.T\""), AstroConvert.ToStringValue(Longitude, "+DD°MM'SS.T\"")); } else { Longitude = double.NaN; Latitude = double.NaN; } ImageInfo += string.Format("GPS:{0};CLKFRQ:{1};CCDTMP:{2}", m_Header.GPSStatus, m_Header.MaxClock, ccdTemp.ToString("0.0", CultureInfo.InvariantCulture)); if (m_LoggedFrameNo != frameNo) { int currExpMS = (int) Math.Round((m_Header.EndTime - m_Header.StartTime).TotalMilliseconds); int msDiff = Math.Abs(m_LastExpMS - currExpMS); int msGap = (int)Math.Round((m_Header.StartTime - m_LastEndTime).TotalMilliseconds); string flags = msDiff > 5 ? ";LARGE-DIFF" : ""; if (msGap > 5) flags += ";LARGE-GAP"; Trace.WriteLine(string.Format("QHY {0} |{1}| GPSFlag:{2};MaxClock:{3};EXPD:{4}ms;GAP:{5}{6}", m_Header.StartTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), string.Join(" ", pixelBytes.Take(44).Select(x => Convert.ToString(x, 16).PadLeft(2, '0'))), m_Header.GPSStatus, m_Header.MaxClock, msDiff, msGap, flags)); m_LoggedFrameNo = frameNo; m_LastExpMS = currExpMS; m_LastEndTime = m_Header.EndTime; } }
private void VideoGrabberWorker(object state) { int w = 0; int h = 0; int bpp = 0; int channels = 0; byte[] imageBytes = new byte[m_ImageSize]; m_CurrentBytes = new byte[m_ImageSize]; for (int i = 0; i < m_ImageSize; i++) { imageBytes[i] = 0x66; } m_FrameNo = 0; int rv; var stopwatch = new Stopwatch(); m_GPSLongitude = double.NaN; m_GPSLatitude = double.NaN; m_CCDTemp = double.NaN; if (m_UseCooling) stopwatch.Start(); while (m_Connected) { try { rv = QHYPInvoke.GetQHYCCDLiveFrame(m_Handle, ref w, ref h, ref bpp, ref channels, imageBytes); if (rv >= 0) { m_FrameNo++; var header = new ImageHeader(m_FrameNo, imageBytes, bpp); if (m_CameraState == VideoCameraState.videoCameraRecording) { lock (m_SyncLock) { if (m_Recorder == null) { m_Recorder = new AdvRecorder(); Version occuRecVersion = Assembly.GetExecutingAssembly().GetName().Version; bool isBeta = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(BetaReleaseAttribute), false).Length == 1; // Start Recording m_Recorder.FileMetaData.RecorderSoftwareName = "OccuRec"; m_Recorder.FileMetaData.RecorderSoftwareVersion = string.Format("{0}.{1}{2}", occuRecVersion.Major, occuRecVersion.Minor, isBeta ? " BETA" : ""); m_Recorder.FileMetaData.CameraModel = m_CameraModel; m_Recorder.FileMetaData.CameraSensorInfo = m_CameraModel; if (!double.IsNaN(m_GPSLongitude) && !double.IsNaN(m_GPSLatitude)) m_Recorder.LocationData.SetLocation(m_GPSLongitude, m_GPSLatitude, double.NaN, "ALTITUDE-UNAVAILABLE"); m_Recorder.StatusSectionConfig.RecordGain = true; m_Recorder.StatusSectionConfig.RecordGamma = true; m_Recorder.StatusSectionConfig.RecordSystemTime = true; m_Recorder.StatusSectionConfig.RecordFixStatus = true; m_Recorder.StatusSectionConfig.RecordVideoCameraFrameId = true; m_TimeStampFlagTagId = m_Recorder.StatusSectionConfig.AddDefineTag("TimeStampFlag", Adv2TagType.Int8); m_EstimatedTimeStampErrorMillisecondsTagId = m_Recorder.StatusSectionConfig.AddDefineTag("EstimatedTimeStampErrorMilliseconds", Adv2TagType.Real); if (m_UseCooling) m_CCDTempTagId = m_Recorder.StatusSectionConfig.AddDefineTag("CCDTemperature", Adv2TagType.Real); m_Recorder.ImageConfig.SetImageParameters((ushort)m_Width, (ushort)m_Height, (byte)m_Bpp, null); m_Recorder.StartRecordingNewFile(m_PreferredFileName, 1000000, true); m_PrevVoxFreqIsGood = false; } var statusChannel = new AdvRecorder.AdvStatusEntry() { Gain = m_CurrentGain, Gamma = (float)m_CurrentGamma, VideoCameraFrameId = header.SeqNumber, SystemTime = AdvTimeStamp.FromDateTime(DateTime.Now) }; if (m_UseCooling) statusChannel.AdditionalStatusTags = new object[] { (byte)0, 0, (float)m_CCDTemp }; else statusChannel.AdditionalStatusTags = new object[] { (byte)0, 0 }; if (header.GpsTimeAvailable) { if (header.Latitude != 0 && header.Longitude != 0) statusChannel.FixStatus = FixStatus.GFix; else statusChannel.FixStatus = FixStatus.PFix; } else statusChannel.FixStatus = FixStatus.NoFix; if (header.MaxClock == 10000500 && m_PrevVoxFreqIsGood) { // NOTE: Add Potentially Bad GPS Timestamp Flag statusChannel.AdditionalStatusTags[0] = (byte)1; } else { // NOTE: Add GPS Timestamp Bias Estimate double biasMSPerSec = (header.MaxClock - 10000000) * 0.5 / 1000.0; double biasMS = biasMSPerSec * (header.EndTime - header.StartTime).TotalSeconds; statusChannel.AdditionalStatusTags[1] = (float)biasMS; } m_PrevVoxFreqIsGood = header.MaxClock != 10000500; /* TODO [2548] System.InvalidCastException : Specified cast is not valid. [2548] at Adv.AdvRecorder.BeginVideoFrame(AdvStream advStream, Nullable`1 startClockTicks, Nullable`1 endClockTicks, AdvTimeStamp startUtcTimeStamp, AdvTimeStamp endUtcTimeStamp, AdvStatusEntry metadata) [2548] at Adv.AdvRecorder.AddFrame(AdvStream advStream, Byte[] pixels, Boolean compressIfPossible, Nullable`1 preferredCompression, Nullable`1 startClockTicks, Nullable`1 endClockTicks, AdvTimeStamp startUtcTimeStamp, AdvTimeStamp endUtcTimeStamp, AdvStatusEntry metadata, AdvImageData imageData) [2548] at Adv.AdvRecorder.AddVideoFrame(Byte[] pixels, Boolean compressIfPossible, Nullable`1 preferredCompression, AdvTimeStamp startUtcTimeStamp, AdvTimeStamp endUtcTimeStamp, AdvStatusEntry metadata, AdvImageData imageData) [2548] at OccuRec.Drivers.QHYVideo.Video.VideoGrabberWorker(Object state) in f:\WORK\OccuRec\OccuRec\Drivers\QHYVideo\Video.cs:line 714 [2548] -------------------------------------------------------------------------------------------------- */ m_Recorder.AddVideoFrame( imageBytes, true, PreferredCompression.Lagarith16, AdvTimeStamp.FromDateTime(header.StartTime), AdvTimeStamp.FromDateTime(header.EndTime), statusChannel, bpp == 8 ? AdvImageData.PixelDepth8Bit : AdvImageData.PixelDepth16Bit); } } lock (m_SyncLock) { Array.Copy(imageBytes, 0, m_CurrentBytes, 0, m_ImageSize); } if (m_ChangeGaintTo.HasValue) { rv = QHYPInvoke.SetQHYCCDParam(m_Handle, CONTROL_ID.CONTROL_GAIN, m_ChangeGaintTo.Value); if (QHYPInvoke.SUCCEEDED(rv)) { m_CurrentGain = m_ChangeGaintTo.Value; m_ChangeGaintTo = null; } } if (m_ChangeGammaTo.HasValue) { double gamma = m_SupportedGammaValues[m_ChangeGammaTo.Value]; rv = QHYPInvoke.SetQHYCCDParam(m_Handle, CONTROL_ID.CONTROL_GAMMA, gamma); if (QHYPInvoke.SUCCEEDED(rv)) { m_CurrentGamma = gamma; m_CurrentGammaIndex = m_ChangeGammaTo.Value; m_ChangeGammaTo = null; } } if (m_ChangeExposureIndexTo.HasValue) { rv = QHYPInvoke.SetQHYCCDParam(m_Handle, CONTROL_ID.CONTROL_EXPOSURE, m_SupportedExposureMilliseconds[m_ChangeExposureIndexTo.Value] * 1000); if (QHYPInvoke.SUCCEEDED(rv)) { m_CurrentExposureIndex = m_ChangeExposureIndexTo.Value; m_ChangeExposureIndexTo = null; } } var val = m_VOXFreqFitter.GetNextValue((uint)header.MaxClock); if (val.HasValue) QHYPInvoke.SetQHYCCDGPSVCOXFreq(m_Handle, val.Value); } if (m_UseCooling && stopwatch.ElapsedMilliseconds > 1000) { m_CCDTemp = QHYPInvoke.GetQHYCCDParam(m_Handle, CONTROL_ID.CONTROL_CURTEMP); rv = QHYPInvoke.ControlQHYCCDTemp(m_Handle, -50); if (!QHYPInvoke.SUCCEEDED(rv)) { Trace.WriteLine("QHYPInvoke.ControlQHYCCDTemp() Failed!"); } stopwatch.Reset(); stopwatch.Start(); } Thread.Sleep(0); } catch (Exception ex) { Trace.WriteLine(Extensions.GetFullStackTrace(ex)); } } }