diff --git a/packager/media/base/fourccs.h b/packager/media/base/fourccs.h index a999a5e058..1225b669f4 100644 --- a/packager/media/base/fourccs.h +++ b/packager/media/base/fourccs.h @@ -147,6 +147,7 @@ enum FourCC : uint32_t { FOURCC_zaac = 0x7A616163, FOURCC_zach = 0x7A616368, FOURCC_zacp = 0x7A616370, + FOURCC_zavc = 0x7A617663, }; const FourCC kAppleSampleAesProtectionScheme = FOURCC_cbca; diff --git a/packager/media/formats/mp2t/program_map_table_writer.cc b/packager/media/formats/mp2t/program_map_table_writer.cc index d1b5385b24..75e92816b8 100644 --- a/packager/media/formats/mp2t/program_map_table_writer.cc +++ b/packager/media/formats/mp2t/program_map_table_writer.cc @@ -12,7 +12,6 @@ #include "packager/media/base/buffer_writer.h" #include "packager/media/base/fourccs.h" #include "packager/media/codecs/aac_audio_specific_config.h" -#include "packager/media/formats/mp2t/continuity_counter.h" #include "packager/media/formats/mp2t/ts_packet_writer_util.h" namespace shaka { @@ -119,65 +118,6 @@ uint32_t Crc32Mpeg2(const uint8_t* data, size_t data_size) { return crc; } -// For all the pointer fields in the PMTs, they are not really part of the PMT -// but it's there so that an extra buffer isn't required to prepend the 0x00 -// byte. - -// PMT for H264 clear segments. -// Note that this is version 0, so it only works for clear lead or clear stream. -const uint8_t kPmtH264[] = { - 0x00, // pointer field - kProgramMapTableId, - 0xB0, // assumes length is <= 256 bytes. - 0x12, // length of the rest of this array. - 0x00, kProgramNumber, - 0xC1, // version 0, current next indicator 1. - 0x00, // section number - 0x00, // last section number. - 0xE0, // first 3 bits reserved. - // PCR PID is the elementary streams PID. - ProgramMapTableWriter::kElementaryPid, - 0xF0, // first 4 bits reserved. - 0x00, // No descriptor at this level. - // stream_type -> PID. - kStreamTypeH264, 0xE0, ProgramMapTableWriter::kElementaryPid, - 0xF0, 0x00, // Es_info_length is 0. - // CRC32. - 0x43, 0x49, 0x97, 0xBE, -}; - -// PMT for AAC clear segments. -// Note that this is version 0, so it only works for clear lead or clear stream. -const uint8_t kPmtAac[] = { - 0x00, // pointer field - 0x02, // table id must be 0x02. - 0xB0, // assumes length is <= 256 bytes. - 0x12, // length of the rest of this array. - 0x00, kProgramNumber, - 0xC1, // version 0, current next indicator 1. - 0x00, // section number - 0x00, // last section number. - 0xE0, // first 3 bits reserved. - // PCR PID is the elementary streams PID. - ProgramMapTableWriter::kElementaryPid, - 0xF0, // first 4 bits reserved. - 0x00, // No descriptor at this level. - // stream_type -> PID. - kStreamTypeAdtsAac, 0xE0, ProgramMapTableWriter::kElementaryPid, - 0xF0, 0x00, // Es_info_length is 0. - // CRC32. - 0xE0, 0x6F, 0x1A, 0x31, -}; - -// private_data_indicator for SAMPLE-AES H264. This is the same for all H264 -// streams. -const uint8_t kPrivateDataIndicatorDescriptorEncryptedH264[] = { - 0x0F, // descriptor_tag. - 0x04, // Length of the rest of this descriptor. - // 'zavc'. - 0x7A, 0x61, 0x76, 0x63, -}; - void WritePmtToBuffer(const uint8_t* pmt, size_t pmt_size, ContinuityCounter* continuity_counter, @@ -261,8 +201,7 @@ void WritePmtWithParameters(uint8_t stream_type, int current_next_indicator, const uint8_t* descriptors, size_t descriptors_size, - ContinuityCounter* continuity_counter, - BufferWriter* output) { + BufferWriter* pmt) { DCHECK(current_next_indicator == kCurrent || current_next_indicator == kNext); // Body starting from program number. BufferWriter pmt_body; @@ -291,106 +230,135 @@ void WritePmtWithParameters(uint8_t stream_type, // 4 reserved bits followed by ES_info_length. pmt_body.AppendInt(static_cast(0xF000 | descriptors_size)); - pmt_body.AppendArray(descriptors, descriptors_size); + if (descriptors_size > 0) { + DCHECK(descriptors); + pmt_body.AppendArray(descriptors, descriptors_size); + } - // The whole PMT has 3 bytes before the body and 4 more bytes for CRC. This - // also includes pointer field (1 byte) so + 8 in total. - BufferWriter pmt(pmt_body.Size() + 8); - // Pointer field. - pmt.AppendInt(static_cast(0x00)); - // PMT table ID is always 2. - pmt.AppendInt(static_cast(0x02)); + pmt->Clear(); + // Pointer field is not really part of the PMT but it's there so that an extra + // buffer isn't required to prepend the 0x00 byte. + const uint8_t kPointerField = 0; + pmt->AppendInt(kPointerField); + pmt->AppendInt(kProgramMapTableId); // First four bits must be '1011'. +4 for CRC. - pmt.AppendInt(static_cast(0xB000 | (pmt_body.Size() + 4))); - pmt.AppendBuffer(pmt_body); + pmt->AppendInt(static_cast(0xB000 | (pmt_body.Size() + 4))); + pmt->AppendBuffer(pmt_body); // Don't include the pointer field. - const uint32_t crc = Crc32Mpeg2(pmt.Buffer() + 1, pmt.Size() - 1); - pmt.AppendInt(crc); - WritePmtToBuffer(pmt.Buffer(), pmt.Size(), continuity_counter, output); + const uint32_t crc = Crc32Mpeg2(pmt->Buffer() + 1, pmt->Size() - 1); + pmt->AppendInt(crc); } } // namespace -ProgramMapTableWriter::ProgramMapTableWriter() {} -ProgramMapTableWriter::~ProgramMapTableWriter() {} +ProgramMapTableWriter::ProgramMapTableWriter(Codec codec) : codec_(codec) {} -H264ProgramMapTableWriter::H264ProgramMapTableWriter( - ContinuityCounter* continuity_counter) - : continuity_counter_(continuity_counter) { - DCHECK(continuity_counter); -} +bool ProgramMapTableWriter::EncryptedSegmentPmt(BufferWriter* writer) { + uint8_t stream_type; + switch (codec_) { + case kCodecH264: + stream_type = kStreamTypeEncryptedH264; + break; + case kCodecAAC: + stream_type = kStreamTypeEncryptedAdtsAac; + break; + default: + LOG(ERROR) << "Codec " << codec_ << " is not supported in TS yet."; + return false; + } -H264ProgramMapTableWriter::~H264ProgramMapTableWriter() {} + if (encrypted_pmt_.Size() == 0) { + BufferWriter descriptors; + if (!WriteDescriptors(&descriptors)) + return false; -bool H264ProgramMapTableWriter::EncryptedSegmentPmt(BufferWriter* writer) { - WritePmtWithParameters( - kStreamTypeEncryptedH264, has_clear_lead_ ? kVersion1 : kVersion0, - kCurrent, kPrivateDataIndicatorDescriptorEncryptedH264, - arraysize(kPrivateDataIndicatorDescriptorEncryptedH264), - continuity_counter_, writer); + const bool has_clear_lead = clear_pmt_.Size() > 0; + WritePmtWithParameters(stream_type, has_clear_lead ? kVersion1 : kVersion0, + kCurrent, descriptors.Buffer(), descriptors.Size(), + &encrypted_pmt_); + DCHECK_NE(encrypted_pmt_.Size(), 0u); + } + WritePmtToBuffer(encrypted_pmt_.Buffer(), encrypted_pmt_.Size(), + &continuity_counter_, writer); return true; } -bool H264ProgramMapTableWriter::ClearSegmentPmt(BufferWriter* writer) { - has_clear_lead_ = true; - WritePmtToBuffer(kPmtH264, arraysize(kPmtH264), continuity_counter_, writer); - // Cannot insert PMT for following encrypted segments because - // some players consider encrypted segments as "zavc" codec which is different - // from "avc1" codec, which causes problems. +bool ProgramMapTableWriter::ClearSegmentPmt(BufferWriter* writer) { + uint8_t stream_type; + switch (codec_) { + case kCodecH264: + stream_type = kStreamTypeH264; + break; + case kCodecAAC: + stream_type = kStreamTypeAdtsAac; + break; + default: + LOG(ERROR) << "Codec " << codec_ << " is not supported in TS yet."; + return false; + } + + if (clear_pmt_.Size() == 0) { + WritePmtWithParameters(stream_type, kVersion0, kCurrent, nullptr, 0, + &clear_pmt_); + DCHECK_NE(clear_pmt_.Size(), 0u); + } + WritePmtToBuffer(clear_pmt_.Buffer(), clear_pmt_.Size(), &continuity_counter_, + writer); return true; } -AacProgramMapTableWriter::AacProgramMapTableWriter( - const std::vector& aac_audio_specific_config, - ContinuityCounter* continuity_counter) - : aac_audio_specific_config_(aac_audio_specific_config), - continuity_counter_(continuity_counter) { - DCHECK(!aac_audio_specific_config.empty()); - DCHECK(continuity_counter_); -} +VideoProgramMapTableWriter::VideoProgramMapTableWriter(Codec codec) + : ProgramMapTableWriter(codec) {} -AacProgramMapTableWriter::~AacProgramMapTableWriter() {} - -// TODO(rkuroiwa): Cache the PMT for encrypted segments, it doesn't need to -// be recalculated. -bool AacProgramMapTableWriter::EncryptedSegmentPmt(BufferWriter* writer) { - // Version 1 and current. - return EncryptedSegmentPmtWithParameters( - has_clear_lead_ ? kVersion1 : kVersion0, kCurrent, writer); -} - -bool AacProgramMapTableWriter::ClearSegmentPmt(BufferWriter* writer) { - has_clear_lead_ = true; - WritePmtToBuffer(kPmtAac, arraysize(kPmtAac), continuity_counter_, writer); +bool VideoProgramMapTableWriter::WriteDescriptors( + BufferWriter* descriptors) const { + FourCC fourcc; + switch (codec()) { + case kCodecH264: + fourcc = FOURCC_zavc; + break; + default: + LOG(ERROR) << "Codec " << codec() << " is not supported in TS yet."; + return false; + } + WritePrivateDataIndicatorDescriptor(fourcc, descriptors); return true; } -bool AacProgramMapTableWriter::EncryptedSegmentPmtWithParameters( - int version, - int current_next_indicator, - BufferWriter* writer) { +AudioProgramMapTableWriter::AudioProgramMapTableWriter( + Codec codec, + const std::vector& audio_specific_config) + : ProgramMapTableWriter(codec), + audio_specific_config_(audio_specific_config) { + DCHECK(!audio_specific_config.empty()); +} + +bool AudioProgramMapTableWriter::WriteDescriptors( + BufferWriter* descriptors) const { + FourCC fourcc; + switch (codec()) { + case kCodecAAC: + fourcc = FOURCC_aacd; + break; + default: + LOG(ERROR) << "Codec " << codec() << " is not supported in TS yet."; + return false; + } + WritePrivateDataIndicatorDescriptor(fourcc, descriptors); + // -12 because there are 12 bytes between 'descriptor_length' in // registration_descriptor and 'setup_data_length' in audio_setup_information. - if (aac_audio_specific_config_.size() > + if (audio_specific_config_.size() > std::numeric_limits::max() - 12U) { LOG(ERROR) << "AACAudioSpecificConfig of size: " - << aac_audio_specific_config_.size() + << audio_specific_config_.size() << " will not fit in the descriptor."; return false; } - BufferWriter descriptors; - WritePrivateDataIndicatorDescriptor(FOURCC_aacd, &descriptors); - if (!WriteRegistrationDescriptorForEncryptedAudio( - aac_audio_specific_config_.data(), aac_audio_specific_config_.size(), - &descriptors)) { - return false; - } - - WritePmtWithParameters( - kStreamTypeEncryptedAdtsAac, version, current_next_indicator, - descriptors.Buffer(), descriptors.Size(), continuity_counter_, writer); - return true; + return WriteRegistrationDescriptorForEncryptedAudio( + audio_specific_config_.data(), audio_specific_config_.size(), + descriptors); } } // namespace mp2t diff --git a/packager/media/formats/mp2t/program_map_table_writer.h b/packager/media/formats/mp2t/program_map_table_writer.h index fbb920d37b..fb7c1ef738 100644 --- a/packager/media/formats/mp2t/program_map_table_writer.h +++ b/packager/media/formats/mp2t/program_map_table_writer.h @@ -11,7 +11,10 @@ #include -#include "packager/base/macros.h" +#include "packager/media/base/buffer_writer.h" +// TODO(kqyang): Move codec to codec.h. +#include "packager/media/base/stream_info.h" +#include "packager/media/formats/mp2t/continuity_counter.h" namespace shaka { namespace media { @@ -20,20 +23,19 @@ class BufferWriter; namespace mp2t { -class ContinuityCounter; - /// Puts PMT into TS packets and writes them to buffer. -/// Note that this does not currently allow encryption without clear lead. class ProgramMapTableWriter { public: - ProgramMapTableWriter(); - virtual ~ProgramMapTableWriter(); + explicit ProgramMapTableWriter(Codec codec); + virtual ~ProgramMapTableWriter() = default; /// Writes TS packets with PMT for encrypted segments. - virtual bool EncryptedSegmentPmt(BufferWriter* writer) = 0; + // Virtual for testing. + virtual bool EncryptedSegmentPmt(BufferWriter* writer); /// Writes TS packets with PMT for clear segments. - virtual bool ClearSegmentPmt(BufferWriter* writer) = 0; + // Virtual for testing. + virtual bool ClearSegmentPmt(BufferWriter* writer); // The pid can be 13 bits long but 8 bits is sufficient for this library. // This is the minimum PID that can be used for PMT. @@ -41,53 +43,54 @@ class ProgramMapTableWriter { // This is arbitrary number that is not reserved by the spec. static const uint8_t kElementaryPid = 0x50; -}; -/// This is not a general purpose PMT writer. This is intended to be used by -/// TsWriter. -class H264ProgramMapTableWriter : public ProgramMapTableWriter { - public: - explicit H264ProgramMapTableWriter(ContinuityCounter* continuity_counter); - ~H264ProgramMapTableWriter() override; - - bool EncryptedSegmentPmt(BufferWriter* writer) override; - bool ClearSegmentPmt(BufferWriter* writer) override; + protected: + /// @return the underlying codec. + Codec codec() const { return codec_; } 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; + ProgramMapTableWriter(const ProgramMapTableWriter&) = delete; + ProgramMapTableWriter& operator=(const ProgramMapTableWriter&) = delete; - DISALLOW_COPY_AND_ASSIGN(H264ProgramMapTableWriter); + // Writes descriptors for PMT (only needed for encrypted PMT). + virtual bool WriteDescriptors(BufferWriter* writer) const = 0; + + const Codec codec_; + ContinuityCounter continuity_counter_; + BufferWriter clear_pmt_; + BufferWriter encrypted_pmt_; }; -// TODO(rkuroiwa): For now just handle AAC, we would want AudioProgramMapTable -// later when we support other audio codecs. -/// This is not a general purpose PMT writer. This is intended to be used by -/// TsWriter. -class AacProgramMapTableWriter : public ProgramMapTableWriter { +/// ProgramMapTableWriter for video codecs. +class VideoProgramMapTableWriter : public ProgramMapTableWriter { public: - AacProgramMapTableWriter( - const std::vector& aac_audio_specific_config, - ContinuityCounter* continuity_counter); - ~AacProgramMapTableWriter() override; - - bool EncryptedSegmentPmt(BufferWriter* writer) override; - bool ClearSegmentPmt(BufferWriter* writer) override; + explicit VideoProgramMapTableWriter(Codec codec); + ~VideoProgramMapTableWriter() override = default; private: - bool EncryptedSegmentPmtWithParameters(int version, - int current_next_indicator, - BufferWriter* writer); + VideoProgramMapTableWriter(const VideoProgramMapTableWriter&) = delete; + VideoProgramMapTableWriter& operator=(const VideoProgramMapTableWriter&) = + delete; - const std::vector 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; + bool WriteDescriptors(BufferWriter* writer) const override; +}; - DISALLOW_COPY_AND_ASSIGN(AacProgramMapTableWriter); +/// ProgramMapTableWriter for video codecs. +class AudioProgramMapTableWriter : public ProgramMapTableWriter { + public: + AudioProgramMapTableWriter(Codec codec, + const std::vector& audio_specific_config); + ~AudioProgramMapTableWriter() override = default; + + private: + AudioProgramMapTableWriter(const AudioProgramMapTableWriter&) = delete; + AudioProgramMapTableWriter& operator=(const AudioProgramMapTableWriter&) = + delete; + + // Writers descriptors for PMT (only needed for encrypted PMT). + bool WriteDescriptors(BufferWriter* descriptors) const override; + + const std::vector audio_specific_config_; }; } // namespace mp2t diff --git a/packager/media/formats/mp2t/program_map_table_writer_unittest.cc b/packager/media/formats/mp2t/program_map_table_writer_unittest.cc index 81c6040f51..17324acc90 100644 --- a/packager/media/formats/mp2t/program_map_table_writer_unittest.cc +++ b/packager/media/formats/mp2t/program_map_table_writer_unittest.cc @@ -49,8 +49,7 @@ class ProgramMapTableWriterTest : public ::testing::Test { }; TEST_F(ProgramMapTableWriterTest, ClearH264) { - ContinuityCounter counter; - H264ProgramMapTableWriter writer(&counter); + VideoProgramMapTableWriter writer(kCodecH264); BufferWriter buffer; writer.ClearSegmentPmt(&buffer); @@ -91,8 +90,7 @@ TEST_F(ProgramMapTableWriterTest, ClearH264) { // Verify that PSI for encrypted segments after clear lead is generated // correctly. TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadH264) { - ContinuityCounter counter; - H264ProgramMapTableWriter writer(&counter); + VideoProgramMapTableWriter writer(kCodecH264); BufferWriter buffer; writer.ClearSegmentPmt(&buffer); buffer.Clear(); @@ -136,8 +134,7 @@ TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadH264) { // Verify that PMT for encrypted segments can be generated (without clear lead). TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsH264Pmt) { - ContinuityCounter counter; - H264ProgramMapTableWriter writer(&counter); + VideoProgramMapTableWriter writer(kCodecH264); BufferWriter buffer; writer.EncryptedSegmentPmt(&buffer); @@ -179,11 +176,10 @@ TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsH264Pmt) { } TEST_F(ProgramMapTableWriterTest, ClearAac) { - ContinuityCounter counter; const std::vector aac_audio_specific_config( - kAacBasicProfileExtraData, - kAacBasicProfileExtraData + arraysize(kAacBasicProfileExtraData)); - AacProgramMapTableWriter writer(aac_audio_specific_config, &counter); + std::begin(kAacBasicProfileExtraData), + std::end(kAacBasicProfileExtraData)); + AudioProgramMapTableWriter writer(kCodecAAC, aac_audio_specific_config); BufferWriter buffer; writer.ClearSegmentPmt(&buffer); @@ -222,11 +218,10 @@ TEST_F(ProgramMapTableWriterTest, ClearAac) { // Verify that PSI for encrypted segments after clear lead is generated // correctly. TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadAac) { - ContinuityCounter counter; const std::vector aac_audio_specific_config( - kAacBasicProfileExtraData, - kAacBasicProfileExtraData + arraysize(kAacBasicProfileExtraData)); - AacProgramMapTableWriter writer(aac_audio_specific_config, &counter); + std::begin(kAacBasicProfileExtraData), + std::end(kAacBasicProfileExtraData)); + AudioProgramMapTableWriter writer(kCodecAAC, aac_audio_specific_config); BufferWriter buffer; writer.ClearSegmentPmt(&buffer); @@ -283,11 +278,10 @@ TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAfterClearLeadAac) { // Verify that PMT for encrypted segments can be generated (without clear lead). TEST_F(ProgramMapTableWriterTest, EncryptedSegmentsAacPmt) { - ContinuityCounter counter; const std::vector aac_audio_specific_config( - kAacBasicProfileExtraData, - kAacBasicProfileExtraData + arraysize(kAacBasicProfileExtraData)); - AacProgramMapTableWriter writer(aac_audio_specific_config, &counter); + std::begin(kAacBasicProfileExtraData), + std::end(kAacBasicProfileExtraData)); + AudioProgramMapTableWriter writer(kCodecAAC, aac_audio_specific_config); BufferWriter buffer; writer.EncryptedSegmentPmt(&buffer); diff --git a/packager/media/formats/mp2t/ts_writer.cc b/packager/media/formats/mp2t/ts_writer.cc index da45e4f52c..ad67f2f54a 100644 --- a/packager/media/formats/mp2t/ts_writer.cc +++ b/packager/media/formats/mp2t/ts_writer.cc @@ -173,23 +173,14 @@ bool TsWriter::Initialize(const StreamInfo& stream_info) { if (stream_info.stream_type() == StreamType::kStreamVideo) { const VideoStreamInfo& video_stream_info = static_cast(stream_info); - if (video_stream_info.codec() != Codec::kCodecH264) { - LOG(ERROR) << "TsWriter cannot handle video codec " - << video_stream_info.codec() << " yet."; - return false; - } - pmt_writer_.reset(new H264ProgramMapTableWriter(&pmt_continuity_counter_)); + pmt_writer_.reset( + new VideoProgramMapTableWriter(video_stream_info.codec())); } else { DCHECK_EQ(stream_type, StreamType::kStreamAudio); const AudioStreamInfo& audio_stream_info = static_cast(stream_info); - if (audio_stream_info.codec() != Codec::kCodecAAC) { - LOG(ERROR) << "TsWriter cannot handle audio codec " - << audio_stream_info.codec() << " yet."; - return false; - } - pmt_writer_.reset(new AacProgramMapTableWriter( - audio_stream_info.codec_config(), &pmt_continuity_counter_)); + pmt_writer_.reset(new AudioProgramMapTableWriter( + audio_stream_info.codec(), audio_stream_info.codec_config())); } return true; diff --git a/packager/media/formats/mp2t/ts_writer.h b/packager/media/formats/mp2t/ts_writer.h index c4d6e105af..4efbbe9b83 100644 --- a/packager/media/formats/mp2t/ts_writer.h +++ b/packager/media/formats/mp2t/ts_writer.h @@ -65,7 +65,6 @@ class TsWriter { // True if further segments generated by this instance should be encrypted. bool encrypted_ = false; - ContinuityCounter pmt_continuity_counter_; ContinuityCounter pat_continuity_counter_; ContinuityCounter elementary_stream_continuity_counter_; diff --git a/packager/media/formats/mp2t/ts_writer_unittest.cc b/packager/media/formats/mp2t/ts_writer_unittest.cc index 67eab7a8f3..bdac3d22b8 100644 --- a/packager/media/formats/mp2t/ts_writer_unittest.cc +++ b/packager/media/formats/mp2t/ts_writer_unittest.cc @@ -58,11 +58,18 @@ const uint8_t kAacBasicProfileExtraData[] = {0x12, 0x10}; class MockProgramMapTableWriter : public ProgramMapTableWriter { public: - MockProgramMapTableWriter() {} + MockProgramMapTableWriter() : ProgramMapTableWriter(kUnknownCodec) {} ~MockProgramMapTableWriter() override {} MOCK_METHOD1(EncryptedSegmentPmt, bool(BufferWriter* writer)); MOCK_METHOD1(ClearSegmentPmt, bool(BufferWriter* writer)); + + private: + MockProgramMapTableWriter(const MockProgramMapTableWriter&) = delete; + MockProgramMapTableWriter& operator=(const MockProgramMapTableWriter&) = + delete; + + bool WriteDescriptors(BufferWriter* writer) const override { return true; } }; // This is not a real TS Packet. But is used to check that the result from the @@ -165,15 +172,6 @@ TEST_F(TsWriterTest, InitializeVideoH264) { EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); } -TEST_F(TsWriterTest, InitializeVideoNonH264) { - std::shared_ptr stream_info(new VideoStreamInfo( - kTrackId, kTimeScale, kDuration, Codec::kCodecVP9, - H26xStreamFormat::kUnSpecified, kCodecString, kExtraData, - arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, - kTrickPlayFactor, kNaluLengthSize, kLanguage, kIsEncrypted)); - EXPECT_FALSE(ts_writer_.Initialize(*stream_info)); -} - TEST_F(TsWriterTest, InitializeAudioAac) { std::shared_ptr stream_info(new AudioStreamInfo( kTrackId, kTimeScale, kDuration, kAacCodec, kCodecString, kExtraData, @@ -183,15 +181,6 @@ TEST_F(TsWriterTest, InitializeAudioAac) { EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); } -TEST_F(TsWriterTest, InitializeAudioNonAac) { - std::shared_ptr stream_info(new AudioStreamInfo( - kTrackId, kTimeScale, kDuration, Codec::kCodecOpus, kCodecString, - kExtraData, arraysize(kExtraData), kSampleBits, kNumChannels, - kSamplingFrequency, kSeekPreroll, kCodecDelay, kMaxBitrate, - kAverageBitrate, kLanguage, kIsEncrypted)); - EXPECT_FALSE(ts_writer_.Initialize(*stream_info)); -} - // Verify that PAT and PMT are correct for clear segment. // This test covers verifies the PAT, and since it doesn't change, other tests // shouldn't have to check this. @@ -305,6 +294,22 @@ TEST_F(TsWriterTest, ClearLeadH264Pmt) { kTsPacketSize)); } +TEST_F(TsWriterTest, ClearSegmentPmtFailure) { + std::unique_ptr mock_pmt_writer( + new MockProgramMapTableWriter()); + EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(Return(false)); + + std::shared_ptr stream_info(new AudioStreamInfo( + kTrackId, kTimeScale, kDuration, kAacCodec, kCodecString, + kAacBasicProfileExtraData, arraysize(kAacBasicProfileExtraData), + kSampleBits, kNumChannels, kSamplingFrequency, kSeekPreroll, kCodecDelay, + kMaxBitrate, kAverageBitrate, kLanguage, kIsEncrypted)); + EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); + + ts_writer_.SetProgramMapTableWriterForTesting(std::move(mock_pmt_writer)); + EXPECT_FALSE(ts_writer_.NewSegment(test_file_name_)); +} + // Check the encrypted segments' PMT (after clear lead). TEST_F(TsWriterTest, EncryptedSegmentsH264Pmt) { std::unique_ptr mock_pmt_writer( @@ -338,6 +343,28 @@ TEST_F(TsWriterTest, EncryptedSegmentsH264Pmt) { kTsPacketSize)); } +TEST_F(TsWriterTest, EncryptedSegmentPmtFailure) { + std::unique_ptr mock_pmt_writer( + new MockProgramMapTableWriter()); + InSequence s; + EXPECT_CALL(*mock_pmt_writer, ClearSegmentPmt(_)).WillOnce(Return(true)); + EXPECT_CALL(*mock_pmt_writer, EncryptedSegmentPmt(_)).WillOnce(Return(false)); + + std::shared_ptr stream_info(new VideoStreamInfo( + kTrackId, kTimeScale, kDuration, kH264Codec, + H26xStreamFormat::kAnnexbByteStream, kCodecString, kExtraData, + arraysize(kExtraData), kWidth, kHeight, kPixelWidth, kPixelHeight, + kTrickPlayFactor, kNaluLengthSize, kLanguage, kIsEncrypted)); + EXPECT_TRUE(ts_writer_.Initialize(*stream_info)); + + ts_writer_.SetProgramMapTableWriterForTesting(std::move(mock_pmt_writer)); + EXPECT_TRUE(ts_writer_.NewSegment(test_file_name_)); + EXPECT_TRUE(ts_writer_.FinalizeSegment()); + + ts_writer_.SignalEncrypted(); + EXPECT_FALSE(ts_writer_.NewSegment(test_file_name_)); +} + // Same as ClearLeadH264Pmt but for AAC. TEST_F(TsWriterTest, ClearLeadAacPmt) { std::unique_ptr mock_pmt_writer(