MythTV master
tspacket.h
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2// Copyright (c) 2003-2004,2010 Daniel Thor Kristjansson
3#ifndef TS_PACKET_H
4#define TS_PACKET_H
5
6#include <algorithm>
7#include <array>
8#include <cassert>
9#include <chrono>
10#include <cstdlib>
11#include <cstring>
12
13#include <QString>
14
15#include "libmythtv/mythtvexp.h"
16
17// n.b. these PID relationships are only a recommendation from ATSC,
18// but seem to be universal
19//static constexpr uint16_t VIDEO_PID(uint16_t bp) { return bp+1; };
20//static constexpr uint16_t AUDIO_PID(uint16_t bp) { return bp+4; };
21static constexpr uint8_t SYNC_BYTE { 0x47 };
22
23using TSHeaderArray = std::array<uint8_t,4>;
24
25// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
26
47{
48 public:
49 using Clock = std::chrono::steady_clock;
50 using TimePoint = std::chrono::time_point<Clock, std::chrono::microseconds>;
51
53 {
54 m_tsData[0] = SYNC_BYTE;
55 /*
56 no need to init rest of header, this is only a part of a larger
57 packets which initialize the rest of the data differently.
58 */
59 }
60 explicit TSHeader(int cc)
61 {
62 m_tsData[0] = SYNC_BYTE;
63 SetContinuityCounter(cc);
64 /*
65 no need to init rest of header, this is only a part of a larger
66 packets which initialize the rest of the data differently.
67 */
68 }
69 void InitHeader(const unsigned char* header) {
70 if (header)
71 {
72 m_tsData[0]=header[0];
73 m_tsData[1]=header[1];
74 m_tsData[2]=header[2];
75 m_tsData[3]=header[3];
76 }
77 }
78
79 // Decode the link header (bytes 0-4):
80 // gets
81
82 //0.0 8 bits SYNC_BYTE
83 bool HasSync(void) const { return SYNC_BYTE == m_tsData[0]; }
84 //1.0 1 bit transport_packet_error (if set discard immediately:
85 // modem error)
86 bool TransportError(void) const { return ( m_tsData[1] & 0x80 ) != 0; }
87 //1.1 1 bit payload_unit_start_indicator
88 // (if set this packet starts a section, and has pointerField)
89 bool PayloadStart(void) const { return ( m_tsData[1] & 0x40 ) != 0; }
90 //1.2 1 bit transport_priority (ignore)
91 bool Priority(void) const { return ( m_tsData[1] & 0x20 ) != 0; }
92 //1.3 13 bit PID (packet ID, which transport stream)
93 unsigned int PID(void) const {
94 return ((m_tsData[1] << 8) + m_tsData[2]) & 0x1fff;
95 }
96 //3.0 2 bit transport_scrambling_control (00,01 OK; 10,11 scrambled)
97 unsigned int ScramblingControl(void) const { return (m_tsData[3] >> 6) & 0x3; }
98 //3.2 2 bit adaptation_field_control
99 // (01-no adaptation field,payload only
100 // 10-adaptation field only,no payload
101 // 11-adaptation field followed by payload
102 // 00-reserved)
103 unsigned int AdaptationFieldControl(void) const {
104 return (m_tsData[3] >> 4) & 0x3;
105 }
106 //3.4 4 bit continuity counter (should cycle 0->15 in sequence
107 // for each PID; if skip, we lost a packet; if dup, we can
108 // ignore packet)
109 unsigned int ContinuityCounter(void) const { return m_tsData[3] & 0xf; }
110
111 // shortcuts
112 bool Scrambled(void) const { return ( m_tsData[3] & 0x80 ) != 0; }
113 bool HasAdaptationField(void) const { return ( m_tsData[3] & 0x20 ) != 0; }
114 size_t AdaptationFieldSize(void) const
115 { return (HasAdaptationField() ? static_cast<size_t>(data()[4]) : 0); }
116 bool HasPayload(void) const { return ( m_tsData[3] & 0x10 ) != 0; }
117
119 { return (AdaptationFieldSize() > 0) && ((data()[5] & 0x80 ) != 0); }
120
121 bool HasPCR(void) const { return (AdaptationFieldSize() > 0) &&
122 ((data()[5] & 0x10 ) != 0); }
123
124 /*
125 The PCR field is a 42 bit field in the adaptation field of the
126 Transport Stream. The PCR field consists of a 9 bit part that
127 increments at a 27MHz rate and a 33 bit part that increments at
128 a 90kHz rate (when the 27MHz part rolls over).
129 */
130 // The high-order 33bits (of the 48 total) are the 90kHz clock
131 int64_t GetPCRbase(void) const
132 { return ((static_cast<int64_t>(data()[6]) << 25) |
133 (static_cast<int64_t>(data()[7]) << 17) |
134 (static_cast<int64_t>(data()[8]) << 9) |
135 (static_cast<int64_t>(data()[9]) << 1) |
136 (data()[10] >> 7)); }
137
138 // The low-order 9 bits (of the 48 total) are the 27MHz clock
139 int32_t GetPCRext(void) const
140 { return (((static_cast<int32_t>(data()[10]) & 0x1) << 8) |
141 static_cast<int32_t>(data()[11])); }
142
143 // PCR in a 27MHz clock
144 int64_t GetPCRraw(void) const
145 { return ((GetPCRbase() * 300) + GetPCRext()); }
146
147 // PCR as a time point
148 TimePoint GetPCR(void) const
149 { return TimePoint(std::chrono::microseconds(GetPCRraw() / 27)); }
150
151 void SetTransportError(bool err) {
152 if (err) m_tsData[1] |= 0x80; else m_tsData[1] &= (0xff-(0x80));
153 }
154 void SetPayloadStart(bool start) {
155 if (start) m_tsData[1] |= 0x40; else m_tsData[1] &= (0xff-0x40);
156 }
157 void SetPriority(bool priority) {
158 if (priority) m_tsData[1] |= 0x20; else m_tsData[1] &= (0xff-0x20);
159 }
160 void SetPID(unsigned int pid) {
161 m_tsData[1] = ((pid >> 8) & 0x1F) | (m_tsData[1] & 0xE0);
162 m_tsData[2] = (pid & 0xFF);
163 }
164 void SetScrambled(unsigned int scr) {
165 m_tsData[3] = (m_tsData[3] & (0xff-(0x3<<6))) | (scr<<6);
166 }
167 void SetAdaptationFieldControl(unsigned int afc) {
168 m_tsData[3] = (m_tsData[3] & 0xcf) | (afc&0x3)<<4;
169 }
170 void SetContinuityCounter(unsigned int cc) {
171 m_tsData[3] = (m_tsData[3] & 0xf0) | (cc & 0xf);
172 }
173
174 const unsigned char* data(void) const { return m_tsData.data(); }
175 unsigned char* data(void) { return m_tsData.data(); }
176
177 static constexpr unsigned int kHeaderSize {4};
179 private:
180 TSHeaderArray m_tsData; // Intentionally no initialization
181};
182
183static_assert(sizeof(TSHeader) == 4,
184 "The TSHeader class must be 4 bytes in size. It must "
185 "have only one non-static variable (m_tsData) of 4 "
186 "bytes, and it must not have any virtual functions.");
187
188
189
208{
209 friend class PESPacket;
210 public:
211 /* note: payload is intentionally left uninitialized */
212 // cppcheck-suppress uninitMemberVar
213 TSPacket(void) = default;
214
216 {
217 auto *pkt = new TSPacket();
218 pkt->InitHeader(kPayloadOnlyHeader.data());
219 pkt->m_tsPayload.fill(0xFF);
220 pkt->SetStartOfFieldPointer(0);
221 return pkt;
222 }
223
224 TSPacket* CreateClone(void) const {
225 auto *pkt = new TSPacket();
226 memcpy(pkt, this, kSize);
227 return pkt;
228 }
229
230 void InitPayload(const unsigned char *payload)
231 {
232 if (payload)
233 std::copy(payload, payload+kPayloadSize, m_tsPayload.data());
234 }
235
236 void InitPayload(const unsigned char *payload, uint size)
237 {
238 if (payload)
239 std::copy(payload, payload+size, m_tsPayload.data());
240 else
241 size = 0;
242
243 if (size < TSPacket::kPayloadSize)
244 std::fill_n(&m_tsPayload[size], TSPacket::kPayloadSize - size, 0xff);
245 }
246
247 // This points outside the TSHeader data, but is declared here because
248 // it is used for the different types of packets that employ a TS Header
249 unsigned int AFCOffset(void) const { // only works if AFC fits in TSPacket
250 return HasAdaptationField() ? m_tsPayload[0]+1+4 : 4;
251 }
252
253 //4.0 8 bits, iff payloadStart(), points to start of field
254 unsigned int StartOfFieldPointer(void) const
255 { return m_tsPayload[AFCOffset()-4]; }
257 { m_tsPayload[AFCOffset()-4] = sof; }
258
259 QString toString(void) const;
260
261 static constexpr unsigned int kSize {188};
262 static constexpr unsigned int kPayloadSize {188-4};
263 static constexpr unsigned int kDVBEmissionSize {204};
264 static constexpr unsigned int kISDBEmissionSize {204};
265 static constexpr unsigned int k8VSBEmissionSize {208};
266 static const TSPacket *kNullPacket;
267 private:
268 std::array<uint8_t,184> m_tsPayload; // Intentionally no initialization
269};
270
271static_assert(sizeof(TSPacket) == 188,
272 "The TSPacket class must be 188 bytes in size. It must "
273 "have only one non-static variable (m_tsPayload) of 184 "
274 "bytes, and it must not have any virtual functions.");
275
276// NOLINTEND(cppcoreguidelines-pro-type-member-init)
277
278#if 0 /* not used yet */
282class MTV_PUBLIC TSDVBEmissionPacket : public TSPacket
283{
284 private:
285 unsigned char m_tsFec[16];
286};
287
291class MTV_PUBLIC TSISDBEmissionPacket : public TSPacket
292{
293 private:
294 unsigned char m_tsFec[16];
295};
296
300class MTV_PUBLIC TS8VSBEmissionPacket : public TSPacket
301{
302 private:
303 unsigned char m_tsFec[20];
304};
305#endif
306
307#endif // TS_PACKET_H
Allows us to transform TS packets to PES packets, which are used to hold multimedia streams and very ...
Definition: pespacket.h:26
Used to access header of a TSPacket.
Definition: tspacket.h:47
TSHeader(int cc)
Definition: tspacket.h:60
void SetAdaptationFieldControl(unsigned int afc)
Definition: tspacket.h:167
unsigned char * data(void)
Definition: tspacket.h:175
bool HasAdaptationField(void) const
Definition: tspacket.h:113
void SetScrambled(unsigned int scr)
Definition: tspacket.h:164
unsigned int ContinuityCounter(void) const
Definition: tspacket.h:109
unsigned int ScramblingControl(void) const
Definition: tspacket.h:97
int64_t GetPCRraw(void) const
Definition: tspacket.h:144
void InitHeader(const unsigned char *header)
Definition: tspacket.h:69
bool HasPCR(void) const
Definition: tspacket.h:121
std::chrono::steady_clock Clock
Definition: tspacket.h:49
bool GetDiscontinuityIndicator(void) const
Definition: tspacket.h:118
std::chrono::time_point< Clock, std::chrono::microseconds > TimePoint
Definition: tspacket.h:50
unsigned int PID(void) const
Definition: tspacket.h:93
bool HasPayload(void) const
Definition: tspacket.h:116
TSHeader(void)
Definition: tspacket.h:52
bool PayloadStart(void) const
Definition: tspacket.h:89
unsigned int AdaptationFieldControl(void) const
Definition: tspacket.h:103
TimePoint GetPCR(void) const
Definition: tspacket.h:148
TSHeaderArray m_tsData
Definition: tspacket.h:180
bool TransportError(void) const
Definition: tspacket.h:86
int32_t GetPCRext(void) const
Definition: tspacket.h:139
void SetTransportError(bool err)
Definition: tspacket.h:151
bool Scrambled(void) const
Definition: tspacket.h:112
bool HasSync(void) const
Definition: tspacket.h:83
void SetContinuityCounter(unsigned int cc)
Definition: tspacket.h:170
void SetPayloadStart(bool start)
Definition: tspacket.h:154
static const TSHeaderArray kPayloadOnlyHeader
Definition: tspacket.h:178
void SetPID(unsigned int pid)
Definition: tspacket.h:160
bool Priority(void) const
Definition: tspacket.h:91
void SetPriority(bool priority)
Definition: tspacket.h:157
const unsigned char * data(void) const
Definition: tspacket.h:174
int64_t GetPCRbase(void) const
Definition: tspacket.h:131
size_t AdaptationFieldSize(void) const
Definition: tspacket.h:114
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:208
static constexpr unsigned int kPayloadSize
Definition: tspacket.h:262
void InitPayload(const unsigned char *payload)
Definition: tspacket.h:230
unsigned int AFCOffset(void) const
Definition: tspacket.h:249
std::array< uint8_t, 184 > m_tsPayload
Definition: tspacket.h:268
void InitPayload(const unsigned char *payload, uint size)
Definition: tspacket.h:236
TSPacket * CreateClone(void) const
Definition: tspacket.h:224
static TSPacket * CreatePayloadOnlyPacket(void)
Definition: tspacket.h:215
unsigned int StartOfFieldPointer(void) const
Definition: tspacket.h:254
static const TSPacket * kNullPacket
Definition: tspacket.h:266
TSPacket(void)=default
void SetStartOfFieldPointer(uint sof)
Definition: tspacket.h:256
unsigned int uint
Definition: freesurround.h:24
#define MTV_PUBLIC
Definition: mythtvexp.h:15
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
std::array< uint8_t, 4 > TSHeaderArray
Definition: tspacket.h:23
static constexpr uint8_t SYNC_BYTE
Definition: tspacket.h:21
std::chrono::time_point< Clock > TimePoint
Definition: zmserver.h:29