2
* Copyright 2012, The Android Open Source Project
3
* Copyright (C) 2016 Canonical, Ltd.
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
* you may not use this file except in compliance with the License.
7
* You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
19
* NOTE: The implementation is based on the Android implementation for WiFi
20
* display support in frameworks/av/libstagefright/wifi-display/TSPacketizer.cpp
21
* and is adjusted for our needs.
24
#include <arpa/inet.h>
27
#include "mcs/utils.h"
28
#include "mcs/logger.h"
30
#include "mcs/video/utils.h"
32
#include "mcs/streaming/mpegtspacketizer.h"
35
static constexpr uint8_t kH264NALPrefix[] = { 0x00, 0x00, 0x00, 0x01 };
37
// One byte for each profile, level and constraint
38
static constexpr uint32_t kCSDSize{3};
40
// See WiFi Display spec version 1.1 chapter D.4.2 PAT/PMT
41
static constexpr unsigned int kPIDofPMT{0x100};
42
static constexpr unsigned int kPIDofPCR{0x1000};
43
static constexpr unsigned int kVideoPIDStart{0x1011};
45
static constexpr unsigned int kH264StreamType{0x1b};
46
static constexpr unsigned int kVideoStreamIdStart{0xe0};
47
static constexpr unsigned int kVideoStreamIdStop{0xef};
48
static constexpr unsigned int kAVCVideoDescriptorTag{40};
49
static constexpr unsigned int kAVCTimingAndHRDDescriptor{42};
55
struct MPEGTSPacketizer::Track {
56
typedef std::shared_ptr<Track> Ptr;
58
static Ptr Create(const TrackFormat &format, unsigned int pid,
59
unsigned int stream_type, unsigned int stream_id);
61
unsigned int NextContinuityCounter();
63
bool IsAudio() const { return mcs::Utils::StringStartsWith(format.mime, "audio/"); }
64
bool IsVideo() const { return mcs::Utils::StringStartsWith(format.mime, "video/"); }
66
bool IsH264() const { return format.mime == "video/avc"; }
68
void SubmitCSD(const mcs::video::Buffer::Ptr &buffer);
70
mcs::video::Buffer::Ptr PrependCSD(const mcs::video::Buffer::Ptr &buffer) const;
74
Track(const TrackFormat &format, unsigned int pid,
75
unsigned int stream_type, unsigned int stream_id);
79
unsigned int stream_type;
80
unsigned int stream_id;
81
unsigned int continuity_counter;
83
std::vector<mcs::video::Buffer::Ptr> csd;
84
std::vector<mcs::video::Buffer::Ptr> descriptors;
87
MPEGTSPacketizer::Track::Ptr MPEGTSPacketizer::Track::Create(const TrackFormat &format, unsigned int pid,
88
unsigned int stream_type, unsigned int stream_id) {
89
return std::shared_ptr<Track>(new Track(format, pid, stream_type, stream_id));
92
MPEGTSPacketizer::Track::Track(const TrackFormat &format, unsigned int pid,
93
unsigned int stream_type, unsigned int stream_id) :
96
stream_type(stream_type),
98
continuity_counter(0),
102
unsigned int MPEGTSPacketizer::Track::NextContinuityCounter() {
103
unsigned int prev = continuity_counter;
104
if (++continuity_counter == 16)
105
continuity_counter = 0;
109
void MPEGTSPacketizer::Track::SubmitCSD(const video::Buffer::Ptr &buffer) {
113
const uint8_t *data = buffer->Data();
114
size_t size = buffer->Length();
116
const uint8_t *nal_start;
119
while (mcs::video::GetNextNALUnit(&data, &size, &nal_start, &nal_size, true)) {
120
auto current = mcs::video::Buffer::Create(nal_size + sizeof(kH264NALPrefix));
122
::memcpy(current->Data(), kH264NALPrefix, sizeof(kH264NALPrefix));
123
::memcpy(current->Data() + sizeof(kH264NALPrefix), nal_start, nal_size);
125
csd.push_back(current);
129
mcs::video::Buffer::Ptr MPEGTSPacketizer::Track::PrependCSD(const mcs::video::Buffer::Ptr &buffer) const {
131
for (auto current : csd)
132
size += current->Length();
134
auto new_buffer = mcs::video::Buffer::Create(buffer->Length() + size);
136
for (auto current : csd) {
137
::memcpy(new_buffer->Data() + offset, current->Data(), current->Length());
138
offset += current->Length();
141
::memcpy(new_buffer->Data() + offset, buffer->Data(), buffer->Length());
146
void MPEGTSPacketizer::Track::Finalize() {
156
// AVC video descriptor (40)
157
const auto descriptor = mcs::video::Buffer::Create(6);
158
uint8_t *data = descriptor->Data();
159
data[0] = kAVCVideoDescriptorTag; // descriptor_tag
160
data[1] = 4; // descriptor_length
162
if (csd.size() > 0) {
163
// Seems to be a conventation that the first NAL we get
164
// submitted as part of the codec-specific data is the
166
auto sps = csd.at(0);
167
// We skip the first four bytes (NAL preamble) and then
168
// just copy profile/constraint/level settings (one byte
170
memcpy(&data[2], sps->Data() + sizeof(kH264NALPrefix), kCSDSize);
173
data[2] = format.profile_idc; // profile_idc
174
data[3] = format.constraint_set; // constraint_set*
175
data[4] = format.level_idc; // level_idc
178
// AVC_still_present=0, AVC_24_hour_picture_flag=0, reserved
181
descriptors.push_back(descriptor);
184
// AVC timing and HRD descriptor (42)
186
auto descriptor = mcs::video::Buffer::Create(4);
187
uint8_t *data = descriptor->Data();
188
data[0] = kAVCTimingAndHRDDescriptor; // descriptor_tag
189
data[1] = 2; // descriptor_length
191
// hrd_management_valid_flag = 0
192
// reserved = 111111b
193
// picture_and_timing_info_present = 0
196
// fixed_frame_rate_flag = 0
197
// temporal_poc_flag = 0
198
// picture_to_display_conversion_flag = 0
202
descriptors.push_back(descriptor);
208
Packetizer::Ptr MPEGTSPacketizer::Create() {
209
return std::shared_ptr<Packetizer>(new MPEGTSPacketizer);
212
MPEGTSPacketizer::MPEGTSPacketizer() :
213
pat_continuity_counter_(0),
214
pmt_continuity_counter_(0) {
218
MPEGTSPacketizer::~MPEGTSPacketizer() {
221
MPEGTSPacketizer::TrackId MPEGTSPacketizer::AddTrack(const TrackFormat &format) {
222
auto is_video = mcs::Utils::StringStartsWith(format.mime, "video/");
225
MCS_ERROR("Audio tracks for MPEGTS are currently not supported");
229
if (format.mime != "video/avc") {
230
MCS_ERROR("Video formats other than video/avc are not supported");
234
// First PID as per WiFi Display spec
235
unsigned int pidstart = kVideoPIDStart;
236
unsigned int stream_type = kH264StreamType;
237
unsigned int stream_id_start = kVideoStreamIdStart;
238
unsigned int stream_id_stop = kVideoStreamIdStop;
240
unsigned int num_same_tracks = 0;
241
unsigned int pid = pidstart;
243
for (auto track : tracks_) {
244
if (track->stream_type == stream_type)
247
if (track->IsAudio() || track->IsVideo())
251
unsigned int stream_id = stream_id_start + num_same_tracks;
252
if (stream_id > stream_id_stop) {
253
MCS_ERROR("All stream ids are in use");
257
auto track = Track::Create(format, pid, stream_type, stream_id);
258
tracks_.push_back(track);
260
return tracks_.size() - 1;
263
void MPEGTSPacketizer::SubmitCSD(TrackId track_index, const video::Buffer::Ptr &buffer) {
264
if (track_index > tracks_.size() -1)
267
auto track = tracks_.at(track_index);
268
track->SubmitCSD(buffer);
271
bool MPEGTSPacketizer::Packetize(TrackId track_index, const video::Buffer::Ptr &_access_unit,
272
video::Buffer::Ptr *packets, int flags) {
273
size_t numStuffingBytes = 0;
274
const uint8_t *PES_private_data = nullptr;
275
size_t PES_private_data_len = 0;
276
mcs::video::Buffer::Ptr access_unit = _access_unit;
277
int64_t timeUs = access_unit->Timestamp();
281
if (track_index > tracks_.size() - 1) {
282
MCS_ERROR("Invalid track index %d supplied", track_index);
286
auto track = tracks_.at(track_index);
288
if (track->IsH264() && (flags & Flags::kPrependSPSandPPStoIDRFrames)
289
&& mcs::video::DoesBufferContainIDRFrame(access_unit)) {
290
// prepend codec specific data, i.e. SPS and PPS.
291
access_unit = track->PrependCSD(access_unit);
295
// transport_error_indicator = b0
296
// payload_unit_start_indicator = b1
297
// transport_priority = b0
299
// transport_scrambling_control = b00
300
// adaptation_field_control = b??
301
// continuity_counter = b????
302
// -- payload follows
303
// packet_startcode_prefix = 0x000001
305
// PES_packet_length = 0x????
307
// PES_scrambling_control = b00
309
// data_alignment_indicator = b1
311
// original_or_copy = b0
312
// PTS_DTS_flags = b10 (PTS only)
315
// DSM_trick_mode_flag = b0
316
// additional_copy_info_flag = b0
318
// PES_extension_flag = b0
319
// PES_header_data_length = 0x05
320
// reserved = b0010 (PTS)
321
// PTS[32..30] = b???
323
// PTS[29..15] = b??? ???? ???? ???? (15 bits)
325
// PTS[14..0] = b??? ???? ???? ???? (15 bits)
327
// the first fragment of "buffer" follows
329
// Each transport packet (except for the last one contributing to the PES
330
// payload) must contain a multiple of 16 bytes of payload per HDCP spec.
331
bool alignPayload = false;
334
a) The very first PES transport stream packet contains
338
14 bytes of static PES header
339
PES_private_data_len + 1 bytes (only if PES_private_data_len > 0)
340
numStuffingBytes bytes
342
followed by the payload
344
b) Subsequent PES transport stream packets contain
349
followed by the payload
352
size_t PES_packet_length = access_unit->Length() + 8 + numStuffingBytes;
353
if (PES_private_data_len > 0)
354
PES_packet_length += PES_private_data_len + 1;
356
size_t numTSPackets = 1;
359
// Make sure the PES header fits into a single TS packet:
360
size_t PES_header_size = 14 + numStuffingBytes;
361
if (PES_private_data_len > 0) {
362
PES_header_size += PES_private_data_len + 1;
365
if (PES_header_size > 188u - 4u)
366
MCS_FATAL("Invalid header size");
368
size_t sizeAvailableForPayload = 188 - 4 - PES_header_size;
369
size_t numBytesOfPayload = access_unit->Length();
371
if (numBytesOfPayload > sizeAvailableForPayload) {
372
numBytesOfPayload = sizeAvailableForPayload;
374
if (alignPayload && numBytesOfPayload > 16) {
375
numBytesOfPayload -= (numBytesOfPayload % 16);
379
size_t numBytesOfPayloadRemaining = access_unit->Length() - numBytesOfPayload;
381
// This is how many bytes of payload each subsequent TS packet
382
// can contain at most.
383
sizeAvailableForPayload = 188 - 4;
384
size_t sizeAvailableForAlignedPayload = sizeAvailableForPayload;
386
// We're only going to use a subset of the available space
387
// since we need to make each fragment a multiple of 16 in size.
388
sizeAvailableForAlignedPayload -=
389
(sizeAvailableForAlignedPayload % 16);
392
size_t numFullTSPackets =
393
numBytesOfPayloadRemaining / sizeAvailableForAlignedPayload;
395
numTSPackets += numFullTSPackets;
397
numBytesOfPayloadRemaining -=
398
numFullTSPackets * sizeAvailableForAlignedPayload;
400
// numBytesOfPayloadRemaining < sizeAvailableForAlignedPayload
401
if (numFullTSPackets == 0 && numBytesOfPayloadRemaining > 0) {
402
// There wasn't enough payload left to form a full aligned payload,
403
// the last packet doesn't have to be aligned.
405
} else if (numFullTSPackets > 0
406
&& numBytesOfPayloadRemaining
407
+ sizeAvailableForAlignedPayload > sizeAvailableForPayload) {
408
// The last packet emitted had a full aligned payload and together
409
// with the bytes remaining does exceed the unaligned payload
410
// size, so we need another packet.
415
if (flags & Flags::kEmitPATandPMT)
418
if (flags & Flags::kEmitPCR)
421
auto buffer = mcs::video::Buffer::Create(numTSPackets * 188);
422
buffer->SetTimestamp(access_unit->Timestamp());
424
uint8_t *packetDataStart = buffer->Data();
426
if (flags & Flags::kEmitPATandPMT) {
427
// Program Association Table (PAT):
429
// transport_error_indicator = b0
430
// payload_unit_start_indicator = b1
431
// transport_priority = b0
432
// PID = b0000000000000 (13 bits)
433
// transport_scrambling_control = b00
434
// adaptation_field_control = b01 (no adaptation field, payload only)
435
// continuity_counter = b????
437
// --- payload follows
439
// section_syntax_indicator = b1
442
// section_length = 0x00d
443
// transport_stream_id = 0x0000
445
// version_number = b00001
446
// current_next_indicator = b1
447
// section_number = 0x00
448
// last_section_number = 0x00
449
// one program follows:
450
// program_number = 0x0001
452
// program_map_PID = kpidPMT (13 bits!)
455
if (++pat_continuity_counter_ == 16)
456
pat_continuity_counter_ = 0;
458
uint8_t *ptr = packetDataStart;
462
*ptr++ = 0x10 | pat_continuity_counter_;
465
uint8_t *crcDataStart = ptr;
476
*ptr++ = 0xe0 | (kPIDofPMT >> 8);
477
*ptr++ = kPIDofPMT & 0xff;
479
if (ptr - crcDataStart != 12)
480
MCS_FATAL("Invalid position for ptr");
482
uint32_t crc = ::htonl(CalcCrc32(crcDataStart, ptr - crcDataStart));
483
::memcpy(ptr, &crc, 4);
486
size_t sizeLeft = packetDataStart + 188 - ptr;
487
::memset(ptr, 0xff, sizeLeft);
489
packetDataStart += 188;
491
// Program Map (PMT):
493
// transport_error_indicator = b0
494
// payload_unit_start_indicator = b1
495
// transport_priority = b0
496
// PID = kpidPMT (13 bits)
497
// transport_scrambling_control = b00
498
// adaptation_field_control = b01 (no adaptation field, payload only)
499
// continuity_counter = b????
501
// -- payload follows
503
// section_syntax_indicator = b1
506
// section_length = 0x???
507
// program_number = 0x0001
509
// version_number = b00001
510
// current_next_indicator = b1
511
// section_number = 0x00
512
// last_section_number = 0x00
514
// PCR_PID = kPCR_PID (13 bits)
516
// program_info_length = 0x???
517
// program_info_descriptors follow
518
// one or more elementary stream descriptions follow:
519
// stream_type = 0x??
521
// elementary_PID = b? ???? ???? ???? (13 bits)
523
// ES_info_length = 0x000
526
if (++pmt_continuity_counter_ == 16)
527
pmt_continuity_counter_ = 0;
529
ptr = packetDataStart;
532
*ptr++ = 0x40 | (kPIDofPMT >> 8);
533
*ptr++ = kPIDofPMT & 0xff;
534
*ptr++ = 0x10 | pmt_continuity_counter_;
540
*ptr++ = 0x00; // section_length to be filled in below.
548
*ptr++ = 0xe0 | (kPIDofPCR >> 8);
549
*ptr++ = kPIDofPCR & 0xff;
551
size_t program_info_length = 0;
552
for (auto descriptor : program_info_descriptors_)
553
program_info_length += descriptor->Length();
555
if(program_info_length >= 0x400)
556
MCS_FATAL("Invalid length for program info");
558
*ptr++ = 0xf0 | (program_info_length >> 8);
559
*ptr++ = (program_info_length & 0xff);
561
for (auto descriptor : program_info_descriptors_) {
562
::memcpy(ptr, descriptor->Data(), descriptor->Length());
563
ptr += descriptor->Length();
566
for (auto track : tracks_) {
567
// Make sure all the decriptors have been added.
570
*ptr++ = track->stream_type;
571
*ptr++ = 0xe0 | (track->pid >> 8);
572
*ptr++ = track->pid & 0xff;
574
size_t ES_info_length = 0;
575
for (auto descriptor : track->descriptors)
576
ES_info_length += descriptor->Length();
578
if (ES_info_length > 0xfff)
579
MCS_FATAL("Invalid ES length %d", ES_info_length);
581
*ptr++ = 0xf0 | (ES_info_length >> 8);
582
*ptr++ = (ES_info_length & 0xff);
584
for (auto descriptor : track->descriptors) {
585
memcpy(ptr, descriptor->Data(), descriptor->Length());
586
ptr += descriptor->Length();
590
size_t section_length = ptr - (crcDataStart + 3) + 4 /* CRC */;
592
crcDataStart[1] = 0xb0 | (section_length >> 8);
593
crcDataStart[2] = section_length & 0xff;
595
crc = ::htonl(CalcCrc32(crcDataStart, ptr - crcDataStart));
596
memcpy(ptr, &crc, 4);
599
sizeLeft = packetDataStart + 188 - ptr;
600
memset(ptr, 0xff, sizeLeft);
602
packetDataStart += 188;
605
if (flags & Flags::kEmitPCR) {
608
// transport_error_indicator = b0
609
// payload_unit_start_indicator = b1
610
// transport_priority = b0
611
// PID = kPCR_PID (13 bits)
612
// transport_scrambling_control = b00
613
// adaptation_field_control = b10 (adaptation field only, no payload)
614
// continuity_counter = b0000 (does not increment)
615
// adaptation_field_length = 183
616
// discontinuity_indicator = b0
617
// random_access_indicator = b0
618
// elementary_stream_priority_indicator = b0
621
// splicing_point_flag = b0
622
// transport_private_data_flag = b0
623
// adaptation_field_extension_flag = b0
624
// program_clock_reference_base = b?????????????????????????????????
625
// reserved = b111111
626
// program_clock_reference_extension = b?????????
628
int64_t nowUs = mcs::Utils::GetNowUs();
629
uint64_t PCR = nowUs * 27; // PCR based on a 27MHz clock
630
uint64_t PCR_base = PCR / 300;
631
uint32_t PCR_ext = PCR % 300;
633
uint8_t *ptr = packetDataStart;
635
*ptr++ = 0x40 | (kPIDofPCR >> 8);
636
*ptr++ = kPIDofPCR & 0xff;
638
*ptr++ = 0xb7; // adaptation_field_length
640
*ptr++ = (PCR_base >> 25) & 0xff;
641
*ptr++ = (PCR_base >> 17) & 0xff;
642
*ptr++ = (PCR_base >> 9) & 0xff;
643
*ptr++ = ((PCR_base & 1) << 7) | 0x7e | ((PCR_ext >> 8) & 1);
644
*ptr++ = (PCR_ext & 0xff);
646
size_t sizeLeft = packetDataStart + 188 - ptr;
647
::memset(ptr, 0xff, sizeLeft);
649
packetDataStart += 188;
652
// Adjust time to 90kHz
653
uint64_t PTS = (timeUs * 9ll) / 100ll;
655
if (PES_packet_length >= 65536) {
656
// This really should only happen for video.
657
if (!track->IsVideo())
658
MCS_FATAL("PES packet length too hight; should only happen for video (track %d mime %s)",
659
track_index, track->format.mime);
661
MCS_WARNING("Reset PES packet length to 0");
663
// It's valid to set this to 0 for video according to the specs.
664
PES_packet_length = 0;
667
size_t sizeAvailableForPayload = 188 - 4 - 14 - numStuffingBytes;
668
if (PES_private_data_len > 0) {
669
sizeAvailableForPayload -= PES_private_data_len + 1;
672
size_t copy = access_unit->Length();
674
if (copy > sizeAvailableForPayload) {
675
copy = sizeAvailableForPayload;
677
if (alignPayload && copy > 16) {
682
size_t numPaddingBytes = sizeAvailableForPayload - copy;
684
uint8_t *ptr = packetDataStart;
686
*ptr++ = 0x40 | (track->pid >> 8);
687
*ptr++ = track->pid & 0xff;
689
*ptr++ = (numPaddingBytes > 0 ? 0x30 : 0x10)
690
| track->NextContinuityCounter();
692
if (numPaddingBytes > 0) {
693
*ptr++ = numPaddingBytes - 1;
694
if (numPaddingBytes >= 2) {
696
::memset(ptr, 0xff, numPaddingBytes - 2);
697
ptr += numPaddingBytes - 2;
704
*ptr++ = track->stream_id;
705
*ptr++ = PES_packet_length >> 8;
706
*ptr++ = PES_packet_length & 0xff;
708
*ptr++ = (PES_private_data_len > 0) ? 0x81 : 0x80;
710
size_t headerLength = 0x05 + numStuffingBytes;
711
if (PES_private_data_len > 0) {
712
headerLength += 1 + PES_private_data_len;
715
*ptr++ = headerLength;
717
*ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
718
*ptr++ = (PTS >> 22) & 0xff;
719
*ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
720
*ptr++ = (PTS >> 7) & 0xff;
721
*ptr++ = ((PTS & 0x7f) << 1) | 1;
723
if (PES_private_data_len > 0) {
724
*ptr++ = 0x8e; // PES_private_data_flag, reserved.
725
::memcpy(ptr, PES_private_data, PES_private_data_len);
726
ptr += PES_private_data_len;
729
for (size_t i = 0; i < numStuffingBytes; ++i) {
733
::memcpy(ptr, access_unit->Data(), copy);
736
if (ptr != packetDataStart + 188)
737
MCS_FATAL("Invalid pointer %p", ptr);
739
packetDataStart += 188;
741
size_t offset = copy;
742
while (offset < access_unit->Length()) {
743
// for subsequent fragments of "buffer":
745
// transport_error_indicator = b0
746
// payload_unit_start_indicator = b0
747
// transport_priority = b0
748
// PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
749
// transport_scrambling_control = b00
750
// adaptation_field_control = b??
751
// continuity_counter = b????
752
// the fragment of "buffer" follows.
754
size_t sizeAvailableForPayload = 188 - 4;
756
size_t copy = access_unit->Length() - offset;
758
if (copy > sizeAvailableForPayload) {
759
copy = sizeAvailableForPayload;
761
if (alignPayload && copy > 16) {
766
size_t numPaddingBytes = sizeAvailableForPayload - copy;
768
uint8_t *ptr = packetDataStart;
770
*ptr++ = 0x00 | (track->pid >> 8);
771
*ptr++ = track->pid & 0xff;
773
*ptr++ = (numPaddingBytes > 0 ? 0x30 : 0x10)
774
| track->NextContinuityCounter();
776
if (numPaddingBytes > 0) {
777
*ptr++ = numPaddingBytes - 1;
778
if (numPaddingBytes >= 2) {
780
memset(ptr, 0xff, numPaddingBytes - 2);
781
ptr += numPaddingBytes - 2;
785
memcpy(ptr, access_unit->Data() + offset, copy);
787
if (ptr != packetDataStart + 188)
788
MCS_FATAL("Invalid pointer position %p", ptr);
791
packetDataStart += 188;
794
if (packetDataStart != buffer->Data() + buffer->Length())
795
MCS_FATAL("Invalid packet start position");
802
void MPEGTSPacketizer::InitCrcTable() {
803
uint32_t poly = 0x04C11DB7;
805
for (int i = 0; i < 256; i++) {
806
uint32_t crc = i << 24;
807
for (int j = 0; j < 8; j++) {
808
crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
814
uint32_t MPEGTSPacketizer::CalcCrc32(const uint8_t *start, size_t size) const {
815
uint32_t crc = 0xFFFFFFFF;
818
for (p = start; p < start + size; ++p) {
819
crc = (crc << 8) ^ crc_table_[((crc >> 24) ^ *p) & 0xFF];
825
} // namespace streaming