libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
mpegtsdemuxer.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <cstdint>
14#include <promeki/namespace.h>
15#include <promeki/buffer.h>
16#include <promeki/bufferview.h>
17#include <promeki/error.h>
18#include <promeki/function.h>
19#include <promeki/list.h>
20#include <promeki/map.h>
21#include <promeki/mpegts.h>
22
23PROMEKI_NAMESPACE_BEGIN
24
80class MpegTsDemuxer {
81 public:
92 struct AccessUnit {
93 uint16_t pid = 0;
94 MpegTs::StreamType streamType = MpegTs::StreamTypeReserved;
106 uint32_t registrationFormat = 0;
107 BufferView payload;
108 bool hasPts = false;
109 bool hasDts = false;
110 uint64_t pts90k = 0;
111 uint64_t dts90k = 0;
112 bool randomAccess = false;
113 bool dataAlignment = false;
114 bool discontinuity = false;
115 };
116
124 using StreamCallback = Function<Error(const AccessUnit &)>;
125
135 using ProgramCallback = Function<void()>;
136
148 using PcrCallback = Function<void(uint16_t pid, uint64_t pcr27mhz)>;
149
150 MpegTsDemuxer();
151 ~MpegTsDemuxer();
152
154 void setStreamCallback(StreamCallback cb) { _streamCallback = std::move(cb); }
155
157 void setProgramCallback(ProgramCallback cb) { _programCallback = std::move(cb); }
158
167 void setPcrCallback(PcrCallback cb) { _pcrCallback = std::move(cb); }
168
181 Error push(const BufferView &data);
182
192 Error flush();
193
199 uint16_t pmtPid() const { return _pmtPid; }
200
205 uint16_t programNumber() const { return _programNumber; }
206
212 uint16_t pcrPid() const { return _pcrPid; }
213
218 struct StreamInfo {
219 uint16_t pid = 0;
220 MpegTs::StreamType streamType = MpegTs::StreamTypeReserved;
227 uint32_t registrationFormat = 0;
228 };
229
236 List<StreamInfo> streams() const;
237
243 uint64_t continuityErrors() const { return _continuityErrors; }
244
250 uint64_t bytesDiscarded() const { return _bytesDiscarded; }
251
252 private:
263 struct PsiReasm {
264 Buffer buffer;
265 size_t writePos = 0;
266 size_t expectedTotal = 0; // 0 = not yet known.
267 };
268
269 struct PesReasm {
270 MpegTs::StreamType streamType = MpegTs::StreamTypeReserved;
271 Buffer buffer;
272 size_t writePos = 0;
273 size_t expectedTotal = 0;
274 bool inProgress = false;
275 bool unbounded = false;
276 bool hasPts = false;
277 bool hasDts = false;
278 uint64_t pts90k = 0;
279 uint64_t dts90k = 0;
280 bool randomAccess = false;
281 bool dataAlignment = false;
282 bool discontinuity = false;
283 uint8_t continuityCounter = 0;
284 bool haveCc = false;
285 };
286
287 Error processPacket(const uint8_t *p);
288 Error processPsiPacket(const uint8_t *payload, size_t payloadLen, uint16_t pid, bool pusi);
289 Error dispatchPsiSection(uint16_t pid, const uint8_t *section, size_t len);
290 Error parsePat(const uint8_t *section, size_t len);
291 Error parsePmt(const uint8_t *section, size_t len);
292 Error finalizePes(uint16_t pid, PesReasm &pr);
293 Error startNewPes(uint16_t pid, PesReasm &pr, const uint8_t *pesStart, size_t pesAvail,
294 bool randomAccess, bool discontinuity);
295
296 StreamCallback _streamCallback;
297 ProgramCallback _programCallback;
298 PcrCallback _pcrCallback;
299
300 // Sync-alignment ring buffer. Holds up to (188 - 1)
301 // bytes carried over from one push() to the next.
302 uint8_t _carry[MpegTs::PacketSize];
303 size_t _carrySize = 0;
304
305 uint16_t _programNumber = 0;
306 uint16_t _pmtPid = MpegTs::PidNull;
307 uint16_t _pcrPid = MpegTs::PidNull;
308 bool _havePat = false;
309 bool _havePmt = false;
310
311 Map<uint16_t, MpegTs::StreamType> _streamTypeByPid;
312 Map<uint16_t, uint32_t> _registrationByPid;
313 Map<uint16_t, PesReasm> _pes;
314 Map<uint16_t, PsiReasm> _psi;
315
316 uint64_t _continuityErrors = 0;
317 uint64_t _bytesDiscarded = 0;
318};
319
320PROMEKI_NAMESPACE_END
321
322#endif // PROMEKI_ENABLE_PROAV