Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,15 @@ private fun VideoPlayerContent(
},
update = { playerView ->
try {
// Verify that the player is still valid before updating
if (playerState is DefaultVideoPlayerState &&
playerState.exoPlayer != null &&
playerView.player != null
) {
// Update the resize mode when contentScale changes
val state = playerState as? DefaultVideoPlayerState
if (state?.exoPlayer != null) {
// Re-attach after LazyList recycle: onReset nulls playerView.player
// and calls onPause(). Without this, the surface stays blank until
// the user navigates away and back.
if (playerView.player == null) {
state.attachPlayerView(playerView)
playerView.onResume()
}
playerView.resizeMode = mapContentScaleToResizeMode(contentScale)
}
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package io.github.kdroidfilter.composemediaplayer

import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue

/**
* Represents metadata information of a video file.
*
* This data class holds various attributes related to the video content,
* including its title, artist, duration, dimensions, codec details, and audio properties.
* This metadata is typically used to provide detailed information about a video
* during playback or for insights in media management systems.
* Properties are backed by [mutableStateOf] so mutations trigger Compose recomposition.
* This matters when callers update fields in place (e.g. on `onVideoSizeChanged` or HLS
* resolution changes) while the metadata instance is read from a composable.
*
* @property title The title of the video, if available.
* @property duration The length of the video in milliseconds, if known.
Expand All @@ -21,21 +23,29 @@ import androidx.compose.runtime.Stable
* @property audioSampleRate The sample rate of the audio track in the video, measured in Hz.
*/
@Stable
data class VideoMetadata(
var title: String? = null,
var duration: Long? = null, // Duration in milliseconds
var width: Int? = null,
var height: Int? = null,
var bitrate: Long? = null, // Bitrate in bits per second
var frameRate: Float? = null,
var mimeType: String? = null,
var audioChannels: Int? = null,
var audioSampleRate: Int? = null,
class VideoMetadata(
title: String? = null,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
bitrate: Long? = null,
frameRate: Float? = null,
mimeType: String? = null,
audioChannels: Int? = null,
audioSampleRate: Int? = null,
) {
var title: String? by mutableStateOf(title)
var duration: Long? by mutableStateOf(duration)
var width: Int? by mutableStateOf(width)
var height: Int? by mutableStateOf(height)
var bitrate: Long? by mutableStateOf(bitrate)
var frameRate: Float? by mutableStateOf(frameRate)
var mimeType: String? by mutableStateOf(mimeType)
var audioChannels: Int? by mutableStateOf(audioChannels)
var audioSampleRate: Int? by mutableStateOf(audioSampleRate)

/**
* Checks if all properties of this metadata object are null.
*
* @return true if all properties are null, false otherwise.
*/
fun isAllNull(): Boolean =
title == null &&
Expand All @@ -47,4 +57,59 @@ data class VideoMetadata(
mimeType == null &&
audioChannels == null &&
audioSampleRate == null

fun copy(
title: String? = this.title,
duration: Long? = this.duration,
width: Int? = this.width,
height: Int? = this.height,
bitrate: Long? = this.bitrate,
frameRate: Float? = this.frameRate,
mimeType: String? = this.mimeType,
audioChannels: Int? = this.audioChannels,
audioSampleRate: Int? = this.audioSampleRate,
): VideoMetadata =
VideoMetadata(
title = title,
duration = duration,
width = width,
height = height,
bitrate = bitrate,
frameRate = frameRate,
mimeType = mimeType,
audioChannels = audioChannels,
audioSampleRate = audioSampleRate,
)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is VideoMetadata) return false
return title == other.title &&
duration == other.duration &&
width == other.width &&
height == other.height &&
bitrate == other.bitrate &&
frameRate == other.frameRate &&
mimeType == other.mimeType &&
audioChannels == other.audioChannels &&
audioSampleRate == other.audioSampleRate
}

override fun hashCode(): Int {
var result = title?.hashCode() ?: 0
result = 31 * result + (duration?.hashCode() ?: 0)
result = 31 * result + (width ?: 0)
result = 31 * result + (height ?: 0)
result = 31 * result + (bitrate?.hashCode() ?: 0)
result = 31 * result + (frameRate?.hashCode() ?: 0)
result = 31 * result + (mimeType?.hashCode() ?: 0)
result = 31 * result + (audioChannels ?: 0)
result = 31 * result + (audioSampleRate ?: 0)
return result
}

override fun toString(): String =
"VideoMetadata(title=$title, duration=$duration, width=$width, height=$height, " +
"bitrate=$bitrate, frameRate=$frameRate, mimeType=$mimeType, " +
"audioChannels=$audioChannels, audioSampleRate=$audioSampleRate)"
}