• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import com.googlecode.mp4parser.AbstractContainerBox;
20 import com.coremedia.iso.boxes.Box;
21 import com.coremedia.iso.boxes.MovieBox;
22 import com.googlecode.mp4parser.annotations.DoNotParseDetail;
23 
24 import java.io.*;
25 import java.nio.ByteBuffer;
26 import java.nio.channels.FileChannel;
27 import java.nio.channels.ReadableByteChannel;
28 import java.nio.channels.WritableByteChannel;
29 
30 /**
31  * The most upper container for ISO Boxes. It is a container box that is a file.
32  * Uses IsoBufferWrapper  to access the underlying file.
33  */
34 @DoNotParseDetail
35 public class IsoFile extends AbstractContainerBox implements Closeable {
36     protected BoxParser boxParser = new PropertyBoxParserImpl();
37     ReadableByteChannel byteChannel;
38 
IsoFile()39     public IsoFile() {
40         super("");
41     }
42 
IsoFile(File f)43     public IsoFile(File f) throws IOException {
44         super("");
45         this.byteChannel = new FileInputStream(f).getChannel();
46         boxParser = createBoxParser();
47         parse();
48     }
49 
IsoFile(ReadableByteChannel byteChannel)50     public IsoFile(ReadableByteChannel byteChannel) throws IOException {
51         super("");
52         this.byteChannel = byteChannel;
53         boxParser = createBoxParser();
54         parse();
55     }
56 
IsoFile(ReadableByteChannel byteChannel, BoxParser boxParser)57     public IsoFile(ReadableByteChannel byteChannel, BoxParser boxParser) throws IOException {
58         super("");
59         this.byteChannel = byteChannel;
60         this.boxParser = boxParser;
61         parse();
62 
63 
64     }
65 
createBoxParser()66     protected BoxParser createBoxParser() {
67         return new PropertyBoxParserImpl();
68     }
69 
70 
71     @Override
_parseDetails(ByteBuffer content)72     public void _parseDetails(ByteBuffer content) {
73         // there are no details to parse we should be just file
74     }
75 
parse(ReadableByteChannel inFC, ByteBuffer header, long contentSize, AbstractBoxParser abstractBoxParser)76     public void parse(ReadableByteChannel inFC, ByteBuffer header, long contentSize, AbstractBoxParser abstractBoxParser) throws IOException {
77         throw new IOException("This method is not meant to be called. Use #parse() directly.");
78     }
79 
parse()80     private void parse() throws IOException {
81 
82         boolean done = false;
83         while (!done) {
84             try {
85                 Box box = boxParser.parseBox(byteChannel, this);
86                 if (box != null) {
87                     //  System.err.println(box.getType());
88                     boxes.add(box);
89                 } else {
90                     done = true;
91                 }
92             } catch (EOFException e) {
93                 done = true;
94             }
95         }
96     }
97 
98     @DoNotParseDetail
toString()99     public String toString() {
100         StringBuilder buffer = new StringBuilder();
101         buffer.append("IsoFile[");
102         if (boxes == null) {
103             buffer.append("unparsed");
104         } else {
105             for (int i = 0; i < boxes.size(); i++) {
106                 if (i > 0) {
107                     buffer.append(";");
108                 }
109                 buffer.append(boxes.get(i).toString());
110             }
111         }
112         buffer.append("]");
113         return buffer.toString();
114     }
115 
116     @DoNotParseDetail
fourCCtoBytes(String fourCC)117     public static byte[] fourCCtoBytes(String fourCC) {
118         byte[] result = new byte[4];
119         if (fourCC != null) {
120             for (int i = 0; i < Math.min(4, fourCC.length()); i++) {
121                 result[i] = (byte) fourCC.charAt(i);
122             }
123         }
124         return result;
125     }
126 
127     @DoNotParseDetail
bytesToFourCC(byte[] type)128     public static String bytesToFourCC(byte[] type) {
129         byte[] result = new byte[]{0, 0, 0, 0};
130         if (type != null) {
131             System.arraycopy(type, 0, result, 0, Math.min(type.length, 4));
132         }
133         try {
134             return new String(result, "ISO-8859-1");
135         } catch (UnsupportedEncodingException e) {
136             throw new Error("Required character encoding is missing", e);
137         }
138     }
139 
140 
141     @Override
getNumOfBytesToFirstChild()142     public long getNumOfBytesToFirstChild() {
143         return 0;
144     }
145 
146     @Override
getSize()147     public long getSize() {
148         long size = 0;
149         for (Box box : boxes) {
150             size += box.getSize();
151         }
152         return size;
153     }
154 
155     @Override
getIsoFile()156     public IsoFile getIsoFile() {
157         return this;
158     }
159 
160 
161     /**
162      * Shortcut to get the MovieBox since it is often needed and present in
163      * nearly all ISO 14496 files (at least if they are derived from MP4 ).
164      *
165      * @return the MovieBox or <code>null</code>
166      */
167     @DoNotParseDetail
getMovieBox()168     public MovieBox getMovieBox() {
169         for (Box box : boxes) {
170             if (box instanceof MovieBox) {
171                 return (MovieBox) box;
172             }
173         }
174         return null;
175     }
176 
getBox(WritableByteChannel os)177     public void getBox(WritableByteChannel os) throws IOException {
178         for (Box box : boxes) {
179 
180             if (os instanceof FileChannel) {
181                 long startPos = ((FileChannel) os).position();
182                 box.getBox(os);
183                 long size = ((FileChannel) os).position() - startPos;
184                 assert size == box.getSize();
185             } else {
186                 box.getBox(os);
187             }
188 
189         }
190     }
191 
close()192     public void close() throws IOException {
193         this.byteChannel.close();
194     }
195 }
196