@volcengine/veplayer-plugin 2.8.0-rc.1 → 2.8.0
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/esm/index.development.js +76618 -35156
- package/esm/index.production.js +8 -7
- package/esm/veplayer.plugin.ad.development.js +1412 -1398
- package/esm/veplayer.plugin.ad.production.js +2 -2
- package/esm/veplayer.plugin.drm.development.js +147 -63
- package/esm/veplayer.plugin.drm.production.js +1 -1
- package/esm/veplayer.plugin.hlsjs.development.js +32501 -10992
- package/esm/veplayer.plugin.hlsjs.production.js +1 -1
- package/esm/veplayer.plugin.rtm.development.js +165 -70
- package/esm/veplayer.plugin.rtm.production.js +1 -1
- package/package.json +1 -1
- package/umd/veplayer.plugin.ad.development.js +1412 -1398
- package/umd/veplayer.plugin.ad.production.js +1 -1
- package/umd/veplayer.plugin.drm.development.js +148 -64
- package/umd/veplayer.plugin.drm.production.js +1 -1
- package/umd/veplayer.plugin.hlsjs.development.js +32478 -10969
- package/umd/veplayer.plugin.hlsjs.production.js +1 -1
- package/umd/veplayer.plugin.rtm.development.js +165 -70
- package/umd/veplayer.plugin.rtm.production.js +1 -1
|
@@ -1291,12 +1291,25 @@
|
|
|
1291
1291
|
KeySystem2["playready"] = "com.microsoft.playready";
|
|
1292
1292
|
return KeySystem2;
|
|
1293
1293
|
})(KeySystem || {});
|
|
1294
|
-
|
|
1294
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
1295
|
+
ErrorCode2[ErrorCode2["UNSUPPORTED"] = 7101] = "UNSUPPORTED";
|
|
1296
|
+
ErrorCode2[ErrorCode2["RECORD"] = 7102] = "RECORD";
|
|
1297
|
+
ErrorCode2[ErrorCode2["NOMEDIAKEY"] = 7103] = "NOMEDIAKEY";
|
|
1298
|
+
ErrorCode2[ErrorCode2["NOKEYSESSION"] = 7104] = "NOKEYSESSION";
|
|
1299
|
+
ErrorCode2[ErrorCode2["GENERATEREQUESTFAIL"] = 7105] = "GENERATEREQUESTFAIL";
|
|
1300
|
+
ErrorCode2[ErrorCode2["LACKSERVERCERTIFICATEPATH"] = 7106] = "LACKSERVERCERTIFICATEPATH";
|
|
1301
|
+
ErrorCode2[ErrorCode2["LACKSERVERPROCESSSPCPATH"] = 7107] = "LACKSERVERPROCESSSPCPATH";
|
|
1302
|
+
ErrorCode2[ErrorCode2["LICENSEFAIL"] = 7108] = "LICENSEFAIL";
|
|
1303
|
+
ErrorCode2[ErrorCode2["KEYERROR"] = 7109] = "KEYERROR";
|
|
1304
|
+
ErrorCode2[ErrorCode2["CERTFAIL"] = 7110] = "CERTFAIL";
|
|
1305
|
+
return ErrorCode2;
|
|
1306
|
+
})(ErrorCode || {});
|
|
1307
|
+
function selectKeySystem(contentType) {
|
|
1295
1308
|
const options = [
|
|
1296
1309
|
{
|
|
1297
1310
|
initDataTypes: ["keyids", "webm"],
|
|
1298
1311
|
audioCapabilities: [{ contentType: 'audio/mp4; codecs="mp4a.40.2"' }],
|
|
1299
|
-
videoCapabilities: [
|
|
1312
|
+
videoCapabilities: contentType ? [{ contentType }] : [
|
|
1300
1313
|
{ contentType: 'video/mp4; codecs="avc1.42c01e"' },
|
|
1301
1314
|
{ contentType: 'video/mp4; codecs="hev1.1.6.L120.90"' },
|
|
1302
1315
|
{ contentType: 'video/webm; codecs="vp8"' }
|
|
@@ -1307,7 +1320,8 @@
|
|
|
1307
1320
|
navigator.requestMediaKeySystemAccess(KeySystem.fairplay, options).then((access) => {
|
|
1308
1321
|
resolve({
|
|
1309
1322
|
access,
|
|
1310
|
-
system: KeySystem.fairplay
|
|
1323
|
+
system: KeySystem.fairplay,
|
|
1324
|
+
systemName: "fairplay"
|
|
1311
1325
|
});
|
|
1312
1326
|
}).catch(() => {
|
|
1313
1327
|
if (globalThis.WebKitMediaKeys && globalThis.WebKitMediaKeys.isTypeSupported(
|
|
@@ -1316,22 +1330,38 @@
|
|
|
1316
1330
|
)) {
|
|
1317
1331
|
resolve({
|
|
1318
1332
|
access: null,
|
|
1319
|
-
system: KeySystem.fairplay
|
|
1333
|
+
system: KeySystem.fairplay,
|
|
1334
|
+
systemName: "fairplay"
|
|
1320
1335
|
});
|
|
1321
1336
|
return;
|
|
1322
1337
|
}
|
|
1323
1338
|
navigator.requestMediaKeySystemAccess(KeySystem.widevine, options).then((access) => {
|
|
1324
1339
|
resolve({
|
|
1325
1340
|
access,
|
|
1326
|
-
system: KeySystem.widevine
|
|
1341
|
+
system: KeySystem.widevine,
|
|
1342
|
+
systemName: "widevine"
|
|
1327
1343
|
});
|
|
1328
1344
|
}).catch(() => {
|
|
1329
1345
|
navigator.requestMediaKeySystemAccess(KeySystem.playready, options).then((access) => {
|
|
1330
1346
|
resolve({
|
|
1331
1347
|
access,
|
|
1332
|
-
system: KeySystem.playready
|
|
1348
|
+
system: KeySystem.playready,
|
|
1349
|
+
systemName: "playready"
|
|
1333
1350
|
});
|
|
1334
|
-
}).catch(
|
|
1351
|
+
}).catch((e) => {
|
|
1352
|
+
if (globalThis.MSMediaKeys && globalThis.MSMediaKeys.isTypeSupported(
|
|
1353
|
+
KeySystem.playready,
|
|
1354
|
+
"video/mp4"
|
|
1355
|
+
)) {
|
|
1356
|
+
resolve({
|
|
1357
|
+
access: null,
|
|
1358
|
+
system: KeySystem.playready,
|
|
1359
|
+
systemName: "playready"
|
|
1360
|
+
});
|
|
1361
|
+
} else {
|
|
1362
|
+
reject(e);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1335
1365
|
});
|
|
1336
1366
|
});
|
|
1337
1367
|
});
|
|
@@ -1348,7 +1378,7 @@
|
|
|
1348
1378
|
}
|
|
1349
1379
|
return array;
|
|
1350
1380
|
}
|
|
1351
|
-
class
|
|
1381
|
+
class Drm extends BasePlugin {
|
|
1352
1382
|
constructor(options) {
|
|
1353
1383
|
super(options);
|
|
1354
1384
|
this.unsupported = false;
|
|
@@ -1363,17 +1393,15 @@
|
|
|
1363
1393
|
event.target;
|
|
1364
1394
|
let initData = event.initData;
|
|
1365
1395
|
const initDataType = event.initDataType;
|
|
1366
|
-
|
|
1367
|
-
if (this.keySystem === KeySystem.fairplay
|
|
1368
|
-
|
|
1369
|
-
this.afterInitDate(initData, contentId, initDataType);
|
|
1370
|
-
};
|
|
1396
|
+
let contentId;
|
|
1397
|
+
if (this.keySystem === KeySystem.fairplay) {
|
|
1398
|
+
contentId = this.extractContentId(initData);
|
|
1371
1399
|
}
|
|
1372
1400
|
this.afterInitDate(initData, contentId, initDataType);
|
|
1373
1401
|
};
|
|
1374
1402
|
this.licenseRequestReady = (event) => {
|
|
1375
1403
|
if (!this.serverProcessSPCPath) {
|
|
1376
|
-
this.emitError("lack serverProcessSPCPath");
|
|
1404
|
+
this.emitError(ErrorCode.LACKSERVERPROCESSSPCPATH, "lack serverProcessSPCPath");
|
|
1377
1405
|
return;
|
|
1378
1406
|
}
|
|
1379
1407
|
const message = event.message;
|
|
@@ -1383,10 +1411,12 @@
|
|
|
1383
1411
|
request.addEventListener("error", this.licenseRequestFailed(event), false);
|
|
1384
1412
|
var params = new Uint8Array(message);
|
|
1385
1413
|
request.open("POST", this.serverProcessSPCPath, true);
|
|
1386
|
-
if (this.
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1414
|
+
if (!this.config.ignoreLicenseHeader) {
|
|
1415
|
+
if (this.keySystem === KeySystem.playready) {
|
|
1416
|
+
request.setRequestHeader("Content-type", "text/xml; charset=utf-8");
|
|
1417
|
+
} else {
|
|
1418
|
+
request.setRequestHeader("Content-type", "application/octet-stream");
|
|
1419
|
+
}
|
|
1390
1420
|
}
|
|
1391
1421
|
request.send(params);
|
|
1392
1422
|
};
|
|
@@ -1394,16 +1424,13 @@
|
|
|
1394
1424
|
const request = event.target;
|
|
1395
1425
|
const arrayBuffer = request.response;
|
|
1396
1426
|
let license;
|
|
1397
|
-
|
|
1398
|
-
license = this.parseServerResponse(arrayBuffer);
|
|
1399
|
-
} else {
|
|
1400
|
-
license = new Uint8Array(arrayBuffer);
|
|
1401
|
-
}
|
|
1427
|
+
license = new Uint8Array(arrayBuffer);
|
|
1402
1428
|
if (license) {
|
|
1403
1429
|
this.keySession.update(license);
|
|
1404
1430
|
} else {
|
|
1405
1431
|
this.emitError(
|
|
1406
|
-
|
|
1432
|
+
ErrorCode.LICENSEFAIL,
|
|
1433
|
+
`The license response no array buffer, license: ${license}`
|
|
1407
1434
|
);
|
|
1408
1435
|
}
|
|
1409
1436
|
};
|
|
@@ -1414,16 +1441,17 @@
|
|
|
1414
1441
|
} else {
|
|
1415
1442
|
const request = event.target;
|
|
1416
1443
|
this.emitError(
|
|
1444
|
+
ErrorCode.LICENSEFAIL,
|
|
1417
1445
|
`The license request fail, status: ${request.status}, statusText: ${request.statusText}`
|
|
1418
1446
|
);
|
|
1419
1447
|
}
|
|
1420
1448
|
};
|
|
1421
1449
|
this.onKeyError = () => {
|
|
1422
|
-
this.emitError("A decryption key error was encountered");
|
|
1450
|
+
this.emitError(ErrorCode.KEYERROR, "A decryption key error was encountered");
|
|
1423
1451
|
};
|
|
1424
1452
|
this.loadCertificate = () => {
|
|
1425
1453
|
if (!this.serverCertificatePath) {
|
|
1426
|
-
this.emitError("lack serverCertificatePath");
|
|
1454
|
+
this.emitError(ErrorCode.LACKSERVERCERTIFICATEPATH, "lack serverCertificatePath");
|
|
1427
1455
|
return;
|
|
1428
1456
|
}
|
|
1429
1457
|
const request = new XMLHttpRequest();
|
|
@@ -1433,17 +1461,18 @@
|
|
|
1433
1461
|
request.open("GET", this.serverCertificatePath, true);
|
|
1434
1462
|
request.send();
|
|
1435
1463
|
};
|
|
1436
|
-
this.emitError = (message) => {
|
|
1464
|
+
this.emitError = (errorCode, message) => {
|
|
1437
1465
|
this.emit("error", {
|
|
1438
|
-
errorCode
|
|
1466
|
+
errorCode,
|
|
1439
1467
|
message,
|
|
1440
|
-
|
|
1468
|
+
// @ts-ignore: Cannot find name '"0.0.0-alpha.13"'
|
|
1469
|
+
drm_sdk_version: "0.0.0-alpha.13"
|
|
1441
1470
|
});
|
|
1442
1471
|
};
|
|
1443
1472
|
this.onCertificateLoaded = (event) => {
|
|
1444
1473
|
const request = event.target;
|
|
1445
1474
|
this.certificate = new Uint8Array(request.response);
|
|
1446
|
-
this.
|
|
1475
|
+
this.loadSource();
|
|
1447
1476
|
};
|
|
1448
1477
|
this.onCertificateError = (event) => {
|
|
1449
1478
|
if (this.certRetryTime > 0) {
|
|
@@ -1452,6 +1481,7 @@
|
|
|
1452
1481
|
} else {
|
|
1453
1482
|
const request = event.target;
|
|
1454
1483
|
this.emitError(
|
|
1484
|
+
ErrorCode.CERTFAIL,
|
|
1455
1485
|
`get cert fail, status: ${request.status}, statusText: ${request.statusText}`
|
|
1456
1486
|
);
|
|
1457
1487
|
}
|
|
@@ -1461,12 +1491,13 @@
|
|
|
1461
1491
|
};
|
|
1462
1492
|
this.reset();
|
|
1463
1493
|
const config = options.config || {};
|
|
1464
|
-
this.
|
|
1465
|
-
this.
|
|
1494
|
+
this.config = config;
|
|
1495
|
+
this.contentType = this.config.contentType;
|
|
1466
1496
|
if (typeof config.unRecord === "boolean") {
|
|
1467
1497
|
this.unRecord = config.unRecord;
|
|
1468
1498
|
}
|
|
1469
1499
|
this.checkUnrecord();
|
|
1500
|
+
this.player.handleSource = false;
|
|
1470
1501
|
}
|
|
1471
1502
|
static get pluginName() {
|
|
1472
1503
|
return "drm";
|
|
@@ -1477,8 +1508,6 @@
|
|
|
1477
1508
|
this._serverCertificatePath = x;
|
|
1478
1509
|
if (this.keySystem === KeySystem.fairplay) {
|
|
1479
1510
|
this.certificate = void 0;
|
|
1480
|
-
this.suspend = () => {
|
|
1481
|
-
};
|
|
1482
1511
|
this.loadCertificate();
|
|
1483
1512
|
}
|
|
1484
1513
|
}
|
|
@@ -1488,9 +1517,11 @@
|
|
|
1488
1517
|
afterCreate() {
|
|
1489
1518
|
this.media = this.player.video;
|
|
1490
1519
|
this.media.addEventListener("webkitneedkey", this.onNeedKey, false);
|
|
1520
|
+
this.media.addEventListener("msneedkey", this.onNeedKey, false);
|
|
1491
1521
|
this.media.addEventListener("needkey", this.onNeedKey, false);
|
|
1492
1522
|
this.media.addEventListener("encrypted", this.onNeedKey);
|
|
1493
1523
|
this.player.on("urlchange", this.restart);
|
|
1524
|
+
this.player.on("reset", this.restart);
|
|
1494
1525
|
}
|
|
1495
1526
|
async checkUnrecord() {
|
|
1496
1527
|
if (this.unRecord) {
|
|
@@ -1507,60 +1538,101 @@
|
|
|
1507
1538
|
});
|
|
1508
1539
|
this.unsupported = !powerEfficient;
|
|
1509
1540
|
} catch (error) {
|
|
1510
|
-
this.emitError(`check powerEfficient failed, ${error.message}`);
|
|
1541
|
+
this.emitError(ErrorCode.RECORD, `check powerEfficient failed, ${error.message}`);
|
|
1511
1542
|
this.unsupported = true;
|
|
1512
1543
|
}
|
|
1513
1544
|
}
|
|
1514
1545
|
if (this.unsupported)
|
|
1515
1546
|
return;
|
|
1516
|
-
selectKeySystem().then(({ access, system }) => {
|
|
1547
|
+
selectKeySystem(this.contentType).then(({ access, system, systemName }) => {
|
|
1517
1548
|
this.keySystem = system;
|
|
1549
|
+
this.systemName = systemName;
|
|
1550
|
+
this.setRequestUrl(systemName);
|
|
1518
1551
|
if (system === KeySystem.fairplay) {
|
|
1519
1552
|
this.loadCertificate();
|
|
1553
|
+
} else {
|
|
1554
|
+
this.loadSource();
|
|
1520
1555
|
}
|
|
1521
1556
|
if (access) {
|
|
1522
1557
|
this.keySystemAccess = access;
|
|
1523
1558
|
}
|
|
1524
1559
|
}).catch((error) => {
|
|
1525
|
-
this.emitError(error.message);
|
|
1560
|
+
this.emitError(ErrorCode.UNSUPPORTED, error.message);
|
|
1526
1561
|
this.unsupported = true;
|
|
1527
1562
|
});
|
|
1528
1563
|
}
|
|
1564
|
+
loadSource() {
|
|
1565
|
+
this.player.retry();
|
|
1566
|
+
}
|
|
1567
|
+
setRequestUrl(systemName) {
|
|
1568
|
+
const systemConfig = this.config[systemName] || this.config;
|
|
1569
|
+
this.serverCertificatePath = systemConfig.serverCertificatePath;
|
|
1570
|
+
this.serverProcessSPCPath = systemConfig.serverProcessSPCPath;
|
|
1571
|
+
}
|
|
1572
|
+
async updateConfig(config) {
|
|
1573
|
+
Object.assign(this.config, config);
|
|
1574
|
+
if (this.config.unRecord && this.contentType !== this.config.contentType) {
|
|
1575
|
+
this.contentType = this.config.contentType;
|
|
1576
|
+
await this.checkUnrecord();
|
|
1577
|
+
}
|
|
1578
|
+
this.setRequestUrl(this.systemName);
|
|
1579
|
+
}
|
|
1529
1580
|
afterInitDate(initData, contentId, initDataType) {
|
|
1530
1581
|
if (!this.keySystemAccess) {
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
this.
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1582
|
+
if (this.keySystem === KeySystem.fairplay) {
|
|
1583
|
+
const mediaKeys = new globalThis.WebKitMediaKeys(this.keySystem);
|
|
1584
|
+
this.media.webkitSetMediaKeys(mediaKeys);
|
|
1585
|
+
if (!this.media.webkitKeys) {
|
|
1586
|
+
this.emitError(ErrorCode.NOMEDIAKEY, "Could not create MediaKeys");
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
const keySession = mediaKeys.createSession(
|
|
1590
|
+
"video/mp4",
|
|
1591
|
+
this.concatInitDataIdAndCertificate(initData, contentId)
|
|
1592
|
+
);
|
|
1593
|
+
this.keySession = keySession;
|
|
1594
|
+
if (!keySession) {
|
|
1595
|
+
this.emitError(ErrorCode.NOKEYSESSION, "Could not create key session");
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
keySession.addEventListener(
|
|
1599
|
+
"webkitkeymessage",
|
|
1600
|
+
this.licenseRequestReady
|
|
1601
|
+
);
|
|
1602
|
+
keySession.addEventListener("webkitkeyerror", this.onKeyError);
|
|
1603
|
+
} else if (this.keySystem === KeySystem.playready) {
|
|
1604
|
+
const mediaKeys = new globalThis.MSMediaKeys(this.keySystem);
|
|
1605
|
+
this.media.msSetMediaKeys(mediaKeys);
|
|
1606
|
+
const keySession = mediaKeys.createSession(
|
|
1607
|
+
"video/mp4",
|
|
1608
|
+
new Uint8Array(initData),
|
|
1609
|
+
null
|
|
1610
|
+
);
|
|
1611
|
+
this.keySession = keySession;
|
|
1612
|
+
if (!keySession) {
|
|
1613
|
+
this.emitError(ErrorCode.NOKEYSESSION, "Could not create key session");
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
keySession.addEventListener("mskeymessage", this.licenseRequestReady);
|
|
1617
|
+
keySession.addEventListener("mskeyerror", this.onKeyError);
|
|
1545
1618
|
}
|
|
1546
|
-
keySession.addEventListener("webkitkeymessage", this.licenseRequestReady);
|
|
1547
|
-
keySession.addEventListener("webkitkeyerror", this.onKeyError);
|
|
1548
1619
|
} else {
|
|
1549
1620
|
this.keySystemAccess.createMediaKeys().then((mediaKeys) => {
|
|
1550
1621
|
this.media.setMediaKeys(mediaKeys);
|
|
1551
1622
|
if (this.media.mediaKeys) {
|
|
1552
|
-
this.emitError("Could not create MediaKeys");
|
|
1623
|
+
this.emitError(ErrorCode.NOMEDIAKEY, "Could not create MediaKeys");
|
|
1553
1624
|
return;
|
|
1554
1625
|
}
|
|
1555
1626
|
const keySession = mediaKeys.createSession();
|
|
1556
1627
|
this.keySession = keySession;
|
|
1557
1628
|
if (!keySession) {
|
|
1558
|
-
this.emitError("Could not create key session");
|
|
1629
|
+
this.emitError(ErrorCode.NOKEYSESSION, "Could not create key session");
|
|
1559
1630
|
return;
|
|
1560
1631
|
}
|
|
1561
1632
|
keySession.addEventListener("message", this.licenseRequestReady);
|
|
1562
|
-
keySession.generateRequest(initDataType, initData).catch((error) => {
|
|
1633
|
+
keySession.generateRequest(initDataType || this.config.initDataType, initData).catch((error) => {
|
|
1563
1634
|
this.emitError(
|
|
1635
|
+
ErrorCode.GENERATEREQUESTFAIL,
|
|
1564
1636
|
`generateRequest failed, code: ${error.errorCode}, message: ${error.message}`
|
|
1565
1637
|
);
|
|
1566
1638
|
});
|
|
@@ -1634,18 +1706,30 @@
|
|
|
1634
1706
|
this.suspend = void 0;
|
|
1635
1707
|
this.keySession = void 0;
|
|
1636
1708
|
this.needKeyed = false;
|
|
1709
|
+
if (this.media) {
|
|
1710
|
+
try {
|
|
1711
|
+
this.media.src = "";
|
|
1712
|
+
if (this.keySystem === KeySystem.fairplay) {
|
|
1713
|
+
this.media.webkitSetMediaKeys(null);
|
|
1714
|
+
} else if (this.keySystem === KeySystem.playready) {
|
|
1715
|
+
this.media.msSetMediaKeys(null);
|
|
1716
|
+
} else {
|
|
1717
|
+
this.media.setMediaKeys(null);
|
|
1718
|
+
}
|
|
1719
|
+
} catch (error) {
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1637
1722
|
}
|
|
1638
1723
|
destroy() {
|
|
1639
1724
|
this.player.off("urlchange", this.restart);
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
data.serverCertificatePath && (this.serverCertificatePath = data.serverCertificatePath);
|
|
1725
|
+
this.player.off("reset", this.restart);
|
|
1726
|
+
this.media.removeEventListener("webkitneedkey", this.onNeedKey, false);
|
|
1727
|
+
this.media.removeEventListener("msneedkey", this.onNeedKey, false);
|
|
1728
|
+
this.media.removeEventListener("needkey", this.onNeedKey, false);
|
|
1729
|
+
this.media.removeEventListener("encrypted", this.onNeedKey);
|
|
1646
1730
|
}
|
|
1647
1731
|
}
|
|
1648
1732
|
const DynamicModule = window["VePlayer"].DynamicModule;
|
|
1649
|
-
VePlayer.registerPlugin(DynamicModule.PluginDrm, { DrmPlugin });
|
|
1650
|
-
exports2.DrmPlugin =
|
|
1733
|
+
VePlayer.registerPlugin(DynamicModule.PluginDrm, { DrmPlugin: Drm });
|
|
1734
|
+
exports2.DrmPlugin = Drm;
|
|
1651
1735
|
});
|