fix(plex): support no-burn transcode subtitles
This commit is contained in:
@@ -46,6 +46,8 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
int _lastEmitMs = 0;
|
||||
int _lastCacheStateMs = 0;
|
||||
int _positionMs = 0;
|
||||
Duration _timelineOffset = Duration.zero;
|
||||
Duration? _timelineDuration;
|
||||
int _nextPropId = 0;
|
||||
final Map<int, String> _propIdToName = {};
|
||||
|
||||
@@ -142,13 +144,13 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
|
||||
case 'time-pos':
|
||||
if (value is num) {
|
||||
_positionMs = (value * 1000).round();
|
||||
final pos = _toTimelinePosition(Duration(milliseconds: (value * 1000).round()));
|
||||
_positionMs = pos.inMilliseconds;
|
||||
// Only allocate Duration + copyWith + emit at ~4Hz (250ms).
|
||||
// Raw int is stored every tick so synchronous reads via _positionMs stay current.
|
||||
final nowMs = _throttleSw.elapsedMilliseconds;
|
||||
if (nowMs - _lastEmitMs >= 250) {
|
||||
_lastEmitMs = nowMs;
|
||||
final pos = Duration(milliseconds: _positionMs);
|
||||
_state = _state.copyWith(position: pos);
|
||||
positionController.add(pos);
|
||||
}
|
||||
@@ -157,7 +159,7 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
|
||||
case 'duration':
|
||||
if (value is num) {
|
||||
final duration = Duration(milliseconds: (value * 1000).toInt());
|
||||
final duration = _timelineDuration ?? _toTimelinePosition(Duration(milliseconds: (value * 1000).toInt()));
|
||||
_state = _state.copyWith(duration: duration);
|
||||
durationController.add(duration);
|
||||
}
|
||||
@@ -174,7 +176,7 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
final nowMs = _throttleSw.elapsedMilliseconds;
|
||||
if (nowMs - _lastCacheStateMs < 250) break;
|
||||
_lastCacheStateMs = nowMs;
|
||||
final buffer = Duration(milliseconds: (value * 1000).toInt());
|
||||
final buffer = _toTimelinePosition(Duration(milliseconds: (value * 1000).toInt()));
|
||||
_state = _state.copyWith(buffer: buffer);
|
||||
bufferController.add(buffer);
|
||||
// Synthesize a single range for players without demuxer-cache-state (ExoPlayer).
|
||||
@@ -295,7 +297,7 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
// Extract cache-end for the single buffer duration (replaces demuxer-cache-time)
|
||||
final cacheEnd = cacheState['cache-end'] as num?;
|
||||
if (cacheEnd != null) {
|
||||
final buffer = Duration(milliseconds: (cacheEnd * 1000).toInt());
|
||||
final buffer = _toTimelinePosition(Duration(milliseconds: (cacheEnd * 1000).toInt()));
|
||||
_state = _state.copyWith(buffer: buffer);
|
||||
bufferController.add(buffer);
|
||||
}
|
||||
@@ -311,8 +313,8 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
if (start != null && end != null) {
|
||||
ranges.add(
|
||||
BufferRange(
|
||||
start: Duration(milliseconds: (start * 1000).toInt()),
|
||||
end: Duration(milliseconds: (end * 1000).toInt()),
|
||||
start: _toTimelinePosition(Duration(milliseconds: (start * 1000).toInt())),
|
||||
end: _toTimelinePosition(Duration(milliseconds: (end * 1000).toInt())),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -491,18 +493,35 @@ abstract class PlayerBase with PlayerStreamControllersMixin implements Player {
|
||||
}
|
||||
|
||||
@protected
|
||||
void resetPlaybackProgress(Duration position) {
|
||||
void configureTimeline({Duration offset = Duration.zero, Duration? duration}) {
|
||||
_timelineOffset = offset;
|
||||
_timelineDuration = duration;
|
||||
}
|
||||
|
||||
@protected
|
||||
Duration sourceSeekPosition(Duration timelinePosition) {
|
||||
final sourcePosition = timelinePosition - _timelineOffset;
|
||||
return sourcePosition.isNegative ? Duration.zero : sourcePosition;
|
||||
}
|
||||
|
||||
Duration _toTimelinePosition(Duration sourcePosition) {
|
||||
return sourcePosition + _timelineOffset;
|
||||
}
|
||||
|
||||
@protected
|
||||
void resetPlaybackProgress(Duration sourcePosition) {
|
||||
final position = _toTimelinePosition(sourcePosition);
|
||||
_positionMs = position.inMilliseconds;
|
||||
_state = _state.copyWith(
|
||||
completed: false,
|
||||
position: position,
|
||||
duration: Duration.zero,
|
||||
duration: _timelineDuration ?? Duration.zero,
|
||||
buffer: Duration.zero,
|
||||
bufferRanges: const [],
|
||||
);
|
||||
completedController.add(false);
|
||||
positionController.add(position);
|
||||
durationController.add(Duration.zero);
|
||||
durationController.add(_timelineDuration ?? Duration.zero);
|
||||
bufferController.add(Duration.zero);
|
||||
bufferRangesController.add(const []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user