Clean up some extrator SeekMap implementations

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=177173618
This commit is contained in:
olly 2017-11-28 09:43:08 -08:00 committed by Oliver Woodman
parent baa80a1b68
commit ff49bc97c4
4 changed files with 69 additions and 81 deletions

View File

@ -32,7 +32,7 @@ import java.lang.annotation.RetentionPolicy;
/**
* Extracts data from the FLV container format.
*/
public final class FlvExtractor implements Extractor, SeekMap {
public final class FlvExtractor implements Extractor {
/**
* Factory for {@link FlvExtractor} instances.
@ -70,32 +70,28 @@ public final class FlvExtractor implements Extractor, SeekMap {
// FLV container identifier.
private static final int FLV_TAG = Util.getIntegerCodeForString("FLV");
// Temporary buffers.
private final ParsableByteArray scratch;
private final ParsableByteArray headerBuffer;
private final ParsableByteArray tagHeaderBuffer;
private final ParsableByteArray tagData;
private final ScriptTagPayloadReader metadataReader;
// Extractor outputs.
private ExtractorOutput extractorOutput;
// State variables.
private @States int state;
private int bytesToNextTagHeader;
private int tagType;
private int tagDataSize;
private long tagTimestampUs;
// Tags readers.
private boolean outputSeekMap;
private AudioTagPayloadReader audioReader;
private VideoTagPayloadReader videoReader;
private ScriptTagPayloadReader metadataReader;
public FlvExtractor() {
scratch = new ParsableByteArray(4);
headerBuffer = new ParsableByteArray(FLV_HEADER_SIZE);
tagHeaderBuffer = new ParsableByteArray(FLV_TAG_HEADER_SIZE);
tagData = new ParsableByteArray();
metadataReader = new ScriptTagPayloadReader();
state = STATE_READING_FLV_HEADER;
}
@ -203,11 +199,7 @@ public final class FlvExtractor implements Extractor, SeekMap {
videoReader = new VideoTagPayloadReader(
extractorOutput.track(TAG_TYPE_VIDEO, C.TRACK_TYPE_VIDEO));
}
if (metadataReader == null) {
metadataReader = new ScriptTagPayloadReader(null);
}
extractorOutput.endTracks();
extractorOutput.seekMap(this);
// We need to skip any additional content in the FLV header, plus the 4 byte previous tag size.
bytesToNextTagHeader = headerBuffer.readInt() - FLV_HEADER_SIZE + 4;
@ -263,11 +255,18 @@ public final class FlvExtractor implements Extractor, SeekMap {
private boolean readTagData(ExtractorInput input) throws IOException, InterruptedException {
boolean wasConsumed = true;
if (tagType == TAG_TYPE_AUDIO && audioReader != null) {
ensureOutputSeekMap();
audioReader.consume(prepareTagData(input), tagTimestampUs);
} else if (tagType == TAG_TYPE_VIDEO && videoReader != null) {
ensureOutputSeekMap();
videoReader.consume(prepareTagData(input), tagTimestampUs);
} else if (tagType == TAG_TYPE_SCRIPT_DATA && metadataReader != null) {
} else if (tagType == TAG_TYPE_SCRIPT_DATA && !outputSeekMap) {
metadataReader.consume(prepareTagData(input), tagTimestampUs);
long durationUs = metadataReader.getDurationUs();
if (durationUs != C.TIME_UNSET) {
extractorOutput.seekMap(new SeekMap.Unseekable(durationUs));
outputSeekMap = true;
}
} else {
input.skipFully(tagDataSize);
wasConsumed = false;
@ -289,21 +288,11 @@ public final class FlvExtractor implements Extractor, SeekMap {
return tagData;
}
// SeekMap implementation.
@Override
public boolean isSeekable() {
return false;
private void ensureOutputSeekMap() {
if (!outputSeekMap) {
extractorOutput.seekMap(new SeekMap.Unseekable(C.TIME_UNSET));
outputSeekMap = true;
}
@Override
public long getDurationUs() {
return metadataReader.getDurationUs();
}
@Override
public long getPosition(long timeUs) {
return 0;
}
}

View File

@ -17,7 +17,6 @@ package com.google.android.exoplayer2.extractor.flv;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.ParsableByteArray;
import java.util.ArrayList;
import java.util.Date;
@ -44,11 +43,8 @@ import java.util.Map;
private long durationUs;
/**
* @param output A {@link TrackOutput} to which samples should be written.
*/
public ScriptTagPayloadReader(TrackOutput output) {
super(output);
public ScriptTagPayloadReader() {
super(null);
durationUs = C.TIME_UNSET;
}

View File

@ -23,7 +23,6 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
@ -31,7 +30,7 @@ import java.io.IOException;
/**
* Extracts data from WAV byte streams.
*/
public final class WavExtractor implements Extractor, SeekMap {
public final class WavExtractor implements Extractor {
/**
* Factory for {@link WavExtractor} instances.
@ -95,7 +94,7 @@ public final class WavExtractor implements Extractor, SeekMap {
if (!wavHeader.hasDataBounds()) {
WavHeaderReader.skipToData(input, wavHeader);
extractorOutput.seekMap(this);
extractorOutput.seekMap(wavHeader);
}
int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);
@ -115,20 +114,4 @@ public final class WavExtractor implements Extractor, SeekMap {
return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
// SeekMap implementation.
@Override
public long getDurationUs() {
return wavHeader.getDurationUs();
}
@Override
public boolean isSeekable() {
return true;
}
@Override
public long getPosition(long timeUs) {
return wavHeader.getPosition(timeUs);
}
}

View File

@ -16,9 +16,10 @@
package com.google.android.exoplayer2.extractor.wav;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.SeekMap;
/** Header for a WAV file. */
/*package*/ final class WavHeader {
/* package */ final class WavHeader implements SeekMap {
/** Number of audio chanels. */
private final int numChannels;
@ -49,12 +50,56 @@ import com.google.android.exoplayer2.C;
this.encoding = encoding;
}
/** Returns the duration in microseconds of this WAV. */
// Setting bounds.
/**
* Sets the data start position and size in bytes of sample data in this WAV.
*
* @param dataStartPosition The data start position in bytes.
* @param dataSize The data size in bytes.
*/
public void setDataBounds(long dataStartPosition, long dataSize) {
this.dataStartPosition = dataStartPosition;
this.dataSize = dataSize;
}
/** Returns whether the data start position and size have been set. */
public boolean hasDataBounds() {
return dataStartPosition != 0 && dataSize != 0;
}
// SeekMap implementation.
@Override
public boolean isSeekable() {
return true;
}
@Override
public long getDurationUs() {
long numFrames = dataSize / blockAlignment;
return (numFrames * C.MICROS_PER_SECOND) / sampleRateHz;
}
@Override
public long getPosition(long timeUs) {
long unroundedPosition = (timeUs * averageBytesPerSecond) / C.MICROS_PER_SECOND;
// Round down to nearest frame.
long position = (unroundedPosition / blockAlignment) * blockAlignment;
return Math.min(position, dataSize - blockAlignment) + dataStartPosition;
}
// Misc getters.
/**
* Returns the time in microseconds for the given position in bytes.
*
* @param position The position in bytes.
*/
public long getTimeUs(long position) {
return position * C.MICROS_PER_SECOND / averageBytesPerSecond;
}
/** Returns the bytes per frame of this WAV. */
public int getBytesPerFrame() {
return blockAlignment;
@ -75,33 +120,8 @@ import com.google.android.exoplayer2.C;
return numChannels;
}
/** Returns the position in bytes in this WAV for the given time in microseconds. */
public long getPosition(long timeUs) {
long unroundedPosition = (timeUs * averageBytesPerSecond) / C.MICROS_PER_SECOND;
// Round down to nearest frame.
long position = (unroundedPosition / blockAlignment) * blockAlignment;
return Math.min(position, dataSize - blockAlignment) + dataStartPosition;
}
/** Returns the time in microseconds for the given position in bytes in this WAV. */
public long getTimeUs(long position) {
return position * C.MICROS_PER_SECOND / averageBytesPerSecond;
}
/** Returns true if the data start position and size have been set. */
public boolean hasDataBounds() {
return dataStartPosition != 0 && dataSize != 0;
}
/** Sets the start position and size in bytes of sample data in this WAV. */
public void setDataBounds(long dataStartPosition, long dataSize) {
this.dataStartPosition = dataStartPosition;
this.dataSize = dataSize;
}
/** Returns the PCM encoding. **/
@C.PcmEncoding
public int getEncoding() {
public @C.PcmEncoding int getEncoding() {
return encoding;
}