001
014
015 package com.liferay.portlet.documentlibrary.util;
016
017 import com.liferay.portal.kernel.util.ArrayUtil;
018
019 import java.io.IOException;
020 import java.io.RandomAccessFile;
021
022
029 public class Atom {
030
031 public static final String CMOV = "cmov";
032
033 public static final String CO64 = "co64";
034
035 public static final String FREE = "free";
036
037 public static final String FTYP = "ftyp";
038
039 public static final String JUNK = "junk";
040
041 public static final String MDAT = "mdat";
042
043 public static final String MOOV = "moov";
044
045 public static final String PICT = "PICT";
046
047 public static final String PNOT = "pnot";
048
049 public static final String SKIP = "skip";
050
051 public static final String STCO = "stco";
052
053 public static final String[] TOP_LEVEL_ATOMS = {
054 FREE, FTYP, JUNK, MDAT, MOOV, PICT, PNOT, SKIP, Atom.WIDE
055 };
056
057 public static final String WIDE = "wide";
058
059 public Atom(RandomAccessFile randomAccessFile) throws IOException {
060 _offset = randomAccessFile.getFilePointer();
061 _size = randomAccessFile.readInt();
062
063 byte[] bytes = new byte[4];
064
065 randomAccessFile.readFully(bytes);
066
067 _type = new String(bytes);
068
069 if (_size == 1) {
070 _size = randomAccessFile.readLong();
071 }
072
073 randomAccessFile.seek(_offset);
074 }
075
076 public void fillBuffer(RandomAccessFile randomAccessFile)
077 throws IOException {
078
079 _buffer = new byte[(int)_size];
080
081 randomAccessFile.readFully(_buffer);
082 }
083
084 public byte[] getBuffer() {
085 return _buffer;
086 }
087
088 public long getOffset() {
089 return _offset;
090 }
091
092 public long getSize() {
093 return _size;
094 }
095
096 public String getType() {
097 return _type;
098 }
099
100 public boolean isFTYP() {
101 return _type.equalsIgnoreCase(FTYP);
102 }
103
104 public boolean isMDAT() {
105 return _type.equalsIgnoreCase(MDAT);
106 }
107
108 public boolean isMOOV() {
109 return _type.equalsIgnoreCase(MOOV);
110 }
111
112 public boolean isTopLevelAtom() {
113 for (String topLevelAtom : TOP_LEVEL_ATOMS) {
114 if (_type.equalsIgnoreCase(topLevelAtom)) {
115 return true;
116 }
117 }
118
119 return false;
120 }
121
122 public void patchAtom() {
123 for (int index = 4; index < _size - 4; index++) {
124 String type = new String(
125 ArrayUtil.clone(_buffer, index, index + 4));
126
127 if (type.equalsIgnoreCase(Atom.STCO)) {
128 index += patchStcoAtom(index) - 4;
129 }
130 else if (type.equalsIgnoreCase(Atom.CO64)) {
131 index += patchCo64Atom(index) - 4;
132 }
133 }
134 }
135
136 public void setBuffer(byte[] buffer) {
137 _buffer = buffer;
138 }
139
140 public void setOffset(long offset) {
141 _offset = offset;
142 }
143
144 public void setSize(long size) {
145 _size = size;
146 }
147
148 public void setType(String type) {
149 _type = type;
150 }
151
152 protected long bytesToLong(byte[] buffer) {
153 long value = 0;
154
155 for (int i = 0; i < buffer.length; i++) {
156 value += ((buffer[i] & _BITMASK) << 8 * (buffer.length - i - 1));
157 }
158
159 return value;
160 }
161
162 protected boolean hasCompressedMoovAtom() {
163 String type = new String(ArrayUtil.clone(_buffer, 12, 15));
164
165 if (type.equalsIgnoreCase(Atom.CMOV)) {
166 return true;
167 }
168 else {
169 return false;
170 }
171 }
172
173 protected int patchCo64Atom(int index) {
174 int size = (int)bytesToLong(ArrayUtil.clone(_buffer, index - 4, index));
175
176 int offsetCount = (int)bytesToLong(
177 ArrayUtil.clone(_buffer, index + 8, index + 12));
178
179 for (int i = 0; i < offsetCount; i++) {
180 int offsetIndex = index + 12 + i * 8;
181
182 long offset = bytesToLong(
183 ArrayUtil.clone(_buffer, offsetIndex, offsetIndex + 8));
184
185 offset += _size;
186
187 _buffer[offsetIndex + 0] = (byte)((offset >> 56) & 0xFF);
188 _buffer[offsetIndex + 1] = (byte)((offset >> 48) & 0xFF);
189 _buffer[offsetIndex + 2] = (byte)((offset >> 40) & 0xFF);
190 _buffer[offsetIndex + 3] = (byte)((offset >> 32) & 0xFF);
191 _buffer[offsetIndex + 4] = (byte)((offset >> 24) & 0xFF);
192 _buffer[offsetIndex + 5] = (byte)((offset >> 16) & 0xFF);
193 _buffer[offsetIndex + 6] = (byte)((offset >> 8) & 0xFF);
194 _buffer[offsetIndex + 7] = (byte)((offset >> 0) & 0xFF);
195 }
196
197 return size;
198 }
199
200 protected int patchStcoAtom(int index) {
201 int size = (int)bytesToLong(ArrayUtil.clone(_buffer, index - 4, index));
202
203 int offsetCount = (int)bytesToLong(
204 ArrayUtil.clone(_buffer, index + 8, index + 12));
205
206 for (int i = 0; i < offsetCount; i++) {
207 int offsetIndex = index + 12 + i * 4;
208
209 int offset = (int)bytesToLong(
210 ArrayUtil.clone(_buffer, offsetIndex, offsetIndex + 4));
211
212 offset += _size;
213
214 _buffer[offsetIndex + 0] = (byte)((offset >> 24) & 0xFF);
215 _buffer[offsetIndex + 1] = (byte)((offset >> 16) & 0xFF);
216 _buffer[offsetIndex + 2] = (byte)((offset >> 8) & 0xFF);
217 _buffer[offsetIndex + 3] = (byte)((offset >> 0) & 0xFF);
218 }
219
220 return size;
221 }
222
223 private static final int _BITMASK = 0x00000000000000FF;
224
225 private byte[] _buffer;
226 private long _offset;
227 private long _size;
228 private String _type;
229
230 }