@nativescript/canvas-media 1.1.0 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/audio/common.js.map +1 -1
- package/package.json +2 -3
- package/platforms/android/canvas_media.aar +0 -0
- package/platforms/android/java/org/nativescript/canvas/media/VideoHelper.java +663 -0
- package/platforms/android/res/layout/player.xml +2 -1
- package/video/common.js +12 -9
- package/video/common.js.map +1 -1
- package/video/index.android.d.ts +13 -24
- package/video/index.android.js +59 -276
- package/video/index.android.js.map +1 -1
- package/video/index.ios.js +5 -4
- package/video/index.ios.js.map +1 -1
- package/LICENSE +0 -201
package/audio/common.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/audio/common.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAuB,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../../packages/canvas-media/audio/common.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAuB,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAGpE,IAAsB,SAAS,GAA/B,MAAsB,SAAU,SAAQ,WAAW;CAIlD,CAAA;AAJqB,SAAS;IAD9B,OAAO,CAAC,OAAO,CAAC;GACK,SAAS,CAI9B;SAJqB,SAAS;AAM/B,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,QAAQ,CAAqB;IAChE,IAAI,EAAE,UAAU;IAChB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,KAAK;CACnB,CAAC,CAAC;AACH,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAqB;IAC5D,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,KAAK;CACnB,CAAC,CAAC;AAEH,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,QAAQ,CAAqB;IAChE,IAAI,EAAE,UAAU;IAChB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,KAAK;CACnB,CAAC,CAAC;AAEH,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nativescript/canvas-media",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
4
|
"description": "Canvas media",
|
|
5
5
|
"main": "index",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -31,6 +31,5 @@
|
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"homepage": "https://github.com/NativeScript/plugins",
|
|
33
33
|
"readmeFilename": "README.md",
|
|
34
|
-
"bootstrapper": "@nativescript/plugin-seed"
|
|
35
|
-
"types": "./index.d.ts"
|
|
34
|
+
"bootstrapper": "@nativescript/plugin-seed"
|
|
36
35
|
}
|
|
Binary file
|
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
package org.nativescript.canvas.media;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.net.Uri;
|
|
5
|
+
import android.os.Build;
|
|
6
|
+
import android.os.Handler;
|
|
7
|
+
import android.os.Looper;
|
|
8
|
+
import android.view.LayoutInflater;
|
|
9
|
+
import android.view.Surface;
|
|
10
|
+
import android.view.View;
|
|
11
|
+
import android.view.ViewGroup;
|
|
12
|
+
import android.widget.FrameLayout;
|
|
13
|
+
import android.widget.LinearLayout;
|
|
14
|
+
|
|
15
|
+
import java.io.File;
|
|
16
|
+
import java.lang.reflect.InvocationTargetException;
|
|
17
|
+
import java.lang.reflect.Method;
|
|
18
|
+
import java.util.ArrayList;
|
|
19
|
+
import java.util.Collections;
|
|
20
|
+
import java.util.List;
|
|
21
|
+
import java.util.Timer;
|
|
22
|
+
import java.util.TimerTask;
|
|
23
|
+
|
|
24
|
+
import com.google.android.exoplayer2.DeviceInfo;
|
|
25
|
+
import com.google.android.exoplayer2.MediaItem;
|
|
26
|
+
import com.google.android.exoplayer2.MediaMetadata;
|
|
27
|
+
import com.google.android.exoplayer2.PlaybackException;
|
|
28
|
+
import com.google.android.exoplayer2.PlaybackParameters;
|
|
29
|
+
import com.google.android.exoplayer2.Player;
|
|
30
|
+
import com.google.android.exoplayer2.Timeline;
|
|
31
|
+
import com.google.android.exoplayer2.TracksInfo;
|
|
32
|
+
import com.google.android.exoplayer2.audio.AudioAttributes;
|
|
33
|
+
import com.google.android.exoplayer2.metadata.Metadata;
|
|
34
|
+
import com.google.android.exoplayer2.source.TrackGroupArray;
|
|
35
|
+
import com.google.android.exoplayer2.text.Cue;
|
|
36
|
+
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
|
37
|
+
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
|
38
|
+
import com.google.android.exoplayer2.ui.StyledPlayerView;
|
|
39
|
+
import com.google.android.exoplayer2.ExoPlayer;
|
|
40
|
+
|
|
41
|
+
import android.view.TextureView;
|
|
42
|
+
|
|
43
|
+
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
|
44
|
+
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
|
|
45
|
+
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
|
46
|
+
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
|
|
47
|
+
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
|
|
48
|
+
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
|
49
|
+
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
|
50
|
+
|
|
51
|
+
import android.graphics.SurfaceTexture;
|
|
52
|
+
|
|
53
|
+
import androidx.annotation.Nullable;
|
|
54
|
+
import androidx.annotation.RequiresApi;
|
|
55
|
+
|
|
56
|
+
import com.google.android.exoplayer2.DefaultLoadControl;
|
|
57
|
+
import com.google.android.exoplayer2.util.Util;
|
|
58
|
+
import com.google.android.exoplayer2.video.VideoSize;
|
|
59
|
+
|
|
60
|
+
import org.nativescript.canvas_media.R;
|
|
61
|
+
|
|
62
|
+
@RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
|
63
|
+
public class VideoHelper implements Player.Listener, SurfaceTexture.OnFrameAvailableListener {
|
|
64
|
+
public static class Source {
|
|
65
|
+
String src;
|
|
66
|
+
String type;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
LinearLayout _container;
|
|
70
|
+
|
|
71
|
+
ArrayList<Source> _sourceView;
|
|
72
|
+
StyledPlayerView _playerView;
|
|
73
|
+
ExoPlayer _player;
|
|
74
|
+
String _src;
|
|
75
|
+
boolean _autoplay;
|
|
76
|
+
boolean _loop;
|
|
77
|
+
TextureView _textureView;
|
|
78
|
+
private DefaultDataSource.Factory _dsf;
|
|
79
|
+
|
|
80
|
+
private static SimpleCache _cache;
|
|
81
|
+
private LeastRecentlyUsedCacheEvictor _leastRecentlyUsedCacheEvictor;
|
|
82
|
+
private StandaloneDatabaseProvider _exoDatabaseProvider;
|
|
83
|
+
private static final long _exoPlayerCacheSize = 100 * 1024 * 1024;
|
|
84
|
+
private DefaultMediaSourceFactory _msf;
|
|
85
|
+
private CacheDataSource.Factory _cdsf;
|
|
86
|
+
boolean _isCustom = false;
|
|
87
|
+
boolean _playing = false;
|
|
88
|
+
Timer _timer;
|
|
89
|
+
SurfaceTexture _st;
|
|
90
|
+
Surface _surface;
|
|
91
|
+
Object _render;
|
|
92
|
+
Object _frameListener;
|
|
93
|
+
Object _canvas;
|
|
94
|
+
Timer _frameTimer;
|
|
95
|
+
int _readyState = 0;
|
|
96
|
+
int _videoWidth = 0;
|
|
97
|
+
int _videoHeight = 0;
|
|
98
|
+
|
|
99
|
+
boolean _hasFrame = false;
|
|
100
|
+
static int BUFFER_MS = 500;
|
|
101
|
+
public static boolean IS_DEBUG = true;
|
|
102
|
+
|
|
103
|
+
public interface Callback {
|
|
104
|
+
void onDurationChange(long duration);
|
|
105
|
+
|
|
106
|
+
void onPlaying();
|
|
107
|
+
|
|
108
|
+
void onVideoSizeChanged(int width, int height);
|
|
109
|
+
|
|
110
|
+
void onCurrentTimeChanged(long time);
|
|
111
|
+
|
|
112
|
+
void onVideoFrame();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private Callback _callback;
|
|
116
|
+
|
|
117
|
+
public void setCallback(Callback callback) {
|
|
118
|
+
this._callback = callback;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Override
|
|
122
|
+
public void onRepeatModeChanged(int repeatMode) {
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Override
|
|
126
|
+
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Override
|
|
130
|
+
public void onPlaybackSuppressionReasonChanged(int playbackSuppressionReason) {
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@Override
|
|
134
|
+
public void onPlaybackStateChanged(int playbackState) {
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@Override
|
|
138
|
+
public void onPositionDiscontinuity(Player.PositionInfo oldPosition, Player.PositionInfo newPosition, int reason) {
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@Override
|
|
142
|
+
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@Override
|
|
146
|
+
public void onTimelineChanged(Timeline timeline, int reason) {
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@Override
|
|
151
|
+
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@Override
|
|
156
|
+
public void onIsLoadingChanged(boolean isLoading) {
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@Override
|
|
160
|
+
public void onDeviceVolumeChanged(int volume, boolean muted) {
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@Override
|
|
164
|
+
public void onDeviceInfoChanged(DeviceInfo deviceInfo) {
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@Override
|
|
168
|
+
public void onRenderedFirstFrame() {
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@Override
|
|
173
|
+
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@Override
|
|
178
|
+
public void onAudioAttributesChanged(AudioAttributes audioAttributes) {
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@Override
|
|
183
|
+
public void onAudioSessionIdChanged(int audioSessionId) {
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@Override
|
|
188
|
+
public void onAvailableCommandsChanged(Player.Commands availableCommands) {
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@Override
|
|
193
|
+
public void onCues(List<Cue> cues) {
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@Override
|
|
198
|
+
public void onEvents(Player player, Player.Events events) {
|
|
199
|
+
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@Override
|
|
203
|
+
public void onMaxSeekToPreviousPositionChanged(long maxSeekToPreviousPositionMs) {
|
|
204
|
+
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@Override
|
|
208
|
+
public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@Override
|
|
213
|
+
public void onMetadata(Metadata metadata) {
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@Override
|
|
218
|
+
public void onPlayerErrorChanged(@Nullable PlaybackException error) {
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@Override
|
|
223
|
+
public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) {
|
|
224
|
+
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@Override
|
|
228
|
+
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@Override
|
|
233
|
+
public void onSeekBackIncrementChanged(long seekBackIncrementMs) {
|
|
234
|
+
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@Override
|
|
238
|
+
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@Override
|
|
243
|
+
public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@Override
|
|
247
|
+
public void onSurfaceSizeChanged(int width, int height) {
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@Override
|
|
252
|
+
public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {
|
|
253
|
+
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@Override
|
|
257
|
+
public void onVolumeChanged(float volume) {
|
|
258
|
+
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@Override
|
|
262
|
+
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@Override
|
|
267
|
+
public void onLoadingChanged(boolean isLoading) {
|
|
268
|
+
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Override
|
|
272
|
+
public void onPositionDiscontinuity(int reason) {
|
|
273
|
+
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@Override
|
|
277
|
+
public void onSeekProcessed() {
|
|
278
|
+
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@Override
|
|
282
|
+
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
|
283
|
+
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@Override
|
|
287
|
+
public void onIsPlayingChanged(boolean isPlaying) {
|
|
288
|
+
long duration = this._player.getDuration();
|
|
289
|
+
if (this.getDuration() != duration) {
|
|
290
|
+
if (this._callback != null) {
|
|
291
|
+
this._callback.onDurationChange(duration);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
this._playing = isPlaying;
|
|
295
|
+
if (isPlaying) {
|
|
296
|
+
if (this._callback != null) {
|
|
297
|
+
this._callback.onPlaying();
|
|
298
|
+
this._callback.onVideoFrame();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (_timer != null) {
|
|
302
|
+
_timer.cancel();
|
|
303
|
+
_timer.purge();
|
|
304
|
+
_timer = null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (_frameTimer != null) {
|
|
308
|
+
_frameTimer.cancel();
|
|
309
|
+
_frameTimer.purge();
|
|
310
|
+
_frameTimer = null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
_timer = new Timer();
|
|
314
|
+
VideoHelper that = this;
|
|
315
|
+
_timer.scheduleAtFixedRate(new TimerTask() {
|
|
316
|
+
@Override
|
|
317
|
+
public void run() {
|
|
318
|
+
handler.post(() -> {
|
|
319
|
+
long current = _player.getCurrentPosition();
|
|
320
|
+
if (current != that.getCurrentTime()) {
|
|
321
|
+
if (that._callback != null) {
|
|
322
|
+
that._callback.onCurrentTimeChanged(current);
|
|
323
|
+
that._callback.onVideoFrame();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}, 0, 1000);
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
} else {
|
|
332
|
+
if (_timer != null) {
|
|
333
|
+
_timer.cancel();
|
|
334
|
+
_timer.purge();
|
|
335
|
+
_timer = null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (_frameTimer != null) {
|
|
339
|
+
_frameTimer.cancel();
|
|
340
|
+
_frameTimer.purge();
|
|
341
|
+
_frameTimer = null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
if (this._callback != null) {
|
|
346
|
+
this._callback.onCurrentTimeChanged(this._player.getCurrentPosition());
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@Override
|
|
352
|
+
public void onPlayerError(PlaybackException error) {
|
|
353
|
+
if (VideoHelper.IS_DEBUG) {
|
|
354
|
+
android.util.Log.d("JS", "" + error);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@Override
|
|
359
|
+
public void onVideoSizeChanged(VideoSize videoSize) {
|
|
360
|
+
this._videoWidth = videoSize.width;
|
|
361
|
+
this._videoHeight = videoSize.height;
|
|
362
|
+
if (this._callback != null) {
|
|
363
|
+
this._callback.onVideoSizeChanged(videoSize.width, videoSize.height);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
@Override
|
|
369
|
+
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
|
|
370
|
+
this._hasFrame = true;
|
|
371
|
+
if (this._callback != null) {
|
|
372
|
+
this._callback.onVideoFrame();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
Handler handler;
|
|
377
|
+
|
|
378
|
+
public VideoHelper(Context context, String cacheRoot) {
|
|
379
|
+
File cacheDir = new File(cacheRoot, "MEDIA_PLAYER_CACHE");
|
|
380
|
+
if (!cacheDir.exists()) {
|
|
381
|
+
cacheDir.mkdirs();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
Looper looper1 = Looper.myLooper();
|
|
385
|
+
if (looper1 == null) {
|
|
386
|
+
Looper.prepare();
|
|
387
|
+
looper1 = Looper.myLooper();
|
|
388
|
+
}
|
|
389
|
+
handler = new Handler(looper1);
|
|
390
|
+
|
|
391
|
+
_leastRecentlyUsedCacheEvictor = new LeastRecentlyUsedCacheEvictor(VideoHelper._exoPlayerCacheSize);
|
|
392
|
+
String packageName = context.getPackageName();
|
|
393
|
+
_exoDatabaseProvider = new StandaloneDatabaseProvider(context);
|
|
394
|
+
if(_cache == null){
|
|
395
|
+
_cache = new com.google.android.exoplayer2.upstream.cache.SimpleCache(cacheDir, _leastRecentlyUsedCacheEvictor, _exoDatabaseProvider);
|
|
396
|
+
}
|
|
397
|
+
DefaultHttpDataSource.Factory factory = new com.google.android.exoplayer2.upstream.DefaultHttpDataSource.Factory();
|
|
398
|
+
factory.setUserAgent(Util.getUserAgent(context, packageName));
|
|
399
|
+
_dsf = new DefaultDataSource.Factory(context, factory);
|
|
400
|
+
_cdsf = new CacheDataSource.Factory();
|
|
401
|
+
_cdsf.setCache(_cache);
|
|
402
|
+
_cdsf.setUpstreamDataSourceFactory(_dsf);
|
|
403
|
+
_msf = new DefaultMediaSourceFactory(_cdsf);
|
|
404
|
+
|
|
405
|
+
ExoPlayer.Builder builder = new ExoPlayer.Builder(context);
|
|
406
|
+
builder.setMediaSourceFactory(_msf);
|
|
407
|
+
|
|
408
|
+
DefaultLoadControl.Builder loadControl = new DefaultLoadControl.Builder();
|
|
409
|
+
loadControl.setBufferDurationsMs(BUFFER_MS, com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_MAX_BUFFER_MS, BUFFER_MS, BUFFER_MS);
|
|
410
|
+
builder.setLoadControl(loadControl.build());
|
|
411
|
+
_player = builder.build();
|
|
412
|
+
|
|
413
|
+
LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
414
|
+
this._player.addListener(this);
|
|
415
|
+
this._playerView = (StyledPlayerView) inflator.inflate(R.layout.player, null, false);
|
|
416
|
+
this._container = new LinearLayout(context);
|
|
417
|
+
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
|
|
418
|
+
this._textureView = new TextureView(context);
|
|
419
|
+
this._container.addView(this._textureView, params);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
static class Utils {
|
|
423
|
+
private Class<?> canvasUtils;
|
|
424
|
+
private Method canvasCreateRenderAndAttachToGLContext;
|
|
425
|
+
|
|
426
|
+
private Method canvasCreateSurfaceTexture;
|
|
427
|
+
|
|
428
|
+
private Method canvasUpdateTexImage;
|
|
429
|
+
|
|
430
|
+
Utils() {
|
|
431
|
+
try {
|
|
432
|
+
canvasUtils = Class.forName("org.nativescript.canvas.Utils");
|
|
433
|
+
canvasCreateRenderAndAttachToGLContext = canvasUtils.getDeclaredMethod("createRenderAndAttachToGLContext", Long.TYPE, SurfaceTexture.class);
|
|
434
|
+
canvasCreateSurfaceTexture = canvasUtils.getDeclaredMethod("createSurfaceTexture", Long.TYPE);
|
|
435
|
+
canvasUpdateTexImage = canvasUtils.getDeclaredMethod("updateTexImage", Long.TYPE, Boolean.TYPE, SurfaceTexture.class, Class.forName("org.nativescript.canvas.TextureRender"), Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE);
|
|
436
|
+
} catch (Exception e) {
|
|
437
|
+
if (IS_DEBUG) {
|
|
438
|
+
android.util.Log.d("JS", "" + e);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
Object createRenderAndAttachToGLContext(long state, SurfaceTexture st) {
|
|
444
|
+
try {
|
|
445
|
+
return canvasCreateRenderAndAttachToGLContext.invoke(null, state, st);
|
|
446
|
+
} catch (IllegalAccessException ignored) {
|
|
447
|
+
return null;
|
|
448
|
+
} catch (InvocationTargetException ignored) {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
Object[] createSurfaceTexture(long state) {
|
|
454
|
+
try {
|
|
455
|
+
return (Object[]) canvasCreateSurfaceTexture.invoke(null, state);
|
|
456
|
+
} catch (IllegalAccessException ignored) {
|
|
457
|
+
return null;
|
|
458
|
+
} catch (InvocationTargetException ignored) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
public void updateTexImage(long state, boolean flipY, SurfaceTexture st, Object render, int videoWidth, int videoHeight, int internalFormat, int format) {
|
|
464
|
+
try {
|
|
465
|
+
Class<?> TextureRender = Class.forName("org.nativescript.canvas.TextureRender");
|
|
466
|
+
canvasUpdateTexImage.invoke(null, state, flipY, st, TextureRender.cast(render), videoWidth, videoHeight, internalFormat, format);
|
|
467
|
+
} catch (IllegalAccessException ignored) {
|
|
468
|
+
} catch (InvocationTargetException ignored) {
|
|
469
|
+
} catch (ClassNotFoundException ignored) {
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
private final Utils _utils = new Utils();
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
public void getCurrentFrame(boolean isLoaded, long state, boolean flipY, int internalFormat,
|
|
479
|
+
int format) {
|
|
480
|
+
if (isLoaded) {
|
|
481
|
+
View surfaceView = this._playerView.getVideoSurfaceView();
|
|
482
|
+
if (surfaceView instanceof TextureView) {
|
|
483
|
+
SurfaceTexture st = ((TextureView) surfaceView).getSurfaceTexture();
|
|
484
|
+
if (st != null) {
|
|
485
|
+
// @ts-ignore
|
|
486
|
+
this._render = _utils.createRenderAndAttachToGLContext(state, st);
|
|
487
|
+
this._st = st;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (this._st == null) {
|
|
493
|
+
Object[] result = _utils.createSurfaceTexture(state);
|
|
494
|
+
assert result != null;
|
|
495
|
+
this._st = (SurfaceTexture) result[0];
|
|
496
|
+
|
|
497
|
+
this._st.setOnFrameAvailableListener(this);
|
|
498
|
+
|
|
499
|
+
this._surface = new Surface(this._st);
|
|
500
|
+
this._player.setVideoSurface(this._surface);
|
|
501
|
+
this._render = result[1];
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (this._st != null) {
|
|
505
|
+
if (!this._hasFrame) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
_utils.updateTexImage(state, flipY, this._st, this._render, this._videoWidth, this._videoHeight, internalFormat, format);
|
|
509
|
+
this._hasFrame = false;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
public StyledPlayerView getPlayerView(){
|
|
514
|
+
return this._playerView;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
public void setPlayer(){
|
|
518
|
+
this._playerView.setPlayer(this._player);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
public LinearLayout getContainer() {
|
|
522
|
+
return this._container;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
public void setSurface(Surface surface) {
|
|
526
|
+
this._player.setVideoSurface(surface);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private void _setSrc(String value) {
|
|
530
|
+
try {
|
|
531
|
+
|
|
532
|
+
this._player.setMediaItems(Collections.singletonList(MediaItem.fromUri(Uri.parse(value))), true);
|
|
533
|
+
this._player.prepare();
|
|
534
|
+
if (this._autoplay) {
|
|
535
|
+
this._player.setPlayWhenReady(true);
|
|
536
|
+
}
|
|
537
|
+
} catch (Exception e) {
|
|
538
|
+
if (IS_DEBUG) {
|
|
539
|
+
android.util.Log.d("JS", "" + e);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
public void play() {
|
|
545
|
+
this._player.setPlayWhenReady(true);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
public void pause() {
|
|
549
|
+
this._player.setPlayWhenReady(false);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
public boolean getMuted() {
|
|
553
|
+
return this._player.isDeviceMuted();
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
public void setMuted(boolean value) {
|
|
557
|
+
this._player.setDeviceMuted(value);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
public long getDuration() {
|
|
561
|
+
return this._player.getDuration();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
public long getCurrentTime() {
|
|
565
|
+
return this._player.getCurrentPosition() / 1000;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
public void setCurrentTime(long value) {
|
|
569
|
+
this._player.seekTo((int) (value * 1000), 0);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
public String getSrc() {
|
|
573
|
+
return this._src;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
public void setSrc(String value) {
|
|
577
|
+
this._src = value;
|
|
578
|
+
this._setSrc(value);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
public boolean getAutoplay() {
|
|
582
|
+
return this._autoplay;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
public void setAutoplay(boolean value) {
|
|
586
|
+
this._player.setPlayWhenReady(value);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
public boolean getControls() {
|
|
590
|
+
return this._playerView.getUseController();
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
public void setControls(boolean enabled) {
|
|
594
|
+
this._playerView.setUseController(enabled);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
public boolean getLoop() {
|
|
598
|
+
return this._loop;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
public void setLoop(boolean value) {
|
|
602
|
+
this._loop = value;
|
|
603
|
+
if (value) {
|
|
604
|
+
this._player.setRepeatMode(com.google.android.exoplayer2.Player.REPEAT_MODE_ALL);
|
|
605
|
+
} else {
|
|
606
|
+
this._player.setRepeatMode(com.google.android.exoplayer2.Player.REPEAT_MODE_OFF);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
public int getWidth() {
|
|
612
|
+
int width = this._container.getWidth();
|
|
613
|
+
if (width == 0) {
|
|
614
|
+
ViewGroup.LayoutParams rootParams = this._container.getLayoutParams();
|
|
615
|
+
if (rootParams != null) {
|
|
616
|
+
return rootParams.width;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return width;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
public int getHeight() {
|
|
623
|
+
int height = this._container.getHeight();
|
|
624
|
+
if (height == 0) {
|
|
625
|
+
ViewGroup.LayoutParams rootParams = this._container.getLayoutParams();
|
|
626
|
+
if (rootParams != null) {
|
|
627
|
+
return rootParams.height;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return height;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
public void layoutNative(int width, int height) {
|
|
634
|
+
|
|
635
|
+
ViewGroup.LayoutParams rootParams = this._container.getLayoutParams();
|
|
636
|
+
|
|
637
|
+
if (rootParams != null && width == rootParams.width && height == rootParams.height) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (width != 0 && height != 0) {
|
|
642
|
+
if (rootParams == null) {
|
|
643
|
+
rootParams = new android.widget.FrameLayout.LayoutParams(0, 0);
|
|
644
|
+
}
|
|
645
|
+
rootParams.width = width;
|
|
646
|
+
rootParams.height = height;
|
|
647
|
+
FrameLayout.LayoutParams surfaceParams = new android.widget.FrameLayout.LayoutParams(0, 0);
|
|
648
|
+
|
|
649
|
+
this._container.setLayoutParams(rootParams);
|
|
650
|
+
|
|
651
|
+
int w = android.view.View.MeasureSpec.makeMeasureSpec(width, android.view.View.MeasureSpec.EXACTLY);
|
|
652
|
+
int h = android.view.View.MeasureSpec.makeMeasureSpec(height, android.view.View.MeasureSpec.EXACTLY);
|
|
653
|
+
|
|
654
|
+
this._container.measure(w, h);
|
|
655
|
+
|
|
656
|
+
this._container.layout(0, 0, width, height);
|
|
657
|
+
|
|
658
|
+
if (this._st != null) {
|
|
659
|
+
this._st.setDefaultBufferSize(width, height);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<com.google.android.exoplayer2.ui.
|
|
2
|
+
<com.google.android.exoplayer2.ui.StyledPlayerView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
3
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
4
4
|
android:layout_width="match_parent"
|
|
5
5
|
android:layout_height="match_parent"
|
|
6
|
+
app:use_controller="false"
|
|
6
7
|
app:surface_type="texture_view"/>
|