1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
|
/*
Copyright (c) 2003-2021, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file AS_DCP.h
\version $Id$
\brief AS-DCP library, public interface
The asdcplib library is a set of file access objects that offer simplified
access to files conforming to the standards published by the SMPTE
D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP,
is described in a series of documents which includes but may not
be be limited to:
o SMPTE ST 429-2:2011 DCP Operational Constraints
o SMPTE ST 429-3:2006 Sound and Picture Track File
o SMPTE ST 429-4:2006 MXF JPEG 2000 Application
o SMPTE ST 429-5:2009 Timed Text Track File
o SMPTE ST 429-6:2006 MXF Track File Essence Encryption
o SMPTE ST 429-10:2008 Stereoscopic Picture Track File
o SMPTE ST 429-14:2008 Aux Data Track File
o SMPTE ST 330:2004 - UMID
o SMPTE ST 336:2001 - KLV
o SMPTE ST 377:2004 - MXF (old version, required)
o SMPTE ST 377-1:2011 - MXF
o SMPTE ST 377-4:2012 - MXF Multichannel Audio Labeling Framework
o SMPTE ST 390:2011 - MXF OP-Atom
o SMPTE ST 379-1:2009 - MXF Generic Container (GC)
o SMPTE ST 381-1:2005 - MPEG2 picture in GC
o SMPTE ST 422:2006 - JPEG 2000 picture in GC
o SMPTE ST 382:2007 - WAV/PCM sound in GC
o IETF RFC 2104 - HMAC/SHA1
o NIST FIPS 197 - AES (Rijndael) (via OpenSSL)
o MXF Interop Track File Specification
o MXF Interop Track File Essence Encryption Specification
o MXF Interop Operational Constraints Specification
- Note: the MXF Interop documents are not formally published.
Contact the asdcplib support address to get copies.
The following use cases are supported by the library:
o Write essence to a plaintext or ciphertext AS-DCP file:
o Read essence from a plaintext or ciphertext AS-DCP file:
MPEG2 Video Elementary Stream
JPEG 2000 codestreams
JPEG 2000 stereoscopic codestream pairs
PCM audio streams
SMPTE 429-7 Timed Text XML with font and image resources
Aux Data (frame-wrapped synchronous blob)
Proposed Dolby (TM) Atmos track file
o Read header metadata from an AS-DCP file
This project depends upon the following libraries:
- OpenSSL http://www.openssl.org/
- Expat http://expat.sourceforge.net/ or
Xerces-C http://xerces.apache.org/xerces-c/
An XML library is not needed if you don't need support for SMPTE ST 429-5:2009.
*/
#ifndef _AS_DCP_H_
#define _AS_DCP_H_
#include "KM_error.h"
#include "KM_fileio.h"
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <iosfwd>
#include <string>
#include <cstring>
#include <list>
//--------------------------------------------------------------------------------
// common integer types
// supply your own by defining ASDCP_NO_BASE_TYPES
#ifndef ASDCP_NO_BASE_TYPES
typedef unsigned char byte_t;
typedef char i8_t;
typedef unsigned char ui8_t;
typedef short i16_t;
typedef unsigned short ui16_t;
typedef int i32_t;
typedef unsigned int ui32_t;
#endif
//--------------------------------------------------------------------------------
// convenience macros
// Convenience macros for managing return values in predicates
#define ASDCP_SUCCESS(v) (((v) < 0) ? 0 : 1)
#define ASDCP_FAILURE(v) (((v) < 0) ? 1 : 0)
// Returns RESULT_PTR if the given argument is NULL.
// See Result_t below for an explanation of RESULT_* symbols.
#define ASDCP_TEST_NULL(p) \
if ( (p) == 0 ) { \
return ASDCP::RESULT_PTR; \
}
// Returns RESULT_PTR if the given argument is NULL. See Result_t
// below for an explanation of RESULT_* symbols. It then assumes
// that the argument is a pointer to a string and returns
// RESULT_NULL_STR if the first character is '\0'.
//
#define ASDCP_TEST_NULL_STR(p) \
ASDCP_TEST_NULL(p); \
if ( (p)[0] == '\0' ) { \
return ASDCP::RESULT_NULL_STR; \
}
// Produces copy constructor boilerplate. Allows convenient private
// declatarion of copy constructors to prevent the compiler from
// silently manufacturing default methods.
#define ASDCP_NO_COPY_CONSTRUCT(T) \
T(const T&); \
T& operator=(const T&)
//--------------------------------------------------------------------------------
// All library components are defined in the namespace ASDCP
//
namespace ASDCP {
//
// The version number declaration and explanation have moved to ../configure.ac
const char* Version();
// UUIDs are passed around as strings of UUIDlen bytes
const ui32_t UUIDlen = 16;
// Encryption keys are passed around as strings of KeyLen bytes
const ui32_t KeyLen = 16;
//---------------------------------------------------------------------------------
// return values
using Kumu::Result_t;
using Kumu::RESULT_FALSE;
using Kumu::RESULT_OK;
using Kumu::RESULT_FAIL;
using Kumu::RESULT_PTR;
using Kumu::RESULT_NULL_STR;
using Kumu::RESULT_ALLOC;
using Kumu::RESULT_PARAM;
using Kumu::RESULT_SMALLBUF;
using Kumu::RESULT_INIT;
using Kumu::RESULT_NOT_FOUND;
using Kumu::RESULT_NO_PERM;
using Kumu::RESULT_FILEOPEN;
using Kumu::RESULT_BADSEEK;
using Kumu::RESULT_READFAIL;
using Kumu::RESULT_WRITEFAIL;
using Kumu::RESULT_STATE;
using Kumu::RESULT_ENDOFFILE;
using Kumu::RESULT_CONFIG;
KM_DECLARE_RESULT(FORMAT, -101, "The file format is not proper OP-Atom/AS-DCP.");
KM_DECLARE_RESULT(RAW_ESS, -102, "Unknown raw essence file type.");
KM_DECLARE_RESULT(RAW_FORMAT, -103, "Raw essence format invalid.");
KM_DECLARE_RESULT(RANGE, -104, "Frame number out of range.");
KM_DECLARE_RESULT(CRYPT_CTX, -105, "AESEncContext required when writing to encrypted file.");
KM_DECLARE_RESULT(LARGE_PTO, -106, "Plaintext offset exceeds frame buffer size.");
KM_DECLARE_RESULT(CAPEXTMEM, -107, "Cannot resize externally allocated memory.");
KM_DECLARE_RESULT(CHECKFAIL, -108, "The check value did not decrypt correctly.");
KM_DECLARE_RESULT(HMACFAIL, -109, "HMAC authentication failure.");
KM_DECLARE_RESULT(HMAC_CTX, -110, "HMAC context required.");
KM_DECLARE_RESULT(CRYPT_INIT, -111, "Error initializing block cipher context.");
KM_DECLARE_RESULT(EMPTY_FB, -112, "Empty frame buffer.");
KM_DECLARE_RESULT(KLV_CODING, -113, "KLV coding error.");
KM_DECLARE_RESULT(SPHASE, -114, "Stereoscopic phase mismatch.");
KM_DECLARE_RESULT(SFORMAT, -115, "Rate mismatch, file may contain stereoscopic essence.");
//---------------------------------------------------------------------------------
// file identification
// The file accessors in this library implement a bounded set of essence types.
// This list will be expanded when support for new types is added to the library.
enum EssenceType_t {
ESS_UNKNOWN, // the file is not a supported AS-DCP or AS-02 essence container
//
ESS_MPEG2_VES, // the file contains an MPEG-2 video elementary stream
// d-cinema essence types (AS-DCP)
ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams
ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams
// IMF essence types (AS-02)
ESS_AS02_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
ESS_AS02_PCM_24b_48k, // the file contains one or more PCM audio pairs, clip wrapped
ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped
ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources
ESS_AS02_ISXD, // the file contains an ISXD document stream (per SMPTE RDD 47)
ESS_AS02_ACES, // the file contains two or more ACES codestreams (per SMPTE ST 2067-50)
ESS_AS02_IAB, // the file contains an IAB stream (per SMPTE ST 2067-201)
ESS_AS02_JPEG_XS, // the file contains one or more JPEG XS codestreams
// experimental
ESS_JPEG_XS, // the file contains one or more JPEG XS codestreams in an AS-DCP wrapping
ESS_MAX
};
// Determine the type of essence contained in the given MXF file. RESULT_OK
// is returned if the file is successfully opened and contains a valid MXF
// stream. If there is an error, the result code will indicate the reason.
Result_t EssenceType(const std::string& filename, EssenceType_t& type, const Kumu::IFileReaderFactory& fileReaderFactory);
// Determine the type of essence contained in the given raw file. RESULT_OK
// is returned if the file is successfully opened and contains a known
// stream type. If there is an error, the result code will indicate the reason.
Result_t RawEssenceType(const std::string& filename, EssenceType_t& type);
//---------------------------------------------------------------------------------
// base types
// A simple container for rational numbers.
class Rational
{
public:
i32_t Numerator;
i32_t Denominator;
Rational() : Numerator(0), Denominator(0) {}
Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
inline double Quotient() const {
return (double)Numerator / (double)Denominator;
}
inline bool operator==(const Rational& rhs) const {
return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
}
inline bool operator!=(const Rational& rhs) const {
return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
}
inline bool operator<(const Rational& rhs) {
if ( Numerator < rhs.Numerator ) return true;
if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator ) return true;
return false;
}
inline bool operator>(const Rational& rhs) {
if ( Numerator > rhs.Numerator ) return true;
if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator ) return true;
return false;
}
};
// Encodes a rational number as a string having a single delimiter character between
// numerator and denominator. Retuns the buffer pointer to allow convenient in-line use.
const char* EncodeRational(const Rational&, char* str_buf, ui32_t buf_len, char delimiter = ' ');
// Decodes a rational number havng a single non-digit delimiter character between
// the numerator and denominator. Returns false if the string does not contain
// the expected syntax.
bool DecodeRational(const char* str_rat, Rational&);
// common edit rates, use these instead of hard coded constants
const Rational EditRate_24 = Rational(24,1);
const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value!
const Rational EditRate_48 = Rational(48,1);
const Rational SampleRate_48k = Rational(48000,1);
const Rational SampleRate_96k = Rational(96000,1);
// Additional frame rates, see ST 428-11, ST 429-13
// These rates are new and not supported by all systems. Do not assume that
// a package made using one of these rates will work just anywhere!
const Rational EditRate_25 = Rational(25,1);
const Rational EditRate_30 = Rational(30,1);
const Rational EditRate_50 = Rational(50,1);
const Rational EditRate_60 = Rational(60,1);
const Rational EditRate_96 = Rational(96,1);
const Rational EditRate_100 = Rational(100,1);
const Rational EditRate_120 = Rational(120,1);
const Rational EditRate_192 = Rational(192,1);
const Rational EditRate_200 = Rational(200,1);
const Rational EditRate_240 = Rational(240,1);
// Archival frame rates, see ST 428-21
// These rates are new and not supported by all systems. Do not assume that
// a package made using one of these rates will work just anywhere!
const Rational EditRate_16 = Rational(16,1);
const Rational EditRate_18 = Rational(200,11); // 18.182
const Rational EditRate_20 = Rational(20,1);
const Rational EditRate_22 = Rational(240,11); // 21.818
// Non-reference counting container for internal member objects.
// Please do not use this class for any other purpose.
template <class T>
class mem_ptr
{
T* m_p; // the thing we point to
mem_ptr(T&);
public:
mem_ptr() : m_p(0) {}
mem_ptr(T* p) : m_p(p) {}
~mem_ptr() { delete m_p; }
inline T& operator*() const { return *m_p; }
inline T* operator->() const { return m_p; }
inline operator T*()const { return m_p; }
inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
inline T* get() const { return m_p; }
inline void release() { m_p = 0; }
inline bool empty() const { return m_p == 0; }
};
//---------------------------------------------------------------------------------
// WriterInfo class - encapsulates writer identification details used for
// OpenWrite() calls. Replace these values at runtime to identify your product.
//
// MXF files use SMPTE Universal Labels to identify data items. The set of Labels
// in a file is determined by the MXF Operational Pattern and any constraining
// documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
// (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
//
// OPAtom
// Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
// SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
//
// EKLV Packet:
// Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
// SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 00
//
// GenericDescriptor/SubDescriptors:
// Interop : 06 0e 2b 34 01 01 01 02 06 01 01 04 06 10 00 00
// SMPTE : 06 0e 2b 34 01 01 01 09 06 01 01 04 06 10 00 00
//
// asdcplib will read any (otherwise valid) file which has any combination of the
// above values. When writing files, MXF Interop labels are used by default. To
// write a file containing SMPTE labels, replace the default label set value in
// the WriterInfo before calling OpenWrite()
//
//
enum LabelSet_t
{
LS_MXF_UNKNOWN,
LS_MXF_INTEROP,
LS_MXF_SMPTE,
LS_MAX
};
//
struct WriterInfo
{
byte_t ProductUUID[UUIDlen];
byte_t AssetUUID[UUIDlen];
byte_t ContextID[UUIDlen];
byte_t CryptographicKeyID[UUIDlen];
bool EncryptedEssence; // true if essence data is (or is going to be) encrypted
bool UsesHMAC; // true if HMAC exists or is to be calculated
std::string ProductVersion;
std::string CompanyName;
std::string ProductName;
LabelSet_t LabelSetType;
WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
{
static byte_t default_ProductUUID_Data[UUIDlen] = {
0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
memset(AssetUUID, 0, UUIDlen);
memset(ContextID, 0, UUIDlen);
memset(CryptographicKeyID, 0, UUIDlen);
ProductVersion = "Unreleased ";
ProductVersion += Version();
CompanyName = "DCI";
ProductName = "asdcplib";
}
};
// Print WriterInfo to std::ostream
std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
// Print WriterInfo to stream, stderr by default.
void WriterInfoDump(const WriterInfo&, FILE* = 0);
//---------------------------------------------------------------------------------
// cryptographic support
// The following classes define interfaces to Rijndael contexts having the following properties:
// o 16 byte key
// o CBC mode with 16 byte block size
const ui32_t CBC_KEY_SIZE = 16;
const ui32_t CBC_BLOCK_SIZE = 16;
const ui32_t HMAC_SIZE = 20;
//
class AESEncContext
{
class h__AESContext;
mem_ptr<h__AESContext> m_Context;
ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
public:
AESEncContext();
~AESEncContext();
// Initializes Rijndael CBC encryption context.
// Returns error if the key argument is NULL.
Result_t InitKey(const byte_t* key);
// Initializes 16 byte CBC Initialization Vector. This operation may be performed
// any number of times for a given key.
// Returns error if the i_vec argument is NULL.
Result_t SetIVec(const byte_t* i_vec);
Result_t GetIVec(byte_t* i_vec) const;
// Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
// Returns error if either argument is NULL.
Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
};
//
class AESDecContext
{
class h__AESContext;
mem_ptr<h__AESContext> m_Context;
ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
public:
AESDecContext();
~AESDecContext();
// Initializes Rijndael CBC decryption context.
// Returns error if the key argument is NULL.
Result_t InitKey(const byte_t* key);
// Initializes 16 byte CBC Initialization Vector. This operation may be performed
// any number of times for a given key.
// Returns error if the i_vec argument is NULL.
Result_t SetIVec(const byte_t* i_vec);
// Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
// Returns error if either argument is NULL.
Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
};
//
class HMACContext
{
class h__HMACContext;
mem_ptr<h__HMACContext> m_Context;
ASDCP_NO_COPY_CONSTRUCT(HMACContext);
public:
HMACContext();
~HMACContext();
// Initializes HMAC context. The key argument must point to a binary
// key that is CBC_KEY_SIZE bytes in length. Returns error if the key
// argument is NULL.
Result_t InitKey(const byte_t* key, LabelSet_t);
// Reset internal state, allows repeated cycles of Update -> Finalize
void Reset();
// Add data to the digest. Returns error if the key argument is NULL or
// if the digest has been finalized.
Result_t Update(const byte_t* buf, ui32_t buf_len);
// Finalize digest. Returns error if the digest has already been finalized.
Result_t Finalize();
// Writes HMAC value to given buffer. buf must point to a writable area of
// memory that is at least HMAC_SIZE bytes in length. Returns error if the
// buf argument is NULL or if the digest has not been finalized.
Result_t GetHMACValue(byte_t* buf) const;
// Tests the given value against the finalized value in the object. buf must
// point to a readable area of memory that is at least HMAC_SIZE bytes in length.
// Returns error if the buf argument is NULL or if the values do ot match.
Result_t TestHMACValue(const byte_t* buf) const;
// Writes MIC key to given buffer. buf must point to a writable area of
// memory that is at least KeyLen bytes in length. Returns error if the
// buf argument is NULL.
Result_t GetMICKey(byte_t* buf) const;
};
//---------------------------------------------------------------------------------
// frame buffer base class
//
// The supported essence types are stored using per-frame KLV packetization. The
// following class implements essence-neutral functionality for managing a buffer
// containing a frame of essence.
class FrameBuffer
{
ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
protected:
byte_t* m_Data; // pointer to memory area containing frame data
ui32_t m_Capacity; // size of memory area pointed to by m_Data
bool m_OwnMem; // if false, m_Data points to externally allocated memory
ui32_t m_Size; // size of frame data in memory area pointed to by m_Data
ui32_t m_FrameNumber; // delivery-order frame number
// It is possible to read raw ciphertext from an encrypted AS-DCP file.
// After reading an encrypted AS-DCP file in raw mode, the frame buffer will
// contain the encrypted source value portion of the Encrypted Triplet, followed
// by the integrity pack, if it exists.
// The buffer will begin with the IV and CheckValue, followed by encrypted essence
// and optional integrity pack
// The SourceLength and PlaintextOffset values from the packet will be held in the
// following variables:
ui32_t m_SourceLength; // plaintext length (delivered plaintext+decrypted ciphertext)
ui32_t m_PlaintextOffset; // offset to first byte of ciphertext
public:
FrameBuffer();
virtual ~FrameBuffer();
// Instructs the object to use an externally allocated buffer. The external
// buffer will not be cleaned up by the frame buffer when it exits.
// Call with (0,0) to revert to internally allocated buffer.
// Returns error if the buf_addr argument is NULL and buf_size is non-zero.
Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
// Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
// if the object is using an externally allocated buffer via SetData();
// Resets content size to zero.
Result_t Capacity(ui32_t cap);
// returns the size of the buffer
inline ui32_t Capacity() const { return m_Capacity; }
// returns a const pointer to the essence data
inline const byte_t* RoData() const { return m_Data; }
// returns a non-const pointer to the essence data
inline byte_t* Data() { return m_Data; }
// set the size of the buffer's contents
inline ui32_t Size(ui32_t size) { return m_Size = size; }
// returns the size of the buffer's contents
inline ui32_t Size() const { return m_Size; }
// Sets the absolute frame number of this frame in the file in delivery order.
inline void FrameNumber(ui32_t num) { m_FrameNumber = num; }
// Returns the absolute frame number of this frame in the file in delivery order.
inline ui32_t FrameNumber() const { return m_FrameNumber; }
// Sets the length of the plaintext essence data
inline void SourceLength(ui32_t len) { m_SourceLength = len; }
// When this value is 0 (zero), the buffer contains only plaintext. When it is
// non-zero, the buffer contains raw ciphertext and the return value is the length
// of the original plaintext.
inline ui32_t SourceLength() const { return m_SourceLength; }
// Sets the offset into the buffer at which encrypted data begins
inline void PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
// Returns offset into buffer of first byte of ciphertext.
inline ui32_t PlaintextOffset() const { return m_PlaintextOffset; }
};
//---------------------------------------------------------------------------------
// Accessors in the MXFReader and MXFWriter classes below return these types to
// provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
namespace MXF {
// #include<Metadata.h> to use these
class OP1aHeader;
class OPAtomIndexFooter;
class RIP;
};
//---------------------------------------------------------------------------------
// MPEG2 video elementary stream support
//
namespace MPEG2
{
// MPEG picture coding type
enum FrameType_t {
FRAME_U = 0x00, // Unknown
FRAME_I = 0x01, // I-Frame
FRAME_P = 0x02, // P-Frame
FRAME_B = 0x03 // B-Frame
};
// convert FrameType_t to char
inline char FrameTypeChar(FrameType_t type)
{
switch ( type )
{
case FRAME_I: return 'I';
case FRAME_B: return 'B';
case FRAME_P: return 'P';
default: return 'U';
}
}
// Structure represents the metadata elements in the file header's
// MPEG2VideoDescriptor object.
struct VideoDescriptor
{
Rational EditRate; //
ui32_t FrameRate; //
Rational SampleRate; //
ui8_t FrameLayout; //
ui32_t StoredWidth; //
ui32_t StoredHeight; //
Rational AspectRatio; //
ui32_t ComponentDepth; //
ui32_t HorizontalSubsampling; //
ui32_t VerticalSubsampling; //
ui8_t ColorSiting; //
ui8_t CodedContentType; //
bool LowDelay; //
ui32_t BitRate; //
ui8_t ProfileAndLevel; //
ui32_t ContainerDuration; //
};
// Print VideoDescriptor to std::ostream
std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
// Print VideoDescriptor to stream, stderr by default.
void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
// A container for MPEG frame data.
class FrameBuffer : public ASDCP::FrameBuffer
{
ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
protected:
FrameType_t m_FrameType;
ui8_t m_TemporalOffset;
bool m_ClosedGOP;
bool m_GOPStart;
public:
FrameBuffer() :
m_FrameType(FRAME_U), m_TemporalOffset(0),
m_ClosedGOP(false), m_GOPStart(false) {}
FrameBuffer(ui32_t size) :
m_FrameType(FRAME_U), m_TemporalOffset(0),
m_ClosedGOP(false), m_GOPStart(false)
{
Capacity(size);
}
virtual ~FrameBuffer() {}
// Sets the MPEG frame type of the picture data in the frame buffer.
inline void FrameType(FrameType_t type) { m_FrameType = type; }
// Returns the MPEG frame type of the picture data in the frame buffer.
inline FrameType_t FrameType() const { return m_FrameType; }
// Sets the MPEG temporal offset of the picture data in the frame buffer.
inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
// Returns the MPEG temporal offset of the picture data in the frame buffer.
inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
// Sets the MPEG GOP 'start' attribute for the frame buffer.
inline void GOPStart(bool start) { m_GOPStart = start; }
// True if the frame in the buffer is the first in the GOP (in transport order)
inline bool GOPStart() const { return m_GOPStart; }
// Sets the MPEG GOP 'closed' attribute for the frame buffer.
inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
// Returns true if the frame in the buffer is from a closed GOP, false if
// the frame is from an open GOP. Always returns false unless GOPStart()
// returns true.
inline bool ClosedGOP() const { return m_ClosedGOP; }
// Print object state to stream, include n bytes of frame data if indicated.
// Default stream is stderr.
void Dump(FILE* = 0, ui32_t dump_len = 0) const;
};
// An object which opens and reads an MPEG2 Video Elementary Stream file. The call to
// OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
// Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
// given FrameBuffer object.
class Parser
{
class h__Parser;
mem_ptr<h__Parser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(Parser);
public:
Parser();
virtual ~Parser();
// Opens the stream for reading, parses enough data to provide a complete
// set of stream metadata for the MXFWriter below.
Result_t OpenRead(const std::string& filename) const;
Result_t OpenRead(unsigned char const* data, int size) const;
// Fill a VideoDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillVideoDescriptor(VideoDescriptor&) const;
// Rewind the stream to the beginning.
Result_t Reset() const;
// Reads the next sequential frame in the input file and places it in the
// frame buffer. Fails if the buffer is too small or the stream is empty.
// The frame buffer's PlaintextOffset parameter will be set to the first
// data byte of the first slice. Set this value to zero if you want
// encrypted headers.
Result_t ReadFrame(FrameBuffer&) const;
};
// A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
// Not yet implemented
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const VideoDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
Result_t FakeWriteFrame(int size, FrameType_t frame_type, bool gop_start, bool closed_gop, ui8_t temporal_offset);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
// Return the current file offset in the MXF file that we are writing.
ui64_t Tell() const;
};
// A class which reads MPEG frame data from an AS-DCP format MXF file.
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill a VideoDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillVideoDescriptor(VideoDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Calculates the first frame in transport order of the GOP in which the requested
// frame is located. Calls ReadFrame() to fetch the frame at the calculated position.
// Returns RESULT_INIT if the file is not open.
Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Calculates the first frame in transport order of the GOP in which the requested
// frame is located. Sets key_frame_number to the number of the frame at the calculated position.
// Returns RESULT_INIT if the file is not open.
Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
// Returns the type of the frame at the given position.
// Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace MPEG2
//---------------------------------------------------------------------------------
//
namespace PCM
{
// The default value of the ChannelFormat element of the AudioDescriptor struct
// is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
// values, the file's Wave Audio Descriptor will contain a Channel Assignment
// element.
//
// The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
// SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
// the 429-2 may also be used.
//
enum ChannelFormat_t {
CF_NONE,
CF_CFG_1, // 5.1 with optional HI/VI
CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
CF_CFG_3, // 7.1 (SDDS) with optional HI/VI
CF_CFG_4, // Wild Track Format
CF_CFG_5, // 7.1 DS with optional HI/VI
CF_CFG_6, // ST 377-4 (MCA) labels (see also ASDCP::MXF::decode_mca_string)
CF_MAXIMUM
};
struct AudioDescriptor
{
Rational EditRate; // rate of frame wrapping
Rational AudioSamplingRate; // rate of audio sample
ui32_t Locked; //
ui32_t ChannelCount; // number of channels
ui32_t QuantizationBits; // number of bits per single-channel sample
ui32_t BlockAlign; // number of bytes ber sample, all channels
ui32_t AvgBps; //
ui32_t LinkedTrackID; //
ui32_t ContainerDuration; // number of frames
ChannelFormat_t ChannelFormat; // audio channel arrangement
};
// Print AudioDescriptor to std::ostream
std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
// Print debugging information to stream (stderr default)
void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
// Returns size in bytes of a single sample of data described by ADesc
inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
{
return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
}
// Returns number of samples per frame of data described by ADesc
inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
{
double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
return (ui32_t)ceil(tmpd);
}
// Returns the size in bytes of a frame of data described by ADesc
inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
{
return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
}
//
class FrameBuffer : public ASDCP::FrameBuffer
{
public:
FrameBuffer() {}
FrameBuffer(ui32_t size) { Capacity(size); }
virtual ~FrameBuffer() {}
// Print debugging information to stream (stderr default)
void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
};
// An object which opens and reads a WAV file. The call to OpenRead() reads metadata from
// the file and populates an internal AudioDescriptor object. Each subsequent call to
// ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
// A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
class WAVParser
{
class h__WAVParser;
mem_ptr<h__WAVParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(WAVParser);
public:
WAVParser();
virtual ~WAVParser();
// Opens the stream for reading, parses enough data to provide a complete
// set of stream metadata for the MXFWriter below. PictureRate controls
// ther frame rate for the MXF frame wrapping option.
Result_t OpenRead(const std::string& filename, const Rational& PictureRate) const;
// Fill an AudioDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillAudioDescriptor(AudioDescriptor&) const;
// Rewind the stream to the beginning.
Result_t Reset() const;
// Reads the next sequential frame in the input file and places it in the
// frame buffer. Fails if the buffer is too small or the stream is empty.
Result_t ReadFrame(FrameBuffer&) const;
Result_t Seek(ui32_t frame_number) const;
};
//
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const AudioDescriptor&, ui32_t HeaderSize = 16384);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
};
//
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill an AudioDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillAudioDescriptor(AudioDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace PCM
//---------------------------------------------------------------------------------
//
namespace JP2K
{
const ui32_t MaxComponents = 3;
const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
const ui32_t MaxDefaults = 256; // made up
const ui8_t MaxCapabilities = 32;
const ui16_t MaxPRFN = 4;
const ui16_t MaxCPFN = 4;
const i8_t NoExtendedCapabilitiesSignaled = -1;
const ui16_t NoPRFSignaled = 0;
const ui16_t NoCPFSignaled = 0;
#pragma pack(1)
struct ImageComponent_t // ISO 15444-1 Annex A.5.1
{
ui8_t Ssize;
ui8_t XRsize;
ui8_t YRsize;
};
struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
{
ui8_t Scod;
struct
{
ui8_t ProgressionOrder;
ui8_t NumberOfLayers[sizeof(ui16_t)];
ui8_t MultiCompTransform;
} SGcod;
struct
{
ui8_t DecompositionLevels;
ui8_t CodeblockWidth;
ui8_t CodeblockHeight;
ui8_t CodeblockStyle;
ui8_t Transformation;
ui8_t PrecinctSize[MaxPrecincts];
} SPcod;
};
struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
{
ui8_t Sqcd;
ui8_t SPqcd[MaxDefaults];
ui8_t SPqcdLength;
};
struct ExtendedCapabilities_t // ISO 15444-1 Annex A.5.2
{
ui32_t Pcap; // Pcap = 0 means that no extended capabilities are required
i8_t N; // Number of Ccap elements, or NoExtendedCapabilitiesSignaled if no Extended Capabilities are signaled
ui16_t Ccap[MaxCapabilities];
};
struct Profile_t // ISO 15444-1
{
ui16_t N; // N = NoPRFSignaled means that Profile is signaled through Rsiz exclusively
ui16_t Pprf[MaxPRFN]; // Pprf^i in ISO/IEC 15444-1 corresponds to Pprf[i -1]
};
struct CorrespondingProfile_t // ISO 15444-1
{
ui16_t N; // N = NoCPFSignaled means that no corresponding profile is signaled
ui16_t Pcpf[MaxCPFN]; // Pcpf^i in ISO/IEC 15444-1 corresponds to Pcpf[i -1]
};
#pragma pack()
struct PictureDescriptor
{
Rational EditRate;
ui32_t ContainerDuration;
Rational SampleRate;
ui32_t StoredWidth;
ui32_t StoredHeight;
Rational AspectRatio;
ui16_t Rsize;
ui32_t Xsize;
ui32_t Ysize;
ui32_t XOsize;
ui32_t YOsize;
ui32_t XTsize;
ui32_t YTsize;
ui32_t XTOsize;
ui32_t YTOsize;
ui16_t Csize;
ImageComponent_t ImageComponents[MaxComponents];
CodingStyleDefault_t CodingStyleDefault;
QuantizationDefault_t QuantizationDefault;
ExtendedCapabilities_t ExtendedCapabilities;
Profile_t Profile;
CorrespondingProfile_t CorrespondingProfile;
};
// Print debugging information to std::ostream
std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
// Print debugging information to stream (stderr default)
void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
//
class FrameBuffer : public ASDCP::FrameBuffer
{
public:
FrameBuffer() {}
FrameBuffer(ui32_t size) { Capacity(size); }
virtual ~FrameBuffer() {}
// Print debugging information to stream (stderr default)
void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
};
// An object which opens and reads a JPEG 2000 codestream file. The file is expected
// to contain exactly one complete frame of picture essence as an unwrapped (raw)
// ISO/IEC 15444 codestream.
class CodestreamParser
{
class h__CodestreamParser;
mem_ptr<h__CodestreamParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
public:
CodestreamParser();
virtual ~CodestreamParser();
// Opens a file for reading, parses enough data to provide a complete
// set of stream metadata for the MXFWriter below.
// The frame buffer's PlaintextOffset parameter will be set to the first
// byte of the data segment. Set this value to zero if you want
// encrypted headers.
Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
Result_t OpenReadFrame(const unsigned char * data, unsigned int size, FrameBuffer&) const;
// Fill a PictureDescriptor struct with the values from the file's codestream.
// Returns RESULT_INIT if the file is not open.
Result_t FillPictureDescriptor(PictureDescriptor&) const;
};
// Parses the data in the frame buffer to fill in the picture descriptor. Copies
// the offset of the image data into start_of_data. Returns error if the parser fails.
Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
// An object which reads a sequence of files containing JPEG 2000 pictures.
class SequenceParser
{
class h__SequenceParser;
mem_ptr<h__SequenceParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
public:
SequenceParser();
virtual ~SequenceParser();
// Opens a directory for reading. The directory is expected to contain one or
// more files, each containing the codestream for exactly one picture. The
// files must be named such that the frames are in temporal order when sorted
// alphabetically by filename. The parser will automatically parse enough data
// from the first file to provide a complete set of stream metadata for the
// MXFWriter below. If the "pedantic" parameter is given and is true, the
// parser will check the metadata for each codestream and fail if a
// mismatch is detected.
Result_t OpenRead(const std::string& filename, bool pedantic = false) const;
// Opens a file sequence for reading. The sequence is expected to contain one or
// more filenames, each naming a file containing the codestream for exactly one
// picture. The parser will automatically parse enough data
// from the first file to provide a complete set of stream metadata for the
// MXFWriter below. If the "pedantic" parameter is given and is true, the
// parser will check the metadata for each codestream and fail if a
// mismatch is detected.
Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
// Fill a PictureDescriptor struct with the values from the first file's codestream.
// Returns RESULT_INIT if the directory is not open.
Result_t FillPictureDescriptor(PictureDescriptor&) const;
// Rewind the directory to the beginning.
Result_t Reset() const;
// Reads the next sequential frame in the directory and places it in the
// frame buffer. Fails if the buffer is too small or the direcdtory
// contains no more files.
// The frame buffer's PlaintextOffset parameter will be set to the first
// byte of the data segment. Set this value to zero if you want
// encrypted headers.
Result_t ReadFrame(FrameBuffer&) const;
};
//
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist unless overwrite is true. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const PictureDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// A MD5 hash of the data that we write is written to hash if it is not 0
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
Result_t FakeWriteFrame(int size);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
// Return the current file offset in the MXF file that we are writing.
ui64_t Tell() const;
};
//
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill an AudioDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillPictureDescriptor(PictureDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
// Stereoscopic Image support
//
enum StereoscopicPhase_t
{
SP_LEFT,
SP_RIGHT
};
struct SFrameBuffer
{
JP2K::FrameBuffer Left;
JP2K::FrameBuffer Right;
SFrameBuffer(ui32_t size) {
Left.Capacity(size);
Right.Capacity(size);
}
};
class MXFSWriter
{
class h__SWriter;
mem_ptr<h__SWriter> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
public:
MXFSWriter();
virtual ~MXFSWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist unless overwrite is true. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const PictureDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false);
// Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs. Frames must be written in the proper phase (L-R-L-R),
// RESULT_SPHASE will be returned if phase is reversed. The first frame
// written must be left eye.
Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase);
// Closes the MXF file, writing the index and revised header. Returns
// RESULT_SPHASE if WriteFrame was called an odd number of times.
Result_t Finalize();
// Return the current file offset in the MXF file that we are writing
ui64_t Tell() const;
};
//
class MXFSReader
{
class h__SReader;
mem_ptr<h__SReader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
public:
MXFSReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFSReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill an AudioDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillPictureDescriptor(PictureDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace JP2K
//---------------------------------------------------------------------------------
//
namespace TimedText
{
enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
struct TimedTextResourceDescriptor
{
byte_t ResourceID[UUIDlen];
MIMEType_t Type;
TimedTextResourceDescriptor() : Type(MT_BIN) { memset(ResourceID, 0, UUIDlen); }
};
typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
struct TimedTextDescriptor
{
Rational EditRate; //
ui32_t ContainerDuration;
byte_t AssetID[UUIDlen];
std::string NamespaceName;
std::string EncodingName;
ResourceList_t ResourceList;
std::string RFC5646LanguageTagList;
TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") { memset(AssetID, 0, UUIDlen); } // D-Cinema format is always UTF-8
};
// Print debugging information to std::ostream
std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
// Print debugging information to stream (stderr default)
void DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
//
class FrameBuffer : public ASDCP::FrameBuffer
{
ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
protected:
byte_t m_AssetID[UUIDlen];
std::string m_MIMEType;
public:
FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
virtual ~FrameBuffer() {}
inline const byte_t* AssetID() const { return m_AssetID; }
inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
inline const char* MIMEType() const { return m_MIMEType.c_str(); }
inline void MIMEType(const std::string& s) { m_MIMEType = s; }
// Print debugging information to stream (stderr default)
void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
};
// An abstract base for a lookup service that returns the resource data
// identified by the given ancillary resource id.
//
class IResourceResolver
{
public:
virtual ~IResourceResolver() {}
virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
};
// Resolves resource references by testing the named directory for file names containing
// the respective UUID.
//
class LocalFilenameResolver : public ASDCP::TimedText::IResourceResolver
{
std::string m_Dirname;
ASDCP_NO_COPY_CONSTRUCT(LocalFilenameResolver);
public:
LocalFilenameResolver();
virtual ~LocalFilenameResolver();
Result_t OpenRead(const std::string& dirname);
Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const;
};
//
class DCSubtitleParser
{
class h__SubtitleParser;
mem_ptr<h__SubtitleParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
public:
DCSubtitleParser();
virtual ~DCSubtitleParser();
// Opens an XML file for reading, parses data to provide a complete
// set of stream metadata for the MXFWriter below.
Result_t OpenRead(const std::string& filename) const;
// Parses an XML document to provide a complete set of stream metadata
// for the MXFWriter below. The optional filename argument is used to
// initialize the default resource resolver (see ReadAncillaryResource).
Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
// Fill a TimedTextDescriptor struct with the values from the file's contents.
// Returns RESULT_INIT if the file is not open.
Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
// Reads the complete Timed Text Resource into the given string.
Result_t ReadTimedTextResource(std::string&) const;
// Reads the Ancillary Resource having the given ID. Fails if the buffer
// is too small or the resource does not exist. The optional Resolver
// argument can be provided which will be used to retrieve the resource
// having a particulat UUID. If a Resolver is not supplied, the default
// internal resolver will return the contents of the file having the UUID
// as the filename. The filename must exist in the same directory as the
// XML file opened with OpenRead().
Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
const IResourceResolver* Resolver = 0) const;
};
//
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
// Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
// encoded. If the optional AESEncContext argument is present, the essence
// is encrypted prior to writing. Fails if the file is not open, is finalized,
// or an operating system error occurs.
// This method may only be called once, and it must be called before any
// call to WriteAncillaryResource(). RESULT_STATE will be returned if these
// conditions are not met.
Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
// Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs. RESULT_STATE will be returned if the method is called before
// WriteTimedTextResource()
Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
};
//
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill a TimedTextDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads the complete Timed Text Resource into the given string. Fails if the resource
// is encrypted and AESDecContext is NULL (use the following method to retrieve the
// raw ciphertet block).
Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
// Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
// argument is present, the resource is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Reads the timed-text resource having the given UUID from the MXF file. If the
// optional AESEncContext argument is present, the resource is decrypted after
// reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
// the frame buffer will contain the ciphertext frame data. If the HMACContext
// argument is not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace TimedText
//---------------------------------------------------------------------------------
//
namespace DCData
{
struct DCDataDescriptor
{
Rational EditRate; // Sample rate
ui32_t ContainerDuration; // number of frames
byte_t AssetID[UUIDlen]; // The UUID for the DCData track
byte_t DataEssenceCoding[UUIDlen]; // The coding for the data carried
};
// Print DCDataDescriptor to std::ostream
std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc);
// Print debugging information to stream (stderr default)
void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0);
//
class FrameBuffer : public ASDCP::FrameBuffer
{
public:
FrameBuffer() {}
FrameBuffer(ui32_t size) { Capacity(size); }
virtual ~FrameBuffer() {}
// Print debugging information to stream (stderr default)
void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
};
// An object which opens and reads a DC Data file. The file is expected
// to contain exactly one complete frame of DC data essence as an unwrapped (raw)
// byte stream.
class BytestreamParser
{
class h__BytestreamParser;
mem_ptr<h__BytestreamParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(BytestreamParser);
public:
BytestreamParser();
virtual ~BytestreamParser();
// Opens a file for reading, parses enough data to provide a complete
// set of stream metadata for the MXFWriter below.
// The frame buffer's PlaintextOffset parameter will be set to the first
// byte of the data segment. Set this value to zero if you want
// encrypted headers.
Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
// Fill a DCDataDescriptor struct with the values from the file's bytestream.
// Returns RESULT_INIT if the file is not open.
Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
};
// An object which reads a sequence of files containing DC Data.
class SequenceParser
{
class h__SequenceParser;
mem_ptr<h__SequenceParser> m_Parser;
ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
public:
SequenceParser();
virtual ~SequenceParser();
// Opens a directory for reading. The directory is expected to contain one or
// more files, each containing the bytestream for exactly one frame. The files
// must be named such that the frames are in temporal order when sorted
// alphabetically by filename.
Result_t OpenRead(const std::string& filename) const;
// Opens a file sequence for reading. The sequence is expected to contain one or
// more filenames, each naming a file containing the bytestream for exactly one
// frame.
Result_t OpenRead(const std::list<std::string>& file_list) const;
// Fill a DCDataDescriptor struct with default values.
// Returns RESULT_INIT if the directory is not open.
Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
// Rewind the directory to the beginning.
Result_t Reset() const;
// Reads the next sequential frame in the directory and places it in the
// frame buffer. Fails if the buffer is too small or the direcdtory
// contains no more files.
// The frame buffer's PlaintextOffset parameter will be set to the first
// byte of the data segment. Set this value to zero if you want
// encrypted headers.
Result_t ReadFrame(FrameBuffer&) const;
};
//
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const DCDataDescriptor&, ui32_t HeaderSize = 16384);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
};
//
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill a DCDataDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace DCData
//---------------------------------------------------------------------------------
//
namespace ATMOS
{
struct AtmosDescriptor : public DCData::DCDataDescriptor
{
ui32_t FirstFrame; // Frame number of the frame to align with the FFOA of the picture track
ui16_t MaxChannelCount; // Max number of channels in bitstream
ui16_t MaxObjectCount; // Max number of objects in bitstream
byte_t AtmosID[UUIDlen]; // UUID of Atmos Project
ui8_t AtmosVersion; // ATMOS Coder Version used to create bitstream
};
// Print AtmosDescriptor to std::ostream
std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc);
// Print debugging information to stream (stderr default)
void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0);
// Determine if a file is a raw atmos file
bool IsDolbyAtmos(const std::string& filename);
//
class MXFWriter
{
class h__Writer;
mem_ptr<h__Writer> m_Writer;
ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
public:
MXFWriter();
virtual ~MXFWriter();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed or if nonsensical data is discovered
// in the essence descriptor.
Result_t OpenWrite(const std::string& filename, const WriterInfo&,
const AtmosDescriptor&, ui32_t HeaderSize = 16384);
// Writes a frame of essence to the MXF file. If the optional AESEncContext
// argument is present, the essence is encrypted prior to writing.
// Fails if the file is not open, is finalized, or an operating system
// error occurs.
Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
// Closes the MXF file, writing the index and revised header.
Result_t Finalize();
};
//
class MXFReader
{
class h__Reader;
mem_ptr<h__Reader> m_Reader;
ASDCP_NO_COPY_CONSTRUCT(MXFReader);
public:
MXFReader(const Kumu::IFileReaderFactory& fileReaderFactory);
virtual ~MXFReader();
// Warning: direct manipulation of MXF structures can interfere
// with the normal operation of the wrapper. Caveat emptor!
virtual MXF::OP1aHeader& OP1aHeader();
virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
virtual MXF::RIP& RIP();
// Open the file for reading. The file must exist. Returns error if the
// operation cannot be completed.
Result_t OpenRead(const std::string& filename) const;
// Returns RESULT_INIT if the file is not open.
Result_t Close() const;
// Fill an AtmosDescriptor struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillAtmosDescriptor(AtmosDescriptor&) const;
// Fill a WriterInfo struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
Result_t FillWriterInfo(WriterInfo&) const;
// Reads a frame of essence from the MXF file. If the optional AESEncContext
// argument is present, the essence is decrypted after reading. If the MXF
// file is encrypted and the AESDecContext argument is NULL, the frame buffer
// will contain the ciphertext frame data. If the HMACContext argument is
// not NULL, the HMAC will be calculated (if the file supports it).
// Returns RESULT_INIT if the file is not open, failure if the frame number is
// out of range, or if optional decrypt or HAMC operations fail.
Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
// Using the index table read from the footer partition, lookup the frame number
// and return the offset into the file at which to read that frame of essence.
// Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
// out of range.
Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
// Print debugging information to stream
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
} // namespace ATMOS
} // namespace ASDCP
#endif // _AS_DCP_H_
//
// end AS_DCP.h
//
|