~phablet-team/aethercast/fix-for-microsoft-dongle

« back to all changes in this revision

Viewing changes to src/mcs/streaming/mpegtspacketizer.cpp

Add hardware encoding and video streaming support.

The hardware encoding is currently only for Android 5.x based devices. On all others encoding will simply not work. The streaming part of aethercast (MPEGTS packetizing, RTP sending) as based on some code from Android.

Approved by PS Jenkins bot, Thomas Voß, Jim Hodapp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2012, The Android Open Source Project
 
3
 * Copyright (C) 2016 Canonical, Ltd.
 
4
 *
 
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
 
8
 *
 
9
 *     http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
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.
 
16
 */
 
17
 
 
18
/**
 
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.
 
22
 */
 
23
 
 
24
#include <arpa/inet.h>
 
25
#include <memory.h>
 
26
 
 
27
#include "mcs/utils.h"
 
28
#include "mcs/logger.h"
 
29
 
 
30
#include "mcs/video/utils.h"
 
31
 
 
32
#include "mcs/streaming/mpegtspacketizer.h"
 
33
 
 
34
namespace {
 
35
static constexpr uint8_t kH264NALPrefix[] = { 0x00, 0x00, 0x00, 0x01 };
 
36
 
 
37
// One byte for each profile, level and constraint
 
38
static constexpr uint32_t kCSDSize{3};
 
39
 
 
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};
 
44
 
 
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};
 
50
}
 
51
 
 
52
namespace mcs {
 
53
namespace streaming {
 
54
 
 
55
struct MPEGTSPacketizer::Track {
 
56
    typedef std::shared_ptr<Track> Ptr;
 
57
 
 
58
    static Ptr Create(const TrackFormat &format, unsigned int pid,
 
59
                      unsigned int stream_type, unsigned int stream_id);
 
60
 
 
61
    unsigned int NextContinuityCounter();
 
62
 
 
63
    bool IsAudio() const { return mcs::Utils::StringStartsWith(format.mime, "audio/"); }
 
64
    bool IsVideo() const { return mcs::Utils::StringStartsWith(format.mime, "video/"); }
 
65
 
 
66
    bool IsH264() const { return format.mime == "video/avc"; }
 
67
 
 
68
    void SubmitCSD(const mcs::video::Buffer::Ptr &buffer);
 
69
 
 
70
    mcs::video::Buffer::Ptr PrependCSD(const mcs::video::Buffer::Ptr &buffer) const;
 
71
 
 
72
    void Finalize();
 
73
 
 
74
    Track(const TrackFormat &format, unsigned int pid,
 
75
          unsigned int stream_type, unsigned int stream_id);
 
76
 
 
77
    TrackFormat format;
 
78
    unsigned int pid;
 
79
    unsigned int stream_type;
 
80
    unsigned int stream_id;
 
81
    unsigned int continuity_counter;
 
82
    bool finalized;
 
83
    std::vector<mcs::video::Buffer::Ptr> csd;
 
84
    std::vector<mcs::video::Buffer::Ptr> descriptors;
 
85
};
 
86
 
 
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));
 
90
}
 
91
 
 
92
MPEGTSPacketizer::Track::Track(const TrackFormat &format, unsigned int pid,
 
93
                               unsigned int stream_type, unsigned int stream_id) :
 
94
    format(format),
 
95
    pid(pid),
 
96
    stream_type(stream_type),
 
97
    stream_id(stream_id),
 
98
    continuity_counter(0),
 
99
    finalized(false) {
 
100
}
 
101
 
 
102
unsigned int MPEGTSPacketizer::Track::NextContinuityCounter() {
 
103
    unsigned int prev = continuity_counter;
 
104
    if (++continuity_counter == 16)
 
105
        continuity_counter = 0;
 
106
    return prev;
 
107
}
 
108
 
 
109
void MPEGTSPacketizer::Track::SubmitCSD(const video::Buffer::Ptr &buffer) {
 
110
    if (!IsH264())
 
111
        return;
 
112
 
 
113
    const uint8_t *data = buffer->Data();
 
114
    size_t size = buffer->Length();
 
115
 
 
116
    const uint8_t *nal_start;
 
117
    size_t nal_size;
 
118
 
 
119
    while (mcs::video::GetNextNALUnit(&data, &size, &nal_start, &nal_size, true)) {
 
120
        auto current = mcs::video::Buffer::Create(nal_size + sizeof(kH264NALPrefix));
 
121
 
 
122
        ::memcpy(current->Data(), kH264NALPrefix, sizeof(kH264NALPrefix));
 
123
        ::memcpy(current->Data() + sizeof(kH264NALPrefix), nal_start, nal_size);
 
124
 
 
125
        csd.push_back(current);
 
126
    }
 
127
}
 
128
 
 
129
mcs::video::Buffer::Ptr MPEGTSPacketizer::Track::PrependCSD(const mcs::video::Buffer::Ptr &buffer) const {
 
130
    size_t size = 0;
 
131
    for (auto current : csd)
 
132
        size += current->Length();
 
133
 
 
134
    auto new_buffer = mcs::video::Buffer::Create(buffer->Length() + size);
 
135
    size_t offset = 0;
 
136
    for (auto current : csd) {
 
137
        ::memcpy(new_buffer->Data() + offset, current->Data(), current->Length());
 
138
        offset += current->Length();
 
139
    }
 
140
 
 
141
    ::memcpy(new_buffer->Data() + offset, buffer->Data(), buffer->Length());
 
142
 
 
143
    return new_buffer;
 
144
}
 
145
 
 
146
void MPEGTSPacketizer::Track::Finalize() {
 
147
    if (finalized)
 
148
        return;
 
149
 
 
150
    if(!IsH264())
 
151
        return;
 
152
 
 
153
    MCS_DEBUG("");
 
154
 
 
155
    {
 
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
 
161
 
 
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
 
165
            // SPS we want here.
 
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
 
169
            // each).
 
170
            memcpy(&data[2], sps->Data() + sizeof(kH264NALPrefix), kCSDSize);
 
171
        }
 
172
        else {
 
173
            data[2] = format.profile_idc;    // profile_idc
 
174
            data[3] = format.constraint_set; // constraint_set*
 
175
            data[4] = format.level_idc;      // level_idc
 
176
        }
 
177
 
 
178
        // AVC_still_present=0, AVC_24_hour_picture_flag=0, reserved
 
179
        data[5] = 0x3f;
 
180
 
 
181
        descriptors.push_back(descriptor);
 
182
    }
 
183
    {
 
184
        // AVC timing and HRD descriptor (42)
 
185
 
 
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
 
190
 
 
191
        // hrd_management_valid_flag = 0
 
192
        // reserved = 111111b
 
193
        // picture_and_timing_info_present = 0
 
194
        data[2] = 0x7e;
 
195
 
 
196
        // fixed_frame_rate_flag = 0
 
197
        // temporal_poc_flag = 0
 
198
        // picture_to_display_conversion_flag = 0
 
199
        // reserved = 11111b
 
200
        data[3] = 0x1f;
 
201
 
 
202
        descriptors.push_back(descriptor);
 
203
    }
 
204
 
 
205
    finalized = true;
 
206
}
 
207
 
 
208
Packetizer::Ptr MPEGTSPacketizer::Create() {
 
209
    return std::shared_ptr<Packetizer>(new MPEGTSPacketizer);
 
210
}
 
211
 
 
212
MPEGTSPacketizer::MPEGTSPacketizer() :
 
213
    pat_continuity_counter_(0),
 
214
    pmt_continuity_counter_(0) {
 
215
    InitCrcTable();
 
216
}
 
217
 
 
218
MPEGTSPacketizer::~MPEGTSPacketizer() {
 
219
}
 
220
 
 
221
MPEGTSPacketizer::TrackId MPEGTSPacketizer::AddTrack(const TrackFormat &format) {
 
222
    auto is_video = mcs::Utils::StringStartsWith(format.mime, "video/");
 
223
 
 
224
    if (!is_video) {
 
225
        MCS_ERROR("Audio tracks for MPEGTS are currently not supported");
 
226
        return TrackId(-1);
 
227
    }
 
228
 
 
229
    if (format.mime != "video/avc") {
 
230
        MCS_ERROR("Video formats other than video/avc are not supported");
 
231
        return TrackId(-1);
 
232
    }
 
233
 
 
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;
 
239
 
 
240
    unsigned int num_same_tracks = 0;
 
241
    unsigned int pid = pidstart;
 
242
 
 
243
    for (auto track : tracks_) {
 
244
        if (track->stream_type == stream_type)
 
245
            num_same_tracks++;
 
246
 
 
247
        if (track->IsAudio() || track->IsVideo())
 
248
            pid++;
 
249
    }
 
250
 
 
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");
 
254
        return TrackId(-1);
 
255
    }
 
256
 
 
257
    auto track = Track::Create(format, pid, stream_type, stream_id);
 
258
    tracks_.push_back(track);
 
259
 
 
260
    return tracks_.size() - 1;
 
261
}
 
262
 
 
263
void MPEGTSPacketizer::SubmitCSD(TrackId track_index, const video::Buffer::Ptr &buffer) {
 
264
    if (track_index > tracks_.size() -1)
 
265
        return;
 
266
 
 
267
    auto track = tracks_.at(track_index);
 
268
    track->SubmitCSD(buffer);
 
269
}
 
270
 
 
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();
 
278
 
 
279
    packets->reset();
 
280
 
 
281
    if (track_index > tracks_.size() - 1) {
 
282
        MCS_ERROR("Invalid track index %d supplied", track_index);
 
283
        return false;
 
284
    }
 
285
 
 
286
    auto track = tracks_.at(track_index);
 
287
 
 
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);
 
292
    }
 
293
 
 
294
    // 0x47
 
295
    // transport_error_indicator = b0
 
296
    // payload_unit_start_indicator = b1
 
297
    // transport_priority = b0
 
298
    // PID
 
299
    // transport_scrambling_control = b00
 
300
    // adaptation_field_control = b??
 
301
    // continuity_counter = b????
 
302
    // -- payload follows
 
303
    // packet_startcode_prefix = 0x000001
 
304
    // stream_id
 
305
    // PES_packet_length = 0x????
 
306
    // reserved = b10
 
307
    // PES_scrambling_control = b00
 
308
    // PES_priority = b0
 
309
    // data_alignment_indicator = b1
 
310
    // copyright = b0
 
311
    // original_or_copy = b0
 
312
    // PTS_DTS_flags = b10  (PTS only)
 
313
    // ESCR_flag = b0
 
314
    // ES_rate_flag = b0
 
315
    // DSM_trick_mode_flag = b0
 
316
    // additional_copy_info_flag = b0
 
317
    // PES_CRC_flag = b0
 
318
    // PES_extension_flag = b0
 
319
    // PES_header_data_length = 0x05
 
320
    // reserved = b0010 (PTS)
 
321
    // PTS[32..30] = b???
 
322
    // reserved = b1
 
323
    // PTS[29..15] = b??? ???? ???? ???? (15 bits)
 
324
    // reserved = b1
 
325
    // PTS[14..0] = b??? ???? ???? ???? (15 bits)
 
326
    // reserved = b1
 
327
    // the first fragment of "buffer" follows
 
328
 
 
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;
 
332
 
 
333
    /*
 
334
       a) The very first PES transport stream packet contains
 
335
 
 
336
       4 bytes of TS header
 
337
       ... padding
 
338
       14 bytes of static PES header
 
339
       PES_private_data_len + 1 bytes (only if PES_private_data_len > 0)
 
340
       numStuffingBytes bytes
 
341
 
 
342
       followed by the payload
 
343
 
 
344
       b) Subsequent PES transport stream packets contain
 
345
 
 
346
       4 bytes of TS header
 
347
       ... padding
 
348
 
 
349
       followed by the payload
 
350
    */
 
351
 
 
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;
 
355
 
 
356
    size_t numTSPackets = 1;
 
357
 
 
358
    {
 
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;
 
363
        }
 
364
 
 
365
        if (PES_header_size > 188u - 4u)
 
366
            MCS_FATAL("Invalid header size");
 
367
 
 
368
        size_t sizeAvailableForPayload = 188 - 4 - PES_header_size;
 
369
        size_t numBytesOfPayload = access_unit->Length();
 
370
 
 
371
        if (numBytesOfPayload > sizeAvailableForPayload) {
 
372
            numBytesOfPayload = sizeAvailableForPayload;
 
373
 
 
374
            if (alignPayload && numBytesOfPayload > 16) {
 
375
                numBytesOfPayload -= (numBytesOfPayload % 16);
 
376
            }
 
377
        }
 
378
 
 
379
        size_t numBytesOfPayloadRemaining = access_unit->Length() - numBytesOfPayload;
 
380
 
 
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;
 
385
        if (alignPayload) {
 
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);
 
390
        }
 
391
 
 
392
        size_t numFullTSPackets =
 
393
            numBytesOfPayloadRemaining / sizeAvailableForAlignedPayload;
 
394
 
 
395
        numTSPackets += numFullTSPackets;
 
396
 
 
397
        numBytesOfPayloadRemaining -=
 
398
            numFullTSPackets * sizeAvailableForAlignedPayload;
 
399
 
 
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.
 
404
            ++numTSPackets;
 
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.
 
411
            ++numTSPackets;
 
412
        }
 
413
    }
 
414
 
 
415
    if (flags & Flags::kEmitPATandPMT)
 
416
        numTSPackets += 2;
 
417
 
 
418
    if (flags & Flags::kEmitPCR)
 
419
        ++numTSPackets;
 
420
 
 
421
    auto buffer = mcs::video::Buffer::Create(numTSPackets * 188);
 
422
    buffer->SetTimestamp(access_unit->Timestamp());
 
423
 
 
424
    uint8_t *packetDataStart = buffer->Data();
 
425
 
 
426
    if (flags & Flags::kEmitPATandPMT) {
 
427
        // Program Association Table (PAT):
 
428
        // 0x47
 
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????
 
436
        // skip = 0x00
 
437
        // --- payload follows
 
438
        // table_id = 0x00
 
439
        // section_syntax_indicator = b1
 
440
        // must_be_zero = b0
 
441
        // reserved = b11
 
442
        // section_length = 0x00d
 
443
        // transport_stream_id = 0x0000
 
444
        // reserved = b11
 
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
 
451
        //   reserved = b111
 
452
        //   program_map_PID = kpidPMT (13 bits!)
 
453
        // CRC = 0x????????
 
454
 
 
455
        if (++pat_continuity_counter_ == 16)
 
456
            pat_continuity_counter_ = 0;
 
457
 
 
458
        uint8_t *ptr = packetDataStart;
 
459
        *ptr++ = 0x47;
 
460
        *ptr++ = 0x40;
 
461
        *ptr++ = 0x00;
 
462
        *ptr++ = 0x10 | pat_continuity_counter_;
 
463
        *ptr++ = 0x00;
 
464
 
 
465
        uint8_t *crcDataStart = ptr;
 
466
        *ptr++ = 0x00;
 
467
        *ptr++ = 0xb0;
 
468
        *ptr++ = 0x0d;
 
469
        *ptr++ = 0x00;
 
470
        *ptr++ = 0x00;
 
471
        *ptr++ = 0xc3;
 
472
        *ptr++ = 0x00;
 
473
        *ptr++ = 0x00;
 
474
        *ptr++ = 0x00;
 
475
        *ptr++ = 0x01;
 
476
        *ptr++ = 0xe0 | (kPIDofPMT >> 8);
 
477
        *ptr++ = kPIDofPMT & 0xff;
 
478
 
 
479
        if (ptr - crcDataStart != 12)
 
480
            MCS_FATAL("Invalid position for ptr");
 
481
 
 
482
        uint32_t crc = ::htonl(CalcCrc32(crcDataStart, ptr - crcDataStart));
 
483
        ::memcpy(ptr, &crc, 4);
 
484
        ptr += 4;
 
485
 
 
486
        size_t sizeLeft = packetDataStart + 188 - ptr;
 
487
        ::memset(ptr, 0xff, sizeLeft);
 
488
 
 
489
        packetDataStart += 188;
 
490
 
 
491
        // Program Map (PMT):
 
492
        // 0x47
 
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????
 
500
        // skip = 0x00
 
501
        // -- payload follows
 
502
        // table_id = 0x02
 
503
        // section_syntax_indicator = b1
 
504
        // must_be_zero = b0
 
505
        // reserved = b11
 
506
        // section_length = 0x???
 
507
        // program_number = 0x0001
 
508
        // reserved = b11
 
509
        // version_number = b00001
 
510
        // current_next_indicator = b1
 
511
        // section_number = 0x00
 
512
        // last_section_number = 0x00
 
513
        // reserved = b111
 
514
        // PCR_PID = kPCR_PID (13 bits)
 
515
        // reserved = b1111
 
516
        // program_info_length = 0x???
 
517
        //   program_info_descriptors follow
 
518
        // one or more elementary stream descriptions follow:
 
519
        //   stream_type = 0x??
 
520
        //   reserved = b111
 
521
        //   elementary_PID = b? ???? ???? ???? (13 bits)
 
522
        //   reserved = b1111
 
523
        //   ES_info_length = 0x000
 
524
        // CRC = 0x????????
 
525
 
 
526
        if (++pmt_continuity_counter_ == 16)
 
527
            pmt_continuity_counter_ = 0;
 
528
 
 
529
        ptr = packetDataStart;
 
530
 
 
531
        *ptr++ = 0x47;
 
532
        *ptr++ = 0x40 | (kPIDofPMT >> 8);
 
533
        *ptr++ = kPIDofPMT & 0xff;
 
534
        *ptr++ = 0x10 | pmt_continuity_counter_;
 
535
        *ptr++ = 0x00;
 
536
 
 
537
        crcDataStart = ptr;
 
538
        *ptr++ = 0x02;
 
539
 
 
540
        *ptr++ = 0x00;  // section_length to be filled in below.
 
541
        *ptr++ = 0x00;
 
542
 
 
543
        *ptr++ = 0x00;
 
544
        *ptr++ = 0x01;
 
545
        *ptr++ = 0xc3;
 
546
        *ptr++ = 0x00;
 
547
        *ptr++ = 0x00;
 
548
        *ptr++ = 0xe0 | (kPIDofPCR >> 8);
 
549
        *ptr++ = kPIDofPCR & 0xff;
 
550
 
 
551
        size_t program_info_length = 0;
 
552
        for (auto descriptor : program_info_descriptors_)
 
553
            program_info_length += descriptor->Length();
 
554
 
 
555
        if(program_info_length >= 0x400)
 
556
            MCS_FATAL("Invalid length for program info");
 
557
 
 
558
        *ptr++ = 0xf0 | (program_info_length >> 8);
 
559
        *ptr++ = (program_info_length & 0xff);
 
560
 
 
561
        for (auto descriptor : program_info_descriptors_) {
 
562
            ::memcpy(ptr, descriptor->Data(), descriptor->Length());
 
563
            ptr += descriptor->Length();
 
564
        }
 
565
 
 
566
        for (auto track : tracks_) {
 
567
            // Make sure all the decriptors have been added.
 
568
            track->Finalize();
 
569
 
 
570
            *ptr++ = track->stream_type;
 
571
            *ptr++ = 0xe0 | (track->pid >> 8);
 
572
            *ptr++ = track->pid & 0xff;
 
573
 
 
574
            size_t ES_info_length = 0;
 
575
            for (auto descriptor : track->descriptors)
 
576
                ES_info_length += descriptor->Length();
 
577
 
 
578
            if (ES_info_length > 0xfff)
 
579
                MCS_FATAL("Invalid ES length %d", ES_info_length);
 
580
 
 
581
            *ptr++ = 0xf0 | (ES_info_length >> 8);
 
582
            *ptr++ = (ES_info_length & 0xff);
 
583
 
 
584
            for (auto descriptor : track->descriptors) {
 
585
                memcpy(ptr, descriptor->Data(), descriptor->Length());
 
586
                ptr += descriptor->Length();
 
587
            }
 
588
        }
 
589
 
 
590
        size_t section_length = ptr - (crcDataStart + 3) + 4 /* CRC */;
 
591
 
 
592
        crcDataStart[1] = 0xb0 | (section_length >> 8);
 
593
        crcDataStart[2] = section_length & 0xff;
 
594
 
 
595
        crc = ::htonl(CalcCrc32(crcDataStart, ptr - crcDataStart));
 
596
        memcpy(ptr, &crc, 4);
 
597
        ptr += 4;
 
598
 
 
599
        sizeLeft = packetDataStart + 188 - ptr;
 
600
        memset(ptr, 0xff, sizeLeft);
 
601
 
 
602
        packetDataStart += 188;
 
603
    }
 
604
 
 
605
    if (flags & Flags::kEmitPCR) {
 
606
        // PCR stream
 
607
        // 0x47
 
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
 
619
        // PCR_flag = b1
 
620
        // OPCR_flag = 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?????????
 
627
 
 
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;
 
632
 
 
633
        uint8_t *ptr = packetDataStart;
 
634
        *ptr++ = 0x47;
 
635
        *ptr++ = 0x40 | (kPIDofPCR >> 8);
 
636
        *ptr++ = kPIDofPCR & 0xff;
 
637
        *ptr++ = 0x20;
 
638
        *ptr++ = 0xb7;  // adaptation_field_length
 
639
        *ptr++ = 0x10;
 
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);
 
645
 
 
646
        size_t sizeLeft = packetDataStart + 188 - ptr;
 
647
        ::memset(ptr, 0xff, sizeLeft);
 
648
 
 
649
        packetDataStart += 188;
 
650
    }
 
651
 
 
652
    // Adjust time to 90kHz
 
653
    uint64_t PTS = (timeUs * 9ll) / 100ll;
 
654
 
 
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);
 
660
 
 
661
        MCS_WARNING("Reset PES packet length to 0");
 
662
 
 
663
        // It's valid to set this to 0 for video according to the specs.
 
664
        PES_packet_length = 0;
 
665
    }
 
666
 
 
667
    size_t sizeAvailableForPayload = 188 - 4 - 14 - numStuffingBytes;
 
668
    if (PES_private_data_len > 0) {
 
669
        sizeAvailableForPayload -= PES_private_data_len + 1;
 
670
    }
 
671
 
 
672
    size_t copy = access_unit->Length();
 
673
 
 
674
    if (copy > sizeAvailableForPayload) {
 
675
        copy = sizeAvailableForPayload;
 
676
 
 
677
        if (alignPayload && copy > 16) {
 
678
            copy -= (copy % 16);
 
679
        }
 
680
    }
 
681
 
 
682
    size_t numPaddingBytes = sizeAvailableForPayload - copy;
 
683
 
 
684
    uint8_t *ptr = packetDataStart;
 
685
    *ptr++ = 0x47;
 
686
    *ptr++ = 0x40 | (track->pid >> 8);
 
687
    *ptr++ = track->pid & 0xff;
 
688
 
 
689
    *ptr++ = (numPaddingBytes > 0 ? 0x30 : 0x10)
 
690
                | track->NextContinuityCounter();
 
691
 
 
692
    if (numPaddingBytes > 0) {
 
693
        *ptr++ = numPaddingBytes - 1;
 
694
        if (numPaddingBytes >= 2) {
 
695
            *ptr++ = 0x00;
 
696
            ::memset(ptr, 0xff, numPaddingBytes - 2);
 
697
            ptr += numPaddingBytes - 2;
 
698
        }
 
699
    }
 
700
 
 
701
    *ptr++ = 0x00;
 
702
    *ptr++ = 0x00;
 
703
    *ptr++ = 0x01;
 
704
    *ptr++ = track->stream_id;
 
705
    *ptr++ = PES_packet_length >> 8;
 
706
    *ptr++ = PES_packet_length & 0xff;
 
707
    *ptr++ = 0x84;
 
708
    *ptr++ = (PES_private_data_len > 0) ? 0x81 : 0x80;
 
709
 
 
710
    size_t headerLength = 0x05 + numStuffingBytes;
 
711
    if (PES_private_data_len > 0) {
 
712
        headerLength += 1 + PES_private_data_len;
 
713
    }
 
714
 
 
715
    *ptr++ = headerLength;
 
716
 
 
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;
 
722
 
 
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;
 
727
    }
 
728
 
 
729
    for (size_t i = 0; i < numStuffingBytes; ++i) {
 
730
        *ptr++ = 0xff;
 
731
    }
 
732
 
 
733
    ::memcpy(ptr, access_unit->Data(), copy);
 
734
    ptr += copy;
 
735
 
 
736
    if (ptr != packetDataStart + 188)
 
737
        MCS_FATAL("Invalid pointer %p", ptr);
 
738
 
 
739
    packetDataStart += 188;
 
740
 
 
741
    size_t offset = copy;
 
742
    while (offset < access_unit->Length()) {
 
743
        // for subsequent fragments of "buffer":
 
744
        // 0x47
 
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.
 
753
 
 
754
        size_t sizeAvailableForPayload = 188 - 4;
 
755
 
 
756
        size_t copy = access_unit->Length() - offset;
 
757
 
 
758
        if (copy > sizeAvailableForPayload) {
 
759
            copy = sizeAvailableForPayload;
 
760
 
 
761
            if (alignPayload && copy > 16) {
 
762
                copy -= (copy % 16);
 
763
            }
 
764
        }
 
765
 
 
766
        size_t numPaddingBytes = sizeAvailableForPayload - copy;
 
767
 
 
768
        uint8_t *ptr = packetDataStart;
 
769
        *ptr++ = 0x47;
 
770
        *ptr++ = 0x00 | (track->pid >> 8);
 
771
        *ptr++ = track->pid & 0xff;
 
772
 
 
773
        *ptr++ = (numPaddingBytes > 0 ? 0x30 : 0x10)
 
774
                    | track->NextContinuityCounter();
 
775
 
 
776
        if (numPaddingBytes > 0) {
 
777
            *ptr++ = numPaddingBytes - 1;
 
778
            if (numPaddingBytes >= 2) {
 
779
                *ptr++ = 0x00;
 
780
                memset(ptr, 0xff, numPaddingBytes - 2);
 
781
                ptr += numPaddingBytes - 2;
 
782
            }
 
783
        }
 
784
 
 
785
        memcpy(ptr, access_unit->Data() + offset, copy);
 
786
        ptr += copy;
 
787
        if (ptr != packetDataStart + 188)
 
788
            MCS_FATAL("Invalid pointer position %p", ptr);
 
789
 
 
790
        offset += copy;
 
791
        packetDataStart += 188;
 
792
    }
 
793
 
 
794
    if (packetDataStart != buffer->Data() + buffer->Length())
 
795
        MCS_FATAL("Invalid packet start position");
 
796
 
 
797
    *packets = buffer;
 
798
 
 
799
    return true;
 
800
}
 
801
 
 
802
void MPEGTSPacketizer::InitCrcTable() {
 
803
    uint32_t poly = 0x04C11DB7;
 
804
 
 
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);
 
809
        }
 
810
        crc_table_[i] = crc;
 
811
    }
 
812
}
 
813
 
 
814
uint32_t MPEGTSPacketizer::CalcCrc32(const uint8_t *start, size_t size) const {
 
815
    uint32_t crc = 0xFFFFFFFF;
 
816
    const uint8_t *p;
 
817
 
 
818
    for (p = start; p < start + size; ++p) {
 
819
        crc = (crc << 8) ^ crc_table_[((crc >> 24) ^ *p) & 0xFF];
 
820
    }
 
821
 
 
822
    return crc;
 
823
}
 
824
 
 
825
} // namespace streaming
 
826
} // namespace mcs