158 SECTION(
"Invalid PES header - wrong start code") {
159 std::vector<uint8_t> data = {0x00, 0x00, 0x02, 0xE0, 0x00, 0x00};
165 SECTION(
"Invalid PES header - one byte too short") {
166 std::vector<uint8_t> data = {0x00, 0x00, 0x01, 0xE0, 0x00, 0x10, 0xAA, 0xBB};
172 SECTION(
"Stream type without PES extension") {
173 std::vector<uint8_t> data;
176 data.push_back(0x00);
177 data.push_back(0x00);
178 data.push_back(0x01);
181 data.push_back(0xBE);
184 data.push_back(0x00);
185 data.push_back(0x01);
188 data.push_back(0xAA);
277 SECTION(
"Get packet length for unbounded MPEG2 (length field = 0)") {
281 REQUIRE(
pes.GetPacketLength() ==
static_cast<int>(data.size()));
284 SECTION(
"Get packet length for unbounded H.264 (length field = 0)") {
288 REQUIRE(
pes.GetPacketLength() ==
static_cast<int>(data.size()));
291 SECTION(
"Get packet length with specified length field") {
299 data.push_back(0x00);
307 SECTION(
"Get packet length for packet with PTS and specified length") {
318 data.push_back(0x00);
326 SECTION(
"Get packet length when input buffer is larger than PES packet") {
333 data.push_back(0xAA);
337 for (
int i = 0;
i < 50;
i++) {
338 data.push_back(0xFF);
344 REQUIRE(
pes.GetPacketLength() <
static_cast<int>(data.size()));
347 SECTION(
"Unbounded packet with buffer larger than actual data") {
352 for (
int i = 0;
i < 30;
i++) {
353 data.push_back(0xAA);
360 for (
int i = 0;
i < 50;
i++) {
361 data.push_back(0xFF);
366 REQUIRE(
pes.GetPacketLength() ==
static_cast<int>(data.size()));
370 SECTION(
"Get packet length for audio packet with specified length") {
377 data.push_back(0xFF);
436TEST_CASE(
"cReassemblyBufferVideo - H.264 codec detection",
"[reassembly][video]") {
437 SECTION(
"Detect H.264 without leading zero") {
441 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x01, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64};
447 SECTION(
"Detect H.264 with leading zero") {
451 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64};
458TEST_CASE(
"cReassemblyBufferVideo - HEVC codec detection",
"[reassembly][video]") {
459 SECTION(
"Detect HEVC without leading zero") {
463 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x01, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40};
469 SECTION(
"Detect HEVC with leading zero") {
473 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40};
500TEST_CASE(
"cReassemblyBufferVideo - HasLeadingZero detection",
"[reassembly][video]") {
501 SECTION(
"Detect leading zero with H.264") {
505 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01, 0x09, 0x10, 0x00, 0x00};
510 SECTION(
"No leading zero - normal start code") {
514 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x01, 0x09, 0x10};
519 SECTION(
"Leading zero with HEVC") {
523 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01, 0x46, 0x10};
532 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01};
537 SECTION(
"First byte not zero") {
541 std::vector<uint8_t>
fragment = {0xFF, 0x00, 0x00, 0x01, 0x09};
547TEST_CASE(
"cReassemblyBufferVideo - Push and drain",
"[reassembly][video]") {
548 SECTION(
"Push video data and create AVPacket") {
552 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x01, 0xB3, 0xAA, 0xBB, 0xCC, 0xDD};
571 std::vector<uint8_t>
fragment = {0x00, 0x00, 0x00, 0x01, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64};
690TEST_CASE(
"cReassemblyBufferAudio - FindSyncWord with offset",
"[reassembly][audio][syncword]") {
691 SECTION(
"Find AC3 sync word at position 10") {
694 std::vector<uint8_t> data = {
695 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
696 0x0B, 0x77, 0x00, 0x00, 0x00, 0x00
705 SECTION(
"Find LATM sync word in the middle") {
708 std::vector<uint8_t> data = {
721TEST_CASE(
"cReassemblyBufferAudio - FindSyncWord no match",
"[reassembly][audio][syncword]") {
722 SECTION(
"No sync word in garbage data") {
725 std::vector<uint8_t> data = {
726 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
738 std::vector<uint8_t> data = {};
746 SECTION(
"Data too short for any codec") {
750 std::vector<uint8_t> data = { 0xFF, 0xF1 };
759TEST_CASE(
"cReassemblyBufferAudio - FindSyncWord multiple candidates",
"[reassembly][audio][syncword]") {
760 SECTION(
"Returns first valid sync word when multiple present") {
764 std::vector<uint8_t> data = {
766 0x0B, 0x77, 0x00, 0x00, 0x00, 0x00,
767 0xFF, 0xF3, 0x44, 0xC0
777 SECTION(
"Find sync word when partial match exists earlier") {
781 std::vector<uint8_t> data = {
783 0x0B, 0x77, 0x00, 0x00, 0x00, 0x00
793TEST_CASE(
"cReassemblyBufferAudio - TruncateBufferUntilFirstValidData at start",
"[reassembly][audio][consecutive]") {
794 SECTION(
"Two consecutive LATM frames at position 0") {
799 std::vector<uint8_t> data = {
800 0x56, 0xE0, 0x05, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE,
801 0x56, 0xE0, 0x03, 0x11, 0x22, 0x33
804 buffer.
Push(data.data(), data.size(), 0);
811TEST_CASE(
"cReassemblyBufferAudio - TruncateBufferUntilFirstValidData with offset",
"[reassembly][audio][consecutive]") {
812 SECTION(
"Two consecutive LATM frames after garbage data") {
815 std::vector<uint8_t> data = {
816 0x00, 0x01, 0x02, 0x03, 0x04,
817 0x56, 0xE0, 0x04, 0xAA, 0xBB, 0xCC, 0xDD,
818 0x56, 0xE0, 0x02, 0x11, 0x22, 0x00
821 buffer.
Push(data.data(), data.size(), 0);
827 SECTION(
"Two consecutive LATM frames after false positive sync word") {
830 std::vector<uint8_t> data = {
831 0x56, 0xE0, 0x02, 0xAA, 0xBB,
832 0x00, 0x00, 0x00, 0x00,
833 0x56, 0xE0, 0x02, 0x11, 0x22,
834 0x56, 0xE0, 0x03, 0x44, 0x55, 0x66
837 buffer.
Push(data.data(), data.size(), 0);
844TEST_CASE(
"cReassemblyBufferAudio - TruncateBufferUntilFirstValidData edge cases",
"[reassembly][audio][consecutive]") {
845 SECTION(
"Only one LATM frame present") {
848 std::vector<uint8_t> data = {
849 0x56, 0xE0, 0x05, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE
852 buffer.
Push(data.data(), data.size(), 0);
858 SECTION(
"First frame incomplete at end of buffer") {
862 std::vector<uint8_t> data = {
863 0x56, 0xE0, 0x0A, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE
866 buffer.
Push(data.data(), data.size(), 0);
872 SECTION(
"Second frame incomplete") {
875 std::vector<uint8_t> data = {
876 0x56, 0xE0, 0x02, 0xAA, 0xBB,
880 buffer.
Push(data.data(), data.size(), 0);
886 SECTION(
"Wrong codec for second frame") {
889 std::vector<uint8_t> data = {
890 0x56, 0xE0, 0x02, 0xAA, 0xBB,
891 0x0B, 0x77, 0x00, 0x00, 0x00, 0x00
894 buffer.
Push(data.data(), data.size(), 0);
900 SECTION(
"Wrong codec for second frame, and first frame contains a sync word in payload, and second sync word is not long enough") {
903 std::vector<uint8_t> data = {
904 0x56, 0xE0, 0x03, 0x56, 0xE0, 0xAA,
905 0x0B, 0x77, 0x00, 0x00, 0x00
908 buffer.
Push(data.data(), data.size(), 0);
917 std::vector<uint8_t> data = {
921 buffer.
Push(data.data(), data.size(), 0);
928TEST_CASE(
"cReassemblyBufferAudio - TruncateBufferUntilFirstValidData no sync word",
"[reassembly][audio][consecutive]") {
929 SECTION(
"No sync word in data") {
932 std::vector<uint8_t> data = {
933 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
936 buffer.
Push(data.data(), data.size(), 0);
945 std::vector<uint8_t> data = {};
947 buffer.
Push(data.data(), data.size(), 0);
1012TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize AAC/ADTS codec",
"[reassembly][audio][framesize]") {
1015 SECTION(
"ADTS frame with minimum size") {
1018 std::vector<uint8_t> data = {0xFF, 0xF1, 0x50, 0x00, 0x00, 0xE0, 0x00};
1023 SECTION(
"ADTS frame with 100 byte total size") {
1029 std::vector<uint8_t> data = {0xFF, 0xF1, 0x50, 0x00, 0x0C, 0x80, 0x00};
1034 SECTION(
"ADTS frame with 1024 byte total size") {
1040 std::vector<uint8_t> data = {0xFF, 0xF1, 0x50, 0x00, 0x80, 0x00, 0x00};
1045 SECTION(
"ADTS frame with maximum 13-bit size (8191 bytes)") {
1050 std::vector<uint8_t> data = {0xFF, 0xF1, 0x50, 0x03, 0xFF, 0xE0, 0x00};
1056TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize AC3 codec",
"[reassembly][audio][framesize]") {
1059 SECTION(
"AC3 frame - 48 kHz, smallest frame (128 bytes)") {
1062 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x40, 0x00};
1067 SECTION(
"AC3 frame - 44.1 kHz, smallest frame") {
1070 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x00, 0x00};
1075 SECTION(
"AC3 frame - 32 kHz, smallest frame") {
1078 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x80, 0x00};
1083 SECTION(
"AC3 frame - 48 kHz, largest frame (frmsizcod=37)") {
1086 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x65, 0x00};
1091 SECTION(
"AC3 frame - 44.1 kHz, mid-range frame (frmsizcod=18)") {
1094 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x12, 0x00};
1100TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize AC3 error conditions",
"[reassembly][audio][framesize]") {
1103 SECTION(
"AC3 invalid sample rate (fscod=11)") {
1105 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0xC0, 0x00};
1109 SECTION(
"AC3 invalid frame size code (frmsizcod=38)") {
1111 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x26, 0x00};
1115 SECTION(
"AC3 invalid frame size code (frmsizcod=63)") {
1117 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x3F, 0x00};
1122TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize E-AC3 codec",
"[reassembly][audio][framesize]") {
1125 SECTION(
"E-AC3 frame - minimum size (1 word = 2 bytes)") {
1128 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x00, 0x00, 0x51};
1133 SECTION(
"E-AC3 frame - 100 words (200 bytes)") {
1136 std::vector<uint8_t> data = {0x0B, 0x77, 0x00, 0x63, 0x00, 0x51};
1141 SECTION(
"E-AC3 frame - 512 words (1024 bytes)") {
1144 std::vector<uint8_t> data = {0x0B, 0x77, 0x01, 0xFF, 0x00, 0x51};
1149 SECTION(
"E-AC3 frame - maximum 11-bit size (2047 words = 4094 bytes)") {
1152 std::vector<uint8_t> data = {0x0B, 0x77, 0x07, 0xFE, 0x00, 0x51};
1168TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize MP2 codec",
"[reassembly][audio][framesize]") {
1171 SECTION(
"MP2 MPEG1 Layer 2, 128kbps, 44.1kHz, no padding") {
1174 std::vector<uint8_t> data = {0xFF, 0xFD, 0x80, 0x00};
1179 SECTION(
"MP2 MPEG1 Layer 2, 128kbps, 44.1kHz, with padding") {
1182 std::vector<uint8_t> data = {0xFF, 0xFD, 0x82, 0x00};
1187 SECTION(
"MP2 MPEG1 Layer 2, 192kbps, 48kHz, no padding") {
1190 std::vector<uint8_t> data = {0xFF, 0xFD, 0xA4, 0x00};
1195 SECTION(
"MP2 MPEG2 Layer 2, 64kbps, 24kHz, no padding") {
1198 std::vector<uint8_t> data = {0xFF, 0xF5, 0x84, 0x00};
1203 SECTION(
"MP2 MPEG1 Layer 3, 128kbps, 44.1kHz, no padding") {
1206 std::vector<uint8_t> data = {0xFF, 0xFB, 0x90, 0x00};
1211 SECTION(
"MP2 MPEG1 Layer 1, 128kbps, 44.1kHz, no padding") {
1214 std::vector<uint8_t> data = {0xFF, 0xFF, 0x40, 0x00};
1219 SECTION(
"MP2 MPEG1 Layer 1, 128kbps, 44.1kHz, with padding") {
1222 std::vector<uint8_t> data = {0xFF, 0xFF, 0x42, 0x00};
1228TEST_CASE(
"cReassemblyBufferAudio - GetFrameSize MP2 error conditions",
"[reassembly][audio][framesize]") {
1231 SECTION(
"MP2 invalid sample rate (index 3)") {
1233 std::vector<uint8_t> data = {0xFF, 0xFD, 0x5C, 0x00};
1237 SECTION(
"MP2 invalid bit rate (index 0)") {
1239 std::vector<uint8_t> data = {0xFF, 0xFD, 0x04, 0x00};
1243 SECTION(
"MP2 invalid bit rate (index 15)") {
1245 std::vector<uint8_t> data = {0xFF, 0xFD, 0xF0, 0x00};
1287TEST_CASE(
"cPtsTrackingBuffer - Erase basic functionality",
"[ptstracking][erase]") {
1288 SECTION(
"Erase from buffer with single PTS entry") {
1292 std::vector<uint8_t> data(10, 0xAA);
1293 buffer.
Push(data.data(), data.size(), 1000);
1302 SECTION(
"Erase entire buffer") {
1305 std::vector<uint8_t> data(10, 0xAA);
1306 buffer.
Push(data.data(), data.size(), 1000);
1314TEST_CASE(
"cPtsTrackingBuffer - Erase with multiple PTS entries",
"[ptstracking][erase]") {
1315 SECTION(
"Erase exactly at PTS boundary") {
1319 std::vector<uint8_t>
data1(10, 0xAA);
1323 std::vector<uint8_t>
data2(10, 0xBB);
1332 SECTION(
"Erase removes old PTS, keeps and adjusts newer PTS") {
1336 std::vector<uint8_t>
data1 = {0x00, 0x01, 0x02, 0x03, 0x04};
1340 std::vector<uint8_t>
data2 = {0x05, 0x06, 0x07, 0x08, 0x09};
1343 std::vector<uint8_t>
data3 = {0x0A, 0x0B, 0x0C, 0x0D, 0x0E};
1353 SECTION(
"Erase preserves PTS when erasing before next PTS entry") {
1357 std::vector<uint8_t>
data1(10, 0xAA);
1361 std::vector<uint8_t>
data2(10, 0xBB);