7 #include "packager/media/formats/mp2t/ts_writer.h"
11 #include "packager/base/logging.h"
12 #include "packager/media/base/audio_stream_info.h"
13 #include "packager/media/base/buffer_writer.h"
14 #include "packager/media/base/stream_info.h"
15 #include "packager/media/base/video_stream_info.h"
17 namespace edash_packager {
28 kElementaryPid = 0x50,
32 const uint8_t kProgramNumber = 0x01;
34 const uint8_t kStreamTypeH264 = 0x1B;
35 const uint8_t kStreamTypeAdtsAac = 0x0F;
41 const uint8_t kProgramAssociationTableId = 0x00;
42 const uint8_t kProgramMapTableId = 0x02;
49 const uint8_t kPat[] = {
51 kProgramAssociationTableId,
63 0xF9, 0x62, 0xF5, 0x8B,
68 const uint8_t kPmtH264[] = {
81 kStreamTypeH264, 0xE0, kElementaryPid,
84 0x43, 0x49, 0x97, 0xBE,
87 const uint8_t kPmtAac[] = {
100 kStreamTypeAdtsAac, 0xE0, kElementaryPid,
103 0xE0, 0x6F, 0x1A, 0x31,
106 const bool kHasPcr =
true;
107 const bool kPayloadUnitStartIndicator =
true;
109 const uint8_t kSyncByte = 0x47;
110 const int kPcrFieldsSize = 6;
114 const int kTsPacketHeaderSize = 4;
115 const int kTsPacketSize = 188;
116 const int kTsPacketMaximumPayloadSize =
117 kTsPacketSize - kTsPacketHeaderSize;
119 const size_t kMaxPesPacketLengthValue = 0xFFFF;
122 const uint8_t kPaddingBytes[] = {
123 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
124 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
125 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
126 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
127 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
128 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
129 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
130 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
131 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
132 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
133 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
134 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
135 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
137 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
138 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
139 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
140 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
141 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
142 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
143 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
144 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
145 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
146 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
148 static_assert(arraysize(kPaddingBytes) >= kTsPacketMaximumPayloadSize,
149 "Padding array is not big enough.");
154 void WriteAdaptationField(
bool has_pcr,
156 size_t remaining_data_size,
157 BufferWriter* writer) {
159 if (!has_pcr && remaining_data_size == kTsPacketMaximumPayloadSize - 1) {
160 writer->AppendInt(static_cast<uint8_t>(0));
165 const int kAdaptationFieldLengthSize = 1;
168 const int kAdaptationFieldHeaderSize = 1;
169 int adaptation_field_length =
170 kAdaptationFieldHeaderSize + (has_pcr ? kPcrFieldsSize : 0);
171 if (remaining_data_size < kTsPacketMaximumPayloadSize) {
172 const int current_ts_size = kTsPacketHeaderSize + remaining_data_size +
173 adaptation_field_length +
174 kAdaptationFieldLengthSize;
175 if (current_ts_size < kTsPacketSize) {
176 adaptation_field_length += kTsPacketSize - current_ts_size;
180 writer->AppendInt(static_cast<uint8_t>(adaptation_field_length));
181 int remaining_bytes = adaptation_field_length;
182 writer->AppendInt(static_cast<uint8_t>(
184 static_cast<uint8_t>(has_pcr) << 4));
185 remaining_bytes -= 1;
189 const uint32_t most_significant_32bits_pcr =
190 static_cast<uint32_t
>(pcr_base >> 1);
191 const uint16_t pcr_last_bit_reserved_and_pcr_extension =
192 ((pcr_base & 1) << 15);
193 writer->AppendInt(most_significant_32bits_pcr);
194 writer->AppendInt(pcr_last_bit_reserved_and_pcr_extension);
195 remaining_bytes -= kPcrFieldsSize;
197 DCHECK_GE(remaining_bytes, 0);
198 if (remaining_bytes == 0)
201 DCHECK_GE(static_cast<int>(arraysize(kPaddingBytes)), remaining_bytes);
202 writer->AppendArray(kPaddingBytes, remaining_bytes);
207 void WritePayloadToBufferWriter(
const uint8_t* payload,
209 bool payload_unit_start_indicator,
213 ContinuityCounter* continuity_counter,
214 BufferWriter* writer) {
215 size_t payload_bytes_written = 0;
218 const bool must_write_adaptation_header = has_pcr;
219 const size_t bytes_left = payload_size - payload_bytes_written;
220 const bool has_adaptation_field = must_write_adaptation_header ||
221 bytes_left < kTsPacketMaximumPayloadSize;
223 writer->AppendInt(kSyncByte);
224 writer->AppendInt(static_cast<uint16_t>(
226 static_cast<int>(payload_unit_start_indicator) << 14 | pid));
228 const uint8_t adaptation_field_control =
229 ((has_adaptation_field ? 1 : 0) << 1) | ((bytes_left != 0) ? 1 : 0);
231 writer->AppendInt(static_cast<uint8_t>(adaptation_field_control << 4 |
232 continuity_counter->GetNext()));
234 if (has_adaptation_field) {
235 const size_t before = writer->Size();
236 WriteAdaptationField(has_pcr, pcr_base, bytes_left, writer);
237 const size_t bytes_for_adaptation_field = writer->Size() - before;
239 const int write_bytes =
240 kTsPacketMaximumPayloadSize - bytes_for_adaptation_field;
241 writer->AppendArray(payload + payload_bytes_written, write_bytes);
242 payload_bytes_written += write_bytes;
244 writer->AppendArray(payload + payload_bytes_written,
245 kTsPacketMaximumPayloadSize);
246 payload_bytes_written += kTsPacketMaximumPayloadSize;
251 payload_unit_start_indicator =
false;
252 }
while (payload_bytes_written < payload_size);
255 void WritePatPmtToBuffer(
const uint8_t* data,
258 ContinuityCounter* continuity_counter,
259 BufferWriter* writer) {
260 WritePayloadToBufferWriter(data, data_size, kPayloadUnitStartIndicator, pid,
261 !kHasPcr, 0, continuity_counter, writer);
264 void WritePatToBuffer(
const uint8_t* pat,
266 ContinuityCounter* continuity_counter,
267 BufferWriter* writer) {
268 const int kPatPid = 0;
269 WritePatPmtToBuffer(pat, pat_size, kPatPid, continuity_counter, writer);
272 void WritePmtToBuffer(
const uint8_t* pmt,
274 ContinuityCounter* continuity_counter,
275 BufferWriter* writer) {
276 WritePatPmtToBuffer(pmt, pmt_size, kPmtPid, continuity_counter, writer);
280 void WritePtsOrDts(uint8_t leading_bits,
282 BufferWriter* writer) {
285 leading_bits << 4 | (((pts_or_dts >> 30) & 0x07) << 1) | 1;
287 uint8_t second_byte = (pts_or_dts >> 22) & 0xFF;
289 uint8_t third_byte = (((pts_or_dts >> 15) & 0x7F) << 1) | 1;
291 uint8_t fourth_byte = ((pts_or_dts >> 7) & 0xFF);
293 uint8_t fifth_byte = ((pts_or_dts & 0x7F) << 1) | 1;
294 writer->AppendInt(first_byte);
295 writer->AppendInt(second_byte);
296 writer->AppendInt(third_byte);
297 writer->AppendInt(fourth_byte);
298 writer->AppendInt(fifth_byte);
301 bool WritePesToFile(
const PesPacket& pes,
302 ContinuityCounter* continuity_counter,
305 const int kAdaptationFieldLengthSize = 1;
307 const int kAdaptationFieldHeaderSize = 1;
308 const int kPcrFieldSize = 6;
309 const int kTsPacketMaxPayloadWithPcr =
310 kTsPacketMaximumPayloadSize - kAdaptationFieldLengthSize -
311 kAdaptationFieldHeaderSize - kPcrFieldSize;
312 const uint64_t pcr_base = pes.has_dts() ? pes.dts() : pes.pts();
313 const int pid = kElementaryPid;
316 BufferWriter pes_header_writer;
319 pes_header_writer.AppendInt(static_cast<uint8_t>(0x80));
320 pes_header_writer.AppendInt(
321 static_cast<uint8_t>(static_cast<int>(pes.has_pts()) << 7 |
322 static_cast<int>(pes.has_dts()) << 6
325 uint8_t pes_header_data_length = 0;
327 pes_header_data_length += 5;
329 pes_header_data_length += 5;
330 pes_header_writer.AppendInt(pes_header_data_length);
332 if (pes.has_pts() && pes.has_dts()) {
333 WritePtsOrDts(0x03, pes.pts(), &pes_header_writer);
334 WritePtsOrDts(0x01, pes.dts(), &pes_header_writer);
335 }
else if (pes.has_pts()) {
336 WritePtsOrDts(0x02, pes.pts(), &pes_header_writer);
341 BufferWriter first_ts_packet_buffer(kTsPacketSize);
342 first_ts_packet_buffer.AppendNBytes(static_cast<uint64_t>(0x000001), 3);
343 first_ts_packet_buffer.AppendInt(pes.stream_id());
344 const size_t pes_packet_length = pes.data().size() + pes_header_writer.Size();
345 first_ts_packet_buffer.AppendInt(static_cast<uint16_t>(
346 pes_packet_length > kMaxPesPacketLengthValue ? 0 : pes_packet_length));
347 first_ts_packet_buffer.AppendBuffer(pes_header_writer);
349 const int available_payload =
350 kTsPacketMaxPayloadWithPcr - first_ts_packet_buffer.Size();
351 const int bytes_consumed =
352 std::min(static_cast<int>(pes.data().size()), available_payload);
353 first_ts_packet_buffer.AppendArray(pes.data().data(), bytes_consumed);
355 BufferWriter output_writer;
356 WritePayloadToBufferWriter(first_ts_packet_buffer.Buffer(),
357 first_ts_packet_buffer.Size(),
358 kPayloadUnitStartIndicator, pid, kHasPcr, pcr_base,
359 continuity_counter, &output_writer);
361 const size_t remaining_pes_data_size = pes.data().size() - bytes_consumed;
362 if (remaining_pes_data_size > 0) {
363 WritePayloadToBufferWriter(pes.data().data() + bytes_consumed,
364 remaining_pes_data_size,
365 !kPayloadUnitStartIndicator, pid, !kHasPcr, 0,
366 continuity_counter, &output_writer);
368 return output_writer.WriteToFile(file).ok();
373 ContinuityCounter::ContinuityCounter() {}
374 ContinuityCounter::~ContinuityCounter() {}
383 TsWriter::TsWriter() {}
384 TsWriter::~TsWriter() {}
389 time_scale_ = stream_info.time_scale();
390 if (time_scale_ == 0) {
391 LOG(ERROR) <<
"Timescale is 0.";
394 const StreamType stream_type = stream_info.stream_type();
395 if (stream_type != StreamType::kStreamVideo &&
396 stream_type != StreamType::kStreamAudio) {
397 LOG(ERROR) <<
"TsWriter cannot handle stream type " << stream_type
402 const uint8_t* pmt =
nullptr;
403 size_t pmt_size = 0u;
404 if (stream_info.stream_type() == StreamType::kStreamVideo) {
407 if (video_stream_info.codec() != VideoCodec::kCodecH264) {
408 LOG(ERROR) <<
"TsWriter cannot handle video codec "
409 << video_stream_info.codec() <<
" yet.";
413 pmt_size = arraysize(kPmtH264);
415 DCHECK_EQ(stream_type, StreamType::kStreamAudio);
418 if (audio_stream_info.codec() != AudioCodec::kCodecAAC) {
419 LOG(ERROR) <<
"TsWriter cannot handle audio codec "
420 << audio_stream_info.codec() <<
" yet.";
424 pmt_size = arraysize(kPmtAac);
427 DCHECK_GT(pmt_size, 0u);
431 WritePatToBuffer(kPat, arraysize(kPat), &pat_continuity_counter_,
433 WritePmtToBuffer(pmt, pmt_size, &pmt_continuity_counter_, &psi_writer);
435 psi_writer.SwapBuffer(&psi_ts_packets_);
440 DCHECK(!psi_ts_packets_.empty());
442 LOG(ERROR) <<
"File " << current_file_->file_name() <<
" still open.";
445 current_file_.reset(
File::Open(file_name.c_str(),
"w"));
446 if (!current_file_) {
447 LOG(ERROR) <<
"Failed to open file " << file_name;
453 psi_writer.AppendVector(psi_ts_packets_);
454 if (!psi_writer.WriteToFile(current_file_.get()).ok()) {
455 LOG(ERROR) <<
"Failed to write PSI to file.";
463 return current_file_.release()->Close();
467 if (time_scale_ == 0) {
468 LOG(ERROR) <<
"Timescale is 0.";
471 DCHECK(current_file_);
472 if (!WritePesToFile(*pes_packet, &elementary_stream_continuity_counter_,
473 current_file_.get())) {
474 LOG(ERROR) <<
"Failed to write pes to file.";