Do not partially encrypt a segment
Mimic iso-bmff behavior: either all the samples in a segment are encrypted or all the samples are clear. Change-Id: I03bdbbf5a4b690f4d87c4dceb0f8155e6fae941e
This commit is contained in:
parent
23f2913248
commit
de9667080f
Binary file not shown.
|
@ -19,7 +19,6 @@ const std::string kKeyId = "4c6f72656d20697073756d20646f6c6f";
|
||||||
const std::string kIv = "0123456789012345";
|
const std::string kIv = "0123456789012345";
|
||||||
const std::string kKey = "01234567890123456789012345678901";
|
const std::string kKey = "01234567890123456789012345678901";
|
||||||
const std::string kPsshData = "";
|
const std::string kPsshData = "";
|
||||||
|
|
||||||
const uint8_t kBasicSupportData[] = {
|
const uint8_t kBasicSupportData[] = {
|
||||||
// ID: EBML Header, Payload Size: 31
|
// ID: EBML Header, Payload Size: 31
|
||||||
0x1a, 0x45, 0xdf, 0xa3, 0x9f,
|
0x1a, 0x45, 0xdf, 0xa3, 0x9f,
|
||||||
|
@ -37,8 +36,8 @@ const uint8_t kBasicSupportData[] = {
|
||||||
0x42, 0x87, 0x81, 0x02,
|
0x42, 0x87, 0x81, 0x02,
|
||||||
// DocTypeReadVersion: 2
|
// DocTypeReadVersion: 2
|
||||||
0x42, 0x85, 0x81, 0x02,
|
0x42, 0x85, 0x81, 0x02,
|
||||||
// ID: Segment, Payload Size: 411
|
// ID: Segment, Payload Size: 432
|
||||||
0x18, 0x53, 0x80, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9b,
|
0x18, 0x53, 0x80, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb0,
|
||||||
// ID: SeekHead, Payload Size: 58
|
// ID: SeekHead, Payload Size: 58
|
||||||
0x11, 0x4d, 0x9b, 0x74, 0xba,
|
0x11, 0x4d, 0x9b, 0x74, 0xba,
|
||||||
// ID: Seek, Payload Size: 11
|
// ID: Seek, Payload Size: 11
|
||||||
|
@ -63,8 +62,8 @@ const uint8_t kBasicSupportData[] = {
|
||||||
0x4d, 0xbb, 0x8c,
|
0x4d, 0xbb, 0x8c,
|
||||||
// SeekID: binary(4) (Cues)
|
// SeekID: binary(4) (Cues)
|
||||||
0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
|
0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
|
||||||
// SeekPosition: 392
|
// SeekPosition: 398
|
||||||
0x53, 0xac, 0x82, 0x01, 0x88,
|
0x53, 0xac, 0x82, 0x01, 0x8e,
|
||||||
// ID: Void, Payload Size: 24
|
// ID: Void, Payload Size: 24
|
||||||
0xec, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0xec, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
@ -131,8 +130,8 @@ const uint8_t kBasicSupportData[] = {
|
||||||
0x54, 0xb0, 0x81, 0x64,
|
0x54, 0xb0, 0x81, 0x64,
|
||||||
// DisplayHeight: 100
|
// DisplayHeight: 100
|
||||||
0x54, 0xba, 0x81, 0x64,
|
0x54, 0xba, 0x81, 0x64,
|
||||||
// ID: Cluster, Payload Size: 101
|
// ID: Cluster, Payload Size: 45
|
||||||
0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
|
0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
|
||||||
// Timecode: 0
|
// Timecode: 0
|
||||||
0xe7, 0x81, 0x00,
|
0xe7, 0x81, 0x00,
|
||||||
// ID: SimpleBlock, Payload Size: 10
|
// ID: SimpleBlock, Payload Size: 10
|
||||||
|
@ -141,44 +140,48 @@ const uint8_t kBasicSupportData[] = {
|
||||||
0x00,
|
0x00,
|
||||||
// Frame Data:
|
// Frame Data:
|
||||||
0xde, 0xad, 0xbe, 0xef, 0x00,
|
0xde, 0xad, 0xbe, 0xef, 0x00,
|
||||||
// ID: SimpleBlock, Payload Size: 18
|
// ID: SimpleBlock, Payload Size: 10
|
||||||
0xa3, 0x92, 0x81, 0x03, 0xe8, 0x80,
|
0xa3, 0x8a, 0x81, 0x03, 0xe8, 0x80,
|
||||||
|
// Signal Byte: Clear
|
||||||
|
0x00,
|
||||||
|
// Frame Data:
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0x00,
|
||||||
|
// ID: BlockGroup, Payload Size: 16
|
||||||
|
0xa0, 0x90,
|
||||||
|
// ID: Block, Payload Size: 10
|
||||||
|
0xa1, 0x8a, 0x81, 0x07, 0xd0, 0x00,
|
||||||
|
// Signal Byte: Clear
|
||||||
|
0x00,
|
||||||
|
// Frame Data:
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0x00,
|
||||||
|
// BlockDuration: 1000
|
||||||
|
0x9b, 0x82, 0x03, 0xe8,
|
||||||
|
// ID: Cluster, Payload Size: 50
|
||||||
|
0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
|
||||||
|
// Timecode: 3000
|
||||||
|
0xe7, 0x82, 0x0b, 0xb8,
|
||||||
|
// ID: SimpleBlock: Payload Size: 18
|
||||||
|
0xa3, 0x92, 0x81, 0x00,0x00, 0x80,
|
||||||
// Signal Byte: Encrypted
|
// Signal Byte: Encrypted
|
||||||
0x01,
|
0x01,
|
||||||
// IV:
|
// IV:
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
|
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
|
||||||
// Frame Data:
|
// Frame Data:
|
||||||
0xcc, 0x03, 0xef, 0xc4, 0xf4,
|
0xcc, 0x03, 0xef, 0xc4, 0xf4,
|
||||||
// ID: SimpleBlock, Payload Size: 18
|
// ID: BlockGroup, Payload Size: 24
|
||||||
0xa3, 0x92, 0x81, 0x07, 0xd0, 0x80,
|
0xa0, 0x98,
|
||||||
|
// ID: Block, Payload Size: 18
|
||||||
|
0xa1, 0x92, 0x81, 0x03, 0xe8, 0x00,
|
||||||
// Signal Byte: Encrypted
|
// Signal Byte: Encrypted
|
||||||
0x01,
|
0x01,
|
||||||
// IV:
|
// IV:
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x46,
|
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x46,
|
||||||
// Frame Data:
|
// Frame Data:
|
||||||
0xbf, 0x38, 0x72, 0x20, 0xac,
|
0xbf, 0x38, 0x72, 0x20, 0xac,
|
||||||
// ID: SimpleBlock, Payload Size: 18
|
|
||||||
0xa3, 0x92, 0x81, 0x0b, 0xb8, 0x80,
|
|
||||||
// Signal Byte: Encrypted
|
|
||||||
0x01,
|
|
||||||
// IV:
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x47,
|
|
||||||
// Frame Data:
|
|
||||||
0x0d, 0x8e, 0xae, 0xbe, 0xd0,
|
|
||||||
// ID: BlockGroup, Payload Size: 24
|
|
||||||
0xa0, 0x98,
|
|
||||||
// ID: Block, Payload Size: 18
|
|
||||||
0xa1, 0x92, 0x81, 0x0f, 0xa0, 0x00,
|
|
||||||
// Signal Byte: Encrypted
|
|
||||||
0x01,
|
|
||||||
// IV:
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x48,
|
|
||||||
// Frame Data:
|
|
||||||
0xa5, 0x97, 0xf8, 0x9e, 0x87,
|
|
||||||
// BlockDuration: 1000
|
// BlockDuration: 1000
|
||||||
0x9b, 0x82, 0x03, 0xe8,
|
0x9b, 0x82, 0x03, 0xe8,
|
||||||
// ID: Cues, Payload Size: 14
|
// ID: Cues, Payload Size: 29
|
||||||
0x1c, 0x53, 0xbb, 0x6b, 0x8e,
|
0x1c, 0x53, 0xbb, 0x6b, 0x9d,
|
||||||
// ID: CuePoint, Payload Size: 12
|
// ID: CuePoint, Payload Size: 12
|
||||||
0xbb, 0x8c,
|
0xbb, 0x8c,
|
||||||
// CueTime: 0
|
// CueTime: 0
|
||||||
|
@ -188,7 +191,17 @@ const uint8_t kBasicSupportData[] = {
|
||||||
// CueTrack: 1
|
// CueTrack: 1
|
||||||
0xf7, 0x81, 0x01,
|
0xf7, 0x81, 0x01,
|
||||||
// CueClusterPosition: 279
|
// CueClusterPosition: 279
|
||||||
0xf1, 0x82, 0x01, 0x17
|
0xf1, 0x82, 0x01, 0x17,
|
||||||
|
// ID: CuePoint, Payload Size: 13
|
||||||
|
0xbb, 0x8d,
|
||||||
|
// CueTime: 3000
|
||||||
|
0xb3, 0x82, 0x0b, 0xb8,
|
||||||
|
// ID: CueTrackPositions, Payload Size: 7
|
||||||
|
0xb7, 0x87,
|
||||||
|
// CueTrack: 1
|
||||||
|
0xf7, 0x81, 0x01,
|
||||||
|
// CueClusterPosition: 336
|
||||||
|
0xf1, 0x82, 0x01, 0x50,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -213,9 +226,12 @@ class EncrypedSegmenterTest : public SegmentTestBase {
|
||||||
|
|
||||||
TEST_F(EncrypedSegmenterTest, BasicSupport) {
|
TEST_F(EncrypedSegmenterTest, BasicSupport) {
|
||||||
MuxerOptions options = CreateMuxerOptions();
|
MuxerOptions options = CreateMuxerOptions();
|
||||||
|
options.segment_duration = 3.0;
|
||||||
ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options));
|
ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options));
|
||||||
|
|
||||||
// Write the samples to the Segmenter.
|
// Write the samples to the Segmenter.
|
||||||
|
// There should be 2 segments with the first segment in clear and the second
|
||||||
|
// segment encrypted.
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
scoped_refptr<MediaSample> sample =
|
scoped_refptr<MediaSample> sample =
|
||||||
CreateSample(kKeyFrame, kDuration, kNoSideData);
|
CreateSample(kKeyFrame, kDuration, kNoSideData);
|
||||||
|
@ -228,4 +244,3 @@ TEST_F(EncrypedSegmenterTest, BasicSupport) {
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ int64_t kSecondsToNs = 1000000000L;
|
||||||
Segmenter::Segmenter(const MuxerOptions& options)
|
Segmenter::Segmenter(const MuxerOptions& options)
|
||||||
: reference_frame_timestamp_(0),
|
: reference_frame_timestamp_(0),
|
||||||
options_(options),
|
options_(options),
|
||||||
|
clear_lead_(0),
|
||||||
|
enable_encryption_(false),
|
||||||
info_(NULL),
|
info_(NULL),
|
||||||
muxer_listener_(NULL),
|
muxer_listener_(NULL),
|
||||||
progress_listener_(NULL),
|
progress_listener_(NULL),
|
||||||
|
@ -144,6 +146,15 @@ Status Segmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
segment_length_sec_ = 0;
|
segment_length_sec_ = 0;
|
||||||
cluster_length_sec_ = 0;
|
cluster_length_sec_ = 0;
|
||||||
wrote_frame = true;
|
wrote_frame = true;
|
||||||
|
|
||||||
|
if (encryptor_ && !enable_encryption_) {
|
||||||
|
if (sample->pts() - first_timestamp_ >=
|
||||||
|
clear_lead_ * info_->time_scale()) {
|
||||||
|
enable_encryption_ = true;
|
||||||
|
if (muxer_listener_)
|
||||||
|
muxer_listener_->OnEncryptionStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (cluster_length_sec_ >= options_.fragment_duration) {
|
} else if (cluster_length_sec_ >= options_.fragment_duration) {
|
||||||
if (sample->is_key_frame() || !options_.fragment_sap_aligned) {
|
if (sample->is_key_frame() || !options_.fragment_sap_aligned) {
|
||||||
|
@ -161,20 +172,13 @@ Status Segmenter::AddSample(scoped_refptr<MediaSample> sample) {
|
||||||
|
|
||||||
// Encrypt the frame.
|
// Encrypt the frame.
|
||||||
if (encryptor_) {
|
if (encryptor_) {
|
||||||
const bool encrypt_frame =
|
status = encryptor_->EncryptFrame(sample, enable_encryption_);
|
||||||
static_cast<double>(sample->pts() - first_timestamp_) /
|
|
||||||
info_->time_scale() >=
|
|
||||||
clear_lead_;
|
|
||||||
status = encryptor_->EncryptFrame(sample, encrypt_frame);
|
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
LOG(ERROR) << "Error encrypting frame.";
|
LOG(ERROR) << "Error encrypting frame.";
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
if (encrypt_frame && muxer_listener_)
|
|
||||||
muxer_listener_->OnEncryptionStart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add the sample to the durations even though we have not written the frame
|
// Add the sample to the durations even though we have not written the frame
|
||||||
// yet. This is needed to make sure we split Clusters at the correct point.
|
// yet. This is needed to make sure we split Clusters at the correct point.
|
||||||
// These are only used in this method.
|
// These are only used in this method.
|
||||||
|
|
|
@ -135,6 +135,7 @@ class Segmenter {
|
||||||
const MuxerOptions& options_;
|
const MuxerOptions& options_;
|
||||||
std::unique_ptr<Encryptor> encryptor_;
|
std::unique_ptr<Encryptor> encryptor_;
|
||||||
double clear_lead_;
|
double clear_lead_;
|
||||||
|
bool enable_encryption_; // Encryption is enabled only after clear_lead_.
|
||||||
|
|
||||||
std::unique_ptr<mkvmuxer::Cluster> cluster_;
|
std::unique_ptr<mkvmuxer::Cluster> cluster_;
|
||||||
mkvmuxer::Cues cues_;
|
mkvmuxer::Cues cues_;
|
||||||
|
|
Loading…
Reference in New Issue