public void SampleAdvFileRecording5() { fileName = @"C:\hello-world-5.adv"; const uint MILLI_TO_NANO = 1000000; const int WIDTH = 800; const int HEIGHT = 600; var rec = new AdvRecorder(); rec.ImageConfig.SetImageParameters(WIDTH, HEIGHT, 16, 0); rec.FileMetaData.RecorderSoftwareName = "MyVideoRecorder"; rec.FileMetaData.RecorderSoftwareVersion = "x.y.z"; rec.FileMetaData.CameraModel = "TestCamera"; rec.FileMetaData.CameraSensorInfo = "TestSensor"; rec.FileMetaData.GainResponseMode = ResponseMode.Linear; rec.FileMetaData.Telescope = "14\" LX-200 ACF (Tangra Observatory)"; rec.FileMetaData.Observer = "Hristo Pavlov"; rec.FileMetaData.ObjectName = "Chariklo"; rec.FileMetaData.Comment = "Full moon only 20 deg away from the target."; rec.FileMetaData.AddUserTag("Timing Hardware", "IOTA-VTI v3"); rec.StatusSectionConfig.AddDefineTag("ErrorFlag", Adv2TagType.Int8); rec.StatusSectionConfig.AddDefineTag("Temperature", Adv2TagType.Real); rec.StartRecordingNewFile(fileName, 1 * MILLI_TO_NANO /* 1ms */); // TODO: Get the real actual timestamps and exposure DateTime startTime = DateTime.UtcNow; double exposureSeconds = 0.5; for (int i = 0; i < 10; i++) { ushort[] pixels = new ushort[WIDTH * HEIGHT]; var statusEntry = new AdvRecorder.AdvStatusEntry() { // Set actual values. Order and type of values is important. AdditionalStatusTags = new object[] { (byte)1, 15.3f } }; rec.AddVideoFrame( pixels, false, null, AdvTimeStamp.FromDateTime(startTime.AddSeconds(exposureSeconds * i)), AdvTimeStamp.FromDateTime(startTime.AddSeconds(exposureSeconds * (i + 1))), statusEntry, AdvImageData.PixelDepth16Bit); } rec.FinishRecording(); }
public void SampleAdvFileRecording4() { fileName = @"C:\hello-world.adv"; const uint MILLI_TO_NANO = 1000000; const int WIDTH = 800; const int HEIGHT = 600; var recorder = new AdvRecorder(); recorder.ImageConfig.SetImageParameters(WIDTH, HEIGHT, 16, 0); recorder.FileMetaData.RecorderSoftwareName = "MyVideoRecorder"; recorder.FileMetaData.RecorderSoftwareVersion = "x.y.z"; recorder.FileMetaData.CameraModel = "TestCamera"; recorder.FileMetaData.CameraSensorInfo = "TestSensor"; recorder.StatusSectionConfig.RecordGain = true; recorder.StatusSectionConfig.RecordGamma = true; recorder.StartRecordingNewFile(fileName, 1 * MILLI_TO_NANO /* 1ms */); for (int i = 0; i < 10; i++) { ushort[] pixels = new ushort[WIDTH * HEIGHT]; var statusEntry = new AdvRecorder.AdvStatusEntry() { Gain = 38.3f, Gamma = 1 }; recorder.AddVideoFrame( pixels, false, null, AdvTimeStamp.FromDateTime(DateTime.Now), AdvTimeStamp.FromDateTime(DateTime.Now.AddSeconds(0.5 * i)), statusEntry, AdvImageData.PixelDepth16Bit); } recorder.FinishRecording(); }
public void GenerateaAdv_V2(AdvGenerationConfig config, string fileName) { var recorder = new AdvRecorder(); // First set the values of the standard file metadata recorder.FileMetaData.RecorderSoftwareName = "AdvLibRecorder"; recorder.FileMetaData.RecorderSoftwareVersion = "x.y.z"; recorder.FileMetaData.RecorderHardwareName = "a.b.c"; recorder.FileMetaData.CameraModel = "Flea3 FL3-FW-03S3M"; recorder.FileMetaData.CameraSensorInfo = "Sony ICX414AL (1/2\" 648x488 CCD)"; recorder.FileMetaData.ObjectName = "Generated File Object"; recorder.FileMetaData.Telescope = "Generated File Telescope"; recorder.FileMetaData.Observer = "Generated File Observer"; if (config.SaveLocationData) { recorder.LocationData.SetLocation( 150 + 38 / 60.0 + 27.7 / 3600.0, -1 * (33 + 39 / 60.0 + 49.3 / 3600.0), 284.4); } recorder.ImageConfig.SetImageParameters(640, 480, config.DynaBits, config.NormalPixelValue); // By default no status section values will be recorded. The user must enable the ones they need recorded and // can also define additional status parameters to be recorded with each video frame recorder.StatusSectionConfig.RecordGain = true; recorder.StatusSectionConfig.RecordGamma = true; recorder.StatusSectionConfig.RecordSystemErrors = true; if (config.MainStreamCustomClock != null) { recorder.DefineCustomClock(AdvRecorder.AdvStream.MainStream, config.MainStreamCustomClock.ClockFrequency, config.MainStreamCustomClock.TicksTimingAccuracy, config.MainStreamCustomClock.ClockTicksCallback); } if (config.CalibrationStreamCustomClock != null) { recorder.DefineCustomClock(AdvRecorder.AdvStream.CalibrationStream, config.CalibrationStreamCustomClock.ClockFrequency, config.CalibrationStreamCustomClock.TicksTimingAccuracy, config.CalibrationStreamCustomClock.ClockTicksCallback); } if (config.BayerPattern != null) { recorder.ImageConfig.SetBayerPattern(config.BayerPattern.Value); } foreach (string key in config.MainStreamMetadata.Keys) { recorder.FileMetaData.AddMainStreamTag(key, config.MainStreamMetadata[key]); } foreach (string key in config.CalibrationStreamMetadata.Keys) { recorder.FileMetaData.AddCalibrationStreamTag(key, config.CalibrationStreamMetadata[key]); } foreach (string key in config.UserMetadata.Keys) { recorder.FileMetaData.AddUserTag(key, config.UserMetadata[key]); } if (config.SaveCustomStatusSectionTags) { recorder.StatusSectionConfig.AddDefineTag("CustomInt8", Adv2TagType.Int8); recorder.StatusSectionConfig.AddDefineTag("CustomInt16", Adv2TagType.Int16); recorder.StatusSectionConfig.AddDefineTag("CustomInt32", Adv2TagType.Int32); recorder.StatusSectionConfig.AddDefineTag("CustomLong64", Adv2TagType.Long64); recorder.StatusSectionConfig.AddDefineTag("CustomReal", Adv2TagType.Real); recorder.StatusSectionConfig.AddDefineTag("CustomString", Adv2TagType.UTF8String); } recorder.StartRecordingNewFile(fileName, config.UtcTimestampAccuracyInNanoseconds); AdvRecorder.AdvStatusEntry status = new AdvRecorder.AdvStatusEntry(); status.AdditionalStatusTags = new object[2]; for (int i = 0; i < config.NumberOfFrames; i++) { // NOTE: Get the test data uint exposure = config.ExposureCallback != null?config.ExposureCallback(i) : 0; DateTime startTimestamp = config.TimeStampCallback != null?config.TimeStampCallback(i) : DateTime.Now; var utcStart = AdvTimeStamp.FromDateTime(startTimestamp); var utcEnd = utcStart.AddNanoseconds(exposure); status.Gain = config.GainCallback != null?config.GainCallback(i) : 0; status.Gamma = config.GammaCallback != null?config.GammaCallback(i) : 0; status.SystemErrors = config.SystemErrorsCallback != null?config.SystemErrorsCallback(i) : null; if (config.SaveCustomStatusSectionTags) { status.AdditionalStatusTags = new object[] { (byte)12, (short)-123, (int)192847, -1 * (long)(0x6E9104B012CD110F), 91.291823f, "Значение 1" }; } else { status.AdditionalStatusTags = null; } if (config.SourceFormat == AdvSourceDataFormat.Format16BitUShort) { ushort[] imagePixels = imageGenerator.GetCurrentImageBytesInt16(i, config.DynaBits); recorder.AddVideoFrame( imagePixels, // NOTE: Use with caution! Using compression is slower and may not work at high frame rates // i.e. it may take longer to compress the data than for the next image to arrive on the buffer config.Compression != CompressionType.Uncompressed, config.Compression == CompressionType.Lagarith16 ? PreferredCompression.Lagarith16 : PreferredCompression.QuickLZ, utcStart, utcEnd, status, AdvImageData.PixelDepth16Bit); } else if (config.SourceFormat == AdvSourceDataFormat.Format16BitLittleEndianByte) { byte[] imageBytes = imageGenerator.GetCurrentImageBytes(i, config.DynaBits); recorder.AddVideoFrame( imageBytes, // NOTE: Use with caution! Using compression is slower and may not work at high frame rates // i.e. it may take longer to compress the data than for the next image to arrive on the buffer config.Compression != CompressionType.Uncompressed, config.Compression == CompressionType.Lagarith16 ? PreferredCompression.Lagarith16 : PreferredCompression.QuickLZ, utcStart, utcEnd, status, AdvImageData.PixelDepth16Bit); } else if (config.SourceFormat == AdvSourceDataFormat.Format12BitPackedByte) { byte[] imageBytes = imageGenerator.GetCurrentImageBytes(i, config.DynaBits); recorder.AddVideoFrame( imageBytes, // NOTE: Use with caution! Using compression is slower and may not work at high frame rates // i.e. it may take longer to compress the data than for the next image to arrive on the buffer config.Compression != CompressionType.Uncompressed, config.Compression == CompressionType.Lagarith16 ? PreferredCompression.Lagarith16 : PreferredCompression.QuickLZ, utcStart, utcEnd, status, AdvImageData.PixelData12Bit); } else if (config.SourceFormat == AdvSourceDataFormat.Format8BitByte) { byte[] imageBytes = imageGenerator.GetCurrentImageBytes(i, config.DynaBits); recorder.AddVideoFrame( imageBytes, // NOTE: Use with caution! Using compression is slower and may not work at high frame rates // i.e. it may take longer to compress the data than for the next image to arrive on the buffer config.Compression != CompressionType.Uncompressed, config.Compression == CompressionType.Lagarith16 ? PreferredCompression.Lagarith16 : PreferredCompression.QuickLZ, utcStart, utcEnd, status, AdvImageData.PixelDepth8Bit); } else if (config.SourceFormat == AdvSourceDataFormat.Format24BitColour) { throw new NotImplementedException(); } } recorder.FinishRecording(); }
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)); } } }
public void TestStatusTagsAreSavedAndReadCorrectly() { string fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); if (File.Exists(fileName)) { File.Delete(fileName); } try { // Generate var recorder = new AdvRecorder(); recorder.ImageConfig.SetImageParameters(640, 480, 16, 0); recorder.FileMetaData.RecorderSoftwareName = "AdvLibTestRecorder"; recorder.FileMetaData.RecorderSoftwareVersion = "x.y.z"; recorder.FileMetaData.RecorderHardwareName = "a.b.c"; recorder.FileMetaData.CameraModel = "TestCamera"; recorder.FileMetaData.CameraSensorInfo = "TestSensor"; recorder.StatusSectionConfig.RecordGain = true; recorder.StatusSectionConfig.RecordGamma = true; recorder.StatusSectionConfig.RecordShutter = true; recorder.StatusSectionConfig.RecordCameraOffset = true; recorder.StatusSectionConfig.RecordSystemTime = true; recorder.StatusSectionConfig.RecordTrackedSatellites = true; recorder.StatusSectionConfig.RecordAlmanacStatus = true; recorder.StatusSectionConfig.RecordAlmanacOffset = true; recorder.StatusSectionConfig.RecordFixStatus = true; recorder.StatusSectionConfig.RecordSystemErrors = true; recorder.StatusSectionConfig.RecordVideoCameraFrameId = true; recorder.StatusSectionConfig.RecordHardwareTimerFrameId = true; recorder.StatusSectionConfig.AddDefineTag("CustomInt8", Adv2TagType.Int8); recorder.StatusSectionConfig.AddDefineTag("CustomInt16", Adv2TagType.Int16); recorder.StatusSectionConfig.AddDefineTag("CustomInt32", Adv2TagType.Int32); recorder.StatusSectionConfig.AddDefineTag("CustomLong64", Adv2TagType.Long64); recorder.StatusSectionConfig.AddDefineTag("CustomReal", Adv2TagType.Real); recorder.StatusSectionConfig.AddDefineTag("CustomString", Adv2TagType.UTF8String); recorder.StartRecordingNewFile(fileName, 0); var systemTimeStamp = DateTime.Now.AddMilliseconds(123); var status = new AdvRecorder.AdvStatusEntry() { AlmanacStatus = AlmanacStatus.Good, AlmanacOffset = 14, TrackedSatellites = 8, CameraOffset = 8.23f, FixStatus = FixStatus.PFix, Gain = 32.82f, Gamma = 0.35f, Shutter = 2.502f, SystemTime = AdvTimeStamp.FromDateTime(systemTimeStamp), VideoCameraFrameId = 19289232, HardwareTimerFrameId = 9102 }; status.AdditionalStatusTags = new object[] { (byte)12, (short)-123, (int)192847, -1 * (long)(0x6E9104B012CD110F), 91.291823f, "Значение 1" }; var imageGenerator = new ImageGenerator(); ushort[] imagePixels = imageGenerator.GetCurrentImageBytesInt16(0, 16); recorder.AddVideoFrame( imagePixels, false, null, AdvTimeStamp.FromDateTime(DateTime.Now), AdvTimeStamp.FromDateTime(DateTime.Now.AddSeconds(2.56)), status, AdvImageData.PixelDepth16Bit); recorder.FinishRecording(); // Verify using (var loadedFile = new AdvFile2(fileName)) { AdvFrameInfo frameInfo; loadedFile.GetMainFramePixels(0, out frameInfo); Assert.AreEqual(status.Gain, frameInfo.Gain, 0.000001); Assert.AreEqual(status.Gamma, frameInfo.Gamma, 0.000001); Assert.AreEqual(status.Shutter, frameInfo.Shutter, 0.000001); Assert.AreEqual(status.CameraOffset, frameInfo.Offset, 0.000001); Assert.AreEqual(status.FixStatus, (FixStatus)frameInfo.GPSFixStatus); Assert.AreEqual(status.AlmanacStatus, (AlmanacStatus)frameInfo.GPSAlmanacStatus); Assert.AreEqual(status.TrackedSatellites, frameInfo.GPSTrackedSattelites); Assert.AreEqual(status.AlmanacOffset, frameInfo.GPSAlmanacOffset); Assert.AreEqual(status.VideoCameraFrameId, frameInfo.VideoCameraFrameId); Assert.AreEqual(status.HardwareTimerFrameId, frameInfo.HardwareTimerFrameId); Assert.AreEqual(systemTimeStamp.Ticks, frameInfo.SystemTimestamp.Ticks); Assert.AreEqual(status.AdditionalStatusTags[0], frameInfo.Status["CustomInt8"]); Assert.AreEqual(status.AdditionalStatusTags[1], frameInfo.Status["CustomInt16"]); Assert.AreEqual(status.AdditionalStatusTags[2], frameInfo.Status["CustomInt32"]); Assert.AreEqual(status.AdditionalStatusTags[3], frameInfo.Status["CustomLong64"]); Assert.AreEqual(status.AdditionalStatusTags[4], frameInfo.Status["CustomReal"]); Assert.AreEqual(status.AdditionalStatusTags[5], frameInfo.Status["CustomString"]); } } finally { try { if (File.Exists(fileName)) { File.Delete(fileName); } } catch (Exception ex) { Console.WriteLine(ex); Trace.WriteLine(ex); } } }