Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions java-library/src/main/java/com/sandflow/smpte/mxf/ClipReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class ClipReader extends InputStream {
final AUID elementKey;
final long elementLength;
final long essenceOffset;
/* size of the key and length of the clip */
final long klLength;
final RandomAccessFileInfo info;
final RandomAccessInputSource source;

Expand All @@ -67,6 +69,7 @@ public ClipReader(RandomAccessFileInfo info, RandomAccessInputSource source) thr
MXFDataInput mis = new MXFDataInput(this.source);
this.elementKey = mis.readAUID();
this.elementLength = mis.readBERLength();
this.klLength = this.source.position() - clipStartPosition;

/*
* ECXEPTION: Some versions of ASDCPLib index from the start of the K of the
Expand All @@ -78,7 +81,7 @@ public ClipReader(RandomAccessFileInfo info, RandomAccessInputSource source) thr
&& this.info.euToECPosition(0) != 0) {
this.essenceOffset = 0;
} else {
this.essenceOffset = this.source.position() - clipStartPosition;
this.essenceOffset = this.klLength;
}

this.seek(0);
Expand Down Expand Up @@ -131,7 +134,8 @@ public void seek(long euPosition) throws IOException {
long ecPosition = this.info.euToECPosition(euPosition);
long filePosition = this.info.ecToFilePositions(ecPosition) + this.essenceOffset;
this.source.position(filePosition);
this.remainingElementBytes = this.elementLength - ecPosition;
/* ecPosition + essenceOffset is relative to the start of the K of the clip */
this.remainingElementBytes = this.elementLength - (ecPosition + this.essenceOffset - this.klLength);
}

/**
Expand Down Expand Up @@ -163,9 +167,12 @@ public int read() throws IOException {
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (this.remainingElementBytes == 0)
if (len == 0)
return 0;
if (this.remainingElementBytes <= 0)
return -1;
int r = source.read(b, off, len);
/* do not read past the end of the element */
int r = source.read(b, off, (int) Math.min(len, this.remainingElementBytes));
this.remainingElementBytes = r == -1 ? 0 : this.remainingElementBytes - r;
return r;
}
Expand All @@ -179,9 +186,10 @@ public int read(byte[] b, int off, int len) throws IOException {
*/
@Override
public long skip(long n) throws IOException {
if (this.remainingElementBytes == 0)
return -1;
long s = this.source.skip(n);
if (n <= 0 || this.remainingElementBytes <= 0)
return 0;
/* do not skip past the end of the element */
long s = Math.max(0, this.source.skip(Math.min(n, this.remainingElementBytes)));
this.remainingElementBytes = this.remainingElementBytes - s;
return s;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,12 @@ public int read() throws IOException {
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (this.remainingElementBytes == 0)
if (len == 0)
return 0;
if (this.remainingElementBytes <= 0)
return -1;
int r = source.read(b, off, len);
/* do not read past the end of the element */
int r = source.read(b, off, (int) Math.min(len, this.remainingElementBytes));
this.remainingElementBytes = r == -1 ? 0 : this.remainingElementBytes - r;
return r;
}
Expand All @@ -159,9 +162,10 @@ public int read(byte[] b, int off, int len) throws IOException {
*/
@Override
public long skip(long n) throws IOException {
if (this.remainingElementBytes == 0)
return -1;
long s = this.source.skip(n);
if (n <= 0 || this.remainingElementBytes <= 0)
return 0;
/* do not skip past the end of the element */
long s = Math.max(0, this.source.skip(Math.min(n, this.remainingElementBytes)));
this.remainingElementBytes = this.remainingElementBytes - s;
return s;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,12 @@ public int read(byte[] b, int off, int len) throws IOException {
if (this.state != State.IN_PAYLOAD) {
throw new RuntimeException();
}
if (this.remainingElementBytes == 0)
if (len == 0)
return 0;
if (this.remainingElementBytes <= 0)
return -1;
int r = this.mis.read(b, off, len);
/* do not read past the end of the element */
int r = this.mis.read(b, off, (int) Math.min(len, this.remainingElementBytes));
this.remainingElementBytes = r == -1 ? 0 : this.remainingElementBytes - r;
return r;
}
Expand All @@ -170,9 +173,10 @@ public long skip(long n) throws IOException {
if (this.state != State.IN_PAYLOAD) {
throw new RuntimeException();
}
if (this.remainingElementBytes == 0)
return -1;
long s = this.mis.skip(n);
if (n <= 0 || this.remainingElementBytes <= 0)
return 0;
/* do not skip past the end of the element */
long s = Math.max(0, this.mis.skip(Math.min(n, this.remainingElementBytes)));
this.remainingElementBytes = this.remainingElementBytes - s;
return s;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,38 @@ void testTimedEvents() throws Exception {
gsr.close();
}

/*
* Bulk reads and skips must not go past the end of the element
*/
@Test
void testReadPastElementEnd() throws Exception {
File f = new File(ClassLoader.getSystemResource("mxf-files/timed_events.mxf").toURI());
FileRandomAccessInputSource rais = new FileRandomAccessInputSource(new RandomAccessFile(f, "r"));

RandomAccessFileInfo fi = new RandomAccessFileInfo(rais, null);

ClipReader cr = new ClipReader(fi, rais);
assertEquals(840, cr.readAllBytes().length);
assertEquals(0, cr.getRemainingElementBytes());
assertEquals(-1, cr.read());

cr.seek(0);
assertEquals(840, cr.skip(Long.MAX_VALUE));
assertEquals(0, cr.skip(1));
assertEquals(-1, cr.read(new byte[16]));
cr.close();

GenericStreamReader gsr = new GenericStreamReader(fi, rais);
gsr.seek(12);
assertEquals(81, gsr.readAllBytes().length);
assertEquals(0, gsr.getRemainingElementBytes());
assertEquals(-1, gsr.read());

gsr.seek(12);
assertEquals(81, gsr.skip(Long.MAX_VALUE));
assertEquals(0, gsr.skip(1));
assertEquals(-1, gsr.read(new byte[16]));
gsr.close();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,37 @@ void testTimedEvents() throws Exception {
sr.close();
}

/*
* Bulk reads and skips must not go past the end of the element
*/
@Test
void testReadPastElementEnd() throws Exception {
InputStream is = ClassLoader.getSystemResourceAsStream("mxf-files/timed_events.mxf");
assertNotNull(is);

new StreamingFileInfo(is, null);
StreamingReader sr = new StreamingReader(is, null);

/* Timed Events Resource */

assertTrue(sr.nextElement());
assertEquals(840, sr.readAllBytes().length);
assertEquals(-1, sr.read());
assertEquals(0, sr.skip(1));

/* Timed Events Ancillary Resource, in a generic stream */

assertTrue(sr.nextElement());
assertEquals(12L, sr.getSID());
assertEquals(81, sr.readAllBytes().length);
assertEquals(-1, sr.read(new byte[16]));
assertEquals(0, sr.skip(Long.MAX_VALUE));

assertFalse(sr.nextElement());

sr.close();
}

/*
* SMPTE ST 2067-204 ADM audio track file, from the Photon test suite
* (https://github.com/wruppelx/photon)
Expand Down
Loading