private void ParseAtom(InputFile file, ulong position, Atom atom) { file.Seek(position); UInt64 length = file.ReadUInt32(position); if (length == 0) { atom.TotalLength = file.Length - position; atom.HeaderLength = 8; } else if (length == 1) { atom.TotalLength = file.ReadUInt64(position + 8); atom.HeaderLength = 16; } else { atom.TotalLength = length; atom.HeaderLength = 8; } if (atom.Type == "mdat") { if (!IsAtom(GetAtomType(file, position + atom.TotalLength))) { EOSMovieFixer.Log(" Buggy [mdat] section (32 bit overflow detected)..."); EOSMovieFixer.Log(" Probing [mdat] end..."); /* try to find end of mdat by probing next atom */ EOSMovieFixer.Log(" length 0x" + atom.TotalLength.ToString("X16")); while (!IsAtom(GetAtomType(file, position + atom.TotalLength)) && ((position + atom.TotalLength) < file.Length)) { atom.TotalLength += 0x0100000000; EOSMovieFixer.Log(" length 0x" + atom.TotalLength.ToString("X16")); } if (!IsAtom(GetAtomType(file, position + atom.TotalLength))) { throw new Exception("Could not find 'mdat' end"); } else { EOSMovieFixer.Log(" Real atom end found successfully"); } } } atom.HeaderFileOffset = position; /* save original length for rewriting purposes */ atom.OriginalPayloadLength = atom.PayloadLength; atom.OriginalPayloadFileOffset = atom.PayloadFileOffset; atom.ParsePayload(file, position); }
private ArrayList StcoExtractOffsets(Atom stco, Atom mdat) { ArrayList offsetsInMdat = new ArrayList(); UInt64 lastOffset = 0; UInt64 overflow = 0; int entry = 0; for (UInt64 pos = 8; pos < stco.PayloadLength; pos += 4) { UInt64 offset = InFile.ReadUInt32(stco.PayloadFileOffset + pos) + overflow; if (lastOffset > offset) { offset += 0x0100000000; overflow += 0x0100000000; } lastOffset = offset; if ((lastOffset < mdat.PayloadFileOffset) || ((lastOffset - mdat.PayloadFileOffset) >= mdat.PayloadLength)) { throw new Exception("Offset not pointing into 'mdat'"); } UInt64 relativeOffset = (UInt64)(lastOffset - mdat.PayloadFileOffset); if (entry < 5) { Log(" abs: 0x" + offset.ToString("X08") + " -> rel: 0x" + relativeOffset.ToString("X08")); } offsetsInMdat.Add(relativeOffset); entry++; } Log(" ..."); UInt32 entries = InFile.ReadUInt32(stco.PayloadFileOffset + 4); Log(" (" + offsetsInMdat.Count + " chunks)"); if (entries != offsetsInMdat.Count) { throw new Exception("Offset count invalid"); } return offsetsInMdat; }
private void StcoUpdate(Atom stco, Atom mdat, ArrayList offsetsInMdat) { for (int entry = 0; entry < offsetsInMdat.Count; entry++) { UInt64 relativeOffset = (UInt64)offsetsInMdat[entry]; UInt64 offset = relativeOffset + mdat.PayloadFileOffset; if (entry < 5) { Log(" rel: 0x" + relativeOffset.ToString("X08") + " -> abs: 0x" + offset.ToString("X08")); } byte[] a64 = BitConverter.GetBytes(offset); Array.Reverse(a64); Array.Copy(a64, 0, stco.PayloadData, 2 * 4 + entry * 8, 8); } Log(" ..."); }
private void StcoExtend(Atom stco, Atom mdat, ArrayList offsetsInMdat) { byte[] newPayload = new byte[2 * 4 + offsetsInMdat.Count * 8]; /* read 8 bytes - version, flags and entry count */ InFile.ReadBytes(stco.PayloadFileOffset, newPayload, 8); /* apply changes */ stco.Type = "co64"; stco.PayloadData = newPayload; }