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 double clear_lead_in_seconds) {
39 return Status(error::MUXER_FAILURE,
"Segment template not specified.");
40 if (!ts_writer_->Initialize(stream_info,
false))
41 return Status(error::MUXER_FAILURE,
"Failed to initialize TsWriter.");
42 if (!pes_packet_generator_->Initialize(stream_info)) {
43 return Status(error::MUXER_FAILURE,
44 "Failed to initialize PesPacketGenerator.");
47 if (encryption_key_source) {
48 scoped_ptr<EncryptionKey> encryption_key(
new EncryptionKey());
49 const KeySource::TrackType type =
50 GetTrackTypeForEncryption(stream_info, max_sd_pixels);
51 Status status = encryption_key_source->
GetKey(type, encryption_key.get());
53 if (encryption_key->iv.empty()) {
55 return Status(error::INTERNAL_ERROR,
"Failed to generate random iv.");
60 encryption_key_ = encryption_key.Pass();
61 clear_lead_in_seconds_ = clear_lead_in_seconds;
62 status = NotifyEncrypted();
67 timescale_scale_ = kTsTimescale / stream_info.time_scale();
79 const bool passed_segment_duration =
81 if (sample->is_key_frame() && passed_segment_duration) {
87 if (!ts_writer_file_opened_ && !sample->is_key_frame())
88 LOG(WARNING) <<
"A segment will start with a non key frame.";
90 if (!pes_packet_generator_->PushSample(sample)) {
91 return Status(error::MUXER_FAILURE,
92 "Failed to add sample to PesPacketGenerator.");
95 const double scaled_sample_duration = sample->duration() * timescale_scale_;
96 current_segment_total_sample_duration_ +=
97 scaled_sample_duration / kTsTimescale;
99 return WritePesPacketsToFile();
103 ts_writer_ = writer.Pass();
107 scoped_ptr<PesPacketGenerator> generator) {
108 pes_packet_generator_ = generator.Pass();
112 ts_writer_file_opened_ = value;
115 Status TsSegmenter::OpenNewSegmentIfClosed(uint32_t next_pts) {
116 if (ts_writer_file_opened_)
118 const std::string segment_name =
120 segment_number_++, muxer_options_.
bandwidth);
121 if (!ts_writer_->NewSegment(segment_name))
122 return Status(error::MUXER_FAILURE,
"Failed to initilize TsPacketWriter.");
123 current_segment_start_time_ = next_pts;
124 current_segment_path_ = segment_name;
125 ts_writer_file_opened_ =
true;
129 Status TsSegmenter::WritePesPacketsToFile() {
130 while (pes_packet_generator_->NumberOfReadyPesPackets() > 0u) {
131 scoped_ptr<PesPacket> pes_packet =
132 pes_packet_generator_->GetNextPesPacket();
134 Status status = OpenNewSegmentIfClosed(pes_packet->pts());
138 if (!ts_writer_->AddPesPacket(pes_packet.Pass()))
139 return Status(error::MUXER_FAILURE,
"Failed to add PES packet.");
144 Status TsSegmenter::Flush() {
145 if (!pes_packet_generator_->Flush()) {
146 return Status(error::MUXER_FAILURE,
147 "Failed to flush PesPacketGenerator.");
149 Status status = WritePesPacketsToFile();
155 if (ts_writer_file_opened_) {
156 if (!ts_writer_->FinalizeSegment()) {
157 return Status(error::MUXER_FAILURE,
"Failed to finalize TsWriter.");
160 const int64_t file_size =
163 current_segment_path_, current_segment_start_time_,
164 current_segment_total_sample_duration_ * kTsTimescale, file_size);
166 ts_writer_file_opened_ =
false;
167 total_duration_in_seconds_ += current_segment_total_sample_duration_;
169 current_segment_total_sample_duration_ = 0.0;
170 current_segment_start_time_ = 0;
171 current_segment_path_.clear();
172 return NotifyEncrypted();
175 Status TsSegmenter::NotifyEncrypted() {
176 if (encryption_key_ && total_duration_in_seconds_ >= clear_lead_in_seconds_) {
179 const bool kIsInitialEncryptionInfo =
true;
181 kIsInitialEncryptionInfo, FOURCC_cbcs, encryption_key_->key_id,
182 encryption_key_->iv, encryption_key_->key_system_info);
185 if (!pes_packet_generator_->SetEncryptionKey(encryption_key_.Pass()))
186 return Status(error::INTERNAL_ERROR,
"Failed to set encryption key.");
187 ts_writer_->SignalEncypted();