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