Add EMMG to carry fingerprinting and service blocking info

This commit is contained in:
Lu Chen
2020-09-15 09:16:59 -07:00
parent 3d8f585313
commit 1ce468e5ba
143 changed files with 2316 additions and 17450 deletions

View File

@@ -67,3 +67,13 @@ cc_binary(
srcs = ["wv_cas_types_example.cc"],
deps = ["//media_cas_packager_sdk/public:wv_cas_types"],
)
cc_binary(
name = "wv_cas_emm_example",
srcs = ["wv_cas_emm_example.cc"],
deps = [
"//base",
"//common:status",
"//media_cas_packager_sdk/public:wv_cas_emm",
],
)

View File

@@ -52,7 +52,7 @@ const char kTestEmmgChannelSetup[] = {
'\x01' // parameter_value
};
const char kTestEmmgStreamSetup[] = {
const char kTestEmmgStreamSetupForPrivateData[] = {
'\x02', // protocol_version
'\x01', '\x11', // message_type - Stream_setup
'\x00', '\x1f', // message_length
@@ -73,6 +73,27 @@ const char kTestEmmgStreamSetup[] = {
'\x01' // parameter_value - private data
};
const char kTestEmmgStreamSetupForEmm[] = {
'\x02', // protocol_version
'\x01', '\x11', // message_type - Stream_setup
'\x00', '\x1f', // message_length
'\x00', '\x01', // parameter_type - client_id
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
'\x00', '\x03', // parameter_type - data_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x04', // parameter_type - data_stream_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x08', // parameter_type - data_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x07', // parameter_type - data_type
'\x00', '\x01', // parameter_length
'\x00' // parameter_value - emm
};
const char kTestEmmgStreamBwRequest[] = {
'\x02', // protocol_version
'\x01', '\x17', // message_type - Stream_BW_request
@@ -109,7 +130,7 @@ const char kTestEmmgStreamBwAllocation[] = {
'\x00', '\x32' // parameter_value (50 kbps)
};
const char kTestEmmgDataProvision[] = {
const char kTestEmmgPrivateDataProvision[] = {
'\x02', // protocol_version
'\x02', '\x11', // message_type - Data_provision
'\x00', '\xda', // message_length
@@ -149,10 +170,10 @@ const char kTestEmmgDataProvision[] = {
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
const char kTestEmptyEmmgDataProvision[] = {
const char kTestEmmgEmmDataProvision[] = {
'\x02', // protocol_version
'\x02', '\x11', // message_type - Data_provision
'\x00', '\x00', // message_length
'\x01', '\x96', // message_length
'\x00', '\x01', // parameter_type - client_id
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
@@ -165,9 +186,57 @@ const char kTestEmptyEmmgDataProvision[] = {
'\x00', '\x08', // parameter_type - data_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x00', // parameter_type - datagram
'\x00', '\x00', // parameter_length
};
'\x00', '\x05', // parameter_type - datagram
'\x01', '\x78', // parameter_length
// Start of the first TS packet (188 bytes).
'\x47', '\x40', '\x00', '\x10', // TS packet header (4 bytes).
'\x00', // Pointer field (1 byte).
'\x82', '\x70', '\xbe', // Secyion header (3 bytes).
// Start of Widevine EMM.
'\x01', '\x08', '\x00', '\x00', '\x00', '\x00', '\x5f', '\x3d', '\xc1',
'\xfb', '\x00', '\x6b', '\x0a', '\x14', '\x0a', '\x03', '\x43', '\x48',
'\x31', '\x0a', '\x03', '\x43', '\x48', '\x32', '\x12', '\x08', '\x63',
'\x6f', '\x6e', '\x74', '\x72', '\x6f', '\x6c', '\x73', '\x0a', '\x16',
'\x0a', '\x03', '\x43', '\x48', '\x33', '\x12', '\x0f', '\x61', '\x6e',
'\x6f', '\x74', '\x68', '\x65', '\x72', '\x20', '\x63', '\x6f', '\x6e',
'\x74', '\x72', '\x6f', '\x6c', '\x12', '\x18', '\x0a', '\x03', '\x43',
'\x48', '\x31', '\x0a', '\x03', '\x43', '\x48', '\x32', '\x12', '\x06',
'\x47', '\x72', '\x6f', '\x75', '\x70', '\x31', '\x20', '\xd2', '\x85',
'\xd8', '\xcc', '\x04', '\x12', '\x21', '\x0a', '\x03', '\x43', '\x48',
'\x33', '\x12', '\x06', '\x47', '\x72', '\x6f', '\x75', '\x70', '\x32',
'\x12', '\x06', '\x47', '\x72', '\x6f', '\x75', '\x70', '\x33', '\x18',
'\xd2', '\x85', '\xd8', '\xcc', '\x04', '\x20', '\xd3', '\x85', '\xd8',
'\xcc', '\x04', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
// Start of the second TS packet (188 bytes).
'\x47', '\x00', '\x00', '\x11', // TS packet header (4 bytes).
// Continued Widevine EMM.
'\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78', '\x78',
'\x78', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff'};
const char kTestEmmgStreamCloseRequest[] = {
'\x02', // protocol_version

View File

@@ -0,0 +1,133 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright 2020 Google LLC.
//
// This software is licensed under the terms defined in the Widevine Master
// License Agreement. For a copy of this agreement, please contact
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
// Example of how to use the wv_cas_emm library.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
#include "common/status.h"
#include "media_cas_packager_sdk/public/wv_cas_emm.h"
namespace {
using widevine::cas::WvCasEmm;
using widevine::cas::WvCasFingerprintingInitParameters;
using widevine::cas::WvCasServiceBlockingInitParameters;
// PID for the EMM packet.
static constexpr int kEmmPid = 1;
static constexpr size_t kTsPacketSize = 188;
static constexpr size_t kMaxPossibleTsPacketsCount = 6;
static constexpr size_t kMaxPossibleTsPacketsSizeBytes =
kMaxPossibleTsPacketsCount * kTsPacketSize;
static constexpr unsigned char kTestECPrivateKey2Secp256r1[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x34, 0x9a, 0xf2, 0x95,
0x94, 0xd4, 0xca, 0xb9, 0xa0, 0x81, 0xe4, 0x1c, 0xf5, 0xde, 0x8d,
0x23, 0xf6, 0x79, 0xba, 0x3c, 0x6e, 0xc9, 0x0b, 0x56, 0x0f, 0x07,
0x5e, 0x9f, 0xe9, 0x38, 0x18, 0xfc, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42,
0x00, 0x04, 0x7b, 0x2a, 0x61, 0x59, 0xe5, 0x1b, 0xb6, 0x30, 0x7b,
0x59, 0x98, 0x42, 0x59, 0x37, 0xfb, 0x46, 0xfe, 0x53, 0xfe, 0x32,
0xa1, 0x5c, 0x93, 0x36, 0x11, 0xb0, 0x5a, 0xae, 0xa4, 0x48, 0xe3,
0x20, 0x12, 0xce, 0x78, 0xa7, 0x7f, 0xfd, 0x73, 0x5e, 0x09, 0x77,
0x53, 0x77, 0x8f, 0xd6, 0x1b, 0x26, 0xfa, 0xc4, 0x2c, 0xc4, 0x11,
0xfa, 0x72, 0x6a, 0xbe, 0x94, 0x78, 0x4d, 0x74, 0x20, 0x27, 0x86};
std::vector<WvCasFingerprintingInitParameters> GetFingerprintingParams() {
WvCasFingerprintingInitParameters fingerprinting_1;
// Channels used in the fingerprinting and service blocking info. The channel
// definition is opaque to Widevine.
fingerprinting_1.channels = {"CH1", "CH2"};
// Fingerprinting control information. The format is opaque to Widevine.
fingerprinting_1.control = "controls";
WvCasFingerprintingInitParameters fingerprinting_2;
fingerprinting_2.channels = {"CH3"};
fingerprinting_2.control = "another control";
return {fingerprinting_1, fingerprinting_2};
}
std::vector<WvCasServiceBlockingInitParameters> GetServiceBlockingParams() {
WvCasServiceBlockingInitParameters service_blocking_1;
service_blocking_1.channels = {"CH1"};
// Device groups that should have service blocking. The group definition is
// opaque to Widevine.
service_blocking_1.device_groups = {"Group1", "Group2"};
// Service blocking start and end time, Epoch time in seconds.
service_blocking_1.start_time = 1598398260;
service_blocking_1.end_time = 1598398261;
WvCasServiceBlockingInitParameters service_blocking_2;
service_blocking_2.channels = {"CH2", "CH3"};
service_blocking_2.device_groups = {"Group3"};
service_blocking_2.start_time = 0; // start_time set to 0 means immediate.
service_blocking_2.end_time = 1598398261;
return {service_blocking_1, service_blocking_2};
}
} // namespace
int main(int argc, char** argv) {
widevine::Status status;
// Create EMM object with the ECC signing key.
std::string ecc_signing_key(std::begin(kTestECPrivateKey2Secp256r1),
std::end(kTestECPrivateKey2Secp256r1));
std::unique_ptr<WvCasEmm> emm = WvCasEmm::Create(ecc_signing_key);
if (emm == nullptr) {
std::cerr << "Failed to create WvCasEmm object";
return -1;
}
// Optionally set the fingerprinting info.
status = emm->SetFingerprinting(GetFingerprintingParams());
if (!status.ok()) {
std::cerr << "Failed to set fingerprinting info: " << status << std::endl;
return -2;
}
// Optionally set the service blocking info.
status = emm->SetServiceBlocking(GetServiceBlockingParams());
if (!status.ok()) {
std::cerr << "Failed to set service blocking info: " << status << std::endl;
return -3;
}
// Generate serialized EMM.
std::string serialized_emm;
status = emm->GenerateEmm(&serialized_emm);
if (!status.ok()) {
std::cerr << "Failed to generate serialized EMM: " << status << std::endl;
return -4;
}
std::cout << "Successfully generated EMM bytes: ";
for (size_t i = 0; i < serialized_emm.size(); i++) {
printf("'\\x%02x', ", static_cast<uint8_t>(serialized_emm[i]));
}
std::cout << std::endl;
// Generate EMM wrapped in TS packet.
// Notice that the signature of the EMM is expected to differ for each call.
uint8_t packet[kMaxPossibleTsPacketsSizeBytes];
ssize_t packet_size = kMaxPossibleTsPacketsSizeBytes;
uint8_t continuity_counter = 0;
status = emm->GenerateEmmTsPackets(kEmmPid, &continuity_counter, packet,
&packet_size);
if (!status.ok()) {
std::cerr << "Failed to generate EMM TS packet: " << status << std::endl;
return -5;
}
std::cout << "Successfully generated EMM TS packet bytes: ";
for (size_t i = 0; i < packet_size; i++) {
printf("'\\x%02x', ", packet[i]);
}
std::cout << std::endl;
return 0;
}