Skip to content

Commit

Permalink
Add loading error reports to ExtractorSampleSource
Browse files Browse the repository at this point in the history
This CL also implements loading errors in the DemoApp by logging them.
The sourceId in the ExtractorSampleSource interface allows a class to
implement the same signature for all the SampleSources. The
eventSourceId in the ExtractorSampleSource is unlikely to be useful,
considering it is expected to use one single source. However, it was
added for two reasons:

* Consistency, since the ChunkSampleSource
* In the strange case that two ExtractorSampleSources live at the same
  time, it would be possible to diferentiate them.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=116366928
  • Loading branch information
AquilesCanta authored and ojw28 committed Mar 10, 2016
1 parent 5f46958 commit c6faacb
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.google.android.exoplayer.chunk.Format;
import com.google.android.exoplayer.dash.DashChunkSource;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.hls.HlsSampleSource;
import com.google.android.exoplayer.metadata.MetadataTrackRenderer.MetadataRenderer;
import com.google.android.exoplayer.metadata.id3.Id3Frame;
Expand All @@ -57,10 +58,11 @@
* SmoothStreaming and so on).
*/
public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener,
HlsSampleSource.EventListener, DefaultBandwidthMeter.EventListener,
MediaCodecVideoTrackRenderer.EventListener, MediaCodecAudioTrackRenderer.EventListener,
StreamingDrmSessionManager.EventListener, DashChunkSource.EventListener, TextRenderer,
MetadataRenderer<List<Id3Frame>>, DebugTextViewHelper.Provider {
HlsSampleSource.EventListener, ExtractorSampleSource.EventListener,
DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener,
MediaCodecAudioTrackRenderer.EventListener, StreamingDrmSessionManager.EventListener,
DashChunkSource.EventListener, TextRenderer, MetadataRenderer<List<Id3Frame>>,
DebugTextViewHelper.Provider {

/**
* Builds renderers for the player.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import android.media.AudioManager;
import android.media.MediaCodec;
import android.net.Uri;
import android.os.Handler;

/**
* A {@link RendererBuilder} for streams that can be read using an {@link Extractor}.
Expand All @@ -56,21 +57,21 @@ public ExtractorRendererBuilder(Context context, String userAgent, Uri uri) {
@Override
public void buildRenderers(DemoPlayer player) {
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
Handler mainHandler = player.getMainHandler();

// Build the video and audio renderers.
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(player.getMainHandler(),
null);
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(mainHandler, null);
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri, dataSource, allocator,
BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE, mainHandler, player, 0);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context,
sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000,
player.getMainHandler(), player, 50);
mainHandler, player, 50);
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource,
MediaCodecSelector.DEFAULT, null, true, player.getMainHandler(), player,
MediaCodecSelector.DEFAULT, null, true, mainHandler, player,
AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC);
TrackRenderer textRenderer = new TextTrackRenderer(sampleSource, player,
player.getMainHandler().getLooper());
mainHandler.getLooper());

// Invoke the callback.
TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.google.android.exoplayer.util.Util;

import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import android.util.SparseArray;

Expand Down Expand Up @@ -69,6 +70,21 @@
public final class ExtractorSampleSource implements SampleSource, SampleSourceReader,
ExtractorOutput, Loader.Callback {

/**
* Interface definition for a callback to be notified of {@link ExtractorSampleSource} events.
*/
public interface EventListener {

/**
* Invoked when an error occurs loading media data.
*
* @param sourceId The id of the reporting {@link SampleSource}.
* @param e The cause of the failure.
*/
void onLoadError(int sourceId, IOException e);

}

/**
* Thrown if the input format could not recognized.
*/
Expand Down Expand Up @@ -176,6 +192,9 @@ public UnrecognizedInputFormatException(Extractor[] extractors) {
private final int minLoadableRetryCount;
private final Uri uri;
private final DataSource dataSource;
private final Handler eventHandler;
private final EventListener eventListener;
private final int eventSourceId;

private volatile boolean tracksBuilt;
private volatile SeekMap seekMap;
Expand Down Expand Up @@ -224,6 +243,26 @@ public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator
extractors);
}

/**
* @param uri The {@link Uri} of the media stream.
* @param dataSource A data source to read the media stream.
* @param allocator An {@link Allocator} from which to obtain memory allocations.
* @param requestedBufferSize The requested total buffer size for storing sample data, in bytes.
* The actual allocated size may exceed the value passed in if the implementation requires it.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @param eventSourceId An identifier that gets passed to {@code eventListener} methods.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing
* priority. If omitted, the default extractors will be used.
*/
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, Handler eventHandler, EventListener eventListener,
int eventSourceId, Extractor... extractors) {
this(uri, dataSource, allocator, requestedBufferSize, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA,
eventHandler, eventListener, eventSourceId, extractors);
}

/**
* @param uri The {@link Uri} of the media stream.
* @param dataSource A data source to read the media stream.
Expand All @@ -237,8 +276,33 @@ public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator
*/
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, int minLoadableRetryCount, Extractor... extractors) {
this(uri, dataSource, allocator, requestedBufferSize, minLoadableRetryCount, null, null, 0,
extractors);
}

/**
* @param uri The {@link Uri} of the media stream.
* @param dataSource A data source to read the media stream.
* @param allocator An {@link Allocator} from which to obtain memory allocations.
* @param requestedBufferSize The requested total buffer size for storing sample data, in bytes.
* The actual allocated size may exceed the value passed in if the implementation requires it.
* @param minLoadableRetryCount The minimum number of times that the sample source will retry
* if a loading error occurs.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @param eventSourceId An identifier that gets passed to {@code eventListener} methods.
* @param extractors {@link Extractor}s to extract the media stream, in order of decreasing
* priority. If omitted, the default extractors will be used.
*/
public ExtractorSampleSource(Uri uri, DataSource dataSource, Allocator allocator,
int requestedBufferSize, int minLoadableRetryCount, Handler eventHandler,
EventListener eventListener, int eventSourceId, Extractor... extractors) {
this.uri = uri;
this.dataSource = dataSource;
this.eventListener = eventListener;
this.eventHandler = eventHandler;
this.eventSourceId = eventSourceId;
this.allocator = allocator;
this.requestedBufferSize = requestedBufferSize;
this.minLoadableRetryCount = minLoadableRetryCount;
Expand Down Expand Up @@ -504,6 +568,7 @@ public void onLoadError(Loadable ignored, IOException e) {
currentLoadableExceptionCount = extractedSampleCount > extractedSampleCountAtStartOfLoad ? 1
: currentLoadableExceptionCount + 1;
currentLoadableExceptionTimestamp = SystemClock.elapsedRealtime();
notifyLoadError(e);
maybeStartLoading();
}

Expand Down Expand Up @@ -661,6 +726,17 @@ private long getRetryDelayMillis(long errorCount) {
return Math.min((errorCount - 1) * 1000, 5000);
}

private void notifyLoadError(final IOException e) {
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onLoadError(eventSourceId, e);
}
});
}
}

/**
* Extension of {@link DefaultTrackOutput} that increments a shared counter of the total number
* of extracted samples.
Expand Down

0 comments on commit c6faacb

Please sign in to comment.