diff --git a/lib/src/asms/better_player_asms_subtitle.dart b/lib/src/asms/better_player_asms_subtitle.dart index 83a9d201b..1967edcd8 100644 --- a/lib/src/asms/better_player_asms_subtitle.dart +++ b/lib/src/asms/better_player_asms_subtitle.dart @@ -30,6 +30,9 @@ class BetterPlayerAsmsSubtitle { ///List of subtitle segments. Only used when [isSegmented] is true. final List? segments; + ///If the subtitle is the default + final bool? isDefault; + BetterPlayerAsmsSubtitle({ this.language, this.name, @@ -40,5 +43,6 @@ class BetterPlayerAsmsSubtitle { this.isSegmented, this.segmentsTime, this.segments, + this.isDefault, }); } diff --git a/lib/src/core/better_player_controller.dart b/lib/src/core/better_player_controller.dart index 1528f8aaf..246dc21f9 100644 --- a/lib/src/core/better_player_controller.dart +++ b/lib/src/core/better_player_controller.dart @@ -329,6 +329,7 @@ class BetterPlayerController { asmsIsSegmented: asmsSubtitle.isSegmented, asmsSegmentsTime: asmsSubtitle.segmentsTime, asmsSegments: asmsSubtitle.segments, + selectedByDefault: asmsSubtitle.isDefault, ), ); }); diff --git a/lib/src/hls/better_player_hls_utils.dart b/lib/src/hls/better_player_hls_utils.dart index ef61faba8..f1ec367be 100644 --- a/lib/src/hls/better_player_hls_utils.dart +++ b/lib/src/hls/better_player_hls_utils.dart @@ -13,6 +13,7 @@ import 'package:better_player/src/hls/hls_parser/hls_media_playlist.dart'; import 'package:better_player/src/hls/hls_parser/hls_playlist_parser.dart'; import 'package:better_player/src/hls/hls_parser/rendition.dart'; import 'package:better_player/src/hls/hls_parser/segment.dart'; +import 'package:better_player/src/hls/hls_parser/util.dart'; ///HLS helper class class BetterPlayerHlsUtils { @@ -137,6 +138,12 @@ class BetterPlayerHlsUtils { targetDuration = parsedSubtitle.targetDurationUs! ~/ 1000; } + bool isDefault = false; + + if(rendition.format.selectionFlags != null) { + isDefault = Util.checkBitPositionIsSet(rendition.format.selectionFlags!, 1); + } + return BetterPlayerAsmsSubtitle( name: rendition.format.label, language: rendition.format.language, @@ -145,6 +152,7 @@ class BetterPlayerHlsUtils { isSegmented: isSegmented, segmentsTime: targetDuration, segments: asmsSegments, + isDefault: isDefault ); } catch (exception) { BetterPlayerUtils.log("Failed to process subtitles playlist: $exception"); diff --git a/lib/src/hls/hls_parser/format.dart b/lib/src/hls/hls_parser/format.dart index 0e348e79c..97ec455ef 100644 --- a/lib/src/hls/hls_parser/format.dart +++ b/lib/src/hls/hls_parser/format.dart @@ -23,6 +23,7 @@ class Format { this.channelCount, String? language, this.accessibilityChannel, + this.isDefault, }) : language = language?.toLowerCase(); factory Format.createVideoContainerFormat( @@ -37,7 +38,9 @@ class Format { required int? height, required double? frameRate, int selectionFlags = Util.selectionFlagDefault, - int? roleFlags}) => + int? roleFlags, + bool? isDefault, + }) => Format( id: id, label: label, @@ -51,6 +54,7 @@ class Format { height: height, frameRate: frameRate, roleFlags: roleFlags, + isDefault: isDefault, ); /// An identifier for the format, or null if unknown or not applicable. @@ -111,6 +115,9 @@ class Format { /// The Accessibility channel, or null if not known or applicable. final int? accessibilityChannel; + /// If track is marked as default, or null if not known or applicable + final bool? isDefault; + Format copyWithMetadata(Metadata metadata) => Format( id: id, label: label, diff --git a/lib/src/hls/hls_parser/hls_playlist_parser.dart b/lib/src/hls/hls_parser/hls_playlist_parser.dart index 6ec85449b..7233e2546 100644 --- a/lib/src/hls/hls_parser/hls_playlist_parser.dart +++ b/lib/src/hls/hls_parser/hls_playlist_parser.dart @@ -602,6 +602,7 @@ class HlsPlaylistParser { static int _parseSelectionFlags(String line) { int flags = 0; + if (parseOptionalBooleanAttribute( line: line, pattern: regexpDefault, @@ -622,8 +623,12 @@ class HlsPlaylistParser { required String pattern, required bool defaultValue, }) { - final List list = line.allMatches(pattern).toList(); - return list.isEmpty ? defaultValue : list.first.pattern == booleanTrue; + final regExp = RegExp(pattern); + final List list = regExp.allMatches(line).toList(); + final ret = list.isEmpty + ? defaultValue + : line.substring(list.first.start, list.first.end).contains(booleanTrue); + return ret; } static int _parseRoleFlags( diff --git a/lib/src/hls/hls_parser/util.dart b/lib/src/hls/hls_parser/util.dart index 5186175ca..d2fe2938f 100644 --- a/lib/src/hls/hls_parser/util.dart +++ b/lib/src/hls/hls_parser/util.dart @@ -126,6 +126,13 @@ class Util { static List splitCodecs(String? codecs) => codecs?.isNotEmpty != true ? [] : codecs!.trim().split(RegExp('(\\s*,\\s*)')); + + static bool checkBitPositionIsSet(int number, int bitPosition) { + if ((number & (1 << (bitPosition - 1))) > 0) + return true; + else + return false; + } } class CencType {