1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/* 2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright 2008 CoreMedia AG, Hamburg 3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the License); 5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * you may not use this file except in compliance with the License. 6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * You may obtain a copy of the License at 7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * http://www.apache.org/licenses/LICENSE-2.0 9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software 11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * distributed under the License is distributed on an AS IS BASIS, 12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * See the License for the specific language governing permissions and 14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * limitations under the License. 15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.coremedia.iso.boxes; 18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.BoxParser; 21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.ChannelHelper; 22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeWriter; 23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.AbstractBox; 24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.IOException; 26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer; 27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.channels.FileChannel; 28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.channels.ReadableByteChannel; 29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.channels.WritableByteChannel; 30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.LinkedList; 31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List; 32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport static com.googlecode.mp4parser.util.CastUtils.l2i; 34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/** 36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * A free box. Just a placeholder to enable editing without rewriting the whole file. 37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */ 38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class FreeBox implements Box { 39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public static final String TYPE = "free"; 40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ByteBuffer data; 41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu List<Box> replacers = new LinkedList<Box>(); 42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu private ContainerBox parent; 43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public FreeBox() { 45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public FreeBox(int size) { 48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.data = ByteBuffer.allocate(size); 49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public ByteBuffer getData() { 53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return data; 54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setData(ByteBuffer data) { 57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.data = data; 58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void getBox(WritableByteChannel os) throws IOException { 61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (Box replacer : replacers) { 62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu replacer.getBox(os); 63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ByteBuffer header = ByteBuffer.allocate(8); 65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu IsoTypeWriter.writeUInt32(header, 8 + data.limit()); 66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu header.put(TYPE.getBytes()); 67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu header.rewind(); 68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu os.write(header); 69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu data.rewind(); 70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu os.write(data); 71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public ContainerBox getParent() { 75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return parent; 76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void setParent(ContainerBox parent) { 79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu this.parent = parent; 80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public long getSize() { 83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu long size = 8; 84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu for (Box replacer : replacers) { 85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu size += replacer.getSize(); 86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu size += data.limit(); 88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return size; 89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public String getType() { 92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu return TYPE; 93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { 96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu if (readableByteChannel instanceof FileChannel && contentSize > 1024 * 1024) { 97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu // It's quite expensive to map a file into the memory. Just do it when the box is larger than a MB. 98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu data = ((FileChannel) readableByteChannel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) readableByteChannel).position(), contentSize); 99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); 100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } else { 101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu assert contentSize < Integer.MAX_VALUE; 102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu data = ChannelHelper.readFully(readableByteChannel, contentSize); 103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu public void addAndReplace(Box box) { 108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu data.position(l2i(box.getSize())); 109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu data = data.slice(); 110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu replacers.add(box); 111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu } 112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu 114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu}