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; };
21 static constexpr uint8_t SYNC_BYTE { 0x47 };
22 
23 using 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 
52  TSHeader(void)
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 
118  bool GetDiscontinuityIndicator(void) const
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 
183 static_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 
271 static_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 */
279 
282 class MTV_PUBLIC TSDVBEmissionPacket : public TSPacket
283 {
284  private:
285  unsigned char m_tsFec[16];
286 };
287 
291 class MTV_PUBLIC TSISDBEmissionPacket : public TSPacket
292 {
293  private:
294  unsigned char m_tsFec[16];
295 };
296 
300 class MTV_PUBLIC TS8VSBEmissionPacket : public TSPacket
301 {
302  private:
303  unsigned char m_tsFec[20];
304 };
305 #endif
306 
307 #endif // TS_PACKET_H
TSHeader::TSHeader
TSHeader(int cc)
Definition: tspacket.h:60
TSHeader::PayloadStart
bool PayloadStart(void) const
Definition: tspacket.h:89
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
TSHeader::AdaptationFieldSize
size_t AdaptationFieldSize(void) const
Definition: tspacket.h:114
TSHeader::Priority
bool Priority(void) const
Definition: tspacket.h:91
TSHeader::ScramblingControl
unsigned int ScramblingControl(void) const
Definition: tspacket.h:97
TSPacket::StartOfFieldPointer
unsigned int StartOfFieldPointer(void) const
Definition: tspacket.h:254
TSHeader::data
unsigned char * data(void)
Definition: tspacket.h:175
TSHeader::HasPCR
bool HasPCR(void) const
Definition: tspacket.h:121
TSHeader::m_tsData
TSHeaderArray m_tsData
Definition: tspacket.h:180
TSPacket::SetStartOfFieldPointer
void SetStartOfFieldPointer(uint sof)
Definition: tspacket.h:256
TSHeader::SetScrambled
void SetScrambled(unsigned int scr)
Definition: tspacket.h:164
mythtvexp.h
TSHeader::PID
unsigned int PID(void) const
Definition: tspacket.h:93
TSPacket::AFCOffset
unsigned int AFCOffset(void) const
Definition: tspacket.h:249
TimePoint
std::chrono::time_point< Clock > TimePoint
Definition: zmserver.h:29
x3
static int x3
Definition: mythsocket.cpp:52
TSPacket::CreateClone
TSPacket * CreateClone(void) const
Definition: tspacket.h:224
TSHeader::Scrambled
bool Scrambled(void) const
Definition: tspacket.h:112
TSHeader::GetPCRraw
int64_t GetPCRraw(void) const
Definition: tspacket.h:144
TSHeader::kPayloadOnlyHeader
static const TSHeaderArray kPayloadOnlyHeader
Definition: tspacket.h:178
TSHeader::SetAdaptationFieldControl
void SetAdaptationFieldControl(unsigned int afc)
Definition: tspacket.h:167
TSHeader::HasAdaptationField
bool HasAdaptationField(void) const
Definition: tspacket.h:113
TSHeader::ContinuityCounter
unsigned int ContinuityCounter(void) const
Definition: tspacket.h:109
TSHeader::SetContinuityCounter
void SetContinuityCounter(unsigned int cc)
Definition: tspacket.h:170
TSHeader::GetDiscontinuityIndicator
bool GetDiscontinuityIndicator(void) const
Definition: tspacket.h:118
TSHeader::SetPriority
void SetPriority(bool priority)
Definition: tspacket.h:157
MythFile::copy
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
Definition: mythmiscutil.cpp:263
TSPacket
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:207
x1
static int x1
Definition: mythsocket.cpp:50
TSPacket::m_tsPayload
std::array< uint8_t, 184 > m_tsPayload
Definition: tspacket.h:268
TSHeader::GetPCRbase
int64_t GetPCRbase(void) const
Definition: tspacket.h:131
TSHeader::SetPayloadStart
void SetPayloadStart(bool start)
Definition: tspacket.h:154
TSPacket::InitPayload
void InitPayload(const unsigned char *payload, uint size)
Definition: tspacket.h:236
TSPacket::CreatePayloadOnlyPacket
static TSPacket * CreatePayloadOnlyPacket(void)
Definition: tspacket.h:215
TSPacket::kPayloadSize
static constexpr unsigned int kPayloadSize
Definition: tspacket.h:262
TSPacket::InitPayload
void InitPayload(const unsigned char *payload)
Definition: tspacket.h:230
MTV_PUBLIC
#define MTV_PUBLIC
Definition: mythtvexp.h:15
PESPacket
Allows us to transform TS packets to PES packets, which are used to hold multimedia streams and very ...
Definition: pespacket.h:25
TSHeader::SetTransportError
void SetTransportError(bool err)
Definition: tspacket.h:151
TSHeader::AdaptationFieldControl
unsigned int AdaptationFieldControl(void) const
Definition: tspacket.h:103
TSPacket::kNullPacket
static const TSPacket * kNullPacket
Definition: tspacket.h:266
TSHeaderArray
std::array< uint8_t, 4 > TSHeaderArray
Definition: tspacket.h:23
TSHeader::Clock
std::chrono::steady_clock Clock
Definition: tspacket.h:49
TSHeader::SetPID
void SetPID(unsigned int pid)
Definition: tspacket.h:160
TSHeader::HasPayload
bool HasPayload(void) const
Definition: tspacket.h:116
TSHeader
Used to access header of a TSPacket.
Definition: tspacket.h:46
TSHeader::GetPCRext
int32_t GetPCRext(void) const
Definition: tspacket.h:139
SYNC_BYTE
static constexpr uint8_t SYNC_BYTE
Definition: tspacket.h:21
TSHeader::HasSync
bool HasSync(void) const
Definition: tspacket.h:83
TSHeader::GetPCR
TimePoint GetPCR(void) const
Definition: tspacket.h:148
TSHeader::TSHeader
TSHeader(void)
Definition: tspacket.h:52
TSHeader::data
const unsigned char * data(void) const
Definition: tspacket.h:174
TSHeader::TimePoint
std::chrono::time_point< Clock, std::chrono::microseconds > TimePoint
Definition: tspacket.h:50
TSHeader::InitHeader
void InitHeader(const unsigned char *header)
Definition: tspacket.h:69
TSHeader::TransportError
bool TransportError(void) const
Definition: tspacket.h:86
uint
unsigned int uint
Definition: freesurround.h:24