Make edash-packager outputs predictable for testing
- Added --iv to inject iv for fixed key encryption. - Added support for key rotation in fixed key encryption. - Added --use_fake_clock_for_muxer to set timestamp to 0 in the output. Also updates stream info dump message: - Modified pixel_width: %d\n pixel_height: %d to pixel aspect ratio: %d:%d - Removed language from video stream info. These flags should only be used for testing. Change-Id: Iedf8d6d6492226219f49fe44d932645f557010e4
This commit is contained in:
parent
7ac31f2111
commit
8c202047fb
|
@ -18,6 +18,10 @@ DEFINE_bool(enable_fixed_key_decryption,
|
|||
"Enable decryption with fixed key.");
|
||||
DEFINE_string(key_id, "", "Key id in hex string format.");
|
||||
DEFINE_string(key, "", "Key in hex string format.");
|
||||
DEFINE_string(iv,
|
||||
"",
|
||||
"Iv in hex string format. If not specified, a random iv will be "
|
||||
"generated. This flag should only be used for testing.");
|
||||
DEFINE_string(pssh, "", "PSSH in hex string format.");
|
||||
|
||||
namespace edash_packager {
|
||||
|
@ -38,6 +42,10 @@ bool ValidateFixedCryptoFlags() {
|
|||
"key", FLAGS_key, fixed_crypto, false, fixed_crypto_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (!ValidateFlag("iv", FLAGS_iv, FLAGS_enable_fixed_key_encryption, true,
|
||||
"--enable_fixed_key_encryption")) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
// --pssh is associated with --enable_fix_key_encryption.
|
||||
if (!ValidateFlag("pssh",
|
||||
|
|
|
@ -15,6 +15,7 @@ DECLARE_bool(enable_fixed_key_encryption);
|
|||
DECLARE_bool(enable_fixed_key_decryption);
|
||||
DECLARE_string(key_id);
|
||||
DECLARE_string(key);
|
||||
DECLARE_string(iv);
|
||||
DECLARE_string(pssh);
|
||||
|
||||
namespace edash_packager {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "packager/app/fixed_key_encryption_flags.h"
|
||||
|
@ -18,6 +19,7 @@
|
|||
#include "packager/base/strings/string_split.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/base/threading/simple_thread.h"
|
||||
#include "packager/base/time/clock.h"
|
||||
#include "packager/media/base/demuxer.h"
|
||||
#include "packager/media/base/key_source.h"
|
||||
#include "packager/media/base/muxer_options.h"
|
||||
|
@ -29,6 +31,12 @@
|
|||
#include "packager/mpd/base/mpd_builder.h"
|
||||
#include "packager/mpd/base/simple_mpd_notifier.h"
|
||||
|
||||
DEFINE_bool(use_fake_clock_for_muxer,
|
||||
false,
|
||||
"Set to true to use a fake clock for muxer. With this flag set, "
|
||||
"creation time and modification time in outputs are set to 0. "
|
||||
"Should only be used for testing.");
|
||||
|
||||
namespace {
|
||||
const char kUsage[] =
|
||||
"Packager driver program. Sample Usage:\n"
|
||||
|
@ -66,6 +74,13 @@ enum ExitStatus {
|
|||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
// A fake clock that always return time 0 (epoch). Should only be used for
|
||||
// testing.
|
||||
class FakeClock : public base::Clock {
|
||||
public:
|
||||
virtual base::Time Now() OVERRIDE { return base::Time(); }
|
||||
};
|
||||
|
||||
// Demux, Mux(es) and worker thread used to remux a source file/stream.
|
||||
class RemuxJob : public base::SimpleThread {
|
||||
public:
|
||||
|
@ -99,6 +114,7 @@ class RemuxJob : public base::SimpleThread {
|
|||
|
||||
bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
||||
const MuxerOptions& muxer_options,
|
||||
FakeClock* fake_clock,
|
||||
KeySource* key_source,
|
||||
MpdNotifier* mpd_notifier,
|
||||
std::vector<RemuxJob*>* remux_jobs) {
|
||||
|
@ -149,6 +165,8 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
|||
DCHECK(!remux_jobs->empty());
|
||||
|
||||
scoped_ptr<Muxer> muxer(new mp4::MP4Muxer(stream_muxer_options));
|
||||
if (FLAGS_use_fake_clock_for_muxer) muxer->set_clock(fake_clock);
|
||||
|
||||
if (key_source) {
|
||||
muxer->SetKeySource(key_source,
|
||||
FLAGS_max_sd_pixels,
|
||||
|
@ -274,10 +292,9 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
|||
|
||||
std::vector<RemuxJob*> remux_jobs;
|
||||
STLElementDeleter<std::vector<RemuxJob*> > scoped_jobs_deleter(&remux_jobs);
|
||||
if (!CreateRemuxJobs(stream_descriptors,
|
||||
muxer_options,
|
||||
encryption_key_source.get(),
|
||||
mpd_notifier.get(),
|
||||
FakeClock fake_clock;
|
||||
if (!CreateRemuxJobs(stream_descriptors, muxer_options, &fake_clock,
|
||||
encryption_key_source.get(), mpd_notifier.get(),
|
||||
&remux_jobs)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ scoped_ptr<KeySource> CreateEncryptionKeySource() {
|
|||
encryption_key_source = widevine_key_source.Pass();
|
||||
} else if (FLAGS_enable_fixed_key_encryption) {
|
||||
encryption_key_source = KeySource::CreateFromHexStrings(
|
||||
FLAGS_key_id, FLAGS_key, FLAGS_pssh, "");
|
||||
FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
|
||||
}
|
||||
return encryption_key_source.Pass();
|
||||
}
|
||||
|
|
|
@ -142,12 +142,6 @@ bool ValidateWidevineCryptoFlags() {
|
|||
if (FLAGS_crypto_period_duration < 0) {
|
||||
PrintError("--crypto_period_duration should not be negative.");
|
||||
success = false;
|
||||
} else if (FLAGS_crypto_period_duration > 0 &&
|
||||
!FLAGS_enable_widevine_encryption) {
|
||||
PrintError(
|
||||
"--crypto_period_duration should be specified only if "
|
||||
"--enable_widevine_encryption.");
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -90,12 +90,9 @@ bool AudioStreamInfo::IsValidConfig() const {
|
|||
std::string AudioStreamInfo::ToString() const {
|
||||
return base::StringPrintf(
|
||||
"%s codec: %s\n sample_bits: %d\n num_channels: %d\n "
|
||||
"sampling_frequency: %d\n",
|
||||
StreamInfo::ToString().c_str(),
|
||||
AudioCodecToString(codec_).c_str(),
|
||||
sample_bits_,
|
||||
num_channels_,
|
||||
sampling_frequency_);
|
||||
"sampling_frequency: %d\n language: %s\n",
|
||||
StreamInfo::ToString().c_str(), AudioCodecToString(codec_).c_str(),
|
||||
sample_bits_, num_channels_, sampling_frequency_, language().c_str());
|
||||
}
|
||||
|
||||
std::string AudioStreamInfo::GetCodecString(AudioCodec codec,
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace {
|
|||
const uint8_t kWidevineSystemId[] = {0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6,
|
||||
0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc,
|
||||
0xd5, 0x1d, 0x21, 0xed};
|
||||
const char kDefaultUUID[] = "";
|
||||
// TODO(kqyang): Consider making it configurable.
|
||||
const char kDefaultUUID[] = "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed";
|
||||
const char kDefaultSystemName[] = "";
|
||||
} // namespace
|
||||
|
||||
|
@ -65,8 +66,27 @@ Status KeySource::GetKey(const std::vector<uint8_t>& key_id,
|
|||
Status KeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
|
||||
TrackType track_type,
|
||||
EncryptionKey* key) {
|
||||
NOTIMPLEMENTED();
|
||||
return Status(error::UNIMPLEMENTED, "");
|
||||
*key = *encryption_key_;
|
||||
// A naive key rotation algorithm is implemented here by left rotating the
|
||||
// key, key_id and pssh. Note that this implementation is only intended for
|
||||
// testing purpose. The actual key rotation algorithm can be much more
|
||||
// complicated.
|
||||
LOG(WARNING)
|
||||
<< "This naive key rotation algorithm should not be used in production.";
|
||||
std::rotate(key->key_id.begin(),
|
||||
key->key_id.begin() + (crypto_period_index % key->key_id.size()),
|
||||
key->key_id.end());
|
||||
std::rotate(key->key.begin(),
|
||||
key->key.begin() + (crypto_period_index % key->key.size()),
|
||||
key->key.end());
|
||||
const size_t kPsshHeaderSize = 32u;
|
||||
std::vector<uint8_t> pssh_data(key->pssh.begin() + kPsshHeaderSize,
|
||||
key->pssh.end());
|
||||
std::rotate(pssh_data.begin(),
|
||||
pssh_data.begin() + (crypto_period_index % pssh_data.size()),
|
||||
pssh_data.end());
|
||||
key->pssh = PsshBoxFromPsshData(pssh_data);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
std::string KeySource::UUID() {
|
||||
|
|
|
@ -40,11 +40,11 @@ StreamInfo::~StreamInfo() {}
|
|||
std::string StreamInfo::ToString() const {
|
||||
return base::StringPrintf(
|
||||
"type: %s\n codec_string: %s\n time_scale: %d\n duration: "
|
||||
"%" PRIu64 " (%.1f seconds)\n language: %s\n is_encrypted: %s\n",
|
||||
"%" PRIu64 " (%.1f seconds)\n is_encrypted: %s\n",
|
||||
(stream_type_ == kStreamAudio ? "Audio" : "Video"),
|
||||
codec_string_.c_str(),
|
||||
time_scale_, duration_,
|
||||
static_cast<double>(duration_) / time_scale_, language_.c_str(),
|
||||
static_cast<double>(duration_) / time_scale_,
|
||||
is_encrypted_ ? "true" : "false");
|
||||
}
|
||||
|
||||
|
|
|
@ -85,13 +85,11 @@ bool VideoStreamInfo::IsValidConfig() const {
|
|||
|
||||
std::string VideoStreamInfo::ToString() const {
|
||||
return base::StringPrintf(
|
||||
"%s codec: %s\n width: %d\n height: %d\n pixel_width: %d\n pixel_height: "
|
||||
"%d\n trick_play_rate: %d\n nalu_length_size: %d\n",
|
||||
StreamInfo::ToString().c_str(),
|
||||
VideoCodecToString(codec_).c_str(),
|
||||
width_, height_,
|
||||
pixel_width_, pixel_height_,
|
||||
trick_play_rate_, nalu_length_size_);
|
||||
"%s codec: %s\n width: %d\n height: %d\n pixel aspect ratio: %d:%d\n "
|
||||
"trick_play_rate: %d\n nalu_length_size: %d\n",
|
||||
StreamInfo::ToString().c_str(), VideoCodecToString(codec_).c_str(),
|
||||
width_, height_, pixel_width_, pixel_height_, trick_play_rate_,
|
||||
nalu_length_size_);
|
||||
}
|
||||
|
||||
std::string VideoStreamInfo::GetCodecString(VideoCodec codec,
|
||||
|
|
Loading…
Reference in New Issue