forked from ryanheise/just_audio
/
LazyMediaSource.java
160 lines (137 loc) · 5.38 KB
/
LazyMediaSource.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package com.ryanheise.just_audio;
import android.os.Handler;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* A {@link MediaSource} that lazily defers to another {@link MediaSource} when it is required.
* <p>
* This {@link MediaSource} must be used with a {@link com.google.android.exoplayer2.source.MaskingMediaSource}.
*/
class LazyMediaSource implements MediaSource {
private final LazyMediaSourceProvider mediaSourceProvider;
public final String id;
public final MediaItem placeholderMediaItem;
private final Map<MediaSourceEventListener, Handler> pendingEventListeners = new HashMap<>();
private final Map<DrmSessionEventListener, Handler> pendingDrmEventListeners = new HashMap<>();
private MediaSource mediaSource;
LazyMediaSource(LazyMediaSourceProvider mediaSourceProvider, String id, MediaItem placeholderMediaItem) {
this.mediaSourceProvider = mediaSourceProvider;
this.id = id;
this.placeholderMediaItem = placeholderMediaItem;
}
@Override
public void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
if (mediaSource == null) {
pendingEventListeners.put(eventListener, handler);
} else {
mediaSource.addEventListener(handler, eventListener);
}
}
@Override
public void removeEventListener(MediaSourceEventListener eventListener) {
if (mediaSource == null) {
pendingEventListeners.remove(eventListener);
} else {
mediaSource.removeEventListener(eventListener);
}
}
@Override
public void addDrmEventListener(Handler handler, DrmSessionEventListener eventListener) {
if (mediaSource == null) {
pendingDrmEventListeners.put(eventListener, handler);
} else {
mediaSource.addDrmEventListener(handler, eventListener);
}
}
@Override
public void removeDrmEventListener(DrmSessionEventListener eventListener) {
if (mediaSource == null) {
pendingDrmEventListeners.remove(eventListener);
} else {
mediaSource.removeDrmEventListener(eventListener);
}
}
@Override
public Timeline getInitialTimeline() {
if (mediaSource == null) return null;
return mediaSource.getInitialTimeline();
}
@Override
public boolean isSingleWindow() {
if (mediaSource == null) return false;
return mediaSource.isSingleWindow();
}
@Override
public MediaItem getMediaItem() {
if (mediaSource == null) {
return placeholderMediaItem;
} else {
return mediaSource.getMediaItem();
}
}
@Override
public void prepareSource(
MediaSourceCaller caller,
TransferListener mediaTransferListener,
PlayerId playerId
) {
mediaSourceProvider.createMediaSource(id, (mediaSource) -> {
this.mediaSource = mediaSource;
for (Map.Entry<MediaSourceEventListener, Handler> entry : pendingEventListeners.entrySet()) {
mediaSource.addEventListener(entry.getValue(), entry.getKey());
}
pendingEventListeners.clear();
for (Map.Entry<DrmSessionEventListener, Handler> entry : pendingDrmEventListeners.entrySet()) {
mediaSource.addDrmEventListener(entry.getValue(), entry.getKey());
}
pendingDrmEventListeners.clear();
mediaSource.prepareSource(caller, mediaTransferListener, playerId);
});
}
@Override
public void maybeThrowSourceInfoRefreshError() throws IOException {
if (mediaSource == null) return;
mediaSource.maybeThrowSourceInfoRefreshError();
}
@Override
public void enable(MediaSourceCaller caller) {
if (mediaSource == null) throw new IllegalStateException();
mediaSource.enable(caller);
}
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
if (mediaSource == null) throw new IllegalStateException();
return mediaSource.createPeriod(id, allocator, startPositionUs);
}
@Override
public void releasePeriod(MediaPeriod mediaPeriod) {
if (mediaSource == null) throw new IllegalStateException();
mediaSource.releasePeriod(mediaPeriod);
}
@Override
public void disable(MediaSourceCaller caller) {
if (mediaSource == null) throw new IllegalStateException();
mediaSource.disable(caller);
}
@Override
public void releaseSource(MediaSourceCaller caller) {
if (mediaSource == null) return;
mediaSource.releaseSource(caller);
}
}
interface LazyMediaSourceReceiver {
void onMediaSourceCreated(MediaSource mediaSource);
}
interface LazyMediaSourceProvider {
void createMediaSource(String id, LazyMediaSourceReceiver receiver);
}