Some nullness cleanup for extractor.ogg
PiperOrigin-RevId: 286203692
This commit is contained in:
parent
e8068f0fcb
commit
8b0f5b0a86
@ -24,9 +24,9 @@ import com.google.android.exoplayer2.extractor.SeekMap;
|
|||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.FlacConstants;
|
import com.google.android.exoplayer2.util.FlacConstants;
|
||||||
import com.google.android.exoplayer2.util.FlacStreamMetadata;
|
import com.google.android.exoplayer2.util.FlacStreamMetadata;
|
||||||
|
import com.google.android.exoplayer2.util.FlacStreamMetadata.SeekTable;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,15 +70,17 @@ import java.util.Arrays;
|
|||||||
@Override
|
@Override
|
||||||
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) {
|
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) {
|
||||||
byte[] data = packet.data;
|
byte[] data = packet.data;
|
||||||
|
@Nullable FlacStreamMetadata streamMetadata = this.streamMetadata;
|
||||||
if (streamMetadata == null) {
|
if (streamMetadata == null) {
|
||||||
streamMetadata = new FlacStreamMetadata(data, 17);
|
streamMetadata = new FlacStreamMetadata(data, 17);
|
||||||
|
this.streamMetadata = streamMetadata;
|
||||||
byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit());
|
byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit());
|
||||||
setupData.format = streamMetadata.getFormat(metadata, /* id3Metadata= */ null);
|
setupData.format = streamMetadata.getFormat(metadata, /* id3Metadata= */ null);
|
||||||
} else if ((data[0] & 0x7F) == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
|
} else if ((data[0] & 0x7F) == FlacConstants.METADATA_TYPE_SEEK_TABLE) {
|
||||||
flacOggSeeker = new FlacOggSeeker();
|
SeekTable seekTable = FlacMetadataReader.readSeekTableMetadataBlock(packet);
|
||||||
FlacStreamMetadata.SeekTable seekTable =
|
|
||||||
FlacMetadataReader.readSeekTableMetadataBlock(packet);
|
|
||||||
streamMetadata = streamMetadata.copyWithSeekTable(seekTable);
|
streamMetadata = streamMetadata.copyWithSeekTable(seekTable);
|
||||||
|
this.streamMetadata = streamMetadata;
|
||||||
|
flacOggSeeker = new FlacOggSeeker(streamMetadata, seekTable);
|
||||||
} else if (isAudioPacket(data)) {
|
} else if (isAudioPacket(data)) {
|
||||||
if (flacOggSeeker != null) {
|
if (flacOggSeeker != null) {
|
||||||
flacOggSeeker.setFirstFrameOffset(position);
|
flacOggSeeker.setFirstFrameOffset(position);
|
||||||
@ -101,12 +103,16 @@ import java.util.Arrays;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FlacOggSeeker implements OggSeeker {
|
private static final class FlacOggSeeker implements OggSeeker {
|
||||||
|
|
||||||
|
private FlacStreamMetadata streamMetadata;
|
||||||
|
private SeekTable seekTable;
|
||||||
private long firstFrameOffset;
|
private long firstFrameOffset;
|
||||||
private long pendingSeekGranule;
|
private long pendingSeekGranule;
|
||||||
|
|
||||||
public FlacOggSeeker() {
|
public FlacOggSeeker(FlacStreamMetadata streamMetadata, SeekTable seekTable) {
|
||||||
|
this.streamMetadata = streamMetadata;
|
||||||
|
this.seekTable = seekTable;
|
||||||
firstFrameOffset = -1;
|
firstFrameOffset = -1;
|
||||||
pendingSeekGranule = -1;
|
pendingSeekGranule = -1;
|
||||||
}
|
}
|
||||||
@ -116,7 +122,7 @@ import java.util.Arrays;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long read(ExtractorInput input) throws IOException, InterruptedException {
|
public long read(ExtractorInput input) {
|
||||||
if (pendingSeekGranule >= 0) {
|
if (pendingSeekGranule >= 0) {
|
||||||
long result = -(pendingSeekGranule + 2);
|
long result = -(pendingSeekGranule + 2);
|
||||||
pendingSeekGranule = -1;
|
pendingSeekGranule = -1;
|
||||||
@ -127,9 +133,10 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startSeek(long targetGranule) {
|
public void startSeek(long targetGranule) {
|
||||||
Assertions.checkNotNull(streamMetadata.seekTable);
|
long[] seekPointGranules = seekTable.pointSampleNumbers;
|
||||||
long[] seekPointGranules = streamMetadata.seekTable.pointSampleNumbers;
|
int index =
|
||||||
int index = Util.binarySearchFloor(seekPointGranules, targetGranule, true, true);
|
Util.binarySearchFloor(
|
||||||
|
seekPointGranules, targetGranule, /* inclusive= */ true, /* stayInBounds= */ true);
|
||||||
pendingSeekGranule = seekPointGranules[index];
|
pendingSeekGranule = seekPointGranules[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,19 @@ import java.util.List;
|
|||||||
putNativeOrderLong(initializationData, preskip);
|
putNativeOrderLong(initializationData, preskip);
|
||||||
putNativeOrderLong(initializationData, DEFAULT_SEEK_PRE_ROLL_SAMPLES);
|
putNativeOrderLong(initializationData, DEFAULT_SEEK_PRE_ROLL_SAMPLES);
|
||||||
|
|
||||||
setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_OPUS, null,
|
setupData.format =
|
||||||
Format.NO_VALUE, Format.NO_VALUE, channelCount, SAMPLE_RATE, initializationData, null, 0,
|
Format.createAudioSampleFormat(
|
||||||
null);
|
null,
|
||||||
|
MimeTypes.AUDIO_OPUS,
|
||||||
|
/* codecs= */ null,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
channelCount,
|
||||||
|
SAMPLE_RATE,
|
||||||
|
initializationData,
|
||||||
|
/* drmInitData= */ null,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
/* language= */ null);
|
||||||
headerRead = true;
|
headerRead = true;
|
||||||
} else {
|
} else {
|
||||||
boolean headerPacket = packet.readInt() == OPUS_CODE;
|
boolean headerPacket = packet.readInt() == OPUS_CODE;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.ogg;
|
package com.google.android.exoplayer2.extractor.ogg;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
@ -23,6 +24,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
|||||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -51,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private long currentGranule;
|
private long currentGranule;
|
||||||
private int state;
|
private int state;
|
||||||
private int sampleRate;
|
private int sampleRate;
|
||||||
private SetupData setupData;
|
@Nullable private SetupData setupData;
|
||||||
private long lengthOfReadPacket;
|
private long lengthOfReadPacket;
|
||||||
private boolean seekMapSet;
|
private boolean seekMapSet;
|
||||||
private boolean formatSet;
|
private boolean formatSet;
|
||||||
@ -149,7 +151,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
boolean isLastPage = (firstPayloadPageHeader.type & 0x04) != 0; // Type 4 is end of stream.
|
boolean isLastPage = (firstPayloadPageHeader.type & 0x04) != 0; // Type 4 is end of stream.
|
||||||
oggSeeker =
|
oggSeeker =
|
||||||
new DefaultOggSeeker(
|
new DefaultOggSeeker(
|
||||||
this,
|
/* streamReader= */ this,
|
||||||
payloadStartPosition,
|
payloadStartPosition,
|
||||||
input.getLength(),
|
input.getLength(),
|
||||||
firstPayloadPageHeader.headerSize + firstPayloadPageHeader.bodySize,
|
firstPayloadPageHeader.headerSize + firstPayloadPageHeader.bodySize,
|
||||||
@ -173,8 +175,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
} else if (position < -1) {
|
} else if (position < -1) {
|
||||||
onSeekEnd(-(position + 2));
|
onSeekEnd(-(position + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!seekMapSet) {
|
if (!seekMapSet) {
|
||||||
SeekMap seekMap = oggSeeker.createSeekMap();
|
SeekMap seekMap = Assertions.checkNotNull(oggSeeker.createSeekMap());
|
||||||
extractorOutput.seekMap(seekMap);
|
extractorOutput.seekMap(seekMap);
|
||||||
seekMapSet = true;
|
seekMapSet = true;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.ogg;
|
package com.google.android.exoplayer2.extractor.ogg;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
@ -30,16 +31,16 @@ import java.util.ArrayList;
|
|||||||
*/
|
*/
|
||||||
/* package */ final class VorbisReader extends StreamReader {
|
/* package */ final class VorbisReader extends StreamReader {
|
||||||
|
|
||||||
private VorbisSetup vorbisSetup;
|
@Nullable private VorbisSetup vorbisSetup;
|
||||||
private int previousPacketBlockSize;
|
private int previousPacketBlockSize;
|
||||||
private boolean seenFirstAudioPacket;
|
private boolean seenFirstAudioPacket;
|
||||||
|
|
||||||
private VorbisUtil.VorbisIdHeader vorbisIdHeader;
|
@Nullable private VorbisUtil.VorbisIdHeader vorbisIdHeader;
|
||||||
private VorbisUtil.CommentHeader commentHeader;
|
@Nullable private VorbisUtil.CommentHeader commentHeader;
|
||||||
|
|
||||||
public static boolean verifyBitstreamType(ParsableByteArray data) {
|
public static boolean verifyBitstreamType(ParsableByteArray data) {
|
||||||
try {
|
try {
|
||||||
return VorbisUtil.verifyVorbisHeaderCapturePattern(0x01, data, true);
|
return VorbisUtil.verifyVorbisHeaderCapturePattern(/* headerType= */ 0x01, data, true);
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -102,14 +103,24 @@ import java.util.ArrayList;
|
|||||||
codecInitialisationData.add(vorbisSetup.idHeader.data);
|
codecInitialisationData.add(vorbisSetup.idHeader.data);
|
||||||
codecInitialisationData.add(vorbisSetup.setupHeaderData);
|
codecInitialisationData.add(vorbisSetup.setupHeaderData);
|
||||||
|
|
||||||
setupData.format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_VORBIS, null,
|
setupData.format =
|
||||||
this.vorbisSetup.idHeader.bitrateNominal, Format.NO_VALUE,
|
Format.createAudioSampleFormat(
|
||||||
this.vorbisSetup.idHeader.channels, (int) this.vorbisSetup.idHeader.sampleRate,
|
null,
|
||||||
codecInitialisationData, null, 0, null);
|
MimeTypes.AUDIO_VORBIS,
|
||||||
|
/* codecs= */ null,
|
||||||
|
this.vorbisSetup.idHeader.bitrateNominal,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
this.vorbisSetup.idHeader.channels,
|
||||||
|
(int) this.vorbisSetup.idHeader.sampleRate,
|
||||||
|
codecInitialisationData,
|
||||||
|
null,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
/* language= */ null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@Nullable
|
||||||
/* package */ VorbisSetup readSetupHeaders(ParsableByteArray scratch) throws IOException {
|
/* package */ VorbisSetup readSetupHeaders(ParsableByteArray scratch) throws IOException {
|
||||||
|
|
||||||
if (vorbisIdHeader == null) {
|
if (vorbisIdHeader == null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user