static public void DecodeAtomChildren(System.Action <TAtom> EnumAtom, TAtom Parent, System.Func <long, byte[]> ReadData = null) { long MoovPos = 0; System.Func <long, byte[]> ReadMoovData = (long DataSize) => { if (MoovPos == Parent.AtomData.Length) { return(null); } var ChildData = Parent.AtomData.SubArray(MoovPos, DataSize); MoovPos += DataSize; return(ChildData); }; // decode moov children (mvhd, trak, udta) int LoopSafety = 1000; long FilePos = Parent.AtomDataFilePosition; while (LoopSafety-- > 0) { // when this throws, we're assuming we're out of data var NextAtom = GetNextAtom(ReadMoovData, FilePos); if (!NextAtom.HasValue) { break; } var Atom = NextAtom.Value; //Debug.Log("Found " + Atom.Fourcc); EnumAtom(Atom); FilePos += NextAtom.Value.AtomSize; } }
static public TAtom?GetChildAtom(TAtom ParentAtom, string Fourcc, System.Func <long, byte[]> ReadData) { TAtom?MatchAtom = null; System.Action <TAtom> FindChild = (ChildAtom) => { if (ChildAtom.Fourcc == Fourcc) { MatchAtom = ChildAtom; } }; DecodeAtomChildren(FindChild, ParentAtom); return(MatchAtom); }
public static TAtom?GetNextAtom(System.Func <long, byte[]> ReadData, long FilePosition) { byte[] AtomData = null; try { AtomData = ReadData(TAtom.AtomHeaderSize); // EOF if (AtomData == null) { return(null); } } catch (System.ArgumentException e) { Debug.Log("Ran out of atom data" + e); return(null); } catch (System.Exception e) { Debug.Log("Ran out of atom data" + e); // assuming out of data return(null); } System.Func <byte[]> GetNext8 = () => { var AtomExtData = ReadData(8); return(AtomExtData); }; // let it throw(TM) var Atom = new TAtom(); Atom.FilePosition = FilePosition; Atom.Init(AtomData, GetNext8); // todo: can we verify the fourcc? lets check the spec if the characters have to be ascii or something // grab the atom's data if (Atom.DataSize > 0) { Atom.AtomData = ReadData(Atom.DataSize); } return(Atom); }
static List <long> GetSampleSizes(TAtom Atom, byte[] FileData) { var Sizes = new List <long>(); var AtomData = Atom.AtomData; // https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html //var Version = AtomData[8]; /*var Flags = */ Get24(AtomData[9], AtomData[10], AtomData[11]); var SampleSize = Get32(AtomData[12], AtomData[13], AtomData[14], AtomData[15]); var EntryCount = Get32(AtomData[16], AtomData[17], AtomData[18], AtomData[19]); // if size specified, they're all this size if (SampleSize != 0) { for (int i = 0; i < EntryCount; i++) { Sizes.Add(SampleSize); } return(Sizes); } // each entry in the table is the size of a sample (and one chunk can have many samples) var SampleSizeStart = 20; // gr: docs don't say size, but this seems accurate... SampleSize = (AtomData.Length - SampleSizeStart) / EntryCount; for (int i = SampleSizeStart; i < AtomData.Length; i += SampleSize) { if (SampleSize == 3) { var Size = Get24(AtomData[i + 0], AtomData[i + 1], AtomData[i + 2]); Sizes.Add(Size); } else if (SampleSize == 4) { var Size = Get32(AtomData[i + 0], AtomData[i + 1], AtomData[i + 2], AtomData[i + 3]); Sizes.Add(Size); } } if (Sizes.Count() != EntryCount) { Debug.LogWarning("Expected " + EntryCount + " sample sizes, got " + Sizes.Count()); } return(Sizes); }
static List <SampleMeta> GetSampleMetas(TAtom Atom, byte[] FileData) { var Metas = new List <SampleMeta>(); var AtomData = Atom.AtomData; // https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html //var Version = AtomData[8]; /*var Flags = */ Get24(AtomData[9], AtomData[10], AtomData[11]); var EntryCount = Get32(AtomData[12], AtomData[13], AtomData[14], AtomData[15]); var MetaSize = 3 * 4; for (int i = 16; i < AtomData.Length; i += MetaSize) { var Meta = new SampleMeta(AtomData, i); Metas.Add(Meta); } if (Metas.Count() != EntryCount) { Debug.LogWarning("Expected " + EntryCount + " sample metas, got " + Metas.Count()); } return(Metas); }