// --- children --- protected void readChildren(MP4InputStream inStream) { while ((size - (inStream.getOffset() - start)) > 0) { Descriptor desc = createDescriptor(inStream); children.Add(desc); } }
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); }
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); }
protected long getLeft(MP4InputStream inStream) { return((offset + size) - inStream.getOffset()); }