/* * 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.boxes; import com.coremedia.iso.BoxParser; import com.coremedia.iso.ChannelHelper; import com.coremedia.iso.IsoTypeWriter; import com.googlecode.mp4parser.AbstractBox; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.LinkedList; import java.util.List; import static com.googlecode.mp4parser.util.CastUtils.l2i; /** * A free box. Just a placeholder to enable editing without rewriting the whole file. */ public class FreeBox implements Box { public static final String TYPE = "free"; ByteBuffer data; List replacers = new LinkedList(); private ContainerBox parent; public FreeBox() { } public FreeBox(int size) { this.data = ByteBuffer.allocate(size); } public ByteBuffer getData() { return data; } public void setData(ByteBuffer data) { this.data = data; } public void getBox(WritableByteChannel os) throws IOException { for (Box replacer : replacers) { replacer.getBox(os); } ByteBuffer header = ByteBuffer.allocate(8); IsoTypeWriter.writeUInt32(header, 8 + data.limit()); header.put(TYPE.getBytes()); header.rewind(); os.write(header); data.rewind(); os.write(data); } public ContainerBox getParent() { return parent; } public void setParent(ContainerBox parent) { this.parent = parent; } public long getSize() { long size = 8; for (Box replacer : replacers) { size += replacer.getSize(); } size += data.limit(); return size; } public String getType() { return TYPE; } public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException { if (readableByteChannel instanceof FileChannel && contentSize > 1024 * 1024) { // It's quite expensive to map a file into the memory. Just do it when the box is larger than a MB. data = ((FileChannel) readableByteChannel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) readableByteChannel).position(), contentSize); ((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize); } else { assert contentSize < Integer.MAX_VALUE; data = ChannelHelper.readFully(readableByteChannel, contentSize); } } public void addAndReplace(Box box) { data.position(l2i(box.getSize())); data = data.slice(); replacers.add(box); } }