private bool GetNextBox(out MpegBox mpegBox, long endPosition, MpegBox parentBox) { // return empty object when we reach data endPosition. If endPosition is set // to zero, return empty object if we reach EOF. if (this.br.BaseStream.Position == (0 == endPosition ? this.br.BaseStream.Length : endPosition)) { mpegBox = null; return(false); } // create new box, fill in the byte offset MpegBox ma = new MpegBox(parentBox, null, MpegBox.BoxType.Unknown, this.br.BaseStream.Position, 0); // now get the size and type ma.Size = BU.ReverseToUInt32(this.br.ReadBytes(4)); // size // special size values aren't handled yet if (ma.Size < 2) { throw new MsvDecoderException("Special MPEG box size values are not yet supported."); } // type try { ma.Type = (MpegBox.BoxType)BU.ReverseToInt32(this.br.ReadBytes(4)); } catch { ma.Type = MpegBox.BoxType.Unknown; } // check the type to see if it has data or child boxes that we care about switch (ma.Type) { case MpegBox.BoxType.moov: { // now that we've picked up the moov box, leave br's pointer // at the start of the moov data and read in all its child boxes ma.Children = GetBoxes(br, ma.Offset + ma.Size, ma); break; } case MpegBox.BoxType.trak: { // read in all its child boxes ma.Children = GetBoxes(br, ma.Offset + ma.Size, ma); break; } case MpegBox.BoxType.mdia: { // read in all its child boxes ma.Children = GetBoxes(br, ma.Offset + ma.Size, ma); break; } case MpegBox.BoxType.minf: { // read in all its child boxes ma.Children = GetBoxes(br, ma.Offset + ma.Size, ma); break; } case MpegBox.BoxType.stbl: { // read in all its child boxes ma.Children = GetBoxes(br, ma.Offset + ma.Size, ma); break; } case MpegBox.BoxType.uuid: // may have data we want { // note current br pointer location long dataStartPos = this.br.BaseStream.Position; // get the 16 byte UUID value from the start of data ma.UuidType = GetUuidType(this.br.ReadBytes(16)); // return pointer to previous location this.br.BaseStream.Position = dataStartPos; // if this is a uuid we care about, copy its data into the box if (!(MpegBox.BoxUuidType.Unknown == ma.UuidType || MpegBox.BoxUuidType.None == ma.UuidType)) { // TODO: throw exception if ma.Size is bigger than an Int32 can hold // read data into ma, then leave br's pointer at the end of this data/box ma.Data = br.ReadBytes((int)ma.Size - 8); // box size, less size/tag bytes } else { // don't care about this uuid, move br's pointer to the end of this box this.br.BaseStream.Seek(ma.Size - 8, SeekOrigin.Current); break; } break; } case MpegBox.BoxType.stco: // contains list of mdat data chunk offsets { // read data into ma, then leave br's pointer at the end of this data/box ma.Data = br.ReadBytes((int)ma.Size - 8); // box size, less size/tag bytes break; } default: // unrecognized, don't read any data from this box { // just move br's pointer to the end of this box this.br.BaseStream.Seek(ma.Size - 8, SeekOrigin.Current); break; } } // all done, verify br's pointer is where it should be // return finished box mpegBox = ma; return(true); }
private bool GetNextAtom(out MpegAtom mpegAtom, long endPosition, MpegAtom parentAtom) { // return empty object when we reach data endPosition. If endPosition is set // to zero, return empty object if we reach EOF. if (this.br.BaseStream.Position == (0 == endPosition ? this.br.BaseStream.Length : endPosition)) { mpegAtom = null; return(false); } // create new atom, fill in the byte offset MpegAtom ma = new MpegAtom(null, null, MpegAtom.AtomType.Unknown, this.br.BaseStream.Position, 0); // now get the size and type ma.Size = BU.ReverseToUInt32(this.br.ReadBytes(4)); // size // type try { ma.Type = (MpegAtom.AtomType)BU.ReverseToInt32(this.br.ReadBytes(4)); } catch { ma.Type = MpegAtom.AtomType.Unknown; } /* * switch (BU.ReverseToInt32(this.br.ReadBytes(4))) // type * { * case 0x6D6F6F76: ma.Type = MpegAtom.AtomType.moov; break; // "moov" * case 0x75756964: ma.Type = MpegAtom.AtomType.uuid; break; // "uuid" * default: ma.Type = MpegAtom.AtomType.Unknown; break; // uninteresting to us * } */ // check the type to see if it has data or child atoms that we care about switch (ma.Type) { case MpegAtom.AtomType.moov: { // now that we've picked up the moov atom, leave br's pointer // at the start of the moov data and read in all its child atoms ma.Children = GetAtoms(br, ma.Offset + ma.Size); // TODO: verify br's pointer is now at end of moov data break; } case MpegAtom.AtomType.trak: { // now that we've picked up the moov atom, leave br's pointer // at the start of the moov data and read in all its child atoms ma.Children = GetAtoms(br, ma.Offset + ma.Size); // TODO: verify br's pointer is now at end of moov data break; } case MpegAtom.AtomType.uuid: // may have data we want { // note current br pointer location long dataStartPos = this.br.BaseStream.Position; // get the 16 byte UUID value from the start of data ma.UuidType = GetUuidType(this.br.ReadBytes(16)); // return pointer to previous location this.br.BaseStream.Position = dataStartPos; // if this is a uuid we care about, copy its data into the atom if (!(MpegAtom.AtomUuidType.Unknown == ma.UuidType || MpegAtom.AtomUuidType.None == ma.UuidType)) { // TODO: throw exception if ma.Size is bigger than an Int32 can hold // read data into ma, then leave br's pointer at the end of this data/atom ma.Data = br.ReadBytes((int)ma.Size - 8); // atom size, less size/tag bytes } else { // don't care about this uuid, move br's pointer to the end of this atom this.br.BaseStream.Seek(ma.Size - 8, SeekOrigin.Current); break; } break; } default: // unrecognized, don't read any data from this atom { // just move br's pointer to the end of this atom this.br.BaseStream.Seek(ma.Size - 8, SeekOrigin.Current); break; } } // all done, verify br's pointer is where it should be // return finished atom mpegAtom = ma; return(true); }