From f5e92134af3c0f112ec8ad7644d7282b7e8e2ce8 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 1 Aug 2019 16:32:29 +0100 Subject: [PATCH] Shorten data length if it exceeds length of input Issue: #6241 PiperOrigin-RevId: 261126968 --- RELEASENOTES.md | 2 ++ .../extractor/wav/WavExtractor.java | 6 ++-- .../exoplayer2/extractor/wav/WavHeader.java | 36 +++++++++++-------- .../extractor/wav/WavHeaderReader.java | 13 +++++-- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 39cc640807..9bc77f8cfc 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,6 +9,8 @@ tags instead of 3-letter ISO 639-2 language tags. * Ensure the `SilenceMediaSource` position is in range ([#6229](https://github.com/google/ExoPlayer/issues/6229)). +* Calculate correct duration for clipped WAV streams + ([#6241](https://github.com/google/ExoPlayer/issues/6241)). * Fix issue where initial seek positions get ignored when playing a preroll ad ([#6201](https://github.com/google/ExoPlayer/issues/6201)). * Fix issue where invalid language tags were normalized to "und" instead of diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java index d3114f9b69..91097c9e5b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java @@ -91,10 +91,10 @@ public final class WavExtractor implements Extractor { input.skipFully(wavHeader.getDataStartPosition()); } - long dataLimit = wavHeader.getDataLimit(); - Assertions.checkState(dataLimit != C.POSITION_UNSET); + long dataEndPosition = wavHeader.getDataEndPosition(); + Assertions.checkState(dataEndPosition != C.POSITION_UNSET); - long bytesLeft = dataLimit - input.getPosition(); + long bytesLeft = dataEndPosition - input.getPosition(); if (bytesLeft <= 0) { return Extractor.RESULT_END_OF_INPUT; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java index c7858dcd96..6e3c5988a9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeader.java @@ -33,17 +33,21 @@ import com.google.android.exoplayer2.util.Util; private final int blockAlignment; /** Bits per sample for the audio data. */ private final int bitsPerSample; - /** The PCM encoding */ - @C.PcmEncoding - private final int encoding; + /** The PCM encoding. */ + @C.PcmEncoding private final int encoding; /** Position of the start of the sample data, in bytes. */ private int dataStartPosition; - /** Total size of the sample data, in bytes. */ - private long dataSize; + /** Position of the end of the sample data (exclusive), in bytes. */ + private long dataEndPosition; - public WavHeader(int numChannels, int sampleRateHz, int averageBytesPerSecond, int blockAlignment, - int bitsPerSample, @C.PcmEncoding int encoding) { + public WavHeader( + int numChannels, + int sampleRateHz, + int averageBytesPerSecond, + int blockAlignment, + int bitsPerSample, + @C.PcmEncoding int encoding) { this.numChannels = numChannels; this.sampleRateHz = sampleRateHz; this.averageBytesPerSecond = averageBytesPerSecond; @@ -51,6 +55,7 @@ import com.google.android.exoplayer2.util.Util; this.bitsPerSample = bitsPerSample; this.encoding = encoding; dataStartPosition = C.POSITION_UNSET; + dataEndPosition = C.POSITION_UNSET; } // Data bounds. @@ -59,11 +64,11 @@ import com.google.android.exoplayer2.util.Util; * Sets the data start position and size in bytes of sample data in this WAV. * * @param dataStartPosition The position of the start of the sample data, in bytes. - * @param dataSize The total size of the sample data, in bytes. + * @param dataEndPosition The position of the end of the sample data (exclusive), in bytes. */ - public void setDataBounds(int dataStartPosition, long dataSize) { + public void setDataBounds(int dataStartPosition, long dataEndPosition) { this.dataStartPosition = dataStartPosition; - this.dataSize = dataSize; + this.dataEndPosition = dataEndPosition; } /** @@ -75,11 +80,11 @@ import com.google.android.exoplayer2.util.Util; } /** - * Returns the limit of the sample data, in bytes, or {@link C#POSITION_UNSET} if the data bounds - * have not been set. + * Returns the position of the end of the sample data (exclusive), in bytes, or {@link + * C#POSITION_UNSET} if the data bounds have not been set. */ - public long getDataLimit() { - return hasDataBounds() ? (dataStartPosition + dataSize) : C.POSITION_UNSET; + public long getDataEndPosition() { + return dataEndPosition; } /** Returns whether the data start position and size have been set. */ @@ -96,12 +101,13 @@ import com.google.android.exoplayer2.util.Util; @Override public long getDurationUs() { - long numFrames = dataSize / blockAlignment; + long numFrames = (dataEndPosition - dataStartPosition) / blockAlignment; return (numFrames * C.MICROS_PER_SECOND) / sampleRateHz; } @Override public SeekPoints getSeekPoints(long timeUs) { + long dataSize = dataEndPosition - dataStartPosition; long positionOffset = (timeUs * averageBytesPerSecond) / C.MICROS_PER_SECOND; // Constrain to nearest preceding frame offset. positionOffset = (positionOffset / blockAlignment) * blockAlignment; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java index 839a9e3d5c..bbcb75aa2d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/WavHeaderReader.java @@ -91,8 +91,8 @@ import java.io.IOException; // If present, skip extensionSize, validBitsPerSample, channelMask, subFormatGuid, ... input.advancePeekPosition((int) chunkHeader.size - 16); - return new WavHeader(numChannels, sampleRateHz, averageBytesPerSecond, blockAlignment, - bitsPerSample, encoding); + return new WavHeader( + numChannels, sampleRateHz, averageBytesPerSecond, blockAlignment, bitsPerSample, encoding); } /** @@ -139,7 +139,14 @@ import java.io.IOException; // Skip past the "data" header. input.skipFully(ChunkHeader.SIZE_IN_BYTES); - wavHeader.setDataBounds((int) input.getPosition(), chunkHeader.size); + int dataStartPosition = (int) input.getPosition(); + long dataEndPosition = dataStartPosition + chunkHeader.size; + long inputLength = input.getLength(); + if (inputLength != C.LENGTH_UNSET && dataEndPosition > inputLength) { + Log.w(TAG, "Data exceeds input length: " + dataEndPosition + ", " + inputLength); + dataEndPosition = inputLength; + } + wavHeader.setDataBounds(dataStartPosition, dataEndPosition); } private WavHeaderReader() {