/* * Copyright 2008 CoreMedia AG, Hamburg * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.coremedia.iso; import com.coremedia.iso.boxes.AbstractContainerBox; import com.coremedia.iso.boxes.Box; import com.coremedia.iso.boxes.MovieBox; import com.coremedia.iso.boxes.fragment.MovieFragmentBox; import java.io.IOException; import java.nio.charset.Charset; /** * The most upper container for ISO Boxes. It is a container box that is a file. * Uses IsoBufferWrapper to access the underlying file. */ public class IsoFile extends AbstractContainerBox { protected BoxParser boxParser = new PropertyBoxParserImpl(); protected IsoBufferWrapper originalIso; public IsoFile(IsoBufferWrapper originalIso) { super(new byte[]{}); boxParser = createBoxParser(); this.originalIso = originalIso; } public IsoFile(IsoBufferWrapper originalIso, BoxParser boxParser) { this(originalIso); this.boxParser = boxParser; } protected BoxParser createBoxParser() { return new PropertyBoxParserImpl(); } @Override public void parse(IsoBufferWrapper in, long size, BoxParser boxParser, Box lastMovieFragmentBox) throws IOException { throw new RuntimeException("This method is not meant to be used. Use parse() instead"); //super.parse(in, size, boxParser, lastMovieFragmentBox); //To change body of overridden methods use File | Settings | File Templates. } public void parse() throws IOException { boolean done = false; Box lastMovieFragmentBox = null; while (!done) { long sp = originalIso.position(); if (originalIso.remaining() >= 8) { Box box = boxParser.parseBox(originalIso, this, lastMovieFragmentBox); if (box != null) { if (box instanceof MovieFragmentBox) lastMovieFragmentBox = box; boxes.add(box); assert box.calculateOffset() == sp : "calculated offset differs from offset in file"; } else { done = true; } } else { done = true; } } parsed = done; } public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append("IsoFile["); if (boxes == null) { buffer.append("unparsed"); } else { for (int i = 0; i < boxes.size(); i++) { if (i > 0) { buffer.append(";"); } buffer.append(boxes.get(i).toString()); } } buffer.append("]"); return buffer.toString(); } public static byte[] fourCCtoBytes(String fourCC) { byte[] result = new byte[4]; if (fourCC != null) { for (int i = 0; i < Math.min(4, fourCC.length()); i++) { result[i] = (byte) fourCC.charAt(i); } } return result; } public static String bytesToFourCC(byte[] type) { byte[] result = new byte[]{0, 0, 0, 0}; if (type != null) { for (int i = 0; i < Math.min(type.length, 4); i++) { result[i] = type[i]; } } return new String(result); //return new String(result, Charset.forName("ISO-8859-1")); } @Override public long getNumOfBytesToFirstChild() { return 0; } @Override public long getSize() { long size = 0; for (Box box : boxes) { size += box.getSize(); } return size; } @Override public long calculateOffset() { return 0; } @Override public long getOffset() { return 0; } @Override public IsoFile getIsoFile() { return this; } @Override protected long getHeaderSize() { return 0; } @Override public byte[] getHeader() { return new byte[0]; } public BoxParser getBoxParser() { return boxParser; } public IsoBufferWrapper getOriginalIso() { return originalIso; } /** * Shortcut to get the MovieBox since it is often needed and present in * nearly all ISO 14496 files (at least if they are derived from MP4 ). * * @return the MovieBox or <code>null</code> */ public MovieBox getMovieBox() { for (Box box : boxes) { if (box instanceof MovieBox) { return (MovieBox) box; } } return null; } }