Пример #1
0
        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();
                }
        }
Пример #2
0
        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();
        }
Пример #3
0
        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());
        }
Пример #4
0
        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;
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }