music: actually remove dependence on dcoders

Actually remove dependence on the non-audio decoders in the music
(and image) modules.
This commit is contained in:
Alexander Capehart 2023-02-19 13:08:44 -07:00
parent e515534023
commit 192b917904
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
6 changed files with 57 additions and 23 deletions

View file

@ -6,6 +6,7 @@ plugins {
id "kotlin-parcelize" id "kotlin-parcelize"
id "dagger.hilt.android.plugin" id "dagger.hilt.android.plugin"
id "kotlin-kapt" id "kotlin-kapt"
id 'org.jetbrains.kotlin.android'
} }
android { android {
@ -81,6 +82,7 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1" implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01" implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
implementation 'androidx.core:core-ktx:+'
// Lifecycle // Lifecycle
def lifecycle_version = "2.5.1" def lifecycle_version = "2.5.1"

View file

@ -24,6 +24,7 @@ import com.google.android.exoplayer2.MediaMetadata
import com.google.android.exoplayer2.MetadataRetriever import com.google.android.exoplayer2.MetadataRetriever
import com.google.android.exoplayer2.metadata.flac.PictureFrame import com.google.android.exoplayer2.metadata.flac.PictureFrame
import com.google.android.exoplayer2.metadata.id3.ApicFrame import com.google.android.exoplayer2.metadata.id3.ApicFrame
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -31,6 +32,7 @@ import kotlinx.coroutines.withContext
import org.oxycblt.auxio.image.CoverMode import org.oxycblt.auxio.image.CoverMode
import org.oxycblt.auxio.image.ImageSettings import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.AudioOnlyExtractors
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logW
@ -103,7 +105,9 @@ object Covers {
*/ */
private suspend fun fetchExoplayerCover(context: Context, album: Album): InputStream? { private suspend fun fetchExoplayerCover(context: Context, album: Album): InputStream? {
val uri = album.songs[0].uri val uri = album.songs[0].uri
val future = MetadataRetriever.retrieveMetadata(context, MediaItem.fromUri(uri)) val future =
MetadataRetriever.retrieveMetadata(
DefaultMediaSourceFactory(context, AudioOnlyExtractors), MediaItem.fromUri(uri))
// future.get is a blocking call that makes us spin until the future is done. // future.get is a blocking call that makes us spin until the future is done.
// This is bad for a co-routine, as it prevents cancellation and by extension // This is bad for a co-routine, as it prevents cancellation and by extension

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2023 Auxio Project
*
* 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.music
import com.google.android.exoplayer2.extractor.ExtractorsFactory
import com.google.android.exoplayer2.extractor.flac.FlacExtractor
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor
import com.google.android.exoplayer2.extractor.ogg.OggExtractor
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor
import com.google.android.exoplayer2.extractor.wav.WavExtractor
/**
* A [ExtractorsFactory] that only provides audio containers to save APK space.
* @author Alexander Capehart (OxygenCobalt)
*/
object AudioOnlyExtractors : ExtractorsFactory {
override fun createExtractors() =
arrayOf(
FlacExtractor(),
WavExtractor(),
Mp4Extractor(),
OggExtractor(),
MatroskaExtractor(),
// Enable constant bitrate seeking so that certain MP3s/AACs are seekable
AdtsExtractor(AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING),
Mp3Extractor(Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING))
}

View file

@ -21,10 +21,12 @@ import android.content.Context
import androidx.core.text.isDigitsOnly import androidx.core.text.isDigitsOnly
import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.MetadataRetriever import com.google.android.exoplayer2.MetadataRetriever
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import org.oxycblt.auxio.music.AudioOnlyExtractors
import org.oxycblt.auxio.music.model.RawSong import org.oxycblt.auxio.music.model.RawSong
import org.oxycblt.auxio.music.storage.toAudioUri import org.oxycblt.auxio.music.storage.toAudioUri
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
@ -113,7 +115,7 @@ private class Task(context: Context, private val rawSong: RawSong) {
// listener is used, instead crashing the app entirely. // listener is used, instead crashing the app entirely.
private val future = private val future =
MetadataRetriever.retrieveMetadata( MetadataRetriever.retrieveMetadata(
context, DefaultMediaSourceFactory(context, AudioOnlyExtractors),
MediaItem.fromUri( MediaItem.fromUri(
requireNotNull(rawSong.mediaStoreId) { "Invalid raw: No id" }.toAudioUri())) requireNotNull(rawSong.mediaStoreId) { "Invalid raw: No id" }.toAudioUri()))

View file

@ -35,14 +35,6 @@ import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.audio.AudioCapabilities import com.google.android.exoplayer2.audio.AudioCapabilities
import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer
import com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer import com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer
import com.google.android.exoplayer2.extractor.ExtractorsFactory
import com.google.android.exoplayer2.extractor.flac.FlacExtractor
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor
import com.google.android.exoplayer2.extractor.ogg.OggExtractor
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor
import com.google.android.exoplayer2.extractor.wav.WavExtractor
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector import com.google.android.exoplayer2.mediacodec.MediaCodecSelector
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -52,6 +44,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.BuildConfig
import org.oxycblt.auxio.music.AudioOnlyExtractors
import org.oxycblt.auxio.music.MusicRepository import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.MusicSettings import org.oxycblt.auxio.music.MusicSettings
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
@ -125,17 +118,6 @@ class PlaybackService :
// Define our own extractors so we can exclude non-audio parsers. // Define our own extractors so we can exclude non-audio parsers.
// Ordering is derived from the DefaultExtractorsFactory's optimized ordering: // Ordering is derived from the DefaultExtractorsFactory's optimized ordering:
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ. // https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
val extractorsFactory = ExtractorsFactory {
arrayOf(
FlacExtractor(),
WavExtractor(),
Mp4Extractor(),
OggExtractor(),
MatroskaExtractor(),
// Enable constant bitrate seeking so that certain MP3s/AACs are seekable
AdtsExtractor(AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING),
Mp3Extractor(Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING))
}
// Since Auxio is a music player, only specify an audio renderer to save // Since Auxio is a music player, only specify an audio renderer to save
// battery/apk size/cache size // battery/apk size/cache size
val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ -> val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ ->
@ -152,7 +134,7 @@ class PlaybackService :
player = player =
ExoPlayer.Builder(this, audioRenderer) ExoPlayer.Builder(this, audioRenderer)
.setMediaSourceFactory(DefaultMediaSourceFactory(this, extractorsFactory)) .setMediaSourceFactory(DefaultMediaSourceFactory(this, AudioOnlyExtractors))
// Enable automatic WakeLock support // Enable automatic WakeLock support
.setWakeMode(C.WAKE_MODE_LOCAL) .setWakeMode(C.WAKE_MODE_LOCAL)
.setAudioAttributes( .setAudioAttributes(

View file

@ -1,6 +1,6 @@
buildscript { buildscript {
ext { ext {
kotlin_version = '1.7.21' kotlin_version = '1.8.0'
navigation_version = "2.5.3" navigation_version = "2.5.3"
hilt_version = '2.45' hilt_version = '2.45'
} }