@nativescript/canvas-media 2.0.0-webgpu.0 → 2.0.0-webgpu.2

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