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