Skip to content
Snippets Groups Projects
Commit 02733524 authored by Leo Ma's avatar Leo Ma
Browse files

Add new files for mp4 parser


Signed-off-by: default avatarLeo Ma <begeekmyfriend@gmail.com>
parent 4b67a064
No related branches found
No related tags found
No related merge requests found
Showing
with 845 additions and 0 deletions
/*
* 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.boxes;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.IsoTypeWriter;
import com.googlecode.mp4parser.AbstractBox;
import java.nio.ByteBuffer;
/**
* Contains a reference to a track. The type of the box gives the kind of reference.
*/
public class TrackReferenceTypeBox extends AbstractBox {
public static final String TYPE1 = "hint";
public static final String TYPE2 = "cdsc";
private long[] trackIds;
public TrackReferenceTypeBox(String type) {
super(type);
}
public long[] getTrackIds() {
return trackIds;
}
@Override
public void _parseDetails(ByteBuffer content) {
int count = (int) (content.remaining() / 4);
trackIds = new long[count];
for (int i = 0; i < count; i++) {
trackIds[i] = IsoTypeReader.readUInt32(content);
}
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
for (long trackId : trackIds) {
IsoTypeWriter.writeUInt32(byteBuffer, trackId);
}
}
protected long getContentSize() {
return trackIds.length * 4;
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("TrackReferenceTypeBox[type=").append(getType());
for (int i = 0; i < trackIds.length; i++) {
buffer.append(";trackId");
buffer.append(i);
buffer.append("=");
buffer.append(trackIds[i]);
}
buffer.append("]");
return buffer.toString();
}
}
/*
* 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.boxes;
import com.googlecode.mp4parser.AbstractBox;
import java.nio.ByteBuffer;
/**
* A box unknown to the ISO Parser. If there is no specific Box implementation for a Box this <code>UnknownBox</code>
* will just hold the box's data.
*/
public class UnknownBox extends AbstractBox {
ByteBuffer data;
public UnknownBox(String type) {
super(type);
}
@Override
protected long getContentSize() {
return data.limit();
}
@Override
public void _parseDetails(ByteBuffer content) {
data = content;
content.position(content.position() + content.remaining());
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
data.rewind();
byteBuffer.put(data);
}
public ByteBuffer getData() {
return data;
}
public void setData(ByteBuffer data) {
this.data = data;
}
}
/*
* 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.boxes;
import com.coremedia.iso.BoxParser;
import com.googlecode.mp4parser.AbstractContainerBox;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
/**
* This box contains objects that declare user information about the containing box and its data (presentation or
* track).<br>
* The User Data Box is a container box for informative user-data. This user data is formatted as a set of boxes
* with more specific box types, which declare more precisely their content
*/
public class UserDataBox extends AbstractContainerBox {
public static final String TYPE = "udta";
@Override
protected long getContentSize() {
return super.getContentSize(); //To change body of overridden methods use File | Settings | File Templates.
}
@Override
public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
super.parse(readableByteChannel, header, contentSize, boxParser); //To change body of overridden methods use File | Settings | File Templates.
}
@Override
public void _parseDetails(ByteBuffer content) {
super._parseDetails(content); //To change body of overridden methods use File | Settings | File Templates.
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
super.getContent(byteBuffer); //To change body of overridden methods use File | Settings | File Templates.
}
public UserDataBox() {
super(TYPE);
}
}
package com.coremedia.iso.boxes;
/**
* The <class>WriteListener</class> is used to get the offset of
* a box before writing the box. This can be used if a box written
* later needs an offset.
*/
public interface WriteListener {
public void beforeWrite(long offset);
}
package com.coremedia.iso.boxes;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.Utf8;
import com.googlecode.mp4parser.AbstractFullBox;
import java.nio.ByteBuffer;
/**
*
*/
public class XmlBox extends AbstractFullBox {
String xml = "";
public static final String TYPE = "xml ";
public XmlBox() {
super(TYPE);
}
public String getXml() {
return xml;
}
public void setXml(String xml) {
this.xml = xml;
}
@Override
protected long getContentSize() {
return 4 + Utf8.utf8StringLengthInBytes(xml);
}
@Override
public void _parseDetails(ByteBuffer content) {
parseVersionAndFlags(content);
xml = IsoTypeReader.readString(content, content.remaining());
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
writeVersionAndFlags(byteBuffer);
byteBuffer.put(Utf8.convert(xml));
}
@Override
public String toString() {
return "XmlBox{" +
"xml='" + xml + '\'' +
'}';
}
}
package com.coremedia.iso.boxes.apple;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.IsoTypeWriter;
import com.coremedia.iso.Utf8;
import com.googlecode.mp4parser.AbstractBox;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.ContainerBox;
import com.googlecode.mp4parser.util.ByteBufferByteChannel;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
/**
*
*/
public abstract class AbstractAppleMetaDataBox extends AbstractBox implements ContainerBox {
private static Logger LOG = Logger.getLogger(AbstractAppleMetaDataBox.class.getName());
AppleDataBox appleDataBox = new AppleDataBox();
public List<Box> getBoxes() {
return Collections.singletonList((Box) appleDataBox);
}
public void setBoxes(List<Box> boxes) {
if (boxes.size() == 1 && boxes.get(0) instanceof AppleDataBox) {
appleDataBox = (AppleDataBox) boxes.get(0);
} else {
throw new IllegalArgumentException("This box only accepts one AppleDataBox child");
}
}
public <T extends Box> List<T> getBoxes(Class<T> clazz) {
return getBoxes(clazz, false);
}
public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) {
//todo recursive?
if (clazz.isAssignableFrom(appleDataBox.getClass())) {
return (List<T>) Collections.singletonList(appleDataBox);
}
return null;
}
public AbstractAppleMetaDataBox(String type) {
super(type);
}
@Override
public void _parseDetails(ByteBuffer content) {
long dataBoxSize = IsoTypeReader.readUInt32(content);
String thisShouldBeData = IsoTypeReader.read4cc(content);
assert "data".equals(thisShouldBeData);
appleDataBox = new AppleDataBox();
try {
appleDataBox.parse(new ByteBufferByteChannel(content), null, content.remaining(), null);
} catch (IOException e) {
throw new RuntimeException(e);
}
appleDataBox.setParent(this);
}
protected long getContentSize() {
return appleDataBox.getSize();
}
protected void getContent(ByteBuffer byteBuffer) {
try {
appleDataBox.getBox(new ByteBufferByteChannel(byteBuffer));
} catch (IOException e) {
throw new RuntimeException("The Channel is based on a ByteBuffer and therefore it shouldn't throw any exception");
}
}
public long getNumOfBytesToFirstChild() {
return getSize() - appleDataBox.getSize();
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" +
"appleDataBox=" + getValue() +
'}';
}
static long toLong(byte b) {
return b < 0 ? b + 256 : b;
}
public void setValue(String value) {
if (appleDataBox.getFlags() == 1) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(1);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(Utf8.convert(value));
} else if (appleDataBox.getFlags() == 21) {
byte[] content = appleDataBox.getData();
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(21);
appleDataBox.setFourBytes(new byte[4]);
ByteBuffer bb = ByteBuffer.allocate(content.length);
if (content.length == 1) {
IsoTypeWriter.writeUInt8(bb, (Byte.parseByte(value) & 0xFF));
} else if (content.length == 2) {
IsoTypeWriter.writeUInt16(bb, Integer.parseInt(value));
} else if (content.length == 4) {
IsoTypeWriter.writeUInt32(bb, Long.parseLong(value));
} else if (content.length == 8) {
IsoTypeWriter.writeUInt64(bb, Long.parseLong(value));
} else {
throw new Error("The content length within the appleDataBox is neither 1, 2, 4 or 8. I can't handle that!");
}
appleDataBox.setData(bb.array());
} else if (appleDataBox.getFlags() == 0) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(0);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(hexStringToByteArray(value));
} else {
LOG.warning("Don't know how to handle appleDataBox with flag=" + appleDataBox.getFlags());
}
}
public String getValue() {
if (appleDataBox.getFlags() == 1) {
return Utf8.convert(appleDataBox.getData());
} else if (appleDataBox.getFlags() == 21) {
byte[] content = appleDataBox.getData();
long l = 0;
int current = 1;
int length = content.length;
for (byte b : content) {
l += toLong(b) << (8 * (length - current++));
}
return "" + l;
} else if (appleDataBox.getFlags() == 0) {
return String.format("%x", new BigInteger(appleDataBox.getData()));
} else {
return "unknown";
}
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
package com.coremedia.iso.boxes.apple;
/**
* itunes MetaData comment box.
*/
public class AppleAlbumArtistBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "aART";
public AppleAlbumArtistBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
/**
*
*/
public final class AppleAlbumBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "\u00a9alb";
public AppleAlbumBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
/**
* iTunes Artist box.
*/
public final class AppleArtistBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "\u00a9ART";
public AppleArtistBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
package com.coremedia.iso.boxes.apple;
/**
* itunes MetaData comment box.
*/
public final class AppleCommentBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "\u00a9cmt";
public AppleCommentBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
package com.coremedia.iso.boxes.apple;
/**
* Compilation.
*/
public final class AppleCompilationBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "cpil";
public AppleCompilationBox() {
super(TYPE);
appleDataBox = AppleDataBox.getUint8AppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
/**
* itunes MetaData comment box.
*/
public final class AppleCopyrightBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "cprt";
public AppleCopyrightBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
import java.util.logging.Logger;
/**
*
*/
public final class AppleCoverBox extends AbstractAppleMetaDataBox {
private static Logger LOG = Logger.getLogger(AppleCoverBox.class.getName());
public static final String TYPE = "covr";
public AppleCoverBox() {
super(TYPE);
}
public void setPng(byte[] pngData) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(0xe);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(pngData);
}
public void setJpg(byte[] jpgData) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(0xd);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(jpgData);
}
@Override
public void setValue(String value) {
LOG.warning("---");
}
@Override
public String getValue() {
return "---";
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
import com.coremedia.iso.Utf8;
/**
*
*/
public final class AppleCustomGenreBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "\u00a9gen";
public AppleCustomGenreBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
public void setGenre(String genre) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(1);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(Utf8.convert(genre));
}
public String getGenre() {
return Utf8.convert(appleDataBox.getData());
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
import com.googlecode.mp4parser.AbstractFullBox;
import java.nio.ByteBuffer;
/**
* Most stupid box of the world. Encapsulates actual data within
*/
public final class AppleDataBox extends AbstractFullBox {
public static final String TYPE = "data";
private byte[] fourBytes = new byte[4];
private byte[] data;
private static AppleDataBox getEmpty() {
AppleDataBox appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFourBytes(new byte[4]);
return appleDataBox;
}
public static AppleDataBox getStringAppleDataBox() {
AppleDataBox appleDataBox = getEmpty();
appleDataBox.setFlags(1);
appleDataBox.setData(new byte[]{0});
return appleDataBox;
}
public static AppleDataBox getUint8AppleDataBox() {
AppleDataBox appleDataBox = new AppleDataBox();
appleDataBox.setFlags(21);
appleDataBox.setData(new byte[]{0});
return appleDataBox;
}
public static AppleDataBox getUint16AppleDataBox() {
AppleDataBox appleDataBox = new AppleDataBox();
appleDataBox.setFlags(21);
appleDataBox.setData(new byte[]{0, 0});
return appleDataBox;
}
public static AppleDataBox getUint32AppleDataBox() {
AppleDataBox appleDataBox = new AppleDataBox();
appleDataBox.setFlags(21);
appleDataBox.setData(new byte[]{0, 0, 0, 0});
return appleDataBox;
}
public AppleDataBox() {
super(TYPE);
}
protected long getContentSize() {
return data.length + 8;
}
public void setData(byte[] data) {
this.data = new byte[data.length];
System.arraycopy(data, 0, this.data, 0, data.length);
}
public void setFourBytes(byte[] fourBytes) {
System.arraycopy(fourBytes, 0, this.fourBytes, 0, 4);
}
@Override
public void _parseDetails(ByteBuffer content) {
parseVersionAndFlags(content);
fourBytes = new byte[4];
content.get(fourBytes);
data = new byte[content.remaining()];
content.get(data);
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
writeVersionAndFlags(byteBuffer);
byteBuffer.put(fourBytes, 0, 4);
byteBuffer.put(data);
}
public byte[] getFourBytes() {
return fourBytes;
}
public byte[] getData() {
return data;
}
}
/*
* Copyright 2009 castLabs GmbH, Berlin
*
* 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.boxes.apple;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.IsoTypeWriter;
import com.googlecode.mp4parser.AbstractFullBox;
import java.nio.ByteBuffer;
public class AppleDataRateBox extends AbstractFullBox {
public static final String TYPE = "rmdr";
private long dataRate;
public AppleDataRateBox() {
super(TYPE);
}
protected long getContentSize() {
return 8;
}
@Override
public void _parseDetails(ByteBuffer content) {
parseVersionAndFlags(content);
dataRate = IsoTypeReader.readUInt32(content);
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
writeVersionAndFlags(byteBuffer);
IsoTypeWriter.writeUInt32(byteBuffer, dataRate);
}
public long getDataRate() {
return dataRate;
}
}
/*
* Copyright 2009 castLabs GmbH, Berlin
*
* 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.boxes.apple;
import com.coremedia.iso.IsoFile;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.IsoTypeWriter;
import com.coremedia.iso.Utf8;
import com.googlecode.mp4parser.AbstractFullBox;
import java.nio.ByteBuffer;
import static com.googlecode.mp4parser.util.CastUtils.l2i;
public class AppleDataReferenceBox extends AbstractFullBox {
public static final String TYPE = "rdrf";
private int dataReferenceSize;
private String dataReferenceType;
private String dataReference;
public AppleDataReferenceBox() {
super(TYPE);
}
protected long getContentSize() {
return 12 + dataReferenceSize;
}
@Override
public void _parseDetails(ByteBuffer content) {
parseVersionAndFlags(content);
dataReferenceType = IsoTypeReader.read4cc(content);
dataReferenceSize = l2i(IsoTypeReader.readUInt32(content));
dataReference = IsoTypeReader.readString(content, dataReferenceSize);
}
@Override
protected void getContent(ByteBuffer byteBuffer) {
writeVersionAndFlags(byteBuffer);
byteBuffer.put(IsoFile.fourCCtoBytes(dataReferenceType));
IsoTypeWriter.writeUInt32(byteBuffer, dataReferenceSize);
byteBuffer.put(Utf8.convert(dataReference));
}
public long getDataReferenceSize() {
return dataReferenceSize;
}
public String getDataReferenceType() {
return dataReferenceType;
}
public String getDataReference() {
return dataReference;
}
}
package com.coremedia.iso.boxes.apple;
/**
*
*/
public final class AppleDescriptionBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "desc";
public AppleDescriptionBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
/**
* itunes MetaData comment box.
*/
public final class AppleEncoderBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "\u00a9too";
public AppleEncoderBox() {
super(TYPE);
appleDataBox = AppleDataBox.getStringAppleDataBox();
}
}
\ No newline at end of file
package com.coremedia.iso.boxes.apple;
/**
* Gapless Playback.
*/
public final class AppleGaplessPlaybackBox extends AbstractAppleMetaDataBox {
public static final String TYPE = "pgap";
public AppleGaplessPlaybackBox() {
super(TYPE);
appleDataBox = AppleDataBox.getUint8AppleDataBox();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment