public void ParseAtoms(ContainerVisitor visitor, BinaryReader reader, long offset, long stopAt, StructInstance parent) { while (offset < stopAt) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); uint atomSize = Util.EndianFlip32(reader.ReadUInt32()); string atomType = Util.ReadFourCC(reader); if (_atomDefs.ContainsKey(atomType)) { StructElement atomDef = _atomDefs[atomType]; StructInstance inst = GetAtomInstance(reader, atomDef, atomSize, parent); string desc = GetAtomDesc(atomDef, atomSize, inst); visitor.BeginVisitNode(atomType, desc); // If it is a container atom if (atomDef != null && atomDef.Elements == null) { // parse children atoms recursively ParseAtoms(visitor, reader, reader.BaseStream.Position, offset + atomSize, inst); } if (parent != null) { parent[atomType] = inst; } visitor.EndVisitNode(); } // now set offset to next atom (or end-of-file) in special case // (atomSize = 0 means atom goes to EOF) if (atomSize == 0) { offset = reader.BaseStream.Length; } else { offset += atomSize; } // if a 'udta' container atom, then jump ahead 4 to work around // Apple's QT 1.0 workaround // @see http://developer.apple.com/technotes/qt/qt_03.html if (atomType == "udta") { offset += 4; } } }
public void ParseListsChunks(ContainerVisitor visitor, BinaryReader reader, long offset, long stopAt, StructInstance parent) { while (offset < stopAt) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); string id = Util.ReadFourCC(reader); int size = reader.ReadInt32(); if (size % 2 != 0) { size++; } StructInstance inst = null; if (id == "LIST") // 'LIST' listSize listType listData { string listType = Util.ReadFourCC(reader); // a LIST instance is needed to maintain a list of sub LISTs and CHUNKs. StructElement listDef = _chunkDefs["LIST"]; inst = GetChunkInstance(reader, listDef, 0, parent); if (listType != "movi") { visitor.BeginVisitNode( string.Format("LIST ({0})", listType), string.Empty); ParseListsChunks(visitor, reader, reader.BaseStream.Position, offset + size + 8, inst); } else { visitor.BeginVisitNode( string.Format("LIST ({0})", listType), "Content in this list is skipped."); } offset += size + 8; } else // ckID ckSize ckData { StructElement chunkDef = _chunkDefs[id]; inst = GetChunkInstance(reader, chunkDef, size, parent); visitor.BeginVisitNode(id, GetChunkDescription(reader, id, size, inst)); offset += size + 8; } if (parent != null) { // link CHUNK to its parent LIST parent[id] = inst; } visitor.EndVisitNode(); } }
public void Walk(ContainerVisitor visitor) { using (BinaryReader reader = new BinaryReader(File.OpenRead(_fname))) { // 'RIFF' fileSize fileType (data) if (Util.ReadFourCC(reader) == "RIFF") { _fileSize = reader.ReadInt32(); _fileType = Util.ReadFourCC(reader); visitor.BeginVisitNode(string.Format("RIFF ({0})", _fileType), string.Empty); ParseListsChunks(visitor, reader, reader.BaseStream.Position, _fileSize + 8, null); visitor.EndVisitNode(); } } }