7 #include "packager/media/formats/mp2t/ts_segmenter.h"
11 #include "packager/media/base/aes_encryptor.h"
12 #include "packager/media/base/key_source.h"
13 #include "packager/media/base/muxer_util.h"
14 #include "packager/media/base/status.h"
15 #include "packager/media/base/video_stream_info.h"
16 #include "packager/media/event/muxer_listener.h"
17 #include "packager/media/event/progress_listener.h"
24 const double kTsTimescale = 90000;
28 : muxer_options_(options),
32 TsSegmenter::~TsSegmenter() {}
36 uint32_t max_sd_pixels,
37 uint32_t max_hd_pixels,
38 uint32_t max_uhd1_pixels,
39 double clear_lead_in_seconds) {
41 return Status(error::MUXER_FAILURE,
"Segment template not specified.");
42 if (!ts_writer_->Initialize(stream_info))
43 return Status(error::MUXER_FAILURE,
"Failed to initialize TsWriter.");
44 if (!pes_packet_generator_->Initialize(stream_info)) {
45 return Status(error::MUXER_FAILURE,
46 "Failed to initialize PesPacketGenerator.");
49 if (encryption_key_source) {
50 std::unique_ptr<EncryptionKey> encryption_key(
new EncryptionKey());
51 const KeySource::TrackType type =
52 GetTrackTypeForEncryption(stream_info, max_sd_pixels,
53 max_hd_pixels, max_uhd1_pixels);
54 Status status = encryption_key_source->
GetKey(type, encryption_key.get());
56 if (encryption_key->iv.empty()) {
58 return Status(error::INTERNAL_ERROR,
"Failed to generate random iv.");
64 encryption_key_ = std::move(encryption_key);
65 clear_lead_in_seconds_ = clear_lead_in_seconds;
69 const bool kIsInitialEncryptionInfo =
true;
71 kIsInitialEncryptionInfo, FOURCC_cbcs, encryption_key_->key_id,
72 encryption_key_->iv, encryption_key_->key_system_info);
75 status = NotifyEncrypted();
80 timescale_scale_ = kTsTimescale / stream_info.time_scale();
89 if (!ts_writer_file_opened_ && !sample->is_key_frame())
90 LOG(WARNING) <<
"A segment will start with a non key frame.";
92 if (!pes_packet_generator_->PushSample(sample)) {
93 return Status(error::MUXER_FAILURE,
94 "Failed to add sample to PesPacketGenerator.");
96 return WritePesPacketsToFile();
100 ts_writer_ = std::move(writer);
104 std::unique_ptr<PesPacketGenerator> generator) {
105 pes_packet_generator_ = std::move(generator);
109 ts_writer_file_opened_ = value;
112 Status TsSegmenter::OpenNewSegmentIfClosed(uint32_t next_pts) {
113 if (ts_writer_file_opened_)
115 const std::string segment_name =
117 segment_number_++, muxer_options_.
bandwidth);
118 if (!ts_writer_->NewSegment(segment_name))
119 return Status(error::MUXER_FAILURE,
"Failed to initilize TsPacketWriter.");
120 current_segment_path_ = segment_name;
121 ts_writer_file_opened_ =
true;
125 Status TsSegmenter::WritePesPacketsToFile() {
126 while (pes_packet_generator_->NumberOfReadyPesPackets() > 0u) {
127 std::unique_ptr<PesPacket> pes_packet =
128 pes_packet_generator_->GetNextPesPacket();
130 Status status = OpenNewSegmentIfClosed(pes_packet->pts());
134 if (!ts_writer_->AddPesPacket(std::move(pes_packet)))
135 return Status(error::MUXER_FAILURE,
"Failed to add PES packet.");
142 if (!pes_packet_generator_->Flush()) {
143 return Status(error::MUXER_FAILURE,
144 "Failed to flush PesPacketGenerator.");
146 Status status = WritePesPacketsToFile();
152 if (ts_writer_file_opened_) {
153 if (!ts_writer_->FinalizeSegment()) {
154 return Status(error::MUXER_FAILURE,
"Failed to finalize TsWriter.");
157 const int64_t file_size =
160 start_timestamp * timescale_scale_,
161 duration * timescale_scale_, file_size);
163 ts_writer_file_opened_ =
false;
164 total_duration_in_seconds_ += duration * timescale_scale_ / kTsTimescale;
166 current_segment_path_.clear();
167 return NotifyEncrypted();
170 Status TsSegmenter::NotifyEncrypted() {
171 if (encryption_key_ && total_duration_in_seconds_ >= clear_lead_in_seconds_) {
175 if (!pes_packet_generator_->SetEncryptionKey(std::move(encryption_key_)))
176 return Status(error::INTERNAL_ERROR,
"Failed to set encryption key.");
177 ts_writer_->SignalEncrypted();