Tusky-App-Android/app/src/main/java/com/keylesspalace/tusky/di/PlayerModule.kt

183 lines
7.3 KiB
Kotlin
Raw Normal View History

Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
/*
* Copyright 2024 Tusky Contributors
*
* This file is a part of Tusky.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see <http://www.gnu.org/licenses>.
*/
package com.keylesspalace.tusky.di
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
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.RenderersFactory
import androidx.media3.exoplayer.audio.AudioSink
import androidx.media3.exoplayer.audio.DefaultAudioSink
import androidx.media3.exoplayer.audio.MediaCodecAudioRenderer
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
import androidx.media3.exoplayer.metadata.MetadataRenderer
import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.ProgressiveMediaSource
import androidx.media3.exoplayer.text.TextRenderer
import androidx.media3.exoplayer.video.MediaCodecVideoRenderer
import androidx.media3.extractor.ExtractorsFactory
import androidx.media3.extractor.flac.FlacExtractor
import androidx.media3.extractor.mkv.MatroskaExtractor
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
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
import androidx.media3.extractor.wav.WavExtractor
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
@Module
@OptIn(UnstableApi::class)
object PlayerModule {
@Provides
fun provideAudioSink(context: Context): AudioSink {
return DefaultAudioSink.Builder(context)
.build()
}
@Provides
fun provideRenderersFactory(context: Context, audioSink: AudioSink): RenderersFactory {
return RenderersFactory { eventHandler,
videoRendererEventListener,
audioRendererEventListener,
textRendererOutput,
metadataRendererOutput ->
arrayOf(
MediaCodecVideoRenderer(
context,
MediaCodecSelector.DEFAULT,
DefaultRenderersFactory.DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS,
enableDecoderFallback for ExoPlayer (#4360) This helps playing some media even if there is a problem with the primary decoder. E.g. [this video](https://mastodon.social/@krzyzanowskim/112208964123517040) fails on my Fairphone 4 without this change. <img src="https://github.com/tuskyapp/Tusky/assets/10157047/215d932c-9ed1-4ee8-8be7-e6ca28ddec23" width="200"/> <details> <summary>Stacktrace</summary> ``` androidx.media3.exoplayer.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(1, null, null, video/avc, avc1.640034, -1, null, [1920, 1440, 119.99593, ColorInfo(BT709, Limited range, sRGB, false, 8bit Luma, 8bit Chroma)], [-1, -1]), format_supported=YES at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:620) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: androidx.media3.exoplayer.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.qcom.video.decoder.avc, Format(1, null, null, video/avc, avc1.640034, -1, null, [1920, 1440, 119.99593, ColorInfo(BT709, Limited range, sRGB, false, 8bit Luma, 8bit Chroma)], [-1, -1]) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1114) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:551) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1560) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1152) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:994) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:814) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:940) at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1102) at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:541) at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loopOnce(Looper.java:201)  at android.os.Looper.loop(Looper.java:288)  at android.os.HandlerThread.run(HandlerThread.java:67)  Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff4 at android.media.MediaCodec.native_configure(Native Method) at android.media.MediaCodec.configure(MediaCodec.java:2215) at android.media.MediaCodec.configure(MediaCodec.java:2131) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter.initialize(AsynchronousMediaCodecAdapter.java:174) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter.access$100(AsynchronousMediaCodecAdapter.java:54) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter$Factory.createAdapter(AsynchronousMediaCodecAdapter.java:119) at androidx.media3.exoplayer.mediacodec.DefaultMediaCodecAdapterFactory.createAdapter(DefaultMediaCodecAdapterFactory.java:117) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1195) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1103) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:551)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1560)  at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1152)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:994)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:814)  at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:940)  at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1102)  at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:541)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loopOnce(Looper.java:201)  at android.os.Looper.loop(Looper.java:288)  at android.os.HandlerThread.run(HandlerThread.java:67)  ``` </details>
2024-04-10 21:46:52 +02:00
// enableDecoderFallback = true, helps playing videos even if one decoder fails
true,
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
eventHandler,
videoRendererEventListener,
DefaultRenderersFactory.MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY
),
MediaCodecAudioRenderer(
context,
MediaCodecSelector.DEFAULT,
enableDecoderFallback for ExoPlayer (#4360) This helps playing some media even if there is a problem with the primary decoder. E.g. [this video](https://mastodon.social/@krzyzanowskim/112208964123517040) fails on my Fairphone 4 without this change. <img src="https://github.com/tuskyapp/Tusky/assets/10157047/215d932c-9ed1-4ee8-8be7-e6ca28ddec23" width="200"/> <details> <summary>Stacktrace</summary> ``` androidx.media3.exoplayer.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(1, null, null, video/avc, avc1.640034, -1, null, [1920, 1440, 119.99593, ColorInfo(BT709, Limited range, sRGB, false, 8bit Luma, 8bit Chroma)], [-1, -1]), format_supported=YES at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:620) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: androidx.media3.exoplayer.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.qcom.video.decoder.avc, Format(1, null, null, video/avc, avc1.640034, -1, null, [1920, 1440, 119.99593, ColorInfo(BT709, Limited range, sRGB, false, 8bit Luma, 8bit Chroma)], [-1, -1]) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1114) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:551) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1560) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1152) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:994) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:814) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:940) at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1102) at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:541) at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loopOnce(Looper.java:201)  at android.os.Looper.loop(Looper.java:288)  at android.os.HandlerThread.run(HandlerThread.java:67)  Caused by: android.media.MediaCodec$CodecException: Error 0xfffffff4 at android.media.MediaCodec.native_configure(Native Method) at android.media.MediaCodec.configure(MediaCodec.java:2215) at android.media.MediaCodec.configure(MediaCodec.java:2131) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter.initialize(AsynchronousMediaCodecAdapter.java:174) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter.access$100(AsynchronousMediaCodecAdapter.java:54) at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecAdapter$Factory.createAdapter(AsynchronousMediaCodecAdapter.java:119) at androidx.media3.exoplayer.mediacodec.DefaultMediaCodecAdapterFactory.createAdapter(DefaultMediaCodecAdapterFactory.java:117) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1195) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1103) at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:551)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1560)  at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1152)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:994)  at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:814)  at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:940)  at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1102)  at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:541)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loopOnce(Looper.java:201)  at android.os.Looper.loop(Looper.java:288)  at android.os.HandlerThread.run(HandlerThread.java:67)  ``` </details>
2024-04-10 21:46:52 +02:00
// enableDecoderFallback = true
true,
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
eventHandler,
audioRendererEventListener,
audioSink
),
TextRenderer(
textRendererOutput,
eventHandler.looper
),
MetadataRenderer(
metadataRendererOutput,
eventHandler.looper
)
)
}
}
@Provides
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 {
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
// Extractors order is optimized according to
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ
return ExtractorsFactory {
arrayOf(
FlacExtractor(),
WavExtractor(),
Mp4Extractor(subtitleParserFactory),
FragmentedMp4Extractor(subtitleParserFactory),
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
OggExtractor(),
MatroskaExtractor(subtitleParserFactory),
Move ExoPlayer initialization to a Dagger module and optimize its dependencies (#4296) Currently, ExoPlayer is initialized explicitly in `ViewMediaFragment` with all its dependencies, including many that are not useful for viewing Mastodon media attachments. This pull request moves most ExoPlayer initialization and configuration to a new Dagger module, and instead a `Provider<ExoPlayer>` factory is injected in the Fragment so it can create new instances when needed. The following ExoPlayer components will be configured: - **Renderers**: all of them (audio, video, metadata, subtitles) except for the `CameraMotionRenderer`. - **Extractors**: FLAC, Wav, Mp4, Ogg, Matroska/WebM and MP3 containers, to provide the same support as Firefox or Chrome browsers. Other container formats that are either image formats (already covered by Glide), not web-friendly or reserved for live streaming are skipped. - **MediaSource**: only progressive download (through OkHttp) is provided. Live streaming support using protocols like RTSP, MPEG/Dash or HLS is skipped, because Mastodon servers don't use these protocols to download attachments. The Mastodon documentation mentions the [supported media formats for attachments](https://docs.joinmastodon.org/user/posting/#media) and this covers them and even more. The docs also mentions that the video and audio files are transcoded to MP4 and MP3 upon upload but that was not the case in the past (for example WebM was used) and it could change again in the future. Specifying these components manually allows reducing the APK size by about 200 KB thanks to R8 shrinking. There are also a few extra code changes: - Remove the code specific to API < 24 since the min SDK of the app is now 24. - Add support for pausing a video when unplugging headphones. - Specify the audio attributes according to content type to help the Android audio mixer.
2024-03-09 11:04:04 +01:00
Mp3Extractor()
)
}
}
@Provides
fun provideDataSourceFactory(context: Context, okHttpClient: OkHttpClient): DataSource.Factory {
return DefaultDataSource.Factory(context, OkHttpDataSource.Factory(okHttpClient))
}
@Provides
fun provideMediaSourceFactory(
dataSourceFactory: DataSource.Factory,
extractorsFactory: ExtractorsFactory
): MediaSource.Factory {
// Only progressive download is supported for Mastodon attachments
return ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
}
@Provides
fun provideExoPlayer(
context: Context,
renderersFactory: RenderersFactory,
mediaSourceFactory: MediaSource.Factory
): ExoPlayer {
return ExoPlayer.Builder(context, renderersFactory, mediaSourceFactory)
.setLooper(Looper.getMainLooper())
.setHandleAudioBecomingNoisy(true) // automatically pause when unplugging headphones
.setWakeMode(C.WAKE_MODE_NONE) // playback is always in the foreground
.build()
}
}