protected MLVTypes.mlv_file_hdr_t ReadMainHeader() { Reader[0].BaseStream.Position = 0; byte[] block = ReadBlockData(Reader[0]); return((MLVTypes.mlv_file_hdr_t)MLVTypes.ToStruct("MLVI", block)); }
public virtual void SaveIndex() { if (BlockIndex == null || BlockIndex.Length == 0) { return; } MLVTypes.mlv_file_hdr_t fileHeader = ReadMainHeader(); MLVTypes.mlv_xref_hdr_t xrefHdr = new MLVTypes.mlv_xref_hdr_t(); /* update MLVI header */ fileHeader.blockSize = (uint)Marshal.SizeOf(fileHeader); fileHeader.videoFrameCount = 0; fileHeader.audioFrameCount = 0; fileHeader.fileNum = (ushort)FileNames.Length; /* create XREF block */ xrefHdr.blockType = "XREF"; xrefHdr.blockSize = (uint)(Marshal.SizeOf(xrefHdr) + BlockIndex.Length * Marshal.SizeOf(new MLVTypes.mlv_xref_t())); xrefHdr.timestamp = 1; xrefHdr.frameType = 3; /* video+audio */ xrefHdr.entryCount = (uint)BlockIndex.Length; /* open file */ BinaryWriter writer = new BinaryWriter(new FileStream(IndexName, FileMode.Create, FileAccess.Write)); writer.Write(MLVTypes.ToByteArray(fileHeader)); writer.Write(MLVTypes.ToByteArray(xrefHdr)); foreach (var entry in BlockIndex) { MLVTypes.mlv_xref_t xrefEntry = new MLVTypes.mlv_xref_t(); xrefEntry.fileNumber = (ushort)entry.fileNumber; xrefEntry.frameOffset = (ulong)entry.position; xrefEntry.empty = 0; switch (entry.type) { case "VIDF": xrefEntry.frameType = 1; break; case "AUDF": xrefEntry.frameType = 2; break; default: xrefEntry.frameType = 0; break; } writer.Write(MLVTypes.ToByteArray(xrefEntry)); } writer.Close(); }
public virtual bool ReadBlock() { if (Reader == null) { return(false); } FileNum = BlockIndex[CurrentBlockNumber].fileNumber; FilePos = BlockIndex[CurrentBlockNumber].position; int size = Math.Max(BlockIndex[CurrentBlockNumber].size, 16); byte[] buf = new byte[size]; /* seek to current block pos */ Reader[FileNum].BaseStream.Position = FilePos; /* if there are not enough blocks anymore */ if (Reader[FileNum].BaseStream.Position >= Reader[FileNum].BaseStream.Length - 16) { return(false); } /* read MLV block header */ if (Reader[FileNum].Read(buf, 0, size) != size) { return(false); } string type = Encoding.UTF8.GetString(buf, 0, 4); UInt32 length = BitConverter.ToUInt32(buf, 4); UInt64 timestamp = BitConverter.ToUInt64(buf, 8); /* oh, size mismatch. boo. */ if (size != length) { /* resize buffer to the block size */ Array.Resize <byte>(ref buf, (int)length); /* now read the rest of the block */ Reader[FileNum].BaseStream.Position = FilePos; if (Reader[FileNum].Read(buf, 0, (int)length) != (int)length) { return(false); } } var data = MLVTypes.ToStruct(type, buf); int headerLength = Marshal.SizeOf(data.GetType()); Handler(type, data, buf, headerLength, buf.Length - headerLength); LastType = type; return(true); }
private void LoadIndex() { BinaryReader index = new BinaryReader(File.Open(IndexName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); /* read MLV block header */ byte[] mlvBlockBuf = ReadBlockData(index); MLVTypes.mlv_file_hdr_t fileHeader = (MLVTypes.mlv_file_hdr_t)MLVTypes.ToStruct("MLVI", mlvBlockBuf); MLVTypes.mlv_file_hdr_t mainHeader = ReadMainHeader(); if (mainHeader.fileGuid != fileHeader.fileGuid) { throw new Exception("GUID mismatch"); } byte[] xrefBlockBuf = ReadBlockData(index); MLVTypes.mlv_xref_hdr_t xrefHeader = (MLVTypes.mlv_xref_hdr_t)MLVTypes.ToStruct("XREF", xrefBlockBuf); BlockIndex = new xrefEntry[xrefHeader.entryCount]; int entrySize = Marshal.SizeOf(new MLVTypes.mlv_xref_t()); for (int pos = 0; pos < xrefHeader.entryCount; pos++) { MLVTypes.mlv_xref_t xrefEntry = (MLVTypes.mlv_xref_t)MLVTypes.ToStruct("XREF_ENTRY", xrefBlockBuf, Marshal.SizeOf(xrefHeader) + pos * entrySize); BlockIndex[pos] = new xrefEntry(); BlockIndex[pos].fileNumber = xrefEntry.fileNumber; BlockIndex[pos].position = (long)xrefEntry.frameOffset; BlockIndex[pos].size = 0; switch (xrefEntry.frameType) { case 0: BlockIndex[pos].type = ""; break; case 1: BlockIndex[pos].type = "VIDF"; break; case 2: BlockIndex[pos].type = "AUDF"; break; } } }
private bool FilesValid() { MLVTypes.mlv_file_hdr_t mainFileHeader; mainFileHeader.fileGuid = 0; for (int fileNum = 0; fileNum < Reader.Length; fileNum++) { byte[] buf = new byte[16]; Reader[fileNum].BaseStream.Position = 0; /* read MLV block header */ if (Reader[fileNum].Read(buf, 0, 16) != 16) { break; } string type = Encoding.UTF8.GetString(buf, 0, 4); if (type != "MLVI") { MessageBox.Show("File '" + FileNames[fileNum] + "' has a invalid header."); return(false); } /* seems to be a valid header, proceed */ UInt32 length = BitConverter.ToUInt32(buf, 4); UInt64 timestamp = BitConverter.ToUInt64(buf, 8); /* resize buffer to the block size */ Array.Resize <byte>(ref buf, (int)length); /* now read the rest of the block */ if (Reader[fileNum].Read(buf, 16, (int)length - 16) != (int)length - 16) { MessageBox.Show("File '" + FileNames[fileNum] + "' has a invalid header."); return(false); } MLVTypes.mlv_file_hdr_t hdr = (MLVTypes.mlv_file_hdr_t)MLVTypes.ToStruct(type, buf); if (hdr.versionString != "v2.0") { MessageBox.Show("File '" + FileNames[fileNum] + "' has a invalid version '" + hdr.versionString + "'."); return(false); } if (fileNum == 0) { mainFileHeader = hdr; } else { if (mainFileHeader.fileGuid != hdr.fileGuid) { MessageBox.Show("File '" + FileNames[fileNum] + "' has a different GUID from the main .MLV. Please delete or rename it to fix that issue."); return(false); } } } return(true); }
public virtual void BuildFrameIndex() { if (Reader == null) { return; } HighestVideoFrameNumber = 0; TotalVideoFrameCount = 0; Dictionary <uint, frameXrefEntry> vidfXrefList = new Dictionary <uint, frameXrefEntry>(); Dictionary <uint, frameXrefEntry> audfXrefList = new Dictionary <uint, frameXrefEntry>(); MetadataContainer metadataContainer = new MetadataContainer(); uint highestFrameNumber = 0; for (int blockIndexPos = 0; blockIndexPos < BlockIndex.Length; blockIndexPos++) { var block = BlockIndex[blockIndexPos]; Reader[block.fileNumber].BaseStream.Position = block.position; /* 16 bytes are enough for size, type and timestamp, but we try to read all blocks up to 1k */ byte[] buf = new byte[1024]; /* read MLV block header */ if (Reader[block.fileNumber].Read(buf, 0, 16) != 16) { break; } uint size = BitConverter.ToUInt32(buf, 4); string type = Encoding.UTF8.GetString(buf, 0, 4); UInt64 timestamp = BitConverter.ToUInt64(buf, 8); /* read that block, up to 256 byte */ Reader[block.fileNumber].BaseStream.Position = block.position; /* read MLV block header */ int readSize = (int)Math.Min(size, 256); if (Reader[block.fileNumber].Read(buf, 0, readSize) != readSize) { break; } object blockData = MLVTypes.ToStruct(buf); switch (type) { case "NULL": continue; case "VIDF": { MLVTypes.mlv_vidf_hdr_t header = (MLVTypes.mlv_vidf_hdr_t)blockData; if (!vidfXrefList.ContainsKey(header.frameNumber)) { frameXrefEntry entry = new frameXrefEntry(); entry.blockIndexPos = blockIndexPos; entry.metadata = metadataContainer.Metadata; entry.timestamp = timestamp; vidfXrefList.Add(header.frameNumber, entry); } else { FrameRedundantErrors++; } highestFrameNumber = Math.Max(highestFrameNumber, header.frameNumber); } break; case "AUDF": { MLVTypes.mlv_audf_hdr_t header = (MLVTypes.mlv_audf_hdr_t)blockData; if (!audfXrefList.ContainsKey(header.frameNumber)) { frameXrefEntry entry = new frameXrefEntry(); entry.blockIndexPos = blockIndexPos; entry.metadata = metadataContainer.Metadata; entry.timestamp = timestamp; audfXrefList.Add(header.frameNumber, entry); } else { FrameRedundantErrors++; } } break; default: metadataContainer.Update(type, blockData); break; } } /* count the number of missing video frames */ uint curFrame = 0; foreach (var elem in vidfXrefList.OrderBy(elem => elem.Key)) { if (elem.Key != curFrame) { curFrame = elem.Key; FrameMissingErrors++; } curFrame++; } VidfXrefList = vidfXrefList; AudfXrefList = audfXrefList; TotalVideoFrameCount = (uint)vidfXrefList.Count; HighestVideoFrameNumber = highestFrameNumber; }