hls.js 1.5.14-0.canary.10559 → 1.5.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/dist/hls-demo.js +38 -41
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +2911 -4558
- package/dist/hls.js.d.ts +112 -186
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +2291 -3311
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +1813 -2835
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +4707 -6356
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +42 -42
- package/src/config.ts +2 -5
- package/src/controller/abr-controller.ts +25 -39
- package/src/controller/audio-stream-controller.ts +136 -156
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +10 -27
- package/src/controller/base-stream-controller.ts +107 -263
- package/src/controller/buffer-controller.ts +97 -250
- package/src/controller/buffer-operation-queue.ts +19 -16
- package/src/controller/cap-level-controller.ts +2 -3
- package/src/controller/cmcd-controller.ts +14 -51
- package/src/controller/content-steering-controller.ts +15 -29
- package/src/controller/eme-controller.ts +23 -10
- package/src/controller/error-controller.ts +22 -28
- package/src/controller/fps-controller.ts +3 -8
- package/src/controller/fragment-finders.ts +16 -44
- package/src/controller/fragment-tracker.ts +25 -58
- package/src/controller/gap-controller.ts +16 -43
- package/src/controller/id3-track-controller.ts +35 -45
- package/src/controller/latency-controller.ts +13 -18
- package/src/controller/level-controller.ts +19 -37
- package/src/controller/stream-controller.ts +83 -100
- package/src/controller/subtitle-stream-controller.ts +47 -35
- package/src/controller/subtitle-track-controller.ts +3 -5
- package/src/controller/timeline-controller.ts +22 -20
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +16 -32
- package/src/crypt/fast-aes-key.ts +5 -28
- package/src/demux/audio/aacdemuxer.ts +5 -5
- package/src/demux/audio/ac3-demuxer.ts +4 -5
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/audio/base-audio-demuxer.ts +15 -21
- package/src/demux/audio/mp3demuxer.ts +3 -4
- package/src/demux/audio/mpegaudio.ts +1 -1
- package/src/demux/id3.ts +411 -0
- package/src/demux/inject-worker.ts +4 -38
- package/src/demux/mp4demuxer.ts +8 -17
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +83 -106
- package/src/demux/transmuxer-worker.ts +77 -111
- package/src/demux/transmuxer.ts +22 -46
- package/src/demux/tsdemuxer.ts +65 -131
- package/src/demux/video/avc-video-parser.ts +156 -219
- package/src/demux/video/base-video-parser.ts +9 -133
- package/src/demux/video/exp-golomb.ts +208 -0
- package/src/errors.ts +0 -2
- package/src/events.ts +1 -8
- package/src/exports-named.ts +1 -1
- package/src/hls.ts +48 -97
- package/src/loader/date-range.ts +5 -71
- package/src/loader/fragment-loader.ts +21 -23
- package/src/loader/fragment.ts +4 -8
- package/src/loader/key-loader.ts +1 -3
- package/src/loader/level-details.ts +6 -6
- package/src/loader/level-key.ts +9 -10
- package/src/loader/m3u8-parser.ts +144 -138
- package/src/loader/playlist-loader.ts +7 -5
- package/src/remux/mp4-generator.ts +1 -196
- package/src/remux/mp4-remuxer.ts +84 -55
- package/src/remux/passthrough-remuxer.ts +8 -23
- package/src/task-loop.ts +2 -5
- package/src/types/component-api.ts +1 -3
- package/src/types/demuxer.ts +1 -3
- package/src/types/events.ts +6 -19
- package/src/types/fragment-tracker.ts +2 -2
- package/src/types/general.ts +6 -0
- package/src/types/media-playlist.ts +1 -9
- package/src/types/remuxer.ts +1 -1
- package/src/utils/attr-list.ts +9 -96
- package/src/utils/buffer-helper.ts +31 -12
- package/src/utils/cea-608-parser.ts +3 -1
- package/src/utils/codecs.ts +5 -34
- package/src/utils/discontinuities.ts +47 -21
- package/src/utils/fetch-loader.ts +1 -1
- package/src/utils/hdr.ts +7 -4
- package/src/utils/imsc1-ttml-parser.ts +1 -1
- package/src/utils/keysystem-util.ts +6 -1
- package/src/utils/level-helper.ts +44 -71
- package/src/utils/logger.ts +23 -58
- package/src/utils/mp4-tools.ts +3 -5
- package/src/utils/rendition-helper.ts +74 -100
- package/src/utils/variable-substitution.ts +19 -0
- package/src/utils/webvtt-parser.ts +12 -2
- package/dist/hls.d.mts +0 -3179
- package/dist/hls.d.ts +0 -3179
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/demux/video/hevc-video-parser.ts +0 -718
- package/src/utils/encryption-methods-util.ts +0 -21
- package/src/utils/hash.ts +0 -10
- package/src/utils/utf8-utils.ts +0 -18
- package/src/version.ts +0 -1
package/src/loader/date-range.ts
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
import { AttrList } from '../utils/attr-list';
|
2
2
|
import { logger } from '../utils/logger';
|
3
|
-
import type { Fragment } from './fragment';
|
4
3
|
|
5
4
|
// Avoid exporting const enum so that these values can be inlined
|
6
5
|
const enum DateRangeAttribute {
|
7
6
|
ID = 'ID',
|
8
7
|
CLASS = 'CLASS',
|
9
|
-
CUE = 'CUE',
|
10
8
|
START_DATE = 'START-DATE',
|
11
9
|
DURATION = 'DURATION',
|
12
10
|
END_DATE = 'END-DATE',
|
@@ -14,22 +12,12 @@ const enum DateRangeAttribute {
|
|
14
12
|
PLANNED_DURATION = 'PLANNED-DURATION',
|
15
13
|
SCTE35_OUT = 'SCTE35-OUT',
|
16
14
|
SCTE35_IN = 'SCTE35-IN',
|
17
|
-
SCTE35_CMD = 'SCTE35-CMD',
|
18
15
|
}
|
19
16
|
|
20
|
-
export type DateRangeCue = {
|
21
|
-
pre: boolean;
|
22
|
-
post: boolean;
|
23
|
-
once: boolean;
|
24
|
-
};
|
25
|
-
|
26
|
-
const CLASS_INTERSTITIAL = 'com.apple.hls.interstitial';
|
27
|
-
|
28
17
|
export function isDateRangeCueAttribute(attrName: string): boolean {
|
29
18
|
return (
|
30
19
|
attrName !== DateRangeAttribute.ID &&
|
31
20
|
attrName !== DateRangeAttribute.CLASS &&
|
32
|
-
attrName !== DateRangeAttribute.CUE &&
|
33
21
|
attrName !== DateRangeAttribute.START_DATE &&
|
34
22
|
attrName !== DateRangeAttribute.DURATION &&
|
35
23
|
attrName !== DateRangeAttribute.END_DATE &&
|
@@ -40,27 +28,17 @@ export function isDateRangeCueAttribute(attrName: string): boolean {
|
|
40
28
|
export function isSCTE35Attribute(attrName: string): boolean {
|
41
29
|
return (
|
42
30
|
attrName === DateRangeAttribute.SCTE35_OUT ||
|
43
|
-
attrName === DateRangeAttribute.SCTE35_IN
|
44
|
-
attrName === DateRangeAttribute.SCTE35_CMD
|
31
|
+
attrName === DateRangeAttribute.SCTE35_IN
|
45
32
|
);
|
46
33
|
}
|
47
34
|
|
48
35
|
export class DateRange {
|
49
36
|
public attr: AttrList;
|
50
|
-
public tagAnchor: Fragment | null;
|
51
|
-
public tagOrder: number;
|
52
37
|
private _startDate: Date;
|
53
38
|
private _endDate?: Date;
|
54
|
-
private _cue?: DateRangeCue;
|
55
39
|
private _badValueForSameId?: string;
|
56
40
|
|
57
|
-
constructor(
|
58
|
-
dateRangeAttr: AttrList,
|
59
|
-
dateRangeWithSameId?: DateRange | undefined,
|
60
|
-
tagCount: number = 0,
|
61
|
-
) {
|
62
|
-
this.tagAnchor = dateRangeWithSameId?.tagAnchor || null;
|
63
|
-
this.tagOrder = dateRangeWithSameId?.tagOrder ?? tagCount;
|
41
|
+
constructor(dateRangeAttr: AttrList, dateRangeWithSameId?: DateRange) {
|
64
42
|
if (dateRangeWithSameId) {
|
65
43
|
const previousAttr = dateRangeWithSameId.attr;
|
66
44
|
for (const key in previousAttr) {
|
@@ -83,13 +61,9 @@ export class DateRange {
|
|
83
61
|
);
|
84
62
|
}
|
85
63
|
this.attr = dateRangeAttr;
|
86
|
-
this._startDate =
|
87
|
-
? dateRangeWithSameId.startDate
|
88
|
-
: new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);
|
64
|
+
this._startDate = new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);
|
89
65
|
if (DateRangeAttribute.END_DATE in this.attr) {
|
90
|
-
const endDate =
|
91
|
-
dateRangeWithSameId?.endDate ||
|
92
|
-
new Date(this.attr[DateRangeAttribute.END_DATE]);
|
66
|
+
const endDate = new Date(this.attr[DateRangeAttribute.END_DATE]);
|
93
67
|
if (Number.isFinite(endDate.getTime())) {
|
94
68
|
this._endDate = endDate;
|
95
69
|
}
|
@@ -104,36 +78,6 @@ export class DateRange {
|
|
104
78
|
return this.attr.CLASS;
|
105
79
|
}
|
106
80
|
|
107
|
-
get cue(): DateRangeCue {
|
108
|
-
const _cue = this._cue;
|
109
|
-
if (_cue === undefined) {
|
110
|
-
return (this._cue = this.attr.enumeratedStringList(
|
111
|
-
this.attr.CUE ? 'CUE' : 'X-CUE',
|
112
|
-
{
|
113
|
-
pre: false,
|
114
|
-
post: false,
|
115
|
-
once: false,
|
116
|
-
},
|
117
|
-
));
|
118
|
-
}
|
119
|
-
return _cue;
|
120
|
-
}
|
121
|
-
|
122
|
-
get startTime(): number {
|
123
|
-
const { tagAnchor } = this;
|
124
|
-
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
125
|
-
if (tagAnchor === null || tagAnchor.programDateTime === null) {
|
126
|
-
logger.warn(
|
127
|
-
`Expected tagAnchor Fragment with PDT set for DateRange "${this.id}": ${tagAnchor}`,
|
128
|
-
);
|
129
|
-
return NaN;
|
130
|
-
}
|
131
|
-
return (
|
132
|
-
tagAnchor.start +
|
133
|
-
(this.startDate.getTime() - tagAnchor.programDateTime) / 1000
|
134
|
-
);
|
135
|
-
}
|
136
|
-
|
137
81
|
get startDate(): Date {
|
138
82
|
return this._startDate;
|
139
83
|
}
|
@@ -176,23 +120,13 @@ export class DateRange {
|
|
176
120
|
return this.attr.bool(DateRangeAttribute.END_ON_NEXT);
|
177
121
|
}
|
178
122
|
|
179
|
-
get isInterstitial(): boolean {
|
180
|
-
return this.class === CLASS_INTERSTITIAL;
|
181
|
-
}
|
182
|
-
|
183
123
|
get isValid(): boolean {
|
184
124
|
return (
|
185
125
|
!!this.id &&
|
186
126
|
!this._badValueForSameId &&
|
187
127
|
Number.isFinite(this.startDate.getTime()) &&
|
188
128
|
(this.duration === null || this.duration >= 0) &&
|
189
|
-
(!this.endOnNext || !!this.class)
|
190
|
-
(!this.attr.CUE ||
|
191
|
-
(!this.cue.pre && !this.cue.post) ||
|
192
|
-
this.cue.pre !== this.cue.post) &&
|
193
|
-
(!this.isInterstitial ||
|
194
|
-
'X-ASSET-URI' in this.attr ||
|
195
|
-
'X-ASSET-LIST' in this.attr)
|
129
|
+
(!this.endOnNext || !!this.class)
|
196
130
|
);
|
197
131
|
}
|
198
132
|
}
|
@@ -1,17 +1,18 @@
|
|
1
1
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
2
|
+
import { Fragment } from './fragment';
|
3
|
+
import {
|
4
|
+
Loader,
|
5
|
+
LoaderConfiguration,
|
6
|
+
FragmentLoaderContext,
|
7
|
+
} from '../types/loader';
|
2
8
|
import { getLoaderConfigWithoutReties } from '../utils/error-helper';
|
3
9
|
import type { HlsConfig } from '../config';
|
4
|
-
import type { BaseSegment,
|
10
|
+
import type { BaseSegment, Part } from './fragment';
|
5
11
|
import type {
|
6
12
|
ErrorData,
|
7
13
|
FragLoadedData,
|
8
14
|
PartsLoadedData,
|
9
15
|
} from '../types/events';
|
10
|
-
import type {
|
11
|
-
Loader,
|
12
|
-
LoaderConfiguration,
|
13
|
-
FragmentLoaderContext,
|
14
|
-
} from '../types/loader';
|
15
16
|
|
16
17
|
const MIN_CHUNK_SIZE = Math.pow(2, 17); // 128kb
|
17
18
|
|
@@ -76,11 +77,13 @@ export default class FragmentLoader {
|
|
76
77
|
frag.gap = false;
|
77
78
|
}
|
78
79
|
}
|
79
|
-
const loader =
|
80
|
-
|
81
|
-
|
80
|
+
const loader =
|
81
|
+
(this.loader =
|
82
|
+
frag.loader =
|
83
|
+
FragmentILoader
|
84
|
+
? new FragmentILoader(config)
|
85
|
+
: (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
|
82
86
|
const loaderContext = createLoaderContext(frag);
|
83
|
-
frag.loader = loader;
|
84
87
|
const loadPolicy = getLoaderConfigWithoutReties(
|
85
88
|
config.fragLoadPolicy.default,
|
86
89
|
);
|
@@ -185,11 +188,13 @@ export default class FragmentLoader {
|
|
185
188
|
reject(createGapLoadError(frag, part));
|
186
189
|
return;
|
187
190
|
}
|
188
|
-
const loader =
|
189
|
-
|
190
|
-
|
191
|
+
const loader =
|
192
|
+
(this.loader =
|
193
|
+
frag.loader =
|
194
|
+
FragmentILoader
|
195
|
+
? new FragmentILoader(config)
|
196
|
+
: (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
|
191
197
|
const loaderContext = createLoaderContext(frag, part);
|
192
|
-
frag.loader = loader;
|
193
198
|
// Should we define another load policy for parts?
|
194
199
|
const loadPolicy = getLoaderConfigWithoutReties(
|
195
200
|
config.fragLoadPolicy.default,
|
@@ -331,11 +336,8 @@ function createLoaderContext(
|
|
331
336
|
if (Number.isFinite(start) && Number.isFinite(end)) {
|
332
337
|
let byteRangeStart = start;
|
333
338
|
let byteRangeEnd = end;
|
334
|
-
if (
|
335
|
-
|
336
|
-
isMethodFullSegmentAesCbc(frag.decryptdata?.method)
|
337
|
-
) {
|
338
|
-
// MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
|
339
|
+
if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {
|
340
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
339
341
|
// has the unencrypted size specified in the range.
|
340
342
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
341
343
|
const fragmentLen = end - start;
|
@@ -370,10 +372,6 @@ function createGapLoadError(frag: Fragment, part?: Part): LoadError {
|
|
370
372
|
return new LoadError(errorData);
|
371
373
|
}
|
372
374
|
|
373
|
-
function isMethodFullSegmentAesCbc(method) {
|
374
|
-
return method === 'AES-128' || method === 'AES-256';
|
375
|
-
}
|
376
|
-
|
377
375
|
export class LoadError extends Error {
|
378
376
|
public readonly data: FragLoadFailResult;
|
379
377
|
constructor(data: FragLoadFailResult) {
|
package/src/loader/fragment.ts
CHANGED
@@ -90,10 +90,6 @@ export class BaseSegment {
|
|
90
90
|
}
|
91
91
|
}
|
92
92
|
|
93
|
-
export interface MediaFragment extends Fragment {
|
94
|
-
sn: number;
|
95
|
-
}
|
96
|
-
|
97
93
|
/**
|
98
94
|
* Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.
|
99
95
|
*/
|
@@ -127,9 +123,9 @@ export class Fragment extends BaseSegment {
|
|
127
123
|
// The ending Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.
|
128
124
|
public endPTS?: number;
|
129
125
|
// The starting Decode Time Stamp (DTS) of the fragment. Set after transmux complete.
|
130
|
-
public startDTS
|
126
|
+
public startDTS!: number;
|
131
127
|
// The ending Decode Time Stamp (DTS) of the fragment. Set after transmux complete.
|
132
|
-
public endDTS
|
128
|
+
public endDTS!: number;
|
133
129
|
// The start time of the fragment, as listed in the manifest. Updated after transmux complete.
|
134
130
|
public start: number = 0;
|
135
131
|
// Set by `updateFragPTSDTS` in level-helper
|
@@ -278,13 +274,13 @@ export class Part extends BaseSegment {
|
|
278
274
|
public readonly gap: boolean = false;
|
279
275
|
public readonly independent: boolean = false;
|
280
276
|
public readonly relurl: string;
|
281
|
-
public readonly fragment:
|
277
|
+
public readonly fragment: Fragment;
|
282
278
|
public readonly index: number;
|
283
279
|
public stats: LoadStats = new LoadStats();
|
284
280
|
|
285
281
|
constructor(
|
286
282
|
partAttrs: AttrList,
|
287
|
-
frag:
|
283
|
+
frag: Fragment,
|
288
284
|
baseurl: string,
|
289
285
|
index: number,
|
290
286
|
previous?: Part,
|
package/src/loader/key-loader.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
2
|
-
import
|
2
|
+
import {
|
3
3
|
LoaderStats,
|
4
4
|
LoaderResponse,
|
5
5
|
LoaderConfiguration,
|
@@ -194,8 +194,6 @@ export default class KeyLoader implements ComponentAPI {
|
|
194
194
|
}
|
195
195
|
return this.loadKeyEME(keyInfo, frag);
|
196
196
|
case 'AES-128':
|
197
|
-
case 'AES-256':
|
198
|
-
case 'AES-256-CTR':
|
199
197
|
return this.loadKeyHTTP(keyInfo, frag);
|
200
198
|
default:
|
201
199
|
return Promise.reject(
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import
|
2
|
-
import type {
|
1
|
+
import { Part } from './fragment';
|
2
|
+
import type { Fragment } from './fragment';
|
3
3
|
import type { AttrList } from '../utils/attr-list';
|
4
|
+
import type { DateRange } from './date-range';
|
4
5
|
import type { VariableMap } from '../types/level';
|
5
6
|
|
6
7
|
const DEFAULT_TARGET_DURATION = 10;
|
@@ -14,11 +15,10 @@ export class LevelDetails {
|
|
14
15
|
public averagetargetduration?: number;
|
15
16
|
public endCC: number = 0;
|
16
17
|
public endSN: number = 0;
|
17
|
-
public fragments:
|
18
|
-
public fragmentHint?:
|
18
|
+
public fragments: Fragment[];
|
19
|
+
public fragmentHint?: Fragment;
|
19
20
|
public partList: Part[] | null = null;
|
20
21
|
public dateRanges: Record<string, DateRange>;
|
21
|
-
public dateRangeTagCount: number = 0;
|
22
22
|
public live: boolean = true;
|
23
23
|
public ageHeader: number = 0;
|
24
24
|
public advancedDateTime?: number;
|
@@ -148,7 +148,7 @@ export class LevelDetails {
|
|
148
148
|
|
149
149
|
get lastPartSn(): number {
|
150
150
|
if (this.partList?.length) {
|
151
|
-
return this.partList[this.partList.length - 1].fragment.sn;
|
151
|
+
return this.partList[this.partList.length - 1].fragment.sn as number;
|
152
152
|
}
|
153
153
|
return this.endSN;
|
154
154
|
}
|
package/src/loader/level-key.ts
CHANGED
@@ -2,7 +2,6 @@ import {
|
|
2
2
|
changeEndianness,
|
3
3
|
convertDataUriToArrayBytes,
|
4
4
|
} from '../utils/keysystem-util';
|
5
|
-
import { isFullSegmentEncryption } from '../utils/encryption-methods-util';
|
6
5
|
import { KeySystemFormats } from '../utils/mediakeys-helper';
|
7
6
|
import { mp4pssh } from '../utils/mp4-tools';
|
8
7
|
import { logger } from '../utils/logger';
|
@@ -52,14 +51,13 @@ export class LevelKey implements DecryptData {
|
|
52
51
|
this.keyFormatVersions = formatversions;
|
53
52
|
this.iv = iv;
|
54
53
|
this.encrypted = method ? method !== 'NONE' : false;
|
55
|
-
this.isCommonEncryption =
|
56
|
-
this.encrypted && !isFullSegmentEncryption(method);
|
54
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
57
55
|
}
|
58
56
|
|
59
57
|
public isSupported(): boolean {
|
60
58
|
// If it's Segment encryption or No encryption, just select that key system
|
61
59
|
if (this.method) {
|
62
|
-
if (
|
60
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
63
61
|
return true;
|
64
62
|
}
|
65
63
|
if (this.keyFormat === 'identity') {
|
@@ -90,15 +88,16 @@ export class LevelKey implements DecryptData {
|
|
90
88
|
return null;
|
91
89
|
}
|
92
90
|
|
93
|
-
if (
|
91
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
94
92
|
if (typeof sn !== 'number') {
|
95
93
|
// We are fetching decryption data for a initialization segment
|
96
|
-
// If the segment was encrypted with AES-128
|
94
|
+
// If the segment was encrypted with AES-128
|
97
95
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
if (this.method === 'AES-128' && !this.iv) {
|
97
|
+
logger.warn(
|
98
|
+
`missing IV for initialization segment with method="${this.method}" - compliance issue`,
|
99
|
+
);
|
100
|
+
}
|
102
101
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
103
102
|
sn = 0;
|
104
103
|
}
|