Files
sm-emby-share/lib/core/media/media_capability_analyzer.dart
T
2026-07-14 11:11:36 +08:00

171 lines
5.0 KiB
Dart

import '../contracts/library.dart';
import '../../shared/utils/app_logger.dart';
import 'media_range_detector.dart';
enum VideoRangeCategory { dolbyVision, hdr10, hlg, sdr, unknown }
class MediaCapability {
final VideoRangeCategory rangeCategory;
final String? codec;
const MediaCapability({required this.rangeCategory, this.codec});
}
class ProbeResult {
final String? videoCodec;
final String? videoRange;
final String? videoRangeType;
const ProbeResult({this.videoCodec, this.videoRange, this.videoRangeType});
}
class MediaCapabilityAnalyzer {
static const _tag = 'MediaCap';
static MediaCapability analyze(
EmbyRawMediaSource? source, {
ProbeResult? probeResult,
}) {
if (source == null && probeResult == null) {
AppLogger.debug(_tag, 'analyze: source=null probeResult=null -> unknown');
return const MediaCapability(rangeCategory: VideoRangeCategory.unknown);
}
final codec = _resolveCodec(source, probeResult);
final videoRange = _resolveVideoRange(source, probeResult);
final videoRangeType = _resolveVideoRangeType(source, probeResult);
final isDV = _checkDolbyVision(
source,
probeResult,
codec,
videoRange,
videoRangeType,
);
final isHdrDetected = _checkHdr(
source,
probeResult,
videoRange,
videoRangeType,
);
final VideoRangeCategory rangeCategory;
if (isDV) {
rangeCategory = VideoRangeCategory.dolbyVision;
} else if (isHdrDetected) {
rangeCategory = _classifyHdr(videoRangeType, videoRange);
} else {
rangeCategory = VideoRangeCategory.sdr;
}
AppLogger.debug(
_tag,
'analyze: codec=$codec '
'videoRange=$videoRange videoRangeType=$videoRangeType '
'-> rangeCategory=${rangeCategory.name}',
);
return MediaCapability(rangeCategory: rangeCategory, codec: codec);
}
static String? _resolveCodec(EmbyRawMediaSource? source, ProbeResult? probe) {
if (probe?.videoCodec != null) return probe!.videoCodec;
if (source == null) return null;
final video = findVideoStream(source);
return video?.Codec;
}
static String? _resolveVideoRange(
EmbyRawMediaSource? source,
ProbeResult? probe,
) {
if (probe?.videoRange != null) return probe!.videoRange;
if (source == null) return null;
final video = findVideoStream(source);
return video?.extra['VideoRange'] as String?;
}
static String? _resolveVideoRangeType(
EmbyRawMediaSource? source,
ProbeResult? probe,
) {
if (probe?.videoRangeType != null) return probe!.videoRangeType;
if (source == null) return null;
final video = findVideoStream(source);
return video?.extra['VideoRangeType'] as String?;
}
static bool _checkDolbyVision(
EmbyRawMediaSource? source,
ProbeResult? probe,
String? codec,
String? videoRange,
String? videoRangeType,
) {
if (probe != null) {
final lCodec = codec?.toLowerCase() ?? '';
final lRange = videoRange?.toLowerCase() ?? '';
final lRangeType = videoRangeType?.toLowerCase() ?? '';
if (lRangeType.contains('dovi') || lRangeType.contains('dolby')) {
return true;
}
if (lRange.contains('dovi') || lRange.contains('dolby')) return true;
if (lCodec.contains('dvh') || lCodec.contains('dovi')) return true;
if (videoRange != null || videoRangeType != null) return false;
}
if (source != null) return isDolbyVision(source);
return false;
}
static bool _checkHdr(
EmbyRawMediaSource? source,
ProbeResult? probe,
String? videoRange,
String? videoRangeType,
) {
if (probe != null) {
final lRange = videoRange?.toLowerCase() ?? '';
final lRangeType = videoRangeType?.toLowerCase() ?? '';
final hasHdrSignal =
lRange.contains('hdr') ||
lRange.contains('dovi') ||
lRangeType.contains('hdr') ||
lRangeType.contains('dovi') ||
lRangeType.contains('hlg');
if (hasHdrSignal) return true;
if (videoRange != null || videoRangeType != null) return false;
}
if (source != null) {
if (isHdr(source)) return true;
final video = findVideoStream(source);
if (video != null) {
final rangeType = (video.extra['VideoRangeType'] as String? ?? '')
.toLowerCase();
if (rangeType.contains('hlg')) return true;
}
return false;
}
return false;
}
static VideoRangeCategory _classifyHdr(
String? videoRangeType,
String? videoRange,
) {
final lRangeType = videoRangeType?.toLowerCase() ?? '';
if (lRangeType.contains('hlg')) return VideoRangeCategory.hlg;
if (lRangeType.contains('hdr10')) return VideoRangeCategory.hdr10;
if (lRangeType.contains('hdr')) return VideoRangeCategory.hdr10;
final lRange = videoRange?.toLowerCase() ?? '';
if (lRange.contains('hlg')) return VideoRangeCategory.hlg;
if (lRange.contains('hdr')) return VideoRangeCategory.hdr10;
return VideoRangeCategory.unknown;
}
}