-
Notifications
You must be signed in to change notification settings - Fork 3
/
Mp4TagCreator.java
150 lines (142 loc) · 5.83 KB
/
Mp4TagCreator.java
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
/*
* Entagged Audio Tag library
* Copyright (c) 2003-2005 Raphaël Slinckx <raphael@slinckx.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jaudiotagger.tag.mp4;
import org.jaudiotagger.audio.generic.AbstractTagCreator;
import org.jaudiotagger.audio.generic.Utils;
import org.jaudiotagger.audio.mp4.Mp4AtomIdentifier;
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.KeyNotFoundException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagField;
import org.jaudiotagger.tag.mp4.field.Mp4TagCoverField;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Iterator;
/**
* Create raw content of mp4 tag data, concerns itself with atoms upto the ilst atom
* <p/>
* <p>This level is was selected because the ilst atom can be recreated without reference to existing mp4 fields
* but fields above this level are dependent upon other information that is not held in the tag.
* <p/>
* <pre>
* |--- ftyp
* |--- moov
* |......|
* |......|----- mvdh
* |......|----- trak
* |......|----- udta
* |..............|
* |..............|-- meta
* |....................|
* |....................|-- hdlr
* |....................|-- ilst
* |....................|.. ..|
* |....................|.....|---- @nam (Optional for each metadatafield)
* |....................|.....|.......|-- data
* |....................|.....|....... ecetera
* |....................|.....|---- ---- (Optional for reverse dns field)
* |....................|.............|-- mean
* |....................|.............|-- name
* |....................|.............|-- data
* |....................|................ ecetere
* |....................|-- free
* |--- free
* |--- mdat
* </pre>
*/
public class Mp4TagCreator extends AbstractTagCreator
{
/**
* Convert tagdata to rawdata ready for writing to file
*
* @param tag
* @param padding TODO padding parameter currently ignored
* @return
* @throws UnsupportedEncodingException
*/
public ByteBuffer convert(Tag tag, int padding) throws UnsupportedEncodingException
{
try
{
//Add metadata raw content
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Iterator<TagField> it = tag.getFields();
boolean processedArtwork = false;
while (it.hasNext())
{
TagField frame = it.next();
//To ensure order is maintained dont process artwork until iterator hits it.
if (frame instanceof Mp4TagCoverField)
{
if (processedArtwork)
{
//ignore
}
else
{
processedArtwork = true;
//Because each artwork image is held within the tag as a separate field, but when
//they are written they are all held under a single covr box we need to do some checks
//and special processing here if we have any artwork image (this code only necessary
//if we have more than 1 but do it anyway even if only have 1 image)
ByteArrayOutputStream covrDataBaos = new ByteArrayOutputStream();
try
{
for (TagField artwork : tag.getFields(FieldKey.COVER_ART))
{
covrDataBaos.write(((Mp4TagField) artwork).getRawContentDataOnly());
}
}
catch (KeyNotFoundException knfe)
{
//This cannot happen
throw new RuntimeException("Unable to find COVERART Key");
}
//Now create the parent Data
byte[] data = covrDataBaos.toByteArray();
baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + data.length));
baos.write(Utils.getDefaultBytes(Mp4FieldKey.ARTWORK.getFieldName(), "ISO-8859-1"));
baos.write(data);
}
}
else
{
baos.write(frame.getRawContent());
}
}
//Wrap into ilst box
ByteArrayOutputStream ilst = new ByteArrayOutputStream();
ilst.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
ilst.write(Utils.getDefaultBytes(Mp4AtomIdentifier.ILST.getFieldName(), "ISO-8859-1"));
ilst.write(baos.toByteArray());
//Put into ByteBuffer
ByteBuffer buf = ByteBuffer.wrap(ilst.toByteArray());
buf.rewind();
return buf;
}
catch (IOException ioe)
{
//Should never happen as not writing to file at this point
throw new RuntimeException(ioe);
}
}
}