internal void SaveRecoveredFileAs(string newFileName) { string oldFile = Path.GetFullPath(m_FileName); string newFile = Path.GetFullPath(newFileName); if (string.Compare(oldFile, newFile, StringComparison.InvariantCultureIgnoreCase) != 0) { File.Copy(oldFile, newFile, true); } using (FileStream fs = new FileStream(newFile, FileMode.Open, FileAccess.Write)) using (BinaryWriter writer = new BinaryWriter(fs)) { uint numFrames = m_Index.NumberOfFrames; long indexTablePosition = fs.Length; fs.Seek(0, SeekOrigin.End); writer.Write(numFrames); for (int i = 0; i < numFrames; i++) { AdvFramesIndexEntry entry = m_Index.Index[i]; uint elapsedMiliseconds = (uint)entry.ElapsedTime.TotalMilliseconds; long offset = entry.Offset; uint length = entry.Length; writer.Write(elapsedMiliseconds); writer.Write(offset); writer.Write(length); } long userMetadataTablePosition = fs.Position; uint numUserEntries = 0; writer.Write(numUserEntries); fs.Seek(5, SeekOrigin.Begin); writer.Write(numFrames); writer.Write(indexTablePosition); fs.Seek(8, SeekOrigin.Current); writer.Write(userMetadataTablePosition); fs.Flush(); } }
public void GetFrameImageSectionHeader(int frameNo, out byte layoutId, out AdvImageLayout.GetByteMode byteMode) { AdvFramesIndexEntry idxEntry = m_Index.Index[frameNo]; m_InputFile.Seek(idxEntry.Offset, SeekOrigin.Begin); uint frameDataMagic = m_FileReader.ReadUInt32(); Trace.Assert(frameDataMagic == 0xEE0122FF); // 8 bytes timestamp + 4 bytes exposure + 4 bytes image section length m_InputFile.Seek(16, SeekOrigin.Current); layoutId = m_FileReader.ReadByte(); byteMode = (AdvImageLayout.GetByteMode)m_FileReader.ReadByte(); }
public object[] GetFrameSectionData(int frameNo, ushort[,] prevFrame) { AdvFramesIndexEntry idxEntry = m_Index.Index[frameNo]; m_InputFile.Seek(idxEntry.Offset, SeekOrigin.Begin); uint frameDataMagic = m_FileReader.ReadUInt32(); Trace.Assert(frameDataMagic == 0xEE0122FF); byte[] data = m_FileReader.ReadBytes((int)idxEntry.Length); // Read the timestamp and exposure long frameTimeMsSince2010 = (long)data[0] + (((long)data[1]) << 8) + (((long)data[2]) << 16) + (((long)data[3]) << 24) + (((long)data[4]) << 32) + (((long)data[5]) << 40) + (((long)data[6]) << 48) + (((long)data[7]) << 56); int exposure = data[8] + (data[9] << 8) + (data[10] << 16) + (data[11] << 24); var sectionObjects = new List <object>(); int dataOffset = 12; foreach (IAdvDataSection section in m_Sections) { int sectionDataLength = data[dataOffset] + (data[dataOffset + 1] << 8) + (data[dataOffset + 2] << 16) + (data[dataOffset + 3] << 24); object sectionObject = section.GetDataFromDataBytes(data, prevFrame, sectionDataLength, dataOffset + 4); sectionObjects.Add(sectionObject); dataOffset += sectionDataLength + 4; } // ADV Format Specification v1.5 (and later), the time stamp is the MIDDLE of the exposure (this changed from spec v1.4 where it was the START) of the exposure try { ((AdvImageData)sectionObjects[0]).MidExposureUtc = ADV_ZERO_DATE_REF.AddMilliseconds(frameTimeMsSince2010); } catch (ArgumentOutOfRangeException) { ((AdvImageData)sectionObjects[0]).MidExposureUtc = ADV_ZERO_DATE_REF; } ((AdvImageData)sectionObjects[0]).ExposureMilliseconds = (float)(exposure / 10.0); return(sectionObjects.ToArray()); }
internal bool CropAdvFile(string fileName, int firstFrame, int lastFrame, OnSearchProgressDelegate 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)) { AdvFramesIndexEntry firstEntry = m_Index.Index[0]; CopyRawBytes(reader, 0, firstEntry.Offset, writer); progressCallback(5, 0); AdvFramesIndexEntry firstEntryToCopy = m_Index.Index[firstFrame]; long zeroTicks = firstEntryToCopy.ElapsedTime.Ticks; var newIndex = new List<AdvFramesIndexEntry>(); for (int i = firstFrame; i <= lastFrame; i++) { AdvFramesIndexEntry frameToCopy = m_Index.Index[i]; var copiedFrame = new AdvFramesIndexEntry() { Offset = writer.BaseStream.Position, Length = frameToCopy.Length }; long nextFrameStartPos = i == m_Index.NumberOfFrames - 1 ? m_Index.TableOffset : m_Index.Index[i + 1].Offset; CopyRawBytes(reader, frameToCopy.Offset, nextFrameStartPos - frameToCopy.Offset, writer); copiedFrame.ElapsedTime = new TimeSpan(frameToCopy.ElapsedTime.Ticks - zeroTicks); newIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, 90 * (i - firstFrame) * 1.0 / (lastFrame - firstFrame + 1)); progressCallback(5 + percDone, 0); } long indexTableOffset = writer.BaseStream.Position; progressCallback(95, 0); writer.Write((uint)newIndex.Count); // Save the new INDEX foreach (AdvFramesIndexEntry newIndexEntry in newIndex) { writer.Write((uint)Math.Round(newIndexEntry.ElapsedTime.TotalMilliseconds)); writer.Write((long)newIndexEntry.Offset); writer.Write((uint)newIndexEntry.Length); } long userMetadataTablePosition = writer.BaseStream.Position; if (fsr.Length > m_UserMetadataTableOffset) { CopyRawBytes(reader, m_UserMetadataTableOffset, fsr.Length - m_UserMetadataTableOffset, writer); } writer.BaseStream.Seek(5, SeekOrigin.Begin); writer.Write((uint)newIndex.Count); writer.Write(indexTableOffset); writer.BaseStream.Seek(8, SeekOrigin.Current); writer.Write(userMetadataTablePosition); writer.BaseStream.Flush(); progressCallback(100, 0); } return false; }
internal bool FixAavFile18Aug(string fileName, int firstFrame, int lastFrame) { fileName = m_FileName; string newFile = Path.ChangeExtension(fileName, ".new.aav"); File.Copy(fileName, newFile, true); using (FileStream fsr = new FileStream(fileName, FileMode.Open, FileAccess.Read)) using (BinaryReader reader = new BinaryReader(fsr)) using (FileStream fs = new FileStream(newFile, FileMode.Open, FileAccess.Write)) using (BinaryWriter writer = new BinaryWriter(fs)) { uint numFrames = m_Index.NumberOfFrames; long ZEROTICKS = (new DateTime(2013, 8, 18).Ticks - ADV_ZERO_DATE_REF.Ticks) / 10000; for (int i = 0; i < numFrames; i++) { AdvFramesIndexEntry entry = m_Index.Index[i]; uint elapsedMiliseconds = (uint)entry.ElapsedTime.TotalMilliseconds; long offset = entry.Offset; uint length = entry.Length; object[] data = GetFrameSectionData(i, null); AdvImageData imageData = (AdvImageData)data[0]; AdvStatusData statusData = (AdvStatusData)data[1]; AdvTagDefinition startTS = StatusSection.TagDefinitions[3]; AdvTagDefinition endTS = StatusSection.TagDefinitions[4]; AdvTagDefinition gpsFix = StatusSection.TagDefinitions[7]; string startTSString = statusData.TagValues[startTS]; string endTSString = statusData.TagValues[endTS]; string gpsFixString = statusData.TagValues[gpsFix]; long ticksStart = FixOSD(ref startTSString, true); long ticksEnd = FixOSD(ref endTSString, false); long midTicks = ZEROTICKS + (ticksStart - 20 * 10000 + ticksEnd) / 20000; long exposureMs10 = new TimeSpan(ticksEnd - ticksStart + 20 * 10000).Milliseconds * 10; fsr.Seek(12 + (4 + entry.Offset), SeekOrigin.Begin); int bytesToSkip = reader.ReadInt32(); WriteInt16((short)exposureMs10, 8 + (4 + entry.Offset), writer, reader); WriteInt64(midTicks, (4 + entry.Offset), writer, reader); WriteString(startTSString, 16 + (4 + entry.Offset) + bytesToSkip + 0x22, writer, reader); WriteString(endTSString, 16 + (4 + entry.Offset) + bytesToSkip + 0x43, writer, reader); int gspFixByte = int.Parse(gpsFixString); if (gspFixByte >= 1) { gspFixByte++; } WriteInt8((byte)gspFixByte, 16 + (4 + entry.Offset) + bytesToSkip + 0x1f, writer, reader); //writer.Write(elapsedMiliseconds); //writer.Write(offset); //writer.Write(length); } fs.Flush(); } return(false); }
internal bool CropAdvFile(string fileName, int firstFrame, int lastFrame, OnSearchProgressDelegate 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)) { AdvFramesIndexEntry firstEntry = m_Index.Index[0]; CopyRawBytes(reader, 0, firstEntry.Offset, writer); progressCallback(5, 0); AdvFramesIndexEntry firstEntryToCopy = m_Index.Index[firstFrame]; long zeroTicks = firstEntryToCopy.ElapsedTime.Ticks; var newIndex = new List <AdvFramesIndexEntry>(); for (int i = firstFrame; i <= lastFrame; i++) { AdvFramesIndexEntry frameToCopy = m_Index.Index[i]; var copiedFrame = new AdvFramesIndexEntry() { Offset = writer.BaseStream.Position, Length = frameToCopy.Length }; long nextFrameStartPos = i == m_Index.NumberOfFrames - 1 ? m_Index.TableOffset : m_Index.Index[i + 1].Offset; CopyRawBytes(reader, frameToCopy.Offset, nextFrameStartPos - frameToCopy.Offset, writer); copiedFrame.ElapsedTime = new TimeSpan(frameToCopy.ElapsedTime.Ticks - zeroTicks); newIndex.Add(copiedFrame); int percDone = (int)Math.Min(90, 90 * (i - firstFrame) * 1.0 / (lastFrame - firstFrame + 1)); progressCallback(5 + percDone, 0); } long indexTableOffset = writer.BaseStream.Position; progressCallback(95, 0); writer.Write((uint)newIndex.Count); // Save the new INDEX foreach (AdvFramesIndexEntry newIndexEntry in newIndex) { writer.Write((uint)Math.Round(newIndexEntry.ElapsedTime.TotalMilliseconds)); writer.Write((long)newIndexEntry.Offset); writer.Write((uint)newIndexEntry.Length); } long userMetadataTablePosition = writer.BaseStream.Position; if (fsr.Length > m_UserMetadataTableOffset) { CopyRawBytes(reader, m_UserMetadataTableOffset, fsr.Length - m_UserMetadataTableOffset, writer); } writer.BaseStream.Seek(5, SeekOrigin.Begin); writer.Write((uint)newIndex.Count); writer.Write(indexTableOffset); writer.BaseStream.Seek(8, SeekOrigin.Current); writer.Write(userMetadataTablePosition); writer.BaseStream.Flush(); progressCallback(100, 0); } return(false); }
internal bool SaveAsAviFile(string fileName, int firstFrame, int lastFrame, AdvToAviConverter converter, bool tryCodec, double msPerFrame, double addedGamma, OnSearchProgressDelegate progressCallback) { IAviSaver saver = AdvToAviConverterFactory.CreateConverter(converter); saver.CloseAviFile(); if (!saver.StartNewAviFile(fileName, (int)ImageSection.Width, (int)ImageSection.Height, 8, 25, tryCodec)) { progressCallback(100, 0); return(false); } try { int aviFrameNo = 0; AdvFramesIndexEntry firstFrameIdx = m_Index.Index[firstFrame]; double startingTimeMilliseconds = firstFrameIdx.ElapsedTime.TotalMilliseconds; bool isAavFile = AdvFileTags["FSTF-TYPE"] == "AAV"; double effFrameDuration = double.NaN; try { effFrameDuration = 1000 / double.Parse(AdvFileTags["EFFECTIVE-FRAME-RATE"]); } catch { } if (isAavFile && m_Index.Index[lastFrame].ElapsedTime.Ticks == 0 && (double.IsNaN(effFrameDuration) || double.IsInfinity(effFrameDuration))) { MessageBox.Show( "This AAV video format is too old or the AAV file is corrupted. It cannot be converted to AVI", "Tangra 3", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } if ((isAavFile && !double.IsNaN(effFrameDuration)) || !isAavFile && m_Index.Index[lastFrame].ElapsedTime.Ticks != 0) { // Sampling can be done as we have sufficient timing information } else { MessageBox.Show( "There is insufficient timing information in this file to convert it to AVI. This could be caused by an old file format.", "Tangra 3", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } progressCallback(5, 0); for (int i = firstFrame; i <= lastFrame; i++) { AdvFramesIndexEntry frame = m_Index.Index[i]; AdvImageData currentImageData; AdvStatusData currentStatusData; Bitmap currentBitmap; using (Pixelmap pixmap = GetFrameData(i, out currentImageData, out currentStatusData, out currentBitmap)) { int lastRepeatedAviFrameNo = 0; if (isAavFile && !double.IsNaN(effFrameDuration)) { lastRepeatedAviFrameNo = (int)Math.Round(((i - firstFrame) * effFrameDuration) / msPerFrame); } else if (!isAavFile && frame.ElapsedTime.Ticks != 0) { lastRepeatedAviFrameNo = (int)Math.Round((frame.ElapsedTime.TotalMilliseconds - startingTimeMilliseconds) / msPerFrame); } while (aviFrameNo < lastRepeatedAviFrameNo) { if (!saver.AddAviVideoFrame(pixmap, addedGamma, ImageSection.Adv16NormalisationValue)) { progressCallback(100, 0); return(false); } aviFrameNo++; } if (currentBitmap != null) { currentBitmap.Dispose(); } } 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); }