Check for TS synchronization before parsing packet from random position
#minor-release Issue: #9100 PiperOrigin-RevId: 384962258
This commit is contained in:
parent
7157f3c119
commit
99abb4e1e9
@ -109,6 +109,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
|
||||
|
@ -180,10 +180,13 @@ import java.io.IOException;
|
||||
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);
|
||||
|
@ -21,6 +21,38 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
|
||||
/** 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user