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