@svta/cml-608 1.0.3 → 1.1.1

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/dist/index.js CHANGED
@@ -15,10 +15,46 @@ const VerboseLevel = {
15
15
  DEBUG: 3,
16
16
  DATA: 3
17
17
  };
18
-
19
18
  //#endregion
20
19
  //#region src/CaptionsLogger.ts
21
20
  /**
21
+ *
22
+ * This code was ported from the dash.js project at:
23
+ * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
24
+ * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
25
+ *
26
+ * The original copyright appears below:
27
+ *
28
+ * The copyright in this software is being made available under the BSD License,
29
+ * included below. This software may be subject to other third party and contributor
30
+ * rights, including patent rights, and no such rights are granted under this license.
31
+ *
32
+ * Copyright (c) 2015-2016, DASH Industry Forum.
33
+ * All rights reserved.
34
+ *
35
+ * Redistribution and use in source and binary forms, with or without modification,
36
+ * are permitted provided that the following conditions are met:
37
+ * 1. Redistributions of source code must retain the above copyright notice, this
38
+ * list of conditions and the following disclaimer.
39
+ * * Redistributions in binary form must reproduce the above copyright notice,
40
+ * this list of conditions and the following disclaimer in the documentation and/or
41
+ * other materials provided with the distribution.
42
+ * 2. Neither the name of Dash Industry Forum nor the names of its
43
+ * contributors may be used to endorse or promote products derived from this software
44
+ * without specific prior written permission.
45
+ *
46
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
47
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
50
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
+ * POSSIBILITY OF SUCH DAMAGE.
56
+ */
57
+ /**
22
58
  * CaptionsLogger. To be removed in the future.
23
59
  *
24
60
  * @public
@@ -35,7 +71,6 @@ var CaptionsLogger = class {
35
71
  }
36
72
  }
37
73
  };
38
-
39
74
  //#endregion
40
75
  //#region src/PenState.ts
41
76
  /**
@@ -81,10 +116,46 @@ var PenState = class {
81
116
  this.flash = newPenState.flash;
82
117
  }
83
118
  };
84
-
85
119
  //#endregion
86
120
  //#region src/StyledUnicodeChar.ts
87
121
  /**
122
+ *
123
+ * This code was ported from the dash.js project at:
124
+ * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
125
+ * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
126
+ *
127
+ * The original copyright appears below:
128
+ *
129
+ * The copyright in this software is being made available under the BSD License,
130
+ * included below. This software may be subject to other third party and contributor
131
+ * rights, including patent rights, and no such rights are granted under this license.
132
+ *
133
+ * Copyright (c) 2015-2016, DASH Industry Forum.
134
+ * All rights reserved.
135
+ *
136
+ * Redistribution and use in source and binary forms, with or without modification,
137
+ * are permitted provided that the following conditions are met:
138
+ * 1. Redistributions of source code must retain the above copyright notice, this
139
+ * list of conditions and the following disclaimer.
140
+ * * Redistributions in binary form must reproduce the above copyright notice,
141
+ * this list of conditions and the following disclaimer in the documentation and/or
142
+ * other materials provided with the distribution.
143
+ * 2. Neither the name of Dash Industry Forum nor the names of its
144
+ * contributors may be used to endorse or promote products derived from this software
145
+ * without specific prior written permission.
146
+ *
147
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
148
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
149
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
150
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
151
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
152
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
153
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
154
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
155
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
156
+ * POSSIBILITY OF SUCH DAMAGE.
157
+ */
158
+ /**
88
159
  * Unicode character with styling and background.
89
160
  *
90
161
  * @public
@@ -116,11 +187,6 @@ var StyledUnicodeChar = class {
116
187
  return this.uchar === " " && this.penState.isDefault();
117
188
  }
118
189
  };
119
-
120
- //#endregion
121
- //#region src/utils/NR_COLS.ts
122
- const NR_COLS = 100;
123
-
124
190
  //#endregion
125
191
  //#region src/utils/specialCea608CharsCodes.ts
126
192
  /**
@@ -218,16 +284,51 @@ const specialCea608CharsCodes = {
218
284
  206: 9495,
219
285
  207: 9499
220
286
  };
221
-
222
287
  //#endregion
223
288
  //#region src/utils/getCharForByte.ts
224
289
  function getCharForByte(byte) {
225
290
  return String.fromCharCode(specialCea608CharsCodes[byte] || byte);
226
291
  }
227
-
228
292
  //#endregion
229
293
  //#region src/Row.ts
230
294
  /**
295
+ *
296
+ * This code was ported from the dash.js project at:
297
+ * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
298
+ * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
299
+ *
300
+ * The original copyright appears below:
301
+ *
302
+ * The copyright in this software is being made available under the BSD License,
303
+ * included below. This software may be subject to other third party and contributor
304
+ * rights, including patent rights, and no such rights are granted under this license.
305
+ *
306
+ * Copyright (c) 2015-2016, DASH Industry Forum.
307
+ * All rights reserved.
308
+ *
309
+ * Redistribution and use in source and binary forms, with or without modification,
310
+ * are permitted provided that the following conditions are met:
311
+ * 1. Redistributions of source code must retain the above copyright notice, this
312
+ * list of conditions and the following disclaimer.
313
+ * * Redistributions in binary form must reproduce the above copyright notice,
314
+ * this list of conditions and the following disclaimer in the documentation and/or
315
+ * other materials provided with the distribution.
316
+ * 2. Neither the name of Dash Industry Forum nor the names of its
317
+ * contributors may be used to endorse or promote products derived from this software
318
+ * without specific prior written permission.
319
+ *
320
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
321
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
322
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
323
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
324
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
325
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
326
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
327
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
328
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
329
+ * POSSIBILITY OF SUCH DAMAGE.
330
+ */
331
+ /**
231
332
  * CTA-608 row consisting of NR_COLS instances of StyledUnicodeChar.
232
333
  *
233
334
  * @public
@@ -238,19 +339,19 @@ var Row = class {
238
339
  this.cueStartTime = null;
239
340
  this.pos = 0;
240
341
  this.currPenState = new PenState();
241
- for (let i = 0; i < NR_COLS; i++) this.chars.push(new StyledUnicodeChar());
342
+ for (let i = 0; i < 100; i++) this.chars.push(new StyledUnicodeChar());
242
343
  this.logger = logger;
243
344
  }
244
345
  equals(other) {
245
- for (let i = 0; i < NR_COLS; i++) if (!this.chars[i].equals(other.chars[i])) return false;
346
+ for (let i = 0; i < 100; i++) if (!this.chars[i].equals(other.chars[i])) return false;
246
347
  return true;
247
348
  }
248
349
  copy(other) {
249
- for (let i = 0; i < NR_COLS; i++) this.chars[i].copy(other.chars[i]);
350
+ for (let i = 0; i < 100; i++) this.chars[i].copy(other.chars[i]);
250
351
  }
251
352
  isEmpty() {
252
353
  let empty = true;
253
- for (let i = 0; i < NR_COLS; i++) if (!this.chars[i].isEmpty()) {
354
+ for (let i = 0; i < 100; i++) if (!this.chars[i].isEmpty()) {
254
355
  empty = false;
255
356
  break;
256
357
  }
@@ -264,9 +365,9 @@ var Row = class {
264
365
  if (this.pos < 0) {
265
366
  this.logger.log(VerboseLevel.DEBUG, "Negative cursor position " + this.pos);
266
367
  this.pos = 0;
267
- } else if (this.pos > NR_COLS) {
368
+ } else if (this.pos > 100) {
268
369
  this.logger.log(VerboseLevel.DEBUG, "Too large cursor position " + this.pos);
269
- this.pos = NR_COLS;
370
+ this.pos = 100;
270
371
  }
271
372
  }
272
373
  /**
@@ -287,7 +388,7 @@ var Row = class {
287
388
  insertChar(byte) {
288
389
  if (byte >= 144) this.backSpace();
289
390
  const char = getCharForByte(byte);
290
- if (this.pos >= NR_COLS) {
391
+ if (this.pos >= 100) {
291
392
  this.logger.log(VerboseLevel.ERROR, () => "Cannot insert " + byte.toString(16) + " (" + char + ") at position " + this.pos + ". Skipping it!");
292
393
  return;
293
394
  }
@@ -296,7 +397,7 @@ var Row = class {
296
397
  }
297
398
  clearFromPos(startPos) {
298
399
  let i;
299
- for (i = startPos; i < NR_COLS; i++) this.chars[i].reset();
400
+ for (i = startPos; i < 100; i++) this.chars[i].reset();
300
401
  }
301
402
  clear() {
302
403
  this.clearFromPos(0);
@@ -309,7 +410,7 @@ var Row = class {
309
410
  getTextString() {
310
411
  const chars = [];
311
412
  let empty = true;
312
- for (let i = 0; i < NR_COLS; i++) {
413
+ for (let i = 0; i < 100; i++) {
313
414
  const char = this.chars[i].uchar;
314
415
  if (char !== " ") empty = false;
315
416
  chars.push(char);
@@ -322,14 +423,46 @@ var Row = class {
322
423
  this.chars[this.pos].setPenState(this.currPenState);
323
424
  }
324
425
  };
325
-
326
- //#endregion
327
- //#region src/utils/NR_ROWS.ts
328
- const NR_ROWS = 15;
329
-
330
426
  //#endregion
331
427
  //#region src/CaptionScreen.ts
332
428
  /**
429
+ *
430
+ * This code was ported from the dash.js project at:
431
+ * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
432
+ * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
433
+ *
434
+ * The original copyright appears below:
435
+ *
436
+ * The copyright in this software is being made available under the BSD License,
437
+ * included below. This software may be subject to other third party and contributor
438
+ * rights, including patent rights, and no such rights are granted under this license.
439
+ *
440
+ * Copyright (c) 2015-2016, DASH Industry Forum.
441
+ * All rights reserved.
442
+ *
443
+ * Redistribution and use in source and binary forms, with or without modification,
444
+ * are permitted provided that the following conditions are met:
445
+ * 1. Redistributions of source code must retain the above copyright notice, this
446
+ * list of conditions and the following disclaimer.
447
+ * * Redistributions in binary form must reproduce the above copyright notice,
448
+ * this list of conditions and the following disclaimer in the documentation and/or
449
+ * other materials provided with the distribution.
450
+ * 2. Neither the name of Dash Industry Forum nor the names of its
451
+ * contributors may be used to endorse or promote products derived from this software
452
+ * without specific prior written permission.
453
+ *
454
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
455
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
456
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
457
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
458
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
459
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
460
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
461
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
462
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
463
+ * POSSIBILITY OF SUCH DAMAGE.
464
+ */
465
+ /**
333
466
  * Keep a CTA-608 screen of 32x15 styled characters
334
467
  *
335
468
  * @public
@@ -337,30 +470,30 @@ const NR_ROWS = 15;
337
470
  var CaptionScreen = class {
338
471
  constructor(logger = new CaptionsLogger()) {
339
472
  this.rows = [];
340
- this.currRow = NR_ROWS - 1;
473
+ this.currRow = 14;
341
474
  this.nrRollUpRows = null;
342
475
  this.lastOutputScreen = null;
343
- for (let i = 0; i < NR_ROWS; i++) this.rows.push(new Row(logger));
476
+ for (let i = 0; i < 15; i++) this.rows.push(new Row(logger));
344
477
  this.logger = logger;
345
478
  }
346
479
  reset() {
347
- for (let i = 0; i < NR_ROWS; i++) this.rows[i].clear();
348
- this.currRow = NR_ROWS - 1;
480
+ for (let i = 0; i < 15; i++) this.rows[i].clear();
481
+ this.currRow = 14;
349
482
  }
350
483
  equals(other) {
351
484
  let equal = true;
352
- for (let i = 0; i < NR_ROWS; i++) if (!this.rows[i].equals(other.rows[i])) {
485
+ for (let i = 0; i < 15; i++) if (!this.rows[i].equals(other.rows[i])) {
353
486
  equal = false;
354
487
  break;
355
488
  }
356
489
  return equal;
357
490
  }
358
491
  copy(other) {
359
- for (let i = 0; i < NR_ROWS; i++) this.rows[i].copy(other.rows[i]);
492
+ for (let i = 0; i < 15; i++) this.rows[i].copy(other.rows[i]);
360
493
  }
361
494
  isEmpty() {
362
495
  let empty = true;
363
- for (let i = 0; i < NR_ROWS; i++) if (!this.rows[i].isEmpty()) {
496
+ for (let i = 0; i < 15; i++) if (!this.rows[i].isEmpty()) {
364
497
  empty = false;
365
498
  break;
366
499
  }
@@ -393,7 +526,7 @@ var CaptionScreen = class {
393
526
  let newRow = pacData.row - 1;
394
527
  if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) newRow = this.nrRollUpRows - 1;
395
528
  if (this.nrRollUpRows && this.currRow !== newRow) {
396
- for (let i = 0; i < NR_ROWS; i++) this.rows[i].clear();
529
+ for (let i = 0; i < 15; i++) this.rows[i].clear();
397
530
  const topRowIndex = this.currRow + 1 - this.nrRollUpRows;
398
531
  const lastOutputScreen = this.lastOutputScreen;
399
532
  if (lastOutputScreen) {
@@ -451,7 +584,7 @@ var CaptionScreen = class {
451
584
  const displayText = [];
452
585
  let text = "";
453
586
  let rowNr = -1;
454
- for (let i = 0; i < NR_ROWS; i++) {
587
+ for (let i = 0; i < 15; i++) {
455
588
  const rowText = this.rows[i].getTextString();
456
589
  if (rowText) {
457
590
  rowNr = i + 1;
@@ -459,15 +592,16 @@ var CaptionScreen = class {
459
592
  else displayText.push(rowText.trim());
460
593
  }
461
594
  }
462
- if (displayText.length > 0) if (asOneRow) text = "[" + displayText.join(" | ") + "]";
463
- else text = displayText.join("\n");
595
+ if (displayText.length > 0) {
596
+ if (asOneRow) text = "[" + displayText.join(" | ") + "]";
597
+ else text = displayText.join("\n");
598
+ }
464
599
  return text;
465
600
  }
466
601
  getTextAndFormat() {
467
602
  return this.rows;
468
603
  }
469
604
  };
470
-
471
605
  //#endregion
472
606
  //#region src/Cta608Channel.ts
473
607
  /**
@@ -483,7 +617,7 @@ var Cta608Channel = class {
483
617
  this.displayedMemory = new CaptionScreen(logger);
484
618
  this.nonDisplayedMemory = new CaptionScreen(logger);
485
619
  this.lastOutputScreen = new CaptionScreen(logger);
486
- this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
620
+ this.currRollUpRow = this.displayedMemory.rows[14];
487
621
  this.writeScreen = this.displayedMemory;
488
622
  this.mode = null;
489
623
  this.cueStartTime = null;
@@ -496,7 +630,7 @@ var Cta608Channel = class {
496
630
  this.nonDisplayedMemory.reset();
497
631
  this.lastOutputScreen.reset();
498
632
  this.outputFilter?.reset?.();
499
- this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];
633
+ this.currRollUpRow = this.displayedMemory.rows[14];
500
634
  this.writeScreen = this.displayedMemory;
501
635
  this.mode = null;
502
636
  this.cueStartTime = null;
@@ -645,7 +779,6 @@ var Cta608Channel = class {
645
779
  }
646
780
  }
647
781
  };
648
-
649
782
  //#endregion
650
783
  //#region src/utils/backgroundColors.ts
651
784
  const backgroundColors = [
@@ -659,7 +792,6 @@ const backgroundColors = [
659
792
  "black",
660
793
  "transparent"
661
794
  ];
662
-
663
795
  //#endregion
664
796
  //#region src/utils/createCmdHistory.ts
665
797
  function createCmdHistory() {
@@ -668,13 +800,11 @@ function createCmdHistory() {
668
800
  b: null
669
801
  };
670
802
  }
671
-
672
803
  //#endregion
673
804
  //#region src/utils/hasCmdRepeated.ts
674
805
  function hasCmdRepeated(a, b, cmdHistory) {
675
806
  return cmdHistory.a === a && cmdHistory.b === b;
676
807
  }
677
-
678
808
  //#endregion
679
809
  //#region src/utils/numArrayToHexArray.ts
680
810
  function numArrayToHexArray(numArray) {
@@ -682,7 +812,6 @@ function numArrayToHexArray(numArray) {
682
812
  for (const num of numArray) hexArray.push(num.toString(16));
683
813
  return hexArray;
684
814
  }
685
-
686
815
  //#endregion
687
816
  //#region src/utils/rowsHighCh1.ts
688
817
  const rowsHighCh1 = {
@@ -694,7 +823,6 @@ const rowsHighCh1 = {
694
823
  19: 13,
695
824
  20: 15
696
825
  };
697
-
698
826
  //#endregion
699
827
  //#region src/utils/rowsHighCh2.ts
700
828
  const rowsHighCh2 = {
@@ -706,7 +834,6 @@ const rowsHighCh2 = {
706
834
  27: 13,
707
835
  28: 15
708
836
  };
709
-
710
837
  //#endregion
711
838
  //#region src/utils/rowsLowCh1.ts
712
839
  const rowsLowCh1 = {
@@ -719,7 +846,6 @@ const rowsLowCh1 = {
719
846
  19: 12,
720
847
  20: 14
721
848
  };
722
-
723
849
  //#endregion
724
850
  //#region src/utils/rowsLowCh2.ts
725
851
  const rowsLowCh2 = {
@@ -732,17 +858,52 @@ const rowsLowCh2 = {
732
858
  27: 12,
733
859
  28: 14
734
860
  };
735
-
736
861
  //#endregion
737
862
  //#region src/utils/setLastCmd.ts
738
863
  function setLastCmd(a, b, cmdHistory) {
739
864
  cmdHistory.a = a;
740
865
  cmdHistory.b = b;
741
866
  }
742
-
743
867
  //#endregion
744
868
  //#region src/Cta608Parser.ts
745
869
  /**
870
+ *
871
+ * This code was ported from the dash.js project at:
872
+ * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
873
+ * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
874
+ *
875
+ * The original copyright appears below:
876
+ *
877
+ * The copyright in this software is being made available under the BSD License,
878
+ * included below. This software may be subject to other third party and contributor
879
+ * rights, including patent rights, and no such rights are granted under this license.
880
+ *
881
+ * Copyright (c) 2015-2016, DASH Industry Forum.
882
+ * All rights reserved.
883
+ *
884
+ * Redistribution and use in source and binary forms, with or without modification,
885
+ * are permitted provided that the following conditions are met:
886
+ * 1. Redistributions of source code must retain the above copyright notice, this
887
+ * list of conditions and the following disclaimer.
888
+ * * Redistributions in binary form must reproduce the above copyright notice,
889
+ * this list of conditions and the following disclaimer in the documentation and/or
890
+ * other materials provided with the distribution.
891
+ * 2. Neither the name of Dash Industry Forum nor the names of its
892
+ * contributors may be used to endorse or promote products derived from this software
893
+ * without specific prior written permission.
894
+ *
895
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
896
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
897
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
898
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
899
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
900
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
901
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
902
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
903
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
904
+ * POSSIBILITY OF SUCH DAMAGE.
905
+ */
906
+ /**
746
907
  * CEA-608 caption parser.
747
908
  *
748
909
  * @public
@@ -983,7 +1144,46 @@ var Cta608Parser = class {
983
1144
  for (const channel of this.channels) if (channel) channel.cueSplitAtTime(t);
984
1145
  }
985
1146
  };
986
-
1147
+ //#endregion
1148
+ //#region src/utils/parseCcData.ts
1149
+ function isCCType(type) {
1150
+ return type === 0 || type === 1;
1151
+ }
1152
+ function isNonEmptyCCData(ccData1, ccData2) {
1153
+ return (ccData1 & 127) > 0 || (ccData2 & 127) > 0;
1154
+ }
1155
+ /**
1156
+ * Parse an ATSC A/53 Part 4 `cc_data()` structure into per-field byte pairs.
1157
+ *
1158
+ * The payload is identical for every carriage format — an AVC/HEVC/VVC SEI message and
1159
+ * an AV1 `metadata_itu_t_t35` OBU carry the same bytes under the same T.35/GA94
1160
+ * identifier — so this is the single parser shared by all of them. Only the envelope
1161
+ * around it differs.
1162
+ *
1163
+ * `cc_data()` is self-delimiting: `cc_count` states how many 3-byte constructs follow,
1164
+ * so anything after them (SEI `rbsp_trailing_bits`, an AV1 OBU `trailing_bits` byte) is
1165
+ * ignored without needing to be recognized.
1166
+ *
1167
+ * @param raw - The DataView holding the `cc_data()` structure
1168
+ * @param pos - The position of the first `cc_data()` byte, holding `cc_count`
1169
+ * @param endPos - The exclusive upper bound to read within
1170
+ * @param fieldData - Field 1 and field 2 byte arrays, appended to in place
1171
+ */
1172
+ function parseCcData(raw, pos, endPos, fieldData) {
1173
+ if (pos + 2 > endPos) return;
1174
+ const ccCount = raw.getUint8(pos) & 31;
1175
+ let cursor = pos + 2;
1176
+ const ccEnd = Math.min(cursor + ccCount * 3, endPos);
1177
+ for (; cursor + 2 < ccEnd; cursor += 3) {
1178
+ const byte = raw.getUint8(cursor);
1179
+ if (!(byte & 4)) continue;
1180
+ const ccType = byte & 3;
1181
+ if (!isCCType(ccType)) continue;
1182
+ const ccData1 = raw.getUint8(cursor + 1);
1183
+ const ccData2 = raw.getUint8(cursor + 2);
1184
+ if (isNonEmptyCCData(ccData1, ccData2)) fieldData[ccType].push(ccData1, ccData2);
1185
+ }
1186
+ }
987
1187
  //#endregion
988
1188
  //#region src/extractCta608Data.ts
989
1189
  /**
@@ -996,33 +1196,163 @@ var Cta608Parser = class {
996
1196
  * @public
997
1197
  */
998
1198
  function extractCta608Data(raw, cta608Range) {
999
- let pos = cta608Range[0];
1000
1199
  const fieldData = [[], []];
1001
- pos += 8;
1002
- const ccCount = raw.getUint8(pos) & 31;
1003
- pos += 2;
1004
- for (let i = 0; i < ccCount; i++) {
1005
- const byte = raw.getUint8(pos);
1006
- const ccValid = byte & 4;
1007
- const ccType = byte & 3;
1008
- pos++;
1009
- const ccData1 = raw.getUint8(pos);
1010
- pos++;
1011
- const ccData2 = raw.getUint8(pos);
1012
- pos++;
1013
- if (ccValid && (ccData1 & 127) + (ccData2 & 127) !== 0) {
1014
- if (ccType === 0) {
1015
- fieldData[0].push(ccData1);
1016
- fieldData[0].push(ccData2);
1017
- } else if (ccType === 1) {
1018
- fieldData[1].push(ccData1);
1019
- fieldData[1].push(ccData2);
1020
- }
1021
- }
1200
+ parseCcData(raw, cta608Range[0] + 8, cta608Range[0] + cta608Range[1], fieldData);
1201
+ return fieldData;
1202
+ }
1203
+ //#endregion
1204
+ //#region src/utils/isCta608UserData.ts
1205
+ /**
1206
+ * The 8-byte ATSC A/53 user identifier that prefixes a `cc_data()` payload, per
1207
+ * ANSI-SCTE 128: `itu_t_t35_country_code` (0xB5, USA), `terminal_provider_code`
1208
+ * (0x0031, ATSC), `terminal_provider_oriented_code` ('GA94'), and
1209
+ * `user_data_type_code` (0x03, cc_data).
1210
+ *
1211
+ * Both carriage formats use it unchanged — an AVC/HEVC/VVC
1212
+ * `user_data_registered_itu_t_t35` SEI message and an AV1 `metadata_itu_t_t35` OBU — so
1213
+ * this identifies CTA-608 user data for either.
1214
+ *
1215
+ * @param raw - The DataView holding the T.35 payload
1216
+ * @param pos - The position of `itu_t_t35_country_code`
1217
+ * @returns true when the 8 bytes at `pos` identify CTA-608 caption data
1218
+ */
1219
+ function isCta608UserData(raw, pos) {
1220
+ return raw.getUint8(pos) === 181 && raw.getUint16(pos + 1) === 49 && raw.getUint32(pos + 3) === 1195456820 && raw.getUint8(pos + 7) === 3;
1221
+ }
1222
+ //#endregion
1223
+ //#region src/utils/obuHelpers.ts
1224
+ /**
1225
+ * AV1 `OBU_METADATA` unit type
1226
+ */
1227
+ const OBU_METADATA = 5;
1228
+ /**
1229
+ * AV1 `METADATA_TYPE_ITUT_T35` metadata type
1230
+ */
1231
+ const METADATA_TYPE_ITUT_T35 = 4;
1232
+ /**
1233
+ * The maximum number of bytes in an AV1 leb128() value
1234
+ */
1235
+ const LEB128_MAX_BYTES = 8;
1236
+ /**
1237
+ * Read an AV1 `leb128()` variable-length integer (AV1 spec section 4.10.5): up to 8
1238
+ * bytes, 7 value bits each, least significant group first, with the high bit marking
1239
+ * continuation.
1240
+ *
1241
+ * Groups are combined by multiplication rather than by `<<`, because a leb128 value may
1242
+ * exceed the 32 bits a JavaScript shift operates on.
1243
+ *
1244
+ * @param raw - The DataView to read from
1245
+ * @param pos - The position of the first leb128 byte
1246
+ * @param endPos - The exclusive upper bound to read within
1247
+ * @returns The value and its byte length, or null when it is truncated or overlong
1248
+ */
1249
+ function readLeb128(raw, pos, endPos) {
1250
+ let value = 0;
1251
+ for (let i = 0; i < LEB128_MAX_BYTES; i++) {
1252
+ if (pos + i >= endPos) return null;
1253
+ const byte = raw.getUint8(pos + i);
1254
+ value += (byte & 127) * 2 ** (i * 7);
1255
+ if (!(byte & 128)) return {
1256
+ value,
1257
+ size: i + 1
1258
+ };
1259
+ }
1260
+ return null;
1261
+ }
1262
+ /**
1263
+ * Detects whether an AV1 OBU header starts an `OBU_METADATA` unit and locates its
1264
+ * payload.
1265
+ *
1266
+ * The header is one byte — `obu_forbidden_bit` (1), `obu_type` (4),
1267
+ * `obu_extension_flag` (1), `obu_has_size_field` (1), `obu_reserved_1bit` (1) — followed
1268
+ * by an optional extension byte and, when `obu_has_size_field` is set, `obu_size` as a
1269
+ * leb128. An OBU without `obu_size` runs to the end of the temporal unit, which mp4
1270
+ * permits only for the final OBU in a sample.
1271
+ *
1272
+ * @param raw - The DataView containing the OBU
1273
+ * @param pos - The position of the OBU header byte
1274
+ * @param endPos - The exclusive end of the enclosing sample
1275
+ * @returns The payload bounds and whether this is a metadata OBU, or null if malformed
1276
+ */
1277
+ function readObu(raw, pos, endPos) {
1278
+ const header = raw.getUint8(pos);
1279
+ if (header & 128) return null;
1280
+ let payloadStart = pos + 1;
1281
+ if (header & 4) payloadStart++;
1282
+ let payloadEnd = endPos;
1283
+ if (header & 2) {
1284
+ const obuSize = readLeb128(raw, payloadStart, endPos);
1285
+ if (!obuSize) return null;
1286
+ payloadStart += obuSize.size;
1287
+ payloadEnd = payloadStart + obuSize.value;
1288
+ if (payloadEnd > endPos) return null;
1289
+ }
1290
+ return {
1291
+ isMetadata: (header >> 3 & 15) === OBU_METADATA,
1292
+ payloadStart,
1293
+ payloadEnd
1294
+ };
1295
+ }
1296
+ /**
1297
+ * Parse CTA-608 field data out of an AV1 metadata OBU payload, ignoring metadata OBUs
1298
+ * of any other type.
1299
+ *
1300
+ * The payload is `metadata_type` as a leb128, then — for ITU-T T.35 — the 8-byte A/53
1301
+ * user identifier and the `cc_data()` structure. Unlike an SEI NAL unit an OBU carries
1302
+ * no emulation prevention, so the bytes are read verbatim.
1303
+ *
1304
+ * @param raw - The DataView containing the OBU payload
1305
+ * @param pos - The position of `metadata_type`
1306
+ * @param endPos - The exclusive end of the OBU payload
1307
+ * @param fieldData - Field 1 and field 2 byte arrays, appended to in place
1308
+ */
1309
+ function parseCta608DataFromMetadataObu(raw, pos, endPos, fieldData) {
1310
+ const metadataType = readLeb128(raw, pos, endPos);
1311
+ if (!metadataType || metadataType.value !== METADATA_TYPE_ITUT_T35) return;
1312
+ const userDataStart = pos + metadataType.size;
1313
+ if (userDataStart + 10 > endPos || !isCta608UserData(raw, userDataStart)) return;
1314
+ parseCcData(raw, userDataStart + 8, endPos, fieldData);
1315
+ }
1316
+ //#endregion
1317
+ //#region src/extractCta608DataFromAv1Sample.ts
1318
+ /**
1319
+ * Extracts CTA-608 data from an AV1 (`av01`) sample.
1320
+ *
1321
+ * AV1 has no NAL units, so captions ride in an `metadata_itu_t_t35` OBU rather than in
1322
+ * an SEI message. The caption payload is unchanged — the same A/53 `cc_data()` under the
1323
+ * same T.35/GA94 identifier that {@link extractCta608DataFromSample} reads — so the
1324
+ * returned field data feeds {@link Cta608Parser} identically.
1325
+ *
1326
+ * This is a separate function rather than a codec branch inside
1327
+ * {@link extractCta608DataFromSample} because the two carriages are framed differently and
1328
+ * neither sample is self-identifying. A NAL unit sample puts a fixed-width big-endian
1329
+ * length in front of each unit, and that width is only known from `lengthSizeMinusOne` in
1330
+ * the `avcC`/`hvcC` config. An AV1 sample uses the low-overhead format, where each OBU
1331
+ * carries its own `obu_size` after the header — and may omit it on the last OBU. Select on
1332
+ * the sample entry type (`av01`) instead.
1333
+ *
1334
+ * @param raw - The DataView with media data
1335
+ * @param startPos - The start position of the sample within the DataView
1336
+ * @param sampleSize - The size of the sample in bytes
1337
+ * @returns fieldData array containing field 1 and field 2 data arrays
1338
+ *
1339
+ * @example
1340
+ * {@includeCode ../test/extractCta608DataFromAv1Sample.test.ts#example}
1341
+ *
1342
+ * @public
1343
+ */
1344
+ function extractCta608DataFromAv1Sample(raw, startPos, sampleSize) {
1345
+ const fieldData = [[], []];
1346
+ const endPos = Math.min(startPos + sampleSize, raw.byteLength);
1347
+ let cursor = startPos;
1348
+ while (cursor < endPos) {
1349
+ const obu = readObu(raw, cursor, endPos);
1350
+ if (!obu) break;
1351
+ if (obu.isMetadata) parseCta608DataFromMetadataObu(raw, obu.payloadStart, obu.payloadEnd, fieldData);
1352
+ cursor = Math.max(obu.payloadEnd, cursor + 1);
1022
1353
  }
1023
1354
  return fieldData;
1024
1355
  }
1025
-
1026
1356
  //#endregion
1027
1357
  //#region src/utils/seiHelpers.ts
1028
1358
  function getSeiData(raw, startPos, endPos) {
@@ -1036,17 +1366,7 @@ function getSeiData(raw, startPos, endPos) {
1036
1366
  }
1037
1367
  function isCea608Sei(payloadType, payloadSize, sei, pos) {
1038
1368
  if (payloadType !== 4 || payloadSize < 8) return false;
1039
- if (sei.getUint8(pos) !== 181) return false;
1040
- if (sei.getUint16(pos + 1) !== 49) return false;
1041
- if (sei.getUint32(pos + 3) !== 1195456820) return false;
1042
- if (sei.getUint8(pos + 7) !== 3) return false;
1043
- return true;
1044
- }
1045
- function isCCType(type) {
1046
- return type === 0 || type === 1;
1047
- }
1048
- function isNonEmptyCCData(ccData1, ccData2) {
1049
- return (ccData1 & 127) > 0 || (ccData2 & 127) > 0;
1369
+ return isCta608UserData(sei, pos);
1050
1370
  }
1051
1371
  /**
1052
1372
  * H.264 SEI NAL unit type
@@ -1113,25 +1433,10 @@ function parseCta608DataFromSei(sei, fieldData) {
1113
1433
  do
1114
1434
  payloadSize += now = sei.getUint8(cursor++);
1115
1435
  while (now === 255);
1116
- if (isCea608Sei(payloadType, payloadSize, sei, cursor)) {
1117
- const pos = cursor + 10;
1118
- const ccCount = pos + (sei.getUint8(pos - 2) & 31) * 3;
1119
- for (let i = pos; i < ccCount; i += 3) {
1120
- const byte = sei.getUint8(i);
1121
- if (byte & 4) {
1122
- const ccType = byte & 3;
1123
- if (isCCType(ccType)) {
1124
- const ccData1 = sei.getUint8(i + 1);
1125
- const ccData2 = sei.getUint8(i + 2);
1126
- if (isNonEmptyCCData(ccData1, ccData2)) fieldData[ccType].push(ccData1, ccData2);
1127
- }
1128
- }
1129
- }
1130
- }
1436
+ if (isCea608Sei(payloadType, payloadSize, sei, cursor)) parseCcData(sei, cursor + 8, cursor + payloadSize, fieldData);
1131
1437
  cursor += payloadSize;
1132
1438
  }
1133
1439
  }
1134
-
1135
1440
  //#endregion
1136
1441
  //#region src/extractCta608DataFromSample.ts
1137
1442
  /**
@@ -1160,7 +1465,6 @@ function extractCta608DataFromSample(raw, startPos, sampleSize) {
1160
1465
  }
1161
1466
  return fieldData;
1162
1467
  }
1163
-
1164
1468
  //#endregion
1165
1469
  //#region src/findCta608Nalus.ts
1166
1470
  /**
@@ -1176,12 +1480,12 @@ function extractCta608DataFromSample(raw, startPos, sampleSize) {
1176
1480
  function findCta608Nalus(raw, startPos, size) {
1177
1481
  let nalSize = 0, cursor = startPos;
1178
1482
  const cta608NaluRanges = [];
1179
- const isCTA608SEI = (payloadType, payloadSize, raw$1, pos) => {
1483
+ const isCTA608SEI = (payloadType, payloadSize, raw, pos) => {
1180
1484
  if (payloadType !== 4 || payloadSize < 8) return null;
1181
- const countryCode = raw$1.getUint8(pos);
1182
- const providerCode = raw$1.getUint16(pos + 1);
1183
- const userIdentifier = raw$1.getUint32(pos + 3);
1184
- const userDataTypeCode = raw$1.getUint8(pos + 7);
1485
+ const countryCode = raw.getUint8(pos);
1486
+ const providerCode = raw.getUint16(pos + 1);
1487
+ const userIdentifier = raw.getUint32(pos + 3);
1488
+ const userDataTypeCode = raw.getUint8(pos + 7);
1185
1489
  return countryCode == 181 && providerCode == 49 && userIdentifier == 1195456820 && userDataTypeCode == 3;
1186
1490
  };
1187
1491
  while (cursor < startPos + size) {
@@ -1213,7 +1517,6 @@ function findCta608Nalus(raw, startPos, size) {
1213
1517
  }
1214
1518
  return cta608NaluRanges;
1215
1519
  }
1216
-
1217
1520
  //#endregion
1218
1521
  //#region src/SccParser.ts
1219
1522
  /**
@@ -1307,7 +1610,7 @@ var SccParser = class {
1307
1610
  return this.nrLinesParsed;
1308
1611
  }
1309
1612
  };
1310
-
1311
1613
  //#endregion
1312
- export { CaptionScreen, CaptionsLogger, Cta608Channel, Cta608Parser, PenState, Row, SccParser, StyledUnicodeChar, VerboseLevel, extractCta608Data, extractCta608DataFromSample, findCta608Nalus };
1614
+ export { CaptionScreen, CaptionsLogger, Cta608Channel, Cta608Parser, PenState, Row, SccParser, StyledUnicodeChar, VerboseLevel, extractCta608Data, extractCta608DataFromAv1Sample, extractCta608DataFromSample, findCta608Nalus };
1615
+
1313
1616
  //# sourceMappingURL=index.js.map