diff --git a/example/wv_cas_ecm_example b/example/wv_cas_ecm_example index b1fbff7..d2bd918 100644 Binary files a/example/wv_cas_ecm_example and b/example/wv_cas_ecm_example differ diff --git a/example/wv_cas_ecm_example.cc b/example/wv_cas_ecm_example.cc index d59a4d9..ae97860 100644 --- a/example/wv_cas_ecm_example.cc +++ b/example/wv_cas_ecm_example.cc @@ -13,17 +13,15 @@ #include #include -#include "gflags/gflags.h" #include "media_cas_packager_sdk/public/wv_cas_ecm.h" #include "media_cas_packager_sdk/public/wv_cas_types.h" -DEFINE_int32(content_iv_size, 8, "Content IV size"); -DEFINE_bool(key_rotation, true, "Whether key rotation is enabled"); -DEFINE_string(crypto_mode, "CSA2", "Only CBC, CTR, or CSA2 is allowed"); -DEFINE_int32(ecm_pid, 149, "PID for the ECM packet"); -DEFINE_string(output_file, "", - "If specified, generated ECM TS packet will be written to the " - "specified output file path"); +const size_t kContentIvSize = 8; +const bool kKeyRotation = false; // whether key rotation is enabled +const char kCryptoMode[] = "CTR"; // CBC, CTR, or CSA2 +const int kEcmPid = 149; // PID for the ECM packet +const char kOutputFile[] = + "/tmp/ecm.ts"; // ECM TS packet will be output to here const char kCsaEvenKey[] = "even_key"; // 8 bytes const char kEvenContentIv8Bytes[] = "even_iv."; // 8 bytes @@ -35,31 +33,31 @@ const char kOddContentIv8Bytes[] = "odd_iv.."; // 8 bytes const char kOddEntitlementKeyId[] = "fake_key_id2...."; // 16 bytes const char kOddEntitlementKey[] = "fakefakefakefakefakefakefake2..."; // 32 bytes +const uint8_t kTableId = 0x80; const size_t kTsPacketSize = 188; -widevine::cas::CryptoMode GetCryptoMode() { - if (FLAGS_crypto_mode.compare("CBC") == 0) { +widevine::cas::CryptoMode GetCryptoMode(const std::string& crypto_mode) { + if (crypto_mode.compare("CBC") == 0) { return widevine::cas::CryptoMode::kAesCbc; } - if (FLAGS_crypto_mode.compare("CTR") == 0) { + if (crypto_mode.compare("CTR") == 0) { return widevine::cas::CryptoMode::kAesCtr; } return widevine::cas::CryptoMode::kDvbCsa2; } -int main(int argc, char **argv) { - gflags::ParseCommandLineFlags(&argc, &argv, true); +int main(int argc, char** argv) { // Generate ECM. widevine::cas::WvCasEcm wv_cas_ecm; widevine::cas::WvCasStatus status = wv_cas_ecm.Initialize( - FLAGS_content_iv_size, FLAGS_key_rotation, GetCryptoMode()); + kContentIvSize, kKeyRotation, GetCryptoMode(kCryptoMode)); if (status != widevine::cas::OK) { std::cerr << "Failed to initialize WV CAS ECM, error: " << widevine::cas::GetWvCasStatusMessage(status) << std::endl; } std::string ecm; - if (FLAGS_key_rotation) { + if (kKeyRotation) { status = wv_cas_ecm.GenerateEcm( kCsaEvenKey, kEvenContentIv8Bytes, kEvenEntitlementKeyId, kEvenEntitlementKey, kCsaOddKey, kOddContentIv8Bytes, @@ -85,8 +83,7 @@ int main(int argc, char **argv) { // Generate ECM TS Packet. uint8_t packet[kTsPacketSize]; uint8_t continuity_counter; // not used. - status = wv_cas_ecm.GenerateTsPacket(ecm, FLAGS_ecm_pid, - /* table_id= */ 0x80, + status = wv_cas_ecm.GenerateTsPacket(ecm, kEcmPid, kTableId, &continuity_counter, packet); if (status != widevine::cas::OK) { std::cerr << "Failed to create ECM TS packet" << std::endl; @@ -99,13 +96,11 @@ int main(int argc, char **argv) { std::cout << std::endl; } // Write ECM TS Packet to a file. - if (!FLAGS_output_file.empty()) { std::ofstream file; - file.open(FLAGS_output_file.c_str(), std::ios_base::binary); + file.open(kOutputFile, std::ios_base::binary); assert(file.is_open()); file.write(reinterpret_cast(packet), kTsPacketSize); file.close(); - } return 0; } diff --git a/example/wv_cas_key_fetcher_example b/example/wv_cas_key_fetcher_example new file mode 100644 index 0000000..87ae8da Binary files /dev/null and b/example/wv_cas_key_fetcher_example differ diff --git a/example/wv_cas_key_fetcher_example.cc b/example/wv_cas_key_fetcher_example.cc new file mode 100644 index 0000000..40dc653 --- /dev/null +++ b/example/wv_cas_key_fetcher_example.cc @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright 2018 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. +//////////////////////////////////////////////////////////////////////////////// + + +#include +#include + +#include "gflags/gflags.h" +#include "glog/logging.h" +#include "common/status.h" +#include "media_cas_packager_sdk/public/wv_cas_key_fetcher.h" +#include "protos/public/media_cas_encryption.pb.h" + +DEFINE_string(content_id, "21140844", "Content ID"); +DEFINE_bool(key_rotation, true, "Whether key rotation is enabled"); +DEFINE_string(track_type, "SD", "Provider name"); + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + CHECK(!FLAGS_content_id.empty() && !FLAGS_track_type.empty()) + << "Flags 'content_id' and 'track_type' are required"; + // Required flags in key fetcher. + CHECK(!FLAGS_license_server.empty() && !FLAGS_signing_provider.empty() && + !FLAGS_signing_key.empty() && !FLAGS_signing_iv.empty()) + << "Flags 'license_server', 'signing_provider', 'signing_key' " + "and 'signing_iv' are required"; + + std::string request_str; + widevine::CasEncryptionRequest request; + request.set_provider(FLAGS_signing_provider); + request.set_content_id(FLAGS_content_id); + request.set_key_rotation(FLAGS_key_rotation); + // Only 1 track in this example. + request.add_track_types(FLAGS_track_type); + LOG(INFO) << "Request: " << request.ShortDebugString(); + if (!request.SerializeToString(&request_str)) { + LOG(ERROR) << "Failed to serialize request"; + return -1; + } + + std::string signed_response_str; + widevine::cas::WvCasKeyFetcher key_fetcher; + widevine::Status status = + key_fetcher.RequestEntitlementKey(request_str, &signed_response_str); + if (!status.ok()) { + LOG(ERROR) << "Failed to request entitlement key"; + return -1; + } + widevine::SignedCasEncryptionResponse signed_response; + if (!signed_response.ParseFromString(signed_response_str)) { + LOG(ERROR) << "Failed to deserialize signed response"; + return -1; + } + LOG(INFO) << "Signed response: " << signed_response.ShortDebugString(); + widevine::CasEncryptionResponse response; + if (!response.ParseFromString(signed_response.response())) { + LOG(ERROR) << "Failed to deserialize response"; + return -1; + } + LOG(INFO) << "Response: " << response.ShortDebugString(); + + return 0; +} diff --git a/example/wv_cas_types_example b/example/wv_cas_types_example index 880f7c5..4a4374e 100644 Binary files a/example/wv_cas_types_example and b/example/wv_cas_types_example differ diff --git a/example/wv_cas_types_example.cc b/example/wv_cas_types_example.cc index d116d76..c8fb4c1 100644 --- a/example/wv_cas_types_example.cc +++ b/example/wv_cas_types_example.cc @@ -10,13 +10,9 @@ #include -#include "gflags/gflags.h" #include "glog/logging.h" #include "media_cas_packager_sdk/public/wv_cas_types.h" -DEFINE_string(function_to_call, "CreateWvCasEncryptionRequestJson", - "Function in wv_cas_types to exercise"); - void CallCreateWvCasEncryptionRequestJson() { widevine::cas::WvCasEncryptionRequest request; request.content_id = "cont_id cont_id "; @@ -25,13 +21,10 @@ void CallCreateWvCasEncryptionRequestJson() { request.key_rotation = true; std::string request_json; widevine::cas::CreateWvCasEncryptionRequestJson(request, &request_json); - LOG(INFO) << FLAGS_function_to_call << " returns " << request_json; + LOG(INFO) << "CreateWvCasEncryptionRequestJson returns " << request_json; } int main(int argc, char **argv) { - gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_function_to_call.compare("CreateWvCasEncryptionRequestJson") == 0) { CallCreateWvCasEncryptionRequestJson(); - } return 0; }