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

« back to all changes in this revision

Viewing changes to tests/mcs/streaming/mpegtspacketizer_tests.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 (C) 2016 Canonical, Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3, as published
 
6
 * by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
 * PURPOSE.  See the GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 */
 
17
 
 
18
#include <gtest/gtest.h>
 
19
 
 
20
#include <chrono>
 
21
 
 
22
#include <mcs/streaming/mpegtspacketizer.h>
 
23
 
 
24
namespace {
 
25
static constexpr uint8_t kMPEGTSPacketLength = 188;
 
26
static constexpr uint8_t kMPEGTSStartByte = 0x47;
 
27
static const uint8_t csd0[] = {
 
28
    // SPS
 
29
    0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x0a, 0xf8, 0x41, 0xa2,
 
30
    // PPS
 
31
    0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x38, 0x80
 
32
};
 
33
static const uint8_t slice_header[] = {
 
34
    // Slice header comes first
 
35
    0x00, 0x00, 0x00, 0x01, 0x05, 0x88, 0x84, 0x21, 0xa0,
 
36
};
 
37
 
 
38
mcs::video::Buffer::Ptr CreateFrame(int size) {
 
39
    auto buffer = mcs::video::Buffer::Create(size + sizeof(slice_header));
 
40
    ::memcpy(buffer->Data(), slice_header, sizeof(slice_header));
 
41
    return buffer;
 
42
}
 
43
 
 
44
class MPEGTSPacketMatcher {
 
45
public:
 
46
    MPEGTSPacketMatcher(const mcs::video::Buffer::Ptr &buffer) :
 
47
        buffer_(buffer) {
 
48
    }
 
49
 
 
50
    MPEGTSPacketMatcher(const MPEGTSPacketMatcher &other) :
 
51
        buffer_(other.buffer_) {
 
52
    }
 
53
 
 
54
    void ExpectValid() {
 
55
        EXPECT_EQ(0x47, buffer_->Data()[0]);
 
56
    }
 
57
 
 
58
    void ExpectPackets(int count) {
 
59
        // One MPEGTS element has a constant length
 
60
        EXPECT_EQ(kMPEGTSPacketLength * count, buffer_->Length());
 
61
 
 
62
        // Split into multiple packets so that those can be process
 
63
        // individually.
 
64
        for (int n = 0; n < count; n++) {
 
65
            auto packet = mcs::video::Buffer::Create(kMPEGTSPacketLength);
 
66
            ::memcpy(packet->Data(), buffer_->Data() + (n * kMPEGTSPacketLength), kMPEGTSPacketLength);
 
67
            packets_.push_back(MPEGTSPacketMatcher(packet));
 
68
        }
 
69
    }
 
70
 
 
71
    void ExpectPID(uint16_t expected_pid) {
 
72
        uint16_t pid = ((buffer_->Data()[1] ^ 0x40) << 8) | buffer_->Data()[2];
 
73
        EXPECT_EQ(expected_pid, pid);
 
74
    }
 
75
 
 
76
    void ExpectPaddingBytesAndContinuityCounter(uint8_t counter) {
 
77
        EXPECT_EQ(0x30 | counter, buffer_->Data()[3]);
 
78
    }
 
79
 
 
80
    void ExpectNoPaddingBytesAndContinuityCounter(uint8_t counter) {
 
81
        EXPECT_EQ(0x10 | counter, buffer_->Data()[3]);
 
82
    }
 
83
 
 
84
    void ExpectData(uint8_t *data, size_t length) {
 
85
        // What we have supplied into the packtizer should be now placed at the end of
 
86
        // the element we got back from the packetizer.
 
87
        EXPECT_EQ(0, memcmp(buffer_->Data() + (buffer_->Length() - length),
 
88
                            data, length));
 
89
    }
 
90
 
 
91
    void ExpectByte(unsigned int n, uint8_t expected_byte) {
 
92
        EXPECT_EQ(expected_byte, buffer_->Data()[n]);
 
93
    }
 
94
 
 
95
    MPEGTSPacketMatcher& At(int n) {
 
96
        return packets_.at(n);
 
97
    }
 
98
 
 
99
private:
 
100
    mcs::video::Buffer::Ptr buffer_;
 
101
    std::vector<MPEGTSPacketMatcher> packets_;
 
102
};
 
103
 
 
104
}
 
105
 
 
106
TEST(MPEGTSPacketizer, AddTrackWithoutAnythingSet) {
 
107
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
108
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{});
 
109
    EXPECT_EQ(-1, id);
 
110
}
 
111
 
 
112
TEST(MPEGTSPacketizer, AddValidTrack) {
 
113
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
114
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
115
    EXPECT_EQ(0, id);
 
116
}
 
117
 
 
118
TEST(MPEGTSPacketizer, TryMoreThanOneValidTrack) {
 
119
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
120
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
121
    EXPECT_EQ(0, id);
 
122
    for (int i = 0; i < 15; i++) {
 
123
        id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
124
        EXPECT_EQ(i+1, id);
 
125
    }
 
126
    id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
127
    EXPECT_EQ(-1, id);
 
128
}
 
129
 
 
130
TEST(MPEGTSPacketizer, SubmitAndProcessCodecSpecificData) {
 
131
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
132
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
133
 
 
134
    auto buffer = mcs::video::Buffer::Create(sizeof(csd0));
 
135
    ::memcpy(buffer->Data(), csd0, sizeof(csd0));
 
136
 
 
137
    mcs::video::Buffer::Ptr out;
 
138
 
 
139
    packetizer->Packetize(id, buffer, &out);
 
140
 
 
141
    MPEGTSPacketMatcher matcher(out);
 
142
 
 
143
    matcher.ExpectPackets(1);
 
144
    matcher.At(0).ExpectPackets(1);
 
145
    matcher.At(0).ExpectValid();
 
146
    matcher.At(0).ExpectPID(0x1011);
 
147
    matcher.At(0).ExpectPaddingBytesAndContinuityCounter(0);
 
148
    matcher.At(0).ExpectData(buffer->Data(), buffer->Length());
 
149
 
 
150
    EXPECT_GE(0, out->Timestamp());
 
151
}
 
152
 
 
153
TEST(MPEGTSPacketizer, EmitPCRandPATandPMT) {
 
154
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
155
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
156
 
 
157
    mcs::video::Buffer::Ptr out;
 
158
    auto buffer = CreateFrame(100);
 
159
 
 
160
    packetizer->Packetize(id, buffer, &out, mcs::streaming::Packetizer::kEmitPCR |
 
161
                          mcs::streaming::Packetizer::kEmitPATandPMT);
 
162
 
 
163
    MPEGTSPacketMatcher matcher(out);
 
164
 
 
165
    // We should have four packets now:
 
166
    // 1. PAT
 
167
    // 2. PMT
 
168
    // 3. PCR
 
169
    // 4. Actual TS packet
 
170
    matcher.ExpectPackets(4);
 
171
 
 
172
    matcher.At(0).ExpectValid();
 
173
    matcher.At(0).ExpectPID(0);
 
174
    matcher.At(0).ExpectNoPaddingBytesAndContinuityCounter(1);
 
175
 
 
176
    matcher.At(1).ExpectValid();
 
177
    matcher.At(1).ExpectPID(0x100);
 
178
    matcher.At(1).ExpectNoPaddingBytesAndContinuityCounter(1);
 
179
 
 
180
    matcher.At(2).ExpectValid();
 
181
    matcher.At(2).ExpectPID(0x1000);
 
182
    // It doesn't really set a continuity counter for the PCR
 
183
    // TS packet so just compare the static value we expect here.
 
184
    matcher.At(2).ExpectByte(3, 0x20);
 
185
 
 
186
    matcher.At(3).ExpectValid();
 
187
    matcher.At(3).ExpectPID(0x1011);
 
188
    matcher.At(3).ExpectPaddingBytesAndContinuityCounter(0);
 
189
    matcher.At(3).ExpectData(buffer->Data(), buffer->Length());
 
190
 
 
191
    EXPECT_GE(0, out->Timestamp());
 
192
}
 
193
 
 
194
TEST(MPEGTSPacketizer, IncreasingContinuityCounter) {
 
195
    auto packetizer = mcs::streaming::MPEGTSPacketizer::Create();
 
196
    auto id = packetizer->AddTrack(mcs::streaming::MPEGTSPacketizer::TrackFormat{"video/avc"});
 
197
 
 
198
    // Make sure we looper over 15 here as that is used for the continuity counter
 
199
    // for PAT/PMT and PCR but shouldn't be used here.
 
200
    for (int n = 0; n < 20; n++) {
 
201
        mcs::video::Buffer::Ptr out;
 
202
        auto buffer = CreateFrame(100);
 
203
 
 
204
        packetizer->Packetize(id, buffer, &out, mcs::streaming::Packetizer::kEmitPCR |
 
205
                              mcs::streaming::Packetizer::kEmitPATandPMT);
 
206
 
 
207
        MPEGTSPacketMatcher matcher(out);
 
208
 
 
209
        matcher.ExpectPackets(4);
 
210
 
 
211
        matcher.At(0).ExpectValid();
 
212
        matcher.At(0).ExpectPID(0);
 
213
        // Continuity counter starts a 1 and goes up to 15
 
214
        matcher.At(0).ExpectNoPaddingBytesAndContinuityCounter((n + 1) % 16);
 
215
 
 
216
        matcher.At(1).ExpectValid();
 
217
        matcher.At(1).ExpectPID(0x100);
 
218
        // Continuity counter starts a 1 and goes up to 15
 
219
        matcher.At(1).ExpectNoPaddingBytesAndContinuityCounter((n + 1) % 16);
 
220
 
 
221
        matcher.At(2).ExpectValid();
 
222
        matcher.At(2).ExpectPID(0x1000);
 
223
        // It doesn't really set a continuity counter for the PCR
 
224
        // TS packet so just compare the static value we expect here.
 
225
        matcher.At(2).ExpectByte(3, 0x20);
 
226
 
 
227
        matcher.At(3).ExpectValid();
 
228
        matcher.At(3).ExpectPID(0x1011);
 
229
        matcher.At(3).ExpectPaddingBytesAndContinuityCounter(n);
 
230
        matcher.At(3).ExpectData(buffer->Data(), buffer->Length());
 
231
    }
 
232
}