diff --git a/io/src/main/java/org/red5/io/rtp/AV1Packetizer.java b/io/src/main/java/org/red5/io/rtp/AV1Packetizer.java index 1252a839b..a71246ff5 100644 --- a/io/src/main/java/org/red5/io/rtp/AV1Packetizer.java +++ b/io/src/main/java/org/red5/io/rtp/AV1Packetizer.java @@ -98,6 +98,15 @@ public class AV1Packetizer { // Collection of OBU Elements; each OBU Element may be a full OBU, or just a fragment of one. private List OBUElements; + // Aggregation item: Z first packet in frame is fragment + private boolean firstPacketInFrame; + + // Aggregation item: Y last packet in frame is fragment + private boolean lastPacketInFrame; + + // Aggregation item: N start sequence + private boolean startSequence; + private byte[] sequenceHeader; /** @@ -115,9 +124,9 @@ public int depacketize(byte[] payload) throws Exception { } // aggregate header byte is used to indicate if the first and/or last OBU element in the payload is a fragment // of an OBU - boolean firstPacketInFrame = OBUParser.startsWithFragment(payload[0]); // Z first packet in frame is fragment - boolean lastPacketInFrame = OBUParser.endsWithFragment(payload[0]); // Y last packet in frame is fragment - boolean startSequence = OBUParser.startsNewCodedVideoSequence(payload[0]); // N + firstPacketInFrame = OBUParser.startsWithFragment(payload[0]); // Z first packet in frame is fragment + lastPacketInFrame = OBUParser.endsWithFragment(payload[0]); // Y last packet in frame is fragment + startSequence = OBUParser.startsNewCodedVideoSequence(payload[0]); // N // obu's in the payload int obuCount = OBUParser.obuCount(payload[0]); // W logger.debug("Depacketize - first packet in frame: {}, last packet in frame: {}, start sequence: {} count: {}", firstPacketInFrame, lastPacketInFrame, startSequence, obuCount); @@ -335,12 +344,38 @@ public void reset() { OBUElements.clear(); } sequenceHeader = null; + // reset aggregation items; also done at depacketize + firstPacketInFrame = lastPacketInFrame = startSequence = false; } public List getOBUElements() { return OBUElements; } + public boolean isFirstPacketInFrame() { + return firstPacketInFrame; + } + + public void setFirstPacketInFrame(boolean firstPacketInFrame) { + this.firstPacketInFrame = firstPacketInFrame; + } + + public boolean isLastPacketInFrame() { + return lastPacketInFrame; + } + + public void setLastPacketInFrame(boolean lastPacketInFrame) { + this.lastPacketInFrame = lastPacketInFrame; + } + + public boolean isStartSequence() { + return startSequence; + } + + public void setStartSequence(boolean startSequence) { + this.startSequence = startSequence; + } + @Override public String toString() { return "AV1Packetizer [OBUElements=" + OBUElements + "]"; diff --git a/io/src/test/java/org/red5/io/obu/OBUParserTest.java b/io/src/test/java/org/red5/io/obu/OBUParserTest.java index cecadaea7..c11f93452 100644 --- a/io/src/test/java/org/red5/io/obu/OBUParserTest.java +++ b/io/src/test/java/org/red5/io/obu/OBUParserTest.java @@ -67,6 +67,19 @@ public void TestAll() throws Exception { System.err.println("Error handling AV1 payloads: " + e.getMessage()); } + // fragmented buffers from Chrome 126 - mtu 1176 + // first packet in frame: false, last packet in frame: true, start sequence: true count: 2 + byte[] chrome = IOUtils.hexStringToByteArray( + "680b0800000024c4ffdf0068023010687440c71c7116c6500000000604d80367f6c757deb25b95ece4ce58c22fd1527dd1d85f10a9880ef543f4144eb319f107306befe993447f6a19491fc40a0609f98c947c5af4dec016d216c14054a1bb81ff9555fbd1d4f373d085636bf5c30bf4ea1236afe915b7cc90bc224d1ae96c8089fa677d926e9f5270deda8b41c545ff51117eb12d9bd4a31a1dc42e6862bca79972ec014a410f26d1dd3bf08415f58b445d38e683cdeb49e6d4c677d3e3e3bd21c7d26309ba514d9cb5e3b40da43c04a1f97eafe5d52952805c5c8b54df0b3e08442851ad743218904b03413e1fdae2fa1e6b907906246311412fb4429a52428ad1a621997b8f7db3715237e417b9b069edec211fe64dca0fa247afb29944139c26050f87f5ba35147c8583dc603060773d8bc3ceaa6b9bf81f432704c4fb60a1365e62645311c8d52f5bb76a9b0ae8962c77ecdc13a378dc44b87a643b8c42ad49fe0494844db3db524d17f207729883bc387351895effbbaf689161693cf173c887d421a3454c5a857e12467618139e39b6999bf99f9103456f20b85b2e67947be501519a4469551e3d2fbe19aff32d0060167ef7ad433e1d802d092ffce569065d9fa80bf0a904038fb2fcff9c50dca3dcd4a6a3d8ae1245a8a045d9ef807b3859e0fe9a67854f68e28e02d16a3de9535f302f5f54ca06afca651ac589e0ed8dc68438f3319c8c03bdacaf6ba16b08631b74d90c9268fc724a5ff49ef0fc7a7828597e1c2ad3b5226652d792a0a18a93296356b7890c399da544b1ef43cfebd998245bc3e71ae8f117f937a4ab5fd8c3666146aa285b543de5c4e6cea142d3b4cab2f315dce647817b56edd76313940ce77727acbd0ce89c22aa56cdc24d3e2379e9fd21b35fdd0f7df1b84a14d03bf513aa6dcc7cb9df2d19d6472bd08c2ea63d76e5a6363bc3e80697381d8d758963a493de55d7311aed6e5fe9d63f13bb6bac1666b8db0c30faee5c2fbb33a78e0d6e30622c1ba104d8316085b63f7c2c87db0bac98a3e702abc1e93ece6b2e30990e3e029f5d3c775d4a685746cac2b67722f4fa3da145c12fc888daebdfd16fcf64d6814ee2cfc76956cf71787307c2dfa14b820da8769ce0900230db54cab4613cd134559aea71d5cab8900b9f0c58db602ce7ec8f5b343d60df3b5538c21ae6d8b65e42c8317e8f173ec9f8e149579b5d6ce4825a8df7e02134c336b404f542b188844efee00e83ca852c2f092c4aeaf8e7ac3e2016ffc76d2658e5e0cb136f426d094f25d7ec540755eed7f85c96b530e9a1cb572ce7c5f3fb51452b5cce4954f38cf0989d28560d6ab685acfd0a0764ef2fd833b2f8477f15819191efca08ca551921020c482b54ad4daad11515eab30fc24d86441379489e8df063d44f5aca478f512255c9ebba7e7b3cdc8af56cee02f031f84369b1dbc52c4c234b9f3feb0228d7fc22eeb576fbab10df5262aad1782402bbc4d26356d18dd1015a28d35156f544258a5f283831c110bcf41e58aeeac98b730102bdb8bb43c0a649594881818ba7be71fa75648e0b16af607db9f9c69962dedee9b178fcfb595f05fec60d2d8e6dde481076d7f9d6efc603aed002230b66f5d6671fd33233d451bb26fdf44276bfa693"); + + // first packet in frame: true, last packet in frame: true, start sequence: false count: 1 + byte[] chrome2 = IOUtils.hexStringToByteArray( + "d0338b6416d0d5ff8cd0f603ab4c0437499ce7dcf4953442cb8ecbfef39d98e9dd4f038a9775535689baed236543bfd0ea390fda2ed67eb3f00eb4c1934eeaced3db614ad0889b6b217f2f3689e52dff41f06e6f45433a96066ae70f2ee12e4cd286808655779867dc0ee8a59dbf393bd0a0350f0273187c1fcaaa2c8ec1b81812e76c7c532b7df34b5f8120d845a55e5727b42a98331164436b8be26468e3fd2fea11cfbecd8b22173eae0b0791be5fc2db1fe5917e389abf7e10686c5861baaa34d11a82f6a270e9d5ec9cf5128d428640c7280983ce76be83de19a48dfa6a41fef303bbd188086e518fea799296f674a947ae92764fce5c65cedfed5e3ebdbfd58e4d68fb778afecdf6612fbce3c65f26f96b973d676e88f4299deb1414181bf254cceb3c6ca0baf48704be28786d0b84cb5c6a4408a01da8bbd018816ab8070e8b2fabc27fc9de50e1dcf300eb2171e4401b9de54028f7e015d93595728f385ea6dca8b6bbcfe79aaf3347a761eff54b6fdff9e608d54e7b6500341ef8964fa5a008590e7aee7dc39a7e5b8ca5a3ffdb2f216ae83b3e56f9309c3bf8d5f01973b020ea26e91b8b03bee5b47501dc6994f2d0c9cb41fd3f54844a43ff9434a2ece55f43a162dd29f5955fe711d865ede95f20dd58532e92bcb30193fbea3e90abdf6e3ba9c3a54144c4bfe36454f4406ff1d7ce95a37e89de7a565961d2ac199396cdb9af76ac1c44a6726be64b5c2eb9606c4f9186c52636d19f14416a5647fb5cb65b292992063abcd1f147dd205ad78f477824ca3aefc26a399b8ba351c41c26646d03b41c421dc67fbcd4356a7b8b1916210d0b0e0d8109aa377feb5ebaff2b8181147b59f2c8d29882bd1da5fbc28533137c9bdfae882a25090bd88e1f2a7183fc89f6dde2e053d40816d65ed421997a5d132a866af31496b2e64956f6b56fac0928abd0377552447e2ca26898188e0facfb15bf6233d6fe628c08dedc56a847844519fc60cc0a0062e54f2c976a4e6dd6f687c12dde56be11bdd60bcebc7f8c4baf6361aec8f86f2d31a36459ab6adf2173c0c5f3a91db9262e61f2b34460af5593e45cffc03afb5ab830ba6938d7625e702f84075259e59742f0edcab5fab0de5435188c0927fbf188ca76cd137260c5575862b225db94cae46555adcb60e8d9af96ee6caea9bb267472b7db43bac4938cf47d45a5b1c87be8d24795e5c924c8fe587ceda53b1a60b08cc1aa69295c82b1b17f4cd7c859c223ce3b2af9f58895070882ee223d3a36078d5e275a98c19404e8fb67eed1b628da0dbe625771346baa288ca4c975e485f9919ea900da2c2547eaa67828901c2ee810024a60257d9faf65366a92a360c498524f0b36c0a46dcec6a6d1aea910e633379d1f550d65861dac2d67c71d791d6f21b0f0fed30b964433b5ff7514ec7f9e4676bdde7346818bada3f48f4900646367139d04e4098f690d6e5f8c47cf7af44fe6848a6b16b9b8909330f0d56650bd705c35ca05ba8f5637269e2b6ede71043013bbe543b14a522e8bf1ccec060939f8f1ef31927fd525dc92db9fcf66252ba8e5d59b23b860a9862f01ecd16f76e11c451373229894f548a5edf5fce3c51aa548c62517a0edb26118265059ba0515f8c0dd06c062e82c510f"); + + // first packet in frame: true, last packet in frame: false, start sequence: false count: 1 + byte[] chrome3 = IOUtils.hexStringToByteArray( + "9058075957493623f9f2678ae960ec641c940d02a4621839ebdae2f9f2b7f36462a365f3c0fd5e4f5f405f997905c16a0b9cbbf9792d55500e90fec3c377442d526c6299f668471bd34dddc74dd70506b829fdecc888a462cc931032849ea8ffd76d4bd21f74be6a3e370b24ba7502ac84bc3b2a7e90d1e0153f1a6a8a2378c85509ec5d4ed60f40a9d1a1b1e45b879d40f10fd811b269d3cd83008026fef516f7f20d367225fdc074f6e8b55d9efc456efd9f331e3d4e86ac4d08698421205590b6c1edf04f6ccc29d89b2ece52b101be4dc1005fabc6241af3c6e6635a983c41764691b591765e414bb95330dabf3f3eb8d1f3c20b56d00f1deb0d647e590697884d291642a0fcceff0c8501bec625bac4f116bc4dc2a7e54b8f0f8f065b6a2b4aa1ffae20d338b6cf4d4a556109627d3edf2b30e13b5c0925c3f86d13a01c74cb5b78c4532647927578c85561d34322547cb875978468c0968224a942edee8de3ec63159fb6d0ded4da44005e6463d38a5692ada3879d361e568ef95fa5a3ee5b6e81cd3c6bcb90dd9e93ac809b328738de8c08a0d4810354daefd92d40abf0585123fc4b3048862d8491bfa0248e4bfd62a0f37734eec5ad755684c93838205aaf8e5a37e3a6a30675db9b13f7ef1693be7c6912d5ee4f386cf1597ba74e3e16523d2c0b3fe6fe66709aa8e090efa9573912aabf23e5d8e6ca8bedf39670a5185e31b2cbb4c426841f97dc39be1322fcc5ad0581cbcccfeb2f0504bf276b1490f822337dc1c64d30d53487c2b7a6c05c11e8146fc83191fe7de089ae1cb50d2f6d892436ee75ddd49121c315424f0e806ed7319b25902f2e5a5cea40d74d49c3d254216623df2a2ec0a41fe1dc937e27b0cc1fa02f3487a36f8dbbac02b4c18b0e84959a852da8ed244eac6424fe9d2ab4a30ff305fc"); + /* // packetizing int mtu = 5;