added header support

This commit is contained in:
tapframe 2025-12-23 17:42:45 +05:30
parent 767fd2ff87
commit 18fa11fd88
6 changed files with 53 additions and 5 deletions

View file

@ -22,6 +22,7 @@ class MPVView @JvmOverloads constructor(
private var pendingDataSource: String? = null
private var isPaused: Boolean = true
private var surface: Surface? = null
private var httpHeaders: Map<String, String>? = null
// Event listener for React Native
var onLoadCallback: ((duration: Double, width: Int, height: Int) -> Unit)? = null
@ -51,6 +52,7 @@ class MPVView @JvmOverloads constructor(
// If a data source was set before surface was ready, load it now
pendingDataSource?.let { url ->
applyHttpHeaders()
loadFile(url)
pendingDataSource = null
}
@ -93,7 +95,7 @@ class MPVView @JvmOverloads constructor(
// Hardware decoding - use mediacodec-copy to allow subtitle overlay
// 'mediacodec-copy' copies frames to CPU memory which enables subtitle blending
MPVLib.setOptionString("hwdec", "mediacodec-copy")
MPVLib.setOptionString("hwdec", "auto")
MPVLib.setOptionString("hwdec-codecs", "all")
// Audio output
@ -105,6 +107,9 @@ class MPVView @JvmOverloads constructor(
MPVLib.setOptionString("cache", "yes")
MPVLib.setOptionString("cache-secs", "30")
// Network options
MPVLib.setOptionString("network-timeout", "60") // 60 second timeout
// Subtitle configuration - CRITICAL for Android
MPVLib.setOptionString("sub-auto", "fuzzy") // Auto-load subtitles
MPVLib.setOptionString("sub-visibility", "yes") // Make subtitles visible by default
@ -155,7 +160,7 @@ class MPVView @JvmOverloads constructor(
val MPV_FORMAT_DOUBLE = 5
MPVLib.observeProperty("time-pos", MPV_FORMAT_DOUBLE)
MPVLib.observeProperty("duration", MPV_FORMAT_DOUBLE)
MPVLib.observeProperty("duration/full", MPV_FORMAT_DOUBLE) // Use /full for complete HLS duration
MPVLib.observeProperty("pause", MPV_FORMAT_FLAG)
MPVLib.observeProperty("paused-for-cache", MPV_FORMAT_FLAG)
MPVLib.observeProperty("eof-reached", MPV_FORMAT_FLAG)
@ -179,12 +184,31 @@ class MPVView @JvmOverloads constructor(
fun setDataSource(url: String) {
if (isMpvInitialized) {
// Apply headers before loading the file
applyHttpHeaders()
loadFile(url)
} else {
pendingDataSource = url
}
}
fun setHeaders(headers: Map<String, String>?) {
httpHeaders = headers
Log.d(TAG, "Headers set: $headers")
}
private fun applyHttpHeaders() {
httpHeaders?.let { headers ->
if (headers.isNotEmpty()) {
// Format headers for MPV: comma-separated "Key: Value" pairs
val headerList = headers.map { (key, value) -> "$key: $value" }
val headerString = headerList.joinToString(",")
Log.d(TAG, "Applying HTTP headers: $headerString")
MPVLib.setOptionString("http-header-fields", headerString)
}
}
}
fun setPaused(paused: Boolean) {
isPaused = paused
if (isMpvInitialized) {
@ -341,10 +365,10 @@ class MPVView @JvmOverloads constructor(
Log.d(TAG, "Property $property = $value (Double)")
when (property) {
"time-pos" -> {
val duration = MPVLib.getPropertyDouble("duration") ?: 0.0
val duration = MPVLib.getPropertyDouble("duration/full") ?: MPVLib.getPropertyDouble("duration") ?: 0.0
onProgressCallback?.invoke(value, duration)
}
"duration" -> {
"duration/full", "duration" -> {
val width = MPVLib.getPropertyInt("width") ?: 0
val height = MPVLib.getPropertyInt("height") ?: 0
onLoadCallback?.invoke(value, width, height)
@ -384,7 +408,7 @@ class MPVView @JvmOverloads constructor(
Log.d(TAG, "MPV_EVENT_END_FILE")
// Heuristic: If duration is effectively 0 at end of file, it's a load error
val duration = MPVLib.getPropertyDouble("duration") ?: 0.0
val duration = MPVLib.getPropertyDouble("duration/full") ?: MPVLib.getPropertyDouble("duration") ?: 0.0
val timePos = MPVLib.getPropertyDouble("time-pos") ?: 0.0
val eofReached = MPVLib.getPropertyBoolean("eof-reached") ?: false

View file

@ -163,4 +163,21 @@ class MpvPlayerViewManager(
fun setResizeMode(view: MPVView, resizeMode: String?) {
view.setResizeMode(resizeMode ?: "contain")
}
@ReactProp(name = "headers")
fun setHeaders(view: MPVView, headers: com.facebook.react.bridge.ReadableMap?) {
if (headers != null) {
val headerMap = mutableMapOf<String, String>()
val iterator = headers.keySetIterator()
while (iterator.hasNextKey()) {
val key = iterator.nextKey()
headers.getString(key)?.let { value ->
headerMap[key] = value
}
}
view.setHeaders(headerMap)
} else {
view.setHeaders(null)
}
}
}

1
mpv-android Submodule

@ -0,0 +1 @@
Subproject commit 118cd1ed3d498265e44230e5dbb015bdd59f9dad

View file

@ -487,6 +487,7 @@ const AndroidVideoPlayer: React.FC = () => {
<View style={{ flex: 1, backgroundColor: 'black' }}>
<VideoSurface
processedStreamUrl={currentStreamUrl}
headers={headers}
volume={volume}
playbackSpeed={speedControl.playbackSpeed}
resizeMode={playerState.resizeMode}

View file

@ -14,6 +14,7 @@ export interface MpvPlayerRef {
export interface MpvPlayerProps {
source: string;
headers?: { [key: string]: string };
paused?: boolean;
volume?: number;
rate?: number;
@ -92,6 +93,7 @@ const MpvPlayer = forwardRef<MpvPlayerRef, MpvPlayerProps>((props, ref) => {
ref={nativeRef}
style={[styles.container, props.style]}
source={props.source}
headers={props.headers}
paused={props.paused ?? true}
volume={props.volume ?? 1.0}
rate={props.rate ?? 1.0}

View file

@ -7,6 +7,7 @@ import { ResizeModeType } from '../../utils/playerTypes';
interface VideoSurfaceProps {
processedStreamUrl: string;
headers?: { [key: string]: string };
volume: number;
playbackSpeed: number;
resizeMode: ResizeModeType;
@ -35,6 +36,7 @@ interface VideoSurfaceProps {
export const VideoSurface: React.FC<VideoSurfaceProps> = ({
processedStreamUrl,
headers,
volume,
playbackSpeed,
resizeMode,
@ -100,6 +102,7 @@ export const VideoSurface: React.FC<VideoSurfaceProps> = ({
<MpvPlayer
ref={mpvPlayerRef}
source={streamUrl}
headers={headers}
paused={paused}
volume={volume}
rate={playbackSpeed}