diff --git a/app/src/main/java/com/keylesspalace/tusky/di/PlayerModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/PlayerModule.kt index 1156f4131..f12587fc5 100644 --- a/app/src/main/java/com/keylesspalace/tusky/di/PlayerModule.kt +++ b/app/src/main/java/com/keylesspalace/tusky/di/PlayerModule.kt @@ -21,6 +21,8 @@ import android.content.Context import android.os.Looper import androidx.annotation.OptIn import androidx.media3.common.C +import androidx.media3.common.Format +import androidx.media3.common.MimeTypes import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.DataSource import androidx.media3.datasource.DefaultDataSource @@ -44,6 +46,10 @@ import androidx.media3.extractor.mp3.Mp3Extractor import androidx.media3.extractor.mp4.FragmentedMp4Extractor import androidx.media3.extractor.mp4.Mp4Extractor import androidx.media3.extractor.ogg.OggExtractor +import androidx.media3.extractor.text.SubtitleParser +import androidx.media3.extractor.text.ttml.TtmlParser +import androidx.media3.extractor.text.webvtt.Mp4WebvttParser +import androidx.media3.extractor.text.webvtt.WebvttParser import androidx.media3.extractor.wav.WavExtractor import dagger.Module import dagger.Provides @@ -98,17 +104,50 @@ object PlayerModule { } @Provides - fun provideExtractorsFactory(): ExtractorsFactory { + fun providesSubtitleParserFactory(): SubtitleParser.Factory { + return object : SubtitleParser.Factory { + override fun supportsFormat(format: Format): Boolean { + return when (format.sampleMimeType) { + MimeTypes.TEXT_VTT, + MimeTypes.APPLICATION_MP4VTT, + MimeTypes.APPLICATION_TTML -> true + + else -> false + } + } + + override fun getCueReplacementBehavior(format: Format): Int { + return when (val mimeType = format.sampleMimeType) { + MimeTypes.TEXT_VTT -> WebvttParser.CUE_REPLACEMENT_BEHAVIOR + MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttParser.CUE_REPLACEMENT_BEHAVIOR + MimeTypes.APPLICATION_TTML -> TtmlParser.CUE_REPLACEMENT_BEHAVIOR + else -> throw IllegalArgumentException("Unsupported MIME type: $mimeType") + } + } + + override fun create(format: Format): SubtitleParser { + return when (val mimeType = format.sampleMimeType) { + MimeTypes.TEXT_VTT -> WebvttParser() + MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttParser() + MimeTypes.APPLICATION_TTML -> TtmlParser() + else -> throw IllegalArgumentException("Unsupported MIME type: $mimeType") + } + } + } + } + + @Provides + fun provideExtractorsFactory(subtitleParserFactory: SubtitleParser.Factory): ExtractorsFactory { // Extractors order is optimized according to // https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ return ExtractorsFactory { arrayOf( FlacExtractor(), WavExtractor(), - Mp4Extractor(), - FragmentedMp4Extractor(), + Mp4Extractor(subtitleParserFactory), + FragmentedMp4Extractor(subtitleParserFactory), OggExtractor(), - MatroskaExtractor(), + MatroskaExtractor(subtitleParserFactory), Mp3Extractor() ) }