expo-libvlc-player 5.0.0 → 5.0.1
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.
|
@@ -42,6 +42,8 @@ private val DISPLAY_MANAGER: DisplayManager? = null
|
|
|
42
42
|
private val ENABLE_SUBTITLES: Boolean = true
|
|
43
43
|
private val USE_TEXTURE_VIEW: Boolean = true
|
|
44
44
|
|
|
45
|
+
private val MAX_RETRY_COUNT: Int = 10
|
|
46
|
+
|
|
45
47
|
class LibVlcPlayerView(
|
|
46
48
|
context: Context,
|
|
47
49
|
appContext: AppContext,
|
|
@@ -53,9 +55,8 @@ class LibVlcPlayerView(
|
|
|
53
55
|
var media: Media? = null
|
|
54
56
|
var vlcDialog: VLCDialog? = null
|
|
55
57
|
|
|
56
|
-
var mediaLength: Long? = null
|
|
57
58
|
var firstPlay: Boolean = true
|
|
58
|
-
var
|
|
59
|
+
private var retryCount: Int = 0
|
|
59
60
|
private var shouldInit: Boolean = true
|
|
60
61
|
|
|
61
62
|
val onBuffering by EventDispatcher<Unit>()
|
|
@@ -137,7 +138,6 @@ class LibVlcPlayerView(
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
firstPlay = true
|
|
140
|
-
firstTime = true
|
|
141
141
|
shouldInit = false
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -208,19 +208,20 @@ class LibVlcPlayerView(
|
|
|
208
208
|
|
|
209
209
|
fun setContentFit() {
|
|
210
210
|
post {
|
|
211
|
-
val
|
|
212
|
-
|
|
211
|
+
val view = getTextureView() ?: return@post
|
|
213
212
|
val matrix = Matrix()
|
|
214
213
|
|
|
215
214
|
mediaPlayer?.let { player ->
|
|
216
215
|
val video = player.getCurrentVideoTrack()
|
|
216
|
+
val width = video?.width ?: 0
|
|
217
|
+
val height = video?.height ?: 0
|
|
217
218
|
|
|
218
|
-
if (
|
|
219
|
-
val viewWidth =
|
|
220
|
-
val viewHeight =
|
|
219
|
+
if (width > 0 && height > 0) {
|
|
220
|
+
val viewWidth = view.width.toFloat()
|
|
221
|
+
val viewHeight = view.height.toFloat()
|
|
221
222
|
|
|
222
|
-
val videoWidth =
|
|
223
|
-
val videoHeight =
|
|
223
|
+
val videoWidth = width.toFloat()
|
|
224
|
+
val videoHeight = height.toFloat()
|
|
224
225
|
|
|
225
226
|
val viewAspect = viewWidth / viewHeight
|
|
226
227
|
val videoAspect = videoWidth / videoHeight
|
|
@@ -260,7 +261,7 @@ class LibVlcPlayerView(
|
|
|
260
261
|
}
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
|
|
264
|
+
view.setTransform(matrix)
|
|
264
265
|
}
|
|
265
266
|
}
|
|
266
267
|
|
|
@@ -270,8 +271,6 @@ class LibVlcPlayerView(
|
|
|
270
271
|
|
|
271
272
|
addPlayerSlaves()
|
|
272
273
|
|
|
273
|
-
setContentFit()
|
|
274
|
-
|
|
275
274
|
if (scale != MediaPlayerConstants.DEFAULT_PLAYER_SCALE) {
|
|
276
275
|
player.setScale(scale)
|
|
277
276
|
}
|
|
@@ -299,6 +298,32 @@ class LibVlcPlayerView(
|
|
|
299
298
|
}
|
|
300
299
|
}
|
|
301
300
|
|
|
301
|
+
fun setupFirstPlay() {
|
|
302
|
+
val tracks = getMediaTracks()
|
|
303
|
+
val media = getMediaInfo()
|
|
304
|
+
val length = getMediaLength()
|
|
305
|
+
|
|
306
|
+
val hasAudio = tracks.audio.any { track -> track.id != -1 }
|
|
307
|
+
val hasVideo = tracks.video.any { track -> track.id != -1 }
|
|
308
|
+
|
|
309
|
+
val hasAudioOnly = hasAudio && !hasVideo && length > 0L
|
|
310
|
+
val hasWidthAndHeight = media.width > 0 && media.height > 0
|
|
311
|
+
val hasAudioAndVideo = hasAudio && hasVideo && hasWidthAndHeight && length > 0L
|
|
312
|
+
|
|
313
|
+
val canFirstPlay = hasAudioOnly || hasAudioAndVideo || retryCount == MAX_RETRY_COUNT
|
|
314
|
+
|
|
315
|
+
if (!canFirstPlay && retryCount < MAX_RETRY_COUNT) {
|
|
316
|
+
retryCount++
|
|
317
|
+
postDelayed(::setupFirstPlay, 100L)
|
|
318
|
+
return
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
retryCount = 0
|
|
322
|
+
onFirstPlay(media)
|
|
323
|
+
setContentFit()
|
|
324
|
+
MediaPlayerManager.audioFocusManager.updateAudioFocus()
|
|
325
|
+
}
|
|
326
|
+
|
|
302
327
|
fun getMediaTracks(): MediaTracks {
|
|
303
328
|
var mediaTracks = MediaTracks()
|
|
304
329
|
|
|
@@ -338,18 +363,26 @@ class LibVlcPlayerView(
|
|
|
338
363
|
return mediaTracks
|
|
339
364
|
}
|
|
340
365
|
|
|
366
|
+
fun getMediaLength(): Long {
|
|
367
|
+
var length: Long = 0L
|
|
368
|
+
|
|
369
|
+
mediaPlayer?.let { player ->
|
|
370
|
+
val duration = player.getLength()
|
|
371
|
+
|
|
372
|
+
if (duration > 0L) {
|
|
373
|
+
length = duration
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return length
|
|
378
|
+
}
|
|
379
|
+
|
|
341
380
|
fun getMediaInfo(): MediaInfo {
|
|
342
381
|
var mediaInfo = MediaInfo()
|
|
343
382
|
|
|
344
383
|
mediaPlayer?.let { player ->
|
|
345
384
|
val video = player.getCurrentVideoTrack()
|
|
346
|
-
val
|
|
347
|
-
val length =
|
|
348
|
-
if (duration != -1L) {
|
|
349
|
-
duration
|
|
350
|
-
} else {
|
|
351
|
-
0L
|
|
352
|
-
}
|
|
385
|
+
val length = getMediaLength()
|
|
353
386
|
val seekable = player.isSeekable()
|
|
354
387
|
|
|
355
388
|
mediaInfo =
|
|
@@ -359,13 +392,6 @@ class LibVlcPlayerView(
|
|
|
359
392
|
length = length.toDouble(),
|
|
360
393
|
seekable = seekable,
|
|
361
394
|
)
|
|
362
|
-
|
|
363
|
-
mediaLength =
|
|
364
|
-
if (length > 0L) {
|
|
365
|
-
length
|
|
366
|
-
} else {
|
|
367
|
-
null
|
|
368
|
-
}
|
|
369
395
|
}
|
|
370
396
|
|
|
371
397
|
return mediaInfo
|
|
@@ -490,8 +516,7 @@ class LibVlcPlayerView(
|
|
|
490
516
|
}
|
|
491
517
|
} else {
|
|
492
518
|
if (type == "position") {
|
|
493
|
-
|
|
494
|
-
time = (value * length.toDouble()).toInt()
|
|
519
|
+
time = (value * getMediaLength().toDouble()).toInt()
|
|
495
520
|
} else {
|
|
496
521
|
time = value.toInt()
|
|
497
522
|
}
|
|
@@ -518,19 +543,20 @@ class LibVlcPlayerView(
|
|
|
518
543
|
fun snapshot(path: String) {
|
|
519
544
|
mediaPlayer?.let { player ->
|
|
520
545
|
try {
|
|
521
|
-
val
|
|
546
|
+
val view = getTextureView() ?: throw Exception()
|
|
522
547
|
val video = player.getCurrentVideoTrack() ?: throw Exception()
|
|
523
548
|
|
|
524
|
-
val
|
|
525
|
-
val
|
|
549
|
+
val width = video.width?.takeIf { it > 0 } ?: throw Exception()
|
|
550
|
+
val height = video.height?.takeIf { it > 0 } ?: throw Exception()
|
|
551
|
+
|
|
552
|
+
val surface = Surface(view.surfaceTexture)
|
|
553
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
526
554
|
|
|
527
555
|
PixelCopy.request(
|
|
528
556
|
surface,
|
|
529
557
|
bitmap,
|
|
530
558
|
{ copyResult ->
|
|
531
|
-
if (copyResult != PixelCopy.SUCCESS)
|
|
532
|
-
throw Exception()
|
|
533
|
-
}
|
|
559
|
+
if (copyResult != PixelCopy.SUCCESS) throw Exception()
|
|
534
560
|
|
|
535
561
|
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd-HH'h'mm'm'ss's'")
|
|
536
562
|
val timestamp = Calendar.getInstance().time
|
|
@@ -582,15 +608,15 @@ fun LibVlcPlayerView.setPlayerListener(player: MediaPlayer) {
|
|
|
582
608
|
onPlaying(Unit)
|
|
583
609
|
|
|
584
610
|
if (firstPlay) {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
attachPlayer()
|
|
611
|
+
setupFirstPlay()
|
|
588
612
|
|
|
589
613
|
setupPlayer()
|
|
590
614
|
|
|
591
615
|
firstPlay = false
|
|
592
616
|
}
|
|
593
617
|
|
|
618
|
+
attachPlayer()
|
|
619
|
+
|
|
594
620
|
MediaPlayerManager.keepAwakeManager.activateKeepAwake()
|
|
595
621
|
MediaPlayerManager.audioFocusManager.updateAudioFocus()
|
|
596
622
|
}
|
|
@@ -609,9 +635,6 @@ fun LibVlcPlayerView.setPlayerListener(player: MediaPlayer) {
|
|
|
609
635
|
|
|
610
636
|
MediaPlayerManager.keepAwakeManager.deactivateKeepAwake()
|
|
611
637
|
MediaPlayerManager.audioFocusManager.updateAudioFocus()
|
|
612
|
-
|
|
613
|
-
firstPlay = true
|
|
614
|
-
firstTime = true
|
|
615
638
|
}
|
|
616
639
|
|
|
617
640
|
Event.EndReached -> {
|
|
@@ -632,12 +655,6 @@ fun LibVlcPlayerView.setPlayerListener(player: MediaPlayer) {
|
|
|
632
655
|
|
|
633
656
|
Event.TimeChanged -> {
|
|
634
657
|
onTimeChanged(mapOf("time" to player.getTime().toInt()))
|
|
635
|
-
|
|
636
|
-
if (firstTime) {
|
|
637
|
-
MediaPlayerManager.audioFocusManager.updateAudioFocus()
|
|
638
|
-
|
|
639
|
-
firstTime = false
|
|
640
|
-
}
|
|
641
658
|
}
|
|
642
659
|
|
|
643
660
|
Event.PositionChanged -> {
|
|
@@ -8,6 +8,8 @@ import UIKit
|
|
|
8
8
|
|
|
9
9
|
private let dialogCustomUI: Bool = true
|
|
10
10
|
|
|
11
|
+
private let maxRetryCount: Int = 10
|
|
12
|
+
|
|
11
13
|
class LibVlcPlayerView: ExpoView {
|
|
12
14
|
private let playerView = UIView()
|
|
13
15
|
|
|
@@ -15,10 +17,10 @@ class LibVlcPlayerView: ExpoView {
|
|
|
15
17
|
var vlcDialog: VLCDialogProvider?
|
|
16
18
|
var vlcDialogRef: NSValue?
|
|
17
19
|
|
|
18
|
-
var mediaLength: Int32?
|
|
19
20
|
var oldVolume: Int = MediaPlayerConstants.maxPlayerVolume
|
|
21
|
+
|
|
20
22
|
var firstPlay: Bool = true
|
|
21
|
-
var
|
|
23
|
+
private var retryCount: Int = 0
|
|
22
24
|
private var shouldInit: Bool = true
|
|
23
25
|
|
|
24
26
|
let onBuffering = EventDispatcher()
|
|
@@ -92,7 +94,6 @@ class LibVlcPlayerView: ExpoView {
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
firstPlay = true
|
|
95
|
-
firstTime = true
|
|
96
97
|
shouldInit = false
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -137,16 +138,17 @@ class LibVlcPlayerView: ExpoView {
|
|
|
137
138
|
|
|
138
139
|
func setContentFit() {
|
|
139
140
|
DispatchQueue.main.async {
|
|
140
|
-
let view = self.playerView
|
|
141
|
-
|
|
141
|
+
let view = self.playerView
|
|
142
142
|
var transform: CGAffineTransform = .identity
|
|
143
143
|
|
|
144
144
|
if let player = self.mediaPlayer {
|
|
145
145
|
let video = player.videoSize
|
|
146
|
+
let width = video.width
|
|
147
|
+
let height = video.height
|
|
146
148
|
|
|
147
|
-
if
|
|
148
|
-
let viewAspect = view.width / view.height
|
|
149
|
-
let videoAspect =
|
|
149
|
+
if width > 0, height > 0 {
|
|
150
|
+
let viewAspect = view.frame.size.width / view.frame.size.height
|
|
151
|
+
let videoAspect = width / height
|
|
150
152
|
|
|
151
153
|
switch self.contentFit {
|
|
152
154
|
case .contain:
|
|
@@ -173,7 +175,7 @@ class LibVlcPlayerView: ExpoView {
|
|
|
173
175
|
}
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
view.transform = transform
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
181
|
|
|
@@ -183,8 +185,6 @@ class LibVlcPlayerView: ExpoView {
|
|
|
183
185
|
|
|
184
186
|
addPlayerSlaves()
|
|
185
187
|
|
|
186
|
-
setContentFit()
|
|
187
|
-
|
|
188
188
|
if scale != MediaPlayerConstants.defaultPlayerScale {
|
|
189
189
|
player.scaleFactor = scale
|
|
190
190
|
}
|
|
@@ -209,6 +209,46 @@ class LibVlcPlayerView: ExpoView {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
func setupFirstPlay() {
|
|
213
|
+
let tracks = getMediaTracks()
|
|
214
|
+
let media = getMediaInfo()
|
|
215
|
+
let length = getMediaLength()
|
|
216
|
+
|
|
217
|
+
let hasAudio = tracks.audio.contains { track in track.id != -1 }
|
|
218
|
+
let hasVideo = tracks.video.contains { track in track.id != -1 }
|
|
219
|
+
|
|
220
|
+
let hasAudioOnly = hasAudio && !hasVideo && length > 0
|
|
221
|
+
let hasWidthAndHeight = media.width > 0 && media.height > 0
|
|
222
|
+
let hasAudioAndVideo = hasAudio && hasVideo && hasWidthAndHeight && length > 0
|
|
223
|
+
|
|
224
|
+
let canFirstPlay = hasAudioOnly || hasAudioAndVideo || retryCount == maxRetryCount
|
|
225
|
+
|
|
226
|
+
if !canFirstPlay, retryCount < maxRetryCount {
|
|
227
|
+
retryCount += 1
|
|
228
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in self?.setupFirstPlay() }
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
retryCount = 0
|
|
233
|
+
onFirstPlay(media)
|
|
234
|
+
setContentFit()
|
|
235
|
+
MediaPlayerManager.shared.audioSessionManager.setAppropriateAudioSession()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
func getMediaLength() -> Int32 {
|
|
239
|
+
var length: Int32 = 0
|
|
240
|
+
|
|
241
|
+
if let player = mediaPlayer, let media = player.media {
|
|
242
|
+
let duration = media.length.intValue
|
|
243
|
+
|
|
244
|
+
if duration > 0 {
|
|
245
|
+
length = duration
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return length
|
|
250
|
+
}
|
|
251
|
+
|
|
212
252
|
func getMediaTracks() -> MediaTracks {
|
|
213
253
|
var mediaTracks = MediaTracks()
|
|
214
254
|
|
|
@@ -261,7 +301,7 @@ class LibVlcPlayerView: ExpoView {
|
|
|
261
301
|
|
|
262
302
|
if let player = mediaPlayer {
|
|
263
303
|
let video = player.videoSize
|
|
264
|
-
let length =
|
|
304
|
+
let length = getMediaLength()
|
|
265
305
|
let seekable = player.isSeekable
|
|
266
306
|
|
|
267
307
|
mediaInfo = MediaInfo(
|
|
@@ -270,10 +310,6 @@ class LibVlcPlayerView: ExpoView {
|
|
|
270
310
|
length: Double(length),
|
|
271
311
|
seekable: seekable,
|
|
272
312
|
)
|
|
273
|
-
|
|
274
|
-
mediaLength = length > 0 ?
|
|
275
|
-
length :
|
|
276
|
-
nil
|
|
277
313
|
}
|
|
278
314
|
|
|
279
315
|
return mediaInfo
|
|
@@ -387,8 +423,7 @@ class LibVlcPlayerView: ExpoView {
|
|
|
387
423
|
}
|
|
388
424
|
} else {
|
|
389
425
|
if type == "position" {
|
|
390
|
-
|
|
391
|
-
time = Int(value * Double(length))
|
|
426
|
+
time = Int(value * Double(getMediaLength()))
|
|
392
427
|
} else {
|
|
393
428
|
time = Int(value)
|
|
394
429
|
}
|
|
@@ -416,13 +451,15 @@ class LibVlcPlayerView: ExpoView {
|
|
|
416
451
|
func snapshot(_ path: String) {
|
|
417
452
|
if let player = mediaPlayer {
|
|
418
453
|
let video = player.videoSize
|
|
454
|
+
let width = video.width
|
|
455
|
+
let height = video.height
|
|
419
456
|
|
|
420
|
-
if
|
|
457
|
+
if width > 0, height > 0 {
|
|
421
458
|
let dateFormatter = DateFormatter()
|
|
422
459
|
dateFormatter.dateFormat = "yyyy-MM-dd-HH'h'mm'm'ss's'"
|
|
423
460
|
let snapshotPath = path + "/vlc-snapshot-\(dateFormatter.string(from: Date())).jpg"
|
|
424
461
|
|
|
425
|
-
player.saveVideoSnapshot(at: snapshotPath, withWidth: Int32(
|
|
462
|
+
player.saveVideoSnapshot(at: snapshotPath, withWidth: Int32(width), andHeight: Int32(height))
|
|
426
463
|
|
|
427
464
|
onSnapshotTaken(["path": snapshotPath])
|
|
428
465
|
} else {
|
|
@@ -457,7 +494,7 @@ extension LibVlcPlayerView: VLCMediaPlayerDelegate {
|
|
|
457
494
|
onPlaying()
|
|
458
495
|
|
|
459
496
|
if firstPlay {
|
|
460
|
-
|
|
497
|
+
setupFirstPlay()
|
|
461
498
|
|
|
462
499
|
setupPlayer()
|
|
463
500
|
|
|
@@ -476,9 +513,6 @@ extension LibVlcPlayerView: VLCMediaPlayerDelegate {
|
|
|
476
513
|
|
|
477
514
|
MediaPlayerManager.shared.keepAwakeManager.deactivateKeepAwake()
|
|
478
515
|
MediaPlayerManager.shared.audioSessionManager.setAppropriateAudioSession()
|
|
479
|
-
|
|
480
|
-
firstPlay = true
|
|
481
|
-
firstTime = true
|
|
482
516
|
case .ended:
|
|
483
517
|
onEndReached()
|
|
484
518
|
|
|
@@ -503,12 +537,6 @@ extension LibVlcPlayerView: VLCMediaPlayerDelegate {
|
|
|
503
537
|
if let player = mediaPlayer {
|
|
504
538
|
onTimeChanged(["time": player.time.intValue])
|
|
505
539
|
|
|
506
|
-
if firstTime {
|
|
507
|
-
MediaPlayerManager.shared.audioSessionManager.setAppropriateAudioSession()
|
|
508
|
-
|
|
509
|
-
firstTime = false
|
|
510
|
-
}
|
|
511
|
-
|
|
512
540
|
onPositionChanged(["position": player.position])
|
|
513
541
|
}
|
|
514
542
|
}
|