private void CropAdvFile(string fileName, int firstMainFrame, int lastMainFrame, int firstCalibrationFrame, int lastCalibrationFrame, UpdateUIDelegate progressCallback) { using (var fsr = new FileStream(m_FileName, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fsr)) using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) using (var writer = new BinaryWriter(fs)) { AdvIndexEntry firstEntry; if (m_AdvFile.MainIndex.Count > 0) { firstEntry = m_AdvFile.MainIndex[0]; if (m_AdvFile.CalibrationIndex.Count > 0 && m_AdvFile.CalibrationIndex[0].FrameOffset < firstEntry.FrameOffset) { firstEntry = m_AdvFile.CalibrationIndex[0]; } } else { firstEntry = m_AdvFile.CalibrationIndex[0]; } CopyRawBytes(reader, 0, firstEntry.FrameOffset, writer); progressCallback(5, 0, true); int MainStreamProgressScale = 5 + 85 * (lastMainFrame - firstMainFrame) / (lastMainFrame - firstMainFrame + lastCalibrationFrame - firstCalibrationFrame); int CalibrationStreamProgressScale = 5 + 85 * (lastCalibrationFrame - firstCalibrationFrame) / (lastMainFrame - firstMainFrame + lastCalibrationFrame - firstCalibrationFrame); var newMainIndex = new List <AdvIndexEntry>(); var newCalibrationIndex = new List <AdvIndexEntry>(); #region Copy Main Frames if (lastMainFrame > firstMainFrame) { AdvIndexEntry firstEntryToCopy = m_AdvFile.MainIndex[firstMainFrame]; long zeroTicks = firstEntryToCopy.ElapsedTicks; for (int i = firstMainFrame; i <= lastMainFrame; i++) { AdvIndexEntry frameToCopy = m_AdvFile.MainIndex[i]; var copiedFrame = new AdvIndexEntry() { FrameOffset = writer.BaseStream.Position, BytesCount = frameToCopy.BytesCount }; CopyRawBytes(reader, frameToCopy.FrameOffset, frameToCopy.BytesCount + FRAME_MAGIC_LENGTH, writer); copiedFrame.ElapsedTicks = frameToCopy.ElapsedTicks - zeroTicks; newMainIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, MainStreamProgressScale * (i - firstMainFrame) * 1.0 / (lastMainFrame - firstMainFrame + 1)); progressCallback(5 + percDone, 0, true); } } #endregion #region Copy Calibration Frames if (lastCalibrationFrame > firstCalibrationFrame) { AdvIndexEntry firstEntryToCopy = m_AdvFile.CalibrationIndex[firstCalibrationFrame]; long zeroTicks = firstEntryToCopy.ElapsedTicks; for (int i = firstCalibrationFrame; i <= lastCalibrationFrame; i++) { AdvIndexEntry frameToCopy = m_AdvFile.CalibrationIndex[i]; var copiedFrame = new AdvIndexEntry() { FrameOffset = writer.BaseStream.Position, BytesCount = frameToCopy.BytesCount }; CopyRawBytes(reader, frameToCopy.FrameOffset, frameToCopy.BytesCount + FRAME_MAGIC_LENGTH, writer); copiedFrame.ElapsedTicks = frameToCopy.ElapsedTicks - zeroTicks; newCalibrationIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, CalibrationStreamProgressScale * (i - firstCalibrationFrame) * 1.0 / (lastCalibrationFrame - firstCalibrationFrame + 1)); progressCallback(5 + percDone, 0, true); } } #endregion long indexTableOffset = writer.BaseStream.Position; progressCallback(95, 0, true); // Save the new INDEX writer.Write((byte)2 /*Index Table Format Version*/); writer.Write((int)9 /* Start Offset*/); writer.Write((int)((newMainIndex.Count + newCalibrationIndex.Count) * 20 + 10) /*Table Size */); writer.Write((uint)newMainIndex.Count); foreach (AdvIndexEntry newIndexEntry in newMainIndex) { writer.Write((long)newIndexEntry.ElapsedTicks); writer.Write((long)newIndexEntry.FrameOffset); writer.Write((int)newIndexEntry.BytesCount); } writer.Write((uint)newCalibrationIndex.Count); foreach (AdvIndexEntry newIndexEntry in newCalibrationIndex) { writer.Write((long)newIndexEntry.ElapsedTicks); writer.Write((long)newIndexEntry.FrameOffset); writer.Write((int)newIndexEntry.BytesCount); } long userMetadataTablePosition = writer.BaseStream.Position; // Read userMetadataTableOffset from source reader.BaseStream.Seek(25, SeekOrigin.Begin); long userMetadataTableOffset = reader.ReadInt64(); if (fsr.Length > userMetadataTableOffset) { CopyRawBytes(reader, userMetadataTableOffset, fsr.Length - userMetadataTableOffset, writer); } // Update new Main Frames Count writer.BaseStream.Seek(40, SeekOrigin.Begin); writer.Write((uint)newMainIndex.Count); // Update new Calibration Frames Count writer.BaseStream.Seek(77, SeekOrigin.Begin); writer.Write((uint)newCalibrationIndex.Count); // Update new index table position writer.BaseStream.Seek(9, SeekOrigin.Begin); writer.Write(indexTableOffset); // Update new userMetadataTable position writer.BaseStream.Seek(25, SeekOrigin.Begin); writer.Write(userMetadataTablePosition); writer.BaseStream.Flush(); progressCallback(100, 0, true); } }
internal bool SaveAsAviFile(string fileName, int firstFrame, int lastFrame, AdvToAviConverter converter, bool tryCodec, bool isCalibrationStream, double msPerFrame, double addedGamma, OnProgressDelegate progressCallback) { IAviSaver saver = AdvToAviConverterFactory.CreateConverter(converter); saver.CloseAviFile(); if (!saver.StartNewAviFile(fileName, (int)m_AdvFile.Width, (int)m_AdvFile.Height, 8, 25, tryCodec)) { progressCallback(100, 0); return(false); } try { int aviFrameNo = 0; AdvIndexEntry firstFrameIdx = isCalibrationStream ? m_AdvFile.CalibrationIndex[firstFrame] : m_AdvFile.MainIndex[firstFrame]; double ticksToMSFactor = 1000.0 / (isCalibrationStream ? m_AdvFile.CalibrationSteamInfo.ClockFrequency : m_AdvFile.MainSteamInfo.ClockFrequency); double startingTimeMilliseconds = firstFrameIdx.ElapsedTicks * ticksToMSFactor; if (m_AdvFile.MainIndex[lastFrame].ElapsedTicks != 0) { // Sampling can be done as we have sufficient timing information } else { InvokeMessageBox( "There is insufficient timing information in this file to convert it to AVI. This could be caused by an old file format or trying to make an AVI from a single frame.", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } if (InvokeMessageBox( "Please note that the AVI export is doing resampling of the original video which will typically cause frames to duplicated and/or dropped.\r\n\r\nThis export function is meant to be used for video streaming (i.e. sharing the video for viewing on the Internet) and should not be used to convert the video to another format for measuring in another software. If you want to measure the video in another software either measure it directly as ADV/AAV file (if supported) or export it to a FITS file sequence from the main file menu and measure the FITS images.\r\n\r\nDo you wish to continue?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) { return(false); } progressCallback(5, 0); for (int i = firstFrame; i <= lastFrame; i++) { AdvIndexEntry frame = isCalibrationStream ? m_AdvFile.CalibrationIndex[i] : m_AdvFile.MainIndex[i]; AdvFrameInfo frameInfo = null; uint[] pixels = null; if (isCalibrationStream) { pixels = m_AdvFile.GetCalibrationFramePixels((uint)i, out frameInfo); } else { pixels = m_AdvFile.GetMainFramePixels((uint)i, out frameInfo); } using (Pixelmap pixmap = CreatePixelmap(pixels)) { int lastRepeatedAviFrameNo = 0; if (frame.ElapsedTicks != 0) { lastRepeatedAviFrameNo = (int)Math.Round((frame.ElapsedTicks * ticksToMSFactor - startingTimeMilliseconds) / msPerFrame); } while (aviFrameNo < lastRepeatedAviFrameNo) { if (!saver.AddAviVideoFrame(pixmap, addedGamma, m_AdvFile.MaxPixelValue)) { progressCallback(100, 0); return(false); } aviFrameNo++; } } int percDone = (int)Math.Min(90, 90 * (i - firstFrame) * 1.0 / (lastFrame - firstFrame + 1)); progressCallback(5 + percDone, 0); } } finally { saver.CloseAviFile(); progressCallback(100, 0); } return(false); }
private void CropAdvFile(string fileName, int firstMainFrame, int lastMainFrame, int firstCalibrationFrame, int lastCalibrationFrame, UpdateUIDelegate progressCallback) { using (var fsr = new FileStream(m_FileName, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(fsr)) using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) using (var writer = new BinaryWriter(fs)) { AdvIndexEntry firstEntry; if (m_AdvFile.MainIndex.Count > 0) { firstEntry = m_AdvFile.MainIndex[0]; if (m_AdvFile.CalibrationIndex.Count > 0 && m_AdvFile.CalibrationIndex[0].FrameOffset < firstEntry.FrameOffset) firstEntry = m_AdvFile.CalibrationIndex[0]; } else firstEntry = m_AdvFile.CalibrationIndex[0]; CopyRawBytes(reader, 0, firstEntry.FrameOffset, writer); progressCallback(5, 0, true); int MainStreamProgressScale = 5 + 85 * (lastMainFrame - firstMainFrame) / (lastMainFrame - firstMainFrame + lastCalibrationFrame - firstCalibrationFrame); int CalibrationStreamProgressScale = 5 + 85 * (lastCalibrationFrame - firstCalibrationFrame) / (lastMainFrame - firstMainFrame + lastCalibrationFrame - firstCalibrationFrame); var newMainIndex = new List<AdvIndexEntry>(); var newCalibrationIndex = new List<AdvIndexEntry>(); #region Copy Main Frames if (lastMainFrame > firstMainFrame) { AdvIndexEntry firstEntryToCopy = m_AdvFile.MainIndex[firstMainFrame]; long zeroTicks = firstEntryToCopy.ElapsedTicks; for (int i = firstMainFrame; i <= lastMainFrame; i++) { AdvIndexEntry frameToCopy = m_AdvFile.MainIndex[i]; var copiedFrame = new AdvIndexEntry() { FrameOffset = writer.BaseStream.Position, BytesCount = frameToCopy.BytesCount }; CopyRawBytes(reader, frameToCopy.FrameOffset, frameToCopy.BytesCount + FRAME_MAGIC_LENGTH, writer); copiedFrame.ElapsedTicks = frameToCopy.ElapsedTicks - zeroTicks; newMainIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, MainStreamProgressScale * (i - firstMainFrame) * 1.0 / (lastMainFrame - firstMainFrame + 1)); progressCallback(5 + percDone, 0, true); } } #endregion #region Copy Calibration Frames if (lastCalibrationFrame > firstCalibrationFrame) { AdvIndexEntry firstEntryToCopy = m_AdvFile.CalibrationIndex[firstCalibrationFrame]; long zeroTicks = firstEntryToCopy.ElapsedTicks; for (int i = firstCalibrationFrame; i <= lastCalibrationFrame; i++) { AdvIndexEntry frameToCopy = m_AdvFile.CalibrationIndex[i]; var copiedFrame = new AdvIndexEntry() { FrameOffset = writer.BaseStream.Position, BytesCount = frameToCopy.BytesCount }; CopyRawBytes(reader, frameToCopy.FrameOffset, frameToCopy.BytesCount + FRAME_MAGIC_LENGTH, writer); copiedFrame.ElapsedTicks = frameToCopy.ElapsedTicks - zeroTicks; newCalibrationIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, CalibrationStreamProgressScale * (i - firstCalibrationFrame) * 1.0 / (lastCalibrationFrame - firstCalibrationFrame + 1)); progressCallback(5 + percDone, 0, true); } } #endregion long indexTableOffset = writer.BaseStream.Position; progressCallback(95, 0, true); // Save the new INDEX writer.Write((byte)2 /*Index Table Format Version*/); writer.Write((int)9 /* Start Offset*/); writer.Write((int)((newMainIndex.Count + newCalibrationIndex.Count) * 20 + 10) /*Table Size */); writer.Write((uint)newMainIndex.Count); foreach (AdvIndexEntry newIndexEntry in newMainIndex) { writer.Write((long)newIndexEntry.ElapsedTicks); writer.Write((long)newIndexEntry.FrameOffset); writer.Write((int)newIndexEntry.BytesCount); } writer.Write((uint)newCalibrationIndex.Count); foreach (AdvIndexEntry newIndexEntry in newCalibrationIndex) { writer.Write((long)newIndexEntry.ElapsedTicks); writer.Write((long)newIndexEntry.FrameOffset); writer.Write((int)newIndexEntry.BytesCount); } long userMetadataTablePosition = writer.BaseStream.Position; // Read userMetadataTableOffset from source reader.BaseStream.Seek(25, SeekOrigin.Begin); long userMetadataTableOffset = reader.ReadInt64(); if (fsr.Length > userMetadataTableOffset) { CopyRawBytes(reader, userMetadataTableOffset, fsr.Length - userMetadataTableOffset, writer); } // Update new Main Frames Count writer.BaseStream.Seek(40, SeekOrigin.Begin); writer.Write((uint)newMainIndex.Count); // Update new Calibration Frames Count writer.BaseStream.Seek(77, SeekOrigin.Begin); writer.Write((uint)newCalibrationIndex.Count); // Update new index table position writer.BaseStream.Seek(9, SeekOrigin.Begin); writer.Write(indexTableOffset); // Update new userMetadataTable position writer.BaseStream.Seek(25, SeekOrigin.Begin); writer.Write(userMetadataTablePosition); writer.BaseStream.Flush(); progressCallback(100, 0, true); } }