Add private @SeekHeader
IntDef to Mp3Extractor
Also use `switch` instead of `if-else`. PiperOrigin-RevId: 597004322
This commit is contained in:
parent
1c1d4d506d
commit
143d782b1c
@ -16,6 +16,7 @@
|
||||
package androidx.media3.extractor.mp3;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -48,7 +49,6 @@ import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@ -67,7 +67,7 @@ public final class Mp3Extractor implements Extractor {
|
||||
* {@link #FLAG_ENABLE_INDEX_SEEKING} and {@link #FLAG_DISABLE_ID3_METADATA}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Retention(SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@IntDef(
|
||||
flag = true,
|
||||
@ -142,6 +142,12 @@ public final class Mp3Extractor implements Extractor {
|
||||
/** Mask that includes the audio header values that must match between frames. */
|
||||
private static final int MPEG_AUDIO_HEADER_MASK = 0xFFFE0C00;
|
||||
|
||||
@Documented
|
||||
@Target(TYPE_USE)
|
||||
@Retention(SOURCE)
|
||||
@IntDef(value = {SEEK_HEADER_XING, SEEK_HEADER_INFO, SEEK_HEADER_VBRI, SEEK_HEADER_UNSET})
|
||||
private @interface SeekHeader {}
|
||||
|
||||
private static final int SEEK_HEADER_XING = 0x58696e67;
|
||||
private static final int SEEK_HEADER_INFO = 0x496e666f;
|
||||
private static final int SEEK_HEADER_VBRI = 0x56425249;
|
||||
@ -506,30 +512,37 @@ public final class Mp3Extractor implements Extractor {
|
||||
(synchronizedHeader.version & 1) != 0
|
||||
? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
|
||||
: (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
|
||||
int seekHeader = getSeekFrameHeader(frame, xingBase);
|
||||
@SeekHeader int seekHeader = getSeekFrameHeader(frame, xingBase);
|
||||
@Nullable Seeker seeker;
|
||||
if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) {
|
||||
seeker = XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
|
||||
if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) {
|
||||
// If there is a Xing header, read gapless playback metadata at a fixed offset.
|
||||
switch (seekHeader) {
|
||||
case SEEK_HEADER_XING:
|
||||
case SEEK_HEADER_INFO:
|
||||
seeker =
|
||||
XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
|
||||
if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) {
|
||||
// If there is a Xing header, read gapless playback metadata at a fixed offset.
|
||||
input.resetPeekPosition();
|
||||
input.advancePeekPosition(xingBase + 141);
|
||||
input.peekFully(scratch.getData(), 0, 3);
|
||||
scratch.setPosition(0);
|
||||
gaplessInfoHolder.setFromXingHeaderValue(scratch.readUnsignedInt24());
|
||||
}
|
||||
input.skipFully(synchronizedHeader.frameSize);
|
||||
if (seeker != null && !seeker.isSeekable() && seekHeader == SEEK_HEADER_INFO) {
|
||||
// Fall back to constant bitrate seeking for Info headers missing a table of contents.
|
||||
return getConstantBitrateSeeker(input, /* allowSeeksIfLengthUnknown= */ false);
|
||||
}
|
||||
break;
|
||||
case SEEK_HEADER_VBRI:
|
||||
seeker =
|
||||
VbriSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
|
||||
input.skipFully(synchronizedHeader.frameSize);
|
||||
break;
|
||||
case SEEK_HEADER_UNSET:
|
||||
default:
|
||||
// This frame doesn't contain seeking information, so reset the peek position.
|
||||
seeker = null;
|
||||
input.resetPeekPosition();
|
||||
input.advancePeekPosition(xingBase + 141);
|
||||
input.peekFully(scratch.getData(), 0, 3);
|
||||
scratch.setPosition(0);
|
||||
gaplessInfoHolder.setFromXingHeaderValue(scratch.readUnsignedInt24());
|
||||
}
|
||||
input.skipFully(synchronizedHeader.frameSize);
|
||||
if (seeker != null && !seeker.isSeekable() && seekHeader == SEEK_HEADER_INFO) {
|
||||
// Fall back to constant bitrate seeking for Info headers missing a table of contents.
|
||||
return getConstantBitrateSeeker(input, /* allowSeeksIfLengthUnknown= */ false);
|
||||
}
|
||||
} else if (seekHeader == SEEK_HEADER_VBRI) {
|
||||
seeker = VbriSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
|
||||
input.skipFully(synchronizedHeader.frameSize);
|
||||
} else { // seekerHeader == SEEK_HEADER_UNSET
|
||||
// This frame doesn't contain seeking information, so reset the peek position.
|
||||
seeker = null;
|
||||
input.resetPeekPosition();
|
||||
}
|
||||
return seeker;
|
||||
}
|
||||
@ -560,7 +573,7 @@ public final class Mp3Extractor implements Extractor {
|
||||
* the provided {@code frame} may have seeking metadata, or {@link #SEEK_HEADER_UNSET} otherwise.
|
||||
* If seeking metadata is present, {@code frame}'s position is advanced past the header.
|
||||
*/
|
||||
private static int getSeekFrameHeader(ParsableByteArray frame, int xingBase) {
|
||||
private static @SeekHeader int getSeekFrameHeader(ParsableByteArray frame, int xingBase) {
|
||||
if (frame.limit() >= xingBase + 4) {
|
||||
frame.setPosition(xingBase);
|
||||
int headerData = frame.readInt();
|
||||
|
Loading…
x
Reference in New Issue
Block a user