Flesh out ExoPlayer extensions.
1. AudioDecoderTrackRenderer now reports decoder initialization and AudioTrack underruns. 2. AudioDecoderTrackRenderer can now render more than one output buffer per call to doSomeWork, to be consistent with MediaCodecAudioTrackRenderer. This may also prevent audio underruns in the case that audio is fragmented into many small buffers. 3. AudioDecoderTrackRenderer now has an overridable method that receives the audio session id, to be consistent with MediaCodecAudioTrackRenderer. 4. Fix unsafe event notification in LibvpxVideoTrackRenderer. 5. Vpx and AudioDecoder extensions now increment the CodecCounter inputBufferCount field correctly. 6. Decoders now have names :). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=122250009
This commit is contained in:
parent
97c633f128
commit
3760f514a9
@ -61,6 +61,11 @@ import java.util.List;
|
|||||||
maxOutputBufferSize = streamInfo.maxDecodedFrameSize();
|
maxOutputBufferSize = streamInfo.maxDecodedFrameSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "libflac";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DecoderInputBuffer createInputBuffer() {
|
public DecoderInputBuffer createInputBuffer() {
|
||||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||||
|
@ -132,6 +132,11 @@ import java.util.List;
|
|||||||
setInitialInputBufferSize(initialInputBufferSize);
|
setInitialInputBufferSize(initialInputBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "libopus" + getLibopusVersion();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DecoderInputBuffer createInputBuffer() {
|
public DecoderInputBuffer createInputBuffer() {
|
||||||
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
|
return new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
|
||||||
|
@ -151,13 +151,15 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
try {
|
try {
|
||||||
if (decoder == null) {
|
if (decoder == null) {
|
||||||
// If we don't have a decoder yet, we need to instantiate one.
|
// If we don't have a decoder yet, we need to instantiate one.
|
||||||
long startElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||||
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE);
|
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE);
|
||||||
decoder.setOutputMode(outputMode);
|
decoder.setOutputMode(outputMode);
|
||||||
notifyDecoderInitialized(startElapsedRealtimeMs, SystemClock.elapsedRealtime());
|
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
|
||||||
|
notifyDecoderInitialized(decoder.getName(), codecInitializedTimestamp,
|
||||||
|
codecInitializedTimestamp - codecInitializingTimestamp);
|
||||||
codecCounters.codecInitCount++;
|
codecCounters.codecInitCount++;
|
||||||
}
|
}
|
||||||
while (processOutputBuffer(positionUs)) {}
|
while (drainOutputBuffer(positionUs)) {}
|
||||||
while (feedInputBuffer()) {}
|
while (feedInputBuffer()) {}
|
||||||
} catch (VpxDecoderException e) {
|
} catch (VpxDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||||
@ -165,8 +167,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
codecCounters.ensureUpdated();
|
codecCounters.ensureUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processOutputBuffer(long positionUs)
|
private boolean drainOutputBuffer(long positionUs) throws VpxDecoderException {
|
||||||
throws VpxDecoderException {
|
|
||||||
if (outputStreamEnded) {
|
if (outputStreamEnded) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -226,7 +227,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
|
|
||||||
private void renderBuffer() {
|
private void renderBuffer() {
|
||||||
codecCounters.renderedOutputBufferCount++;
|
codecCounters.renderedOutputBufferCount++;
|
||||||
notifyIfVideoSizeChanged(outputBuffer);
|
notifyIfVideoSizeChanged(outputBuffer.width, outputBuffer.height);
|
||||||
if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) {
|
if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) {
|
||||||
renderRgbFrame(outputBuffer, scaleToFit);
|
renderRgbFrame(outputBuffer, scaleToFit);
|
||||||
if (!drawnToSurface) {
|
if (!drawnToSurface) {
|
||||||
@ -280,9 +281,13 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
if (inputBuffer.isEndOfStream()) {
|
if (inputBuffer.isEndOfStream()) {
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
|
inputBuffer = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
inputBuffer.flip();
|
inputBuffer.flip();
|
||||||
decoder.queueInputBuffer(inputBuffer);
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
|
codecCounters.inputBufferCount++;
|
||||||
inputBuffer = null;
|
inputBuffer = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -398,16 +403,16 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyIfVideoSizeChanged(final VpxOutputBuffer outputBuffer) {
|
private void notifyIfVideoSizeChanged(final int width, final int height) {
|
||||||
if (previousWidth == -1 || previousHeight == -1
|
if (previousWidth == -1 || previousHeight == -1 || previousWidth != width
|
||||||
|| previousWidth != outputBuffer.width || previousHeight != outputBuffer.height) {
|
|| previousHeight != height) {
|
||||||
previousWidth = outputBuffer.width;
|
previousWidth = width;
|
||||||
previousHeight = outputBuffer.height;
|
previousHeight = height;
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
eventListener.onVideoSizeChanged(outputBuffer.width, outputBuffer.height, 0, 1);
|
eventListener.onVideoSizeChanged(width, height, 0, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -441,14 +446,14 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyDecoderInitialized(
|
private void notifyDecoderInitialized(final String decoderName,
|
||||||
final long startElapsedRealtimeMs, final long finishElapsedRealtimeMs) {
|
final long initializedTimestamp, final long initializationDuration) {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
eventListener.onDecoderInitialized("libvpx" + getLibvpxVersion(),
|
eventListener.onDecoderInitialized(decoderName, initializedTimestamp,
|
||||||
finishElapsedRealtimeMs, finishElapsedRealtimeMs - startElapsedRealtimeMs);
|
initializationDuration);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,11 @@ import java.nio.ByteBuffer;
|
|||||||
setInitialInputBufferSize(initialInputBufferSize);
|
setInitialInputBufferSize(initialInputBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "libvpx" + getLibvpxVersion();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the output mode for frames rendered by the decoder.
|
* Sets the output mode for frames rendered by the decoder.
|
||||||
*
|
*
|
||||||
|
@ -30,6 +30,7 @@ import com.google.android.exoplayer.audio.AudioTrack;
|
|||||||
import com.google.android.exoplayer.util.MimeTypes;
|
import com.google.android.exoplayer.util.MimeTypes;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes and renders audio using a {@link SimpleDecoder}.
|
* Decodes and renders audio using a {@link SimpleDecoder}.
|
||||||
@ -63,6 +64,9 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
private final AudioTrack audioTrack;
|
private final AudioTrack audioTrack;
|
||||||
private int audioSessionId;
|
private int audioSessionId;
|
||||||
|
|
||||||
|
private boolean audioTrackHasData;
|
||||||
|
private long lastFeedElapsedRealtimeMs;
|
||||||
|
|
||||||
public AudioDecoderTrackRenderer() {
|
public AudioDecoderTrackRenderer() {
|
||||||
this(null, null);
|
this(null, null);
|
||||||
}
|
}
|
||||||
@ -101,16 +105,20 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
// If we don't have a decoder yet, we need to instantiate one.
|
// If we don't have a decoder yet, we need to instantiate one.
|
||||||
if (decoder == null) {
|
if (decoder == null) {
|
||||||
try {
|
try {
|
||||||
|
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||||
decoder = createDecoder(inputFormat);
|
decoder = createDecoder(inputFormat);
|
||||||
|
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
|
||||||
|
notifyDecoderInitialized(decoder.getName(), codecInitializedTimestamp,
|
||||||
|
codecInitializedTimestamp - codecInitializingTimestamp);
|
||||||
|
codecCounters.codecInitCount++;
|
||||||
} catch (AudioDecoderException e) {
|
} catch (AudioDecoderException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||||
}
|
}
|
||||||
codecCounters.codecInitCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendering loop.
|
// Rendering loop.
|
||||||
try {
|
try {
|
||||||
renderBuffer();
|
while (drainOutputBuffer()) {}
|
||||||
while (feedInputBuffer()) {}
|
while (feedInputBuffer()) {}
|
||||||
} catch (AudioTrack.InitializationException e) {
|
} catch (AudioTrack.InitializationException e) {
|
||||||
notifyAudioTrackInitializationError(e);
|
notifyAudioTrackInitializationError(e);
|
||||||
@ -145,16 +153,16 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
null, null, null);
|
null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderBuffer() throws AudioDecoderException, AudioTrack.InitializationException,
|
private boolean drainOutputBuffer() throws AudioDecoderException,
|
||||||
AudioTrack.WriteException {
|
AudioTrack.InitializationException, AudioTrack.WriteException {
|
||||||
if (outputStreamEnded) {
|
if (outputStreamEnded) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputBuffer == null) {
|
if (outputBuffer == null) {
|
||||||
outputBuffer = decoder.dequeueOutputBuffer();
|
outputBuffer = decoder.dequeueOutputBuffer();
|
||||||
if (outputBuffer == null) {
|
if (outputBuffer == null) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +171,7 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
audioTrack.handleEndOfStream();
|
audioTrack.handleEndOfStream();
|
||||||
outputBuffer.release();
|
outputBuffer.release();
|
||||||
outputBuffer = null;
|
outputBuffer = null;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!audioTrack.isInitialized()) {
|
if (!audioTrack.isInitialized()) {
|
||||||
@ -174,14 +182,26 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
audioTrack.initialize(audioSessionId);
|
audioTrack.initialize(audioSessionId);
|
||||||
} else {
|
} else {
|
||||||
audioSessionId = audioTrack.initialize();
|
audioSessionId = audioTrack.initialize();
|
||||||
|
onAudioSessionId(audioSessionId);
|
||||||
}
|
}
|
||||||
|
audioTrackHasData = false;
|
||||||
if (getState() == TrackRenderer.STATE_STARTED) {
|
if (getState() == TrackRenderer.STATE_STARTED) {
|
||||||
audioTrack.play();
|
audioTrack.play();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Check for AudioTrack underrun.
|
||||||
|
boolean audioTrackHadData = audioTrackHasData;
|
||||||
|
audioTrackHasData = audioTrack.hasPendingData();
|
||||||
|
if (audioTrackHadData && !audioTrackHasData && getState() == TrackRenderer.STATE_STARTED) {
|
||||||
|
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
|
||||||
|
long bufferSizeUs = audioTrack.getBufferSizeUs();
|
||||||
|
long bufferSizeMs = bufferSizeUs == C.UNSET_TIME_US ? -1 : bufferSizeUs / 1000;
|
||||||
|
notifyAudioTrackUnderrun(audioTrack.getBufferSize(), bufferSizeMs, elapsedSinceLastFeedMs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int handleBufferResult;
|
int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timestampUs);
|
||||||
handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timestampUs);
|
lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
// If we are out of sync, allow currentPositionUs to jump backwards.
|
// If we are out of sync, allow currentPositionUs to jump backwards.
|
||||||
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
|
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
|
||||||
@ -193,7 +213,10 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
codecCounters.renderedOutputBufferCount++;
|
codecCounters.renderedOutputBufferCount++;
|
||||||
outputBuffer.release();
|
outputBuffer.release();
|
||||||
outputBuffer = null;
|
outputBuffer = null;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean feedInputBuffer() throws AudioDecoderException {
|
private boolean feedInputBuffer() throws AudioDecoderException {
|
||||||
@ -218,10 +241,13 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
}
|
}
|
||||||
if (inputBuffer.isEndOfStream()) {
|
if (inputBuffer.isEndOfStream()) {
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
|
inputBuffer = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBuffer.flip();
|
inputBuffer.flip();
|
||||||
decoder.queueInputBuffer(inputBuffer);
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
|
codecCounters.inputBufferCount++;
|
||||||
inputBuffer = null;
|
inputBuffer = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -269,6 +295,19 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when the audio session id becomes known. Once the id is known it will not change
|
||||||
|
* (and hence this method will not be invoked again) unless the renderer is disabled and then
|
||||||
|
* subsequently re-enabled.
|
||||||
|
* <p>
|
||||||
|
* The default implementation is a no-op.
|
||||||
|
*
|
||||||
|
* @param audioSessionId The audio session id.
|
||||||
|
*/
|
||||||
|
protected void onAudioSessionId(int audioSessionId) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onEnabled(Format[] formats, boolean joining) throws ExoPlaybackException {
|
protected void onEnabled(Format[] formats, boolean joining) throws ExoPlaybackException {
|
||||||
notifyAudioCodecCounters();
|
notifyAudioCodecCounters();
|
||||||
@ -320,6 +359,19 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyDecoderInitialized(final String decoderName,
|
||||||
|
final long initializedTimestamp, final long initializationDuration) {
|
||||||
|
if (eventHandler != null && eventListener != null) {
|
||||||
|
eventHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
eventListener.onDecoderInitialized(decoderName, initializedTimestamp,
|
||||||
|
initializationDuration);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyAudioTrackInitializationError(final AudioTrack.InitializationException e) {
|
private void notifyAudioTrackInitializationError(final AudioTrack.InitializationException e) {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@ -342,6 +394,18 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyAudioTrackUnderrun(final int bufferSize, final long bufferSizeMs,
|
||||||
|
final long elapsedSinceLastFeedMs) {
|
||||||
|
if (eventHandler != null && eventListener != null) {
|
||||||
|
eventHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
eventListener.onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyAudioCodecCounters() {
|
private void notifyAudioCodecCounters() {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
|
@ -24,6 +24,13 @@ package com.google.android.exoplayer.extensions;
|
|||||||
*/
|
*/
|
||||||
public interface Decoder<I, O, E extends Exception> {
|
public interface Decoder<I, O, E extends Exception> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the decoder.
|
||||||
|
*
|
||||||
|
* @return The name of the decoder.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dequeues the next input buffer to be filled and queued to the decoder.
|
* Dequeues the next input buffer to be filled and queued to the decoder.
|
||||||
*
|
*
|
||||||
|
@ -27,11 +27,19 @@ public abstract class SimpleSubtitleParser extends
|
|||||||
SimpleDecoder<SubtitleInputBuffer, SubtitleOutputBuffer, ParserException> implements
|
SimpleDecoder<SubtitleInputBuffer, SubtitleOutputBuffer, ParserException> implements
|
||||||
SubtitleParser {
|
SubtitleParser {
|
||||||
|
|
||||||
protected SimpleSubtitleParser() {
|
private final String name;
|
||||||
|
|
||||||
|
protected SimpleSubtitleParser(String name) {
|
||||||
super(new SubtitleInputBuffer[2], new SubtitleOutputBuffer[2]);
|
super(new SubtitleInputBuffer[2], new SubtitleOutputBuffer[2]);
|
||||||
|
this.name = name;
|
||||||
setInitialInputBufferSize(1024);
|
setInitialInputBufferSize(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPositionUs(long timeUs) {
|
public void setPositionUs(long timeUs) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
@ -205,6 +205,11 @@ public final class Eia608Parser implements SubtitleParser {
|
|||||||
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
|
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Eia608Parser";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPositionUs(long positionUs) {
|
public void setPositionUs(long positionUs) {
|
||||||
playbackPositionUs = positionUs;
|
playbackPositionUs = positionUs;
|
||||||
|
@ -43,6 +43,7 @@ public final class SubripParser extends SimpleSubtitleParser {
|
|||||||
private final StringBuilder textBuilder;
|
private final StringBuilder textBuilder;
|
||||||
|
|
||||||
public SubripParser() {
|
public SubripParser() {
|
||||||
|
super("SubripParser");
|
||||||
textBuilder = new StringBuilder();
|
textBuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ public final class TtmlParser extends SimpleSubtitleParser {
|
|||||||
private final XmlPullParserFactory xmlParserFactory;
|
private final XmlPullParserFactory xmlParserFactory;
|
||||||
|
|
||||||
public TtmlParser() {
|
public TtmlParser() {
|
||||||
|
super("TtmlParser");
|
||||||
try {
|
try {
|
||||||
xmlParserFactory = XmlPullParserFactory.newInstance();
|
xmlParserFactory = XmlPullParserFactory.newInstance();
|
||||||
xmlParserFactory.setNamespaceAware(true);
|
xmlParserFactory.setNamespaceAware(true);
|
||||||
|
@ -26,6 +26,10 @@ import com.google.android.exoplayer.text.Subtitle;
|
|||||||
*/
|
*/
|
||||||
public final class Tx3gParser extends SimpleSubtitleParser {
|
public final class Tx3gParser extends SimpleSubtitleParser {
|
||||||
|
|
||||||
|
public Tx3gParser() {
|
||||||
|
super("Tx3gParser");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Subtitle decode(byte[] bytes, int length) {
|
protected Subtitle decode(byte[] bytes, int length) {
|
||||||
String cueText = new String(bytes, 0, length);
|
String cueText = new String(bytes, 0, length);
|
||||||
|
@ -40,6 +40,7 @@ public final class Mp4WebvttParser extends SimpleSubtitleParser {
|
|||||||
private final WebvttCue.Builder builder;
|
private final WebvttCue.Builder builder;
|
||||||
|
|
||||||
public Mp4WebvttParser() {
|
public Mp4WebvttParser() {
|
||||||
|
super("Mp4WebvttParser");
|
||||||
sampleData = new ParsableByteArray();
|
sampleData = new ParsableByteArray();
|
||||||
builder = new WebvttCue.Builder();
|
builder = new WebvttCue.Builder();
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ public final class WebvttParser extends SimpleSubtitleParser {
|
|||||||
private final List<WebvttCssStyle> definedStyles;
|
private final List<WebvttCssStyle> definedStyles;
|
||||||
|
|
||||||
public WebvttParser() {
|
public WebvttParser() {
|
||||||
|
super("WebvttParser");
|
||||||
cueParser = new WebvttCueParser();
|
cueParser = new WebvttCueParser();
|
||||||
parsableWebvttData = new ParsableByteArray();
|
parsableWebvttData = new ParsableByteArray();
|
||||||
webvttCueBuilder = new WebvttCue.Builder();
|
webvttCueBuilder = new WebvttCue.Builder();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user