Commit 5082d1f2 by olly Committed by Oliver Woodman

Some boilerplate for DASH EMSG support

- Parse EMSG leaf atoms during FMP4 extraction (although
  currently they're just discarded).
- Add readNullTerminatedString to ParsableByteArray.

Issue: #2176

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=143555965
parent f735a86e
...@@ -371,6 +371,73 @@ public class ParsableByteArrayTest extends TestCase { ...@@ -371,6 +371,73 @@ public class ParsableByteArrayTest extends TestCase {
assertNull(parser.readLine()); assertNull(parser.readLine());
} }
public void testReadNullTerminatedStringWithLengths() {
byte[] bytes = new byte[] {
'f', 'o', 'o', 0, 'b', 'a', 'r', 0
};
// Test with lengths that match NUL byte positions.
ParsableByteArray parser = new ParsableByteArray(bytes);
assertEquals("foo", parser.readNullTerminatedString(4));
assertEquals(4, parser.getPosition());
assertEquals("bar", parser.readNullTerminatedString(4));
assertEquals(8, parser.getPosition());
assertNull(parser.readNullTerminatedString());
// Test with lengths that do not match NUL byte positions.
parser = new ParsableByteArray(bytes);
assertEquals("fo", parser.readNullTerminatedString(2));
assertEquals(2, parser.getPosition());
assertEquals("o", parser.readNullTerminatedString(2));
assertEquals(4, parser.getPosition());
assertEquals("bar", parser.readNullTerminatedString(3));
assertEquals(7, parser.getPosition());
assertEquals("", parser.readNullTerminatedString(1));
assertEquals(8, parser.getPosition());
assertNull(parser.readNullTerminatedString());
// Test with limit at NUL
parser = new ParsableByteArray(bytes, 4);
assertEquals("foo", parser.readNullTerminatedString(4));
assertEquals(4, parser.getPosition());
assertNull(parser.readNullTerminatedString());
// Test with limit before NUL
parser = new ParsableByteArray(bytes, 3);
assertEquals("foo", parser.readNullTerminatedString(3));
assertEquals(3, parser.getPosition());
assertNull(parser.readNullTerminatedString());
}
public void testReadNullTerminatedString() {
byte[] bytes = new byte[] {
'f', 'o', 'o', 0, 'b', 'a', 'r', 0
};
// Test normal case.
ParsableByteArray parser = new ParsableByteArray(bytes);
assertEquals("foo", parser.readNullTerminatedString());
assertEquals(4, parser.getPosition());
assertEquals("bar", parser.readNullTerminatedString());
assertEquals(8, parser.getPosition());
assertNull(parser.readNullTerminatedString());
// Test with limit at NUL.
parser = new ParsableByteArray(bytes, 4);
assertEquals("foo", parser.readNullTerminatedString());
assertEquals(4, parser.getPosition());
assertNull(parser.readNullTerminatedString());
// Test with limit before NUL.
parser = new ParsableByteArray(bytes, 3);
assertEquals("foo", parser.readNullTerminatedString());
assertEquals(3, parser.getPosition());
assertNull(parser.readNullTerminatedString());
}
public void testReadNullTerminatedStringWithoutEndingNull() {
byte[] bytes = new byte[] {
'f', 'o', 'o', 0, 'b', 'a', 'r'
};
ParsableByteArray parser = new ParsableByteArray(bytes);
assertEquals("foo", parser.readNullTerminatedString());
assertEquals("bar", parser.readNullTerminatedString());
assertNull(parser.readNullTerminatedString());
}
public void testReadSingleLineWithoutEndingTrail() { public void testReadSingleLineWithoutEndingTrail() {
byte[] bytes = new byte[] { byte[] bytes = new byte[] {
'f', 'o', 'o' 'f', 'o', 'o'
......
...@@ -127,6 +127,7 @@ import java.util.List; ...@@ -127,6 +127,7 @@ import java.util.List;
public static final int TYPE_mean = Util.getIntegerCodeForString("mean"); public static final int TYPE_mean = Util.getIntegerCodeForString("mean");
public static final int TYPE_name = Util.getIntegerCodeForString("name"); public static final int TYPE_name = Util.getIntegerCodeForString("name");
public static final int TYPE_data = Util.getIntegerCodeForString("data"); public static final int TYPE_data = Util.getIntegerCodeForString("data");
public static final int TYPE_emsg = Util.getIntegerCodeForString("emsg");
public static final int TYPE_st3d = Util.getIntegerCodeForString("st3d"); public static final int TYPE_st3d = Util.getIntegerCodeForString("st3d");
public static final int TYPE_sv3d = Util.getIntegerCodeForString("sv3d"); public static final int TYPE_sv3d = Util.getIntegerCodeForString("sv3d");
public static final int TYPE_proj = Util.getIntegerCodeForString("proj"); public static final int TYPE_proj = Util.getIntegerCodeForString("proj");
......
...@@ -339,6 +339,8 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -339,6 +339,8 @@ public final class FragmentedMp4Extractor implements Extractor {
ChunkIndex segmentIndex = parseSidx(leaf.data, inputPosition); ChunkIndex segmentIndex = parseSidx(leaf.data, inputPosition);
extractorOutput.seekMap(segmentIndex); extractorOutput.seekMap(segmentIndex);
haveOutputSeekMap = true; haveOutputSeekMap = true;
} else if (leaf.type == Atom.TYPE_emsg) {
onEmsgLeafAtomRead(leaf);
} }
} }
...@@ -417,6 +419,10 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -417,6 +419,10 @@ public final class FragmentedMp4Extractor implements Extractor {
} }
} }
private void onEmsgLeafAtomRead(LeafAtom emsg) {
// Do nothing.
}
/** /**
* Parses a trex atom (defined in 14496-12). * Parses a trex atom (defined in 14496-12).
*/ */
...@@ -1134,7 +1140,7 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -1134,7 +1140,7 @@ public final class FragmentedMp4Extractor implements Extractor {
|| atom == Atom.TYPE_trun || atom == Atom.TYPE_pssh || atom == Atom.TYPE_saiz || atom == Atom.TYPE_trun || atom == Atom.TYPE_pssh || atom == Atom.TYPE_saiz
|| atom == Atom.TYPE_saio || atom == Atom.TYPE_senc || atom == Atom.TYPE_uuid || atom == Atom.TYPE_saio || atom == Atom.TYPE_senc || atom == Atom.TYPE_uuid
|| atom == Atom.TYPE_sbgp || atom == Atom.TYPE_sgpd || atom == Atom.TYPE_elst || atom == Atom.TYPE_sbgp || atom == Atom.TYPE_sgpd || atom == Atom.TYPE_elst
|| atom == Atom.TYPE_mehd; || atom == Atom.TYPE_mehd || atom == Atom.TYPE_emsg;
} }
/** Returns whether the extractor should decode a container atom with type {@code atom}. */ /** Returns whether the extractor should decode a container atom with type {@code atom}. */
......
...@@ -424,11 +424,24 @@ public final class ParsableByteArray { ...@@ -424,11 +424,24 @@ public final class ParsableByteArray {
} }
/** /**
* Reads the next {@code length} bytes as UTF-8 characters. A terminating NUL byte is ignored, * Reads the next {@code length} bytes as characters in the specified {@link Charset}.
*
* @param length The number of bytes to read.
* @param charset The character set of the encoded characters.
* @return The string encoded by the bytes in the specified character set.
*/
public String readString(int length, Charset charset) {
String result = new String(data, position, length, charset);
position += length;
return result;
}
/**
* Reads the next {@code length} bytes as UTF-8 characters. A terminating NUL byte is discarded,
* if present. * if present.
* *
* @param length The number of bytes to read. * @param length The number of bytes to read.
* @return The string encoded by the bytes. * @return The string, not including any terminating NUL byte.
*/ */
public String readNullTerminatedString(int length) { public String readNullTerminatedString(int length) {
if (length == 0) { if (length == 0) {
...@@ -439,22 +452,31 @@ public final class ParsableByteArray { ...@@ -439,22 +452,31 @@ public final class ParsableByteArray {
if (lastIndex < limit && data[lastIndex] == 0) { if (lastIndex < limit && data[lastIndex] == 0) {
stringLength--; stringLength--;
} }
String result = new String(data, position, stringLength, Charset.defaultCharset()); String result = new String(data, position, stringLength);
position += length; position += length;
return result; return result;
} }
/** /**
* Reads the next {@code length} bytes as characters in the specified {@link Charset}. * Reads up to the next NUL byte (or the limit) as UTF-8 characters.
* *
* @param length The number of bytes to read. * @return The string not including any terminating NUL byte, or null if the end of the data has
* @param charset The character set of the encoded characters. * already been reached.
* @return The string encoded by the bytes in the specified character set.
*/ */
public String readString(int length, Charset charset) { public String readNullTerminatedString() {
String result = new String(data, position, length, charset); if (bytesLeft() == 0) {
position += length; return null;
return result; }
int stringLimit = position;
while (stringLimit < limit && data[stringLimit] != 0) {
stringLimit++;
}
String string = new String(data, position, stringLimit - position);
position = stringLimit;
if (position < limit) {
position++;
}
return string;
} }
/** /**
...@@ -464,8 +486,8 @@ public final class ParsableByteArray { ...@@ -464,8 +486,8 @@ public final class ParsableByteArray {
* ('\n'), or a carriage return followed immediately by a line feed ('\r\n'). The system's default * ('\n'), or a carriage return followed immediately by a line feed ('\r\n'). The system's default
* charset (UTF-8) is used. * charset (UTF-8) is used.
* *
* @return A String containing the contents of the line, not including any line-termination * @return The line not including any line-termination characters, or null if the end of the data
* characters, or null if the end of the stream has been reached. * has already been reached.
*/ */
public String readLine() { public String readLine() {
if (bytesLeft() == 0) { if (bytesLeft() == 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment