コード例 #1
0
        private ArrayList getDataSegments(MemoryStream ms, long endPosition)
        {
            // read and validate UUID value
            // TODO:  Implement a real exception handler for this
            if ("55534D5421D24FCEBB88695CFAC9C740" !=
                BU.ByteArrayToStringHex(br.ReadBytes(16)))
            {
                throw new ApplicationException("Atom data supplied is not of type SonyPspTag.");
            }
            // read atom's internal data size
            this.internalSize = BU.ReverseToUInt32(br.ReadBytes(4));
            // validate next marker in header
            // TODO:  Implement a real exception handler for this
            if ("4D544454" != BU.ByteArrayToStringHex(br.ReadBytes(4)))
            {
                throw new ApplicationException("Atom data supplied is not of type SonyPspTag.");
            }
            // read segment count
            this.segmentCount = BU.ReverseToUInt16(br.ReadBytes(2));
            // we should now be at the start of the first segment
            ArrayList             result = new ArrayList();
            SonyPspTagDataSegment ds     = null;

            while (getNextDataSegment(out ds, endPosition, null))
            {
                result.Add(ds);
            }
            // TODO: throw exception if we still have a null result
            //       or if arraylist item count != this.segmentCount
            return(result);
        }
コード例 #2
0
        private bool getNextDataSegment(out SonyPspTagDataSegment dataSegment, long endPosition, MpegAtom parentAtom)
        {
            // return empty object when we reach data endPosition.  If endPosition is set
            // to zero, return empty object if we reach end of data.
            if (this.br.BaseStream.Position == (0 == endPosition ? this.br.BaseStream.Length : endPosition))
            {
                dataSegment = null;
                return(false);
            }

            // create new segment and note its offset in the atom data
            SonyPspTagDataSegment ds = new SonyPspTagDataSegment();

            ds.offset = this.br.BaseStream.Position;
            // now get the segment header info and data
            ds.size            = BU.ReverseToUInt16(this.br.ReadBytes(2)); // size
            ds.type            = BU.ReverseToUInt32(this.br.ReadBytes(4));
            ds.language        = BU.ReverseToUInt16(this.br.ReadBytes(2));
            ds.unknownProperty = BU.ReverseToUInt16(this.br.ReadBytes(2));
            if (0 < ds.size - 10)                                 // if there is any data left after the header, get data
            {
                ds.segmentData = this.br.ReadBytes(ds.size - 10); // data
            }
            // all done, verify br's pointer is where it should be

            // return finished segment
            dataSegment = ds;
            return(true);
        }
コード例 #3
0
        private bool getNextDataSegment(out MsvTagDataSegment dataSegment, long endPosition, MpegBox parentBox)
        {
            // return empty object when we reach data endPosition.  If endPosition is set
            // to zero, return empty object if we reach end of data.
            if (this.br.BaseStream.Position == (0 == endPosition ? this.br.BaseStream.Length : endPosition))
            {
                dataSegment = null;
                return(false);
            }

            // create new segment and note its offset in the box data
            MsvTagDataSegment ds = new MsvTagDataSegment();

            ds.offset = this.br.BaseStream.Position;
            // offset in file is equal to the start of the containing box, plus eight bytes for
            // box's size and uuid markers, plus segment offset from start of box data
            ds.absoluteOffset = msvTagBox.AbsoluteOffset() + 8 + ds.offset;
            // now get the segment header info and data
            ds.size            = BU.ReverseToUInt16(this.br.ReadBytes(2)); // size
            ds.type            = BU.ReverseToUInt32(this.br.ReadBytes(4));
            ds.language        = BU.ReverseToUInt16(this.br.ReadBytes(2));
            ds.unknownProperty = BU.ReverseToUInt16(this.br.ReadBytes(2));
            if (0 < ds.size - 10)                                 // if there is any data left after the header, get data
            {
                ds.segmentData = this.br.ReadBytes(ds.size - 10); // data
            }
            // all done, verify br's pointer is where it should be

            // return finished segment
            dataSegment = ds;
            return(true);
        }
コード例 #4
0
        internal MpegBox.BoxUuidType GetUuidType(byte[] uuidBytes)
        {
            string s = BU.ByteArrayToStringHex(uuidBytes);

            MpegBox.BoxUuidType result = MpegBox.BoxUuidType.Unknown;
            switch (s)
            {
            case "55534D5421D24FCEBB88695CFAC9C740":      // MsvTag
            {
                result = MpegBox.BoxUuidType.MsvTag;
                break;
            }

            case "C0EDBABEA7EBADF00DA7DEADBEEFCAFE":      // MyCustomTag, registered (see below)
            {
                // NOTE: This is a registered UUID, do not use it for your
                //       own purposes.  You can generate and register one for
                //       free at:  http://www.itu.int/ITU-T/asn1/uuid.html
                result = MpegBox.BoxUuidType.MyCustomTag;
                break;
            }

            default:
            {
                // leave the return initialized as Unknown
                break;
            }
            }
            return(result);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        private void SetTagData(ArrayList mpegBoxes, MsvBox.SegmentType type, byte[] bytes,
                                int lengthDelta, bool haveProcessedMdat)
        {
            foreach (MpegBox mb in mpegBoxes)
            {
                if (MpegBox.BoxType.mdat == mb.Type)
                {
                    haveProcessedMdat = true;
                }
                else if (MpegBox.BoxType.moov == mb.Type || MpegBox.BoxType.trak == mb.Type ||
                         MpegBox.BoxType.mdia == mb.Type || MpegBox.BoxType.minf == mb.Type ||
                         MpegBox.BoxType.stbl == mb.Type)
                {
                    SetTagData(mb.Children, type, bytes, lengthDelta, haveProcessedMdat);
                }
                else if (MpegBox.BoxType.stco == mb.Type)
                {
                    // if we've not yet encountered the mdat box, then it must come after the moov box
                    // and so we'll need to adjust all the chunk offsets to match their new locations
                    // if we are resizing the tag's length
                    if (!haveProcessedMdat && lengthDelta != 0)
                    {
                        // go to the start of the actual stco data
                        long dataStartPosition = mb.AbsoluteOffset() + 8;
                        this.br.BaseStream.Seek(dataStartPosition, System.IO.SeekOrigin.Begin);
                        if (0x00 != br.ReadByte())
                        {
                            throw new MsvEncoderException("Detected chunk offset box version is not supported.");
                        }
                        if (!BU.AreByteArraysEqual(new byte[] { 0x00, 0x00, 0x00 }, br.ReadBytes(3)))
                        {
                            throw new MsvEncoderException("Detected chunk offset box flags are not supported.");
                        }
                        UInt32 chunkCount      = BU.ReverseToUInt32(this.br.ReadBytes(4));
                        UInt32 tempChunkOffset = 0;
                        for (int i = 0; i < chunkCount; i++)
                        {
                            // get next chunk offset
                            tempChunkOffset = BU.ReverseToUInt32(this.br.ReadBytes(4));
                            // back pointer up, then rewrite chunk offset to reflect lengthDelta
                            this.br.BaseStream.Seek(-4, System.IO.SeekOrigin.Current);
                            this.bw.Write(BU.ReverseToBytes((UInt32)(tempChunkOffset + lengthDelta)));
                        }
                    }
                }
                else if (MpegBox.BoxUuidType.MsvTag == mb.UuidType)
                {
                    MsvBox pb = new MsvBox(mb);
                    foreach (MsvTagDataSegment ds in pb.DataSegments)
                    {
                        if ((uint)type == ds.type)
                        {
                            // go to the start of the actual data within ds
                            // this assumes that the structure preceding the data is always
                            // consistent between all segments having write support
                            long dataStartPosition = ds.absoluteOffset + 10;
                            this.br.BaseStream.Seek(dataStartPosition, System.IO.SeekOrigin.Begin);
                            // verify that we know what data we're about to overwrite
                            byte[] compare = this.br.ReadBytes(ds.SegmentData.Length);
                            if (!BU.AreByteArraysEqual(compare, ds.SegmentData))
                            {
                                throw new MsvEncoderException(
                                          "The filestream position was invalid while writing tag data.");
                            }

                            if (bytes.Length != ds.SegmentData.Length)
                            {
                                // we have to grow or shrink the file and adjust its size markers
                                long moveByteCount    = this.bw.BaseStream.Length - this.bw.BaseStream.Position;
                                int  moveBlockSize    = 131072;                               // move in 128kb blocks
                                int  partialBlockSize = (int)(moveByteCount % moveBlockSize); // remaining partial block
                                // verify that the supplied lengthDelta value is correct
                                // the length delta is a negative number when shrinking a tag
                                if (lengthDelta != bytes.Length - ds.SegmentData.Length)
                                {
                                    throw new MsvEncoderException(
                                              "lengthDelta supplied did not match old tag length found.");
                                }
                                byte[] buffer;       // buffer for moving blocks

                                if (lengthDelta > 0) // new tag is too big, so grow the file
                                {
                                    // grow the file the needed number of bytes before moving data out
                                    this.br.BaseStream.SetLength(this.bw.BaseStream.Length + lengthDelta);

                                    // need to shift subsequent data further down the file
                                    if (moveByteCount >= moveBlockSize)
                                    {
                                        // we have at least one full block to move
                                        for (int i = 0; i < moveByteCount / moveBlockSize; i++)
                                        {
                                            // move pointer to beginning of next block to be moved
                                            // blocks are moved in reverse, from EOF backward
                                            this.br.BaseStream.Seek((moveBlockSize * (i + 1) + lengthDelta) * -1,
                                                                    System.IO.SeekOrigin.End);
                                            // read in a block
                                            buffer = br.ReadBytes(moveBlockSize);
                                            // move pointer backwards to start of the block, minus the grow size
                                            this.br.BaseStream.Seek((moveBlockSize - lengthDelta) * -1,
                                                                    System.IO.SeekOrigin.Current);
                                            this.bw.Write(buffer);
                                            buffer = null;
                                        }
                                    }
                                    // move any remaining partial block
                                    if (0 != partialBlockSize)
                                    {
                                        // move pointer to start of partial block
                                        this.br.BaseStream.Seek(dataStartPosition + ds.segmentData.Length,
                                                                System.IO.SeekOrigin.Begin);
                                        // read in the partial block
                                        buffer = br.ReadBytes(partialBlockSize);
                                        // move pointer backwards to start of partial block, minus the grow size
                                        this.br.BaseStream.Seek((partialBlockSize - lengthDelta) * -1,
                                                                System.IO.SeekOrigin.Current);
                                        this.bw.Write(buffer);
                                        buffer = null;
                                    }
                                }
                                else if (lengthDelta < 0)  // new tag is too small, so shrink the file
                                {
                                    // need to shift subsequent data further up the file
                                    // move pointer to beginning of first block
                                    this.br.BaseStream.Seek(dataStartPosition + ds.segmentData.Length,
                                                            System.IO.SeekOrigin.Begin);

                                    if (moveByteCount >= moveBlockSize)
                                    {
                                        // we have at least one full block to move
                                        for (int i = 0; i < moveByteCount / moveBlockSize; i++)
                                        {
                                            // read in a block
                                            buffer = br.ReadBytes(moveBlockSize);
                                            // move pointer backwards to start of the block, plus the shrink size
                                            // remember that lengthDelta is a negative number for shrink operations
                                            this.br.BaseStream.Seek((moveBlockSize - lengthDelta) * -1,
                                                                    System.IO.SeekOrigin.Current);
                                            this.bw.Write(buffer);
                                            buffer = null;
                                            // block is moved, so advance pointer to the beginning of the
                                            // next block
                                            this.br.BaseStream.Seek(lengthDelta * -1,
                                                                    System.IO.SeekOrigin.Current);
                                        }
                                    }
                                    // move any remaining partial block
                                    if (0 != partialBlockSize)
                                    {
                                        // pointer should already be at start of partial block
                                        // read in the partial block
                                        buffer = br.ReadBytes(partialBlockSize);
                                        // move pointer backwards to start of the block, plus the shrink size
                                        // remember that lengthDelta is a negative number for shrink operations
                                        this.br.BaseStream.Seek((partialBlockSize - lengthDelta) * -1,
                                                                System.IO.SeekOrigin.Current);
                                        this.bw.Write(buffer);
                                        buffer = null;
                                    }
                                    // shrink the file the needed number of bytes after moving data in
                                    this.br.BaseStream.SetLength(this.bw.BaseStream.Length + lengthDelta);
                                }

                                // now fix up all the size markers
                                UInt32 temp32 = 0;
                                UInt16 temp16 = 0;
                                // this tag's size marker
                                this.br.BaseStream.Seek(ds.absoluteOffset, System.IO.SeekOrigin.Begin);
                                temp16 = BU.ReverseToUInt16(this.br.ReadBytes(2)); // tag size
                                this.br.BaseStream.Seek(-2, System.IO.SeekOrigin.Current);
                                if (temp16 != ds.size)
                                {
                                    throw new MsvEncoderException(
                                              "The filestream position was invalid while writing tag size.");
                                }
                                this.bw.Write(BU.ReverseToBytes((UInt16)(temp16 + lengthDelta)));
                                // the rest of the size markers we must first read and then change
                                // incase for some reason we're changing them multiple times

                                // both of this MSV box's external and internal size markers
                                this.br.BaseStream.Seek(mb.AbsoluteOffset(), System.IO.SeekOrigin.Begin);
                                temp32 = BU.ReverseToUInt32(this.br.ReadBytes(4)); // UUID box size
                                this.br.BaseStream.Seek(-4, System.IO.SeekOrigin.Current);
                                this.bw.Write(BU.ReverseToBytes((UInt32)(temp32 + lengthDelta)));
                                this.br.BaseStream.Seek(20, System.IO.SeekOrigin.Current);
                                temp32 = BU.ReverseToUInt32(this.br.ReadBytes(4)); // MSV internalSize
                                this.br.BaseStream.Seek(-4, System.IO.SeekOrigin.Current);
                                this.bw.Write(BU.ReverseToBytes((UInt32)(temp32 + lengthDelta)));

                                // size markers of this box's parent and all the parent's parents
                                MpegBox tempBox = mb.Parent;
                                while (tempBox != null)
                                {
                                    this.br.BaseStream.Seek(tempBox.AbsoluteOffset(),
                                                            System.IO.SeekOrigin.Begin);
                                    temp32 = BU.ReverseToUInt32(this.br.ReadBytes(4)); // tempBox size
                                    this.br.BaseStream.Seek(-4, System.IO.SeekOrigin.Current);
                                    this.bw.Write(BU.ReverseToBytes((UInt32)(temp32 + lengthDelta)));

                                    tempBox = tempBox.Parent;
                                }
                            }

                            // set reader back to start of tag data we wish to overwrite
                            this.br.BaseStream.Seek(dataStartPosition, System.IO.SeekOrigin.Begin);
                            // now write the new data over the old data
                            this.bw.Write(bytes);
                            this.bw.BaseStream.Seek(dataStartPosition, System.IO.SeekOrigin.Begin);
                            // verify it worked
                            byte[] verify = this.br.ReadBytes(bytes.Length);
                            if (!BU.AreByteArraysEqual(verify, bytes))
                            {
                                throw new MsvEncoderException("The data write failed verification.");
                            }
                            // make sure all the data changes get flushed to disk
                            this.bw.Flush();
                        }
                    }
                }
            }
            return;
        }
コード例 #7
0
        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);
        }