// --- children ---
 protected void readChildren(MP4InputStream inStream)
 {
     while ((size - (inStream.getOffset() - start)) > 0)
     {
         Descriptor desc = createDescriptor(inStream);
         children.Add(desc);
     }
 }
예제 #2
0
 public void readChildren(MP4InputStream inStream)
 {
     while (inStream.getOffset() < (offset + size))
     {
         var box = BoxFactory.parseBox(this, inStream);
         children.Add(box);
     }
 }
        public static Descriptor createDescriptor(MP4InputStream inStream)
        {
            //read tag and size
            int type = inStream.read();
            int read = 1;
            int size = 0;
            int b    = 0;

            do
            {
                b      = inStream.read();
                size <<= 7;
                size  |= b & 0x7f;
                read++;
            }while ((b & 0x80) == 0x80);

            //create descriptor
            Descriptor desc = forTag(type);

            desc.type  = type;
            desc.size  = size;
            desc.start = inStream.getOffset();

            //decode
            desc.decode(inStream);
            //skip remaining bytes
            long remaining = size - (inStream.getOffset() - desc.start);

            if (remaining > 0)
            {
                Logger.LogBoxes(string.Format("Descriptor: bytes left: {0:N0}, offset: {1:N0}", remaining, inStream.getOffset()));
                inStream.skipBytes(remaining);
            }
            desc.size += read; //include type and size fields

            return(desc);
        }
        /// <summary>
        /// Reads the next frame from this track. If it contains no more frames to read, null is returned.
        /// </summary>
        /// <returns>the next frame or null if there are no more frames to read</returns>
        public Frame readNextFrame()
        {
            Frame frame = null;

            if (hasMoreFrames())
            {
                frame = frames[currentFrame];

                long diff = frame.getOffset() - inStream.getOffset();
                if (diff > 0)
                {
                    inStream.skipBytes(diff);
                }
                else if (diff < 0)
                {
                    if (inStream.hasRandomAccess())
                    {
                        inStream.seek(frame.getOffset());
                    }
                    else
                    {
                        Logger.LogServe(string.Format("MP4 API: readNextFrame failed: frame {0:N0} already skipped, offset:{1:N0}, stream:{2:N0}", currentFrame, frame.getOffset(), inStream.getOffset()));
                        throw new IOException("frame already skipped and no random access");
                    }
                }

                var b = new byte[(int)frame.getSize()];
                try
                {
                    inStream.read(b, 0, b.Length);
                }
                catch (Exception)
                {
                    Logger.LogServe(string.Format("MP4 API: readNextFrame failed: tried to read {0:N0} bytes at {1:N0}", frame.getSize(), inStream.getOffset()));
                    throw;
                }
                frame.setData(b);
                currentFrame++;
            }
            return(frame);
        }
예제 #5
0
        public static IBox parseBox(IBox parent, MP4InputStream inStream)
        {
            long offset = inStream.getOffset();
            long size   = inStream.readBytes(4);
            var  type   = (BoxType)(uint)inStream.readBytes(4);

            if (size == 1)
            {
                size = inStream.readBytes(8);
            }
            if (type == BoxType.EXTENDED_TYPE)
            {
                inStream.skipBytes(16);
            }
            if (type == 0)
            {
                return(new UnknownBox());
            }

            // --- error protection ---
            if (parent != null)
            {
                long parentLeft = (parent.getOffset() + parent.getSize()) - offset;
                if (size > parentLeft)
                {
                    throw new Exception("error while decoding box '" + type + "' ('" + typeToString(type) + "') at offset " + offset.ToString("N0") + ": box too large for parent");
                }
            }

            Logger.LogBoxes("[" + offset.ToString("N0") + "] " + GetBoxPath(type, parent));
            var box = forType(type, inStream.getOffset());

            box.setParams(parent, size, type, offset);
            box.decode(inStream);

            // --- if box doesn't contain data it only contains children ---
            if (box.GetType() == typeof(BoxImpl) || box.GetType() == typeof(FullBox))
            {
                box.readChildren(inStream);
            }

            // --- check bytes left ---
            long left = (box.getOffset() + box.getSize()) - inStream.getOffset();

            if (left > 0)
            {
                if (!(box is MediaDataBox) && !(box is UnknownBox) && !(box is FreeSpaceBox))
                {
                    Logger.LogInfo(string.Format("bytes left after reading box {0}: left: {1}, offset: {2}", typeToString(type), left, inStream.getOffset()));
                }

                // --- skip left Data ---
                inStream.skipBytes(left);
            }
            else if (left < 0)
            {
                Logger.LogServe(string.Format("box {0} overread: {1} bytes, offset: {2}", typeToString(type), -left, inStream.getOffset()));
            }

            return(box);
        }
예제 #6
0
 protected long getLeft(MP4InputStream inStream)
 {
     return((offset + size) - inStream.getOffset());
 }