1
package org.jaudiotagger.audio.mp4;
3
import org.jaudiotagger.audio.exceptions.CannotReadException;
4
import org.jaudiotagger.audio.exceptions.NullBoxIdException;
5
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
6
import org.jaudiotagger.audio.mp4.atom.Mp4MetaBox;
7
import org.jaudiotagger.audio.mp4.atom.Mp4StcoBox;
8
import org.jaudiotagger.audio.mp4.atom.NullPadding;
9
import org.jaudiotagger.logging.ErrorMessage;
11
import javax.swing.tree.DefaultMutableTreeNode;
12
import javax.swing.tree.DefaultTreeModel;
13
import java.io.IOException;
14
import java.io.RandomAccessFile;
15
import java.nio.ByteBuffer;
16
import java.nio.channels.FileChannel;
17
import java.util.ArrayList;
18
import java.util.Enumeration;
19
import java.util.List;
20
import java.util.logging.Logger;
23
* Tree representing atoms in the mp4 file
25
* Note it doesn't create the complete tree it delves into subtrees for atom we know about and are interested in. (Note
26
* it would be impossible to create a complete tree for any file without understanding all the nodes because
27
* some atoms such as meta contain data and children and therefore need to be specially preprocessed)
29
* This class is currently only used when writing tags because it better handles the difficulties of mdat aand free
30
* atoms being optional/multiple places then the older sequential method. It is expected this class will eventually
31
* be used when reading tags as well.
33
* Uses a TreeModel for the tree, with convenience methods holding onto references to most common nodes so they
34
* can be used without having to traverse the tree again.
36
public class Mp4AtomTree
38
private DefaultMutableTreeNode rootNode;
39
private DefaultTreeModel dataTree;
40
private DefaultMutableTreeNode moovNode;
41
private DefaultMutableTreeNode mdatNode;
42
private DefaultMutableTreeNode stcoNode;
43
private DefaultMutableTreeNode ilstNode;
44
private DefaultMutableTreeNode metaNode;
45
private DefaultMutableTreeNode udtaNode;
46
private DefaultMutableTreeNode hdlrWithinMdiaNode;
47
private DefaultMutableTreeNode hdlrWithinMetaNode;
48
private List<DefaultMutableTreeNode> freeNodes = new ArrayList<DefaultMutableTreeNode>();
49
private List<DefaultMutableTreeNode> mdatNodes = new ArrayList<DefaultMutableTreeNode>();
50
private List<DefaultMutableTreeNode> trakNodes = new ArrayList<DefaultMutableTreeNode>();
52
private Mp4StcoBox stco;
53
private ByteBuffer moovBuffer; //Contains all the data under moov
54
private Mp4BoxHeader moovHeader;
57
public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp4");
64
* @throws CannotReadException
66
public Mp4AtomTree(RandomAccessFile raf) throws IOException, CannotReadException
72
* Create Atom Tree and maintain open channel to raf, should only be used if will continue
73
* to use raf after this call, you will have to close raf yourself.
76
* @param closeOnExit to keep randomfileaccess open, only used when randomaccessfile already being used
78
* @throws CannotReadException
80
public Mp4AtomTree(RandomAccessFile raf, boolean closeOnExit) throws IOException, CannotReadException
82
buildTree(raf, closeOnExit);
86
* Build a tree of the atoms in the file
89
* @param closeExit false to keep randomfileacces open, only used when randomaccessfile already being used
91
* @throws java.io.IOException
92
* @throws org.jaudiotagger.audio.exceptions.CannotReadException
94
public DefaultTreeModel buildTree(RandomAccessFile raf, boolean closeExit) throws IOException, CannotReadException
96
FileChannel fc = null;
99
fc = raf.getChannel();
101
//make sure at start of file
104
//Build up map of nodes
105
rootNode = new DefaultMutableTreeNode();
106
dataTree = new DefaultTreeModel(rootNode);
108
//Iterate though all the top level Nodes
109
ByteBuffer headerBuffer = ByteBuffer.allocate(Mp4BoxHeader.HEADER_LENGTH);
110
while (fc.position() < fc.size())
112
Mp4BoxHeader boxHeader = new Mp4BoxHeader();
113
headerBuffer.clear();
114
fc.read(headerBuffer);
115
headerBuffer.rewind();
119
boxHeader.update(headerBuffer);
121
catch(NullBoxIdException ne)
123
//If we only get this error after all the expected data has been found we allow it
124
if(moovNode!=null&mdatNode!=null)
126
NullPadding np = new NullPadding(fc.position() - Mp4BoxHeader.HEADER_LENGTH,fc.size());
127
DefaultMutableTreeNode trailingPaddingNode = new DefaultMutableTreeNode(np);
128
rootNode.add(trailingPaddingNode);
129
logger.warning(ErrorMessage.NULL_PADDING_FOUND_AT_END_OF_MP4.getMsg(np.getFilePos()));
134
//File appears invalid
139
boxHeader.setFilePos(fc.position() - Mp4BoxHeader.HEADER_LENGTH);
140
DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader);
143
if (boxHeader.getId().equals(Mp4NotMetaFieldKey.MOOV.getFieldName()))
146
moovHeader = boxHeader;
148
long filePosStart = fc.position();
149
moovBuffer = ByteBuffer.allocate(boxHeader.getDataLength());
153
/*Maybe needed but dont have test case yet
154
if(filePosStart + boxHeader.getDataLength() > fc.size())
156
throw new CannotReadException("The atom states its datalength to be "+boxHeader.getDataLength()
157
+ "but there are only "+fc.size()+"bytes in the file and already at position "+filePosStart);
160
buildChildrenOfNode(moovBuffer, newAtom);
161
fc.position(filePosStart);
163
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.FREE.getFieldName()))
165
//Might be multiple in different locations
166
freeNodes.add(newAtom);
168
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.MDAT.getFieldName()))
170
//mdatNode always points to the last mDatNode, normally there is just one mdatnode but do have
171
//a valid example of multiple mdatnode
175
// throw new CannotReadException(ErrorMessage.MP4_FILE_CONTAINS_MULTIPLE_DATA_ATOMS.getMsg());
178
mdatNodes.add(newAtom);
180
rootNode.add(newAtom);
181
fc.position(fc.position() + boxHeader.getDataLength());
187
//If we cant find the audio then we cannot modify this file so better to throw exception
188
//now rather than later when try and write to it.
191
throw new CannotReadException(ErrorMessage.MP4_CANNOT_FIND_AUDIO.getMsg());
204
@SuppressWarnings("unchecked")
205
public void printAtomTree()
207
Enumeration<DefaultMutableTreeNode> e = rootNode.preorderEnumeration();
208
DefaultMutableTreeNode nextNode;
209
while (e.hasMoreElements())
211
nextNode = e.nextElement();
212
Mp4BoxHeader header = (Mp4BoxHeader) nextNode.getUserObject();
216
for (int i = 1; i < nextNode.getLevel(); i++)
221
if(header instanceof NullPadding)
223
System.out.println(tabbing + "Null pad " + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength()));
227
System.out.println(tabbing + "Atom " + header.getId() + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength()));
237
* @throws IOException
238
* @throws CannotReadException
240
public void buildChildrenOfNode(ByteBuffer moovBuffer, DefaultMutableTreeNode parentNode) throws IOException, CannotReadException
242
Mp4BoxHeader boxHeader;
244
//Preprocessing for nodes that contain data before their children atoms
245
Mp4BoxHeader parentBoxHeader = (Mp4BoxHeader) parentNode.getUserObject();
247
//We set the buffers position back to this after processing the chikdren
248
int justAfterHeaderPos = moovBuffer.position();
250
//Preprocessing for meta that normally contains 4 data bytes, but doesnt whre found under trak atom
251
//TODO is it always under TRAK dont really know the rule
252
if (parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName()))
254
Mp4MetaBox meta = new Mp4MetaBox(parentBoxHeader, moovBuffer);
259
boxHeader = new Mp4BoxHeader(moovBuffer);
261
catch(NullBoxIdException nbe)
263
//It might be that the meta box didnt actually have any additional data after it so we adjust the buffer
264
//to be immediately after metabox and code can retry
265
moovBuffer.position(moovBuffer.position()-Mp4MetaBox.FLAGS_LENGTH);
269
//Skip back last header cos this was only a test
270
moovBuffer.position(moovBuffer.position()- Mp4BoxHeader.HEADER_LENGTH);
274
//Defines where to start looking for the first child node
275
int startPos = moovBuffer.position();
276
while (moovBuffer.position() < ((startPos + parentBoxHeader.getDataLength()) - Mp4BoxHeader.HEADER_LENGTH))
278
boxHeader = new Mp4BoxHeader(moovBuffer);
279
if (boxHeader != null)
281
boxHeader.setFilePos(moovHeader.getFilePos() + moovBuffer.position());
282
logger.finest("Atom " + boxHeader.getId() + " @ " + boxHeader.getFilePos() + " of size:" + boxHeader.getLength() + " ,ends @ " + (boxHeader.getFilePos() + boxHeader.getLength()));
284
DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader);
285
parentNode.add(newAtom);
287
if (boxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
291
//only interested in metaNode that is child of udta node
292
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())&&parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
296
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.HDLR.getFieldName())&&parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName()))
298
hdlrWithinMetaNode = newAtom;
300
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.HDLR.getFieldName()))
302
hdlrWithinMdiaNode = newAtom;
304
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.STCO.getFieldName()))
308
stco = new Mp4StcoBox(boxHeader, moovBuffer);
312
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.ILST.getFieldName()))
314
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)parentNode.getParent();
317
Mp4BoxHeader parentsParent = (Mp4BoxHeader)(parent).getUserObject();
318
if(parentsParent!=null)
320
if(parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())&&parentsParent.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
327
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.FREE.getFieldName()))
329
//Might be multiple in different locations
330
freeNodes.add(newAtom);
332
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.TRAK.getFieldName()))
334
//Might be multiple in different locations, although onely one shoud be audio track
335
trakNodes.add(newAtom);
338
//For these atoms iterate down to build their children
339
if ((boxHeader.getId().equals(Mp4NotMetaFieldKey.TRAK.getFieldName())) ||
340
(boxHeader.getId().equals(Mp4NotMetaFieldKey.MDIA.getFieldName())) ||
341
(boxHeader.getId().equals(Mp4NotMetaFieldKey.MINF.getFieldName())) ||
342
(boxHeader.getId().equals(Mp4NotMetaFieldKey.STBL.getFieldName())) ||
343
(boxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName())) ||
344
(boxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())) ||
345
(boxHeader.getId().equals(Mp4NotMetaFieldKey.ILST.getFieldName())))
347
buildChildrenOfNode(moovBuffer, newAtom);
349
//Now adjust buffer for the next atom header at this level
350
moovBuffer.position(moovBuffer.position() + boxHeader.getDataLength());
354
moovBuffer.position(justAfterHeaderPos);
362
public DefaultTreeModel getDataTree()
372
public DefaultMutableTreeNode getMoovNode()
381
public DefaultMutableTreeNode getStcoNode()
390
public DefaultMutableTreeNode getIlstNode()
400
public Mp4BoxHeader getBoxHeader(DefaultMutableTreeNode node)
406
return (Mp4BoxHeader) node.getUserObject();
413
public DefaultMutableTreeNode getMdatNode()
422
public DefaultMutableTreeNode getUdtaNode()
431
public DefaultMutableTreeNode getMetaNode()
440
public DefaultMutableTreeNode getHdlrWithinMetaNode()
442
return hdlrWithinMetaNode;
449
public DefaultMutableTreeNode getHdlrWithinMdiaNode()
451
return hdlrWithinMdiaNode;
458
public List<DefaultMutableTreeNode> getFreeNodes()
467
public List<DefaultMutableTreeNode> getTrakNodes()
476
public Mp4StcoBox getStco()
485
public ByteBuffer getMoovBuffer()
494
public Mp4BoxHeader getMoovHeader()
1
package org.jaudiotagger.audio.mp4;
3
import org.jaudiotagger.audio.exceptions.CannotReadException;
4
import org.jaudiotagger.audio.exceptions.NullBoxIdException;
5
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
6
import org.jaudiotagger.audio.mp4.atom.Mp4MetaBox;
7
import org.jaudiotagger.audio.mp4.atom.Mp4StcoBox;
8
import org.jaudiotagger.audio.mp4.atom.NullPadding;
9
import org.jaudiotagger.logging.ErrorMessage;
11
import javax.swing.tree.DefaultMutableTreeNode;
12
import javax.swing.tree.DefaultTreeModel;
13
import java.io.IOException;
14
import java.io.RandomAccessFile;
15
import java.nio.ByteBuffer;
16
import java.nio.channels.FileChannel;
17
import java.util.ArrayList;
18
import java.util.Enumeration;
19
import java.util.List;
20
import java.util.logging.Logger;
23
* Tree representing atoms in the mp4 file
25
* Note it doesn't create the complete tree it delves into subtrees for atom we know about and are interested in. (Note
26
* it would be impossible to create a complete tree for any file without understanding all the nodes because
27
* some atoms such as meta contain data and children and therefore need to be specially preprocessed)
29
* This class is currently only used when writing tags because it better handles the difficulties of mdat aand free
30
* atoms being optional/multiple places then the older sequential method. It is expected this class will eventually
31
* be used when reading tags as well.
33
* Uses a TreeModel for the tree, with convenience methods holding onto references to most common nodes so they
34
* can be used without having to traverse the tree again.
36
public class Mp4AtomTree
38
private DefaultMutableTreeNode rootNode;
39
private DefaultTreeModel dataTree;
40
private DefaultMutableTreeNode moovNode;
41
private DefaultMutableTreeNode mdatNode;
42
private DefaultMutableTreeNode stcoNode;
43
private DefaultMutableTreeNode ilstNode;
44
private DefaultMutableTreeNode metaNode;
45
private DefaultMutableTreeNode udtaNode;
46
private DefaultMutableTreeNode hdlrWithinMdiaNode;
47
private DefaultMutableTreeNode hdlrWithinMetaNode;
48
private List<DefaultMutableTreeNode> freeNodes = new ArrayList<DefaultMutableTreeNode>();
49
private List<DefaultMutableTreeNode> mdatNodes = new ArrayList<DefaultMutableTreeNode>();
50
private List<DefaultMutableTreeNode> trakNodes = new ArrayList<DefaultMutableTreeNode>();
52
private Mp4StcoBox stco;
53
private ByteBuffer moovBuffer; //Contains all the data under moov
54
private Mp4BoxHeader moovHeader;
57
public static Logger logger = Logger.getLogger("org.jaudiotagger.audio.mp4");
64
* @throws CannotReadException
66
public Mp4AtomTree(RandomAccessFile raf) throws IOException, CannotReadException
72
* Create Atom Tree and maintain open channel to raf, should only be used if will continue
73
* to use raf after this call, you will have to close raf yourself.
76
* @param closeOnExit to keep randomfileaccess open, only used when randomaccessfile already being used
78
* @throws CannotReadException
80
public Mp4AtomTree(RandomAccessFile raf, boolean closeOnExit) throws IOException, CannotReadException
82
buildTree(raf, closeOnExit);
86
* Build a tree of the atoms in the file
89
* @param closeExit false to keep randomfileacces open, only used when randomaccessfile already being used
91
* @throws java.io.IOException
92
* @throws org.jaudiotagger.audio.exceptions.CannotReadException
94
public DefaultTreeModel buildTree(RandomAccessFile raf, boolean closeExit) throws IOException, CannotReadException
96
FileChannel fc = null;
99
fc = raf.getChannel();
101
//make sure at start of file
104
//Build up map of nodes
105
rootNode = new DefaultMutableTreeNode();
106
dataTree = new DefaultTreeModel(rootNode);
108
//Iterate though all the top level Nodes
109
ByteBuffer headerBuffer = ByteBuffer.allocate(Mp4BoxHeader.HEADER_LENGTH);
110
while (fc.position() < fc.size())
112
Mp4BoxHeader boxHeader = new Mp4BoxHeader();
113
headerBuffer.clear();
114
fc.read(headerBuffer);
115
headerBuffer.rewind();
119
boxHeader.update(headerBuffer);
121
catch(NullBoxIdException ne)
123
//If we only get this error after all the expected data has been found we allow it
124
if(moovNode!=null&mdatNode!=null)
126
NullPadding np = new NullPadding(fc.position() - Mp4BoxHeader.HEADER_LENGTH,fc.size());
127
DefaultMutableTreeNode trailingPaddingNode = new DefaultMutableTreeNode(np);
128
rootNode.add(trailingPaddingNode);
129
logger.warning(ErrorMessage.NULL_PADDING_FOUND_AT_END_OF_MP4.getMsg(np.getFilePos()));
134
//File appears invalid
139
boxHeader.setFilePos(fc.position() - Mp4BoxHeader.HEADER_LENGTH);
140
DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader);
143
if (boxHeader.getId().equals(Mp4NotMetaFieldKey.MOOV.getFieldName()))
146
moovHeader = boxHeader;
148
long filePosStart = fc.position();
149
moovBuffer = ByteBuffer.allocate(boxHeader.getDataLength());
153
/*Maybe needed but dont have test case yet
154
if(filePosStart + boxHeader.getDataLength() > fc.size())
156
throw new CannotReadException("The atom states its datalength to be "+boxHeader.getDataLength()
157
+ "but there are only "+fc.size()+"bytes in the file and already at position "+filePosStart);
160
buildChildrenOfNode(moovBuffer, newAtom);
161
fc.position(filePosStart);
163
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.FREE.getFieldName()))
165
//Might be multiple in different locations
166
freeNodes.add(newAtom);
168
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.MDAT.getFieldName()))
170
//mdatNode always points to the last mDatNode, normally there is just one mdatnode but do have
171
//a valid example of multiple mdatnode
175
// throw new CannotReadException(ErrorMessage.MP4_FILE_CONTAINS_MULTIPLE_DATA_ATOMS.getMsg());
178
mdatNodes.add(newAtom);
180
rootNode.add(newAtom);
181
fc.position(fc.position() + boxHeader.getDataLength());
187
//If we cant find the audio then we cannot modify this file so better to throw exception
188
//now rather than later when try and write to it.
191
throw new CannotReadException(ErrorMessage.MP4_CANNOT_FIND_AUDIO.getMsg());
204
@SuppressWarnings("unchecked")
205
public void printAtomTree()
207
Enumeration<DefaultMutableTreeNode> e = rootNode.preorderEnumeration();
208
DefaultMutableTreeNode nextNode;
209
while (e.hasMoreElements())
211
nextNode = e.nextElement();
212
Mp4BoxHeader header = (Mp4BoxHeader) nextNode.getUserObject();
216
for (int i = 1; i < nextNode.getLevel(); i++)
221
if(header instanceof NullPadding)
223
System.out.println(tabbing + "Null pad " + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength()));
227
System.out.println(tabbing + "Atom " + header.getId() + " @ " + header.getFilePos() + " of size:" + header.getLength() + " ,ends @ " + (header.getFilePos() + header.getLength()));
237
* @throws IOException
238
* @throws CannotReadException
240
public void buildChildrenOfNode(ByteBuffer moovBuffer, DefaultMutableTreeNode parentNode) throws IOException, CannotReadException
242
Mp4BoxHeader boxHeader;
244
//Preprocessing for nodes that contain data before their children atoms
245
Mp4BoxHeader parentBoxHeader = (Mp4BoxHeader) parentNode.getUserObject();
247
//We set the buffers position back to this after processing the chikdren
248
int justAfterHeaderPos = moovBuffer.position();
250
//Preprocessing for meta that normally contains 4 data bytes, but doesnt whre found under trak atom
251
//TODO is it always under TRAK dont really know the rule
252
if (parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName()))
254
Mp4MetaBox meta = new Mp4MetaBox(parentBoxHeader, moovBuffer);
259
boxHeader = new Mp4BoxHeader(moovBuffer);
261
catch(NullBoxIdException nbe)
263
//It might be that the meta box didnt actually have any additional data after it so we adjust the buffer
264
//to be immediately after metabox and code can retry
265
moovBuffer.position(moovBuffer.position()-Mp4MetaBox.FLAGS_LENGTH);
269
//Skip back last header cos this was only a test
270
moovBuffer.position(moovBuffer.position()- Mp4BoxHeader.HEADER_LENGTH);
274
//Defines where to start looking for the first child node
275
int startPos = moovBuffer.position();
276
while (moovBuffer.position() < ((startPos + parentBoxHeader.getDataLength()) - Mp4BoxHeader.HEADER_LENGTH))
278
boxHeader = new Mp4BoxHeader(moovBuffer);
279
if (boxHeader != null)
281
boxHeader.setFilePos(moovHeader.getFilePos() + moovBuffer.position());
282
logger.finest("Atom " + boxHeader.getId() + " @ " + boxHeader.getFilePos() + " of size:" + boxHeader.getLength() + " ,ends @ " + (boxHeader.getFilePos() + boxHeader.getLength()));
284
DefaultMutableTreeNode newAtom = new DefaultMutableTreeNode(boxHeader);
285
parentNode.add(newAtom);
287
if (boxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
291
//only interested in metaNode that is child of udta node
292
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())&&parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
296
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.HDLR.getFieldName())&&parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName()))
298
hdlrWithinMetaNode = newAtom;
300
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.HDLR.getFieldName()))
302
hdlrWithinMdiaNode = newAtom;
304
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.STCO.getFieldName()))
308
stco = new Mp4StcoBox(boxHeader, moovBuffer);
312
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.ILST.getFieldName()))
314
DefaultMutableTreeNode parent = (DefaultMutableTreeNode)parentNode.getParent();
317
Mp4BoxHeader parentsParent = (Mp4BoxHeader)(parent).getUserObject();
318
if(parentsParent!=null)
320
if(parentBoxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())&&parentsParent.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName()))
327
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.FREE.getFieldName()))
329
//Might be multiple in different locations
330
freeNodes.add(newAtom);
332
else if (boxHeader.getId().equals(Mp4NotMetaFieldKey.TRAK.getFieldName()))
334
//Might be multiple in different locations, although onely one shoud be audio track
335
trakNodes.add(newAtom);
338
//For these atoms iterate down to build their children
339
if ((boxHeader.getId().equals(Mp4NotMetaFieldKey.TRAK.getFieldName())) ||
340
(boxHeader.getId().equals(Mp4NotMetaFieldKey.MDIA.getFieldName())) ||
341
(boxHeader.getId().equals(Mp4NotMetaFieldKey.MINF.getFieldName())) ||
342
(boxHeader.getId().equals(Mp4NotMetaFieldKey.STBL.getFieldName())) ||
343
(boxHeader.getId().equals(Mp4NotMetaFieldKey.UDTA.getFieldName())) ||
344
(boxHeader.getId().equals(Mp4NotMetaFieldKey.META.getFieldName())) ||
345
(boxHeader.getId().equals(Mp4NotMetaFieldKey.ILST.getFieldName())))
347
buildChildrenOfNode(moovBuffer, newAtom);
349
//Now adjust buffer for the next atom header at this level
350
moovBuffer.position(moovBuffer.position() + boxHeader.getDataLength());
354
moovBuffer.position(justAfterHeaderPos);
362
public DefaultTreeModel getDataTree()
372
public DefaultMutableTreeNode getMoovNode()
381
public DefaultMutableTreeNode getStcoNode()
390
public DefaultMutableTreeNode getIlstNode()
400
public Mp4BoxHeader getBoxHeader(DefaultMutableTreeNode node)
406
return (Mp4BoxHeader) node.getUserObject();
413
public DefaultMutableTreeNode getMdatNode()
422
public DefaultMutableTreeNode getUdtaNode()
431
public DefaultMutableTreeNode getMetaNode()
440
public DefaultMutableTreeNode getHdlrWithinMetaNode()
442
return hdlrWithinMetaNode;
449
public DefaultMutableTreeNode getHdlrWithinMdiaNode()
451
return hdlrWithinMdiaNode;
458
public List<DefaultMutableTreeNode> getFreeNodes()
467
public List<DefaultMutableTreeNode> getTrakNodes()
476
public Mp4StcoBox getStco()
485
public ByteBuffer getMoovBuffer()
494
public Mp4BoxHeader getMoovHeader()