vdr-plugin-softhddevice-drm-gles 1.4.0
pes.cpp
Go to the documentation of this file.
1
18#include <stdexcept>
19#include <map>
20#include <functional>
21
22#include "pes.h"
23#include "logger.h"
24
25#include "vdr/remux.h"
26
27extern "C"
28{
29#include <libavutil/avutil.h>
30}
31
32static uint32_t ReadBytes(const uint8_t *data, int count)
33{
34 uint32_t value = 0;
35
36 for (int i = 0; i < count; i++) {
37 value <<= 8;
38 value |= data[i];
39 }
40
41 return value;
42}
43
48struct CodecInfo {
50 std::function<bool(const uint8_t*)> MatchSyncWord;
51 std::function<int(const uint8_t*)> GetFrameSize;
52};
53
59static const std::map<AVCodecID, CodecInfo> AudioCodecMap = {
60 {AV_CODEC_ID_MP2, {
61 .minSize = 3,
62 .MatchSyncWord = [](const uint8_t* data) -> bool {
63 constexpr uint32_t MPEG_AUDIO_SYNC_WORD = 0xFF'E000;
64 constexpr uint32_t MPEG_AUDIO_VERSION_FORBIDDEN_VALUE = 0x00'0800;
65 constexpr uint32_t MPEG_AUDIO_LAYER_DESCRIPTION_FORBIDDEN_VALUE = 0x00'0000;
66 constexpr uint32_t MPEG_AUDIO_BITRATE_INDEX_FORBIDDEN_VALUE = 0x00'00F0;
67
68 uint32_t syncWord = ReadBytes(data, 3);
69 return (syncWord & 0b1111'1111'1110'0000'0000'0000) == MPEG_AUDIO_SYNC_WORD &&
70 (syncWord & 0b0000'0000'0001'1000'0000'0000) != MPEG_AUDIO_VERSION_FORBIDDEN_VALUE &&
71 (syncWord & 0b0000'0000'0000'0110'0000'0000) != MPEG_AUDIO_LAYER_DESCRIPTION_FORBIDDEN_VALUE &&
72 (syncWord & 0b0000'0000'0000'0000'1111'0000) != MPEG_AUDIO_BITRATE_INDEX_FORBIDDEN_VALUE;
73 },
74 .GetFrameSize = [](const uint8_t* data) -> int {
75 constexpr uint16_t BitRateTable[2][4][16] = {
76 // MPEG Version 1
77 {{},
78 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
79 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
80 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}},
81 // MPEG Version 2 & 2.5
82 {{},
83 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
84 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
85 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
86 }
87 };
88 constexpr uint16_t SampleRateTable[4] = {44100, 48000, 32000, 0};
89
90 int mpeg2 = !(data[1] & 0x08) && (data[1] & 0x10);
91 int mpeg25 = !(data[1] & 0x08) && !(data[1] & 0x10);
92 int layer = 4 - ((data[1] >> 1) & 0x03);
93 int bitRateIndex = (data[2] >> 4) & 0x0F;
94 int sampleRateIndex = (data[2] >> 2) & 0x03;
95 int padding = (data[2] >> 1) & 0x01;
96
97 int sampleRate = SampleRateTable[sampleRateIndex];
98 if (!sampleRate)
99 throw std::invalid_argument("MPEG: invalid sample rate");
100
101 sampleRate >>= mpeg2;
102 sampleRate >>= mpeg25;
103
104 int bitRate = BitRateTable[mpeg2 | mpeg25][layer][bitRateIndex];
105 if (!bitRate)
106 throw std::invalid_argument("MPEG: invalid bit rate");
107
108 bitRate *= 1000;
109 int frameSize;
110 switch (layer) {
111 case 1:
112 frameSize = (12 * bitRate) / sampleRate;
113 frameSize = (frameSize + padding) * 4;
114 break;
115 case 2:
116 case 3:
117 default:
118 frameSize = (144 * bitRate) / sampleRate;
119 frameSize = frameSize + padding;
120 break;
121 }
122 return frameSize;
123 }
124 }},
125 {AV_CODEC_ID_AAC_LATM, {
126 .minSize = 3,
127 .MatchSyncWord = [](const uint8_t* data) -> bool {
128 constexpr uint32_t LAOS_SYNC_WORD_MASK = 0xFFE000;
129 constexpr uint32_t LAOS_SYNC_WORD = 0x2B7 << (24-11);
130
131 uint32_t syncWord = ReadBytes(data, 3);
132 return (syncWord & LAOS_SYNC_WORD_MASK) == LAOS_SYNC_WORD;
133 },
134 .GetFrameSize = [](const uint8_t* data) -> int {
135 return ((data[1] & 0x1F) << 8) + data[2] + 3;
136 }
137 }},
138 {AV_CODEC_ID_AC3, {
139 .minSize = 6,
140 .MatchSyncWord = [](const uint8_t* data) -> bool {
141 constexpr uint32_t AC3_SYNC_WORD_MASK = 0xFFFF00;
142 constexpr uint32_t AC3_SYNC_WORD = 0x0B77 << (24-16);
143
144 uint32_t syncWord = ReadBytes(data, 3);
145 return (syncWord & AC3_SYNC_WORD_MASK) == AC3_SYNC_WORD &&
146 data[5] <= (10 << 3);
147 },
148 .GetFrameSize = [](const uint8_t* data) -> int {
149 constexpr uint16_t Ac3FrameSizeTable[38][3] = {
150 {64, 69, 96}, {64, 70, 96}, {80, 87, 120}, {80, 88, 120},
151 {96, 104, 144}, {96, 105, 144}, {112, 121, 168}, {112, 122, 168},
152 {128, 139, 192}, {128, 140, 192}, {160, 174, 240}, {160, 175, 240},
153 {192, 208, 288}, {192, 209, 288}, {224, 243, 336}, {224, 244, 336},
154 {256, 278, 384}, {256, 279, 384}, {320, 348, 480}, {320, 349, 480},
155 {384, 417, 576}, {384, 418, 576}, {448, 487, 672}, {448, 488, 672},
156 {512, 557, 768}, {512, 558, 768}, {640, 696, 960}, {640, 697, 960},
157 {768, 835, 1152}, {768, 836, 1152}, {896, 975, 1344}, {896, 976, 1344},
158 {1024, 1114, 1536}, {1024, 1115, 1536}, {1152, 1253, 1728},
159 {1152, 1254, 1728}, {1280, 1393, 1920}, {1280, 1394, 1920},
160 };
161
162 int fscod = data[4] >> 6;
163 if (fscod == 0x03)
164 throw std::invalid_argument("AC3: invalid sample rate");
165
166 int frmsizcod = data[4] & 0x3F;
167 if (frmsizcod > 37)
168 throw std::invalid_argument("AC3: invalid frame size");
169
170 return Ac3FrameSizeTable[frmsizcod][fscod] * 2;
171 }
172 }},
173 {AV_CODEC_ID_EAC3, {
174 .minSize = 6,
175 .MatchSyncWord = [](const uint8_t* data) -> bool {
176 constexpr uint32_t AC3_SYNC_WORD = 0x0B77 << (24-16);
177
178 uint32_t syncWord = ReadBytes(data, 3);
179 return (syncWord & 0xFFFF00) == AC3_SYNC_WORD && data[5] > (10 << 3);
180 },
181 .GetFrameSize = [](const uint8_t* data) -> int {
182 if ((data[4] & 0xF0) == 0xF0)
183 throw std::invalid_argument("AC3: invalid fscod fscod2");
184
185 return (((data[2] & 0x07) << 8) + data[3] + 1) * 2;
186 }
187 }},
188 {AV_CODEC_ID_AAC, {
189 .minSize = 3,
190 .MatchSyncWord = [](const uint8_t* data) -> bool {
191 constexpr uint32_t ADTS_SYNC_WORD = 0xFFF000;
192 constexpr uint32_t ADTS_LAYER = 0x000000;
193 constexpr uint32_t ADTS_SAMPLING_FREQUENCY_FORBIDDEN_VALUE = 15 << 6;
194
195 uint32_t syncWord = ReadBytes(data, 3);
196 return (syncWord & 0b1111'1111'1111'0000'0000'0000) == ADTS_SYNC_WORD &&
197 (syncWord & 0b0000'0000'0000'0110'0000'0000) == ADTS_LAYER &&
198 (syncWord & 0b0000'0000'0000'0011'1100'0000) != ADTS_SAMPLING_FREQUENCY_FORBIDDEN_VALUE;
199 },
200 .GetFrameSize = [](const uint8_t* data) -> int {
201 return ((data[3] & 0x03) << 11) | ((data[4] & 0xFF) << 3) | ((data[5] & 0xE0) >> 5);
202 }
203 }}
204};
205
215cPes::cPes(const uint8_t *data, int size)
216 : m_data(data), m_size(size)
217{
218}
219
232 if (IsHeaderValid() && IsStreamIdValid()) {
233 if (m_size <= 8 || PesPayloadOffset(m_data) > m_size) // header length field is at position 8 when the PES extension is present
234 LOGWARNING("pes: %s: packet too short: %d %02X", __FUNCTION__, m_size, GetStreamId());
235 else
236 m_valid = true;
237 } else
238 LOGDEBUG("pes: %s: invalid packet: %d %02X", __FUNCTION__, m_size, GetStreamId());
239}
240
257 return m_valid;
258}
259
270{
271 return PesLongEnough(m_size) && ReadBytes(m_data, 3) == PES_PACKET_START_CODE_PREFIX;
272}
273
283{
284 return PesHasPts(m_data);
285}
286
296{
297 if (!HasPts())
298 return AV_NOPTS_VALUE;
299
300 return PesGetPts(m_data);
301}
302
311const uint8_t *cPes::GetPayload()
312{
313 return &m_data[PesPayloadOffset(m_data)];
314}
315
325{
326 return m_size - PesPayloadOffset(m_data);
327}
328
347{
348 if (!PesHasLength(m_data))
349 return m_size; // Length field is 0, meaning unbounded/unspecified. Return raw data size.
350
351 return PesLength(m_data);
352}
353
354#include "misc.h"
365{
366 if (size == 0)
367 return nullptr;
368
369 AVPacket *avpkt = av_packet_alloc();
370
371 if (!avpkt)
372 LOGFATAL("pes: %s: out of memory while allocating AVPacket", __FUNCTION__);
373
374 if (av_new_packet(avpkt, size)) // allocates size + AV_INPUT_BUFFER_PADDING_SIZE
375 LOGFATAL("pes: %s: out of memory while allocating AVPacket payload", __FUNCTION__);
376
377 memcpy(avpkt->data, m_buffer.Peek(), size);
378 memset(&avpkt->data[size], 0, AV_INPUT_BUFFER_PADDING_SIZE);
379
380 // Only audio:
381 // If a PES packet contains multiple frames, only the AVPacket with the first frame of that PES packet shall have a PTS value, when sending it to the decoder.
382 // The following AVPackets created from this PES packet shall have no PTS value.
383 // When retrieving PTS values from the same PES packet, they will be identical.
385 avpkt->pts = m_buffer.GetPts();
386 else
387 avpkt->pts = AV_NOPTS_VALUE;
388
390
391 m_buffer.Erase(size);
392
393 return avpkt;
394}
395
396/*
397 * Video specific implementation
398 */
399
411bool cReassemblyBufferVideo::ParseCodecHeader(const uint8_t *fragment, int size) {
412 const uint8_t *codecPayload = &fragment[VIDEO_FRAME_START_CODE_LEN];
413 uint32_t startCode = ReadBytes(fragment, VIDEO_FRAME_START_CODE_LEN);
414
415 // Looking for the MPEG2 start code and stream type in the PES payload
416 if (startCode == VIDEO_FRAME_START_CODE && codecPayload[0] == MPEG2_STREAM_TYPE)
417 m_codec = AV_CODEC_ID_MPEG2VIDEO;
418 else if (HasLeadingZero(fragment, size)) // Looking for a leading zero byte in front of the start code. Can be present in H.264/HEVC streams.
419 codecPayload++;
420 else if (startCode != VIDEO_FRAME_START_CODE)
421 return false; // No start code: PES packet carries fragmented payload, or unknown codec.
422
423 if (size > &codecPayload[7] - fragment) {
424 if ( codecPayload[0] == H264_STREAM_TYPE && (codecPayload[1] == 0x10 || codecPayload[1] == 0xF0 || codecPayload[7] == 0x64))
425 m_codec = AV_CODEC_ID_H264;
426 else if (codecPayload[0] == HEVC_STREAM_TYPE && (codecPayload[1] == 0x10 || codecPayload[1] == 0x50 || codecPayload[7] == 0x40))
427 m_codec = AV_CODEC_ID_HEVC;
428 }
429
430 return m_codec != AV_CODEC_ID_NONE;
431}
432
444bool cReassemblyBufferVideo::HasLeadingZero(const uint8_t *data, int size)
445{
446 return size > VIDEO_FRAME_START_CODE_LEN + 1 && data[0] == 0 && ReadBytes(&data[1], VIDEO_FRAME_START_CODE_LEN) == VIDEO_FRAME_START_CODE;
447}
448
449/*
450 * Audio specific implementation
451 */
452
462{
463 AVCodecID detectedCodec = TruncateBufferUntilFirstValidData();
464
465 if (detectedCodec == AV_CODEC_ID_NONE)
466 return nullptr; // No sync word found in the buffer. Wait for more data.
467 else if (m_codec != AV_CODEC_ID_NONE && detectedCodec != m_codec)
468 LOGERROR("pes: %s: audio codec changed unexpectedly from %d to %d", __FUNCTION__, avcodec_get_name(m_codec), avcodec_get_name(detectedCodec));
469
470 m_codec = detectedCodec;
471
472 try {
473 AVPacket *packet = cReassemblyBuffer::PopAvPacket(AudioCodecMap.at(m_codec).GetFrameSize(m_buffer.Peek()));
474
475 if (m_ptsInvalid) { // the PTS is invalid for this packet because the buffer was truncated before
476 packet->pts = AV_NOPTS_VALUE;
477
478 m_ptsInvalid = false;
479 }
480
481 return packet;
482 } catch (const std::invalid_argument &e) {
483 LOGWARNING("pes: %s: garbage in audio stream received: %s", __FUNCTION__, e.what());
484 // the garbage will be removed in the next call to TruncateBufferUntilFirstValidData()
485 }
486
487 return nullptr;
488}
489
500 int sizeBeforeTruncation = m_buffer.GetSize();
501
503
504 m_buffer.Erase(firstFrame.pos);
505
506 if (m_buffer.GetSize() < sizeBeforeTruncation) {
507 LOGDEBUG("pes: %s: truncated %d of %d bytes while searching for sync word", __FUNCTION__, sizeBeforeTruncation - m_buffer.GetSize(), sizeBeforeTruncation);
508 m_ptsInvalid = true;
509 }
510
511 return firstFrame.codecId;
512}
513
527{
528 while (true) {
530
531 if (firstFrame.codecId == AV_CODEC_ID_NONE) // No sync word found in the entire buffer. Keep only the last few bytes that could contain a partial sync word.
532 return SyncWordInfo{AV_CODEC_ID_NONE, std::max(0, (int)m_buffer.GetSize() - MAX_HEADER_SIZE)};
533
534 try {
535 // determine the length of the first found potential frame by reading the frame's header
536 int sizeOfFirstFrame = AudioCodecMap.at(firstFrame.codecId).GetFrameSize(&m_buffer.Peek()[firstFrame.pos]);
537 int secondSyncWord = firstFrame.pos + sizeOfFirstFrame;
538
539 // check if another sync word follows immediately after the first frame to validate the header of the first frame is a real header and no random data
540 if (secondSyncWord + MAX_HEADER_SIZE > (int)m_buffer.GetSize()) {
541 // Could not find the second sync word, because there might not be enough data in the buffer to contain a complete second sync word. Wait for more data.
542 // In case we have a false positive and the header's frame size field is invalid, we buffer the following amount of data in worst-case:
543 // - MP2: 6913 bytes (Layer 2/3: 384kbps @ 8kHz + padding)
544 // - AAC LATM: 8194 bytes (13-bit length field max: 0x1FFF + 3)
545 // - AC3: 2788 bytes (frmsizcod=37, fscod=1: 1394 * 2)
546 // - EAC3: 4096 bytes (11-bit field max: 2048 * 2)
547 // - AAC ADTS: 8191 bytes (13-bit length field max: 0x1FFF)
548 return SyncWordInfo{AV_CODEC_ID_NONE, firstFrame.pos};
549 } else if (DetectCodecFromSyncWord(&m_buffer.Peek()[secondSyncWord], m_buffer.GetSize() - secondSyncWord) == firstFrame.codecId)
550 // two consecutive frames with the same sync word found, and the first frame's header length field is valid
551 return SyncWordInfo{firstFrame.codecId, firstFrame.pos};
552 } catch (const std::invalid_argument &e) {
553 // Failed to read the frame size from the first frame's header. The found sync word is a false positive.
554 }
555
556 // If we found one sync word, but did not find a second one at the expected position, the first one was a false positive in the middle of random data.
557 // In this case, continue the search one position after the start of the first found sync word.
558 m_buffer.Erase(firstFrame.pos + 1);
559 }
560}
561
574{
575 for (int i = 0; i < size; i++) {
576 AVCodecID detectedCodec = DetectCodecFromSyncWord(&data[i], size - i);
577 if (detectedCodec != AV_CODEC_ID_NONE)
578 return SyncWordInfo{detectedCodec, i};
579 }
580
581 return SyncWordInfo{AV_CODEC_ID_NONE, -1};
582}
583
595AVCodecID cReassemblyBufferAudio::DetectCodecFromSyncWord(const uint8_t *syncWord, int size)
596{
597 for (const auto& [codecId, codecInfo] : AudioCodecMap) {
598 if (size >= codecInfo.minSize && codecInfo.MatchSyncWord(syncWord)) {
599 return codecId;
600 }
601 }
602
603 return AV_CODEC_ID_NONE;
604}
605
619int cReassemblyBufferAudio::GetFrameSizeForCodec(AVCodecID codec, const uint8_t *data)
620{
621 return AudioCodecMap.at(codec).GetFrameSize(data);
622}
623
630{
631 m_buffer.Reset();
632 m_codec = AV_CODEC_ID_NONE;
634}
635
636/*
637 * PTS tracking buffer
638 */
639
650void cPtsTrackingBuffer::Push(const uint8_t *data, int size, int64_t pts) {
651 if (pts != AV_NOPTS_VALUE) // PES packets not starting with a new frame (fragmented data) have no PTS
652 m_pts[m_data.size()] = pts;
653
654 m_data.insert(m_data.end(), data, data + size);
655}
656
670void cPtsTrackingBuffer::Erase(size_t amount) {
671 if (m_data.empty() || amount == 0)
672 return;
673
674 // Only PES packets have PTS values, but not the (fragmented) frames inside.
675 // The reassembled frame's PTS value will become the PTS value of the PES packet where the frame starts.
676 // Therefore, always keep the PTS value for position 0 in the buffer, which is the PTS value of the PES packet where the frame starts.
677 // This is normally the largest PTS value to be removed, or, if future position 0 already has a PTS value, that value will be used.
678 int64_t smallestPts = AV_NOPTS_VALUE;
679 auto it = m_pts.upper_bound(amount);
680 if (it == m_pts.begin())
681 LOGFATAL("pes: %s: %s: no PTS value found for position 0 after erasing %zu bytes", __FUNCTION__, m_identifier, amount);
682 else {
683 --it; // Move to the last entry before 'amount'
684 smallestPts = it->second;
685 }
686
687 std::map<size_t, int64_t> adjusted_pts;
688 for (const auto& [pos, pts] : m_pts) {
689 if (pos >= amount) // erase all PTS entries for data that will be removed
690 adjusted_pts[pos - amount] = pts; // adjust remaining PTS entries to the new data indices
691 }
692 m_pts = std::move(adjusted_pts);
693
694 m_pts[0] = smallestPts;
695
696 m_data.erase(m_data.begin(), m_data.begin() + amount);
697}
698
708 if (m_pts.empty())
709 return AV_NOPTS_VALUE;
710
711 return m_pts.begin()->second;
712}
bool IsValid()
Check if the PES packet is valid.
Definition: pes.cpp:256
static constexpr uint32_t PES_PACKET_START_CODE_PREFIX
Definition: pes.h:61
bool m_valid
flag indicating if the PES packet is valid
Definition: pes.h:55
uint8_t GetStreamId()
Definition: pes.h:48
int GetPayloadSize()
Get the size of the PES payload.
Definition: pes.cpp:324
int m_size
size of the PES packet
Definition: pes.h:57
cPes(const uint8_t *, int)
Construct a PES packet parser.
Definition: pes.cpp:215
int GetPacketLength()
Get the total length of the PES packet.
Definition: pes.cpp:346
const uint8_t * GetPayload()
Get a pointer to the PES payload data.
Definition: pes.cpp:311
const uint8_t * m_data
pointer to the raw PES packet data
Definition: pes.h:56
virtual bool IsStreamIdValid()=0
void Init()
Initialize and validate the PES packet.
Definition: pes.cpp:231
bool IsHeaderValid()
Check if the PES header is valid.
Definition: pes.cpp:269
bool HasPts()
Check if the PES packet contains a Presentation Time Stamp (PTS)
Definition: pes.cpp:282
int64_t GetPts()
Get the Presentation Time Stamp (PTS) from the PES header.
Definition: pes.cpp:295
int GetSize()
Definition: pes.h:107
void Push(const uint8_t *, int, int64_t)
Push data into the PTS tracking buffer.
Definition: pes.cpp:650
std::vector< uint8_t > m_data
Byte buffer.
Definition: pes.h:112
std::map< size_t, int64_t > m_pts
Map of buffer positions to PTS values.
Definition: pes.h:111
void Reset()
Definition: pes.h:106
const uint8_t * Peek()
Definition: pes.h:105
void Erase(size_t)
Erase data from the beginning of the buffer.
Definition: pes.cpp:670
const char * m_identifier
Definition: pes.h:110
int64_t GetPts()
Get the PTS value for the current buffer position.
Definition: pes.cpp:707
AVPacket * PopAvPacket() override
Pop an audio AVPacket from the reassembly buffer.
Definition: pes.cpp:461
static constexpr int MAX_HEADER_SIZE
Definition: pes.h:182
AVCodecID TruncateBufferUntilFirstValidData()
Truncate buffer until the first valid audio frame.
Definition: pes.cpp:499
AVCodecID DetectCodecFromSyncWord(const uint8_t *, int)
Detect audio codec from sync word pattern.
Definition: pes.cpp:595
SyncWordInfo FindSyncWord(const uint8_t *, int)
Find the first audio sync word in data.
Definition: pes.cpp:573
SyncWordInfo FindTwoConsecutiveFramesWithSameSyncWord()
Find two consecutive audio frames with the same sync word.
Definition: pes.cpp:526
bool m_ptsInvalid
flag indicating if PTS is invalid for current buffer, because it was truncated
Definition: pes.h:183
int GetFrameSizeForCodec(AVCodecID, const uint8_t *)
Get the frame size for a given codec and frame header.
Definition: pes.cpp:619
static constexpr uint32_t VIDEO_FRAME_START_CODE
Definition: pes.h:150
static constexpr int VIDEO_FRAME_START_CODE_LEN
Definition: pes.h:151
static constexpr uint8_t H264_STREAM_TYPE
Definition: pes.h:154
static constexpr uint8_t MPEG2_STREAM_TYPE
Definition: pes.h:153
bool HasLeadingZero(const uint8_t *, int)
Check if video data has a leading zero byte before the start code.
Definition: pes.cpp:444
static constexpr uint8_t HEVC_STREAM_TYPE
Definition: pes.h:155
bool ParseCodecHeader(const uint8_t *, int)
Parse video codec header to detect codec type.
Definition: pes.cpp:411
AVCodecID m_codec
detected codec ID
Definition: pes.h:132
virtual AVPacket * PopAvPacket()=0
int64_t m_lastPoppedPts
PTS of the last popped AVPacket.
Definition: pes.h:134
cPtsTrackingBuffer m_buffer
fragmentation buffer
Definition: pes.h:133
void Reset()
Reset the reassembly buffer.
Definition: pes.cpp:629
Logger class header file.
#define LOGDEBUG
Definition: logger.h:49
#define LOGERROR
Definition: logger.h:46
#define LOGWARNING
Definition: logger.h:47
#define LOGFATAL
Logger macros.
Definition: logger.h:45
Misc function header file.
#define AV_NOPTS_VALUE
Definition: misc.h:35
static uint32_t ReadBytes(const uint8_t *data, int count)
Definition: pes.cpp:32
static const std::map< AVCodecID, CodecInfo > AudioCodecMap
Map of audio codec information Key: AVCodecID Value: CodecInfo with sync word detection and frame siz...
Definition: pes.cpp:59
PES packet parser header.
Codec information structure Contains lambdas for sync word detection and frame size calculation.
Definition: pes.cpp:48
std::function< int(const uint8_t *)> GetFrameSize
Definition: pes.cpp:51
int minSize
Definition: pes.cpp:49
std::function< bool(const uint8_t *)> MatchSyncWord
Definition: pes.cpp:50
Information about a detected audio sync word.
Definition: pes.h:161
AVCodecID codecId
Detected codec ID.
Definition: pes.h:162
int pos
Position of sync word in buffer.
Definition: pes.h:163