summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/coremedia/iso/.svn/text-base/IsoFile.java.svn-base
blob: a6f4b2be393bad7832e954a55673042db55e3ea2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*  
 * 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.googlecode.mp4parser.AbstractContainerBox;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.MovieBox;
import com.googlecode.mp4parser.annotations.DoNotParseDetail;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

/**
 * The most upper container for ISO Boxes. It is a container box that is a file.
 * Uses IsoBufferWrapper  to access the underlying file.
 */
@DoNotParseDetail
public class IsoFile extends AbstractContainerBox implements Closeable {
    protected BoxParser boxParser = new PropertyBoxParserImpl();
    ReadableByteChannel byteChannel;

    public IsoFile() {
        super("");
    }

    public IsoFile(File f) throws IOException {
        super("");
        this.byteChannel = new FileInputStream(f).getChannel();
        boxParser = createBoxParser();
        parse();
    }

    public IsoFile(ReadableByteChannel byteChannel) throws IOException {
        super("");
        this.byteChannel = byteChannel;
        boxParser = createBoxParser();
        parse();
    }

    public IsoFile(ReadableByteChannel byteChannel, BoxParser boxParser) throws IOException {
        super("");
        this.byteChannel = byteChannel;
        this.boxParser = boxParser;
        parse();


    }

    protected BoxParser createBoxParser() {
        return new PropertyBoxParserImpl();
    }


    @Override
    public void _parseDetails(ByteBuffer content) {
        // there are no details to parse we should be just file
    }

    public void parse(ReadableByteChannel inFC, ByteBuffer header, long contentSize, AbstractBoxParser abstractBoxParser) throws IOException {
        throw new IOException("This method is not meant to be called. Use #parse() directly.");
    }

    private void parse() throws IOException {

        boolean done = false;
        while (!done) {
            try {
                Box box = boxParser.parseBox(byteChannel, this);
                if (box != null) {
                    //  System.err.println(box.getType());
                    boxes.add(box);
                } else {
                    done = true;
                }
            } catch (EOFException e) {
                done = true;
            }
        }
    }

    @DoNotParseDetail
    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();
    }

    @DoNotParseDetail
    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;
    }

    @DoNotParseDetail
    public static String bytesToFourCC(byte[] type) {
        byte[] result = new byte[]{0, 0, 0, 0};
        if (type != null) {
            System.arraycopy(type, 0, result, 0, Math.min(type.length, 4));
        }
        try {
            return new String(result, "ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            throw new Error("Required character encoding is missing", e);
        }
    }


    @Override
    public long getNumOfBytesToFirstChild() {
        return 0;
    }

    @Override
    public long getSize() {
        long size = 0;
        for (Box box : boxes) {
            size += box.getSize();
        }
        return size;
    }

    @Override
    public IsoFile getIsoFile() {
        return this;
    }


    /**
     * 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>
     */
    @DoNotParseDetail
    public MovieBox getMovieBox() {
        for (Box box : boxes) {
            if (box instanceof MovieBox) {
                return (MovieBox) box;
            }
        }
        return null;
    }

    public void getBox(WritableByteChannel os) throws IOException {
        for (Box box : boxes) {

            if (os instanceof FileChannel) {
                long startPos = ((FileChannel) os).position();
                box.getBox(os);
                long size = ((FileChannel) os).position() - startPos;
                assert size == box.getSize();
            } else {
                box.getBox(os);
            }

        }
    }

    public void close() throws IOException {
        this.byteChannel.close();
    }
}