mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Support implicit i-Frame initialization segment.
In the HLS Spec (https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-04#section-4.4.3.6), specifically this or condition of this statement: "... defined by the EXT-X-MAP tag, or is located between the start of the resource and the offset of the first I-frame segment in that resource." Change adds code to add this "implicit" Media Initialization Segment if no EXT-X-MAP defines one explicitly.
This commit is contained in:
parent
64cd4383ad
commit
1f11233ba0
1 changed files with 34 additions and 2 deletions
|
|
@ -70,6 +70,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
private static final String TAG_DEFINE = "#EXT-X-DEFINE";
|
private static final String TAG_DEFINE = "#EXT-X-DEFINE";
|
||||||
private static final String TAG_STREAM_INF = "#EXT-X-STREAM-INF";
|
private static final String TAG_STREAM_INF = "#EXT-X-STREAM-INF";
|
||||||
private static final String TAG_STREAM_IFRAME = "#EXT-X-I-FRAME-STREAM-INF";
|
private static final String TAG_STREAM_IFRAME = "#EXT-X-I-FRAME-STREAM-INF";
|
||||||
|
private static final String TAG_IFRAME = "#EXT-X-I-FRAMES-ONLY";
|
||||||
private static final String TAG_MEDIA = "#EXT-X-MEDIA";
|
private static final String TAG_MEDIA = "#EXT-X-MEDIA";
|
||||||
private static final String TAG_TARGET_DURATION = "#EXT-X-TARGETDURATION";
|
private static final String TAG_TARGET_DURATION = "#EXT-X-TARGETDURATION";
|
||||||
private static final String TAG_DISCONTINUITY = "#EXT-X-DISCONTINUITY";
|
private static final String TAG_DISCONTINUITY = "#EXT-X-DISCONTINUITY";
|
||||||
|
|
@ -560,7 +561,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
long targetDurationUs = C.TIME_UNSET;
|
long targetDurationUs = C.TIME_UNSET;
|
||||||
boolean hasIndependentSegmentsTag = masterPlaylist.hasIndependentSegments;
|
boolean hasIndependentSegmentsTag = masterPlaylist.hasIndependentSegments;
|
||||||
boolean hasEndTag = false;
|
boolean hasEndTag = false;
|
||||||
Segment initializationSegment = null;
|
@Nullable Segment initializationSegment = null;
|
||||||
HashMap<String, String> variableDefinitions = new HashMap<>();
|
HashMap<String, String> variableDefinitions = new HashMap<>();
|
||||||
List<Segment> segments = new ArrayList<>();
|
List<Segment> segments = new ArrayList<>();
|
||||||
List<String> tags = new ArrayList<>();
|
List<String> tags = new ArrayList<>();
|
||||||
|
|
@ -574,6 +575,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
long segmentStartTimeUs = 0;
|
long segmentStartTimeUs = 0;
|
||||||
long segmentByteRangeOffset = 0;
|
long segmentByteRangeOffset = 0;
|
||||||
long segmentByteRangeLength = C.LENGTH_UNSET;
|
long segmentByteRangeLength = C.LENGTH_UNSET;
|
||||||
|
boolean isExplicitInitSegment = false; // Was declared (TAG_INIT_SEGMENT) vs implied.
|
||||||
|
boolean isIframeOnly = false;
|
||||||
|
|
||||||
long segmentMediaSequence = 0;
|
long segmentMediaSequence = 0;
|
||||||
boolean hasGapTag = false;
|
boolean hasGapTag = false;
|
||||||
|
|
||||||
|
|
@ -625,6 +629,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
segmentByteRangeLength,
|
segmentByteRangeLength,
|
||||||
fullSegmentEncryptionKeyUri,
|
fullSegmentEncryptionKeyUri,
|
||||||
fullSegmentEncryptionIV);
|
fullSegmentEncryptionIV);
|
||||||
|
isExplicitInitSegment = false;
|
||||||
segmentByteRangeOffset = 0;
|
segmentByteRangeOffset = 0;
|
||||||
segmentByteRangeLength = C.LENGTH_UNSET;
|
segmentByteRangeLength = C.LENGTH_UNSET;
|
||||||
} else if (line.startsWith(TAG_TARGET_DURATION)) {
|
} else if (line.startsWith(TAG_TARGET_DURATION)) {
|
||||||
|
|
@ -706,6 +711,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
hasIndependentSegmentsTag = true;
|
hasIndependentSegmentsTag = true;
|
||||||
} else if (line.equals(TAG_ENDLIST)) {
|
} else if (line.equals(TAG_ENDLIST)) {
|
||||||
hasEndTag = true;
|
hasEndTag = true;
|
||||||
|
} else if (line.equals(TAG_IFRAME)) {
|
||||||
|
isIframeOnly = true;
|
||||||
} else if (!line.startsWith("#")) {
|
} else if (!line.startsWith("#")) {
|
||||||
String segmentEncryptionIV;
|
String segmentEncryptionIV;
|
||||||
if (fullSegmentEncryptionKeyUri == null) {
|
if (fullSegmentEncryptionKeyUri == null) {
|
||||||
|
|
@ -716,9 +723,34 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
segmentEncryptionIV = Long.toHexString(segmentMediaSequence);
|
segmentEncryptionIV = Long.toHexString(segmentMediaSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String segmentResourseUri = replaceVariableReferences(line, variableDefinitions);
|
||||||
|
|
||||||
segmentMediaSequence++;
|
segmentMediaSequence++;
|
||||||
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
||||||
segmentByteRangeOffset = 0;
|
segmentByteRangeOffset = 0;
|
||||||
|
} else if (isIframeOnly) {
|
||||||
|
// If the I-Frame segment is byte-ranged then check if there is an initialization segment, if not,
|
||||||
|
// per the spec (https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-04#section-4.4.3.6)
|
||||||
|
// it is assumed to be "located between the start of the resource and the offset of the
|
||||||
|
// first I-frame segment"
|
||||||
|
|
||||||
|
// Wipe previous implict init segment if base resource URI changes
|
||||||
|
if (isExplicitInitSegment && initializationSegment != null) {
|
||||||
|
if (! segmentResourseUri.equals(initializationSegment.url)) {
|
||||||
|
initializationSegment = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initializationSegment == null) {
|
||||||
|
isExplicitInitSegment = true;
|
||||||
|
initializationSegment = new Segment(
|
||||||
|
segmentResourseUri,
|
||||||
|
0,
|
||||||
|
segmentByteRangeOffset - 1,
|
||||||
|
null, // TODO encryption same as segment?
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedDrmInitData == null && !currentSchemeDatas.isEmpty()) {
|
if (cachedDrmInitData == null && !currentSchemeDatas.isEmpty()) {
|
||||||
|
|
@ -735,7 +767,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
|
|
||||||
segments.add(
|
segments.add(
|
||||||
new Segment(
|
new Segment(
|
||||||
replaceVariableReferences(line, variableDefinitions),
|
segmentResourseUri,
|
||||||
initializationSegment,
|
initializationSegment,
|
||||||
segmentTitle,
|
segmentTitle,
|
||||||
segmentDurationUs,
|
segmentDurationUs,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue