Allow encrypted TS without clear lead
Change-Id: Icc4268af94c11b004f020cfb4dd9f5f16a9169af
This commit is contained in:
parent
cb3b277575
commit
d06a9cd17c
|
@ -22,6 +22,7 @@ namespace mp2t {
|
|||
namespace {
|
||||
|
||||
// Values for version. Only 0 and 1 are necessary for the implementation.
|
||||
const int kVersion0 = 0;
|
||||
const int kVersion1 = 1;
|
||||
|
||||
// Values for current_next_indicator.
|
||||
|
@ -328,6 +329,7 @@ H264ProgramMapTableWriter::H264ProgramMapTableWriter(
|
|||
H264ProgramMapTableWriter::~H264ProgramMapTableWriter() {}
|
||||
|
||||
bool H264ProgramMapTableWriter::ClearLeadSegmentPmt(BufferWriter* writer) {
|
||||
has_clear_lead_ = true;
|
||||
WritePmtToBuffer(kPmtH264, arraysize(kPmtH264), continuity_counter_, writer);
|
||||
WritePmtWithParameters(
|
||||
kStreamTypeEncryptedH264, kVersion1, kNext,
|
||||
|
@ -339,8 +341,8 @@ bool H264ProgramMapTableWriter::ClearLeadSegmentPmt(BufferWriter* writer) {
|
|||
|
||||
bool H264ProgramMapTableWriter::EncryptedSegmentPmt(BufferWriter* writer) {
|
||||
WritePmtWithParameters(
|
||||
kStreamTypeEncryptedH264, kVersion1, kCurrent,
|
||||
kPrivateDataIndicatorDescriptorEncryptedH264,
|
||||
kStreamTypeEncryptedH264, has_clear_lead_ ? kVersion1 : kVersion0,
|
||||
kCurrent, kPrivateDataIndicatorDescriptorEncryptedH264,
|
||||
arraysize(kPrivateDataIndicatorDescriptorEncryptedH264),
|
||||
continuity_counter_, writer);
|
||||
return true;
|
||||
|
@ -365,6 +367,7 @@ AacProgramMapTableWriter::~AacProgramMapTableWriter() {}
|
|||
// TODO(rkuroiwa): Cache the PMT for encrypted segments, it doesn't need to
|
||||
// be recalculated.
|
||||
bool AacProgramMapTableWriter::ClearLeadSegmentPmt(BufferWriter* writer) {
|
||||
has_clear_lead_ = true;
|
||||
WritePmtToBuffer(kPmtAac, arraysize(kPmtAac), continuity_counter_, writer);
|
||||
// Version 1 and next.
|
||||
return EncryptedSegmentPmtWithParameters(kVersion1, kNext, writer);
|
||||
|
@ -372,7 +375,8 @@ bool AacProgramMapTableWriter::ClearLeadSegmentPmt(BufferWriter* writer) {
|
|||
|
||||
bool AacProgramMapTableWriter::EncryptedSegmentPmt(BufferWriter* writer) {
|
||||
// Version 1 and current.
|
||||
return EncryptedSegmentPmtWithParameters(kVersion1, kCurrent, writer);
|
||||
return EncryptedSegmentPmtWithParameters(
|
||||
has_clear_lead_ ? kVersion1 : kVersion0, kCurrent, writer);
|
||||
}
|
||||
|
||||
bool AacProgramMapTableWriter::ClearSegmentPmt(BufferWriter* writer) {
|
||||
|
|
|
@ -63,6 +63,9 @@ class H264ProgramMapTableWriter : public ProgramMapTableWriter {
|
|||
|
||||
private:
|
||||
ContinuityCounter* const continuity_counter_;
|
||||
// Set to true if ClearLeadSegmentPmt() has been called. This determines the
|
||||
// version number set in EncryptedSegmentPmt().
|
||||
bool has_clear_lead_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(H264ProgramMapTableWriter);
|
||||
};
|
||||
|
@ -89,6 +92,9 @@ class AacProgramMapTableWriter : public ProgramMapTableWriter {
|
|||
|
||||
const std::vector<uint8_t> aac_audio_specific_config_;
|
||||
ContinuityCounter* const continuity_counter_;
|
||||
// Set to true if ClearLeadSegmentPmt() has been called. This determines the
|
||||
// version number set in EncryptedSegmentPmt().
|
||||
bool has_clear_lead_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AacProgramMapTableWriter);
|
||||
};
|
||||
|
|
|
@ -40,8 +40,11 @@ class ProgramMapTableWriterTest : public ::testing::Test {
|
|||
|
||||
std::vector<uint8_t> actual_suffix(actual + prefix_size + padding_length,
|
||||
actual + kTsPacketSize);
|
||||
EXPECT_EQ(std::vector<uint8_t>(suffix, suffix + suffix_size),
|
||||
actual_suffix);
|
||||
ASSERT_EQ(suffix_size, actual_suffix.size());
|
||||
|
||||
for (size_t i = 0; i < suffix_size; ++i) {
|
||||
EXPECT_EQ(suffix[i], actual_suffix[i]) << "at index " << i;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -161,20 +164,22 @@ TEST_F(ProgramMapTableWriterTest, ClearLeadH264) {
|
|||
buffer.Buffer() + kTsPacketSize));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsH264Pmt) {
|
||||
// Verify that PSI for encrypted segments after clear lead is generated
|
||||
// correctly.
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadH264) {
|
||||
ContinuityCounter counter;
|
||||
H264ProgramMapTableWriter writer(&counter);
|
||||
BufferWriter buffer;
|
||||
writer.ClearLeadSegmentPmt(&buffer);
|
||||
buffer.Clear();
|
||||
writer.EncryptedSegmentPmt(&buffer);
|
||||
|
||||
EXPECT_EQ(kTsPacketSize, buffer.Size());
|
||||
|
||||
const uint8_t kPmtEncryptedH264Prefix[] = {
|
||||
0x47, // Sync byte.
|
||||
0x40, // payload_unit_start_indicator set.
|
||||
0x20, // pid.
|
||||
0x30, // Adaptation field and payload are both present. counter = 0.
|
||||
0x32, // Adaptation field and payload are both present. counter = 2.
|
||||
0x9B, // Adaptation Field length.
|
||||
0x00, // All adaptation field flags 0.
|
||||
};
|
||||
|
@ -205,6 +210,50 @@ TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsH264Pmt) {
|
|||
kPmtEncryptedH264, arraysize(kPmtEncryptedH264), buffer.Buffer()));
|
||||
}
|
||||
|
||||
// Verify that PMT for encrypted segments can be generated (without clear lead).
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsH264Pmt) {
|
||||
ContinuityCounter counter;
|
||||
H264ProgramMapTableWriter writer(&counter);
|
||||
BufferWriter buffer;
|
||||
writer.EncryptedSegmentPmt(&buffer);
|
||||
|
||||
EXPECT_EQ(kTsPacketSize, buffer.Size());
|
||||
|
||||
const uint8_t kPmtEncryptedH264Prefix[] = {
|
||||
0x47, // Sync byte.
|
||||
0x40, // payload_unit_start_indicator set.
|
||||
0x20, // pid.
|
||||
0x30, // Adaptation field and payload are both present. counter = 0.
|
||||
0x9B, // Adaptation Field length.
|
||||
0x00, // All adaptation field flags 0.
|
||||
};
|
||||
|
||||
const uint8_t kPmtEncryptedH264[] = {
|
||||
0x00, // pointer field
|
||||
0x02, // Table id.
|
||||
0xB0, // The first 4 bits must be '1011'.
|
||||
0x18, // length of the rest of this array.
|
||||
0x00, 0x01, // program number.
|
||||
0xC1, // version 0, current next indicator 1.
|
||||
0x00, // section number
|
||||
0x00, // last section number.
|
||||
0xE0, // first 3 bits reserved.
|
||||
0x50, // PCR PID is the elementary streams PID.
|
||||
0xF0, // first 4 bits reserved.
|
||||
0x00, // No descriptor at this level.
|
||||
0xDB, 0xE0, 0x50, // stream_type -> PID.
|
||||
0xF0, 0x06, // Es_info_length is 6 for private_data_indicator
|
||||
0x0F, // descriptor_tag.
|
||||
0x04, // Length of the rest of this descriptor
|
||||
0x7A, 0x61, 0x76, 0x63, // 'zavc'.
|
||||
// CRC32.
|
||||
0xA9, 0xC2, 0x95, 0x7C,
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectTsPacketEqual(
|
||||
kPmtEncryptedH264Prefix, arraysize(kPmtEncryptedH264Prefix), 154,
|
||||
kPmtEncryptedH264, arraysize(kPmtEncryptedH264), buffer.Buffer()));
|
||||
}
|
||||
|
||||
TEST_F(ProgramMapTableWriterTest, ClearAac) {
|
||||
ContinuityCounter counter;
|
||||
const std::vector<uint8_t> aac_audio_specific_config(
|
||||
|
@ -338,23 +387,26 @@ TEST_F(ProgramMapTableWriterTest, ClearLeadAac) {
|
|||
buffer.Buffer() + kTsPacketSize));
|
||||
}
|
||||
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAacPmt) {
|
||||
// Verify that PSI for encrypted segments after clear lead is generated
|
||||
// correctly.
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadAac) {
|
||||
ContinuityCounter counter;
|
||||
const std::vector<uint8_t> aac_audio_specific_config(
|
||||
kAacBasicProfileExtraData,
|
||||
kAacBasicProfileExtraData + arraysize(kAacBasicProfileExtraData));
|
||||
AacProgramMapTableWriter writer(aac_audio_specific_config, &counter);
|
||||
BufferWriter buffer;
|
||||
writer.EncryptedSegmentPmt(&buffer);
|
||||
writer.ClearLeadSegmentPmt(&buffer);
|
||||
|
||||
buffer.Clear();
|
||||
writer.EncryptedSegmentPmt(&buffer);
|
||||
EXPECT_EQ(kTsPacketSize, buffer.Size());
|
||||
|
||||
// Second PMT is for the encrypted segments after clear lead.
|
||||
const uint8_t kPmtEncryptedAacPrefix[] = {
|
||||
0x47, // Sync byte.
|
||||
0x40, // payload_unit_start_indicator set.
|
||||
0x20, // pid.
|
||||
0x30, // Adaptation field and payload are both present. counter = 0.
|
||||
0x32, // Adaptation field and payload are both present. counter = 2.
|
||||
0x8B, // Adaptation Field length.
|
||||
0x00, // All adaptation field flags 0.
|
||||
};
|
||||
|
@ -397,6 +449,66 @@ TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAacPmt) {
|
|||
buffer.Buffer()));
|
||||
}
|
||||
|
||||
// Verify that PMT for encrypted segments can be generated (without clear lead).
|
||||
TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAacPmt) {
|
||||
ContinuityCounter counter;
|
||||
const std::vector<uint8_t> aac_audio_specific_config(
|
||||
kAacBasicProfileExtraData,
|
||||
kAacBasicProfileExtraData + arraysize(kAacBasicProfileExtraData));
|
||||
AacProgramMapTableWriter writer(aac_audio_specific_config, &counter);
|
||||
BufferWriter buffer;
|
||||
writer.EncryptedSegmentPmt(&buffer);
|
||||
|
||||
EXPECT_EQ(kTsPacketSize, buffer.Size());
|
||||
|
||||
// Second PMT is for the encrypted segments after clear lead.
|
||||
const uint8_t kPmtEncryptedAacPrefix[] = {
|
||||
0x47, // Sync byte.
|
||||
0x40, // payload_unit_start_indicator set.
|
||||
0x20, // pid.
|
||||
0x30, // Adaptation field and payload are both present. counter = 0.
|
||||
0x8B, // Adaptation Field length.
|
||||
0x00, // All adaptation field flags 0.
|
||||
};
|
||||
const uint8_t kPmtEncryptedAac[] = {
|
||||
0x00, // pointer field
|
||||
0x02, // table id.
|
||||
0xB0, // The first 4 bits must be '1011'.
|
||||
0x28, // length of the rest of this array.
|
||||
0x00, 0x01, // Program number.
|
||||
0xC1, // version 0, current next indicator 1.
|
||||
0x00, // section number
|
||||
0x00, // last section number.
|
||||
0xE0, // first 3 bits reserved.
|
||||
0x50, // PCR PID is the elementary streams PID.
|
||||
0xF0, // first 4 bits reserved.
|
||||
0x00, // No descriptor at this level.
|
||||
0xCF, 0xE0, 0x50, // stream_type -> PID.
|
||||
0xF0, 0x16, // Es_info_length is 5 for private_data_indicator
|
||||
0x0F, // private_data_indicator descriptor_tag.
|
||||
0x04, // Length of the rest of this descriptor
|
||||
0x61, 0x61, 0x63, 0x64, // 'aacd'.
|
||||
0x05, // registration_descriptor tag.
|
||||
// space for 'zaac' + priming (0x0000) + version (0x01) +
|
||||
// setup_data_length size + size of kAacBasicProfileExtraData + space for
|
||||
// 'apad'. Which is 14.
|
||||
0x0E,
|
||||
0x61, 0x70, 0x61, 0x64, // 'apad'.
|
||||
0x7A, 0x61, 0x61, 0x63, // 'zaac'.
|
||||
0x00, 0x00, // priming.
|
||||
0x01, // version.
|
||||
0x02, // setup_data_length == extra data length
|
||||
0x12, 0x10, // setup_data == extra data.
|
||||
// CRC32.
|
||||
0xF7, 0xD5, 0x2A, 0x53,
|
||||
};
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectTsPacketEqual(
|
||||
kPmtEncryptedAacPrefix, arraysize(kPmtEncryptedAacPrefix), 138,
|
||||
kPmtEncryptedAac, arraysize(kPmtEncryptedAac),
|
||||
buffer.Buffer()));
|
||||
}
|
||||
|
||||
} // namespace mp2t
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
|
Loading…
Reference in New Issue