Skip to content

Commit

Permalink
Check for TS synchronization before parsing packet from random position
Browse files Browse the repository at this point in the history
#minor-release
Issue: #9100
PiperOrigin-RevId: 384962258
  • Loading branch information
AquilesCanta authored and icbaker committed Jul 20, 2021
1 parent d4c62f3 commit 9cd6b50
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
([#7608](https://github.com/google/ExoPlayer/issues/7608)).
* Add support for MP4 H263 atom type
([#9158](https://github.com/google/ExoPlayer/issues/9158)).
* Fix issue around TS synchronization when reading a file's duration
([#9100](https://github.com/google/ExoPlayer/pull/9100)).
* HLS:
* Fix issue where playback of a live event could become stuck rather than
transitioning to `STATE_ENDED` when the event ends
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,13 @@ private int readLastPcrValue(ExtractorInput input, PositionHolder seekPositionHo
private long readLastPcrValueFromBuffer(ParsableByteArray packetBuffer, int pcrPid) {
int searchStartPosition = packetBuffer.getPosition();
int searchEndPosition = packetBuffer.limit();
for (int searchPosition = searchEndPosition - 1;
// We start searching 'TsExtractor.TS_PACKET_SIZE' bytes from the end to prevent trying to read
// from an incomplete TS packet.
for (int searchPosition = searchEndPosition - TsExtractor.TS_PACKET_SIZE;
searchPosition >= searchStartPosition;
searchPosition--) {
if (packetBuffer.getData()[searchPosition] != TsExtractor.TS_SYNC_BYTE) {
if (!TsUtil.isStartOfTsPacket(
packetBuffer.getData(), searchStartPosition, searchEndPosition, searchPosition)) {
continue;
}
long pcrValue = TsUtil.readPcrFromPacket(packetBuffer, searchPosition, pcrPid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,38 @@

/** Utilities method for extracting MPEG-TS streams. */
public final class TsUtil {

/**
* Returns whether a TS packet starts at {@code searchPosition} according to the MPEG-TS
* synchronization recommendations.
*
* <p>ISO/IEC 13818-1:2015 Annex G recommends that 5 sync bytes emulating the start of 5
* consecutive TS packets should never occur as part of the TS packets' contents. So, this method
* returns true when {@code data} contains a sync byte at {@code searchPosition}, and said sync
* byte is also one of five consecutive sync bytes separated from each other by the size of a TS
* packet.
*
* @param data The array holding the data to search in.
* @param start The first valid position in {@code data} from which a sync byte can be read.
* @param limit The first invalid position in {@code data}, after which no data should be read.
* @param searchPosition The position to check for a TS packet start.
* @return Whether a TS packet starts at {@code searchPosition}.
*/
public static boolean isStartOfTsPacket(byte[] data, int start, int limit, int searchPosition) {
int consecutiveSyncByteCount = 0;
for (int i = -4; i <= 4; i++) {
int currentPosition = searchPosition + i * TsExtractor.TS_PACKET_SIZE;
if (currentPosition < start
|| currentPosition >= limit
|| data[currentPosition] != TsExtractor.TS_SYNC_BYTE) {
consecutiveSyncByteCount = 0;
} else if (++consecutiveSyncByteCount == 5) {
return true;
}
}
return false;
}

/**
* Returns the position of the first TS_SYNC_BYTE within the range [startPosition, limitPosition)
* from the provided data array, or returns limitPosition if sync byte could not be found.
Expand Down

0 comments on commit 9cd6b50

Please sign in to comment.