vdr-plugin-softhddevice-drm-gles 1.5.9-20e15de
pes.cpp
Go to the documentation of this file.
1
18#include <functional>
19#include <map>
20#include <stdexcept>
21
22#include "pes.h"
23#include "logger.h"
24#include "misc.h"
25
26#include "vdr/remux.h"
27
28extern "C" {
29#include <libavutil/avutil.h>
30}
31
36struct CodecInfo {
38 std::function<bool(const uint8_t*)> MatchSyncWord;
39 std::function<int(const uint8_t*)> GetFrameSize;
40};
41
47static const std::map<AVCodecID, CodecInfo> AudioCodecMap = {
48 {AV_CODEC_ID_MP2, {
49 .minSize = 3,
50 .MatchSyncWord = [](const uint8_t* data) -> bool {
51 constexpr uint32_t MPEG_AUDIO_SYNC_WORD = 0xFF'E000;
52 constexpr uint32_t MPEG_AUDIO_VERSION_FORBIDDEN_VALUE = 0x00'0800;
53 constexpr uint32_t MPEG_AUDIO_LAYER_DESCRIPTION_FORBIDDEN_VALUE = 0x00'0000;
54 constexpr uint32_t MPEG_AUDIO_BITRATE_INDEX_FORBIDDEN_VALUE = 0x00'00F0;
55
56 uint32_t syncWord = ReadBytes(data, 3);
57 return (syncWord & 0b1111'1111'1110'0000'0000'0000) == MPEG_AUDIO_SYNC_WORD &&
58 (syncWord & 0b0000'0000'0001'1000'0000'0000) != MPEG_AUDIO_VERSION_FORBIDDEN_VALUE &&
59 (syncWord & 0b0000'0000'0000'0110'0000'0000) != MPEG_AUDIO_LAYER_DESCRIPTION_FORBIDDEN_VALUE &&
60 (syncWord & 0b0000'0000'0000'0000'1111'0000) != MPEG_AUDIO_BITRATE_INDEX_FORBIDDEN_VALUE;
61 },
62 .GetFrameSize = [](const uint8_t* data) -> int {
63 constexpr uint16_t BitRateTable[2][4][16] = {
64 // MPEG Version 1
65 {{},
66 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
67 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
68 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}},
69 // MPEG Version 2 & 2.5
70 {{},
71 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
72 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
73 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
74 }
75 };
76 constexpr uint16_t SampleRateTable[4] = {44100, 48000, 32000, 0};
77
78 int mpeg2 = !(data[1] & 0x08) && (data[1] & 0x10);
79 int mpeg25 = !(data[1] & 0x08) && !(data[1] & 0x10);
80 int layer = 4 - ((data[1] >> 1) & 0x03);
81 int bitRateIndex = (data[2] >> 4) & 0x0F;
82 int sampleRateIndex = (data[2] >> 2) & 0x03;
83 int padding = (data[2] >> 1) & 0x01;
84
85 int sampleRate = SampleRateTable[sampleRateIndex];
86 if (!sampleRate)
87 throw std::invalid_argument("MPEG: invalid sample rate");
88
89 sampleRate >>= mpeg2;
90 sampleRate >>= mpeg25;
91
92 int bitRate = BitRateTable[mpeg2 | mpeg25][layer][bitRateIndex];
93 if (!bitRate)
94 throw std::invalid_argument("MPEG: invalid bit rate");
95
96 bitRate *= 1000;
97 int frameSize;
98 switch (layer) {
99 case 1:
100 frameSize = (12 * bitRate) / sampleRate;
101 frameSize = (frameSize + padding) * 4;
102 break;
103 case 2:
104 case 3:
105 default:
106 frameSize = (144 * bitRate) / sampleRate;
107 frameSize = frameSize + padding;
108 break;
109 }
110 return frameSize;
111 }
112 }},
113 {AV_CODEC_ID_AAC_LATM, {
114 .minSize = 3,
115 .MatchSyncWord = [](const uint8_t* data) -> bool {
116 constexpr uint32_t LAOS_SYNC_WORD_MASK = 0xFFE000;
117 constexpr uint32_t LAOS_SYNC_WORD = 0x2B7 << (24-11);
118
119 uint32_t syncWord = ReadBytes(data, 3);
120 return (syncWord & LAOS_SYNC_WORD_MASK) == LAOS_SYNC_WORD;
121 },
122 .GetFrameSize = [](const uint8_t* data) -> int {
123 return ((data[1] & 0x1F) << 8) + data[2] + 3;
124 }
125 }},
126 {AV_CODEC_ID_AC3, {
127 .minSize = 6,
128 .MatchSyncWord = [](const uint8_t* data) -> bool {
129 constexpr uint32_t AC3_SYNC_WORD_MASK = 0xFFFF00;
130 constexpr uint32_t AC3_SYNC_WORD = 0x0B77 << (24-16);
131
132 uint32_t syncWord = ReadBytes(data, 3);
133 return (syncWord & AC3_SYNC_WORD_MASK) == AC3_SYNC_WORD &&
134 data[5] <= (10 << 3);
135 },
136 .GetFrameSize = [](const uint8_t* data) -> int {
137 constexpr uint16_t Ac3FrameSizeTable[38][3] = {
138 {64, 69, 96}, {64, 70, 96}, {80, 87, 120}, {80, 88, 120},
139 {96, 104, 144}, {96, 105, 144}, {112, 121, 168}, {112, 122, 168},
140 {128, 139, 192}, {128, 140, 192}, {160, 174, 240}, {160, 175, 240},
141 {192, 208, 288}, {192, 209, 288}, {224, 243, 336}, {224, 244, 336},
142 {256, 278, 384}, {256, 279, 384}, {320, 348, 480}, {320, 349, 480},
143 {384, 417, 576}, {384, 418, 576}, {448, 487, 672}, {448, 488, 672},
144 {512, 557, 768}, {512, 558, 768}, {640, 696, 960}, {640, 697, 960},
145 {768, 835, 1152}, {768, 836, 1152}, {896, 975, 1344}, {896, 976, 1344},
146 {1024, 1114, 1536}, {1024, 1115, 1536}, {1152, 1253, 1728},
147 {1152, 1254, 1728}, {1280, 1393, 1920}, {1280, 1394, 1920},
148 };
149
150 int fscod = data[4] >> 6;
151 if (fscod == 0x03)
152 throw std::invalid_argument("AC3: invalid sample rate");
153
154 int frmsizcod = data[4] & 0x3F;
155 if (frmsizcod > 37)
156 throw std::invalid_argument("AC3: invalid frame size");
157
158 return Ac3FrameSizeTable[frmsizcod][fscod] * 2;
159 }
160 }},
161 {AV_CODEC_ID_EAC3, {
162 .minSize = 6,
163 .MatchSyncWord = [](const uint8_t* data) -> bool {
164 constexpr uint32_t AC3_SYNC_WORD = 0x0B77 << (24-16);
165
166 uint32_t syncWord = ReadBytes(data, 3);
167 return (syncWord & 0xFFFF00) == AC3_SYNC_WORD && data[5] > (10 << 3);
168 },
169 .GetFrameSize = [](const uint8_t* data) -> int {
170 if ((data[4] & 0xF0) == 0xF0)
171 throw std::invalid_argument("AC3: invalid fscod fscod2");
172
173 return (((data[2] & 0x07) << 8) + data[3] + 1) * 2;
174 }
175 }},
176 {AV_CODEC_ID_AAC, {
177 .minSize = 3,
178 .MatchSyncWord = [](const uint8_t* data) -> bool {
179 constexpr uint32_t ADTS_SYNC_WORD = 0xFFF000;
180 constexpr uint32_t ADTS_LAYER = 0x000000;
181 constexpr uint32_t ADTS_SAMPLING_FREQUENCY_FORBIDDEN_VALUE = 15 << 6;
182
183 uint32_t syncWord = ReadBytes(data, 3);
184 return (syncWord & 0b1111'1111'1111'0000'0000'0000) == ADTS_SYNC_WORD &&
185 (syncWord & 0b0000'0000'0000'0110'0000'0000) == ADTS_LAYER &&
186 (syncWord & 0b0000'0000'0000'0011'1100'0000) != ADTS_SAMPLING_FREQUENCY_FORBIDDEN_VALUE;
187 },
188 .GetFrameSize = [](const uint8_t* data) -> int {
189 return ((data[3] & 0x03) << 11) | ((data[4] & 0xFF) << 3) | ((data[5] & 0xE0) >> 5);
190 }
191 }}
192};
193
203cPes::cPes(const uint8_t *data, int size)
204 : m_data(data), m_size(size)
205{
206}
207
220 if (IsHeaderValid() && IsStreamIdValid()) {
221 if (m_size <= 8 || PesPayloadOffset(m_data) > m_size) // header length field is at position 8 when the PES extension is present
222 LOGWARNING("pes: %s: packet too short: %d %02X", __FUNCTION__, m_size, GetStreamId());
223 else
224 m_valid = true;
225 } else
226 LOGDEBUG("pes: %s: invalid packet: %d %02X", __FUNCTION__, m_size, GetStreamId());
227}
228
245 return m_valid;
246}
247
258{
259 return PesLongEnough(m_size) && ReadBytes(m_data, 3) == PES_PACKET_START_CODE_PREFIX;
260}
261
271{
272 return PesHasPts(m_data);
273}
274
284{
285 if (!HasPts())
286 return AV_NOPTS_VALUE;
287
288 return PesGetPts(m_data);
289}
290
299const uint8_t *cPes::GetPayload()
300{
301 return &m_data[PesPayloadOffset(m_data)];
302}
303
313{
314 return m_size - PesPayloadOffset(m_data);
315}
316
335{
336 if (!PesHasLength(m_data))
337 return m_size; // Length field is 0, meaning unbounded/unspecified. Return raw data size.
338
339 return PesLength(m_data);
340}
341
352{
353 if (size == 0)
354 return nullptr;
355
356 AVPacket *avpkt = av_packet_alloc();
357
358 if (!avpkt)
359 LOGFATAL("pes: %s: out of memory while allocating AVPacket", __FUNCTION__);
360
361 if (av_new_packet(avpkt, size)) // allocates size + AV_INPUT_BUFFER_PADDING_SIZE
362 LOGFATAL("pes: %s: out of memory while allocating AVPacket payload", __FUNCTION__);
363
364 memcpy(avpkt->data, m_buffer.Peek(), size);
365 memset(&avpkt->data[size], 0, AV_INPUT_BUFFER_PADDING_SIZE);
366
367 // Only audio:
368 // 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.
369 // The following AVPackets created from this PES packet shall have no PTS value.
370 // When retrieving PTS values from the same PES packet, they will be identical.
372 avpkt->pts = m_buffer.GetPts();
373 else
374 avpkt->pts = AV_NOPTS_VALUE;
375
377
378 m_buffer.Erase(size);
379
380 return avpkt;
381}
382
383/*
384 * Video specific implementation
385 */
386
398bool cReassemblyBufferVideo::ParseCodecHeader(const uint8_t *fragment, int size) {
399 const uint8_t *codecPayload = &fragment[VIDEO_FRAME_START_CODE_LEN];
400 uint32_t startCode = ReadBytes(fragment, VIDEO_FRAME_START_CODE_LEN);
401
402 // Looking for the MPEG2 start code and stream type in the PES payload
403 if (startCode == VIDEO_FRAME_START_CODE && codecPayload[0] == MPEG2_STREAM_TYPE)
404 m_codec = AV_CODEC_ID_MPEG2VIDEO;
405 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.
406 codecPayload++;
407 else if (startCode != VIDEO_FRAME_START_CODE)
408 return false; // No start code: PES packet carries fragmented payload, or unknown codec.
409
410 if (size > &codecPayload[7] - fragment) {
411 if ( codecPayload[0] == H264_STREAM_TYPE && (codecPayload[1] == 0x10 || codecPayload[1] == 0xF0 || codecPayload[7] == 0x64))
412 m_codec = AV_CODEC_ID_H264;
413 else if (codecPayload[0] == HEVC_STREAM_TYPE && (codecPayload[1] == 0x10 || codecPayload[1] == 0x50 || codecPayload[7] == 0x40))
414 m_codec = AV_CODEC_ID_HEVC;
415 }
416
417 return m_codec != AV_CODEC_ID_NONE;
418}
419
431bool cReassemblyBufferVideo::HasLeadingZero(const uint8_t *data, int size)
432{
433 return size > VIDEO_FRAME_START_CODE_LEN + 1 && data[0] == 0 && ReadBytes(&data[1], VIDEO_FRAME_START_CODE_LEN) == VIDEO_FRAME_START_CODE;
434}
435
436/*
437 * Audio specific implementation
438 */
439
449{
450 AVCodecID detectedCodec = TruncateBufferUntilFirstValidData();
451
452 if (detectedCodec == AV_CODEC_ID_NONE)
453 return nullptr; // No sync word found in the buffer. Wait for more data.
454 else if (m_codec != AV_CODEC_ID_NONE && detectedCodec != m_codec)
455 LOGERROR("pes: %s: audio codec changed unexpectedly from %d to %d", __FUNCTION__, avcodec_get_name(m_codec), avcodec_get_name(detectedCodec));
456
457 m_codec = detectedCodec;
458
459 try {
460 AVPacket *packet = cReassemblyBuffer::PopAvPacket(AudioCodecMap.at(m_codec).GetFrameSize(m_buffer.Peek()));
461
462 if (m_ptsInvalid) { // the PTS is invalid for this packet because the buffer was truncated before
463 packet->pts = AV_NOPTS_VALUE;
464
465 m_ptsInvalid = false;
466 }
467
468 return packet;
469 } catch (const std::invalid_argument &e) {
470 LOGWARNING("pes: %s: garbage in audio stream received: %s", __FUNCTION__, e.what());
471 // the garbage will be removed in the next call to TruncateBufferUntilFirstValidData()
472 }
473
474 return nullptr;
475}
476
487 int sizeBeforeTruncation = m_buffer.GetSize();
488
490
491 m_buffer.Erase(firstFrame.pos);
492
493 if (m_buffer.GetSize() < sizeBeforeTruncation) {
494 LOGDEBUG("pes: %s: truncated %d of %d bytes while searching for sync word", __FUNCTION__, sizeBeforeTruncation - m_buffer.GetSize(), sizeBeforeTruncation);
495 m_ptsInvalid = true;
496 }
497
498 return firstFrame.codecId;
499}
500
514{
515 while (true) {
517
518 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.
519 return SyncWordInfo{AV_CODEC_ID_NONE, std::max(0, (int)m_buffer.GetSize() - MAX_HEADER_SIZE)};
520
521 try {
522 // determine the length of the first found potential frame by reading the frame's header
523 int sizeOfFirstFrame = AudioCodecMap.at(firstFrame.codecId).GetFrameSize(&m_buffer.Peek()[firstFrame.pos]);
524 int secondSyncWord = firstFrame.pos + sizeOfFirstFrame;
525
526 // 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
527 if (secondSyncWord + MAX_HEADER_SIZE > (int)m_buffer.GetSize()) {
528 // 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.
529 // 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:
530 // - MP2: 6913 bytes (Layer 2/3: 384kbps @ 8kHz + padding)
531 // - AAC LATM: 8194 bytes (13-bit length field max: 0x1FFF + 3)
532 // - AC3: 2788 bytes (frmsizcod=37, fscod=1: 1394 * 2)
533 // - EAC3: 4096 bytes (11-bit field max: 2048 * 2)
534 // - AAC ADTS: 8191 bytes (13-bit length field max: 0x1FFF)
535 return SyncWordInfo{AV_CODEC_ID_NONE, firstFrame.pos};
536 } else if (DetectCodecFromSyncWord(&m_buffer.Peek()[secondSyncWord], m_buffer.GetSize() - secondSyncWord) == firstFrame.codecId)
537 // two consecutive frames with the same sync word found, and the first frame's header length field is valid
538 return SyncWordInfo{firstFrame.codecId, firstFrame.pos};
539 } catch (const std::invalid_argument &e) {
540 // Failed to read the frame size from the first frame's header. The found sync word is a false positive.
541 }
542
543 // 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.
544 // In this case, continue the search one position after the start of the first found sync word.
545 m_buffer.Erase(firstFrame.pos + 1);
546 }
547}
548
561{
562 for (int i = 0; i < size; i++) {
563 AVCodecID detectedCodec = DetectCodecFromSyncWord(&data[i], size - i);
564 if (detectedCodec != AV_CODEC_ID_NONE)
565 return SyncWordInfo{detectedCodec, i};
566 }
567
568 return SyncWordInfo{AV_CODEC_ID_NONE, -1};
569}
570
582AVCodecID cReassemblyBufferAudio::DetectCodecFromSyncWord(const uint8_t *syncWord, int size)
583{
584 for (const auto& [codecId, codecInfo] : AudioCodecMap) {
585 if (size >= codecInfo.minSize && codecInfo.MatchSyncWord(syncWord)) {
586 return codecId;
587 }
588 }
589
590 return AV_CODEC_ID_NONE;
591}
592
606int cReassemblyBufferAudio::GetFrameSizeForCodec(AVCodecID codec, const uint8_t *data)
607{
608 return AudioCodecMap.at(codec).GetFrameSize(data);
609}
610
617{
618 m_buffer.Reset();
619 m_codec = AV_CODEC_ID_NONE;
621}
622
623/*
624 * PTS tracking buffer
625 */
626
637void cPtsTrackingBuffer::Push(const uint8_t *data, int size, int64_t pts) {
638 if (pts != AV_NOPTS_VALUE) // PES packets not starting with a new frame (fragmented data) have no PTS
639 m_pts[m_data.size()] = pts;
640
641 m_data.insert(m_data.end(), data, data + size);
642}
643
657void cPtsTrackingBuffer::Erase(size_t amount) {
658 if (m_data.empty() || amount == 0)
659 return;
660
661 // Only PES packets have PTS values, but not the (fragmented) frames inside.
662 // The reassembled frame's PTS value will become the PTS value of the PES packet where the frame starts.
663 // 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.
664 // 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.
665 int64_t smallestPts = AV_NOPTS_VALUE;
666 auto it = m_pts.upper_bound(amount);
667 if (it == m_pts.begin())
668 LOGFATAL("pes: %s: %s: no PTS value found for position 0 after erasing %zu bytes", __FUNCTION__, m_identifier, amount);
669 else {
670 --it; // Move to the last entry before 'amount'
671 smallestPts = it->second;
672 }
673
674 std::map<size_t, int64_t> adjusted_pts;
675 for (const auto& [pos, pts] : m_pts) {
676 if (pos >= amount) // erase all PTS entries for data that will be removed
677 adjusted_pts[pos - amount] = pts; // adjust remaining PTS entries to the new data indices
678 }
679 m_pts = std::move(adjusted_pts);
680
681 m_pts[0] = smallestPts;
682
683 m_data.erase(m_data.begin(), m_data.begin() + amount);
684}
685
695 if (m_pts.empty())
696 return AV_NOPTS_VALUE;
697
698 return m_pts.begin()->second;
699}
bool IsValid()
Check if the PES packet is valid.
Definition pes.cpp:244
static constexpr uint32_t PES_PACKET_START_CODE_PREFIX
Definition pes.h:59
bool m_valid
flag indicating if the PES packet is valid
Definition pes.h:53
uint8_t GetStreamId()
Definition pes.h:46
int GetPayloadSize()
Get the size of the PES payload.
Definition pes.cpp:312
int m_size
size of the PES packet
Definition pes.h:55
cPes(const uint8_t *, int)
Construct a PES packet parser.
Definition pes.cpp:203
int GetPacketLength()
Get the total length of the PES packet.
Definition pes.cpp:334
const uint8_t * GetPayload()
Get a pointer to the PES payload data.
Definition pes.cpp:299
const uint8_t * m_data
pointer to the raw PES packet data
Definition pes.h:54
virtual bool IsStreamIdValid()=0
void Init()
Initialize and validate the PES packet.
Definition pes.cpp:219
bool IsHeaderValid()
Check if the PES header is valid.
Definition pes.cpp:257
bool HasPts()
Check if the PES packet contains a Presentation Time Stamp (PTS)
Definition pes.cpp:270
int64_t GetPts()
Get the Presentation Time Stamp (PTS) from the PES header.
Definition pes.cpp:283
int GetSize()
Definition pes.h:105
void Push(const uint8_t *, int, int64_t)
Push data into the PTS tracking buffer.
Definition pes.cpp:637
std::vector< uint8_t > m_data
Byte buffer.
Definition pes.h:110
std::map< size_t, int64_t > m_pts
Map of buffer positions to PTS values.
Definition pes.h:109
void Reset()
Definition pes.h:104
const uint8_t * Peek()
Definition pes.h:103
void Erase(size_t)
Erase data from the beginning of the buffer.
Definition pes.cpp:657
const char * m_identifier
Definition pes.h:108
int64_t GetPts()
Get the PTS value for the current buffer position.
Definition pes.cpp:694
AVPacket * PopAvPacket() override
Pop an audio AVPacket from the reassembly buffer.
Definition pes.cpp:448
static constexpr int MAX_HEADER_SIZE
Definition pes.h:180
AVCodecID TruncateBufferUntilFirstValidData()
Truncate buffer until the first valid audio frame.
Definition pes.cpp:486
AVCodecID DetectCodecFromSyncWord(const uint8_t *, int)
Detect audio codec from sync word pattern.
Definition pes.cpp:582
SyncWordInfo FindSyncWord(const uint8_t *, int)
Find the first audio sync word in data.
Definition pes.cpp:560
SyncWordInfo FindTwoConsecutiveFramesWithSameSyncWord()
Find two consecutive audio frames with the same sync word.
Definition pes.cpp:513
bool m_ptsInvalid
flag indicating if PTS is invalid for current buffer, because it was truncated
Definition pes.h:181
int GetFrameSizeForCodec(AVCodecID, const uint8_t *)
Get the frame size for a given codec and frame header.
Definition pes.cpp:606
static constexpr uint32_t VIDEO_FRAME_START_CODE
Definition pes.h:148
static constexpr int VIDEO_FRAME_START_CODE_LEN
Definition pes.h:149
static constexpr uint8_t H264_STREAM_TYPE
Definition pes.h:152
static constexpr uint8_t MPEG2_STREAM_TYPE
Definition pes.h:151
bool HasLeadingZero(const uint8_t *, int)
Check if video data has a leading zero byte before the start code.
Definition pes.cpp:431
static constexpr uint8_t HEVC_STREAM_TYPE
Definition pes.h:153
bool ParseCodecHeader(const uint8_t *, int)
Parse video codec header to detect codec type.
Definition pes.cpp:398
AVCodecID m_codec
detected codec ID
Definition pes.h:130
virtual AVPacket * PopAvPacket()=0
int64_t m_lastPoppedPts
PTS of the last popped AVPacket.
Definition pes.h:132
cPtsTrackingBuffer m_buffer
fragmentation buffer
Definition pes.h:131
void Reset()
Reset the reassembly buffer.
Definition pes.cpp:616
Logger class header file.
#define LOGDEBUG
Definition logger.h:44
#define LOGERROR
Definition logger.h:41
#define LOGWARNING
Definition logger.h:42
#define LOGFATAL
Logger macros.
Definition logger.h:40
Misc function header file.
#define AV_NOPTS_VALUE
Definition misc.h:69
static uint32_t ReadBytes(const uint8_t *data, int count)
Return count amount of bytes from data.
Definition misc.h:141
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:47
PES packet parser header.
Codec information structure Contains lambdas for sync word detection and frame size calculation.
Definition pes.cpp:36
std::function< int(const uint8_t *)> GetFrameSize
Definition pes.cpp:39
int minSize
Definition pes.cpp:37
std::function< bool(const uint8_t *)> MatchSyncWord
Definition pes.cpp:38
Information about a detected audio sync word.
Definition pes.h:159
AVCodecID codecId
Detected codec ID.
Definition pes.h:160
int pos
Position of sync word in buffer.
Definition pes.h:161