From fc0693be1c3a437369b9c1ca153b3c9ed2aca689 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sat, 1 Apr 2023 10:51:06 +0200 Subject: [PATCH] initial commit --- .github/dependabot.yml | 6 + .github/workflows/issue-lock.yml | 50 + .github/workflows/lint.yml | 36 + .github/workflows/test.yml | 30 + .gitignore | 1 + .golangci.yml | 28 + LICENSE | 21 + Makefile | 25 + README.md | 16 + go.mod | 11 + go.sum | 17 + pkg/bits/read.go | 123 +++ pkg/bits/read_test.go | 88 ++ pkg/bits/write.go | 26 + pkg/bits/write_test.go | 18 + pkg/codecs/codecs.go | 2 + pkg/codecs/h264/annexb.go | 134 +++ pkg/codecs/h264/annexb_test.go | 127 +++ pkg/codecs/h264/avcc.go | 74 ++ pkg/codecs/h264/avcc_test.go | 69 ++ pkg/codecs/h264/dts_extractor.go | 193 ++++ pkg/codecs/h264/dts_extractor_test.go | 222 +++++ pkg/codecs/h264/emulation_prevention.go | 33 + pkg/codecs/h264/emulation_prevention_test.go | 65 ++ pkg/codecs/h264/h264.go | 11 + pkg/codecs/h264/idrpresent.go | 12 + pkg/codecs/h264/idrpresent_test.go | 17 + pkg/codecs/h264/nalu_type.go | 83 ++ pkg/codecs/h264/nalu_type_test.go | 13 + pkg/codecs/h264/sps.go | 728 +++++++++++++++ pkg/codecs/h264/sps_test.go | 462 ++++++++++ ...6a6db8644720a23ad912d7be68bf441e186095f7fe | 2 + ...2987e270fe2488d4d58ecd712db136a3e011071253 | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...c7ec4be5cffca97bbe1c447ed47eda11adfd7ab0cc | 2 + ...6a6db8644720a23ad912d7be68bf441e186095f7fe | 2 + ...edd305e7f281b04eeb75cc2339d58c64d6618e8702 | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...00be4f0a4b1969c5386f513788f118019a7e9e32b1 | 2 + ...17aa5604d9b3910ddfa989bdb6bc7323714fda66b3 | 2 + ...a8267b56951b5b6ec2fa924f1e8d8fcab394abc2d3 | 2 + ...a8dc649a0c711445e6307ee02a65b0a4322e758021 | 3 + ...85a3b44c94a8135edafbbd664bd8e2eca808ca5ebc | 3 + ...c2c37a8459445dd9279b725d7243c3341e8e5bc746 | 3 + ...c840715796c9540b4942476167f0b4db164b52ce56 | 3 + ...a8877b465cf77c9425c65d3e2cf6f314d6cbd0050e | 3 + ...e86badcea42b216770d5fc4629d036eb04cfef9ae7 | 3 + ...530fb6f91bc8a0f066193f73e2d2fc35b282b88839 | 3 + ...c07d133559251d8a4697da418218cbaf077650f873 | 3 + ...7161402f7e12129cbe32cf765847b4377867ebc9b5 | 3 + ...59c9e32f26eec2d69bb3aff1746a521786027b732c | 3 + ...bb019dc1ad59d072065ef32935d09b5de28f5d77e0 | 2 + ...2987e270fe2488d4d58ecd712db136a3e011071253 | 2 + ...56d5527be7cf004a2b2c42d9299813c7dc88e9bbd2 | 2 + ...47e60a6c7775cdab6db0e3295029427b18ae2ae747 | 2 + ...e4f1a3ffeacee9738e4c3408a600c24a80de240bac | 2 + ...c7dbc448244bfd66bb4f85d90722653942fdcb60e4 | 2 + ...d88ff2ffdd68dd18d6ca5b1074722884e7d4e4c6a2 | 2 + ...28ffeb9d6cdb51781f98d2cda015995753a7f716e9 | 2 + ...343a15d1ea8c4a7baf8b95bdad79903d47a2af568f | 2 + ...1e23922b7370f4b03e776cd4710bb197715d05e106 | 2 + ...b01d25c4d2b9bc91621d5107b91a9ae3ee676b3b69 | 2 + ...f2256411e7c7e865bf4d2fa2417cf15621a0aa6c68 | 2 + ...81c3939268fda76b1a29a64b67fa65580babb9f310 | 2 + ...793c9f06a763063a089bb7c6f5486331ca9426a898 | 2 + ...0d329a844bc5b06ba24530daafe2fb23707ec73f56 | 2 + ...3edece8150d02d0f28a7f580c26847d3e6eae19f8e | 2 + ...c5bb714ab20766839e07e11d6e1a2e92d8c70a60a2 | 2 + ...dafde531d4280c980c2676ab030e7163f4d618869b | 2 + ...aded44531acaea8e1d19f18bd99730de3df81dc2b4 | 2 + ...05a60ccb56dc5bc1db0bae2a12a115443d39d93c6e | 2 + ...570d1373ce2a6d116dfaa39c1ee11befed0cd82e61 | 2 + ...1ce9339664c952ce93ff20e89aee08b4c432aab3a7 | 2 + ...c8c8c532ea89b2ae61816b13f86ea486572215e81d | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...d590dd27179dd0760a53aa6ee2a1ea2cb7a42ce506 | 2 + ...cc5038559d6ae38e23c23db2a0d82eca058e125166 | 2 + ...aa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d | 2 + ...7d0ef76b78172fc99dddd4299e86d13b79b984cb9e | 2 + ...239abd268cf254b3a983a6b7379293611f56ebe74d | 2 + ...d2e1d77b9ed0ab99094562759738971883b12b5ff5 | 2 + ...1ad92e13ad3f99e6ceec8052bfecbee3596422d48a | 2 + ...a593a050d7f842605f017d5e43a0d31b35e66f28fe | 2 + ...246f4b66a05d5841569f9c5f1a4f19d081050b3747 | 2 + ...f55a2d14c8d4dc2d9a4726c8f7806df12bda102326 | 2 + ...0cdf552d94e12df5f835eb9e06e6815957dc2d5fb2 | 2 + ...6e8f008894ef1b0398cbc1d3d72966d26bed74234b | 2 + ...8a45cb1d387b0a5b3ad6f2cdd861badd887f810b45 | 2 + ...b4a38798ea2c723e1d88ab5fb6e144320b2314d6fe | 2 + ...650ec9424c1b3b183dea47cea96cb89b3f9fd36986 | 2 + ...8a8853d53517cfe49f51dc89f688d445d1265e5d7d | 2 + ...795764e75469e2585518502b400bfee0afd89b5d15 | 2 + ...ed9e7162b114412251df6e662ab63a07b1009b5393 | 2 + ...dfdf57dca91dd1a9512911d96d203aa6d135193c07 | 2 + ...f3c68480c0e27cc08808b74a1f30d2a39126ad9576 | 2 + ...16cacabdc3b33e8bb1c3090e8da7bf331caf899fad | 2 + ...5cb6e9222c1a8c685c578eabe92ddab77a56fbda91 | 2 + ...a53f855490a6d93cbb08be7a1f70d7b7f0a237763c | 2 + ...2ba67c34539a4cd854b3de89394f8049e27672f7d5 | 2 + ...14318381ec19d9aa59a1fff4952c4b6aeb741ba02d | 2 + ...2e061280d14af17e8b0075043f1c822533b41ef9ff | 2 + ...36dde3d97fcda3593310c32dcd8cb6981e36d54538 | 2 + ...07881bdc20e3f5c473749397a8c84bd168f9ac799d | 2 + ...387777290f3d60da89055d4df8529dcf6afad9beca | 2 + ...d1822671be4ac721f297e14dcc4a7900d15c7fff7f | 2 + ...4bacf15e50903f836d7c550504188c55ab37cfde4f | 2 + ...a4b039b822e97cd317c07fc97337da68f023d563a2 | 2 + ...36d0278039659036029592195e8a9acf94ffd70546 | 2 + ...fe83479d6e5eba77143048cca05f00e56a244a8066 | 2 + ...4df230fdfbb9ce3abceb662ee5e714a6e1d94ec0ac | 2 + ...927c5c1e65d159b70f39cd161da0dba348c1221ab3 | 2 + ...398f3cfa98589a431137e9dc72ec5a8bb5cc4cd5da | 2 + ...cd56f2ebaa77ed1632549d98dd78ee0348f68554b3 | 2 + ...ca9adc81513ebf3a55d8a8a053ddb5cf87f9f98524 | 2 + pkg/codecs/h265/dts_extractor.go | 242 +++++ pkg/codecs/h265/dts_extractor_test.go | 84 ++ pkg/codecs/h265/h265.go | 11 + pkg/codecs/h265/nalu_type.go | 99 ++ pkg/codecs/h265/nalu_type_test.go | 13 + pkg/codecs/h265/pps.go | 51 ++ pkg/codecs/h265/pps_test.go | 40 + pkg/codecs/h265/sps.go | 861 ++++++++++++++++++ pkg/codecs/h265/sps_test.go | 446 +++++++++ ...3c26cda412817aa65ef38cdeb3aaed76db1c0379a4 | 3 + ...090e339b08e446b5f9e4f7fff7e448ae377664edb0 | 3 + ...e09cb55a3a35b9dd081ab4959ba7a35d04c5f91cb8 | 3 + ...3fd9ec0f57bfe84533014a058f89ed320caceb13a9 | 3 + ...4b872ad99a77e5d04e1472db9455c4b1b5bd8b7073 | 3 + ...e8a166e7a25bbaa5d4431a3900f509c70b756a06fb | 3 + ...e6fff78d2fcadf6942a62141398df17b6cbe61f0b7 | 3 + ...88b42b4e913a44408f4dfb4e496550c34cb92c93fc | 3 + ...ece5f2d2bce19860a7c060445225adcf3dab189bc4 | 3 + ...4aeaf70d8194277f53bc68eb6255f52278d879d48c | 3 + ...9cff0054b22899ced04b7aa1fddf0c96c76937d0fd | 3 + ...f39f20a5ddcdb857a09391b3e18e55376b8155e3a8 | 3 + ...2987e270fe2488d4d58ecd712db136a3e011071253 | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...7c42f3dbe1518bc2481859740855ab13d8abdd88b1 | 2 + ...33f3a90099024e580a6ba319ea2bf539880c50bd7c | 2 + ...be5ef9389790e33ed1886073dec445d4cf05bcd4b4 | 2 + ...c5d1385a967f0634a2573162c00ba67a01fd806919 | 2 + ...7503859a5680dfceb99c4fb98344d87f884ef731ba | 2 + ...aa9d28d80a409c350d4900c88ab2647be4492f25ee | 2 + ...08e0e0d56b83156fd4d8de02c03bda9a96b85679e0 | 2 + ...cfc92d30a0fd17a6f4aa63a8005253a16205b4e3c6 | 2 + ...8bd1b55bf7bc54ee36279dc9f09567d675c044d58f | 2 + ...a2589536a695487fba02686e2130ed0a5b880d52dc | 2 + ...98640e83c09fecc453519c426cc0b446d43a1cbd73 | 2 + ...c5f38a1199e9777ffe846bba3468737defafd094e7 | 2 + ...07f815b5af2a08d4e6406f173702c88b6a86862437 | 2 + ...9aee956d40195ff289a44da3296d0c88ac02fc67bc | 2 + ...a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 | 2 + ...1328eb2c82c55cb593824ddfe49742696889e520d5 | 2 + ...d2162c9c6aac1e8bf42d252c18b6f766ec1858aaff | 2 + ...4af476bb9fa1d01a47a46bed9bae42c10b18e21594 | 2 + ...2d5f9c0d4cb61ea2d4533f554abd52b0df93bbbc4a | 2 + ...45d10ea3068aa66a765d26b383f9848a4881c6c170 | 2 + ...ee1833e960dc84706396c38db6be2c71c772230bf3 | 2 + ...b69b6cc79e8df25b2ae99c5caf497906ea47c87401 | 2 + ...5eb8f86e8dcfe862c5cd7d187c082598daaba1c047 | 2 + ...feeae612a8916981964640a34384b1ade4316e8038 | 2 + ...b495b99b128071c41b8527d5e3dbaab0fa75aa703f | 2 + ...486c43e23d21d3d1709f5d6e909f809e316eef3ad0 | 2 + ...cea909e28289cca73cd868ab29f13674040fbc6744 | 2 + ...30bae3c6d948e0abe6541fd423fdc4415f863329a8 | 2 + ...77b5a21ace6348d0ab462a9bd03318f936ec14cf9c | 2 + ...694b8ae1044f19e4d98d2048c1aefa8efd2d61658b | 2 + ...72286c58d406629607f197524d518d77ba7f8f9b54 | 2 + ...ba9b37e5295eda2a415d5a61533385124723c2e9db | 2 + ...add573756caf6da8dd8aeb7051bc88bc3e954f2901 | 2 + ...d6c35a75cc7c744b63b33f37286bc716604e68ce45 | 2 + ...c371865fb09f7c7a27d7a2cd40809060e804600dc9 | 2 + ...4a627f3b900ee7248a10ebd94afec3bbaa59022126 | 2 + ...73269d7275bdd943870b45d5737a04da49f394c31f | 2 + ...e144f2c1deeed8fa10349a851b491ccae0e134ffd1 | 2 + ...7963cb1ea96e1cb9c3656e1c9b694d58227f4d168a | 2 + ...0eda93b678543c653946f0e4c5205a9a6e688b6aa3 | 2 + ...c9ec11a112f9530cf5b7c018987e1e56d0cb32e364 | 2 + ...33f3a90099024e580a6ba319ea2bf539880c50bd7c | 2 + ...d5f6fafc362a71d1b716bc02d268998df08364ac37 | 2 + ...5f4fba0037165933ebe9e760a70b1de81b23aadc4a | 2 + ...9c488cb91c7451ec0b22ab74c64548531f5d6633c9 | 2 + ...f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 | 2 + ...a86991f4b3a9d92f038aae8a9341a41fda80f92af5 | 2 + ...21a4027055e3ba59c25615a5e96165c0bbb36b33bb | 2 + ...086b9e76dc2b02e9bc964370d3106dbaef5aa6d37a | 2 + ...6b9e36b2cf5ecacc6d3ad9d926ab5ec64ecdad7b96 | 2 + ...e189fc384bd323efd7280990a5ecd6516cacd4cf61 | 2 + ...5f3e298f34ca63022bd4010acb6635278bc742398a | 2 + ...5012d1df6b6197436ce860641d55e275cc228da321 | 2 + ...1574ea92274cb4a498b3c7cb1189a419d2ba7f1ead | 2 + ...c92eec4f50a828baecca4c6fffde8522632e90f847 | 2 + ...7a460823559d30cdd652309d2002ba745ae6bca0f1 | 2 + ...08322871d93f995b41a108e987151365c3924b6372 | 2 + ...bd143cf2da5b1e1c9d921c0410faae807f3360caa2 | 2 + ...d18c13cdabc383fa5bae32cc853a1b3224893458ce | 2 + ...28d441737cc637962c2d057a5647bd4d4174c657c6 | 2 + ...be5ef9389790e33ed1886073dec445d4cf05bcd4b4 | 2 + ...79ce268a18421e73253c9f97cce75e02466a475d6a | 2 + ...4498e9124c6b1459802c7de9dcf18ad058a1688bb9 | 2 + ...5da5b33dda1692c8289162a1e61d5764dee9ba5344 | 2 + ...e8571748c8293bff3c37419ec4f86e0f93b5c6f7ce | 2 + ...c88c0beebc915cd3c7ed985106c7274dd6bf601991 | 2 + ...7708863c7edb8fa90b6973c421b32e45df6e98c897 | 2 + ...d39bb792d28fb9d23bfbf5b241a62a63ebeb36b591 | 2 + ...6bef44bf6bcda1265ee9e83adb021dd883717e44ff | 2 + ...32fa4fc65e7ee28921fd808119a9350650c2889fbb | 2 + ...7f03f4a64a9673fcbabcfd3d8b831163cf26e08257 | 2 + ...2ae9aefa295debe1f892fe6bae3538651459654512 | 2 + ...63a3526fd967ee0df216749b9ef13ed0fd5041b2b4 | 2 + ...7ce2b3ab19075eeda630aa67817acd128712faf440 | 2 + ...fbc157c0cdb2ecfc1a41b2b0c2b2f0adeb78a33412 | 2 + ...90897e25ffbc50c2a2beafe1a090fd5059936f3a44 | 2 + ...0ed4cfa0c873900d9311619e6590fa18cf8b28ef04 | 2 + ...a511af6fb98889143acd71e18ff6adfca0aa3054cf | 2 + ...bdfb3f39bfd2105a931ef0118b72eb1eca4aeddad9 | 2 + ...43f1f81a2a50d46036a1da3d5844117036f78416ab | 2 + ...13848811b2a66fea56a377d3aea5a0a7ffb53952ba | 2 + pkg/codecs/jpeg/define_huffman_table.go | 20 + pkg/codecs/jpeg/define_huffman_table_test.go | 35 + pkg/codecs/jpeg/define_quantization_table.go | 61 ++ .../jpeg/define_quantization_table_test.go | 79 ++ pkg/codecs/jpeg/define_restart_interval.go | 20 + .../jpeg/define_restart_interval_test.go | 44 + pkg/codecs/jpeg/jpeg.go | 14 + pkg/codecs/jpeg/start_of_frame1.go | 83 ++ pkg/codecs/jpeg/start_of_frame1_test.go | 59 ++ pkg/codecs/jpeg/start_of_image.go | 10 + pkg/codecs/jpeg/start_of_image_test.go | 12 + pkg/codecs/jpeg/start_of_scan.go | 28 + pkg/codecs/jpeg/start_of_scan_test.go | 52 ++ ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...4cfaac68bab4e2c2a4c5a0ab953e27ba6b006ffd56 | 2 + ...bf537d4d81f389524539f402d13aa01f93a65ac7e9 | 2 + ...a1342df84c161a53135a7a8e93511489e6b51c0afe | 2 + ...e9ef0f4984e89ae5c891d08a2ad3c917fe77b94408 | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 | 2 + ...7c7ea359c531218826a6db07cf1a68e91f15b540c8 | 2 + ...5bad24c2bc0283177676e17ac5abeb131a80a38ef5 | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + pkg/codecs/mpeg4audio/adts.go | 147 +++ pkg/codecs/mpeg4audio/adts_test.go | 124 +++ pkg/codecs/mpeg4audio/config.go | 235 +++++ pkg/codecs/mpeg4audio/config_test.go | 166 ++++ pkg/codecs/mpeg4audio/mpeg4audio.go | 10 + pkg/codecs/mpeg4audio/object_type.go | 11 + pkg/codecs/mpeg4audio/sample_rates.go | 33 + ...eb00f6097b53b4250a097ff80e498ceb3f0bfb18e0 | 2 + ...a3f8a5bb9528c50c25e5ff75ee285eb272027491b2 | 2 + ...a940cc0ee647a444fa09ed6839dac31246ff1d5a19 | 2 + ...4393d1b16838280d9c256f3f5819ffea4dcfa87db1 | 2 + ...0155c259a95700b8fd3c3ada7d0cee9d8a99ad413f | 2 + ...9a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 + ...394ad6eb8127068a73f80ea005094fbe9e69874e65 | 2 + ...af6831ec6ab83dcc1f3ab1d748b0abe8ed3211bcda | 2 + ...db8312dc2e64752791e45fec451533b5706f56bed9 | 2 + ...bf537d4d81f389524539f402d13aa01f93a65ac7e9 | 2 + ...497a25b23b2568d3c08b1d2b49a1ae857b6497f223 | 2 + ...d0b7548511decda24d17c05fa7ddeccb3b0b049518 | 2 + ...510424748f46929ac0e89aca9dc59096b7c2d59dc7 | 2 + scripts/format.mk | 10 + scripts/lint.mk | 4 + scripts/mod-tidy.mk | 3 + scripts/test.mk | 21 + 265 files changed, 6293 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/issue-lock.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 pkg/bits/read.go create mode 100644 pkg/bits/read_test.go create mode 100644 pkg/bits/write.go create mode 100644 pkg/bits/write_test.go create mode 100644 pkg/codecs/codecs.go create mode 100644 pkg/codecs/h264/annexb.go create mode 100644 pkg/codecs/h264/annexb_test.go create mode 100644 pkg/codecs/h264/avcc.go create mode 100644 pkg/codecs/h264/avcc_test.go create mode 100644 pkg/codecs/h264/dts_extractor.go create mode 100644 pkg/codecs/h264/dts_extractor_test.go create mode 100644 pkg/codecs/h264/emulation_prevention.go create mode 100644 pkg/codecs/h264/emulation_prevention_test.go create mode 100644 pkg/codecs/h264/h264.go create mode 100644 pkg/codecs/h264/idrpresent.go create mode 100644 pkg/codecs/h264/idrpresent_test.go create mode 100644 pkg/codecs/h264/nalu_type.go create mode 100644 pkg/codecs/h264/nalu_type_test.go create mode 100644 pkg/codecs/h264/sps.go create mode 100644 pkg/codecs/h264/sps_test.go create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/dad1340efc3fed8006eb91c7ec4be5cffca97bbe1c447ed47eda11adfd7ab0cc create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/2ce2df4de457e581f3404dedd305e7f281b04eeb75cc2339d58c64d6618e8702 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/f0b7708a3a98029bd20ee500be4f0a4b1969c5386f513788f118019a7e9e32b1 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb2cff69a3eec4b1a50ea017aa5604d9b3910ddfa989bdb6bc7323714fda66b3 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb5317ecce56275a254428a8267b56951b5b6ec2fa924f1e8d8fcab394abc2d3 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1222d4cb572fa515ca7b8ba8dc649a0c711445e6307ee02a65b0a4322e758021 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1223ae83b4925a9f1ade3b85a3b44c94a8135edafbbd664bd8e2eca808ca5ebc create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/262c62a888c4d2e7f51c8ac2c37a8459445dd9279b725d7243c3341e8e5bc746 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3b9a2adc3e27d7bc69f2eac840715796c9540b4942476167f0b4db164b52ce56 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3cb3e1217d3d42a93448aba8877b465cf77c9425c65d3e2cf6f314d6cbd0050e create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/676f114d18955cd69fb374e86badcea42b216770d5fc4629d036eb04cfef9ae7 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/b1d032bee609ec2a117b65530fb6f91bc8a0f066193f73e2d2fc35b282b88839 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/be0df8dc8259c6db1f7fe9c07d133559251d8a4697da418218cbaf077650f873 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c43c2cabc7b2a36f19a4717161402f7e12129cbe32cf765847b4377867ebc9b5 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c624d6d8804714db4b342d59c9e32f26eec2d69bb3aff1746a521786027b732c create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/01288c9efae1307be2542dbb019dc1ad59d072065ef32935d09b5de28f5d77e0 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0af83188e9b1670a268e5a56d5527be7cf004a2b2c42d9299813c7dc88e9bbd2 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0be6d2f66de27526159e6e47e60a6c7775cdab6db0e3295029427b18ae2ae747 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0d87aecf7d4f3648538400e4f1a3ffeacee9738e4c3408a600c24a80de240bac create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0fb8db11e671e6fa6be3b8c7dbc448244bfd66bb4f85d90722653942fdcb60e4 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/139370ab0793372c99ea8cd88ff2ffdd68dd18d6ca5b1074722884e7d4e4c6a2 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/13b2a92583c8d6ab7b595428ffeb9d6cdb51781f98d2cda015995753a7f716e9 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1c8bbab9d5312be1b60753343a15d1ea8c4a7baf8b95bdad79903d47a2af568f create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1f21b9a6112f67bc666a661e23922b7370f4b03e776cd4710bb197715d05e106 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/20599bffc63db3162d9e18b01d25c4d2b9bc91621d5107b91a9ae3ee676b3b69 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2113482bfc82431ab4769ff2256411e7c7e865bf4d2fa2417cf15621a0aa6c68 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/24ee50d0b17798d827100581c3939268fda76b1a29a64b67fa65580babb9f310 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/277b8e88b43c52e9676253793c9f06a763063a089bb7c6f5486331ca9426a898 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/28f06b087ff4d71f788eb50d329a844bc5b06ba24530daafe2fb23707ec73f56 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2ab5ed4810474c02d699123edece8150d02d0f28a7f580c26847d3e6eae19f8e create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/368b44f70bb50f9d3c1bc1c5bb714ab20766839e07e11d6e1a2e92d8c70a60a2 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/3b0f149b796c531a8ae4efdafde531d4280c980c2676ab030e7163f4d618869b create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/41d70545c8a84390058018aded44531acaea8e1d19f18bd99730de3df81dc2b4 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/43b8a2672cd59b21a57bdb05a60ccb56dc5bc1db0bae2a12a115443d39d93c6e create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/452e524b55a29f1fe6f448570d1373ce2a6d116dfaa39c1ee11befed0cd82e61 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/4a9f730d882605508b45b71ce9339664c952ce93ff20e89aee08b4c432aab3a7 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/50b649fe52d479d41725cdc8c8c532ea89b2ae61816b13f86ea486572215e81d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/5f47d452162ac208dcb3afd590dd27179dd0760a53aa6ee2a1ea2cb7a42ce506 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/641f6b7efc39fdef370a2bcc5038559d6ae38e23c23db2a0d82eca058e125166 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/67be690eb46ab3e15c9e157d0ef76b78172fc99dddd4299e86d13b79b984cb9e create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6842f656bc0b9621f03f7e239abd268cf254b3a983a6b7379293611f56ebe74d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6bbb3f597bab8e6e67e8cbd2e1d77b9ed0ab99094562759738971883b12b5ff5 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/706f49c5b21047ed26fe721ad92e13ad3f99e6ceec8052bfecbee3596422d48a create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/7fc443da4b835c24546da2a593a050d7f842605f017d5e43a0d31b35e66f28fe create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/829fde2929450193ab3c21246f4b66a05d5841569f9c5f1a4f19d081050b3747 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/8a25aa52c31a312b339dd3f55a2d14c8d4dc2d9a4726c8f7806df12bda102326 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9095bee7552e53e949500f0cdf552d94e12df5f835eb9e06e6815957dc2d5fb2 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9bed7ad10156a846b730b66e8f008894ef1b0398cbc1d3d72966d26bed74234b create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a068243fd4565e08237d9e8a45cb1d387b0a5b3ad6f2cdd861badd887f810b45 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a1f57473c1cf3a081b94f3b4a38798ea2c723e1d88ab5fb6e144320b2314d6fe create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a4c914c327ff2fa03d0bd9650ec9424c1b3b183dea47cea96cb89b3f9fd36986 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a6f6a9bf667499515f0c228a8853d53517cfe49f51dc89f688d445d1265e5d7d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac3507052c142f5628eada795764e75469e2585518502b400bfee0afd89b5d15 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac47ca534e00877b146ef2ed9e7162b114412251df6e662ab63a07b1009b5393 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b01759614e8bc591068e73dfdf57dca91dd1a9512911d96d203aa6d135193c07 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b2d4d630d9e57dd4ec6030f3c68480c0e27cc08808b74a1f30d2a39126ad9576 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/bb0b3e83bb11594f77b10e16cacabdc3b33e8bb1c3090e8da7bf331caf899fad create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/be193709a33faf69c6616e5cb6e9222c1a8c685c578eabe92ddab77a56fbda91 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c0cf8af892101f975a635da53f855490a6d93cbb08be7a1f70d7b7f0a237763c create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c17af5c152fb10506043072ba67c34539a4cd854b3de89394f8049e27672f7d5 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c1faaebf2f51b9bd7ef64114318381ec19d9aa59a1fff4952c4b6aeb741ba02d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c522f0b5427ed0a18a6b692e061280d14af17e8b0075043f1c822533b41ef9ff create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cad20d5efdb493f9d3c53736dde3d97fcda3593310c32dcd8cb6981e36d54538 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cf3cad2c9f63327a060ace07881bdc20e3f5c473749397a8c84bd168f9ac799d create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/d78a814513f866a302c16d387777290f3d60da89055d4df8529dcf6afad9beca create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/db1c54995fe7b8d0e9628dd1822671be4ac721f297e14dcc4a7900d15c7fff7f create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e0636a49e255b40346c2f44bacf15e50903f836d7c550504188c55ab37cfde4f create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e20f6e43de3d954ca5b920a4b039b822e97cd317c07fc97337da68f023d563a2 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e562907a18f4186251820f36d0278039659036029592195e8a9acf94ffd70546 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e9918f5c3ff4ccead70a7bfe83479d6e5eba77143048cca05f00e56a244a8066 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f235dbad7715685b1e83484df230fdfbb9ce3abceb662ee5e714a6e1d94ec0ac create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f351a5a9537462ce1b8d69398f3cfa98589a431137e9dc72ec5a8bb5cc4cd5da create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/fc7904c804b00a74ab63bacd56f2ebaa77ed1632549d98dd78ee0348f68554b3 create mode 100644 pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/feba85bf0ea4d5f2e9ba1aca9adc81513ebf3a55d8a8a053ddb5cf87f9f98524 create mode 100644 pkg/codecs/h265/dts_extractor.go create mode 100644 pkg/codecs/h265/dts_extractor_test.go create mode 100644 pkg/codecs/h265/h265.go create mode 100644 pkg/codecs/h265/nalu_type.go create mode 100644 pkg/codecs/h265/nalu_type_test.go create mode 100644 pkg/codecs/h265/pps.go create mode 100644 pkg/codecs/h265/pps_test.go create mode 100644 pkg/codecs/h265/sps.go create mode 100644 pkg/codecs/h265/sps_test.go create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/0e888f462a3598bba3429e3c26cda412817aa65ef38cdeb3aaed76db1c0379a4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/1c4d7707525a482640e7c5090e339b08e446b5f9e4f7fff7e448ae377664edb0 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/355f66d5cd294d34483b9be09cb55a3a35b9dd081ab4959ba7a35d04c5f91cb8 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/3c6b851fbf8b3435e3757b3fd9ec0f57bfe84533014a058f89ed320caceb13a9 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/53955e13efd39f08be15944b872ad99a77e5d04e1472db9455c4b1b5bd8b7073 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/6004440a439db44ebabbaee8a166e7a25bbaa5d4431a3900f509c70b756a06fb create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8bf21706c418e930c7b972e6fff78d2fcadf6942a62141398df17b6cbe61f0b7 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8e78b3e3511102b0b24e8f88b42b4e913a44408f4dfb4e496550c34cb92c93fc create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/b467576cf8e0115542bddaece5f2d2bce19860a7c060445225adcf3dab189bc4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f45d427ed4a5ea4af4846b4aeaf70d8194277f53bc68eb6255f52278d879d48c create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f6aa371594073591a2888e9cff0054b22899ced04b7aa1fddf0c96c76937d0fd create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/fd6f09d0654e93abb8d685f39f20a5ddcdb857a09391b3e18e55376b8155e3a8 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/76c06f7399f3b1781289b37c42f3dbe1518bc2481859740855ab13d8abdd88b1 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/00d6da076abf399523d37cc5d1385a967f0634a2573162c00ba67a01fd806919 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/019839a18a6e47ed73c11a7503859a5680dfceb99c4fb98344d87f884ef731ba create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/039e575e749a676e0037b8aa9d28d80a409c350d4900c88ab2647be4492f25ee create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/05c89dc905ecc2ca9fc8fa08e0e0d56b83156fd4d8de02c03bda9a96b85679e0 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/0f8f18804076a2178ba242cfc92d30a0fd17a6f4aa63a8005253a16205b4e3c6 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/123492a203ec37c506b8768bd1b55bf7bc54ee36279dc9f09567d675c044d58f create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/182a4fb401185659940bf9a2589536a695487fba02686e2130ed0a5b880d52dc create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/1ced60e9d7b0105858590098640e83c09fecc453519c426cc0b446d43a1cbd73 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/20c0dd82574437b8f5caaac5f38a1199e9777ffe846bba3468737defafd094e7 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/27052827203b64be7e464d07f815b5af2a08d4e6406f173702c88b6a86862437 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d13274250a51272648fb79aee956d40195ff289a44da3296d0c88ac02fc67bc create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3067c11d51b8a2666368161328eb2c82c55cb593824ddfe49742696889e520d5 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/343dd7a6b769cfbc11b8ffd2162c9c6aac1e8bf42d252c18b6f766ec1858aaff create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3742076c487d68aab77f194af476bb9fa1d01a47a46bed9bae42c10b18e21594 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3765cdec1f28e3f1f6f3f32d5f9c0d4cb61ea2d4533f554abd52b0df93bbbc4a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/38f534b19ae62787a091d045d10ea3068aa66a765d26b383f9848a4881c6c170 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3aaf3f930d2b6f555533d7ee1833e960dc84706396c38db6be2c71c772230bf3 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3dc305666b84e8f7b04c66b69b6cc79e8df25b2ae99c5caf497906ea47c87401 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/40ea349cafd1592da4cd915eb8f86e8dcfe862c5cd7d187c082598daaba1c047 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4205343f82a7d78102d7bcfeeae612a8916981964640a34384b1ade4316e8038 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/458604b691a14a0f80c142b495b99b128071c41b8527d5e3dbaab0fa75aa703f create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/475bdf3daec7839816b18b486c43e23d21d3d1709f5d6e909f809e316eef3ad0 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4a3b46c8074373cb032eadcea909e28289cca73cd868ab29f13674040fbc6744 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4d32bcb6507cca15717e5d30bae3c6d948e0abe6541fd423fdc4415f863329a8 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/547803e15ea20edd45d87377b5a21ace6348d0ab462a9bd03318f936ec14cf9c create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/60d5d2f797c1cc11b7698f694b8ae1044f19e4d98d2048c1aefa8efd2d61658b create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/615cfc8866bc1a828694f072286c58d406629607f197524d518d77ba7f8f9b54 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/649679f2d355f61f168ec2ba9b37e5295eda2a415d5a61533385124723c2e9db create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/653a4111f80a68c2f197f0add573756caf6da8dd8aeb7051bc88bc3e954f2901 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f82af969dfcb94acaf2cfd6c35a75cc7c744b63b33f37286bc716604e68ce45 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f8f56484ea8b20c24fe9dc371865fb09f7c7a27d7a2cd40809060e804600dc9 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/766677dfa01586ac8ad7954a627f3b900ee7248a10ebd94afec3bbaa59022126 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7b6521a56664b1cbb97f5073269d7275bdd943870b45d5737a04da49f394c31f create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7c9233ac7979facf283efce144f2c1deeed8fa10349a851b491ccae0e134ffd1 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8281575bdc3265faffed6f7963cb1ea96e1cb9c3656e1c9b694d58227f4d168a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/863c5cc1f718d5d6e39c6f0eda93b678543c653946f0e4c5205a9a6e688b6aa3 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8703c0328c7aa4fe9e463dc9ec11a112f9530cf5b7c018987e1e56d0cb32e364 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8b8a68c6d9b801391c5df3d5f6fafc362a71d1b716bc02d268998df08364ac37 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8ba5fa6497afeb040d96665f4fba0037165933ebe9e760a70b1de81b23aadc4a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8bb95d053ae9f84b2bc99c9c488cb91c7451ec0b22ab74c64548531f5d6633c9 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/943e3fb12606845898909ba86991f4b3a9d92f038aae8a9341a41fda80f92af5 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9450509d117f96d6008adb21a4027055e3ba59c25615a5e96165c0bbb36b33bb create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/94e4dcd86c2e09aac9c790086b9e76dc2b02e9bc964370d3106dbaef5aa6d37a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9c6e2641e293d6bffef8b06b9e36b2cf5ecacc6d3ad9d926ab5ec64ecdad7b96 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d560010faa7ada26ac70ae189fc384bd323efd7280990a5ecd6516cacd4cf61 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d9abe934c8d92838c18705f3e298f34ca63022bd4010acb6635278bc742398a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a35edfe853b408a7c225af5012d1df6b6197436ce860641d55e275cc228da321 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a5d467a1921f1f1395d0bc1574ea92274cb4a498b3c7cb1189a419d2ba7f1ead create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ab559ccd961e02992fd953c92eec4f50a828baecca4c6fffde8522632e90f847 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/acf6271d3e87a7fc18dc947a460823559d30cdd652309d2002ba745ae6bca0f1 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ada5d60ffad1e135ecbc4f08322871d93f995b41a108e987151365c3924b6372 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/afb972a0b1cfbd4181a062bd143cf2da5b1e1c9d921c0410faae807f3360caa2 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/b3b203da514589b7cc4ed7d18c13cdabc383fa5bae32cc853a1b3224893458ce create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/bfdfa1a6e4892d045614bd28d441737cc637962c2d057a5647bd4d4174c657c6 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c3d5e611c2447ae2d18cf179ce268a18421e73253c9f97cce75e02466a475d6a create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd4f7e682b02a30bc433044498e9124c6b1459802c7de9dcf18ad058a1688bb9 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd939a83576d663b9de5c75da5b33dda1692c8289162a1e61d5764dee9ba5344 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ceb8cba9187af176dab482e8571748c8293bff3c37419ec4f86e0f93b5c6f7ce create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d09dfd7e6702ed14f3d16dc88c0beebc915cd3c7ed985106c7274dd6bf601991 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d2b8f6ff13c57a6493cc417708863c7edb8fa90b6973c421b32e45df6e98c897 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d3c6efd87c63850e112528d39bb792d28fb9d23bfbf5b241a62a63ebeb36b591 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d8729013defaf4cf5833f86bef44bf6bcda1265ee9e83adb021dd883717e44ff create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d9f26138c54e610b9535ad32fa4fc65e7ee28921fd808119a9350650c2889fbb create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/dc2a4cb2325c492ca2a0787f03f4a64a9673fcbabcfd3d8b831163cf26e08257 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e1d156e4fa7380afa414b12ae9aefa295debe1f892fe6bae3538651459654512 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e4a6272c0ccae23d9ff40b63a3526fd967ee0df216749b9ef13ed0fd5041b2b4 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e6a754dcc2747eb5e3225d7ce2b3ab19075eeda630aa67817acd128712faf440 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e7020cfc8cfc8a340f41aafbc157c0cdb2ecfc1a41b2b0c2b2f0adeb78a33412 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e80085c26c10f735691d6790897e25ffbc50c2a2beafe1a090fd5059936f3a44 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ed6952414b61c4c80820200ed4cfa0c873900d9311619e6590fa18cf8b28ef04 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f6872527132c3a2c994316a511af6fb98889143acd71e18ff6adfca0aa3054cf create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f7ffd151838837c215f9bcbdfb3f39bfd2105a931ef0118b72eb1eca4aeddad9 create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f9043ef7bfaf2fdebf518743f1f81a2a50d46036a1da3d5844117036f78416ab create mode 100644 pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ff354e5d8975a43060c65913848811b2a66fea56a377d3aea5a0a7ffb53952ba create mode 100644 pkg/codecs/jpeg/define_huffman_table.go create mode 100644 pkg/codecs/jpeg/define_huffman_table_test.go create mode 100644 pkg/codecs/jpeg/define_quantization_table.go create mode 100644 pkg/codecs/jpeg/define_quantization_table_test.go create mode 100644 pkg/codecs/jpeg/define_restart_interval.go create mode 100644 pkg/codecs/jpeg/define_restart_interval_test.go create mode 100644 pkg/codecs/jpeg/jpeg.go create mode 100644 pkg/codecs/jpeg/start_of_frame1.go create mode 100644 pkg/codecs/jpeg/start_of_frame1_test.go create mode 100644 pkg/codecs/jpeg/start_of_image.go create mode 100644 pkg/codecs/jpeg/start_of_image_test.go create mode 100644 pkg/codecs/jpeg/start_of_scan.go create mode 100644 pkg/codecs/jpeg/start_of_scan_test.go create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/97dc7172b48e6ffd89dfa34cfaac68bab4e2c2a4c5a0ab953e27ba6b006ffd56 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzDefineRestartIntervalUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/04069695460a25181d94bba1342df84c161a53135a7a8e93511489e6b51c0afe create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/52bcb082e28f6e0e4007bae9ef0f4984e89ae5c891d08a2ad3c917fe77b94408 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/9aaf79656de4e8166797e57c7ea359c531218826a6db07cf1a68e91f15b540c8 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/f032221efa2df5f3a4eedd5bad24c2bc0283177676e17ac5abeb131a80a38ef5 create mode 100644 pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfScanUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/mpeg4audio/adts.go create mode 100644 pkg/codecs/mpeg4audio/adts_test.go create mode 100644 pkg/codecs/mpeg4audio/config.go create mode 100644 pkg/codecs/mpeg4audio/config_test.go create mode 100644 pkg/codecs/mpeg4audio/mpeg4audio.go create mode 100644 pkg/codecs/mpeg4audio/object_type.go create mode 100644 pkg/codecs/mpeg4audio/sample_rates.go create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/0de38b892c93cde2f2b32eeb00f6097b53b4250a097ff80e498ceb3f0bfb18e0 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2407269c6f2b6741b662b2a3f8a5bb9528c50c25e5ff75ee285eb272027491b2 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2f1e03b45b2a93962108e8a940cc0ee647a444fa09ed6839dac31246ff1d5a19 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/41b96153add60a0a300ad04393d1b16838280d9c256f3f5819ffea4dcfa87db1 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/4e84166ad43e1c5846255d0155c259a95700b8fd3c3ada7d0cee9d8a99ad413f create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/6962f04b357ab1240e26ab394ad6eb8127068a73f80ea005094fbe9e69874e65 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/bbffbee953abbb79185a8caf6831ec6ab83dcc1f3ab1d748b0abe8ed3211bcda create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/c12d7ec300bda22f7db490db8312dc2e64752791e45fec451533b5706f56bed9 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/d00ea3865173809d88de52497a25b23b2568d3c08b1d2b49a1ae857b6497f223 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/f5da56f6a7a5431290dccfd0b7548511decda24d17c05fa7ddeccb3b0b049518 create mode 100644 pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/fca08d22f8534499db40e6510424748f46929ac0e89aca9dc59096b7c2d59dc7 create mode 100644 scripts/format.mk create mode 100644 scripts/lint.mk create mode 100644 scripts/mod-tidy.mk create mode 100644 scripts/test.mk diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3938344 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/issue-lock.yml b/.github/workflows/issue-lock.yml new file mode 100644 index 0000000..4a95f38 --- /dev/null +++ b/.github/workflows/issue-lock.yml @@ -0,0 +1,50 @@ +name: issue-lock + +on: + schedule: + - cron: '40 15 * * *' + workflow_dispatch: + +jobs: + issue-lock: + runs-on: ubuntu-latest + + steps: + - uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { repo: { owner, repo } } = context; + + const now = new Date(); + + for await (const res of github.paginate.iterator( + github.rest.issues.listForRepo, { + owner, + repo, + state: 'closed', + })) { + for (const issue of res.data) { + if (issue.locked) { + continue; + } + + if ((now - new Date(issue.updated_at)) < 1000*60*60*24*31*6) { + continue; + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: 'This issue is being locked automatically because it has been closed for more than 6 months.\n' + + 'Please open a new issue in case you encounter a similar problem.', + }); + + github.rest.issues.lock({ + owner, + repo, + issue_number: issue.number, + }); + } + } diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..c875c13 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,36 @@ +name: lint + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + golangci-lint: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-go@v3 + with: + go-version: "1.19" + + - uses: golangci/golangci-lint-action@v3 + with: + version: v1.50.1 + + go-mod-tidy: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-go@v2 + with: + go-version: "1.20" + + - run: | + go mod tidy + git diff --exit-code diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..5f27757 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-20.04 + strategy: + matrix: + go: ["1.18", "1.19", "1.20"] + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + + - run: sudo apt update && sudo apt install -y libavformat-dev libswscale-dev + + - run: make test-nodocker + + - if: matrix.go == '1.19' + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1273da7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/coverage*.txt diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..45f0aaa --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,28 @@ +linters: + enable: + - bodyclose + - dupl + - exportloopref + - gochecknoinits + - gocritic + - gofmt + - gofumpt + - misspell + - lll + - prealloc + - revive + - unconvert + - whitespace + disable: + - errcheck + +issues: + exclude-use-default: false + +linters-settings: + govet: + enable-all: true + disable: + - fieldalignment + - reflectvaluecompare + - shadow diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e06e71e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 aler9 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..654d9fc --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +BASE_IMAGE = golang:1.20.1-alpine3.17 +LINT_IMAGE = golangci/golangci-lint:v1.50.1 + +.PHONY: $(shell ls) + +help: + @echo "usage: make [action]" + @echo "" + @echo "available actions:" + @echo "" + @echo " mod-tidy run go mod tidy" + @echo " format format source files" + @echo " test run tests" + @echo " test-highlevel run high-level tests" + @echo " lint run linter" + @echo " bench run benchmarks" + @echo "" + +blank := +define NL + +$(blank) +endef + +include scripts/*.mk diff --git a/README.md b/README.md new file mode 100644 index 0000000..b43da8e --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# mediabase + +[![Test](https://github.com/bluenviron/mediabase/workflows/test/badge.svg)](https://github.com/bluenviron/mediabase/actions?query=workflow:test) +[![Lint](https://github.com/bluenviron/mediabase/workflows/lint/badge.svg)](https://github.com/bluenviron/mediabase/actions?query=workflow:lint) +[![Go Report Card](https://goreportcard.com/badge/github.com/bluenviron/mediabase)](https://goreportcard.com/report/github.com/bluenviron/mediabase) +[![CodeCov](https://codecov.io/gh/bluenviron/mediabase/branch/main/graph/badge.svg)](https://app.codecov.io/gh/bluenviron/mediabase/branch/main) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/bluenviron/mediabase/v3)](https://pkg.go.dev/github.com/bluenviron/mediabase/v3#pkg-index) + +Definitions and functions shared between gortsplib, gohlslib and mediamtx. + +In particular: + +* [Codec definitions](pkg/codecs) +* [Codec utilities](pkg/codecs) +* [Format utilities](pkg/formats) +* [Bit reader and writer](pkg/bits) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..afc9099 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module github.com/bluenviron/mediabase + +go 1.18 + +require github.com/stretchr/testify v1.8.2 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6a56e69 --- /dev/null +++ b/go.sum @@ -0,0 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/bits/read.go b/pkg/bits/read.go new file mode 100644 index 0000000..6d925b4 --- /dev/null +++ b/pkg/bits/read.go @@ -0,0 +1,123 @@ +// Package bits contains functions to read/write bits from/to buffers. +package bits + +import ( + "fmt" +) + +// HasSpace checks whether buffer has space for N bits. +func HasSpace(buf []byte, pos int, n int) error { + if n > ((len(buf) * 8) - pos) { + return fmt.Errorf("not enough bits") + } + return nil +} + +// ReadBits reads N bits. +func ReadBits(buf []byte, pos *int, n int) (uint64, error) { + err := HasSpace(buf, *pos, n) + if err != nil { + return 0, err + } + + return ReadBitsUnsafe(buf, pos, n), nil +} + +// ReadBitsUnsafe reads N bits. +func ReadBitsUnsafe(buf []byte, pos *int, n int) uint64 { + v := uint64(0) + + res := 8 - (*pos & 0x07) + if n < res { + v := uint64((buf[*pos>>0x03] >> (res - n)) & (1<>0x03]&(1<= 8 { + v = (v << 8) | uint64(buf[*pos>>0x03]) + *pos += 8 + n -= 8 + } + + if n > 0 { + v = (v << n) | uint64(buf[*pos>>0x03]>>(8-n)) + *pos += n + } + + return v +} + +// ReadGolombUnsigned reads an unsigned golomb-encoded value. +func ReadGolombUnsigned(buf []byte, pos *int) (uint32, error) { + buflen := len(buf) + leadingZeroBits := uint32(0) + + for { + if (buflen*8 - *pos) == 0 { + return 0, fmt.Errorf("not enough bits") + } + + b := (buf[*pos>>0x03] >> (7 - (*pos & 0x07))) & 0x01 + *pos++ + if b != 0 { + break + } + + leadingZeroBits++ + if leadingZeroBits > 32 { + return 0, fmt.Errorf("invalid value") + } + } + + if (buflen*8 - *pos) < int(leadingZeroBits) { + return 0, fmt.Errorf("not enough bits") + } + + codeNum := uint32(0) + + for n := leadingZeroBits; n > 0; n-- { + b := (buf[*pos>>0x03] >> (7 - (*pos & 0x07))) & 0x01 + *pos++ + codeNum |= uint32(b) << (n - 1) + } + + codeNum = (1 << leadingZeroBits) - 1 + codeNum + + return codeNum, nil +} + +// ReadGolombSigned reads a signed golomb-encoded value. +func ReadGolombSigned(buf []byte, pos *int) (int32, error) { + v, err := ReadGolombUnsigned(buf, pos) + if err != nil { + return 0, err + } + + vi := int32(v) + if (vi & 0x01) != 0 { + return (vi + 1) / 2, nil + } + return -vi / 2, nil +} + +// ReadFlag reads a boolean flag. +func ReadFlag(buf []byte, pos *int) (bool, error) { + err := HasSpace(buf, *pos, 1) + if err != nil { + return false, err + } + + return ReadFlagUnsafe(buf, pos), nil +} + +// ReadFlagUnsafe reads a boolean flag. +func ReadFlagUnsafe(buf []byte, pos *int) bool { + b := (buf[*pos>>0x03] >> (7 - (*pos & 0x07))) & 0x01 + *pos++ + return b == 1 +} diff --git a/pkg/bits/read_test.go b/pkg/bits/read_test.go new file mode 100644 index 0000000..6a72c8a --- /dev/null +++ b/pkg/bits/read_test.go @@ -0,0 +1,88 @@ +package bits + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestReadBits(t *testing.T) { + buf := []byte{0xA8, 0xC7, 0xD6, 0xAA, 0xBB, 0x10} + pos := 0 + v, _ := ReadBits(buf, &pos, 6) + require.Equal(t, uint64(0x2a), v) + v, _ = ReadBits(buf, &pos, 6) + require.Equal(t, uint64(0x0c), v) + v, _ = ReadBits(buf, &pos, 6) + require.Equal(t, uint64(0x1f), v) + v, _ = ReadBits(buf, &pos, 8) + require.Equal(t, uint64(0x5a), v) + v, _ = ReadBits(buf, &pos, 20) + require.Equal(t, uint64(0xaaec4), v) +} + +func TestReadBitsError(t *testing.T) { + buf := []byte{0xA8} + pos := 0 + _, err := ReadBits(buf, &pos, 6) + require.NoError(t, err) + _, err = ReadBits(buf, &pos, 6) + require.EqualError(t, err, "not enough bits") +} + +func TestReadGolombUnsigned(t *testing.T) { + buf := []byte{0x38} + pos := 0 + v, _ := ReadGolombUnsigned(buf, &pos) + require.Equal(t, uint32(6), v) +} + +func TestReadGolombUnsignedErrors(t *testing.T) { + buf := []byte{0x00} + pos := 0 + _, err := ReadGolombUnsigned(buf, &pos) + require.EqualError(t, err, "not enough bits") + + buf = []byte{0x00, 0x01} + pos = 0 + _, err = ReadGolombUnsigned(buf, &pos) + require.EqualError(t, err, "not enough bits") + + buf = []byte{0x00, 0x00, 0x00, 0x00, 0x01} + pos = 0 + _, err = ReadGolombUnsigned(buf, &pos) + require.EqualError(t, err, "invalid value") +} + +func TestReadGolombSigned(t *testing.T) { + buf := []byte{0x38} + pos := 0 + v, _ := ReadGolombSigned(buf, &pos) + require.Equal(t, int32(-3), v) + + buf = []byte{0b00100100} + pos = 0 + v, _ = ReadGolombSigned(buf, &pos) + require.Equal(t, int32(2), v) +} + +func TestReadGolombSignedErrors(t *testing.T) { + buf := []byte{0x00} + pos := 0 + _, err := ReadGolombSigned(buf, &pos) + require.EqualError(t, err, "not enough bits") +} + +func TestReadFlag(t *testing.T) { + buf := []byte{0xFF} + pos := 0 + v, _ := ReadFlag(buf, &pos) + require.Equal(t, true, v) +} + +func TestReadFlagError(t *testing.T) { + buf := []byte{} + pos := 0 + _, err := ReadFlag(buf, &pos) + require.EqualError(t, err, "not enough bits") +} diff --git a/pkg/bits/write.go b/pkg/bits/write.go new file mode 100644 index 0000000..4c71275 --- /dev/null +++ b/pkg/bits/write.go @@ -0,0 +1,26 @@ +package bits + +// WriteBits writes N bits. +func WriteBits(buf []byte, pos *int, bits uint64, n int) { + res := 8 - (*pos & 0x07) + if n < res { + buf[*pos>>0x03] |= byte(bits << (res - n)) + *pos += n + return + } + + buf[*pos>>3] |= byte(bits >> (n - res)) + *pos += res + n -= res + + for n >= 8 { + buf[*pos>>3] = byte(bits >> (n - 8)) + *pos += 8 + n -= 8 + } + + if n > 0 { + buf[*pos>>3] = byte((bits & (1<= bl || start >= 4 { + return nil, fmt.Errorf("initial delimiter not found") + } + + switch initZeroCount { + case 0, 1: + if byts[start] != 0 { + return nil, fmt.Errorf("initial delimiter not found") + } + initZeroCount++ + + case 2, 3: + switch byts[start] { + case 1: + start++ + break outer + + case 0: + + default: + return nil, fmt.Errorf("initial delimiter not found") + } + initZeroCount++ + } + + start++ + } + + zeroCount := 0 + n := 0 + + for i := start; i < bl; i++ { + switch byts[i] { + case 0: + zeroCount++ + + case 1: + if zeroCount == 2 || zeroCount == 3 { + n++ + } + zeroCount = 0 + + default: + zeroCount = 0 + } + } + + if (n + 1) > MaxNALUsPerGroup { + return nil, fmt.Errorf("NALU count (%d) exceeds maximum allowed (%d)", + n+1, MaxNALUsPerGroup) + } + + ret := make([][]byte, n+1) + pos := 0 + start = initZeroCount + 1 + zeroCount = 0 + delimStart := 0 + + for i := start; i < bl; i++ { + switch byts[i] { + case 0: + if zeroCount == 0 { + delimStart = i + } + zeroCount++ + + case 1: + if zeroCount == 2 || zeroCount == 3 { + l := delimStart - start + if l == 0 { + return nil, fmt.Errorf("invalid NALU") + } + if l > MaxNALUSize { + return nil, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", l, MaxNALUSize) + } + + ret[pos] = byts[start:delimStart] + pos++ + start = i + 1 + } + zeroCount = 0 + + default: + zeroCount = 0 + } + } + + l := bl - start + if l == 0 { + return nil, fmt.Errorf("invalid NALU") + } + if l > MaxNALUSize { + return nil, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", l, MaxNALUSize) + } + + ret[pos] = byts[start:bl] + + return ret, nil +} + +func annexBMarshalSize(nalus [][]byte) int { + n := 0 + for _, nalu := range nalus { + n += 4 + len(nalu) + } + return n +} + +// AnnexBMarshal encodes NALUs into the Annex-B stream format. +func AnnexBMarshal(nalus [][]byte) ([]byte, error) { + buf := make([]byte, annexBMarshalSize(nalus)) + pos := 0 + + for _, nalu := range nalus { + pos += copy(buf[pos:], []byte{0x00, 0x00, 0x00, 0x01}) + pos += copy(buf[pos:], nalu) + } + + return buf, nil +} diff --git a/pkg/codecs/h264/annexb_test.go b/pkg/codecs/h264/annexb_test.go new file mode 100644 index 0000000..ae9030c --- /dev/null +++ b/pkg/codecs/h264/annexb_test.go @@ -0,0 +1,127 @@ +//go:build go1.18 +// +build go1.18 + +package h264 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesAnnexB = []struct { + name string + encin []byte + encout []byte + dec [][]byte +}{ + { + "2 zeros", + []byte{ + 0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00, 0x01, + 0xcc, 0xdd, 0x00, 0x00, 0x01, 0xee, 0xff, + }, + []byte{ + 0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, + 0x00, 0x00, 0x00, 0x01, 0xcc, 0xdd, + 0x00, 0x00, 0x00, 0x01, 0xee, 0xff, + }, + [][]byte{ + {0xaa, 0xbb}, + {0xcc, 0xdd}, + {0xee, 0xff}, + }, + }, + { + "3 zeros", + []byte{ + 0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, + 0x00, 0x00, 0x00, 0x01, 0xcc, 0xdd, + 0x00, 0x00, 0x00, 0x01, 0xee, 0xff, + }, + []byte{ + 0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, + 0x00, 0x00, 0x00, 0x01, 0xcc, 0xdd, + 0x00, 0x00, 0x00, 0x01, 0xee, 0xff, + }, + [][]byte{ + {0xaa, 0xbb}, + {0xcc, 0xdd}, + {0xee, 0xff}, + }, + }, + { + // used by Apple inside HLS test streams + "2 or 3 zeros", + []byte{ + 0, 0, 0, 1, 9, 240, + 0, 0, 0, 1, 39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64, + 0, 0, 0, 1, 40, 222, 9, 200, + 0, 0, 1, 6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128, + 0, 0, 1, 6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128, + }, + []byte{ + 0, 0, 0, 1, 9, 240, + 0, 0, 0, 1, 39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64, + 0, 0, 0, 1, 40, 222, 9, 200, + 0, 0, 0, 1, 6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128, + 0, 0, 0, 1, 6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128, + }, + [][]byte{ + {9, 240}, + {39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64}, + {40, 222, 9, 200}, + {6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128}, + {6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128}, + }, + }, +} + +func TestAnnexBUnmarshal(t *testing.T) { + for _, ca := range casesAnnexB { + t.Run(ca.name, func(t *testing.T) { + dec, err := AnnexBUnmarshal(ca.encin) + require.NoError(t, err) + require.Equal(t, ca.dec, dec) + }) + } +} + +func TestAnnexBMarshal(t *testing.T) { + for _, ca := range casesAnnexB { + t.Run(ca.name, func(t *testing.T) { + enc, err := AnnexBMarshal(ca.dec) + require.NoError(t, err) + require.Equal(t, ca.encout, enc) + }) + } +} + +func BenchmarkAnnexBUnmarshal(b *testing.B) { + for i := 0; i < b.N; i++ { + AnnexBUnmarshal([]byte{ + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + }) + } +} + +func FuzzAnnexBUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + AnnexBUnmarshal(b) + }) +} diff --git a/pkg/codecs/h264/avcc.go b/pkg/codecs/h264/avcc.go new file mode 100644 index 0000000..52afe00 --- /dev/null +++ b/pkg/codecs/h264/avcc.go @@ -0,0 +1,74 @@ +package h264 + +import ( + "fmt" +) + +// AVCCUnmarshal decodes NALUs from the AVCC stream format. +func AVCCUnmarshal(buf []byte) ([][]byte, error) { + bl := len(buf) + pos := 0 + var ret [][]byte + + for { + if (bl - pos) < 4 { + return nil, fmt.Errorf("invalid length") + } + + l := int(uint32(buf[pos])<<24 | uint32(buf[pos+1])<<16 | uint32(buf[pos+2])<<8 | uint32(buf[pos+3])) + pos += 4 + + if l == 0 { + return nil, fmt.Errorf("invalid NALU") + } + + if l > MaxNALUSize { + return nil, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", l, MaxNALUSize) + } + + if (len(ret) + 1) > MaxNALUsPerGroup { + return nil, fmt.Errorf("NALU count (%d) exceeds maximum allowed (%d)", + len(ret)+1, MaxNALUsPerGroup) + } + + if (bl - pos) < l { + return nil, fmt.Errorf("invalid length") + } + + ret = append(ret, buf[pos:pos+l]) + pos += l + + if (bl - pos) == 0 { + break + } + } + + return ret, nil +} + +func avccMarshalSize(nalus [][]byte) int { + n := 0 + for _, nalu := range nalus { + n += 4 + len(nalu) + } + return n +} + +// AVCCMarshal encodes NALUs into the AVCC stream format. +func AVCCMarshal(nalus [][]byte) ([]byte, error) { + buf := make([]byte, avccMarshalSize(nalus)) + pos := 0 + + for _, nalu := range nalus { + naluLen := len(nalu) + buf[pos] = byte(naluLen >> 24) + buf[pos+1] = byte(naluLen >> 16) + buf[pos+2] = byte(naluLen >> 8) + buf[pos+3] = byte(naluLen) + pos += 4 + + pos += copy(buf[pos:], nalu) + } + + return buf, nil +} diff --git a/pkg/codecs/h264/avcc_test.go b/pkg/codecs/h264/avcc_test.go new file mode 100644 index 0000000..8d44337 --- /dev/null +++ b/pkg/codecs/h264/avcc_test.go @@ -0,0 +1,69 @@ +//go:build go1.18 +// +build go1.18 + +package h264 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesAVCC = []struct { + name string + enc []byte + dec [][]byte +}{ + { + "single", + []byte{ + 0x00, 0x00, 0x00, 0x03, + 0xaa, 0xbb, 0xcc, + }, + [][]byte{ + {0xaa, 0xbb, 0xcc}, + }, + }, + { + "multiple", + []byte{ + 0x00, 0x00, 0x00, 0x02, + 0xaa, 0xbb, + 0x00, 0x00, 0x00, 0x02, + 0xcc, 0xdd, + 0x00, 0x00, 0x00, 0x02, + 0xee, 0xff, + }, + [][]byte{ + {0xaa, 0xbb}, + {0xcc, 0xdd}, + {0xee, 0xff}, + }, + }, +} + +func TestAVCCUnmarshal(t *testing.T) { + for _, ca := range casesAVCC { + t.Run(ca.name, func(t *testing.T) { + dec, err := AVCCUnmarshal(ca.enc) + require.NoError(t, err) + require.Equal(t, ca.dec, dec) + }) + } +} + +func TestAVCCMarshal(t *testing.T) { + for _, ca := range casesAVCC { + t.Run(ca.name, func(t *testing.T) { + enc, err := AVCCMarshal(ca.dec) + require.NoError(t, err) + require.Equal(t, ca.enc, enc) + }) + } +} + +func FuzzAVCCUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + AVCCUnmarshal(b) + }) +} diff --git a/pkg/codecs/h264/dts_extractor.go b/pkg/codecs/h264/dts_extractor.go new file mode 100644 index 0000000..65ec9b6 --- /dev/null +++ b/pkg/codecs/h264/dts_extractor.go @@ -0,0 +1,193 @@ +package h264 + +import ( + "fmt" + "time" + + "github.com/bluenviron/mediabase/pkg/bits" +) + +func getPictureOrderCount(buf []byte, sps *SPS) (uint32, error) { + if len(buf) < 6 { + return 0, fmt.Errorf("not enough bits") + } + + buf = EmulationPreventionRemove(buf[:6]) + + buf = buf[1:] + pos := 0 + + _, err := bits.ReadGolombUnsigned(buf, &pos) // first_mb_in_slice + if err != nil { + return 0, err + } + + _, err = bits.ReadGolombUnsigned(buf, &pos) // slice_type + if err != nil { + return 0, err + } + + _, err = bits.ReadGolombUnsigned(buf, &pos) // pic_parameter_set_id + if err != nil { + return 0, err + } + + _, err = bits.ReadBits(buf, &pos, int(sps.Log2MaxFrameNumMinus4+4)) // frame_num + if err != nil { + return 0, err + } + + if !sps.FrameMbsOnlyFlag { + return 0, fmt.Errorf("frame_mbs_only_flag = 0 is not supported") + } + + picOrderCntLsb, err := bits.ReadBits(buf, &pos, int(sps.Log2MaxPicOrderCntLsbMinus4+4)) + if err != nil { + return 0, err + } + + return uint32(picOrderCntLsb), nil +} + +func findPictureOrderCount(au [][]byte, sps *SPS) (uint32, error) { + for _, nalu := range au { + typ := NALUType(nalu[0] & 0x1F) + if typ == NALUTypeNonIDR { + poc, err := getPictureOrderCount(nalu, sps) + if err != nil { + return 0, err + } + return poc, nil + } + } + return 0, fmt.Errorf("POC not found") +} + +func getPictureOrderCountDiff(poc1 uint32, poc2 uint32, sps *SPS) int32 { + diff := int32(poc1) - int32(poc2) + switch { + case diff < -((1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 3)) - 1): + diff += (1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 4)) + + case diff > ((1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 3)) - 1): + diff -= (1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 4)) + } + return diff +} + +// DTSExtractor allows to extract DTS from PTS. +type DTSExtractor struct { + spsp *SPS + prevDTSFilled bool + prevDTS time.Duration + expectedPOC uint32 + reorderedFrames int + pauseDTS int + pocIncrement int +} + +// NewDTSExtractor allocates a DTSExtractor. +func NewDTSExtractor() *DTSExtractor { + return &DTSExtractor{ + pocIncrement: 2, + } +} + +func (d *DTSExtractor) extractInner(au [][]byte, pts time.Duration) (time.Duration, error) { + idrPresent := false + + for _, nalu := range au { + typ := NALUType(nalu[0] & 0x1F) + switch typ { + case NALUTypeSPS: + var spsp SPS + err := spsp.Unmarshal(nalu) + if err != nil { + return 0, fmt.Errorf("invalid SPS: %v", err) + } + d.spsp = &spsp + + case NALUTypeIDR: + idrPresent = true + } + } + + if d.spsp == nil { + return 0, fmt.Errorf("SPS not received yet") + } + + if d.spsp.PicOrderCntType == 2 { + return pts, nil + } + + if d.spsp.PicOrderCntType == 1 { + return 0, fmt.Errorf("pic_order_cnt_type = 1 is not supported yet") + } + + if idrPresent { + d.expectedPOC = 0 + d.reorderedFrames = 0 + d.pauseDTS = 0 + d.pocIncrement = 2 + return pts, nil + } + + d.expectedPOC += uint32(d.pocIncrement) + d.expectedPOC &= ((1 << (d.spsp.Log2MaxPicOrderCntLsbMinus4 + 4)) - 1) + + if d.pauseDTS > 0 { + d.pauseDTS-- + return d.prevDTS + 1*time.Millisecond, nil + } + + poc, err := findPictureOrderCount(au, d.spsp) + if err != nil { + return 0, err + } + + if d.pocIncrement == 2 && (poc%2) != 0 { + d.pocIncrement = 1 + d.expectedPOC /= 2 + } + + pocDiff := int(getPictureOrderCountDiff(poc, d.expectedPOC, d.spsp)) + d.reorderedFrames*d.pocIncrement + + if pocDiff < 0 { + return 0, fmt.Errorf("invalid POC") + } + + if pocDiff == 0 { + return pts, nil + } + + reorderedFrames := (pocDiff - d.reorderedFrames*d.pocIncrement) / d.pocIncrement + if reorderedFrames > d.reorderedFrames { + d.pauseDTS = (reorderedFrames - d.reorderedFrames - 1) + d.reorderedFrames = reorderedFrames + return d.prevDTS + 1*time.Millisecond, nil + } + + return d.prevDTS + ((pts - d.prevDTS) * time.Duration(d.pocIncrement) / time.Duration(pocDiff+d.pocIncrement)), nil +} + +// Extract extracts the DTS of a access unit. +func (d *DTSExtractor) Extract(au [][]byte, pts time.Duration) (time.Duration, error) { + dts, err := d.extractInner(au, pts) + if err != nil { + return 0, err + } + + if dts > pts { + return 0, fmt.Errorf("DTS is greater than PTS") + } + + if d.prevDTSFilled && dts <= d.prevDTS { + return 0, fmt.Errorf("DTS is not monotonically increasing, was %v, now is %v", + d.prevDTS, dts) + } + + d.prevDTS = dts + d.prevDTSFilled = true + + return dts, err +} diff --git a/pkg/codecs/h264/dts_extractor_test.go b/pkg/codecs/h264/dts_extractor_test.go new file mode 100644 index 0000000..e5b73f0 --- /dev/null +++ b/pkg/codecs/h264/dts_extractor_test.go @@ -0,0 +1,222 @@ +//go:build go1.18 +// +build go1.18 + +package h264 + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDTSExtractor(t *testing.T) { + type sequenceSample struct { + nalus [][]byte + dts time.Duration + pts time.Duration + } + + for _, ca := range []struct { + name string + sequence []sequenceSample + }{ + { + "with timing info", + []sequenceSample{ + { + [][]byte{ + { // SPS + 0x67, 0x64, 0x00, 0x28, 0xac, 0xd9, 0x40, 0x78, + 0x02, 0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, + 0xc6, 0x58, + }, + { // IDR + 0x65, 0x88, 0x84, 0x00, 0x33, 0xff, + }, + }, + 33333333333 * time.Nanosecond, + 33333333333 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9a, 0x21, 0x6c, 0x45, 0xff}}, + 33366666666 * time.Nanosecond, + 33366666666 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9a, 0x42, 0x3c, 0x21, 0x93}}, + 33400000000 * time.Nanosecond, + 33400000000 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9a, 0x63, 0x49, 0xe1, 0x0f}}, + 33433333333 * time.Nanosecond, + 33433333333 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9a, 0x86, 0x49, 0xe1, 0x0f}}, + 33434333333 * time.Nanosecond, + 33533333333 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9e, 0xa5, 0x42, 0x7f, 0xf9}}, + 33435333333 * time.Nanosecond, + 33500000000 * time.Nanosecond, + }, + { + [][]byte{{0x01, 0x9e, 0xc4, 0x69, 0x13, 0xff}}, + 33466666666 * time.Nanosecond, + 33466666666 * time.Nanosecond, + }, + { + [][]byte{{0x41, 0x9a, 0xc8, 0x4b, 0xa8, 0x42}}, + 33499999999 * time.Nanosecond, + 33600000000 * time.Nanosecond, + }, + }, + }, + { + "no timing info", + []sequenceSample{ + { + [][]byte{ + { // SPS + 0x27, 0x64, 0x00, 0x20, 0xac, 0x52, 0x18, 0x0f, + 0x01, 0x17, 0xef, 0xff, 0x00, 0x01, 0x00, 0x01, + 0x6a, 0x02, 0x02, 0x03, 0x6d, 0x85, 0x6b, 0xde, + 0xf8, 0x08, + }, + { // IDR + 0x25, 0xb8, 0x08, 0x02, 0x1f, 0xff, + }, + }, + 850000000 * time.Nanosecond, + 850000000 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe1, 0x05, 0xc7, 0x38, 0xbf}}, + 866666667 * time.Nanosecond, + 866666667 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe2, 0x09, 0xa1, 0xce, 0x0b}}, + 883333334 * time.Nanosecond, + 883333334 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe3, 0x0d, 0xb1, 0xce, 0x02}}, + 900000000 * time.Nanosecond, + 900000000 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe4, 0x11, 0x90, 0x73, 0x80}}, + 916666667 * time.Nanosecond, + 916666667 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe5, 0x19, 0x0e, 0x70, 0x01}}, + 917666667 * time.Nanosecond, + 950000000 * time.Nanosecond, + }, + { + [][]byte{{0x01, 0xa9, 0x85, 0x7c, 0x93, 0xff}}, + 933333334 * time.Nanosecond, + 933333334 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe6, 0x1d, 0x0e, 0x70, 0x01}}, + 950000000 * time.Nanosecond, + 966666667 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe7, 0x21, 0x0e, 0x70, 0x01}}, + 966666667 * time.Nanosecond, + 983333334 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe8, 0x25, 0x0e, 0x70, 0x01}}, + 983333333 * time.Nanosecond, + 1000000000 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xe9, 0x29, 0x0e, 0x70, 0x01}}, + 1000000000 * time.Nanosecond, + 1016666667 * time.Nanosecond, + }, + { + [][]byte{{0x21, 0xea, 0x31, 0x0e, 0x70, 0x01}}, + 1016666666 * time.Nanosecond, + 1050000000 * time.Nanosecond, + }, + { + [][]byte{{0x01, 0xaa, 0xcb, 0x7c, 0x93, 0xff}}, + 1033333334 * time.Nanosecond, + 1033333334 * time.Nanosecond, + }, + }, + }, + { + "poc increment = 1", + []sequenceSample{ + { + [][]byte{ + { // SPS + 0x67, 0x64, 0x00, 0x2a, 0xac, 0x2c, 0x6a, 0x81, + 0xe0, 0x08, 0x9f, 0x96, 0x6e, 0x02, 0x02, 0x02, + 0x80, 0x00, 0x03, 0x84, 0x00, 0x00, 0xaf, 0xc8, + 0x02, + }, + { // IDR + 0x65, 0xb8, 0x00, 0x00, 0x0b, 0xc8, + }, + }, + 61 * time.Millisecond, + 61 * time.Millisecond, + }, + { + [][]byte{{0x61, 0xe0, 0x20, 0x00, 0x39, 0x37}}, + 101 * time.Millisecond, + 101 * time.Millisecond, + }, + { + [][]byte{{0x61, 0xe0, 0x40, 0x00, 0x59, 0x37}}, + 141 * time.Millisecond, + 141 * time.Millisecond, + }, + { + [][]byte{{0x61, 0xe0, 0x60, 0x00, 0x79, 0x37}}, + 181 * time.Millisecond, + 181 * time.Millisecond, + }, + }, + }, + } { + t.Run(ca.name, func(t *testing.T) { + ex := NewDTSExtractor() + for _, sample := range ca.sequence { + dts, err := ex.Extract(sample.nalus, sample.pts) + require.NoError(t, err) + require.Equal(t, sample.dts, dts) + } + }) + } +} + +func FuzzDTSExtractor(f *testing.F) { + ex := NewDTSExtractor() + f.Fuzz(func(t *testing.T, b []byte, p uint64) { + if len(b) < 1 { + return + } + ex.Extract([][]byte{ + { // SPS + 0x27, 0x64, 0x00, 0x20, 0xac, 0x52, 0x18, 0x0f, + 0x01, 0x17, 0xef, 0xff, 0x00, 0x01, 0x00, 0x01, + 0x6a, 0x02, 0x02, 0x03, 0x6d, 0x85, 0x6b, 0xde, + 0xf8, 0x08, + }, + b, + }, time.Duration(p)) + }) +} diff --git a/pkg/codecs/h264/emulation_prevention.go b/pkg/codecs/h264/emulation_prevention.go new file mode 100644 index 0000000..611a080 --- /dev/null +++ b/pkg/codecs/h264/emulation_prevention.go @@ -0,0 +1,33 @@ +package h264 + +// EmulationPreventionRemove removes emulation prevention bytes from a NALU. +func EmulationPreventionRemove(nalu []byte) []byte { + // 0x00 0x00 0x03 0x00 -> 0x00 0x00 0x00 + // 0x00 0x00 0x03 0x01 -> 0x00 0x00 0x01 + // 0x00 0x00 0x03 0x02 -> 0x00 0x00 0x02 + // 0x00 0x00 0x03 0x03 -> 0x00 0x00 0x03 + + l := len(nalu) + n := l + + for i := 2; i < l; i++ { + if nalu[i-2] == 0 && nalu[i-1] == 0 && nalu[i] == 3 { + n-- + } + } + + ret := make([]byte, n) + pos := 0 + start := 0 + + for i := 2; i < l; i++ { + if nalu[i-2] == 0 && nalu[i-1] == 0 && nalu[i] == 3 { + pos += copy(ret[pos:], nalu[start:i]) + start = i + 1 + } + } + + copy(ret[pos:], nalu[start:]) + + return ret +} diff --git a/pkg/codecs/h264/emulation_prevention_test.go b/pkg/codecs/h264/emulation_prevention_test.go new file mode 100644 index 0000000..bd54ded --- /dev/null +++ b/pkg/codecs/h264/emulation_prevention_test.go @@ -0,0 +1,65 @@ +//go:build go1.18 +// +build go1.18 + +package h264 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEmulationPreventionRemove(t *testing.T) { + for _, ca := range []struct { + name string + unproc []byte + proc []byte + }{ + { + "base", + []byte{ + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + 0x00, 0x00, 0x02, + 0x00, 0x00, 0x03, + }, + []byte{ + 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x03, 0x01, + 0x00, 0x00, 0x03, 0x02, + 0x00, 0x00, 0x03, 0x03, + }, + }, + { + "double emulation byte", + []byte{ + 0x00, 0x00, 0x00, + 0x00, 0x00, + }, + []byte{ + 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, + }, + }, + { + "terminal emulation byte", + []byte{ + 0x00, 0x00, + }, + []byte{ + 0x00, 0x00, 0x03, + }, + }, + } { + t.Run(ca.name, func(t *testing.T) { + unproc := EmulationPreventionRemove(ca.proc) + require.Equal(t, ca.unproc, unproc) + }) + } +} + +func FuzzEmulationPreventionRemove(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + EmulationPreventionRemove(b) + }) +} diff --git a/pkg/codecs/h264/h264.go b/pkg/codecs/h264/h264.go new file mode 100644 index 0000000..e2cf793 --- /dev/null +++ b/pkg/codecs/h264/h264.go @@ -0,0 +1,11 @@ +// Package h264 contains utilities to work with the H264 codec. +package h264 + +const ( + // MaxNALUSize is the maximum size of a NALU. + // with a 250 Mbps H264 video, the maximum NALU size is 2.2MB + MaxNALUSize = 3 * 1024 * 1024 + + // MaxNALUsPerGroup is the maximum number of NALUs per group. + MaxNALUsPerGroup = 20 +) diff --git a/pkg/codecs/h264/idrpresent.go b/pkg/codecs/h264/idrpresent.go new file mode 100644 index 0000000..9c329d4 --- /dev/null +++ b/pkg/codecs/h264/idrpresent.go @@ -0,0 +1,12 @@ +package h264 + +// IDRPresent check if there's an IDR inside provided NALUs. +func IDRPresent(nalus [][]byte) bool { + for _, nalu := range nalus { + typ := NALUType(nalu[0] & 0x1F) + if typ == NALUTypeIDR { + return true + } + } + return false +} diff --git a/pkg/codecs/h264/idrpresent_test.go b/pkg/codecs/h264/idrpresent_test.go new file mode 100644 index 0000000..209f9c8 --- /dev/null +++ b/pkg/codecs/h264/idrpresent_test.go @@ -0,0 +1,17 @@ +package h264 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIDRPresent(t *testing.T) { + require.Equal(t, true, IDRPresent([][]byte{ + {0x05}, + {0x07}, + })) + require.Equal(t, false, IDRPresent([][]byte{ + {0x01}, + })) +} diff --git a/pkg/codecs/h264/nalu_type.go b/pkg/codecs/h264/nalu_type.go new file mode 100644 index 0000000..5c5a86a --- /dev/null +++ b/pkg/codecs/h264/nalu_type.go @@ -0,0 +1,83 @@ +package h264 + +import ( + "fmt" +) + +// NALUType is the type of a NALU. +type NALUType uint8 + +// NALU types. +const ( + NALUTypeNonIDR NALUType = 1 + NALUTypeDataPartitionA NALUType = 2 + NALUTypeDataPartitionB NALUType = 3 + NALUTypeDataPartitionC NALUType = 4 + NALUTypeIDR NALUType = 5 + NALUTypeSEI NALUType = 6 + NALUTypeSPS NALUType = 7 + NALUTypePPS NALUType = 8 + NALUTypeAccessUnitDelimiter NALUType = 9 + NALUTypeEndOfSequence NALUType = 10 + NALUTypeEndOfStream NALUType = 11 + NALUTypeFillerData NALUType = 12 + NALUTypeSPSExtension NALUType = 13 + NALUTypePrefix NALUType = 14 + NALUTypeSubsetSPS NALUType = 15 + NALUTypeReserved16 NALUType = 16 + NALUTypeReserved17 NALUType = 17 + NALUTypeReserved18 NALUType = 18 + NALUTypeSliceLayerWithoutPartitioning NALUType = 19 + NALUTypeSliceExtension NALUType = 20 + NALUTypeSliceExtensionDepth NALUType = 21 + NALUTypeReserved22 NALUType = 22 + NALUTypeReserved23 NALUType = 23 + + // additional NALU types for RTP/H264 + NALUTypeSTAPA NALUType = 24 + NALUTypeSTAPB NALUType = 25 + NALUTypeMTAP16 NALUType = 26 + NALUTypeMTAP24 NALUType = 27 + NALUTypeFUA NALUType = 28 + NALUTypeFUB NALUType = 29 +) + +var naluTypeLabels = map[NALUType]string{ + NALUTypeNonIDR: "NonIDR", + NALUTypeDataPartitionA: "DataPartitionA", + NALUTypeDataPartitionB: "DataPartitionB", + NALUTypeDataPartitionC: "DataPartitionC", + NALUTypeIDR: "IDR", + NALUTypeSEI: "SEI", + NALUTypeSPS: "SPS", + NALUTypePPS: "PPS", + NALUTypeAccessUnitDelimiter: "AccessUnitDelimiter", + NALUTypeEndOfSequence: "EndOfSequence", + NALUTypeEndOfStream: "EndOfStream", + NALUTypeFillerData: "FillerData", + NALUTypeSPSExtension: "SPSExtension", + NALUTypePrefix: "Prefix", + NALUTypeSubsetSPS: "SubsetSPS", + NALUTypeReserved16: "Reserved16", + NALUTypeReserved17: "Reserved17", + NALUTypeReserved18: "Reserved18", + NALUTypeSliceLayerWithoutPartitioning: "SliceLayerWithoutPartitioning", + NALUTypeSliceExtension: "SliceExtension", + NALUTypeSliceExtensionDepth: "SliceExtensionDepth", + NALUTypeReserved22: "Reserved22", + NALUTypeReserved23: "Reserved23", + NALUTypeSTAPA: "STAP-A", + NALUTypeSTAPB: "STAP-B", + NALUTypeMTAP16: "MTAP-16", + NALUTypeMTAP24: "MTAP-24", + NALUTypeFUA: "FU-A", + NALUTypeFUB: "FU-B", +} + +// String implements fmt.Stringer. +func (nt NALUType) String() string { + if l, ok := naluTypeLabels[nt]; ok { + return l + } + return fmt.Sprintf("unknown (%d)", nt) +} diff --git a/pkg/codecs/h264/nalu_type_test.go b/pkg/codecs/h264/nalu_type_test.go new file mode 100644 index 0000000..8602e0a --- /dev/null +++ b/pkg/codecs/h264/nalu_type_test.go @@ -0,0 +1,13 @@ +package h264 + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNALUType(t *testing.T) { + require.NotEqual(t, true, strings.HasPrefix(NALUType(10).String(), "unknown")) + require.Equal(t, true, strings.HasPrefix(NALUType(50).String(), "unknown")) +} diff --git a/pkg/codecs/h264/sps.go b/pkg/codecs/h264/sps.go new file mode 100644 index 0000000..9fbf3c9 --- /dev/null +++ b/pkg/codecs/h264/sps.go @@ -0,0 +1,728 @@ +package h264 + +import ( + "fmt" + + "github.com/bluenviron/mediabase/pkg/bits" +) + +const ( + maxRefFrames = 255 +) + +func readScalingList(buf []byte, pos *int, size int) ([]int32, bool, error) { + lastScale := int32(8) + nextScale := int32(8) + scalingList := make([]int32, size) + var useDefaultScalingMatrixFlag bool + + for j := 0; j < size; j++ { + if nextScale != 0 { + deltaScale, err := bits.ReadGolombSigned(buf, pos) + if err != nil { + return nil, false, err + } + + nextScale = (lastScale + deltaScale + 256) % 256 + useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0) + } + + if nextScale == 0 { + scalingList[j] = lastScale + } else { + scalingList[j] = nextScale + } + + lastScale = scalingList[j] + } + + return scalingList, useDefaultScalingMatrixFlag, nil +} + +// SPS_HRD is a hypotetical reference decoder. +type SPS_HRD struct { //nolint:revive + CpbCntMinus1 uint32 + BitRateScale uint8 + CpbSizeScale uint8 + BitRateValueMinus1 []uint32 + CpbSizeValueMinus1 []uint32 + CbrFlag []bool + InitialCpbRemovalDelayLengthMinus1 uint8 + CpbRemovalDelayLengthMinus1 uint8 + DpbOutputDelayLengthMinus1 uint8 + TimeOffsetLength uint8 +} + +func (h *SPS_HRD) unmarshal(buf []byte, pos *int) error { + var err error + h.CpbCntMinus1, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + err = bits.HasSpace(buf, *pos, 8) + if err != nil { + return err + } + + h.BitRateScale = uint8(bits.ReadBitsUnsafe(buf, pos, 4)) + h.CpbSizeScale = uint8(bits.ReadBitsUnsafe(buf, pos, 4)) + + for i := uint32(0); i <= h.CpbCntMinus1; i++ { + v, err := bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + h.BitRateValueMinus1 = append(h.BitRateValueMinus1, v) + + v, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + h.CpbSizeValueMinus1 = append(h.CpbSizeValueMinus1, v) + + vb, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + h.CbrFlag = append(h.CbrFlag, vb) + } + + err = bits.HasSpace(buf, *pos, 5+5+5+5) + if err != nil { + return err + } + + h.InitialCpbRemovalDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) + h.CpbRemovalDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) + h.DpbOutputDelayLengthMinus1 = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) + h.TimeOffsetLength = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) + + return nil +} + +// SPS_TimingInfo is a timing info. +type SPS_TimingInfo struct { //nolint:revive + NumUnitsInTick uint32 + TimeScale uint32 + FixedFrameRateFlag bool +} + +func (t *SPS_TimingInfo) unmarshal(buf []byte, pos *int) error { + err := bits.HasSpace(buf, *pos, 32+32+1) + if err != nil { + return err + } + + t.NumUnitsInTick = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) + t.TimeScale = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) + t.FixedFrameRateFlag = bits.ReadFlagUnsafe(buf, pos) + + return nil +} + +// SPS_BitstreamRestriction are bitstream restriction infos. +type SPS_BitstreamRestriction struct { //nolint:revive + MotionVectorsOverPicBoundariesFlag bool + MaxBytesPerPicDenom uint32 + MaxBitsPerMbDenom uint32 + Log2MaxMvLengthHorizontal uint32 + Log2MaxMvLengthVertical uint32 + MaxNumReorderFrames uint32 + MaxDecFrameBuffering uint32 +} + +func (r *SPS_BitstreamRestriction) unmarshal(buf []byte, pos *int) error { + var err error + r.MotionVectorsOverPicBoundariesFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + r.MaxBytesPerPicDenom, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.MaxBitsPerMbDenom, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.Log2MaxMvLengthHorizontal, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.Log2MaxMvLengthVertical, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.MaxNumReorderFrames, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.MaxDecFrameBuffering, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + return nil +} + +// SPS_VUI is a video usability information. +type SPS_VUI struct { //nolint:revive + AspectRatioInfoPresentFlag bool + + // AspectRatioInfoPresentFlag == true + AspectRatioIdc uint8 + SarWidth uint16 + SarHeight uint16 + + OverscanInfoPresentFlag bool + + // OverscanInfoPresentFlag == true + OverscanAppropriateFlag bool + VideoSignalTypePresentFlag bool + + // VideoSignalTypePresentFlag == true + VideoFormat uint8 + VideoFullRangeFlag bool + ColourDescriptionPresentFlag bool + + // ColourDescriptionPresentFlag == true + ColourPrimaries uint8 + TransferCharacteristics uint8 + MatrixCoefficients uint8 + + ChromaLocInfoPresentFlag bool + + // ChromaLocInfoPresentFlag == true + ChromaSampleLocTypeTopField uint32 + ChromaSampleLocTypeBottomField uint32 + + TimingInfo *SPS_TimingInfo + NalHRD *SPS_HRD + VclHRD *SPS_HRD + + LowDelayHrdFlag bool + PicStructPresentFlag bool + BitstreamRestriction *SPS_BitstreamRestriction +} + +func (v *SPS_VUI) unmarshal(buf []byte, pos *int) error { + var err error + v.AspectRatioInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.AspectRatioInfoPresentFlag { + tmp, err := bits.ReadBits(buf, pos, 8) + if err != nil { + return err + } + v.AspectRatioIdc = uint8(tmp) + + if v.AspectRatioIdc == 255 { // Extended_SAR + err := bits.HasSpace(buf, *pos, 32) + if err != nil { + return err + } + + v.SarWidth = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) + v.SarHeight = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) + } + } + + v.OverscanInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.OverscanInfoPresentFlag { + v.OverscanAppropriateFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + + v.VideoSignalTypePresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.VideoSignalTypePresentFlag { + err := bits.HasSpace(buf, *pos, 5) + if err != nil { + return err + } + + v.VideoFormat = uint8(bits.ReadBitsUnsafe(buf, pos, 3)) + v.VideoFullRangeFlag = bits.ReadFlagUnsafe(buf, pos) + v.ColourDescriptionPresentFlag = bits.ReadFlagUnsafe(buf, pos) + + if v.ColourDescriptionPresentFlag { + err := bits.HasSpace(buf, *pos, 24) + if err != nil { + return err + } + + v.ColourPrimaries = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + v.TransferCharacteristics = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + v.MatrixCoefficients = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + } + } + + v.ChromaLocInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.ChromaLocInfoPresentFlag { + v.ChromaSampleLocTypeTopField, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + v.ChromaSampleLocTypeBottomField, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + } + + timingInfoPresentFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if timingInfoPresentFlag { + v.TimingInfo = &SPS_TimingInfo{} + err := v.TimingInfo.unmarshal(buf, pos) + if err != nil { + return err + } + } + + nalHrdParametersPresentFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if nalHrdParametersPresentFlag { + v.NalHRD = &SPS_HRD{} + err := v.NalHRD.unmarshal(buf, pos) + if err != nil { + return err + } + } + + vclHrdParametersPresentFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if vclHrdParametersPresentFlag { + v.VclHRD = &SPS_HRD{} + err := v.VclHRD.unmarshal(buf, pos) + if err != nil { + return err + } + } + + if nalHrdParametersPresentFlag || vclHrdParametersPresentFlag { + v.LowDelayHrdFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + + v.PicStructPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + bitstreamRestrictionFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if bitstreamRestrictionFlag { + v.BitstreamRestriction = &SPS_BitstreamRestriction{} + err := v.BitstreamRestriction.unmarshal(buf, pos) + if err != nil { + return err + } + } + + return nil +} + +// SPS_FrameCropping is the frame cropping part of a SPS. +type SPS_FrameCropping struct { //nolint:revive + LeftOffset uint32 + RightOffset uint32 + TopOffset uint32 + BottomOffset uint32 +} + +func (c *SPS_FrameCropping) unmarshal(buf []byte, pos *int) error { + var err error + c.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.RightOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.TopOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + return nil +} + +// SPS is a H264 sequence parameter set. +type SPS struct { + ProfileIdc uint8 + ConstraintSet0Flag bool + ConstraintSet1Flag bool + ConstraintSet2Flag bool + ConstraintSet3Flag bool + ConstraintSet4Flag bool + ConstraintSet5Flag bool + LevelIdc uint8 + ID uint32 + + // only for selected ProfileIdcs + ChromeFormatIdc uint32 + SeparateColourPlaneFlag bool + BitDepthLumaMinus8 uint32 + BitDepthChromaMinus8 uint32 + QpprimeYZeroTransformBypassFlag bool + + // seqScalingListPresentFlag == true + ScalingList4x4 [][]int32 + UseDefaultScalingMatrix4x4Flag []bool + ScalingList8x8 [][]int32 + UseDefaultScalingMatrix8x8Flag []bool + + Log2MaxFrameNumMinus4 uint32 + PicOrderCntType uint32 + + // PicOrderCntType == 0 + Log2MaxPicOrderCntLsbMinus4 uint32 + + // PicOrderCntType == 1 + DeltaPicOrderAlwaysZeroFlag bool + OffsetForNonRefPic int32 + OffsetForTopToBottomField int32 + OffsetForRefFrames []int32 + + MaxNumRefFrames uint32 + GapsInFrameNumValueAllowedFlag bool + PicWidthInMbsMinus1 uint32 + PicHeightInMapUnitsMinus1 uint32 + FrameMbsOnlyFlag bool + + // FrameMbsOnlyFlag == false + MbAdaptiveFrameFieldFlag bool + + Direct8x8InferenceFlag bool + FrameCropping *SPS_FrameCropping + VUI *SPS_VUI +} + +// Unmarshal decodes a SPS from bytes. +func (s *SPS) Unmarshal(buf []byte) error { + buf = EmulationPreventionRemove(buf) + + if len(buf) < 4 { + return fmt.Errorf("not enough bits") + } + + s.ProfileIdc = buf[1] + s.ConstraintSet0Flag = (buf[2] >> 7) == 1 + s.ConstraintSet1Flag = (buf[2] >> 6 & 0x01) == 1 + s.ConstraintSet2Flag = (buf[2] >> 5 & 0x01) == 1 + s.ConstraintSet3Flag = (buf[2] >> 4 & 0x01) == 1 + s.ConstraintSet4Flag = (buf[2] >> 3 & 0x01) == 1 + s.ConstraintSet5Flag = (buf[2] >> 2 & 0x01) == 1 + s.LevelIdc = buf[3] + + buf = buf[4:] + pos := 0 + + var err error + s.ID, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + switch s.ProfileIdc { + case 100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135: + s.ChromeFormatIdc, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + if s.ChromeFormatIdc == 3 { + s.SeparateColourPlaneFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + } else { + s.SeparateColourPlaneFlag = false + } + + s.BitDepthLumaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.BitDepthChromaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.QpprimeYZeroTransformBypassFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + seqScalingMatrixPresentFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if seqScalingMatrixPresentFlag { + var lim int + if s.ChromeFormatIdc != 3 { + lim = 8 + } else { + lim = 12 + } + + for i := 0; i < lim; i++ { + seqScalingListPresentFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if seqScalingListPresentFlag { + if i < 6 { + scalingList, useDefaultScalingMatrixFlag, err := readScalingList(buf, &pos, 16) + if err != nil { + return err + } + + s.ScalingList4x4 = append(s.ScalingList4x4, scalingList) + s.UseDefaultScalingMatrix4x4Flag = append(s.UseDefaultScalingMatrix4x4Flag, + useDefaultScalingMatrixFlag) + } else { + scalingList, useDefaultScalingMatrixFlag, err := readScalingList(buf, &pos, 64) + if err != nil { + return err + } + + s.ScalingList8x8 = append(s.ScalingList8x8, scalingList) + s.UseDefaultScalingMatrix8x8Flag = append(s.UseDefaultScalingMatrix8x8Flag, + useDefaultScalingMatrixFlag) + } + } + } + } + + default: + s.ChromeFormatIdc = 0 + s.SeparateColourPlaneFlag = false + s.BitDepthLumaMinus8 = 0 + s.BitDepthChromaMinus8 = 0 + s.QpprimeYZeroTransformBypassFlag = false + } + + s.Log2MaxFrameNumMinus4, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.PicOrderCntType, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + switch s.PicOrderCntType { + case 0: + s.Log2MaxPicOrderCntLsbMinus4, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.DeltaPicOrderAlwaysZeroFlag = false + s.OffsetForNonRefPic = 0 + s.OffsetForTopToBottomField = 0 + s.OffsetForRefFrames = nil + + case 1: + s.Log2MaxPicOrderCntLsbMinus4 = 0 + + s.DeltaPicOrderAlwaysZeroFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + s.OffsetForNonRefPic, err = bits.ReadGolombSigned(buf, &pos) + if err != nil { + return err + } + + s.OffsetForTopToBottomField, err = bits.ReadGolombSigned(buf, &pos) + if err != nil { + return err + } + + numRefFramesInPicOrderCntCycle, err := bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + if numRefFramesInPicOrderCntCycle > maxRefFrames { + return fmt.Errorf("num_ref_frames_in_pic_order_cnt_cycle exceeds %d", maxRefFrames) + } + + s.OffsetForRefFrames = make([]int32, numRefFramesInPicOrderCntCycle) + for i := uint32(0); i < numRefFramesInPicOrderCntCycle; i++ { + v, err := bits.ReadGolombSigned(buf, &pos) + if err != nil { + return err + } + + s.OffsetForRefFrames[i] = v + } + + case 2: + s.Log2MaxPicOrderCntLsbMinus4 = 0 + s.DeltaPicOrderAlwaysZeroFlag = false + s.OffsetForNonRefPic = 0 + s.OffsetForTopToBottomField = 0 + s.OffsetForRefFrames = nil + + default: + return fmt.Errorf("invalid pic_order_cnt_type: %d", s.PicOrderCntType) + } + + s.MaxNumRefFrames, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.GapsInFrameNumValueAllowedFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + s.PicWidthInMbsMinus1, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.PicHeightInMapUnitsMinus1, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.FrameMbsOnlyFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if !s.FrameMbsOnlyFlag { + s.MbAdaptiveFrameFieldFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + } else { + s.MbAdaptiveFrameFieldFlag = false + } + + s.Direct8x8InferenceFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + frameCroppingFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if frameCroppingFlag { + s.FrameCropping = &SPS_FrameCropping{} + err := s.FrameCropping.unmarshal(buf, &pos) + if err != nil { + return err + } + } else { + s.FrameCropping = nil + } + + vuiParametersPresentFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if vuiParametersPresentFlag { + s.VUI = &SPS_VUI{} + err := s.VUI.unmarshal(buf, &pos) + if err != nil { + return err + } + } else { + s.VUI = nil + } + + return nil +} + +// Width returns the video width. +func (s SPS) Width() int { + if s.FrameCropping != nil { + return int(((s.PicWidthInMbsMinus1 + 1) * 16) - (s.FrameCropping.LeftOffset+s.FrameCropping.RightOffset)*2) + } + + return int((s.PicWidthInMbsMinus1 + 1) * 16) +} + +// Height returns the video height. +func (s SPS) Height() int { + f := uint32(0) + if s.FrameMbsOnlyFlag { + f = 1 + } + + if s.FrameCropping != nil { + return int(((2 - f) * (s.PicHeightInMapUnitsMinus1 + 1) * 16) - + (s.FrameCropping.TopOffset+s.FrameCropping.BottomOffset)*2) + } + + return int((2 - f) * (s.PicHeightInMapUnitsMinus1 + 1) * 16) +} + +// FPS returns the frames per second of the video. +func (s SPS) FPS() float64 { + if s.VUI == nil || s.VUI.TimingInfo == nil { + return 0 + } + + return float64(s.VUI.TimingInfo.TimeScale) / (2 * float64(s.VUI.TimingInfo.NumUnitsInTick)) +} diff --git a/pkg/codecs/h264/sps_test.go b/pkg/codecs/h264/sps_test.go new file mode 100644 index 0000000..0f47e65 --- /dev/null +++ b/pkg/codecs/h264/sps_test.go @@ -0,0 +1,462 @@ +//go:build go1.18 +// +build go1.18 + +package h264 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSPSUnmarshal(t *testing.T) { + for _, ca := range []struct { + name string + byts []byte + sps SPS + width int + height int + fps float64 + }{ + { + "352x288", + []byte{ + 0x67, 0x64, 0x00, 0x0c, 0xac, 0x3b, 0x50, 0xb0, + 0x4b, 0x42, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x00, 0x03, 0x00, 0x3d, 0x08, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 12, + ChromeFormatIdc: 1, + Log2MaxFrameNumMinus4: 6, + PicOrderCntType: 2, + MaxNumRefFrames: 1, + GapsInFrameNumValueAllowedFlag: true, + PicWidthInMbsMinus1: 21, + PicHeightInMapUnitsMinus1: 17, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 30, + FixedFrameRateFlag: true, + }, + }, + }, + 352, + 288, + 15, + }, + { + "1280x720", + []byte{ + 0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50, + 0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18, + 0xcb, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 31, + ChromeFormatIdc: 1, + Log2MaxPicOrderCntLsbMinus4: 2, + MaxNumRefFrames: 4, + PicWidthInMbsMinus1: 79, + PicHeightInMapUnitsMinus1: 44, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + VideoFullRangeFlag: true, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 60, + }, + BitstreamRestriction: &SPS_BitstreamRestriction{ + MotionVectorsOverPicBoundariesFlag: true, + Log2MaxMvLengthHorizontal: 11, + Log2MaxMvLengthVertical: 11, + MaxNumReorderFrames: 2, + MaxDecFrameBuffering: 4, + }, + }, + }, + 1280, + 720, + 30, + }, + { + "1920x1080 baseline", + []byte{ + 0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02, + 0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9, 0x20, + }, + SPS{ + ProfileIdc: 66, + ConstraintSet0Flag: true, + ConstraintSet1Flag: true, + LevelIdc: 40, + PicOrderCntType: 2, + MaxNumRefFrames: 3, + PicWidthInMbsMinus1: 119, + PicHeightInMapUnitsMinus1: 67, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + FrameCropping: &SPS_FrameCropping{ + BottomOffset: 4, + }, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 60, + }, + BitstreamRestriction: &SPS_BitstreamRestriction{ + MotionVectorsOverPicBoundariesFlag: true, + Log2MaxMvLengthHorizontal: 11, + Log2MaxMvLengthVertical: 11, + MaxDecFrameBuffering: 3, + }, + }, + }, + 1920, + 1080, + 30, + }, + { + "1920x1080 nvidia", + []byte{ + 0x67, 0x64, 0x00, 0x28, 0xac, 0xd9, 0x40, 0x78, + 0x02, 0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, + 0xc6, 0x58, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 40, + ChromeFormatIdc: 1, + Log2MaxPicOrderCntLsbMinus4: 2, + MaxNumRefFrames: 4, + PicWidthInMbsMinus1: 119, + PicHeightInMapUnitsMinus1: 67, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + FrameCropping: &SPS_FrameCropping{ + BottomOffset: 4, + }, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 60, + }, + BitstreamRestriction: &SPS_BitstreamRestriction{ + MotionVectorsOverPicBoundariesFlag: true, + Log2MaxMvLengthHorizontal: 11, + Log2MaxMvLengthVertical: 11, + MaxNumReorderFrames: 2, + MaxDecFrameBuffering: 4, + }, + }, + }, + 1920, + 1080, + 30, + }, + { + "1920x1080", + []byte{ + 0x67, 0x64, 0x00, 0x29, 0xac, 0x13, 0x31, 0x40, + 0x78, 0x04, 0x47, 0xde, 0x03, 0xea, 0x02, 0x02, + 0x03, 0xe0, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, + 0x00, 0x06, 0x52, // 0x80, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 41, + ChromeFormatIdc: 1, + Log2MaxFrameNumMinus4: 8, + Log2MaxPicOrderCntLsbMinus4: 5, + MaxNumRefFrames: 4, + PicWidthInMbsMinus1: 119, + PicHeightInMapUnitsMinus1: 33, + Direct8x8InferenceFlag: true, + FrameCropping: &SPS_FrameCropping{ + BottomOffset: 2, + }, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + OverscanInfoPresentFlag: true, + OverscanAppropriateFlag: true, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + ChromaLocInfoPresentFlag: true, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 50, + FixedFrameRateFlag: true, + }, + PicStructPresentFlag: true, + }, + }, + 1920, + 1084, + 25, + }, + { + "hikvision", + []byte{103, 100, 0, 32, 172, 23, 42, 1, 64, 30, 104, 64, 0, 1, 194, 0, 0, 87, 228, 33}, + SPS{ + ProfileIdc: 100, + LevelIdc: 32, + ChromeFormatIdc: 1, + Log2MaxPicOrderCntLsbMinus4: 4, + MaxNumRefFrames: 1, + PicWidthInMbsMinus1: 79, + PicHeightInMapUnitsMinus1: 59, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + Log2MaxFrameNumMinus4: 10, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1800, + TimeScale: 90000, + FixedFrameRateFlag: true, + }, + }, + }, + 1280, + 960, + 25, + }, + { + "scaling matrix", + []byte{ + 103, 100, 0, 50, 173, 132, 1, 12, 32, 8, 97, 0, 67, 8, 2, + 24, 64, 16, 194, 0, 132, 59, 80, 20, 0, 90, 211, + 112, 16, 16, 20, 0, 0, 3, 0, 4, 0, 0, 3, 0, 162, 16, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 50, + ChromeFormatIdc: 1, + ScalingList4x4: [][]int32{ + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + UseDefaultScalingMatrix4x4Flag: []bool{ + false, false, false, false, false, false, + }, + Log2MaxFrameNumMinus4: 6, + PicOrderCntType: 2, + MaxNumRefFrames: 1, + GapsInFrameNumValueAllowedFlag: true, + PicWidthInMbsMinus1: 159, + PicHeightInMapUnitsMinus1: 89, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + VUI: &SPS_VUI{ + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + VideoFullRangeFlag: true, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 40, + FixedFrameRateFlag: true, + }, + }, + }, + 2560, + 1440, + 20, + }, + { + "1920x1080 nvenc hrd", + []byte{ + 103, 100, 0, 42, 172, 44, 172, 7, + 128, 34, 126, 92, 5, 168, 8, 8, + 10, 0, 0, 7, 208, 0, 3, 169, + 129, 192, 0, 0, 76, 75, 0, 0, + 38, 37, 173, 222, 92, 20, + }, + SPS{ + ProfileIdc: 100, + LevelIdc: 42, + ChromeFormatIdc: 1, + Log2MaxFrameNumMinus4: 4, + Log2MaxPicOrderCntLsbMinus4: 4, + MaxNumRefFrames: 2, + PicWidthInMbsMinus1: 119, + PicHeightInMapUnitsMinus1: 67, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + FrameCropping: &SPS_FrameCropping{ + BottomOffset: 4, + }, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1000, + TimeScale: 120000, + FixedFrameRateFlag: true, + }, + NalHRD: &SPS_HRD{ + BitRateValueMinus1: []uint32{39061}, + CpbSizeValueMinus1: []uint32{156249}, + CbrFlag: []bool{true}, + InitialCpbRemovalDelayLengthMinus1: 23, + CpbRemovalDelayLengthMinus1: 15, + DpbOutputDelayLengthMinus1: 5, + TimeOffsetLength: 24, + }, + PicStructPresentFlag: true, + }, + }, + 1920, + 1080, + 60, + }, + { + "1920x1080 hikvision nal hrd + vcl hrd", + []byte{ + 103, 77, 0, 41, 154, 100, 3, 192, + 17, 63, 46, 2, 220, 4, 4, 5, + 0, 0, 3, 3, 232, 0, 0, 195, + 80, 232, 96, 0, 186, 180, 0, 2, + 234, 196, 187, 203, 141, 12, 0, 23, + 86, 128, 0, 93, 88, 151, 121, 112, + 160, + }, + SPS{ + ProfileIdc: 77, + LevelIdc: 41, + Log2MaxFrameNumMinus4: 5, + Log2MaxPicOrderCntLsbMinus4: 5, + MaxNumRefFrames: 1, + PicWidthInMbsMinus1: 119, + PicHeightInMapUnitsMinus1: 67, + FrameMbsOnlyFlag: true, + Direct8x8InferenceFlag: true, + FrameCropping: &SPS_FrameCropping{ + BottomOffset: 4, + }, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + VideoFullRangeFlag: true, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1000, + TimeScale: 50000, + FixedFrameRateFlag: true, + }, + NalHRD: &SPS_HRD{ + BitRateScale: 4, + CpbSizeScale: 3, + BitRateValueMinus1: []uint32{11948}, + CpbSizeValueMinus1: []uint32{95585}, + CbrFlag: []bool{false}, + InitialCpbRemovalDelayLengthMinus1: 23, + CpbRemovalDelayLengthMinus1: 15, + DpbOutputDelayLengthMinus1: 5, + TimeOffsetLength: 24, + }, + VclHRD: &SPS_HRD{ + BitRateScale: 4, + CpbSizeScale: 3, + BitRateValueMinus1: []uint32{11948}, + CpbSizeValueMinus1: []uint32{95585}, + CbrFlag: []bool{false}, + InitialCpbRemovalDelayLengthMinus1: 23, + CpbRemovalDelayLengthMinus1: 15, + DpbOutputDelayLengthMinus1: 5, + TimeOffsetLength: 24, + }, + PicStructPresentFlag: true, + }, + }, + 1920, + 1080, + 25, + }, + } { + t.Run(ca.name, func(t *testing.T) { + var sps SPS + err := sps.Unmarshal(ca.byts) + require.NoError(t, err) + require.Equal(t, ca.sps, sps) + require.Equal(t, ca.width, sps.Width()) + require.Equal(t, ca.height, sps.Height()) + require.Equal(t, ca.fps, sps.FPS()) + }) + } +} + +func BenchmarkSPSUnmarshal(b *testing.B) { + for i := 0; i < b.N; i++ { + var sps SPS + sps.Unmarshal([]byte{ + 103, 77, 0, 41, 154, 100, 3, 192, + 17, 63, 46, 2, 220, 4, 4, 5, + 0, 0, 3, 3, 232, 0, 0, 195, + 80, 232, 96, 0, 186, 180, 0, 2, + 234, 196, 187, 203, 141, 12, 0, 23, + 86, 128, 0, 93, 88, 151, 121, 112, + 160, + }) + } +} + +func FuzzSPSUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var sps SPS + sps.Unmarshal(b) + }) +} diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe new file mode 100644 index 0000000..6dd36a2 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x00\x00\x00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 new file mode 100644 index 0000000..7fd7a20 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/dad1340efc3fed8006eb91c7ec4be5cffca97bbe1c447ed47eda11adfd7ab0cc b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/dad1340efc3fed8006eb91c7ec4be5cffca97bbe1c447ed47eda11adfd7ab0cc new file mode 100644 index 0000000..3252f4a --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAVCCUnmarshal/dad1340efc3fed8006eb91c7ec4be5cffca97bbe1c447ed47eda11adfd7ab0cc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x000\x00\x00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe new file mode 100644 index 0000000..6dd36a2 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/002e276d0123e6698e29b86a6db8644720a23ad912d7be68bf441e186095f7fe @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x00\x00\x00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/2ce2df4de457e581f3404dedd305e7f281b04eeb75cc2339d58c64d6618e8702 b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/2ce2df4de457e581f3404dedd305e7f281b04eeb75cc2339d58c64d6618e8702 new file mode 100644 index 0000000..40e3823 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/2ce2df4de457e581f3404dedd305e7f281b04eeb75cc2339d58c64d6618e8702 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/f0b7708a3a98029bd20ee500be4f0a4b1969c5386f513788f118019a7e9e32b1 b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/f0b7708a3a98029bd20ee500be4f0a4b1969c5386f513788f118019a7e9e32b1 new file mode 100644 index 0000000..2fc528c --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/f0b7708a3a98029bd20ee500be4f0a4b1969c5386f513788f118019a7e9e32b1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x00\x01") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb2cff69a3eec4b1a50ea017aa5604d9b3910ddfa989bdb6bc7323714fda66b3 b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb2cff69a3eec4b1a50ea017aa5604d9b3910ddfa989bdb6bc7323714fda66b3 new file mode 100644 index 0000000..d19fb07 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb2cff69a3eec4b1a50ea017aa5604d9b3910ddfa989bdb6bc7323714fda66b3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x00\x01\x00\x00\x01") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb5317ecce56275a254428a8267b56951b5b6ec2fa924f1e8d8fcab394abc2d3 b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb5317ecce56275a254428a8267b56951b5b6ec2fa924f1e8d8fcab394abc2d3 new file mode 100644 index 0000000..3104422 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzAnnexBUnmarshal/fb5317ecce56275a254428a8267b56951b5b6ec2fa924f1e8d8fcab394abc2d3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x00\x00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1222d4cb572fa515ca7b8ba8dc649a0c711445e6307ee02a65b0a4322e758021 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1222d4cb572fa515ca7b8ba8dc649a0c711445e6307ee02a65b0a4322e758021 new file mode 100644 index 0000000..5f83259 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1222d4cb572fa515ca7b8ba8dc649a0c711445e6307ee02a65b0a4322e758021 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A0\x00\x0000") +uint64(122) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1223ae83b4925a9f1ade3b85a3b44c94a8135edafbbd664bd8e2eca808ca5ebc b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1223ae83b4925a9f1ade3b85a3b44c94a8135edafbbd664bd8e2eca808ca5ebc new file mode 100644 index 0000000..486c699 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/1223ae83b4925a9f1ade3b85a3b44c94a8135edafbbd664bd8e2eca808ca5ebc @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("'000\xdc10") +uint64(23) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/262c62a888c4d2e7f51c8ac2c37a8459445dd9279b725d7243c3341e8e5bc746 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/262c62a888c4d2e7f51c8ac2c37a8459445dd9279b725d7243c3341e8e5bc746 new file mode 100644 index 0000000..793a6b8 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/262c62a888c4d2e7f51c8ac2c37a8459445dd9279b725d7243c3341e8e5bc746 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A00\x0000") +uint64(122) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3b9a2adc3e27d7bc69f2eac840715796c9540b4942476167f0b4db164b52ce56 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3b9a2adc3e27d7bc69f2eac840715796c9540b4942476167f0b4db164b52ce56 new file mode 100644 index 0000000..d6720e5 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3b9a2adc3e27d7bc69f2eac840715796c9540b4942476167f0b4db164b52ce56 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A\x0001\x000") +uint64(188) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3cb3e1217d3d42a93448aba8877b465cf77c9425c65d3e2cf6f314d6cbd0050e b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3cb3e1217d3d42a93448aba8877b465cf77c9425c65d3e2cf6f314d6cbd0050e new file mode 100644 index 0000000..f754490 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/3cb3e1217d3d42a93448aba8877b465cf77c9425c65d3e2cf6f314d6cbd0050e @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A00000") +uint64(122) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/676f114d18955cd69fb374e86badcea42b216770d5fc4629d036eb04cfef9ae7 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/676f114d18955cd69fb374e86badcea42b216770d5fc4629d036eb04cfef9ae7 new file mode 100644 index 0000000..84f7c33 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/676f114d18955cd69fb374e86badcea42b216770d5fc4629d036eb04cfef9ae7 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("%") +uint64(14) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/b1d032bee609ec2a117b65530fb6f91bc8a0f066193f73e2d2fc35b282b88839 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/b1d032bee609ec2a117b65530fb6f91bc8a0f066193f73e2d2fc35b282b88839 new file mode 100644 index 0000000..798dfde --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/b1d032bee609ec2a117b65530fb6f91bc8a0f066193f73e2d2fc35b282b88839 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("\x01\f") +uint64(60) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/be0df8dc8259c6db1f7fe9c07d133559251d8a4697da418218cbaf077650f873 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/be0df8dc8259c6db1f7fe9c07d133559251d8a4697da418218cbaf077650f873 new file mode 100644 index 0000000..2df246f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/be0df8dc8259c6db1f7fe9c07d133559251d8a4697da418218cbaf077650f873 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A\x00\x00\x0000") +uint64(70) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c43c2cabc7b2a36f19a4717161402f7e12129cbe32cf765847b4377867ebc9b5 b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c43c2cabc7b2a36f19a4717161402f7e12129cbe32cf765847b4377867ebc9b5 new file mode 100644 index 0000000..1c0b9c7 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c43c2cabc7b2a36f19a4717161402f7e12129cbe32cf765847b4377867ebc9b5 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("A\x0001B0") +uint64(188) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c624d6d8804714db4b342d59c9e32f26eec2d69bb3aff1746a521786027b732c b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c624d6d8804714db4b342d59c9e32f26eec2d69bb3aff1746a521786027b732c new file mode 100644 index 0000000..ce8b813 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzDTSExtractor/c624d6d8804714db4b342d59c9e32f26eec2d69bb3aff1746a521786027b732c @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("'000%9000") +uint64(23) diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/01288c9efae1307be2542dbb019dc1ad59d072065ef32935d09b5de28f5d77e0 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/01288c9efae1307be2542dbb019dc1ad59d072065ef32935d09b5de28f5d77e0 new file mode 100644 index 0000000..23ff647 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/01288c9efae1307be2542dbb019dc1ad59d072065ef32935d09b5de28f5d77e0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 new file mode 100644 index 0000000..7fd7a20 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0af83188e9b1670a268e5a56d5527be7cf004a2b2c42d9299813c7dc88e9bbd2 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0af83188e9b1670a268e5a56d5527be7cf004a2b2c42d9299813c7dc88e9bbd2 new file mode 100644 index 0000000..092d4ef --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0af83188e9b1670a268e5a56d5527be7cf004a2b2c42d9299813c7dc88e9bbd2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf31Y08\xf7000000000\xd7") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0be6d2f66de27526159e6e47e60a6c7775cdab6db0e3295029427b18ae2ae747 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0be6d2f66de27526159e6e47e60a6c7775cdab6db0e3295029427b18ae2ae747 new file mode 100644 index 0000000..bab326f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0be6d2f66de27526159e6e47e60a6c7775cdab6db0e3295029427b18ae2ae747 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff2\xff0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0d87aecf7d4f3648538400e4f1a3ffeacee9738e4c3408a600c24a80de240bac b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0d87aecf7d4f3648538400e4f1a3ffeacee9738e4c3408a600c24a80de240bac new file mode 100644 index 0000000..7aa0164 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0d87aecf7d4f3648538400e4f1a3ffeacee9738e4c3408a600c24a80de240bac @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000B19") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0fb8db11e671e6fa6be3b8c7dbc448244bfd66bb4f85d90722653942fdcb60e4 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0fb8db11e671e6fa6be3b8c7dbc448244bfd66bb4f85d90722653942fdcb60e4 new file mode 100644 index 0000000..648feee --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/0fb8db11e671e6fa6be3b8c7dbc448244bfd66bb4f85d90722653942fdcb60e4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z0010") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/139370ab0793372c99ea8cd88ff2ffdd68dd18d6ca5b1074722884e7d4e4c6a2 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/139370ab0793372c99ea8cd88ff2ffdd68dd18d6ca5b1074722884e7d4e4c6a2 new file mode 100644 index 0000000..4795b88 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/139370ab0793372c99ea8cd88ff2ffdd68dd18d6ca5b1074722884e7d4e4c6a2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf60000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/13b2a92583c8d6ab7b595428ffeb9d6cdb51781f98d2cda015995753a7f716e9 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/13b2a92583c8d6ab7b595428ffeb9d6cdb51781f98d2cda015995753a7f716e9 new file mode 100644 index 0000000..ee7aa5f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/13b2a92583c8d6ab7b595428ffeb9d6cdb51781f98d2cda015995753a7f716e9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000772.B001") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1c8bbab9d5312be1b60753343a15d1ea8c4a7baf8b95bdad79903d47a2af568f b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1c8bbab9d5312be1b60753343a15d1ea8c4a7baf8b95bdad79903d47a2af568f new file mode 100644 index 0000000..40dd932 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1c8bbab9d5312be1b60753343a15d1ea8c4a7baf8b95bdad79903d47a2af568f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z00002") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1f21b9a6112f67bc666a661e23922b7370f4b03e776cd4710bb197715d05e106 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1f21b9a6112f67bc666a661e23922b7370f4b03e776cd4710bb197715d05e106 new file mode 100644 index 0000000..ea01a67 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/1f21b9a6112f67bc666a661e23922b7370f4b03e776cd4710bb197715d05e106 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf6A") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/20599bffc63db3162d9e18b01d25c4d2b9bc91621d5107b91a9ae3ee676b3b69 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/20599bffc63db3162d9e18b01d25c4d2b9bc91621d5107b91a9ae3ee676b3b69 new file mode 100644 index 0000000..dcd59c7 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/20599bffc63db3162d9e18b01d25c4d2b9bc91621d5107b91a9ae3ee676b3b69 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z00$A0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2113482bfc82431ab4769ff2256411e7c7e865bf4d2fa2417cf15621a0aa6c68 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2113482bfc82431ab4769ff2256411e7c7e865bf4d2fa2417cf15621a0aa6c68 new file mode 100644 index 0000000..06ab239 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2113482bfc82431ab4769ff2256411e7c7e865bf4d2fa2417cf15621a0aa6c68 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017Y1") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/24ee50d0b17798d827100581c3939268fda76b1a29a64b67fa65580babb9f310 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/24ee50d0b17798d827100581c3939268fda76b1a29a64b67fa65580babb9f310 new file mode 100644 index 0000000..ab64a37 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/24ee50d0b17798d827100581c3939268fda76b1a29a64b67fa65580babb9f310 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A10") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/277b8e88b43c52e9676253793c9f06a763063a089bb7c6f5486331ca9426a898 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/277b8e88b43c52e9676253793c9f06a763063a089bb7c6f5486331ca9426a898 new file mode 100644 index 0000000..bf239ee --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/277b8e88b43c52e9676253793c9f06a763063a089bb7c6f5486331ca9426a898 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000777Z\x0e2\x0e000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/28f06b087ff4d71f788eb50d329a844bc5b06ba24530daafe2fb23707ec73f56 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/28f06b087ff4d71f788eb50d329a844bc5b06ba24530daafe2fb23707ec73f56 new file mode 100644 index 0000000..a72a66e --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/28f06b087ff4d71f788eb50d329a844bc5b06ba24530daafe2fb23707ec73f56 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2ab5ed4810474c02d699123edece8150d02d0f28a7f580c26847d3e6eae19f8e b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2ab5ed4810474c02d699123edece8150d02d0f28a7f580c26847d3e6eae19f8e new file mode 100644 index 0000000..b3ecbfc --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/2ab5ed4810474c02d699123edece8150d02d0f28a7f580c26847d3e6eae19f8e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000%0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/368b44f70bb50f9d3c1bc1c5bb714ab20766839e07e11d6e1a2e92d8c70a60a2 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/368b44f70bb50f9d3c1bc1c5bb714ab20766839e07e11d6e1a2e92d8c70a60a2 new file mode 100644 index 0000000..cf007b0 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/368b44f70bb50f9d3c1bc1c5bb714ab20766839e07e11d6e1a2e92d8c70a60a2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z007A") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/3b0f149b796c531a8ae4efdafde531d4280c980c2676ab030e7163f4d618869b b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/3b0f149b796c531a8ae4efdafde531d4280c980c2676ab030e7163f4d618869b new file mode 100644 index 0000000..4d95d66 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/3b0f149b796c531a8ae4efdafde531d4280c980c2676ab030e7163f4d618869b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017Y0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/41d70545c8a84390058018aded44531acaea8e1d19f18bd99730de3df81dc2b4 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/41d70545c8a84390058018aded44531acaea8e1d19f18bd99730de3df81dc2b4 new file mode 100644 index 0000000..474090b --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/41d70545c8a84390058018aded44531acaea8e1d19f18bd99730de3df81dc2b4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000177A000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/43b8a2672cd59b21a57bdb05a60ccb56dc5bc1db0bae2a12a115443d39d93c6e b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/43b8a2672cd59b21a57bdb05a60ccb56dc5bc1db0bae2a12a115443d39d93c6e new file mode 100644 index 0000000..a809978 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/43b8a2672cd59b21a57bdb05a60ccb56dc5bc1db0bae2a12a115443d39d93c6e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z007B000000771B$00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/452e524b55a29f1fe6f448570d1373ce2a6d116dfaa39c1ee11befed0cd82e61 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/452e524b55a29f1fe6f448570d1373ce2a6d116dfaa39c1ee11befed0cd82e61 new file mode 100644 index 0000000..2a33d83 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/452e524b55a29f1fe6f448570d1373ce2a6d116dfaa39c1ee11befed0cd82e61 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000\xff2") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/4a9f730d882605508b45b71ce9339664c952ce93ff20e89aee08b4c432aab3a7 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/4a9f730d882605508b45b71ce9339664c952ce93ff20e89aee08b4c432aab3a7 new file mode 100644 index 0000000..3ce7296 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/4a9f730d882605508b45b71ce9339664c952ce93ff20e89aee08b4c432aab3a7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000%A") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/50b649fe52d479d41725cdc8c8c532ea89b2ae61816b13f86ea486572215e81d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/50b649fe52d479d41725cdc8c8c532ea89b2ae61816b13f86ea486572215e81d new file mode 100644 index 0000000..a2806e2 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/50b649fe52d479d41725cdc8c8c532ea89b2ae61816b13f86ea486572215e81d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff2") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/5f47d452162ac208dcb3afd590dd27179dd0760a53aa6ee2a1ea2cb7a42ce506 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/5f47d452162ac208dcb3afd590dd27179dd0760a53aa6ee2a1ea2cb7a42ce506 new file mode 100644 index 0000000..63f6f5a --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/5f47d452162ac208dcb3afd590dd27179dd0760a53aa6ee2a1ea2cb7a42ce506 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf6017") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/641f6b7efc39fdef370a2bcc5038559d6ae38e23c23db2a0d82eca058e125166 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/641f6b7efc39fdef370a2bcc5038559d6ae38e23c23db2a0d82eca058e125166 new file mode 100644 index 0000000..94335c2 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/641f6b7efc39fdef370a2bcc5038559d6ae38e23c23db2a0d82eca058e125166 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z0017") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d new file mode 100644 index 0000000..959401e --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/67be690eb46ab3e15c9e157d0ef76b78172fc99dddd4299e86d13b79b984cb9e b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/67be690eb46ab3e15c9e157d0ef76b78172fc99dddd4299e86d13b79b984cb9e new file mode 100644 index 0000000..b6a3810 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/67be690eb46ab3e15c9e157d0ef76b78172fc99dddd4299e86d13b79b984cb9e @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf61") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6842f656bc0b9621f03f7e239abd268cf254b3a983a6b7379293611f56ebe74d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6842f656bc0b9621f03f7e239abd268cf254b3a983a6b7379293611f56ebe74d new file mode 100644 index 0000000..faa3aa4 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6842f656bc0b9621f03f7e239abd268cf254b3a983a6b7379293611f56ebe74d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00001\x17\x0000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6bbb3f597bab8e6e67e8cbd2e1d77b9ed0ab99094562759738971883b12b5ff5 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6bbb3f597bab8e6e67e8cbd2e1d77b9ed0ab99094562759738971883b12b5ff5 new file mode 100644 index 0000000..8000885 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/6bbb3f597bab8e6e67e8cbd2e1d77b9ed0ab99094562759738971883b12b5ff5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff0\xff0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/706f49c5b21047ed26fe721ad92e13ad3f99e6ceec8052bfecbee3596422d48a b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/706f49c5b21047ed26fe721ad92e13ad3f99e6ceec8052bfecbee3596422d48a new file mode 100644 index 0000000..1911a8c --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/706f49c5b21047ed26fe721ad92e13ad3f99e6ceec8052bfecbee3596422d48a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z002") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/7fc443da4b835c24546da2a593a050d7f842605f017d5e43a0d31b35e66f28fe b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/7fc443da4b835c24546da2a593a050d7f842605f017d5e43a0d31b35e66f28fe new file mode 100644 index 0000000..7488c6e --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/7fc443da4b835c24546da2a593a050d7f842605f017d5e43a0d31b35e66f28fe @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000X") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/829fde2929450193ab3c21246f4b66a05d5841569f9c5f1a4f19d081050b3747 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/829fde2929450193ab3c21246f4b66a05d5841569f9c5f1a4f19d081050b3747 new file mode 100644 index 0000000..15b5162 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/829fde2929450193ab3c21246f4b66a05d5841569f9c5f1a4f19d081050b3747 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000072") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/8a25aa52c31a312b339dd3f55a2d14c8d4dc2d9a4726c8f7806df12bda102326 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/8a25aa52c31a312b339dd3f55a2d14c8d4dc2d9a4726c8f7806df12bda102326 new file mode 100644 index 0000000..2a95651 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/8a25aa52c31a312b339dd3f55a2d14c8d4dc2d9a4726c8f7806df12bda102326 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017\xf60") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9095bee7552e53e949500f0cdf552d94e12df5f835eb9e06e6815957dc2d5fb2 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9095bee7552e53e949500f0cdf552d94e12df5f835eb9e06e6815957dc2d5fb2 new file mode 100644 index 0000000..e65369c --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9095bee7552e53e949500f0cdf552d94e12df5f835eb9e06e6815957dc2d5fb2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017\xf61") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9bed7ad10156a846b730b66e8f008894ef1b0398cbc1d3d72966d26bed74234b b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9bed7ad10156a846b730b66e8f008894ef1b0398cbc1d3d72966d26bed74234b new file mode 100644 index 0000000..a79f7d2 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/9bed7ad10156a846b730b66e8f008894ef1b0398cbc1d3d72966d26bed74234b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017Y00") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a068243fd4565e08237d9e8a45cb1d387b0a5b3ad6f2cdd861badd887f810b45 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a068243fd4565e08237d9e8a45cb1d387b0a5b3ad6f2cdd861badd887f810b45 new file mode 100644 index 0000000..555f935 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a068243fd4565e08237d9e8a45cb1d387b0a5b3ad6f2cdd861badd887f810b45 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf310\xff00007000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a1f57473c1cf3a081b94f3b4a38798ea2c723e1d88ab5fb6e144320b2314d6fe b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a1f57473c1cf3a081b94f3b4a38798ea2c723e1d88ab5fb6e144320b2314d6fe new file mode 100644 index 0000000..8d7e4f0 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a1f57473c1cf3a081b94f3b4a38798ea2c723e1d88ab5fb6e144320b2314d6fe @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf68") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a4c914c327ff2fa03d0bd9650ec9424c1b3b183dea47cea96cb89b3f9fd36986 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a4c914c327ff2fa03d0bd9650ec9424c1b3b183dea47cea96cb89b3f9fd36986 new file mode 100644 index 0000000..770e9cb --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a4c914c327ff2fa03d0bd9650ec9424c1b3b183dea47cea96cb89b3f9fd36986 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000\xff\xff\xff0a1000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a6f6a9bf667499515f0c228a8853d53517cfe49f51dc89f688d445d1265e5d7d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a6f6a9bf667499515f0c228a8853d53517cfe49f51dc89f688d445d1265e5d7d new file mode 100644 index 0000000..d5ff4cb --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/a6f6a9bf667499515f0c228a8853d53517cfe49f51dc89f688d445d1265e5d7d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A72") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac3507052c142f5628eada795764e75469e2585518502b400bfee0afd89b5d15 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac3507052c142f5628eada795764e75469e2585518502b400bfee0afd89b5d15 new file mode 100644 index 0000000..27a2027 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac3507052c142f5628eada795764e75469e2585518502b400bfee0afd89b5d15 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff2&0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac47ca534e00877b146ef2ed9e7162b114412251df6e662ab63a07b1009b5393 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac47ca534e00877b146ef2ed9e7162b114412251df6e662ab63a07b1009b5393 new file mode 100644 index 0000000..724b773 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/ac47ca534e00877b146ef2ed9e7162b114412251df6e662ab63a07b1009b5393 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf310\xff00007") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b01759614e8bc591068e73dfdf57dca91dd1a9512911d96d203aa6d135193c07 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b01759614e8bc591068e73dfdf57dca91dd1a9512911d96d203aa6d135193c07 new file mode 100644 index 0000000..a2eb5ae --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b01759614e8bc591068e73dfdf57dca91dd1a9512911d96d203aa6d135193c07 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A 0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b2d4d630d9e57dd4ec6030f3c68480c0e27cc08808b74a1f30d2a39126ad9576 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b2d4d630d9e57dd4ec6030f3c68480c0e27cc08808b74a1f30d2a39126ad9576 new file mode 100644 index 0000000..0935648 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/b2d4d630d9e57dd4ec6030f3c68480c0e27cc08808b74a1f30d2a39126ad9576 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf67") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/bb0b3e83bb11594f77b10e16cacabdc3b33e8bb1c3090e8da7bf331caf899fad b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/bb0b3e83bb11594f77b10e16cacabdc3b33e8bb1c3090e8da7bf331caf899fad new file mode 100644 index 0000000..b7d74a8 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/bb0b3e83bb11594f77b10e16cacabdc3b33e8bb1c3090e8da7bf331caf899fad @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000177Z100") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/be193709a33faf69c6616e5cb6e9222c1a8c685c578eabe92ddab77a56fbda91 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/be193709a33faf69c6616e5cb6e9222c1a8c685c578eabe92ddab77a56fbda91 new file mode 100644 index 0000000..933fc99 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/be193709a33faf69c6616e5cb6e9222c1a8c685c578eabe92ddab77a56fbda91 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf30") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c0cf8af892101f975a635da53f855490a6d93cbb08be7a1f70d7b7f0a237763c b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c0cf8af892101f975a635da53f855490a6d93cbb08be7a1f70d7b7f0a237763c new file mode 100644 index 0000000..7444d5e --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c0cf8af892101f975a635da53f855490a6d93cbb08be7a1f70d7b7f0a237763c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000A78X0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c17af5c152fb10506043072ba67c34539a4cd854b3de89394f8049e27672f7d5 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c17af5c152fb10506043072ba67c34539a4cd854b3de89394f8049e27672f7d5 new file mode 100644 index 0000000..b406413 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c17af5c152fb10506043072ba67c34539a4cd854b3de89394f8049e27672f7d5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf60") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c1faaebf2f51b9bd7ef64114318381ec19d9aa59a1fff4952c4b6aeb741ba02d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c1faaebf2f51b9bd7ef64114318381ec19d9aa59a1fff4952c4b6aeb741ba02d new file mode 100644 index 0000000..f42b655 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c1faaebf2f51b9bd7ef64114318381ec19d9aa59a1fff4952c4b6aeb741ba02d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z00d") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c522f0b5427ed0a18a6b692e061280d14af17e8b0075043f1c822533b41ef9ff b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c522f0b5427ed0a18a6b692e061280d14af17e8b0075043f1c822533b41ef9ff new file mode 100644 index 0000000..e85f34f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/c522f0b5427ed0a18a6b692e061280d14af17e8b0075043f1c822533b41ef9ff @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000070") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cad20d5efdb493f9d3c53736dde3d97fcda3593310c32dcd8cb6981e36d54538 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cad20d5efdb493f9d3c53736dde3d97fcda3593310c32dcd8cb6981e36d54538 new file mode 100644 index 0000000..01dfd3f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cad20d5efdb493f9d3c53736dde3d97fcda3593310c32dcd8cb6981e36d54538 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000\xff0A0000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cf3cad2c9f63327a060ace07881bdc20e3f5c473749397a8c84bd168f9ac799d b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cf3cad2c9f63327a060ace07881bdc20e3f5c473749397a8c84bd168f9ac799d new file mode 100644 index 0000000..fdad433 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/cf3cad2c9f63327a060ace07881bdc20e3f5c473749397a8c84bd168f9ac799d @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf31") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/d78a814513f866a302c16d387777290f3d60da89055d4df8529dcf6afad9beca b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/d78a814513f866a302c16d387777290f3d60da89055d4df8529dcf6afad9beca new file mode 100644 index 0000000..cda2805 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/d78a814513f866a302c16d387777290f3d60da89055d4df8529dcf6afad9beca @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf6\xf60000000001") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/db1c54995fe7b8d0e9628dd1822671be4ac721f297e14dcc4a7900d15c7fff7f b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/db1c54995fe7b8d0e9628dd1822671be4ac721f297e14dcc4a7900d15c7fff7f new file mode 100644 index 0000000..fe874a1 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/db1c54995fe7b8d0e9628dd1822671be4ac721f297e14dcc4a7900d15c7fff7f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00007\xb6\xf6018") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e0636a49e255b40346c2f44bacf15e50903f836d7c550504188c55ab37cfde4f b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e0636a49e255b40346c2f44bacf15e50903f836d7c550504188c55ab37cfde4f new file mode 100644 index 0000000..bfeaab6 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e0636a49e255b40346c2f44bacf15e50903f836d7c550504188c55ab37cfde4f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff20") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e20f6e43de3d954ca5b920a4b039b822e97cd317c07fc97337da68f023d563a2 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e20f6e43de3d954ca5b920a4b039b822e97cd317c07fc97337da68f023d563a2 new file mode 100644 index 0000000..84b31fd --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e20f6e43de3d954ca5b920a4b039b822e97cd317c07fc97337da68f023d563a2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017\xf6") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e562907a18f4186251820f36d0278039659036029592195e8a9acf94ffd70546 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e562907a18f4186251820f36d0278039659036029592195e8a9acf94ffd70546 new file mode 100644 index 0000000..fff6fdd --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e562907a18f4186251820f36d0278039659036029592195e8a9acf94ffd70546 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e9918f5c3ff4ccead70a7bfe83479d6e5eba77143048cca05f00e56a244a8066 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e9918f5c3ff4ccead70a7bfe83479d6e5eba77143048cca05f00e56a244a8066 new file mode 100644 index 0000000..5b09b3f --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/e9918f5c3ff4ccead70a7bfe83479d6e5eba77143048cca05f00e56a244a8066 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000%\xf6") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f235dbad7715685b1e83484df230fdfbb9ce3abceb662ee5e714a6e1d94ec0ac b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f235dbad7715685b1e83484df230fdfbb9ce3abceb662ee5e714a6e1d94ec0ac new file mode 100644 index 0000000..aefb778 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f235dbad7715685b1e83484df230fdfbb9ce3abceb662ee5e714a6e1d94ec0ac @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000\xf6\xf60\xf6000110") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3 new file mode 100644 index 0000000..a389d3c --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f351a5a9537462ce1b8d69398f3cfa98589a431137e9dc72ec5a8bb5cc4cd5da b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f351a5a9537462ce1b8d69398f3cfa98589a431137e9dc72ec5a8bb5cc4cd5da new file mode 100644 index 0000000..524e269 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/f351a5a9537462ce1b8d69398f3cfa98589a431137e9dc72ec5a8bb5cc4cd5da @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0z00$002") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/fc7904c804b00a74ab63bacd56f2ebaa77ed1632549d98dd78ee0348f68554b3 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/fc7904c804b00a74ab63bacd56f2ebaa77ed1632549d98dd78ee0348f68554b3 new file mode 100644 index 0000000..8356152 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/fc7904c804b00a74ab63bacd56f2ebaa77ed1632549d98dd78ee0348f68554b3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000A\xff2Z0") diff --git a/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/feba85bf0ea4d5f2e9ba1aca9adc81513ebf3a55d8a8a053ddb5cf87f9f98524 b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/feba85bf0ea4d5f2e9ba1aca9adc81513ebf3a55d8a8a053ddb5cf87f9f98524 new file mode 100644 index 0000000..6feeb59 --- /dev/null +++ b/pkg/codecs/h264/testdata/fuzz/FuzzSPSUnmarshal/feba85bf0ea4d5f2e9ba1aca9adc81513ebf3a55d8a8a053ddb5cf87f9f98524 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000017$") diff --git a/pkg/codecs/h265/dts_extractor.go b/pkg/codecs/h265/dts_extractor.go new file mode 100644 index 0000000..1772b16 --- /dev/null +++ b/pkg/codecs/h265/dts_extractor.go @@ -0,0 +1,242 @@ +package h265 + +import ( + "fmt" + "time" + + "github.com/bluenviron/mediabase/pkg/bits" + "github.com/bluenviron/mediabase/pkg/codecs/h264" +) + +func getPictureOrderCount(buf []byte, sps *SPS, pps *PPS) (uint32, uint32, error) { + if len(buf) < 12 { + return 0, 0, fmt.Errorf("not enough bits") + } + + buf = h264.EmulationPreventionRemove(buf[:12]) + + typ := NALUType((buf[0] >> 1) & 0b111111) + + buf = buf[2:] + pos := 0 + + firstSliceSegmentInPicFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return 0, 0, err + } + + if !firstSliceSegmentInPicFlag { + return 0, 0, fmt.Errorf("first_slice_segment_in_pic_flag = 0 is not supported") + } + + if typ >= NALUType_BLA_W_LP && typ <= NALUType_RSV_IRAP_VCL23 { + _, err := bits.ReadFlag(buf, &pos) // no_output_of_prior_pics_flag + if err != nil { + return 0, 0, err + } + } + + _, err = bits.ReadGolombUnsigned(buf, &pos) // slice_pic_parameter_set_id + if err != nil { + return 0, 0, err + } + + if pps.NumExtraSliceHeaderBits > 0 { + err := bits.HasSpace(buf, pos, int(pps.NumExtraSliceHeaderBits)) + if err != nil { + return 0, 0, err + } + pos += int(pps.NumExtraSliceHeaderBits) + } + + sliceType, err := bits.ReadGolombUnsigned(buf, &pos) // slice_type + if err != nil { + return 0, 0, err + } + + if pps.OutputFlagPresentFlag { + _, err := bits.ReadFlag(buf, &pos) // pic_output_flag + if err != nil { + return 0, 0, err + } + } + + if sps.SeparateColourPlaneFlag { + _, err := bits.ReadBits(buf, &pos, 2) // colour_plane_id + if err != nil { + return 0, 0, err + } + } + + picOrderCntLsb, err := bits.ReadBits(buf, &pos, int(sps.Log2MaxPicOrderCntLsbMinus4+4)) + if err != nil { + return 0, 0, err + } + + shortTermRefPicSetSpsFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return 0, 0, err + } + + if shortTermRefPicSetSpsFlag { + return 0, 0, fmt.Errorf("short_term_ref_pic_set_sps_flag = true is not supported") + } + + var rps SPS_ShortTermRefPicSet + err = rps.unmarshal(buf, &pos, uint32(len(sps.ShortTermRefPicSets)), uint32(len(sps.ShortTermRefPicSets)), nil) + if err != nil { + return 0, 0, err + } + + var v uint32 + + if sliceType == 0 { // B-frame + if typ == NALUType_TRAIL_N || typ == NALUType_RASL_N { + v = sps.MaxNumReorderPics[0] - uint32(len(rps.DeltaPocS1Minus1)) + } else if typ == NALUType_TRAIL_R || typ == NALUType_RASL_R { + if len(rps.DeltaPocS0Minus1) == 0 { + return 0, 0, fmt.Errorf("invalid delta_poc_s0_minus1") + } + v = rps.DeltaPocS0Minus1[0] + sps.MaxNumReorderPics[0] - 1 + } + } else { // I or P-frame + if len(rps.DeltaPocS0Minus1) == 0 { + return 0, 0, fmt.Errorf("invalid delta_poc_s0_minus1") + } + v = rps.DeltaPocS0Minus1[0] + sps.MaxNumReorderPics[0] + } + + dtsPOC := uint32(picOrderCntLsb) - v + dtsPOC &= ((1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 4)) - 1) + + return uint32(picOrderCntLsb), dtsPOC, nil +} + +func findPictureOrderCount(au [][]byte, sps *SPS, pps *PPS) (uint32, uint32, error) { + for _, nalu := range au { + typ := NALUType((nalu[0] >> 1) & 0b111111) + switch typ { + case NALUType_TRAIL_N, NALUType_TRAIL_R, NALUType_CRA_NUT, NALUType_RASL_N, NALUType_RASL_R: + poc, dtsPOC, err := getPictureOrderCount(nalu, sps, pps) + if err != nil { + return 0, 0, err + } + return poc, dtsPOC, nil + } + } + return 0, 0, fmt.Errorf("POC not found") +} + +func getPictureOrderCountDiff(poc1 uint32, poc2 uint32, sps *SPS) int32 { + diff := int32(poc1) - int32(poc2) + switch { + case diff < -((1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 3)) - 1): + diff += (1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 4)) + + case diff > ((1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 3)) - 1): + diff -= (1 << (sps.Log2MaxPicOrderCntLsbMinus4 + 4)) + } + return diff +} + +// DTSExtractor allows to extract DTS from PTS. +type DTSExtractor struct { + spsp *SPS + ppsp *PPS + prevDTSFilled bool + prevDTS time.Duration +} + +// NewDTSExtractor allocates a DTSExtractor. +func NewDTSExtractor() *DTSExtractor { + return &DTSExtractor{} +} + +func (d *DTSExtractor) extractInner(au [][]byte, pts time.Duration) (time.Duration, error) { + idrPresent := false + + for _, nalu := range au { + typ := NALUType((nalu[0] >> 1) & 0b111111) + + switch typ { + case NALUType_SPS_NUT: + var spsp SPS + err := spsp.Unmarshal(nalu) + if err != nil { + return 0, fmt.Errorf("invalid SPS: %v", err) + } + d.spsp = &spsp + + case NALUType_PPS_NUT: + var ppsp PPS + err := ppsp.Unmarshal(nalu) + if err != nil { + return 0, fmt.Errorf("invalid PPS: %v", err) + } + d.ppsp = &ppsp + + case NALUType_IDR_W_RADL, NALUType_IDR_N_LP: + idrPresent = true + } + } + + if d.spsp == nil { + return 0, fmt.Errorf("SPS not received yet") + } + + if d.ppsp == nil { + return 0, fmt.Errorf("PPS not received yet") + } + + if len(d.spsp.MaxNumReorderPics) != 1 || d.spsp.MaxNumReorderPics[0] == 0 { + return pts, nil + } + + if d.spsp.VUI == nil || d.spsp.VUI.TimingInfo == nil { + return pts, nil + } + + var poc uint32 + var dtsPOC uint32 + + if idrPresent { + poc = 0 + dtsPOC = poc - 2 + dtsPOC &= ((1 << (d.spsp.Log2MaxPicOrderCntLsbMinus4 + 4)) - 1) + } else { + var err error + poc, dtsPOC, err = findPictureOrderCount(au, d.spsp, d.ppsp) + if err != nil { + return 0, err + } + } + + pocDiff := getPictureOrderCountDiff(poc, dtsPOC, d.spsp) + timeDiff := time.Duration(pocDiff) * time.Second * + time.Duration(d.spsp.VUI.TimingInfo.NumUnitsInTick) / time.Duration(d.spsp.VUI.TimingInfo.TimeScale) + dts := pts - timeDiff + + return dts, nil +} + +// Extract extracts the DTS of a access unit. +func (d *DTSExtractor) Extract(au [][]byte, pts time.Duration) (time.Duration, error) { + dts, err := d.extractInner(au, pts) + if err != nil { + return 0, err + } + + if dts > pts { + return 0, fmt.Errorf("DTS is greater than PTS") + } + + if d.prevDTSFilled && dts <= d.prevDTS { + return 0, fmt.Errorf("DTS is not monotonically increasing, was %v, now is %v", + d.prevDTS, dts) + } + + d.prevDTSFilled = true + d.prevDTS = dts + + return dts, err +} diff --git a/pkg/codecs/h265/dts_extractor_test.go b/pkg/codecs/h265/dts_extractor_test.go new file mode 100644 index 0000000..bd3e0d2 --- /dev/null +++ b/pkg/codecs/h265/dts_extractor_test.go @@ -0,0 +1,84 @@ +//go:build go1.18 +// +build go1.18 + +package h265 + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDTSExtractor(t *testing.T) { + type sequenceSample struct { + nalus [][]byte + pts time.Duration + dts time.Duration + } + + for _, ca := range []struct { + name string + sequence []sequenceSample + }{ + { + "no timing info", + []sequenceSample{ + { + [][]byte{ + { // SPS + 0x42, 0x01, 0x01, 0x02, 0x20, 0x00, 0x00, 0x03, + 0x00, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x7b, 0xa0, 0x07, 0x82, 0x00, 0x88, 0x7d, + 0xb6, 0x71, 0x8b, 0x92, 0x44, 0x80, 0x53, 0x88, + 0x88, 0x92, 0xcf, 0x24, 0xa6, 0x92, 0x72, 0xc9, + 0x12, 0x49, 0x22, 0xdc, 0x91, 0xaa, 0x48, 0xfc, + 0xa2, 0x23, 0xff, 0x00, 0x01, 0x00, 0x01, 0x6a, + 0x02, 0x02, 0x02, 0x01, + }, + { // PPS + 0x44, 0x01, 0xc0, 0x25, 0x2f, 0x05, 0x32, 0x40, + }, + { + byte(NALUType_CRA_NUT) << 1, + }, + }, + 1 * time.Second, + 1 * time.Second, + }, + }, + }, + } { + t.Run(ca.name, func(t *testing.T) { + ex := NewDTSExtractor() + for _, sample := range ca.sequence { + dts, err := ex.Extract(sample.nalus, sample.pts) + require.NoError(t, err) + require.Equal(t, sample.dts, dts) + } + }) + } +} + +func FuzzDTSExtractor(f *testing.F) { + sps := []byte{ + 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, + 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x10, 0xe5, + 0x96, 0x66, 0x69, 0x24, 0xca, 0xe0, 0x10, 0x00, + 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, + 0xe0, 0x80, + } + + pps := []byte{ + 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, + } + + ex := NewDTSExtractor() + f.Fuzz(func(t *testing.T, b []byte, p uint64) { + if len(b) < 1 { + return + } + ex.Extract([][]byte{sps, pps, b}, time.Duration(p)) + }) +} diff --git a/pkg/codecs/h265/h265.go b/pkg/codecs/h265/h265.go new file mode 100644 index 0000000..6e06e5c --- /dev/null +++ b/pkg/codecs/h265/h265.go @@ -0,0 +1,11 @@ +// Package h265 contains utilities to work with the H265 codec. +package h265 + +const ( + // MaxNALUSize is the maximum size of a NALU. + // with a 250 Mbps H265 video, the maximum NALU size is 2.2MB + MaxNALUSize = 3 * 1024 * 1024 + + // MaxNALUsPerGroup is the maximum number of NALUs per group. + MaxNALUsPerGroup = 20 +) diff --git a/pkg/codecs/h265/nalu_type.go b/pkg/codecs/h265/nalu_type.go new file mode 100644 index 0000000..87b705a --- /dev/null +++ b/pkg/codecs/h265/nalu_type.go @@ -0,0 +1,99 @@ +package h265 + +import ( + "fmt" +) + +// NALUType is the type of a NALU. +type NALUType uint8 + +// NALU types. +const ( + NALUType_TRAIL_N NALUType = 0 //nolint:revive + NALUType_TRAIL_R NALUType = 1 //nolint:revive + NALUType_TSA_N NALUType = 2 //nolint:revive + NALUType_TSA_R NALUType = 3 //nolint:revive + NALUType_STSA_N NALUType = 4 //nolint:revive + NALUType_STSA_R NALUType = 5 //nolint:revive + NALUType_RADL_N NALUType = 6 //nolint:revive + NALUType_RADL_R NALUType = 7 //nolint:revive + NALUType_RASL_N NALUType = 8 //nolint:revive + NALUType_RASL_R NALUType = 9 //nolint:revive + NALUType_RSV_VCL_N10 NALUType = 10 //nolint:revive + NALUType_RSV_VCL_N12 NALUType = 12 //nolint:revive + NALUType_RSV_VCL_N14 NALUType = 14 //nolint:revive + NALUType_RSV_VCL_R11 NALUType = 11 //nolint:revive + NALUType_RSV_VCL_R13 NALUType = 13 //nolint:revive + NALUType_RSV_VCL_R15 NALUType = 15 //nolint:revive + NALUType_BLA_W_LP NALUType = 16 //nolint:revive + NALUType_BLA_W_RADL NALUType = 17 //nolint:revive + NALUType_BLA_N_LP NALUType = 18 //nolint:revive + NALUType_IDR_W_RADL NALUType = 19 //nolint:revive + NALUType_IDR_N_LP NALUType = 20 //nolint:revive + NALUType_CRA_NUT NALUType = 21 //nolint:revive + NALUType_RSV_IRAP_VCL22 NALUType = 22 //nolint:revive + NALUType_RSV_IRAP_VCL23 NALUType = 23 //nolint:revive + NALUType_VPS_NUT NALUType = 32 //nolint:revive + NALUType_SPS_NUT NALUType = 33 //nolint:revive + NALUType_PPS_NUT NALUType = 34 //nolint:revive + NALUType_AUD_NUT NALUType = 35 //nolint:revive + NALUType_EOS_NUT NALUType = 36 //nolint:revive + NALUType_EOB_NUT NALUType = 37 //nolint:revive + NALUType_FD_NUT NALUType = 38 //nolint:revive + NALUType_PREFIX_SEI_NUT NALUType = 39 //nolint:revive + NALUType_SUFFIX_SEI_NUT NALUType = 40 //nolint:revive + + // additional NALU types for RTP/H265 + NALUType_AggregationUnit NALUType = 48 //nolint:revive + NALUType_FragmentationUnit NALUType = 49 //nolint:revive + NALUType_PACI NALUType = 50 //nolint:revive +) + +var naluTypeLabels = map[NALUType]string{ + NALUType_TRAIL_N: "TRAIL_N", + NALUType_TRAIL_R: "TRAIL_R", + NALUType_TSA_N: "TSA_N", + NALUType_TSA_R: "TSA_R", + NALUType_STSA_N: "STSA_N", + NALUType_STSA_R: "STSA_R:", + NALUType_RADL_N: "RADL_N", + NALUType_RADL_R: "RADL_R", + NALUType_RASL_N: "RASL_N", + NALUType_RASL_R: "RASL_R", + NALUType_RSV_VCL_N10: "RSV_VCL_N10", + NALUType_RSV_VCL_N12: "RSV_VCL_N12", + NALUType_RSV_VCL_N14: "RSV_VCL_N14", + NALUType_RSV_VCL_R11: "RSV_VCL_R11", + NALUType_RSV_VCL_R13: "RSV_VCL_R13", + NALUType_RSV_VCL_R15: "RSV_VCL_R15", + NALUType_BLA_W_LP: "BLA_W_LP", + NALUType_BLA_W_RADL: "BLA_W_RADL", + NALUType_BLA_N_LP: "BLA_N_LP", + NALUType_IDR_W_RADL: "IDR_W_RADL", + NALUType_IDR_N_LP: "IDR_N_LP", + NALUType_CRA_NUT: "CRA_NUT", + NALUType_RSV_IRAP_VCL22: "RSV_IRAP_VCL22", + NALUType_RSV_IRAP_VCL23: "RSV_IRAP_VCL23", + NALUType_VPS_NUT: "VPS_NUT", + NALUType_SPS_NUT: "SPS_NUT", + NALUType_PPS_NUT: "PPS_NUT", + NALUType_AUD_NUT: "AUD_NUT", + NALUType_EOS_NUT: "EOS_NUT", + NALUType_EOB_NUT: "EOB_NUT", + NALUType_FD_NUT: "FD_NUT", + NALUType_PREFIX_SEI_NUT: "PrefixSEINUT", + NALUType_SUFFIX_SEI_NUT: "SuffixSEINUT", + + // additional NALU types for RTP/H265 + NALUType_AggregationUnit: "AggregationUnit", + NALUType_FragmentationUnit: "FragmentationUnit", + NALUType_PACI: "PACI", +} + +// String implements fmt.Stringer. +func (nt NALUType) String() string { + if l, ok := naluTypeLabels[nt]; ok { + return l + } + return fmt.Sprintf("unknown (%d)", nt) +} diff --git a/pkg/codecs/h265/nalu_type_test.go b/pkg/codecs/h265/nalu_type_test.go new file mode 100644 index 0000000..3255ff7 --- /dev/null +++ b/pkg/codecs/h265/nalu_type_test.go @@ -0,0 +1,13 @@ +package h265 + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNALUType(t *testing.T) { + require.NotEqual(t, true, strings.HasPrefix(NALUType(10).String(), "unknown")) + require.Equal(t, true, strings.HasPrefix(NALUType(60).String(), "unknown")) +} diff --git a/pkg/codecs/h265/pps.go b/pkg/codecs/h265/pps.go new file mode 100644 index 0000000..33bd09d --- /dev/null +++ b/pkg/codecs/h265/pps.go @@ -0,0 +1,51 @@ +package h265 + +import ( + "fmt" + + "github.com/bluenviron/mediabase/pkg/bits" + "github.com/bluenviron/mediabase/pkg/codecs/h264" +) + +// PPS is a H265 picture parameter set. +type PPS struct { + ID uint32 + SPSID uint32 + DependentSliceSegmentsEnabledFlag bool + OutputFlagPresentFlag bool + NumExtraSliceHeaderBits uint8 +} + +// Unmarshal decodes a PPS. +func (p *PPS) Unmarshal(buf []byte) error { + if len(buf) < 2 { + return fmt.Errorf("not enough bits") + } + + buf = h264.EmulationPreventionRemove(buf) + + buf = buf[2:] + pos := 0 + + var err error + p.ID, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + p.SPSID, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + err = bits.HasSpace(buf, pos, 5) + if err != nil { + return err + } + + p.DependentSliceSegmentsEnabledFlag = bits.ReadFlagUnsafe(buf, &pos) + p.OutputFlagPresentFlag = bits.ReadFlagUnsafe(buf, &pos) + p.NumExtraSliceHeaderBits = uint8(bits.ReadBitsUnsafe(buf, &pos, 3)) + + return nil +} diff --git a/pkg/codecs/h265/pps_test.go b/pkg/codecs/h265/pps_test.go new file mode 100644 index 0000000..d6de60a --- /dev/null +++ b/pkg/codecs/h265/pps_test.go @@ -0,0 +1,40 @@ +//go:build go1.18 +// +build go1.18 + +package h265 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPPSUnmarshal(t *testing.T) { + for _, ca := range []struct { + name string + byts []byte + pps PPS + }{ + { + "default", + []byte{ + 0x44, 0x01, 0xc1, 0x72, 0xb4, 0x62, 0x40, + }, + PPS{}, + }, + } { + t.Run(ca.name, func(t *testing.T) { + var pps PPS + err := pps.Unmarshal(ca.byts) + require.NoError(t, err) + require.Equal(t, ca.pps, pps) + }) + } +} + +func FuzzPPSUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var pps PPS + pps.Unmarshal(b) + }) +} diff --git a/pkg/codecs/h265/sps.go b/pkg/codecs/h265/sps.go new file mode 100644 index 0000000..0c185dc --- /dev/null +++ b/pkg/codecs/h265/sps.go @@ -0,0 +1,861 @@ +package h265 + +import ( + "fmt" + + "github.com/bluenviron/mediabase/pkg/bits" + "github.com/bluenviron/mediabase/pkg/codecs/h264" +) + +const ( + maxNegativePics = 255 + maxPositivePics = 255 + maxShortTermRefPics = 64 +) + +var subWidthC = []uint32{ + 1, + 2, + 2, + 1, +} + +var subHeightC = []uint32{ + 1, + 2, + 1, + 1, +} + +// SPS_DefaultDisplayWindow is a default display window. +type SPS_DefaultDisplayWindow struct { //nolint:revive + LeftOffset uint32 + RightOffset uint32 + TopOffset uint32 + BottomOffset uint32 +} + +func (w *SPS_DefaultDisplayWindow) unmarshal(buf []byte, pos *int) error { + var err error + w.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + w.RightOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + w.TopOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + w.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + return nil +} + +// SPS_TimingInfo is a timing info. +type SPS_TimingInfo struct { //nolint:revive + NumUnitsInTick uint32 + TimeScale uint32 + POCProportionalToTimingFlag bool + + // POCProportionalToTimingFlag == true + NumTicksPOCDiffOneMinus1 uint32 +} + +func (t *SPS_TimingInfo) unmarshal(buf []byte, pos *int) error { + err := bits.HasSpace(buf, *pos, 32+32+1) + if err != nil { + return err + } + + t.NumUnitsInTick = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) + t.TimeScale = uint32(bits.ReadBitsUnsafe(buf, pos, 32)) + t.POCProportionalToTimingFlag = bits.ReadFlagUnsafe(buf, pos) + + if t.POCProportionalToTimingFlag { + t.NumTicksPOCDiffOneMinus1, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + } + + return nil +} + +// SPS_VUI is a video usability information. +type SPS_VUI struct { //nolint:revive + AspectRatioInfoPresentFlag bool + + // AspectRatioInfoPresentFlag == true + AspectRatioIdc uint8 + SarWidth uint16 + SarHeight uint16 + + OverscanInfoPresentFlag bool + + // OverscanInfoPresentFlag == true + OverscanAppropriateFlag bool + VideoSignalTypePresentFlag bool + + // VideoSignalTypePresentFlag == true + VideoFormat uint8 + VideoFullRangeFlag bool + ColourDescriptionPresentFlag bool + + // ColourDescriptionPresentFlag == true + ColourPrimaries uint8 + TransferCharacteristics uint8 + MatrixCoefficients uint8 + + ChromaLocInfoPresentFlag bool + + // ChromaLocInfoPresentFlag == true + ChromaSampleLocTypeTopField uint32 + ChromaSampleLocTypeBottomField uint32 + + NeutralChromaIndicationFlag bool + FieldSeqFlag bool + FrameFieldInfoPresentFlag bool + DefaultDisplayWindow *SPS_DefaultDisplayWindow + TimingInfo *SPS_TimingInfo +} + +func (v *SPS_VUI) unmarshal(buf []byte, pos *int) error { + var err error + v.AspectRatioInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.AspectRatioInfoPresentFlag { + tmp, err := bits.ReadBits(buf, pos, 8) + if err != nil { + return err + } + v.AspectRatioIdc = uint8(tmp) + + if v.AspectRatioIdc == 255 { // EXTENDED_SAR + err := bits.HasSpace(buf, *pos, 32) + if err != nil { + return err + } + + v.SarWidth = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) + v.SarHeight = uint16(bits.ReadBitsUnsafe(buf, pos, 16)) + } + } + + v.OverscanInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.OverscanInfoPresentFlag { + v.OverscanAppropriateFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + + v.VideoSignalTypePresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.VideoSignalTypePresentFlag { + err := bits.HasSpace(buf, *pos, 5) + if err != nil { + return err + } + + v.VideoFormat = uint8(bits.ReadBitsUnsafe(buf, pos, 3)) + v.VideoFullRangeFlag = bits.ReadFlagUnsafe(buf, pos) + v.ColourDescriptionPresentFlag = bits.ReadFlagUnsafe(buf, pos) + + if v.ColourDescriptionPresentFlag { + err := bits.HasSpace(buf, *pos, 24) + if err != nil { + return err + } + + v.ColourPrimaries = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + v.TransferCharacteristics = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + v.MatrixCoefficients = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + } + } + + v.ChromaLocInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if v.ChromaLocInfoPresentFlag { + v.ChromaSampleLocTypeTopField, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + v.ChromaSampleLocTypeBottomField, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + } + + v.NeutralChromaIndicationFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + v.FieldSeqFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + v.FrameFieldInfoPresentFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + defaultDisplayWindowFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if defaultDisplayWindowFlag { + v.DefaultDisplayWindow = &SPS_DefaultDisplayWindow{} + err := v.DefaultDisplayWindow.unmarshal(buf, pos) + if err != nil { + return err + } + } else { + v.DefaultDisplayWindow = nil + } + + timingInfoPresentFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if timingInfoPresentFlag { + v.TimingInfo = &SPS_TimingInfo{} + err := v.TimingInfo.unmarshal(buf, pos) + if err != nil { + return err + } + } else { + v.TimingInfo = nil + } + + return nil +} + +// SPS_ProfileTierLevel is a profile level tier of a SPS. +type SPS_ProfileTierLevel struct { //nolint:revive + GeneralProfileSpace uint8 + GeneralTierFlag uint8 + GeneralProfileIdc uint8 + GeneralProfileCompatibilityFlag [32]bool + GeneralProgressiveSourceFlag bool + GeneralInterlacedSourceFlag bool + GeneralNonPackedConstraintFlag bool + GeneralFrameOnlyConstraintFlag bool + GeneralMax12bitConstraintFlag bool + GeneralMax10bitConstraintFlag bool + GeneralMax8bitConstraintFlag bool + GeneralMax422ChromeConstraintFlag bool + GeneralMax420ChromaConstraintFlag bool + GeneralMaxMonochromeConstraintFlag bool + GeneralIntraConstraintFlag bool + GeneralOnePictureOnlyConstraintFlag bool + GeneralLowerBitRateConstraintFlag bool + GeneralMax14BitConstraintFlag bool + GeneralLevelIdc uint8 + SubLayerProfilePresentFlag []bool + SubLayerLevelPresentFlag []bool +} + +func (p *SPS_ProfileTierLevel) unmarshal(buf []byte, pos *int, maxSubLayersMinus1 uint8) error { + err := bits.HasSpace(buf, *pos, 8+32+12+34+8) + if err != nil { + return err + } + + p.GeneralProfileSpace = uint8(bits.ReadBitsUnsafe(buf, pos, 2)) + p.GeneralTierFlag = uint8(bits.ReadBitsUnsafe(buf, pos, 1)) + p.GeneralProfileIdc = uint8(bits.ReadBitsUnsafe(buf, pos, 5)) + + for j := 0; j < 32; j++ { + p.GeneralProfileCompatibilityFlag[j] = bits.ReadFlagUnsafe(buf, pos) + } + + p.GeneralProgressiveSourceFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralInterlacedSourceFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralNonPackedConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralFrameOnlyConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMax12bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMax10bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMax8bitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMax422ChromeConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMax420ChromaConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralMaxMonochromeConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralIntraConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralOnePictureOnlyConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + p.GeneralLowerBitRateConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + + if p.GeneralProfileIdc == 5 || + p.GeneralProfileIdc == 9 || + p.GeneralProfileIdc == 10 || + p.GeneralProfileIdc == 11 || + p.GeneralProfileCompatibilityFlag[5] || + p.GeneralProfileCompatibilityFlag[9] || + p.GeneralProfileCompatibilityFlag[10] || + p.GeneralProfileCompatibilityFlag[11] { + p.GeneralMax14BitConstraintFlag = bits.ReadFlagUnsafe(buf, pos) + *pos += 34 + } else { + *pos += 35 + } + + p.GeneralLevelIdc = uint8(bits.ReadBitsUnsafe(buf, pos, 8)) + + if maxSubLayersMinus1 > 0 { + p.SubLayerProfilePresentFlag = make([]bool, maxSubLayersMinus1) + p.SubLayerLevelPresentFlag = make([]bool, maxSubLayersMinus1) + + err := bits.HasSpace(buf, *pos, int(2*maxSubLayersMinus1)) + if err != nil { + return err + } + + for j := uint8(0); j < maxSubLayersMinus1; j++ { + p.SubLayerProfilePresentFlag[j] = bits.ReadFlagUnsafe(buf, pos) + p.SubLayerLevelPresentFlag[j] = bits.ReadFlagUnsafe(buf, pos) + } + } + + if maxSubLayersMinus1 > 0 { + err := bits.HasSpace(buf, *pos, int(8-maxSubLayersMinus1)*2) + if err != nil { + return err + } + + *pos += int(8-maxSubLayersMinus1) * 2 + } + + for i := uint8(0); i < maxSubLayersMinus1; i++ { + if p.SubLayerProfilePresentFlag[i] { + return fmt.Errorf("SubLayerProfilePresentFlag not supported yet") + } + + if p.SubLayerLevelPresentFlag[i] { + return fmt.Errorf("SubLayerLevelPresentFlag not supported yet") + } + } + + return nil +} + +// SPS_ConformanceWindow is a conformance window of a SPS. +type SPS_ConformanceWindow struct { //nolint:revive + LeftOffset uint32 + RightOffset uint32 + TopOffset uint32 + BottomOffset uint32 +} + +func (c *SPS_ConformanceWindow) unmarshal(buf []byte, pos *int) error { + var err error + c.LeftOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.RightOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.TopOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + c.BottomOffset, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + return nil +} + +// SPS_ShortTermRefPicSet is a short-term reference picture set. +type SPS_ShortTermRefPicSet struct { //nolint:revive + InterRefPicSetPredictionFlag bool + DeltaIdxMinus1 uint32 + DeltaRpsSign bool + AbsDeltaRpsMinus1 uint32 + NumNegativePics uint32 + NumPositivePics uint32 + DeltaPocS0Minus1 []uint32 + UsedByCurrPicS0Flag []bool + DeltaPocS1Minus1 []uint32 + UsedByCurrPicS1Flag []bool +} + +func (r *SPS_ShortTermRefPicSet) unmarshal(buf []byte, pos *int, stRpsIdx uint32, + numShortTermRefPicSets uint32, shortTermRefPicSets []*SPS_ShortTermRefPicSet, +) error { + var err error + + if stRpsIdx != 0 { + r.InterRefPicSetPredictionFlag, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + + if r.InterRefPicSetPredictionFlag { + if stRpsIdx == numShortTermRefPicSets { + r.DeltaIdxMinus1, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + } + + r.DeltaRpsSign, err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + r.AbsDeltaRpsMinus1, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + refRpsIdx := stRpsIdx - (r.DeltaIdxMinus1 + 1) + numDeltaPocs := shortTermRefPicSets[refRpsIdx].NumNegativePics + shortTermRefPicSets[refRpsIdx].NumPositivePics + + for j := uint32(0); j <= numDeltaPocs; j++ { + usedByCurrPicFlag, err := bits.ReadFlag(buf, pos) + if err != nil { + return err + } + + if usedByCurrPicFlag { + _, err := bits.ReadGolombUnsigned(buf, pos) // use_delta_flag + if err != nil { + return err + } + } + } + } else { + r.NumNegativePics, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.NumPositivePics, err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + if r.NumNegativePics > 0 { + if r.NumNegativePics > maxNegativePics { + return fmt.Errorf("num_negative_pics exceeds %d", maxNegativePics) + } + + r.DeltaPocS0Minus1 = make([]uint32, r.NumNegativePics) + r.UsedByCurrPicS0Flag = make([]bool, r.NumNegativePics) + + for i := uint32(0); i < r.NumNegativePics; i++ { + r.DeltaPocS0Minus1[i], err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.UsedByCurrPicS0Flag[i], err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + } + + if r.NumPositivePics > 0 { + if r.NumPositivePics > maxPositivePics { + return fmt.Errorf("num_positive_pics exceeds %d", maxPositivePics) + } + + r.DeltaPocS1Minus1 = make([]uint32, r.NumPositivePics) + r.UsedByCurrPicS1Flag = make([]bool, r.NumPositivePics) + + for i := uint32(0); i < r.NumPositivePics; i++ { + r.DeltaPocS1Minus1[i], err = bits.ReadGolombUnsigned(buf, pos) + if err != nil { + return err + } + + r.UsedByCurrPicS1Flag[i], err = bits.ReadFlag(buf, pos) + if err != nil { + return err + } + } + } + } + + return nil +} + +// SPS is a H265 sequence parameter set. +type SPS struct { + VPSID uint8 + MaxSubLayersMinus1 uint8 + TemporalIDNestingFlag bool + ProfileTierLevel SPS_ProfileTierLevel + ID uint8 + ChromaFormatIdc uint32 + SeparateColourPlaneFlag bool + PicWidthInLumaSamples uint32 + PicHeightInLumaSamples uint32 + ConformanceWindow *SPS_ConformanceWindow + BitDepthLumaMinus8 uint32 + BitDepthChromaMinus8 uint32 + Log2MaxPicOrderCntLsbMinus4 uint32 + SubLayerOrderingInfoPresentFlag bool + MaxDecPicBufferingMinus1 []uint32 + MaxNumReorderPics []uint32 + MaxLatencyIncreasePlus1 []uint32 + Log2MinLumaCodingBlockSizeMinus3 uint32 + Log2DiffMaxMinLumaCodingBlockSize uint32 + Log2MinLumaTransformBlockSizeMinus2 uint32 + Log2DiffMaxMinLumaTransformBlockSize uint32 + MaxTransformHierarchyDepthInter uint32 + MaxTransformHierarchyDepthIntra uint32 + ScalingListEnabledFlag bool + ScalingListDataPresentFlag bool + AmpEnabledFlag bool + SampleAdaptiveOffsetEnabledFlag bool + PcmEnabledFlag bool + + // PcmEnabledFlag == true + PcmSampleBitDepthLumaMinus1 uint8 + PcmSampleBitDepthChromaMinus1 uint8 + Log2MinPcmLumaCodingBlockSizeMinus3 uint32 + Log2DiffMaxMinPcmLumaCodingBlockSize uint32 + PcmLoopFilterDisabledFlag bool + + ShortTermRefPicSets []*SPS_ShortTermRefPicSet + LongTermRefPicsPresentFlag bool + TemporalMvpEnabledFlag bool + StrongIntraSmoothingEnabledFlag bool + VUI *SPS_VUI +} + +// Unmarshal decodes a SPS from bytes. +func (s *SPS) Unmarshal(buf []byte) error { + buf = h264.EmulationPreventionRemove(buf) + + if len(buf) < 2 { + return fmt.Errorf("not enough bits") + } + + buf = buf[2:] + pos := 0 + + err := bits.HasSpace(buf, pos, 8) + if err != nil { + return err + } + + s.VPSID = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) + s.MaxSubLayersMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 3)) + s.TemporalIDNestingFlag = bits.ReadFlagUnsafe(buf, &pos) + + err = s.ProfileTierLevel.unmarshal(buf, &pos, s.MaxSubLayersMinus1) + if err != nil { + return err + } + + tmp2, err := bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + s.ID = uint8(tmp2) + + s.ChromaFormatIdc, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + if s.ChromaFormatIdc == 3 { + s.SeparateColourPlaneFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + } + + s.PicWidthInLumaSamples, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.PicHeightInLumaSamples, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + conformanceWindowFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if conformanceWindowFlag { + s.ConformanceWindow = &SPS_ConformanceWindow{} + err := s.ConformanceWindow.unmarshal(buf, &pos) + if err != nil { + return err + } + } else { + s.ConformanceWindow = nil + } + + s.BitDepthLumaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.BitDepthChromaMinus8, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.Log2MaxPicOrderCntLsbMinus4, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.SubLayerOrderingInfoPresentFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + var start uint8 + if s.SubLayerOrderingInfoPresentFlag { + start = 0 + } else { + start = s.MaxSubLayersMinus1 + } + + s.MaxDecPicBufferingMinus1 = make([]uint32, s.MaxSubLayersMinus1+1) + s.MaxNumReorderPics = make([]uint32, s.MaxSubLayersMinus1+1) + s.MaxLatencyIncreasePlus1 = make([]uint32, s.MaxSubLayersMinus1+1) + + for i := start; i <= s.MaxSubLayersMinus1; i++ { + s.MaxDecPicBufferingMinus1[i], err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.MaxNumReorderPics[i], err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.MaxLatencyIncreasePlus1[i], err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + } + + s.Log2MinLumaCodingBlockSizeMinus3, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.Log2DiffMaxMinLumaCodingBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.Log2MinLumaTransformBlockSizeMinus2, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.Log2DiffMaxMinLumaTransformBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.MaxTransformHierarchyDepthInter, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.MaxTransformHierarchyDepthIntra, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.ScalingListEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if s.ScalingListEnabledFlag { + s.ScalingListDataPresentFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if s.ScalingListDataPresentFlag { + return fmt.Errorf("ScalingListDataPresentFlag not supported yet") + } + } + + s.AmpEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + s.SampleAdaptiveOffsetEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + s.PcmEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if s.PcmEnabledFlag { + err := bits.HasSpace(buf, pos, 8) + if err != nil { + return err + } + + s.PcmSampleBitDepthLumaMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) + s.PcmSampleBitDepthChromaMinus1 = uint8(bits.ReadBitsUnsafe(buf, &pos, 4)) + + s.Log2MinPcmLumaCodingBlockSizeMinus3, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.Log2DiffMaxMinPcmLumaCodingBlockSize, err = bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + s.PcmLoopFilterDisabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + } + + numShortTermRefPicSets, err := bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + if numShortTermRefPicSets > 0 { + if numShortTermRefPicSets > maxShortTermRefPics { + return fmt.Errorf("num_short_term_ref_pic_sets exceeds %d", maxShortTermRefPics) + } + + s.ShortTermRefPicSets = make([]*SPS_ShortTermRefPicSet, numShortTermRefPicSets) + + for i := uint32(0); i < numShortTermRefPicSets; i++ { + s.ShortTermRefPicSets[i] = &SPS_ShortTermRefPicSet{} + err := s.ShortTermRefPicSets[i].unmarshal(buf, &pos, i, numShortTermRefPicSets, s.ShortTermRefPicSets) + if err != nil { + return err + } + } + } else { + s.ShortTermRefPicSets = nil + } + + s.LongTermRefPicsPresentFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if s.LongTermRefPicsPresentFlag { + numLongTermRefPicsSPS, err := bits.ReadGolombUnsigned(buf, &pos) + if err != nil { + return err + } + + if numLongTermRefPicsSPS > 0 { + return fmt.Errorf("long term ref pics inside SPS are not supported yet") + } + } + + s.TemporalMvpEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + s.StrongIntraSmoothingEnabledFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + vuiParametersPresentFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if vuiParametersPresentFlag { + s.VUI = &SPS_VUI{} + err := s.VUI.unmarshal(buf, &pos) + if err != nil { + return err + } + } else { + s.VUI = nil + } + + return nil +} + +// Width returns the video width. +func (s SPS) Width() int { + width := s.PicWidthInLumaSamples + + if s.ConformanceWindow != nil { + cropUnitX := subWidthC[s.ChromaFormatIdc] + width -= (s.ConformanceWindow.LeftOffset + s.ConformanceWindow.RightOffset) * cropUnitX + } + + return int(width) +} + +// Height returns the video height. +func (s SPS) Height() int { + height := s.PicHeightInLumaSamples + + if s.ConformanceWindow != nil { + cropUnitY := subHeightC[s.ChromaFormatIdc] + height -= (s.ConformanceWindow.TopOffset + s.ConformanceWindow.BottomOffset) * cropUnitY + } + + return int(height) +} + +// FPS returns the frames per second of the video. +func (s SPS) FPS() float64 { + if s.VUI == nil || s.VUI.TimingInfo == nil { + return 0 + } + + return float64(s.VUI.TimingInfo.TimeScale) / float64(s.VUI.TimingInfo.NumUnitsInTick) +} diff --git a/pkg/codecs/h265/sps_test.go b/pkg/codecs/h265/sps_test.go new file mode 100644 index 0000000..eac88c1 --- /dev/null +++ b/pkg/codecs/h265/sps_test.go @@ -0,0 +1,446 @@ +//go:build go1.18 +// +build go1.18 + +package h265 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSPSUnmarshal(t *testing.T) { + for _, ca := range []struct { + name string + byts []byte + sps SPS + width int + height int + fps float64 + }{ + { + "1920x1080", + []byte{ + 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, + 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x10, 0xe5, + 0x96, 0x66, 0x69, 0x24, 0xca, 0xe0, 0x10, 0x00, + 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, + 0xe0, 0x80, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 1, + GeneralProfileCompatibilityFlag: [32]bool{ + false, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralFrameOnlyConstraintFlag: true, + GeneralLevelIdc: 120, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 1920, + PicHeightInLumaSamples: 1080, + Log2MaxPicOrderCntLsbMinus4: 4, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{5}, + MaxNumReorderPics: []uint32{2}, + MaxLatencyIncreasePlus1: []uint32{5}, + Log2DiffMaxMinLumaCodingBlockSize: 3, + Log2DiffMaxMinLumaTransformBlockSize: 3, + SampleAdaptiveOffsetEnabledFlag: true, + TemporalMvpEnabledFlag: true, + StrongIntraSmoothingEnabledFlag: true, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 30, + }, + }, + }, + 1920, + 1080, + 30, + }, + { + "1920x800", + []byte{ + 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, + 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x32, 0x16, + 0x59, 0x59, 0xa4, 0x93, 0x2b, 0xc0, 0x5a, 0x80, + 0x80, 0x80, 0x82, 0x00, 0x00, 0x07, 0xd2, 0x00, + 0x00, 0xbb, 0x80, 0x10, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 1, + GeneralProfileCompatibilityFlag: [32]bool{ + false, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralFrameOnlyConstraintFlag: true, + GeneralLevelIdc: 120, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 1920, + PicHeightInLumaSamples: 800, + Log2MaxPicOrderCntLsbMinus4: 4, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{4}, + MaxNumReorderPics: []uint32{2}, + MaxLatencyIncreasePlus1: []uint32{5}, + Log2DiffMaxMinLumaCodingBlockSize: 3, + Log2DiffMaxMinLumaTransformBlockSize: 3, + SampleAdaptiveOffsetEnabledFlag: true, + TemporalMvpEnabledFlag: true, + StrongIntraSmoothingEnabledFlag: true, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1001, + TimeScale: 24000, + }, + }, + }, + 1920, + 800, + 23.976023976023978, + }, + { + "1280x720", + []byte{ + 0x42, 0x01, 0x01, 0x04, 0x08, 0x00, 0x00, 0x03, + 0x00, 0x98, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x5d, 0x90, 0x00, 0x50, 0x10, 0x05, 0xa2, 0x29, + 0x4b, 0x74, 0x94, 0x98, 0x5f, 0xfe, 0x00, 0x02, + 0x00, 0x02, 0xd4, 0x04, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x03, 0x01, + 0xe0, 0x80, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 4, + GeneralProfileCompatibilityFlag: [32]bool{ + false, false, false, false, true, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralFrameOnlyConstraintFlag: true, + GeneralMax12bitConstraintFlag: true, + GeneralLowerBitRateConstraintFlag: true, + GeneralLevelIdc: 93, + }, + ChromaFormatIdc: 3, + PicWidthInLumaSamples: 1280, + PicHeightInLumaSamples: 720, + BitDepthLumaMinus8: 4, + BitDepthChromaMinus8: 4, + Log2MaxPicOrderCntLsbMinus4: 4, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{2}, + MaxNumReorderPics: []uint32{0}, + MaxLatencyIncreasePlus1: []uint32{1}, + Log2MinLumaCodingBlockSizeMinus3: 1, + Log2DiffMaxMinLumaCodingBlockSize: 1, + Log2DiffMaxMinLumaTransformBlockSize: 3, + TemporalMvpEnabledFlag: true, + StrongIntraSmoothingEnabledFlag: true, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 255, + SarWidth: 1, + SarHeight: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 30, + }, + }, + }, + 1280, + 720, + 30, + }, + { + "10 bit", + []byte{ + 0x42, 0x01, 0x01, 0x22, 0x20, 0x00, 0x00, 0x03, + 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x10, 0xe4, + 0xd9, 0x66, 0x66, 0x92, 0x4c, 0xaf, 0x01, 0x01, + 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x0b, + 0xb5, 0x08, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralTierFlag: 1, + GeneralProfileIdc: 2, + GeneralProfileCompatibilityFlag: [32]bool{ + false, false, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralFrameOnlyConstraintFlag: true, + GeneralLevelIdc: 120, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 1920, + PicHeightInLumaSamples: 1080, + BitDepthLumaMinus8: 2, + BitDepthChromaMinus8: 2, + Log2MaxPicOrderCntLsbMinus4: 4, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{5}, + MaxNumReorderPics: []uint32{2}, + MaxLatencyIncreasePlus1: []uint32{5}, + Log2DiffMaxMinLumaCodingBlockSize: 3, + Log2DiffMaxMinLumaTransformBlockSize: 3, + SampleAdaptiveOffsetEnabledFlag: true, + TemporalMvpEnabledFlag: true, + StrongIntraSmoothingEnabledFlag: true, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 100, + TimeScale: 2997, + }, + }, + }, + 1920, + 1080, + 29.97, + }, + { + "nvenc", + []byte{ + 0x42, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x03, 0x00, 0x7b, 0xa0, 0x03, 0xc0, 0x80, 0x11, + 0x07, 0xcb, 0x96, 0xb4, 0xa4, 0x25, 0x92, 0xe3, + 0x01, 0x6a, 0x02, 0x02, 0x02, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0xe3, + 0x00, 0x2e, 0xf2, 0x88, 0x00, 0x07, 0x27, 0x0c, + 0x00, 0x00, 0x98, 0x96, 0x82, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 1, + GeneralProfileCompatibilityFlag: [32]bool{ + false, true, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralLevelIdc: 123, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 1920, + PicHeightInLumaSamples: 1088, + ConformanceWindow: &SPS_ConformanceWindow{ + BottomOffset: 4, + }, + Log2MaxPicOrderCntLsbMinus4: 4, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{1}, + MaxNumReorderPics: []uint32{0}, + MaxLatencyIncreasePlus1: []uint32{0}, + Log2MinLumaCodingBlockSizeMinus3: 1, + Log2DiffMaxMinLumaCodingBlockSize: 1, + Log2DiffMaxMinLumaTransformBlockSize: 3, + MaxTransformHierarchyDepthInter: 3, + AmpEnabledFlag: true, + SampleAdaptiveOffsetEnabledFlag: true, + ShortTermRefPicSets: []*SPS_ShortTermRefPicSet{{ + NumNegativePics: 1, + DeltaPocS0Minus1: []uint32{0}, + UsedByCurrPicS0Flag: []bool{true}, + }}, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 60, + }, + }, + }, + 1920, + 1080, + 60, + }, + { + "avigilon", + []byte{ + 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, + 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x96, 0xa0, 0x01, 0x80, 0x20, 0x06, 0xc1, + 0xfe, 0x36, 0xbb, 0xb5, 0x37, 0x77, 0x25, 0xd6, + 0x02, 0xdc, 0x04, 0x04, 0x04, 0x10, 0x00, 0x00, + 0x3e, 0x80, 0x00, 0x04, 0x26, 0x87, 0x21, 0xde, + 0xe5, 0x10, 0x01, 0x6e, 0x20, 0x00, 0x66, 0xff, + 0x00, 0x0b, 0x71, 0x00, 0x03, 0x37, 0xf8, 0x80, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 1, + GeneralProfileCompatibilityFlag: [32]bool{ + false, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralLevelIdc: 150, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 3072, + PicHeightInLumaSamples: 1728, + ConformanceWindow: &SPS_ConformanceWindow{}, + Log2MaxPicOrderCntLsbMinus4: 12, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{1}, + MaxNumReorderPics: []uint32{0}, + MaxLatencyIncreasePlus1: []uint32{0}, + Log2DiffMaxMinLumaCodingBlockSize: 2, + SampleAdaptiveOffsetEnabledFlag: true, + PcmEnabledFlag: true, + PcmSampleBitDepthLumaMinus1: 7, + PcmSampleBitDepthChromaMinus1: 7, + Log2DiffMaxMinLumaTransformBlockSize: 2, + MaxTransformHierarchyDepthInter: 1, + Log2MinPcmLumaCodingBlockSizeMinus3: 2, + ShortTermRefPicSets: []*SPS_ShortTermRefPicSet{ + { + NumNegativePics: 1, + DeltaPocS0Minus1: []uint32{0}, + UsedByCurrPicS0Flag: []bool{true}, + }, + }, + TemporalMvpEnabledFlag: true, + VUI: &SPS_VUI{ + AspectRatioInfoPresentFlag: true, + AspectRatioIdc: 1, + VideoSignalTypePresentFlag: true, + VideoFormat: 5, + VideoFullRangeFlag: true, + ColourDescriptionPresentFlag: true, + ColourPrimaries: 1, + TransferCharacteristics: 1, + MatrixCoefficients: 1, + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1000, + TimeScale: 17000, + }, + }, + }, + 3072, + 1728, + 17, + }, + { + "long_term_ref_pics_present_flag", + []byte{ + 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, + 0x00, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x5d, 0xa0, 0x02, 0x80, 0x80, 0x2d, 0x16, + 0x36, 0xb9, 0x24, 0xcb, 0xf0, 0x08, 0x00, 0x00, + 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x95, + 0x08, + }, + SPS{ + TemporalIDNestingFlag: true, + ProfileTierLevel: SPS_ProfileTierLevel{ + GeneralProfileIdc: 1, + GeneralProfileCompatibilityFlag: [32]bool{ + false, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }, + GeneralProgressiveSourceFlag: true, + GeneralNonPackedConstraintFlag: true, + GeneralFrameOnlyConstraintFlag: true, + GeneralLevelIdc: 93, + }, + ChromaFormatIdc: 1, + PicWidthInLumaSamples: 1280, + PicHeightInLumaSamples: 720, + Log2MaxPicOrderCntLsbMinus4: 12, + SubLayerOrderingInfoPresentFlag: true, + MaxDecPicBufferingMinus1: []uint32{1}, + MaxNumReorderPics: []uint32{0}, + MaxLatencyIncreasePlus1: []uint32{0}, + Log2DiffMaxMinLumaCodingBlockSize: 3, + Log2DiffMaxMinLumaTransformBlockSize: 3, + SampleAdaptiveOffsetEnabledFlag: true, + LongTermRefPicsPresentFlag: true, + TemporalMvpEnabledFlag: true, + StrongIntraSmoothingEnabledFlag: true, + VUI: &SPS_VUI{ + TimingInfo: &SPS_TimingInfo{ + NumUnitsInTick: 1, + TimeScale: 50, + POCProportionalToTimingFlag: true, + NumTicksPOCDiffOneMinus1: 1, + }, + }, + }, + 1280, + 720, + 50, + }, + } { + t.Run(ca.name, func(t *testing.T) { + var sps SPS + err := sps.Unmarshal(ca.byts) + require.NoError(t, err) + require.Equal(t, ca.sps, sps) + require.Equal(t, ca.width, sps.Width()) + require.Equal(t, ca.height, sps.Height()) + require.Equal(t, ca.fps, sps.FPS()) + }) + } +} + +func FuzzSPSUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var sps SPS + sps.Unmarshal(b) + }) +} diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/0e888f462a3598bba3429e3c26cda412817aa65ef38cdeb3aaed76db1c0379a4 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/0e888f462a3598bba3429e3c26cda412817aa65ef38cdeb3aaed76db1c0379a4 new file mode 100644 index 0000000..8ca4d7c --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/0e888f462a3598bba3429e3c26cda412817aa65ef38cdeb3aaed76db1c0379a4 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\xc6000000000") +uint64(87) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/1c4d7707525a482640e7c5090e339b08e446b5f9e4f7fff7e448ae377664edb0 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/1c4d7707525a482640e7c5090e339b08e446b5f9e4f7fff7e448ae377664edb0 new file mode 100644 index 0000000..eaa28f7 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/1c4d7707525a482640e7c5090e339b08e446b5f9e4f7fff7e448ae377664edb0 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\x80\x00\x00\x00\x0000000") +uint64(2) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/355f66d5cd294d34483b9be09cb55a3a35b9dd081ab4959ba7a35d04c5f91cb8 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/355f66d5cd294d34483b9be09cb55a3a35b9dd081ab4959ba7a35d04c5f91cb8 new file mode 100644 index 0000000..cee8eb1 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/355f66d5cd294d34483b9be09cb55a3a35b9dd081ab4959ba7a35d04c5f91cb8 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("0") +uint64(0) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/3c6b851fbf8b3435e3757b3fd9ec0f57bfe84533014a058f89ed320caceb13a9 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/3c6b851fbf8b3435e3757b3fd9ec0f57bfe84533014a058f89ed320caceb13a9 new file mode 100644 index 0000000..2022191 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/3c6b851fbf8b3435e3757b3fd9ec0f57bfe84533014a058f89ed320caceb13a9 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("\x000\x920!0000000") +uint64(156) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/53955e13efd39f08be15944b872ad99a77e5d04e1472db9455c4b1b5bd8b7073 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/53955e13efd39f08be15944b872ad99a77e5d04e1472db9455c4b1b5bd8b7073 new file mode 100644 index 0000000..39b9df0 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/53955e13efd39f08be15944b872ad99a77e5d04e1472db9455c4b1b5bd8b7073 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*") +uint64(34) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/6004440a439db44ebabbaee8a166e7a25bbaa5d4431a3900f509c70b756a06fb b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/6004440a439db44ebabbaee8a166e7a25bbaa5d4431a3900f509c70b756a06fb new file mode 100644 index 0000000..69daea5 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/6004440a439db44ebabbaee8a166e7a25bbaa5d4431a3900f509c70b756a06fb @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\x80\x00\x00\x000000 0") +uint64(3) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8bf21706c418e930c7b972e6fff78d2fcadf6942a62141398df17b6cbe61f0b7 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8bf21706c418e930c7b972e6fff78d2fcadf6942a62141398df17b6cbe61f0b7 new file mode 100644 index 0000000..fba610d --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8bf21706c418e930c7b972e6fff78d2fcadf6942a62141398df17b6cbe61f0b7 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\xc6A00000000") +uint64(130) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8e78b3e3511102b0b24e8f88b42b4e913a44408f4dfb4e496550c34cb92c93fc b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8e78b3e3511102b0b24e8f88b42b4e913a44408f4dfb4e496550c34cb92c93fc new file mode 100644 index 0000000..0a7d5d1 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/8e78b3e3511102b0b24e8f88b42b4e913a44408f4dfb4e496550c34cb92c93fc @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("\x000\xb3000000000") +uint64(18) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/b467576cf8e0115542bddaece5f2d2bce19860a7c060445225adcf3dab189bc4 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/b467576cf8e0115542bddaece5f2d2bce19860a7c060445225adcf3dab189bc4 new file mode 100644 index 0000000..f093f29 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/b467576cf8e0115542bddaece5f2d2bce19860a7c060445225adcf3dab189bc4 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\x80\x00\x00\x000000$0") +uint64(9) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f45d427ed4a5ea4af4846b4aeaf70d8194277f53bc68eb6255f52278d879d48c b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f45d427ed4a5ea4af4846b4aeaf70d8194277f53bc68eb6255f52278d879d48c new file mode 100644 index 0000000..8d9c858 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f45d427ed4a5ea4af4846b4aeaf70d8194277f53bc68eb6255f52278d879d48c @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*00000000000") +uint64(6) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f6aa371594073591a2888e9cff0054b22899ced04b7aa1fddf0c96c76937d0fd b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f6aa371594073591a2888e9cff0054b22899ced04b7aa1fddf0c96c76937d0fd new file mode 100644 index 0000000..45ffc85 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/f6aa371594073591a2888e9cff0054b22899ced04b7aa1fddf0c96c76937d0fd @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("0") +uint64(200) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/fd6f09d0654e93abb8d685f39f20a5ddcdb857a09391b3e18e55376b8155e3a8 b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/fd6f09d0654e93abb8d685f39f20a5ddcdb857a09391b3e18e55376b8155e3a8 new file mode 100644 index 0000000..ea4f9f8 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzDTSExtractor/fd6f09d0654e93abb8d685f39f20a5ddcdb857a09391b3e18e55376b8155e3a8 @@ -0,0 +1,3 @@ +go test fuzz v1 +[]byte("*0\x80\x00\x00\x000000A0") +uint64(18) diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 new file mode 100644 index 0000000..7fd7a20 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/06ba4bdb19de593e669c642987e270fe2488d4d58ecd712db136a3e011071253 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/76c06f7399f3b1781289b37c42f3dbe1518bc2481859740855ab13d8abdd88b1 b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/76c06f7399f3b1781289b37c42f3dbe1518bc2481859740855ab13d8abdd88b1 new file mode 100644 index 0000000..7c93803 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/76c06f7399f3b1781289b37c42f3dbe1518bc2481859740855ab13d8abdd88b1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c new file mode 100644 index 0000000..e8000f3 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 new file mode 100644 index 0000000..ef9f9d4 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzPPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/00d6da076abf399523d37cc5d1385a967f0634a2573162c00ba67a01fd806919 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/00d6da076abf399523d37cc5d1385a967f0634a2573162c00ba67a01fd806919 new file mode 100644 index 0000000..a33f390 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/00d6da076abf399523d37cc5d1385a967f0634a2573162c00ba67a01fd806919 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/019839a18a6e47ed73c11a7503859a5680dfceb99c4fb98344d87f884ef731ba b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/019839a18a6e47ed73c11a7503859a5680dfceb99c4fb98344d87f884ef731ba new file mode 100644 index 0000000..a9b9365 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/019839a18a6e47ed73c11a7503859a5680dfceb99c4fb98344d87f884ef731ba @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000007808000000000000ZCz700") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/039e575e749a676e0037b8aa9d28d80a409c350d4900c88ab2647be4492f25ee b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/039e575e749a676e0037b8aa9d28d80a409c350d4900c88ab2647be4492f25ee new file mode 100644 index 0000000..0842b2a --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/039e575e749a676e0037b8aa9d28d80a409c350d4900c88ab2647be4492f25ee @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000002111007000000a00000017ZZZZ\xf9000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/05c89dc905ecc2ca9fc8fa08e0e0d56b83156fd4d8de02c03bda9a96b85679e0 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/05c89dc905ecc2ca9fc8fa08e0e0d56b83156fd4d8de02c03bda9a96b85679e0 new file mode 100644 index 0000000..a26d294 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/05c89dc905ecc2ca9fc8fa08e0e0d56b83156fd4d8de02c03bda9a96b85679e0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000C11110010000\x00000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/0f8f18804076a2178ba242cfc92d30a0fd17a6f4aa63a8005253a16205b4e3c6 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/0f8f18804076a2178ba242cfc92d30a0fd17a6f4aa63a8005253a16205b4e3c6 new file mode 100644 index 0000000..7c50150 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/0f8f18804076a2178ba242cfc92d30a0fd17a6f4aa63a8005253a16205b4e3c6 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000\xf571*07") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/123492a203ec37c506b8768bd1b55bf7bc54ee36279dc9f09567d675c044d58f b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/123492a203ec37c506b8768bd1b55bf7bc54ee36279dc9f09567d675c044d58f new file mode 100644 index 0000000..6616d84 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/123492a203ec37c506b8768bd1b55bf7bc54ee36279dc9f09567d675c044d58f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000y710") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/182a4fb401185659940bf9a2589536a695487fba02686e2130ed0a5b880d52dc b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/182a4fb401185659940bf9a2589536a695487fba02686e2130ed0a5b880d52dc new file mode 100644 index 0000000..291cec8 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/182a4fb401185659940bf9a2589536a695487fba02686e2130ed0a5b880d52dc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/1ced60e9d7b0105858590098640e83c09fecc453519c426cc0b446d43a1cbd73 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/1ced60e9d7b0105858590098640e83c09fecc453519c426cc0b446d43a1cbd73 new file mode 100644 index 0000000..de09603 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/1ced60e9d7b0105858590098640e83c09fecc453519c426cc0b446d43a1cbd73 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000077y2B000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/20c0dd82574437b8f5caaac5f38a1199e9777ffe846bba3468737defafd094e7 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/20c0dd82574437b8f5caaac5f38a1199e9777ffe846bba3468737defafd094e7 new file mode 100644 index 0000000..b081058 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/20c0dd82574437b8f5caaac5f38a1199e9777ffe846bba3468737defafd094e7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000000000170") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/27052827203b64be7e464d07f815b5af2a08d4e6406f173702c88b6a86862437 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/27052827203b64be7e464d07f815b5af2a08d4e6406f173702c88b6a86862437 new file mode 100644 index 0000000..4e6a55e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/27052827203b64be7e464d07f815b5af2a08d4e6406f173702c88b6a86862437 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000\xf571707\x80\x00\x00\x00\xea\xea\xea\xea\xea\xea0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d13274250a51272648fb79aee956d40195ff289a44da3296d0c88ac02fc67bc b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d13274250a51272648fb79aee956d40195ff289a44da3296d0c88ac02fc67bc new file mode 100644 index 0000000..4583c5a --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d13274250a51272648fb79aee956d40195ff289a44da3296d0c88ac02fc67bc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000007100\xf8A102") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 new file mode 100644 index 0000000..3d32e14 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3067c11d51b8a2666368161328eb2c82c55cb593824ddfe49742696889e520d5 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3067c11d51b8a2666368161328eb2c82c55cb593824ddfe49742696889e520d5 new file mode 100644 index 0000000..f1e39d7 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3067c11d51b8a2666368161328eb2c82c55cb593824ddfe49742696889e520d5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000017") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/343dd7a6b769cfbc11b8ffd2162c9c6aac1e8bf42d252c18b6f766ec1858aaff b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/343dd7a6b769cfbc11b8ffd2162c9c6aac1e8bf42d252c18b6f766ec1858aaff new file mode 100644 index 0000000..503702f --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/343dd7a6b769cfbc11b8ffd2162c9c6aac1e8bf42d252c18b6f766ec1858aaff @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3742076c487d68aab77f194af476bb9fa1d01a47a46bed9bae42c10b18e21594 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3742076c487d68aab77f194af476bb9fa1d01a47a46bed9bae42c10b18e21594 new file mode 100644 index 0000000..2ad014b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3742076c487d68aab77f194af476bb9fa1d01a47a46bed9bae42c10b18e21594 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000012Z") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3765cdec1f28e3f1f6f3f32d5f9c0d4cb61ea2d4533f554abd52b0df93bbbc4a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3765cdec1f28e3f1f6f3f32d5f9c0d4cb61ea2d4533f554abd52b0df93bbbc4a new file mode 100644 index 0000000..48e4760 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3765cdec1f28e3f1f6f3f32d5f9c0d4cb61ea2d4533f554abd52b0df93bbbc4a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000077y2B0C") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/38f534b19ae62787a091d045d10ea3068aa66a765d26b383f9848a4881c6c170 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/38f534b19ae62787a091d045d10ea3068aa66a765d26b383f9848a4881c6c170 new file mode 100644 index 0000000..9c1c38a --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/38f534b19ae62787a091d045d10ea3068aa66a765d26b383f9848a4881c6c170 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000070A\xfdv\xad100") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3aaf3f930d2b6f555533d7ee1833e960dc84706396c38db6be2c71c772230bf3 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3aaf3f930d2b6f555533d7ee1833e960dc84706396c38db6be2c71c772230bf3 new file mode 100644 index 0000000..bd9e18b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3aaf3f930d2b6f555533d7ee1833e960dc84706396c38db6be2c71c772230bf3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000711720A") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3dc305666b84e8f7b04c66b69b6cc79e8df25b2ae99c5caf497906ea47c87401 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3dc305666b84e8f7b04c66b69b6cc79e8df25b2ae99c5caf497906ea47c87401 new file mode 100644 index 0000000..d763cb7 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/3dc305666b84e8f7b04c66b69b6cc79e8df25b2ae99c5caf497906ea47c87401 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000A00807XG0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/40ea349cafd1592da4cd915eb8f86e8dcfe862c5cd7d187c082598daaba1c047 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/40ea349cafd1592da4cd915eb8f86e8dcfe862c5cd7d187c082598daaba1c047 new file mode 100644 index 0000000..1e4ca77 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/40ea349cafd1592da4cd915eb8f86e8dcfe862c5cd7d187c082598daaba1c047 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071172X7") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4205343f82a7d78102d7bcfeeae612a8916981964640a34384b1ade4316e8038 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4205343f82a7d78102d7bcfeeae612a8916981964640a34384b1ade4316e8038 new file mode 100644 index 0000000..505fda8 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4205343f82a7d78102d7bcfeeae612a8916981964640a34384b1ade4316e8038 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000\x111") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/458604b691a14a0f80c142b495b99b128071c41b8527d5e3dbaab0fa75aa703f b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/458604b691a14a0f80c142b495b99b128071c41b8527d5e3dbaab0fa75aa703f new file mode 100644 index 0000000..a71665b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/458604b691a14a0f80c142b495b99b128071c41b8527d5e3dbaab0fa75aa703f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000011170B0927$") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/475bdf3daec7839816b18b486c43e23d21d3d1709f5d6e909f809e316eef3ad0 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/475bdf3daec7839816b18b486c43e23d21d3d1709f5d6e909f809e316eef3ad0 new file mode 100644 index 0000000..37aeb09 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/475bdf3daec7839816b18b486c43e23d21d3d1709f5d6e909f809e316eef3ad0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000711720\xcb") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4a3b46c8074373cb032eadcea909e28289cca73cd868ab29f13674040fbc6744 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4a3b46c8074373cb032eadcea909e28289cca73cd868ab29f13674040fbc6744 new file mode 100644 index 0000000..fcac589 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4a3b46c8074373cb032eadcea909e28289cca73cd868ab29f13674040fbc6744 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4d32bcb6507cca15717e5d30bae3c6d948e0abe6541fd423fdc4415f863329a8 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4d32bcb6507cca15717e5d30bae3c6d948e0abe6541fd423fdc4415f863329a8 new file mode 100644 index 0000000..bf66123 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/4d32bcb6507cca15717e5d30bae3c6d948e0abe6541fd423fdc4415f863329a8 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000y7100") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/547803e15ea20edd45d87377b5a21ace6348d0ab462a9bd03318f936ec14cf9c b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/547803e15ea20edd45d87377b5a21ace6348d0ab462a9bd03318f936ec14cf9c new file mode 100644 index 0000000..5bf1504 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/547803e15ea20edd45d87377b5a21ace6348d0ab462a9bd03318f936ec14cf9c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000010\xcb") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/60d5d2f797c1cc11b7698f694b8ae1044f19e4d98d2048c1aefa8efd2d61658b b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/60d5d2f797c1cc11b7698f694b8ae1044f19e4d98d2048c1aefa8efd2d61658b new file mode 100644 index 0000000..1b09a3e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/60d5d2f797c1cc11b7698f694b8ae1044f19e4d98d2048c1aefa8efd2d61658b @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000002007\xffA0200771") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/615cfc8866bc1a828694f072286c58d406629607f197524d518d77ba7f8f9b54 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/615cfc8866bc1a828694f072286c58d406629607f197524d518d77ba7f8f9b54 new file mode 100644 index 0000000..49ee93e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/615cfc8866bc1a828694f072286c58d406629607f197524d518d77ba7f8f9b54 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000002111007B71BC0000007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/649679f2d355f61f168ec2ba9b37e5295eda2a415d5a61533385124723c2e9db b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/649679f2d355f61f168ec2ba9b37e5295eda2a415d5a61533385124723c2e9db new file mode 100644 index 0000000..ba4fe29 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/649679f2d355f61f168ec2ba9b37e5295eda2a415d5a61533385124723c2e9db @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000$X") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/653a4111f80a68c2f197f0add573756caf6da8dd8aeb7051bc88bc3e954f2901 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/653a4111f80a68c2f197f0add573756caf6da8dd8aeb7051bc88bc3e954f2901 new file mode 100644 index 0000000..c615203 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/653a4111f80a68c2f197f0add573756caf6da8dd8aeb7051bc88bc3e954f2901 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000070000000000000,1\x0007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f82af969dfcb94acaf2cfd6c35a75cc7c744b63b33f37286bc716604e68ce45 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f82af969dfcb94acaf2cfd6c35a75cc7c744b63b33f37286bc716604e68ce45 new file mode 100644 index 0000000..44021d0 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f82af969dfcb94acaf2cfd6c35a75cc7c744b63b33f37286bc716604e68ce45 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000070000007\xc1002") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f8f56484ea8b20c24fe9dc371865fb09f7c7a27d7a2cd40809060e804600dc9 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f8f56484ea8b20c24fe9dc371865fb09f7c7a27d7a2cd40809060e804600dc9 new file mode 100644 index 0000000..9f8eb6b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/6f8f56484ea8b20c24fe9dc371865fb09f7c7a27d7a2cd40809060e804600dc9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000A\xfdya00") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/766677dfa01586ac8ad7954a627f3b900ee7248a10ebd94afec3bbaa59022126 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/766677dfa01586ac8ad7954a627f3b900ee7248a10ebd94afec3bbaa59022126 new file mode 100644 index 0000000..7c6f728 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/766677dfa01586ac8ad7954a627f3b900ee7248a10ebd94afec3bbaa59022126 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000y1000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7b6521a56664b1cbb97f5073269d7275bdd943870b45d5737a04da49f394c31f b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7b6521a56664b1cbb97f5073269d7275bdd943870b45d5737a04da49f394c31f new file mode 100644 index 0000000..1eee4c7 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7b6521a56664b1cbb97f5073269d7275bdd943870b45d5737a04da49f394c31f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000000000C2\xc77\xc71") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7c9233ac7979facf283efce144f2c1deeed8fa10349a851b491ccae0e134ffd1 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7c9233ac7979facf283efce144f2c1deeed8fa10349a851b491ccae0e134ffd1 new file mode 100644 index 0000000..36c244a --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/7c9233ac7979facf283efce144f2c1deeed8fa10349a851b491ccae0e134ffd1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000B2700100020A") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8281575bdc3265faffed6f7963cb1ea96e1cb9c3656e1c9b694d58227f4d168a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8281575bdc3265faffed6f7963cb1ea96e1cb9c3656e1c9b694d58227f4d168a new file mode 100644 index 0000000..9f9a7b9 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8281575bdc3265faffed6f7963cb1ea96e1cb9c3656e1c9b694d58227f4d168a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("002000000000000002Y7$") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/863c5cc1f718d5d6e39c6f0eda93b678543c653946f0e4c5205a9a6e688b6aa3 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/863c5cc1f718d5d6e39c6f0eda93b678543c653946f0e4c5205a9a6e688b6aa3 new file mode 100644 index 0000000..1663e76 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/863c5cc1f718d5d6e39c6f0eda93b678543c653946f0e4c5205a9a6e688b6aa3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000711720B") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8703c0328c7aa4fe9e463dc9ec11a112f9530cf5b7c018987e1e56d0cb32e364 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8703c0328c7aa4fe9e463dc9ec11a112f9530cf5b7c018987e1e56d0cb32e364 new file mode 100644 index 0000000..51a6628 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8703c0328c7aa4fe9e463dc9ec11a112f9530cf5b7c018987e1e56d0cb32e364 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000007171708A") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c new file mode 100644 index 0000000..e8000f3 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8b8a68c6d9b801391c5df3d5f6fafc362a71d1b716bc02d268998df08364ac37 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8b8a68c6d9b801391c5df3d5f6fafc362a71d1b716bc02d268998df08364ac37 new file mode 100644 index 0000000..a2fe629 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8b8a68c6d9b801391c5df3d5f6fafc362a71d1b716bc02d268998df08364ac37 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000017") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8ba5fa6497afeb040d96665f4fba0037165933ebe9e760a70b1de81b23aadc4a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8ba5fa6497afeb040d96665f4fba0037165933ebe9e760a70b1de81b23aadc4a new file mode 100644 index 0000000..7810146 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8ba5fa6497afeb040d96665f4fba0037165933ebe9e760a70b1de81b23aadc4a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000717170002X") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8bb95d053ae9f84b2bc99c9c488cb91c7451ec0b22ab74c64548531f5d6633c9 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8bb95d053ae9f84b2bc99c9c488cb91c7451ec0b22ab74c64548531f5d6633c9 new file mode 100644 index 0000000..f6515cd --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/8bb95d053ae9f84b2bc99c9c488cb91c7451ec0b22ab74c64548531f5d6633c9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000\x118") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 new file mode 100644 index 0000000..896722f --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/943e3fb12606845898909ba86991f4b3a9d92f038aae8a9341a41fda80f92af5 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/943e3fb12606845898909ba86991f4b3a9d92f038aae8a9341a41fda80f92af5 new file mode 100644 index 0000000..0042af0 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/943e3fb12606845898909ba86991f4b3a9d92f038aae8a9341a41fda80f92af5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000070A\xfdv\xad0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9450509d117f96d6008adb21a4027055e3ba59c25615a5e96165c0bbb36b33bb b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9450509d117f96d6008adb21a4027055e3ba59c25615a5e96165c0bbb36b33bb new file mode 100644 index 0000000..b7d773b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9450509d117f96d6008adb21a4027055e3ba59c25615a5e96165c0bbb36b33bb @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000000000017") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/94e4dcd86c2e09aac9c790086b9e76dc2b02e9bc964370d3106dbaef5aa6d37a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/94e4dcd86c2e09aac9c790086b9e76dc2b02e9bc964370d3106dbaef5aa6d37a new file mode 100644 index 0000000..7b86d64 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/94e4dcd86c2e09aac9c790086b9e76dc2b02e9bc964370d3106dbaef5aa6d37a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000077y2B0C0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9c6e2641e293d6bffef8b06b9e36b2cf5ecacc6d3ad9d926ab5ec64ecdad7b96 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9c6e2641e293d6bffef8b06b9e36b2cf5ecacc6d3ad9d926ab5ec64ecdad7b96 new file mode 100644 index 0000000..0c2a90d --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9c6e2641e293d6bffef8b06b9e36b2cf5ecacc6d3ad9d926ab5ec64ecdad7b96 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000077y2B\xff\xff") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d560010faa7ada26ac70ae189fc384bd323efd7280990a5ecd6516cacd4cf61 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d560010faa7ada26ac70ae189fc384bd323efd7280990a5ecd6516cacd4cf61 new file mode 100644 index 0000000..b91ea1c --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d560010faa7ada26ac70ae189fc384bd323efd7280990a5ecd6516cacd4cf61 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000127001000A") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d9abe934c8d92838c18705f3e298f34ca63022bd4010acb6635278bc742398a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d9abe934c8d92838c18705f3e298f34ca63022bd4010acb6635278bc742398a new file mode 100644 index 0000000..f62bc1d --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/9d9abe934c8d92838c18705f3e298f34ca63022bd4010acb6635278bc742398a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("002000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a35edfe853b408a7c225af5012d1df6b6197436ce860641d55e275cc228da321 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a35edfe853b408a7c225af5012d1df6b6197436ce860641d55e275cc228da321 new file mode 100644 index 0000000..6e4c427 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a35edfe853b408a7c225af5012d1df6b6197436ce860641d55e275cc228da321 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000077y2B070") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a5d467a1921f1f1395d0bc1574ea92274cb4a498b3c7cb1189a419d2ba7f1ead b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a5d467a1921f1f1395d0bc1574ea92274cb4a498b3c7cb1189a419d2ba7f1ead new file mode 100644 index 0000000..f526e98 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/a5d467a1921f1f1395d0bc1574ea92274cb4a498b3c7cb1189a419d2ba7f1ead @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000011$0071110") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ab559ccd961e02992fd953c92eec4f50a828baecca4c6fffde8522632e90f847 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ab559ccd961e02992fd953c92eec4f50a828baecca4c6fffde8522632e90f847 new file mode 100644 index 0000000..37439c6 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ab559ccd961e02992fd953c92eec4f50a828baecca4c6fffde8522632e90f847 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000B27001000210") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/acf6271d3e87a7fc18dc947a460823559d30cdd652309d2002ba745ae6bca0f1 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/acf6271d3e87a7fc18dc947a460823559d30cdd652309d2002ba745ae6bca0f1 new file mode 100644 index 0000000..d15a96f --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/acf6271d3e87a7fc18dc947a460823559d30cdd652309d2002ba745ae6bca0f1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000002Wy2B00000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ada5d60ffad1e135ecbc4f08322871d93f995b41a108e987151365c3924b6372 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ada5d60ffad1e135ecbc4f08322871d93f995b41a108e987151365c3924b6372 new file mode 100644 index 0000000..cf66e3e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ada5d60ffad1e135ecbc4f08322871d93f995b41a108e987151365c3924b6372 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000B270010007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/afb972a0b1cfbd4181a062bd143cf2da5b1e1c9d921c0410faae807f3360caa2 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/afb972a0b1cfbd4181a062bd143cf2da5b1e1c9d921c0410faae807f3360caa2 new file mode 100644 index 0000000..baf9614 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/afb972a0b1cfbd4181a062bd143cf2da5b1e1c9d921c0410faae807f3360caa2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000020A\xd5Y8G0x") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/b3b203da514589b7cc4ed7d18c13cdabc383fa5bae32cc853a1b3224893458ce b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/b3b203da514589b7cc4ed7d18c13cdabc383fa5bae32cc853a1b3224893458ce new file mode 100644 index 0000000..bfa4e18 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/b3b203da514589b7cc4ed7d18c13cdabc383fa5bae32cc853a1b3224893458ce @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0020000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/bfdfa1a6e4892d045614bd28d441737cc637962c2d057a5647bd4d4174c657c6 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/bfdfa1a6e4892d045614bd28d441737cc637962c2d057a5647bd4d4174c657c6 new file mode 100644 index 0000000..5cf2fec --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/bfdfa1a6e4892d045614bd28d441737cc637962c2d057a5647bd4d4174c657c6 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000000000001872c0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 new file mode 100644 index 0000000..ef9f9d4 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c3d5e611c2447ae2d18cf179ce268a18421e73253c9f97cce75e02466a475d6a b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c3d5e611c2447ae2d18cf179ce268a18421e73253c9f97cce75e02466a475d6a new file mode 100644 index 0000000..493a56c --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/c3d5e611c2447ae2d18cf179ce268a18421e73253c9f97cce75e02466a475d6a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000120A27") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd4f7e682b02a30bc433044498e9124c6b1459802c7de9dcf18ad058a1688bb9 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd4f7e682b02a30bc433044498e9124c6b1459802c7de9dcf18ad058a1688bb9 new file mode 100644 index 0000000..19ce95b --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd4f7e682b02a30bc433044498e9124c6b1459802c7de9dcf18ad058a1688bb9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000070A\xfdv\xad10000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd939a83576d663b9de5c75da5b33dda1692c8289162a1e61d5764dee9ba5344 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd939a83576d663b9de5c75da5b33dda1692c8289162a1e61d5764dee9ba5344 new file mode 100644 index 0000000..c3ceb41 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/cd939a83576d663b9de5c75da5b33dda1692c8289162a1e61d5764dee9ba5344 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000000y720") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ceb8cba9187af176dab482e8571748c8293bff3c37419ec4f86e0f93b5c6f7ce b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ceb8cba9187af176dab482e8571748c8293bff3c37419ec4f86e0f93b5c6f7ce new file mode 100644 index 0000000..a3160d9 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ceb8cba9187af176dab482e8571748c8293bff3c37419ec4f86e0f93b5c6f7ce @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000\x112") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d09dfd7e6702ed14f3d16dc88c0beebc915cd3c7ed985106c7274dd6bf601991 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d09dfd7e6702ed14f3d16dc88c0beebc915cd3c7ed985106c7274dd6bf601991 new file mode 100644 index 0000000..73e0691 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d09dfd7e6702ed14f3d16dc88c0beebc915cd3c7ed985106c7274dd6bf601991 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000011100101177") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d2b8f6ff13c57a6493cc417708863c7edb8fa90b6973c421b32e45df6e98c897 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d2b8f6ff13c57a6493cc417708863c7edb8fa90b6973c421b32e45df6e98c897 new file mode 100644 index 0000000..8bb7738 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d2b8f6ff13c57a6493cc417708863c7edb8fa90b6973c421b32e45df6e98c897 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000$") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d3c6efd87c63850e112528d39bb792d28fb9d23bfbf5b241a62a63ebeb36b591 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d3c6efd87c63850e112528d39bb792d28fb9d23bfbf5b241a62a63ebeb36b591 new file mode 100644 index 0000000..2b1733f --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d3c6efd87c63850e112528d39bb792d28fb9d23bfbf5b241a62a63ebeb36b591 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000007100\xf8A100") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d8729013defaf4cf5833f86bef44bf6bcda1265ee9e83adb021dd883717e44ff b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d8729013defaf4cf5833f86bef44bf6bcda1265ee9e83adb021dd883717e44ff new file mode 100644 index 0000000..fe4fd54 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d8729013defaf4cf5833f86bef44bf6bcda1265ee9e83adb021dd883717e44ff @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d9f26138c54e610b9535ad32fa4fc65e7ee28921fd808119a9350650c2889fbb b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d9f26138c54e610b9535ad32fa4fc65e7ee28921fd808119a9350650c2889fbb new file mode 100644 index 0000000..c813945 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/d9f26138c54e610b9535ad32fa4fc65e7ee28921fd808119a9350650c2889fbb @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/dc2a4cb2325c492ca2a0787f03f4a64a9673fcbabcfd3d8b831163cf26e08257 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/dc2a4cb2325c492ca2a0787f03f4a64a9673fcbabcfd3d8b831163cf26e08257 new file mode 100644 index 0000000..845edc6 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/dc2a4cb2325c492ca2a0787f03f4a64a9673fcbabcfd3d8b831163cf26e08257 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000020A\xd5Y8G07") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e1d156e4fa7380afa414b12ae9aefa295debe1f892fe6bae3538651459654512 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e1d156e4fa7380afa414b12ae9aefa295debe1f892fe6bae3538651459654512 new file mode 100644 index 0000000..bda271e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e1d156e4fa7380afa414b12ae9aefa295debe1f892fe6bae3538651459654512 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000\x00\x040$") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e4a6272c0ccae23d9ff40b63a3526fd967ee0df216749b9ef13ed0fd5041b2b4 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e4a6272c0ccae23d9ff40b63a3526fd967ee0df216749b9ef13ed0fd5041b2b4 new file mode 100644 index 0000000..5587c6e --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e4a6272c0ccae23d9ff40b63a3526fd967ee0df216749b9ef13ed0fd5041b2b4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000$A") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e6a754dcc2747eb5e3225d7ce2b3ab19075eeda630aa67817acd128712faf440 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e6a754dcc2747eb5e3225d7ce2b3ab19075eeda630aa67817acd128712faf440 new file mode 100644 index 0000000..98661f0 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e6a754dcc2747eb5e3225d7ce2b3ab19075eeda630aa67817acd128712faf440 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000B27001000X") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e7020cfc8cfc8a340f41aafbc157c0cdb2ecfc1a41b2b0c2b2f0adeb78a33412 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e7020cfc8cfc8a340f41aafbc157c0cdb2ecfc1a41b2b0c2b2f0adeb78a33412 new file mode 100644 index 0000000..3fa85f2 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e7020cfc8cfc8a340f41aafbc157c0cdb2ecfc1a41b2b0c2b2f0adeb78a33412 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000000A177\xb3011") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e80085c26c10f735691d6790897e25ffbc50c2a2beafe1a090fd5059936f3a44 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e80085c26c10f735691d6790897e25ffbc50c2a2beafe1a090fd5059936f3a44 new file mode 100644 index 0000000..4762d3d --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/e80085c26c10f735691d6790897e25ffbc50c2a2beafe1a090fd5059936f3a44 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000007") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ed6952414b61c4c80820200ed4cfa0c873900d9311619e6590fa18cf8b28ef04 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ed6952414b61c4c80820200ed4cfa0c873900d9311619e6590fa18cf8b28ef04 new file mode 100644 index 0000000..f89ca5c --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ed6952414b61c4c80820200ed4cfa0c873900d9311619e6590fa18cf8b28ef04 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000%00000000A$0") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f6872527132c3a2c994316a511af6fb98889143acd71e18ff6adfca0aa3054cf b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f6872527132c3a2c994316a511af6fb98889143acd71e18ff6adfca0aa3054cf new file mode 100644 index 0000000..a996363 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f6872527132c3a2c994316a511af6fb98889143acd71e18ff6adfca0aa3054cf @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000120A7") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f7ffd151838837c215f9bcbdfb3f39bfd2105a931ef0118b72eb1eca4aeddad9 b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f7ffd151838837c215f9bcbdfb3f39bfd2105a931ef0118b72eb1eca4aeddad9 new file mode 100644 index 0000000..7e9923a --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f7ffd151838837c215f9bcbdfb3f39bfd2105a931ef0118b72eb1eca4aeddad9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f9043ef7bfaf2fdebf518743f1f81a2a50d46036a1da3d5844117036f78416ab b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f9043ef7bfaf2fdebf518743f1f81a2a50d46036a1da3d5844117036f78416ab new file mode 100644 index 0000000..0d05751 --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/f9043ef7bfaf2fdebf518743f1f81a2a50d46036a1da3d5844117036f78416ab @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000071717000\x110") diff --git a/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ff354e5d8975a43060c65913848811b2a66fea56a377d3aea5a0a7ffb53952ba b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ff354e5d8975a43060c65913848811b2a66fea56a377d3aea5a0a7ffb53952ba new file mode 100644 index 0000000..30a4c0f --- /dev/null +++ b/pkg/codecs/h265/testdata/fuzz/FuzzSPSUnmarshal/ff354e5d8975a43060c65913848811b2a66fea56a377d3aea5a0a7ffb53952ba @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0000000000000001Y7") diff --git a/pkg/codecs/jpeg/define_huffman_table.go b/pkg/codecs/jpeg/define_huffman_table.go new file mode 100644 index 0000000..bc46dac --- /dev/null +++ b/pkg/codecs/jpeg/define_huffman_table.go @@ -0,0 +1,20 @@ +package jpeg + +// DefineHuffmanTable is a DHT marker. +type DefineHuffmanTable struct { + Codes []byte + Symbols []byte + TableNumber int + TableClass int +} + +// Marshal encodes the marker. +func (m DefineHuffmanTable) Marshal(buf []byte) []byte { + buf = append(buf, []byte{0xFF, MarkerDefineHuffmanTable}...) + s := 3 + len(m.Codes) + len(m.Symbols) + buf = append(buf, []byte{byte(s >> 8), byte(s)}...) // length + buf = append(buf, []byte{byte(m.TableClass<<4) | byte(m.TableNumber)}...) + buf = append(buf, m.Codes...) + buf = append(buf, m.Symbols...) + return buf +} diff --git a/pkg/codecs/jpeg/define_huffman_table_test.go b/pkg/codecs/jpeg/define_huffman_table_test.go new file mode 100644 index 0000000..b00a640 --- /dev/null +++ b/pkg/codecs/jpeg/define_huffman_table_test.go @@ -0,0 +1,35 @@ +package jpeg + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesDefineHuffmanTable = []struct { + name string + enc []byte + dec DefineHuffmanTable +}{ + { + "base", + []byte{ + 0xff, 0xc4, 0x0, 0x7, 0x43, 0x1, 0x2, 0x3, 0x4, + }, + DefineHuffmanTable{ + Codes: []byte{0x01, 0x02}, + Symbols: []byte{0x03, 0x04}, + TableNumber: 3, + TableClass: 4, + }, + }, +} + +func TestDefineHuffmanTableMarshal(t *testing.T) { + for _, ca := range casesDefineHuffmanTable { + t.Run(ca.name, func(t *testing.T) { + byts := ca.dec.Marshal(nil) + require.Equal(t, ca.enc, byts) + }) + } +} diff --git a/pkg/codecs/jpeg/define_quantization_table.go b/pkg/codecs/jpeg/define_quantization_table.go new file mode 100644 index 0000000..b141fc6 --- /dev/null +++ b/pkg/codecs/jpeg/define_quantization_table.go @@ -0,0 +1,61 @@ +package jpeg + +import ( + "fmt" +) + +// QuantizationTable is a DQT quantization table. +type QuantizationTable struct { + ID uint8 + Precision uint8 + Data []byte +} + +// DefineQuantizationTable is a DQT marker. +type DefineQuantizationTable struct { + Tables []QuantizationTable +} + +// Unmarshal decodes the marker. +func (m *DefineQuantizationTable) Unmarshal(buf []byte) error { + for len(buf) != 0 { + id := buf[0] & 0x0F + precision := buf[0] >> 4 + buf = buf[1:] + if precision != 0 { + return fmt.Errorf("Precision %d is not supported", precision) + } + + if len(buf) < 64 { + return fmt.Errorf("image is too short") + } + + m.Tables = append(m.Tables, QuantizationTable{ + ID: id, + Precision: precision, + Data: buf[:64], + }) + buf = buf[64:] + } + + return nil +} + +// Marshal encodes the marker. +func (m DefineQuantizationTable) Marshal(buf []byte) []byte { + buf = append(buf, []byte{0xFF, MarkerDefineQuantizationTable}...) + + // length + s := 2 + for _, t := range m.Tables { + s += 1 + len(t.Data) + } + buf = append(buf, []byte{byte(s >> 8), byte(s)}...) + + for _, t := range m.Tables { + buf = append(buf, []byte{(t.ID)}...) + buf = append(buf, t.Data...) + } + + return buf +} diff --git a/pkg/codecs/jpeg/define_quantization_table_test.go b/pkg/codecs/jpeg/define_quantization_table_test.go new file mode 100644 index 0000000..d081017 --- /dev/null +++ b/pkg/codecs/jpeg/define_quantization_table_test.go @@ -0,0 +1,79 @@ +//go:build go1.18 +// +build go1.18 + +package jpeg + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +var casesDefineQuantizationTable = []struct { + name string + enc []byte + dec DefineQuantizationTable +}{ + { + "base", + []byte{ + 0xff, 0xdb, 0x0, 0x84, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x1, 0x2, 0x3, + 0x4, 0x1, 0x2, 0x3, 0x4, 0x5, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, 0x5, 0x6, + 0x7, 0x8, 0x5, 0x6, 0x7, 0x8, + }, + DefineQuantizationTable{ + Tables: []QuantizationTable{ + { + ID: 4, + Data: bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 64/4), + }, + { + ID: 5, + Data: bytes.Repeat([]byte{0x05, 0x06, 0x07, 0x08}, 64/4), + }, + }, + }, + }, +} + +func TestDefineQuantizationTableUnmarshal(t *testing.T) { + for _, ca := range casesDefineQuantizationTable { + t.Run(ca.name, func(t *testing.T) { + var h DefineQuantizationTable + err := h.Unmarshal(ca.enc[4:]) + require.NoError(t, err) + require.Equal(t, ca.dec, h) + }) + } +} + +func TestDefineQuantizationTableMarshal(t *testing.T) { + for _, ca := range casesDefineQuantizationTable { + t.Run(ca.name, func(t *testing.T) { + byts := ca.dec.Marshal(nil) + require.Equal(t, ca.enc, byts) + }) + } +} + +func FuzzDefineQuantizationTableUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var h DefineQuantizationTable + h.Unmarshal(b) + }) +} diff --git a/pkg/codecs/jpeg/define_restart_interval.go b/pkg/codecs/jpeg/define_restart_interval.go new file mode 100644 index 0000000..50a3026 --- /dev/null +++ b/pkg/codecs/jpeg/define_restart_interval.go @@ -0,0 +1,20 @@ +package jpeg + +import ( + "fmt" +) + +// DefineRestartInterval is a DRI marker. +type DefineRestartInterval struct { + Interval uint16 +} + +// Unmarshal decodes the marker. +func (m *DefineRestartInterval) Unmarshal(buf []byte) error { + if len(buf) != 2 { + return fmt.Errorf("unsupported DRI size of %d", len(buf)) + } + + m.Interval = uint16(buf[0])<<8 | uint16(buf[1]) + return nil +} diff --git a/pkg/codecs/jpeg/define_restart_interval_test.go b/pkg/codecs/jpeg/define_restart_interval_test.go new file mode 100644 index 0000000..35251c8 --- /dev/null +++ b/pkg/codecs/jpeg/define_restart_interval_test.go @@ -0,0 +1,44 @@ +//go:build go1.18 +// +build go1.18 + +package jpeg + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesDefineRestartInterval = []struct { + name string + enc []byte + dec DefineRestartInterval +}{ + { + "base", + []byte{ + 0xff, MarkerDefineRestartInterval, 0x00, 0x04, 0xd0, 0xc7, + }, + DefineRestartInterval{ + Interval: 53447, + }, + }, +} + +func TestDefineRestartIntervalUnmarshal(t *testing.T) { + for _, ca := range casesDefineRestartInterval { + t.Run(ca.name, func(t *testing.T) { + var h DefineRestartInterval + err := h.Unmarshal(ca.enc[4:]) + require.NoError(t, err) + require.Equal(t, ca.dec, h) + }) + } +} + +func FuzzDefineRestartIntervalUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var h DefineRestartInterval + h.Unmarshal(b) + }) +} diff --git a/pkg/codecs/jpeg/jpeg.go b/pkg/codecs/jpeg/jpeg.go new file mode 100644 index 0000000..db62667 --- /dev/null +++ b/pkg/codecs/jpeg/jpeg.go @@ -0,0 +1,14 @@ +// Package jpeg contains JPEG/JFIF markers. +package jpeg + +// standard JPEG markers. +const ( + MarkerStartOfImage = 0xD8 + MarkerDefineQuantizationTable = 0xDB + MarkerDefineHuffmanTable = 0xC4 + MarkerDefineRestartInterval = 0xDD + MarkerStartOfFrame1 = 0xC0 + MarkerStartOfScan = 0xDA + MarkerEndOfImage = 0xD9 + MarkerComment = 0xFE +) diff --git a/pkg/codecs/jpeg/start_of_frame1.go b/pkg/codecs/jpeg/start_of_frame1.go new file mode 100644 index 0000000..8eb2a25 --- /dev/null +++ b/pkg/codecs/jpeg/start_of_frame1.go @@ -0,0 +1,83 @@ +package jpeg + +import ( + "fmt" +) + +// StartOfFrame1 is a SOF1 marker. +type StartOfFrame1 struct { + Type uint8 + Width int + Height int + QuantizationTableCount uint8 // write only +} + +// Unmarshal decodes the marker. +func (m *StartOfFrame1) Unmarshal(buf []byte) error { + if len(buf) != 15 { + return fmt.Errorf("unsupported SOF size of %d", len(buf)) + } + + precision := buf[0] + if precision != 8 { + return fmt.Errorf("precision %d is not supported", precision) + } + + m.Height = int(buf[1])<<8 | int(buf[2]) + m.Width = int(buf[3])<<8 | int(buf[4]) + + components := buf[5] + if components != 3 { + return fmt.Errorf("number of components = %d is not supported", components) + } + + samp0 := buf[7] + switch samp0 { + case 0x21: + m.Type = 0 + + case 0x22: + m.Type = 1 + + default: + return fmt.Errorf("samp0 %x is not supported", samp0) + } + + samp1 := buf[10] + if samp1 != 0x11 { + return fmt.Errorf("samp1 %x is not supported", samp1) + } + + samp2 := buf[13] + if samp2 != 0x11 { + return fmt.Errorf("samp2 %x is not supported", samp2) + } + + return nil +} + +// Marshal encodes the marker. +func (m StartOfFrame1) Marshal(buf []byte) []byte { + buf = append(buf, []byte{0xFF, MarkerStartOfFrame1}...) + buf = append(buf, []byte{0, 17}...) // length + buf = append(buf, []byte{8}...) // precision + buf = append(buf, []byte{byte(m.Height >> 8), byte(m.Height)}...) // height + buf = append(buf, []byte{byte(m.Width >> 8), byte(m.Width)}...) // width + buf = append(buf, []byte{3}...) // components + if (m.Type & 0x3f) == 0 { // component 0 + buf = append(buf, []byte{0x00, 0x21, 0}...) + } else { + buf = append(buf, []byte{0x00, 0x22, 0}...) + } + + var secondQuantizationTable byte + if m.QuantizationTableCount == 2 { + secondQuantizationTable = 1 + } else { + secondQuantizationTable = 0 + } + + buf = append(buf, []byte{1, 0x11, secondQuantizationTable}...) // component 1 + buf = append(buf, []byte{2, 0x11, secondQuantizationTable}...) // component 2 + return buf +} diff --git a/pkg/codecs/jpeg/start_of_frame1_test.go b/pkg/codecs/jpeg/start_of_frame1_test.go new file mode 100644 index 0000000..56ff313 --- /dev/null +++ b/pkg/codecs/jpeg/start_of_frame1_test.go @@ -0,0 +1,59 @@ +//go:build go1.18 +// +build go1.18 + +package jpeg + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesStartOfFrame1 = []struct { + name string + enc []byte + dec StartOfFrame1 +}{ + { + "base", + []byte{ + 0xff, 0xc0, 0x0, 0x11, 0x8, 0x2, 0x58, 0x3, + 0x20, 0x3, 0x0, 0x22, 0x0, 0x1, 0x11, 0x1, + 0x2, 0x11, 0x1, + }, + StartOfFrame1{ + Type: 1, + Width: 800, + Height: 600, + QuantizationTableCount: 2, + }, + }, +} + +func TestStartOfFrame1Unmarshal(t *testing.T) { + for _, ca := range casesStartOfFrame1 { + t.Run(ca.name, func(t *testing.T) { + var h StartOfFrame1 + err := h.Unmarshal(ca.enc[4:]) + require.NoError(t, err) + h.QuantizationTableCount = 2 + require.Equal(t, ca.dec, h) + }) + } +} + +func TestStartOfFrame1Marshal(t *testing.T) { + for _, ca := range casesStartOfFrame1 { + t.Run(ca.name, func(t *testing.T) { + byts := ca.dec.Marshal(nil) + require.Equal(t, ca.enc, byts) + }) + } +} + +func FuzzStartOfFrame1Unmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var h StartOfFrame1 + h.Unmarshal(b) + }) +} diff --git a/pkg/codecs/jpeg/start_of_image.go b/pkg/codecs/jpeg/start_of_image.go new file mode 100644 index 0000000..9a6ea7a --- /dev/null +++ b/pkg/codecs/jpeg/start_of_image.go @@ -0,0 +1,10 @@ +package jpeg + +// StartOfImage is a SOI marker. +type StartOfImage struct{} + +// Marshal encodes the marker. +func (StartOfImage) Marshal(buf []byte) []byte { + buf = append(buf, []byte{0xFF, MarkerStartOfImage}...) + return buf +} diff --git a/pkg/codecs/jpeg/start_of_image_test.go b/pkg/codecs/jpeg/start_of_image_test.go new file mode 100644 index 0000000..070cf15 --- /dev/null +++ b/pkg/codecs/jpeg/start_of_image_test.go @@ -0,0 +1,12 @@ +package jpeg + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestStartOfImageMarshal(t *testing.T) { + buf := StartOfImage{}.Marshal(nil) + require.Equal(t, []byte{0xff, 0xd8}, buf) +} diff --git a/pkg/codecs/jpeg/start_of_scan.go b/pkg/codecs/jpeg/start_of_scan.go new file mode 100644 index 0000000..da78cb7 --- /dev/null +++ b/pkg/codecs/jpeg/start_of_scan.go @@ -0,0 +1,28 @@ +package jpeg + +import ( + "fmt" +) + +// StartOfScan is a SOS marker. +type StartOfScan struct{} + +// Unmarshal decodes the marker. +func (StartOfScan) Unmarshal(buf []byte) error { + if len(buf) != 10 { + return fmt.Errorf("unsupported SOS size of %d", len(buf)) + } + return nil +} + +// Marshal encodes the marker. +func (StartOfScan) Marshal(buf []byte) []byte { + buf = append(buf, []byte{0xFF, MarkerStartOfScan}...) + buf = append(buf, []byte{0, 12}...) // length + buf = append(buf, []byte{3}...) // components + buf = append(buf, []byte{0, 0}...) // component 0 + buf = append(buf, []byte{1, 0x11}...) // component 1 + buf = append(buf, []byte{2, 0x11}...) // component 2 + buf = append(buf, []byte{0, 63, 0}...) + return buf +} diff --git a/pkg/codecs/jpeg/start_of_scan_test.go b/pkg/codecs/jpeg/start_of_scan_test.go new file mode 100644 index 0000000..1910ddd --- /dev/null +++ b/pkg/codecs/jpeg/start_of_scan_test.go @@ -0,0 +1,52 @@ +//go:build go1.18 +// +build go1.18 + +package jpeg + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesStartOfScan = []struct { + name string + enc []byte + dec StartOfScan +}{ + { + "base", + []byte{ + 0xff, 0xda, 0x0, 0xc, 0x3, 0x0, 0x0, 0x1, + 0x11, 0x2, 0x11, 0x0, 0x3f, 0x0, + }, + StartOfScan{}, + }, +} + +func TestStartOfScanUnmarshal(t *testing.T) { + for _, ca := range casesStartOfScan { + t.Run(ca.name, func(t *testing.T) { + var h StartOfScan + err := h.Unmarshal(ca.enc[4:]) + require.NoError(t, err) + require.Equal(t, ca.dec, h) + }) + } +} + +func TestStartOfScanMarshal(t *testing.T) { + for _, ca := range casesStartOfScan { + t.Run(ca.name, func(t *testing.T) { + byts := ca.dec.Marshal(nil) + require.Equal(t, ca.enc, byts) + }) + } +} + +func FuzzStartOfScanUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var h StartOfScan + h.Unmarshal(b) + }) +} diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/97dc7172b48e6ffd89dfa34cfaac68bab4e2c2a4c5a0ab953e27ba6b006ffd56 b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/97dc7172b48e6ffd89dfa34cfaac68bab4e2c2a4c5a0ab953e27ba6b006ffd56 new file mode 100644 index 0000000..4fbe416 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineQuantizationTableUnmarshal/97dc7172b48e6ffd89dfa34cfaac68bab4e2c2a4c5a0ab953e27ba6b006ffd56 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x01") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineRestartIntervalUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineRestartIntervalUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 new file mode 100644 index 0000000..67322c7 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzDefineRestartIntervalUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/04069695460a25181d94bba1342df84c161a53135a7a8e93511489e6b51c0afe b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/04069695460a25181d94bba1342df84c161a53135a7a8e93511489e6b51c0afe new file mode 100644 index 0000000..98474d5 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/04069695460a25181d94bba1342df84c161a53135a7a8e93511489e6b51c0afe @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\b0000\x030!00\x110000") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/52bcb082e28f6e0e4007bae9ef0f4984e89ae5c891d08a2ad3c917fe77b94408 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/52bcb082e28f6e0e4007bae9ef0f4984e89ae5c891d08a2ad3c917fe77b94408 new file mode 100644 index 0000000..c0bab18 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/52bcb082e28f6e0e4007bae9ef0f4984e89ae5c891d08a2ad3c917fe77b94408 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\b0000\x030!0000000") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 new file mode 100644 index 0000000..896722f --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/93e3bc3735a837c70603d7f0bb7ec05fb087fd4db33e0ee855d9b225ca8f2511 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/9aaf79656de4e8166797e57c7ea359c531218826a6db07cf1a68e91f15b540c8 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/9aaf79656de4e8166797e57c7ea359c531218826a6db07cf1a68e91f15b540c8 new file mode 100644 index 0000000..83a124d --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/9aaf79656de4e8166797e57c7ea359c531218826a6db07cf1a68e91f15b540c8 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\b0000\x03000000000") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/f032221efa2df5f3a4eedd5bad24c2bc0283177676e17ac5abeb131a80a38ef5 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/f032221efa2df5f3a4eedd5bad24c2bc0283177676e17ac5abeb131a80a38ef5 new file mode 100644 index 0000000..9bda36b --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfFrame1Unmarshal/f032221efa2df5f3a4eedd5bad24c2bc0283177676e17ac5abeb131a80a38ef5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\b00000000000000") diff --git a/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfScanUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfScanUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/jpeg/testdata/fuzz/FuzzStartOfScanUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/mpeg4audio/adts.go b/pkg/codecs/mpeg4audio/adts.go new file mode 100644 index 0000000..8922991 --- /dev/null +++ b/pkg/codecs/mpeg4audio/adts.go @@ -0,0 +1,147 @@ +package mpeg4audio + +import ( + "fmt" +) + +// ADTSPacket is an ADTS packet. +type ADTSPacket struct { + Type ObjectType + SampleRate int + ChannelCount int + AU []byte +} + +// ADTSPackets is a group od ADTS packets. +type ADTSPackets []*ADTSPacket + +// Unmarshal decodes an ADTS stream into ADTS packets. +func (ps *ADTSPackets) Unmarshal(buf []byte) error { + // refs: https://wiki.multimedia.cx/index.php/ADTS + + bl := len(buf) + pos := 0 + + for { + if (bl - pos) < 8 { + return fmt.Errorf("invalid length") + } + + syncWord := (uint16(buf[pos]) << 4) | (uint16(buf[pos+1]) >> 4) + if syncWord != 0xfff { + return fmt.Errorf("invalid syncword") + } + + protectionAbsent := buf[pos+1] & 0x01 + if protectionAbsent != 1 { + return fmt.Errorf("CRC is not supported") + } + + pkt := &ADTSPacket{} + + pkt.Type = ObjectType((buf[pos+2] >> 6) + 1) + switch pkt.Type { + case ObjectTypeAACLC: + default: + return fmt.Errorf("unsupported audio type: %d", pkt.Type) + } + + sampleRateIndex := (buf[pos+2] >> 2) & 0x0F + switch { + case sampleRateIndex <= 12: + pkt.SampleRate = sampleRates[sampleRateIndex] + + default: + return fmt.Errorf("invalid sample rate index: %d", sampleRateIndex) + } + + channelConfig := ((buf[pos+2] & 0x01) << 2) | ((buf[pos+3] >> 6) & 0x03) + switch { + case channelConfig >= 1 && channelConfig <= 6: + pkt.ChannelCount = int(channelConfig) + + case channelConfig == 7: + pkt.ChannelCount = 8 + + default: + return fmt.Errorf("invalid channel configuration: %d", channelConfig) + } + + frameLen := int(((uint16(buf[pos+3])&0x03)<<11)| + (uint16(buf[pos+4])<<3)| + ((uint16(buf[pos+5])>>5)&0x07)) - 7 + if frameLen > MaxAccessUnitSize { + return fmt.Errorf("AU size (%d) is too big (maximum is %d)", frameLen, MaxAccessUnitSize) + } + + frameCount := buf[pos+6] & 0x03 + if frameCount != 0 { + return fmt.Errorf("frame count greater than 1 is not supported") + } + + if len(buf[pos+7:]) < frameLen { + return fmt.Errorf("invalid frame length") + } + + pkt.AU = buf[pos+7 : pos+7+frameLen] + pos += 7 + frameLen + + *ps = append(*ps, pkt) + + if (bl - pos) == 0 { + break + } + } + + return nil +} + +func (ps ADTSPackets) marshalSize() int { + n := 0 + for _, pkt := range ps { + n += 7 + len(pkt.AU) + } + return n +} + +// Marshal encodes ADTS packets into an ADTS stream. +func (ps ADTSPackets) Marshal() ([]byte, error) { + buf := make([]byte, ps.marshalSize()) + pos := 0 + + for _, pkt := range ps { + sampleRateIndex, ok := reverseSampleRates[pkt.SampleRate] + if !ok { + return nil, fmt.Errorf("invalid sample rate: %d", pkt.SampleRate) + } + + var channelConfig int + switch { + case pkt.ChannelCount >= 1 && pkt.ChannelCount <= 6: + channelConfig = pkt.ChannelCount + + case pkt.ChannelCount == 8: + channelConfig = 7 + + default: + return nil, fmt.Errorf("invalid channel count (%d)", pkt.ChannelCount) + } + + frameLen := len(pkt.AU) + 7 + + fullness := 0x07FF // like ffmpeg does + + buf[pos+0] = 0xFF + buf[pos+1] = 0xF1 + buf[pos+2] = uint8((int(pkt.Type-1) << 6) | (sampleRateIndex << 2) | ((channelConfig >> 2) & 0x01)) + buf[pos+3] = uint8((channelConfig&0x03)<<6 | (frameLen>>11)&0x03) + buf[pos+4] = uint8((frameLen >> 3) & 0xFF) + buf[pos+5] = uint8((frameLen&0x07)<<5 | ((fullness >> 6) & 0x1F)) + buf[pos+6] = uint8((fullness & 0x3F) << 2) + pos += 7 + + pos += copy(buf[pos:], pkt.AU) + } + + return buf, nil +} diff --git a/pkg/codecs/mpeg4audio/adts_test.go b/pkg/codecs/mpeg4audio/adts_test.go new file mode 100644 index 0000000..c2212c1 --- /dev/null +++ b/pkg/codecs/mpeg4audio/adts_test.go @@ -0,0 +1,124 @@ +package mpeg4audio + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var casesADTS = []struct { + name string + byts []byte + pkts ADTSPackets +}{ + { + "single", + []byte{0xff, 0xf1, 0x4c, 0x80, 0x1, 0x3f, 0xfc, 0xaa, 0xbb}, + ADTSPackets{ + { + Type: ObjectTypeAACLC, + SampleRate: 48000, + ChannelCount: 2, + AU: []byte{0xaa, 0xbb}, + }, + }, + }, + { + "multiple", + []byte{ + 0xff, 0xf1, 0x50, 0x40, 0x1, 0x3f, 0xfc, 0xaa, + 0xbb, 0xff, 0xf1, 0x4c, 0x80, 0x1, 0x3f, 0xfc, + 0xcc, 0xdd, + }, + ADTSPackets{ + { + Type: ObjectTypeAACLC, + SampleRate: 44100, + ChannelCount: 1, + AU: []byte{0xaa, 0xbb}, + }, + { + Type: ObjectTypeAACLC, + SampleRate: 48000, + ChannelCount: 2, + AU: []byte{0xcc, 0xdd}, + }, + }, + }, +} + +func TestADTSUnmarshal(t *testing.T) { + for _, ca := range casesADTS { + t.Run(ca.name, func(t *testing.T) { + var pkts ADTSPackets + err := pkts.Unmarshal(ca.byts) + require.NoError(t, err) + require.Equal(t, ca.pkts, pkts) + }) + } +} + +func TestADTSMarshal(t *testing.T) { + for _, ca := range casesADTS { + t.Run(ca.name, func(t *testing.T) { + byts, err := ca.pkts.Marshal() + require.NoError(t, err) + require.Equal(t, ca.byts, byts) + }) + } +} + +func TestADTSUnmarshalErrors(t *testing.T) { + for _, ca := range []struct { + name string + byts []byte + err string + }{ + { + "invalid length", + []byte{0x01}, + "invalid length", + }, + { + "invalid syncword", + []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, + "invalid syncword", + }, + { + "crc", + []byte{0xff, 0xF0, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, + "CRC is not supported", + }, + { + "invalid audio type", + []byte{0xff, 0xf1, 0x8c, 0x80, 0x1, 0x3f, 0xfc, 0xaa}, + "unsupported audio type: 3", + }, + { + "invalid sample rate index", + []byte{0xff, 0xf1, 0x74, 0x80, 0x1, 0x3f, 0xfc, 0xaa}, + "invalid sample rate index: 13", + }, + { + "invalid channel configuration", + []byte{0xff, 0xf1, 0x4c, 0x00, 0x1, 0x3f, 0xfc, 0xaa}, + "invalid channel configuration: 0", + }, + { + "multiple frame count", + []byte{0xff, 0xf1, 0x4c, 0x80, 0x1, 0x3f, 0xfd, 0xaa}, + "frame count greater than 1 is not supported", + }, + { + "invalid frame length", + []byte{0xff, 0xf1, 0x4c, 0x80, 0x1, 0x3f, 0xfc, 0xaa}, + "invalid frame length", + }, + } { + t.Run(ca.name, func(t *testing.T) { + var pkts ADTSPackets + err := pkts.Unmarshal(ca.byts) + require.EqualError(t, err, ca.err) + }) + } +} diff --git a/pkg/codecs/mpeg4audio/config.go b/pkg/codecs/mpeg4audio/config.go new file mode 100644 index 0000000..6ec3742 --- /dev/null +++ b/pkg/codecs/mpeg4audio/config.go @@ -0,0 +1,235 @@ +package mpeg4audio + +import ( + "fmt" + + "github.com/bluenviron/mediabase/pkg/bits" +) + +// Config is a MPEG-4 Audio configuration. +type Config struct { + Type ObjectType + SampleRate int + ChannelCount int + + // SBR / PS specific + ExtensionType ObjectType + ExtensionSampleRate int + + // AAC-LC specific + FrameLengthFlag bool + DependsOnCoreCoder bool + CoreCoderDelay uint16 +} + +// Unmarshal decodes a Config. +func (c *Config) Unmarshal(buf []byte) error { + pos := 0 + + tmp, err := bits.ReadBits(buf, &pos, 5) + if err != nil { + return err + } + c.Type = ObjectType(tmp) + + switch c.Type { + case ObjectTypeAACLC: + case ObjectTypeSBR: + case ObjectTypePS: + default: + return fmt.Errorf("unsupported object type: %d", c.Type) + } + + sampleRateIndex, err := bits.ReadBits(buf, &pos, 4) + if err != nil { + return err + } + + switch { + case sampleRateIndex <= 12: + c.SampleRate = sampleRates[sampleRateIndex] + + case sampleRateIndex == 0x0F: + tmp, err := bits.ReadBits(buf, &pos, 24) + if err != nil { + return err + } + c.SampleRate = int(tmp) + + default: + return fmt.Errorf("invalid sample rate index (%d)", sampleRateIndex) + } + + channelConfig, err := bits.ReadBits(buf, &pos, 4) + if err != nil { + return err + } + + switch { + case channelConfig == 0: + return fmt.Errorf("not yet supported") + + case channelConfig >= 1 && channelConfig <= 6: + c.ChannelCount = int(channelConfig) + + case channelConfig == 7: + c.ChannelCount = 8 + + default: + return fmt.Errorf("invalid channel configuration (%d)", channelConfig) + } + + if c.Type == ObjectTypeSBR || c.Type == ObjectTypePS { + c.ExtensionType = c.Type + extensionSamplingFrequencyIndex, err := bits.ReadBits(buf, &pos, 4) + if err != nil { + return err + } + + switch { + case extensionSamplingFrequencyIndex <= 12: + c.ExtensionSampleRate = sampleRates[extensionSamplingFrequencyIndex] + + case extensionSamplingFrequencyIndex == 0x0F: + tmp, err := bits.ReadBits(buf, &pos, 24) + if err != nil { + return err + } + c.ExtensionSampleRate = int(tmp) + + default: + return fmt.Errorf("invalid extension sample rate index (%d)", extensionSamplingFrequencyIndex) + } + + tmp, err = bits.ReadBits(buf, &pos, 5) + if err != nil { + return err + } + c.Type = ObjectType(tmp) + + if c.Type != ObjectTypeAACLC { + return fmt.Errorf("unsupported object type: %d", c.Type) + } + } + + c.FrameLengthFlag, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + c.DependsOnCoreCoder, err = bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if c.DependsOnCoreCoder { + tmp, err := bits.ReadBits(buf, &pos, 14) + if err != nil { + return err + } + c.CoreCoderDelay = uint16(tmp) + } + + extensionFlag, err := bits.ReadFlag(buf, &pos) + if err != nil { + return err + } + + if extensionFlag { + return fmt.Errorf("unsupported") + } + + return nil +} + +func (c Config) marshalSize() int { + n := 5 + 4 + 3 + + _, ok := reverseSampleRates[c.SampleRate] + if !ok { + n += 28 + } else { + n += 4 + } + + if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { + _, ok := reverseSampleRates[c.ExtensionSampleRate] + if !ok { + n += 28 + } else { + n += 4 + } + n += 5 + } else if c.DependsOnCoreCoder { + n += 14 + } + + ret := n / 8 + if (n % 8) != 0 { + ret++ + } + + return ret +} + +// Marshal encodes a Config. +func (c Config) Marshal() ([]byte, error) { + buf := make([]byte, c.marshalSize()) + pos := 0 + + if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { + bits.WriteBits(buf, &pos, uint64(c.ExtensionType), 5) + } else { + bits.WriteBits(buf, &pos, uint64(c.Type), 5) + } + + sampleRateIndex, ok := reverseSampleRates[c.SampleRate] + if !ok { + bits.WriteBits(buf, &pos, uint64(15), 4) + bits.WriteBits(buf, &pos, uint64(c.SampleRate), 24) + } else { + bits.WriteBits(buf, &pos, uint64(sampleRateIndex), 4) + } + + var channelConfig int + switch { + case c.ChannelCount >= 1 && c.ChannelCount <= 6: + channelConfig = c.ChannelCount + + case c.ChannelCount == 8: + channelConfig = 7 + + default: + return nil, fmt.Errorf("invalid channel count (%d)", c.ChannelCount) + } + bits.WriteBits(buf, &pos, uint64(channelConfig), 4) + + if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { + sampleRateIndex, ok := reverseSampleRates[c.ExtensionSampleRate] + if !ok { + bits.WriteBits(buf, &pos, uint64(0x0F), 4) + bits.WriteBits(buf, &pos, uint64(c.ExtensionSampleRate), 24) + } else { + bits.WriteBits(buf, &pos, uint64(sampleRateIndex), 4) + } + bits.WriteBits(buf, &pos, uint64(c.Type), 5) + } else { + if c.FrameLengthFlag { + bits.WriteBits(buf, &pos, 1, 1) + } else { + bits.WriteBits(buf, &pos, 0, 1) + } + + if c.DependsOnCoreCoder { + bits.WriteBits(buf, &pos, 1, 1) + } else { + bits.WriteBits(buf, &pos, 0, 1) + } + + if c.DependsOnCoreCoder { + bits.WriteBits(buf, &pos, uint64(c.CoreCoderDelay), 14) + } + } + + return buf, nil +} diff --git a/pkg/codecs/mpeg4audio/config_test.go b/pkg/codecs/mpeg4audio/config_test.go new file mode 100644 index 0000000..d6c01ff --- /dev/null +++ b/pkg/codecs/mpeg4audio/config_test.go @@ -0,0 +1,166 @@ +//go:build go1.18 +// +build go1.18 + +package mpeg4audio + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +var configCases = []struct { + name string + enc []byte + dec Config +}{ + { + "aac-lc 16khz mono", + []byte{0x14, 0x08}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 16000, + ChannelCount: 1, + }, + }, + { + "aac-lc 44.1khz mono", + []byte{0x12, 0x08}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 44100, + ChannelCount: 1, + }, + }, + { + "aac-lc 44.1khz 5.1", + []byte{0x12, 0x30}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 44100, + ChannelCount: 6, + }, + }, + { + "aac-lc 48khz stereo", + []byte{17, 144}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 48000, + ChannelCount: 2, + }, + }, + { + "aac-lc 53khz stereo", + []byte{0x17, 0x80, 0x67, 0x84, 0x10}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 53000, + ChannelCount: 2, + }, + }, + { + "aac-lc 96khz stereo delay", + []byte{0x10, 0x12, 0x0c, 0x08}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 96000, + ChannelCount: 2, + DependsOnCoreCoder: true, + CoreCoderDelay: 385, + }, + }, + { + "aac-lc 44.1khz 8 chans", + []byte{0x12, 0x38}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 44100, + ChannelCount: 8, + }, + }, + { + "sbr (he-aac v1) 44.1khz mono", + []byte{0x2b, 0x8a, 0x08, 0x00}, + Config{ + Type: ObjectTypeAACLC, + SampleRate: 22050, + ChannelCount: 1, + ExtensionSampleRate: 44100, + ExtensionType: ObjectTypeSBR, + }, + }, + { + "sbr (he-aac v1) 44.1khz stereo", + []byte{0x2b, 0x92, 0x08, 0x00}, // the data from fdk_aac + Config{ + Type: ObjectTypeAACLC, + SampleRate: 22050, + ChannelCount: 2, + ExtensionSampleRate: 44100, + ExtensionType: ObjectTypeSBR, + }, + }, + { + "ps (he-aac v2) 48khz stereo", + []byte{0xeb, 0x09, 0x88, 0x00}, // the data from fdk_aac + Config{ + Type: ObjectTypeAACLC, + SampleRate: 24000, + ChannelCount: 1, // for he_aac v2, ChannelCount only set to 1 ? + ExtensionSampleRate: 48000, + ExtensionType: ObjectTypePS, + }, + }, +} + +func TestConfigUnmarshal(t *testing.T) { + for _, ca := range configCases { + t.Run(ca.name, func(t *testing.T) { + var dec Config + err := dec.Unmarshal(ca.enc) + require.NoError(t, err) + require.Equal(t, ca.dec, dec) + }) + } +} + +func TestConfigMarshal(t *testing.T) { + for _, ca := range configCases { + t.Run(ca.name, func(t *testing.T) { + enc, err := ca.dec.Marshal() + require.NoError(t, err) + require.Equal(t, ca.enc, enc) + }) + } +} + +func TestConfigMarshalErrors(t *testing.T) { + for _, ca := range []struct { + name string + conf Config + err string + }{ + { + "invalid channel config", + Config{ + Type: ObjectTypeAACLC, + SampleRate: 44100, + ChannelCount: 0, + }, + "invalid channel count (0)", + }, + } { + t.Run(ca.name, func(t *testing.T) { + _, err := ca.conf.Marshal() + require.EqualError(t, err, ca.err) + }) + } +} + +func FuzzConfigUnmarshal(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + var conf Config + conf.Unmarshal(b) + }) +} diff --git a/pkg/codecs/mpeg4audio/mpeg4audio.go b/pkg/codecs/mpeg4audio/mpeg4audio.go new file mode 100644 index 0000000..6226118 --- /dev/null +++ b/pkg/codecs/mpeg4audio/mpeg4audio.go @@ -0,0 +1,10 @@ +// Package mpeg4audio contains utilities to work with MPEG-4 audio codecs. +package mpeg4audio + +const ( + // MaxAccessUnitSize is the maximum size of an Access Unit (AU). + MaxAccessUnitSize = 5 * 1024 + + // SamplesPerAccessUnit is the number of samples contained by a single AAC AU. + SamplesPerAccessUnit = 1024 +) diff --git a/pkg/codecs/mpeg4audio/object_type.go b/pkg/codecs/mpeg4audio/object_type.go new file mode 100644 index 0000000..7051c7f --- /dev/null +++ b/pkg/codecs/mpeg4audio/object_type.go @@ -0,0 +1,11 @@ +package mpeg4audio + +// ObjectType is a MPEG-4 Audio object type. +type ObjectType int + +// supported types. +const ( + ObjectTypeAACLC ObjectType = 2 + ObjectTypeSBR ObjectType = 5 + ObjectTypePS ObjectType = 29 +) diff --git a/pkg/codecs/mpeg4audio/sample_rates.go b/pkg/codecs/mpeg4audio/sample_rates.go new file mode 100644 index 0000000..660b86e --- /dev/null +++ b/pkg/codecs/mpeg4audio/sample_rates.go @@ -0,0 +1,33 @@ +package mpeg4audio + +var sampleRates = []int{ + 96000, + 88200, + 64000, + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000, + 7350, +} + +var reverseSampleRates = map[int]int{ + 96000: 0, + 88200: 1, + 64000: 2, + 48000: 3, + 44100: 4, + 32000: 5, + 24000: 6, + 22050: 7, + 16000: 8, + 12000: 9, + 11025: 10, + 8000: 11, + 7350: 12, +} diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/0de38b892c93cde2f2b32eeb00f6097b53b4250a097ff80e498ceb3f0bfb18e0 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/0de38b892c93cde2f2b32eeb00f6097b53b4250a097ff80e498ceb3f0bfb18e0 new file mode 100644 index 0000000..86f2599 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/0de38b892c93cde2f2b32eeb00f6097b53b4250a097ff80e498ceb3f0bfb18e0 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x102") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2407269c6f2b6741b662b2a3f8a5bb9528c50c25e5ff75ee285eb272027491b2 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2407269c6f2b6741b662b2a3f8a5bb9528c50c25e5ff75ee285eb272027491b2 new file mode 100644 index 0000000..c5cd837 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2407269c6f2b6741b662b2a3f8a5bb9528c50c25e5ff75ee285eb272027491b2 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2f1e03b45b2a93962108e8a940cc0ee647a444fa09ed6839dac31246ff1d5a19 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2f1e03b45b2a93962108e8a940cc0ee647a444fa09ed6839dac31246ff1d5a19 new file mode 100644 index 0000000..d82bac9 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/2f1e03b45b2a93962108e8a940cc0ee647a444fa09ed6839dac31246ff1d5a19 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\xef\xef") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/41b96153add60a0a300ad04393d1b16838280d9c256f3f5819ffea4dcfa87db1 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/41b96153add60a0a300ad04393d1b16838280d9c256f3f5819ffea4dcfa87db1 new file mode 100644 index 0000000..faf2f31 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/41b96153add60a0a300ad04393d1b16838280d9c256f3f5819ffea4dcfa87db1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(\x00") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/4e84166ad43e1c5846255d0155c259a95700b8fd3c3ada7d0cee9d8a99ad413f b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/4e84166ad43e1c5846255d0155c259a95700b8fd3c3ada7d0cee9d8a99ad413f new file mode 100644 index 0000000..c0584ba --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/4e84166ad43e1c5846255d0155c259a95700b8fd3c3ada7d0cee9d8a99ad413f @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(0\b") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/6962f04b357ab1240e26ab394ad6eb8127068a73f80ea005094fbe9e69874e65 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/6962f04b357ab1240e26ab394ad6eb8127068a73f80ea005094fbe9e69874e65 new file mode 100644 index 0000000..2d7d606 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/6962f04b357ab1240e26ab394ad6eb8127068a73f80ea005094fbe9e69874e65 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(00") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/bbffbee953abbb79185a8caf6831ec6ab83dcc1f3ab1d748b0abe8ed3211bcda b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/bbffbee953abbb79185a8caf6831ec6ab83dcc1f3ab1d748b0abe8ed3211bcda new file mode 100644 index 0000000..f7a5b49 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/bbffbee953abbb79185a8caf6831ec6ab83dcc1f3ab1d748b0abe8ed3211bcda @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(0") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/c12d7ec300bda22f7db490db8312dc2e64752791e45fec451533b5706f56bed9 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/c12d7ec300bda22f7db490db8312dc2e64752791e45fec451533b5706f56bed9 new file mode 100644 index 0000000..2cc8e6b --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/c12d7ec300bda22f7db490db8312dc2e64752791e45fec451533b5706f56bed9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\x101") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 new file mode 100644 index 0000000..67322c7 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/d00ea3865173809d88de52497a25b23b2568d3c08b1d2b49a1ae857b6497f223 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/d00ea3865173809d88de52497a25b23b2568d3c08b1d2b49a1ae857b6497f223 new file mode 100644 index 0000000..8cd503b --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/d00ea3865173809d88de52497a25b23b2568d3c08b1d2b49a1ae857b6497f223 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(A") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/f5da56f6a7a5431290dccfd0b7548511decda24d17c05fa7ddeccb3b0b049518 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/f5da56f6a7a5431290dccfd0b7548511decda24d17c05fa7ddeccb3b0b049518 new file mode 100644 index 0000000..f885c04 --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/f5da56f6a7a5431290dccfd0b7548511decda24d17c05fa7ddeccb3b0b049518 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte(".\xef") diff --git a/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/fca08d22f8534499db40e6510424748f46929ac0e89aca9dc59096b7c2d59dc7 b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/fca08d22f8534499db40e6510424748f46929ac0e89aca9dc59096b7c2d59dc7 new file mode 100644 index 0000000..39ccc7c --- /dev/null +++ b/pkg/codecs/mpeg4audio/testdata/fuzz/FuzzConfigUnmarshal/fca08d22f8534499db40e6510424748f46929ac0e89aca9dc59096b7c2d59dc7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("(7\xed") diff --git a/scripts/format.mk b/scripts/format.mk new file mode 100644 index 0000000..0475707 --- /dev/null +++ b/scripts/format.mk @@ -0,0 +1,10 @@ +define DOCKERFILE_FORMAT +FROM $(BASE_IMAGE) +RUN go install mvdan.cc/gofumpt@v0.3.1 +endef +export DOCKERFILE_FORMAT + +format: + echo "$$DOCKERFILE_FORMAT" | docker build -q . -f - -t temp + docker run --rm -it -v $(PWD):/s -w /s temp \ + sh -c "gofumpt -l -w ." diff --git a/scripts/lint.mk b/scripts/lint.mk new file mode 100644 index 0000000..9c73673 --- /dev/null +++ b/scripts/lint.mk @@ -0,0 +1,4 @@ +lint: + docker run --rm -v $(PWD):/app -w /app \ + $(LINT_IMAGE) \ + golangci-lint run -v diff --git a/scripts/mod-tidy.mk b/scripts/mod-tidy.mk new file mode 100644 index 0000000..b02d72a --- /dev/null +++ b/scripts/mod-tidy.mk @@ -0,0 +1,3 @@ +mod-tidy: + docker run --rm -it -v $(PWD):/s -w /s $(BASE_IMAGE) \ + sh -c "apk add git && GOPROXY=direct go mod tidy" diff --git a/scripts/test.mk b/scripts/test.mk new file mode 100644 index 0000000..3defabd --- /dev/null +++ b/scripts/test.mk @@ -0,0 +1,21 @@ +test-pkg: + go test -v -race -coverprofile=coverage-pkg.txt ./pkg/... + +test-nodocker: test-pkg + +define DOCKERFILE_TEST +FROM $(BASE_IMAGE) +RUN apk add --no-cache make git gcc musl-dev +WORKDIR /s +COPY go.mod go.sum ./ +RUN go mod download +COPY . ./ +endef +export DOCKERFILE_TEST + +test: + echo "$$DOCKERFILE_TEST" | docker build -q . -f - -t temp + docker run --rm -it \ + --name temp \ + temp \ + make test-nodocker