Skip to content

Commit 6cb500f

Browse files
committed
fix subtitle bug
1 parent 2586119 commit 6cb500f

File tree

8 files changed

+67
-67
lines changed

8 files changed

+67
-67
lines changed

app/src/androidTest/java/de/xikolo/testing/instrumented/unit/download/hlsvideodownload/AbstractHlsVideoDownloadItemTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package de.xikolo.testing.instrumented.unit.download.hlsvideodownload
22

3-
import com.google.android.exoplayer2.source.MediaSource
3+
import com.google.android.exoplayer2.source.SingleSampleMediaSource
4+
import com.google.android.exoplayer2.source.hls.HlsMediaSource
45
import de.xikolo.controllers.helper.VideoSettingsHelper
56
import de.xikolo.download.DownloadCategory
67
import de.xikolo.download.hlsvideodownload.HlsVideoDownloadIdentifier
@@ -9,7 +10,7 @@ import de.xikolo.models.Storage
910
import de.xikolo.testing.instrumented.unit.download.DownloadItemTest
1011

1112
abstract class AbstractHlsVideoDownloadItemTest : DownloadItemTest<HlsVideoDownloadItem,
12-
MediaSource, HlsVideoDownloadIdentifier>() {
13+
Pair<HlsMediaSource, Map<String, SingleSampleMediaSource>>, HlsVideoDownloadIdentifier>() {
1314

1415
abstract val storage: Storage
1516

@@ -18,6 +19,7 @@ abstract class AbstractHlsVideoDownloadItemTest : DownloadItemTest<HlsVideoDownl
1819
"https://open.hpi.de/playlists/93a84211-e40a-416a-b224-4d3ecdbb12f9.m3u8?embed_subtitles_for_video=d7e056da-756f-4437-b64a-16970a33d5ef",
1920
DownloadCategory.Other,
2021
VideoSettingsHelper.VideoQuality.HIGH.qualityFraction,
22+
emptyMap(),
2123
storage
2224
)
2325

@@ -26,6 +28,7 @@ abstract class AbstractHlsVideoDownloadItemTest : DownloadItemTest<HlsVideoDownl
2628
null,
2729
DownloadCategory.Other,
2830
0.0f,
31+
emptyMap(),
2932
storage
3033
)
3134
}

app/src/main/java/de/xikolo/controllers/video/VideoItemPlayerFragment.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,9 @@ class VideoItemPlayerFragment : VideoStreamPlayerFragment() {
216216
}
217217

218218
if (item != null && videoDownloadPresent(item)) {
219-
playerView.setVideoSource(item.download!!)
220-
/*item.subs?.let {
221-
playerView.setSubtitleSources(it)
222-
}*/
219+
val mediaSource = item.download!!
220+
playerView.setVideoSource(mediaSource.first)
221+
playerView.setSubtitleSources(mediaSource.second)
223222
isOfflineVideo = true
224223
return true
225224
}

app/src/main/java/de/xikolo/download/filedownload/FileDownloadHandler.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ object FileDownloadHandler : DownloadHandler<FileDownloadIdentifier, FileDownloa
225225
disabledNotificationsManager.addListener(listener)
226226
enabledNotificationsManager.addListener(listener)
227227
}
228+
229+
enabledNotificationsManager.resumeAll()
230+
disabledNotificationsManager.resumeAll()
228231
}
229232

230233
private val listeners: MutableMap<Int, ((DownloadStatus) -> Unit)?> = mutableMapOf()

app/src/main/java/de/xikolo/download/hlsvideodownload/HlsVideoDownloadHandler.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ object HlsVideoDownloadHandler :
7070

7171
init {
7272
Log.i(TAG, "Starting $TAG")
73-
DownloadService.start(
73+
DownloadService.startForeground(
7474
context,
7575
HlsVideoDownloadForegroundService::class.java
7676
)
@@ -119,7 +119,7 @@ object HlsVideoDownloadHandler :
119119
getDatabaseProvider(context),
120120
cache,
121121
dataSourceFactory,
122-
Executors.newSingleThreadExecutor()
122+
Executors.newCachedThreadPool()
123123
).apply {
124124
maxParallelDownloads = 5
125125
minRetryCount = 1
@@ -156,7 +156,10 @@ object HlsVideoDownloadHandler :
156156
downloadManager: DownloadManager,
157157
download: Download
158158
) {
159-
Log.d(TAG, "Download successfully removed: ${download.request.id}")
159+
Log.d(
160+
TAG,
161+
"Download successfully removed: ${download.request.id}"
162+
)
160163
val identifier = download.request.id
161164
val listener = listeners[identifier]
162165
listeners.remove(identifier)
@@ -253,6 +256,7 @@ object HlsVideoDownloadHandler :
253256
estimatedSize
254257
).encode()
255258
)
259+
downloadRequest.customCacheKey
256260
helper.release()
257261

258262
val identifier = downloadRequest.id

app/src/main/java/de/xikolo/download/hlsvideodownload/HlsVideoDownloadItem.kt

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package de.xikolo.download.hlsvideodownload
22

3+
import android.net.Uri
4+
import com.google.android.exoplayer2.C
5+
import com.google.android.exoplayer2.MediaItem
36
import com.google.android.exoplayer2.offline.Download
4-
import com.google.android.exoplayer2.source.MediaSource
7+
import com.google.android.exoplayer2.source.SingleSampleMediaSource
58
import com.google.android.exoplayer2.source.hls.HlsMediaSource
69
import com.google.android.exoplayer2.upstream.cache.Cache
710
import com.google.android.exoplayer2.upstream.cache.CacheDataSource
11+
import com.google.android.exoplayer2.util.MimeTypes
812
import de.xikolo.App
913
import de.xikolo.download.DownloadCategory
1014
import de.xikolo.download.DownloadItemImpl
@@ -17,9 +21,10 @@ open class HlsVideoDownloadItem(
1721
val url: String?,
1822
val category: DownloadCategory,
1923
val quality: Float,
20-
//val subtitles: Map<String, String>?,
24+
val subtitles: Map<String, String>,
2125
storage: Storage = App.instance.preferredStorage
22-
) : DownloadItemImpl<MediaSource, HlsVideoDownloadIdentifier, HlsVideoDownloadRequest>(storage) {
26+
) : DownloadItemImpl<Pair<HlsMediaSource, Map<String, SingleSampleMediaSource>>,
27+
HlsVideoDownloadIdentifier, HlsVideoDownloadRequest>(storage) {
2328

2429
final override val downloader = HlsVideoDownloadHandler
2530

@@ -45,65 +50,43 @@ open class HlsVideoDownloadItem(
4550
)
4651
}
4752

48-
private fun getMediaSource(storage: Storage): MediaSource? {
49-
return getIndexEntry(storage)?.let {
50-
return HlsMediaSource.Factory(
53+
private fun getMediaSource(storage: Storage): Pair<HlsMediaSource, Map<String, SingleSampleMediaSource>>? {
54+
return getIndexEntry(storage)?.let { indexEntry ->
55+
HlsMediaSource.Factory(
5156
CacheDataSource.Factory()
5257
.setCache(getCache(storage))
5358
.setCacheWriteDataSinkFactory(null)
5459
).createMediaSource(
55-
it.request.toMediaItem()
56-
)
60+
indexEntry.request.toMediaItem()
61+
) to subtitles.mapValues { (language, url) ->
62+
SingleSampleMediaSource.Factory(
63+
CacheDataSource.Factory()
64+
.setCache(getCache(storage))
65+
.setCacheWriteDataSinkFactory(null)
66+
).createMediaSource(
67+
MediaItem.Subtitle(
68+
Uri.parse(url), // requires that the HLS playlist links to the API resource
69+
MimeTypes.TEXT_VTT,
70+
language,
71+
C.SELECTION_FLAG_DEFAULT
72+
),
73+
C.TIME_UNSET
74+
)
75+
}
5776
}
5877
}
5978

6079
override val size: Long
6180
get() = getIndexEntry(storage)?.bytesDownloaded ?: 0L
6281

63-
final override val download: MediaSource?
82+
final override val download: Pair<HlsMediaSource, Map<String, SingleSampleMediaSource>>?
6483
get() = getMediaSource(context.internalStorage)
6584
?: context.sdcardStorage?.let { getMediaSource(it) }
6685

67-
/*val subs: Map<String, MediaSource>?
68-
get() {
69-
fun getMediaSource(language: String, url: String): MediaSource =
70-
SingleSampleMediaSource.Factory(
71-
CacheDataSource.Factory()
72-
.setCache(cache)
73-
)
74-
.createMediaSource(
75-
MediaItem.Subtitle(
76-
Uri.parse(url),
77-
MimeTypes.TEXT_VTT,
78-
language,
79-
C.SELECTION_FLAG_DEFAULT
80-
),
81-
C.TIME_UNSET
82-
)
83-
84-
val originalStorage = storage
85-
return try {
86-
storage = context.internalStorage
87-
indexEntry!!
88-
subtitles?.entries?.associate {
89-
it.key to getMediaSource(it.key, it.value)
90-
}
91-
} catch (e: Exception) {
92-
storage = context.sdcardStorage!!
93-
indexEntry!!
94-
subtitles?.entries?.associate {
95-
it.key to getMediaSource(it.key, it.value)
96-
}
97-
} finally {
98-
storage = originalStorage
99-
}
100-
}*/
101-
10286
final override val request
10387
get() = HlsVideoDownloadRequest(
10488
url!!,
10589
quality,
106-
//subtitles,
10790
storage,
10891
title,
10992
true,

app/src/main/java/de/xikolo/download/hlsvideodownload/HlsVideoDownloadRequest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import de.xikolo.models.Storage
1414
* This does not necessarily need to correspond to the bitrates in the master playlist.
1515
* Based on this parameter, the track with the closest calculated target bitrate in the master
1616
* playlist is selected.
17-
* // @param subtitles The subtitles to download along the video.
1817
* @param storage The storage location for the download.
1918
* @param title The title of the download.
2019
* @param showNotification Whether to show a notification while downloading.
@@ -23,7 +22,6 @@ import de.xikolo.models.Storage
2322
class HlsVideoDownloadRequest(
2423
val url: String,
2524
val quality: Float,
26-
//val subtitles: Map<String, String>?,
2725
val storage: Storage,
2826
override val title: String,
2927
override val showNotification: Boolean,

app/src/main/java/de/xikolo/models/DownloadAsset.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ object DownloadAsset {
105105
HlsVideoDownloadItem(
106106
video.streamToPlay?.hlsUrl,
107107
DownloadCategory.Course(item.courseId),
108-
quality.qualityFraction/*,
108+
quality.qualityFraction,
109109
video.subtitles.associate {
110110
it.language to it.vttUrl
111-
}*/
111+
}
112112
) {
113113

114114
override val title = App.instance.getString(R.string.video) + ": " + item.title

app/src/main/java/de/xikolo/views/ExoPlayerVideoView.kt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@ import com.google.android.exoplayer2.ExoPlaybackException
1111
import com.google.android.exoplayer2.MediaItem
1212
import com.google.android.exoplayer2.PlaybackParameters
1313
import com.google.android.exoplayer2.Player
14-
import com.google.android.exoplayer2.Renderer
1514
import com.google.android.exoplayer2.SimpleExoPlayer
16-
import com.google.android.exoplayer2.Timeline
1715
import com.google.android.exoplayer2.source.MediaSource
1816
import com.google.android.exoplayer2.source.MergingMediaSource
1917
import com.google.android.exoplayer2.source.ProgressiveMediaSource
2018
import com.google.android.exoplayer2.source.SingleSampleMediaSource
2119
import com.google.android.exoplayer2.source.TrackGroupArray
20+
import com.google.android.exoplayer2.source.hls.HlsManifest
2221
import com.google.android.exoplayer2.source.hls.HlsMediaSource
2322
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection
2423
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
@@ -30,6 +29,8 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
3029
import com.google.android.exoplayer2.util.MimeTypes
3130
import com.google.android.exoplayer2.util.Util
3231
import com.google.android.exoplayer2.video.VideoListener
32+
import kotlin.math.abs
33+
import kotlin.math.roundToInt
3334

3435
open class ExoPlayerVideoView : PlayerView {
3536

@@ -153,9 +154,6 @@ open class ExoPlayerVideoView : PlayerView {
153154

154155
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
155156
}
156-
157-
override fun onTimelineChanged(timeline: Timeline, reason: Int) {
158-
}
159157
}
160158
)
161159

@@ -292,20 +290,32 @@ open class ExoPlayerVideoView : PlayerView {
292290
DefaultTrackSelector.ParametersBuilder(context)
293291
.apply {
294292
if (quality != null) {
295-
setMaxVideoBitrate(quality.toInt()) // ToDo
296-
setMinVideoBitrate(quality.toInt())
293+
val manifest = exoplayer.currentManifest as? HlsManifest
294+
val formats = manifest?.masterPlaylist?.variants?.map { it.format }
295+
if (formats?.isNotEmpty() == true) {
296+
val lowestBitrate = formats.minOf { it.bitrate }
297+
val highestBitrate = formats.maxOf { it.bitrate }
298+
val targetBitrate = lowestBitrate + quality *
299+
(highestBitrate - lowestBitrate)
300+
val closestBitrate = formats.minByOrNull {
301+
abs(it.bitrate - targetBitrate).roundToInt()
302+
}!!.bitrate
303+
304+
setMaxVideoBitrate(closestBitrate + 1)
305+
setMinVideoBitrate(closestBitrate - 1)
306+
}
297307
}
298308
}
299309
)
300310
}
301311

302312
fun scaleToFill() {
303-
exoplayer.videoScalingMode = Renderer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
313+
exoplayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
304314
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL
305315
}
306316

307317
fun scaleToFit() {
308-
exoplayer.videoScalingMode = Renderer.VIDEO_SCALING_MODE_DEFAULT
318+
exoplayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
309319
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
310320
}
311321

0 commit comments

Comments
 (0)