fix(player): 规范预热回收日志并抓帧过渡
This commit is contained in:
1 parent
bb2c729a7e
commit
4d3d067f77
6 files changed
+186
-40
No files matched your search
@@ -59,12 +59,16 @@ Future<void> _parkNeighbors(
|
||||
_PlayerSlot? warmNext,
|
||||
_PlayerSlot? warmPrevious,
|
||||
) async {
|
||||
await _placeNeighbor(session, old);
|
||||
await _placeNeighbor(session, warmNext);
|
||||
await _placeNeighbor(session, warmPrevious);
|
||||
await _placeNeighbor(session, old, roleHint: 'old-current');
|
||||
await _placeNeighbor(session, warmNext, roleHint: 'next');
|
||||
await _placeNeighbor(session, warmPrevious, roleHint: 'previous');
|
||||
}
|
||||
|
||||
Future<void> _placeNeighbor(PlaybackSession session, _PlayerSlot? slot) async {
|
||||
Future<void> _placeNeighbor(
|
||||
PlaybackSession session,
|
||||
_PlayerSlot? slot, {
|
||||
required String roleHint,
|
||||
}) async {
|
||||
if (slot == null || slot == session._active || slot.retiring) return;
|
||||
if (slot.owner != session.owner) {
|
||||
session._logOwnerRejection('park', slot);
|
||||
@@ -78,7 +82,7 @@ Future<void> _placeNeighbor(PlaybackSession session, _PlayerSlot? slot) async {
|
||||
session._previous = slot;
|
||||
return;
|
||||
}
|
||||
await session._retire(slot);
|
||||
await session._retire(slot, trigger: 'park-neighbor', roleHint: roleHint);
|
||||
}
|
||||
|
||||
/// 当前集已经出画后,按手势方向静默准备上一集和下一集。
|
||||
@@ -118,7 +122,11 @@ Future<void> _warmOne(
|
||||
await session._enqueue(() async {
|
||||
if (!_stillHeld(session, candidate, next: next)) return;
|
||||
_clearNeighbor(session, next: next);
|
||||
await session._retire(candidate);
|
||||
await session._retire(
|
||||
candidate,
|
||||
trigger: 'warm-failure',
|
||||
roleHint: next ? 'next' : 'previous',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -135,7 +143,11 @@ Future<_PlayerSlot?> _allocateNeighbor(
|
||||
final current = next ? session._next : session._previous;
|
||||
if (!allowed || current?.index != index) {
|
||||
_clearNeighbor(session, next: next);
|
||||
await session._retire(current);
|
||||
await session._retire(
|
||||
current,
|
||||
trigger: 'warm-slot-invalid',
|
||||
roleHint: next ? 'next' : 'previous',
|
||||
);
|
||||
}
|
||||
if (!_canAllocate(session, request, allowed: allowed, next: next)) {
|
||||
return;
|
||||
|
||||
@@ -138,8 +138,12 @@ class PlaybackSession extends ChangeNotifier {
|
||||
_notify();
|
||||
unawaited(
|
||||
_enqueue(() async {
|
||||
await _retire(staleNext);
|
||||
await _retire(stalePrevious);
|
||||
await _retire(staleNext, trigger: 'remap-stale-next', roleHint: 'next');
|
||||
await _retire(
|
||||
stalePrevious,
|
||||
trigger: 'remap-stale-previous',
|
||||
roleHint: 'previous',
|
||||
);
|
||||
}),
|
||||
);
|
||||
if (_visible && !_overlayOpen) _warmNeighbors(this);
|
||||
@@ -190,20 +194,23 @@ class PlaybackSession extends ChangeNotifier {
|
||||
return slot;
|
||||
}
|
||||
|
||||
Future<void> _retire(_PlayerSlot? slot) async {
|
||||
Future<void> _retire(
|
||||
_PlayerSlot? slot, {
|
||||
required String trigger,
|
||||
String? roleHint,
|
||||
}) async {
|
||||
if (slot == null) return;
|
||||
if (slot.owner != owner) {
|
||||
_logOwnerRejection('retire', slot);
|
||||
return;
|
||||
}
|
||||
if (!_live.contains(slot)) return;
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'[player-owner] phase=retire owner=${slot.owner.name} '
|
||||
'drama=${slot.dramaId ?? '-'} episodeIndex=${slot.index} '
|
||||
'controller=${_playerIdentity(slot.player)}',
|
||||
);
|
||||
}
|
||||
final role = _slotRole(slot, roleHint: roleHint);
|
||||
final video = slot.player is VideoPlayerPort
|
||||
? slot.player as VideoPlayerPort
|
||||
: null;
|
||||
final value = video?.controller.value;
|
||||
final slotPlaying = slot.playing;
|
||||
slot.retiring = true;
|
||||
final cleared =
|
||||
_active == slot ||
|
||||
@@ -222,6 +229,19 @@ class PlaybackSession extends ChangeNotifier {
|
||||
} finally {
|
||||
await slot.player.dispose();
|
||||
_live.remove(slot);
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'[player-slot] slot_released role=$role owner=${slot.owner.name} '
|
||||
'selectOwner=$owner drama=${slot.dramaId ?? '-'} '
|
||||
'episodeIndex=${slot.index} '
|
||||
'controller=${_playerIdentity(slot.player)} '
|
||||
'slotPlaying=${slotPlaying ? 1 : 0} '
|
||||
'isPlaying=${value?.isPlaying == true ? 1 : 0} '
|
||||
'position=${value?.position.inMilliseconds ?? '-'} '
|
||||
'currentIndex=$_currentIndex generation=$_generation '
|
||||
'trigger=$trigger',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +288,7 @@ class PlaybackSession extends ChangeNotifier {
|
||||
_PlayerSlot? target;
|
||||
await _enqueue(() async {
|
||||
if (_closed || request != _generation) return;
|
||||
await _retire(_handoff);
|
||||
await _retire(_handoff, trigger: 'select-handoff');
|
||||
final old = _active;
|
||||
if (old != null &&
|
||||
old.index == index &&
|
||||
@@ -339,7 +359,9 @@ class PlaybackSession extends ChangeNotifier {
|
||||
await _enqueue(() => _start(slot, request));
|
||||
await Future<void>.delayed(_qualityHandoffHold);
|
||||
if (previous != null && _handoff == previous && _active == slot) {
|
||||
await _enqueue(() => _retire(previous));
|
||||
await _enqueue(
|
||||
() => _retire(previous, trigger: 'quality-handoff-complete'),
|
||||
);
|
||||
}
|
||||
if (!_closed && request == _generation) _warmNeighbors(this);
|
||||
return _active == slot && slot.failure == null;
|
||||
@@ -351,8 +373,8 @@ class PlaybackSession extends ChangeNotifier {
|
||||
if (_closed || request != _generation || _active == null) return;
|
||||
final warm = _next;
|
||||
_next = null;
|
||||
await _retire(_handoff);
|
||||
await _retire(warm);
|
||||
await _retire(_handoff, trigger: 'replacement-handoff');
|
||||
await _retire(warm, trigger: 'replacement-next');
|
||||
if (_closed || request != _generation || _active == null) return;
|
||||
try {
|
||||
created = _create(index);
|
||||
@@ -379,7 +401,9 @@ class PlaybackSession extends ChangeNotifier {
|
||||
|
||||
Future<void> _dropReplacement(_PlayerSlot slot) {
|
||||
return _enqueue(() async {
|
||||
if (_live.contains(slot)) await _retire(slot);
|
||||
if (_live.contains(slot)) {
|
||||
await _retire(slot, trigger: 'replacement-drop');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -474,7 +498,7 @@ class PlaybackSession extends ChangeNotifier {
|
||||
_loading = false;
|
||||
_notify();
|
||||
for (final slot in _live.toList()) {
|
||||
await _retire(slot);
|
||||
await _retire(slot, trigger: 'session-release-all');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -483,6 +507,14 @@ class PlaybackSession extends ChangeNotifier {
|
||||
if (!_closed) notifyListeners();
|
||||
}
|
||||
|
||||
String _slotRole(_PlayerSlot slot, {String? roleHint}) {
|
||||
if (identical(slot, _active)) return 'current';
|
||||
if (identical(slot, _previous)) return 'previous';
|
||||
if (identical(slot, _next)) return 'next';
|
||||
if (identical(slot, _handoff)) return 'handoff';
|
||||
return roleHint ?? 'unassigned';
|
||||
}
|
||||
|
||||
void _logOwnerRejection(String phase, _PlayerSlot slot) {
|
||||
if (!kDebugMode) return;
|
||||
debugPrint(
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../config/app_config.dart';
|
||||
@@ -69,13 +68,6 @@ class VideoPlayerPort implements PlayerPort {
|
||||
Future<void> dispose() async {
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'[player-controller] phase=dispose '
|
||||
'controller=${identityHashCode(controller)} '
|
||||
'source=${controller.dataSource}\n${StackTrace.current}',
|
||||
);
|
||||
}
|
||||
try {
|
||||
await _initialization;
|
||||
} catch (_) {
|
||||
|
||||
Reference in new issue
Block a user