From 4ff5b9634a6909e7016d679e93f5cfed0067cd1e Mon Sep 17 00:00:00 2001 From: axel10 Date: Sat, 2 May 2026 19:22:40 +0800 Subject: [PATCH] Fix `Packet::write*` rejecting zero-sized packets that carry side data --- src/codec/packet/packet.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/codec/packet/packet.rs b/src/codec/packet/packet.rs index f1a10843..4b3b29a3 100644 --- a/src/codec/packet/packet.rs +++ b/src/codec/packet/packet.rs @@ -17,6 +17,11 @@ impl Packet { pub unsafe fn is_empty(&self) -> bool { self.0.size == 0 } + + #[inline(always)] + fn lacks_payload_and_side_data(&self) -> bool { + self.0.size == 0 && self.0.side_data_elems == 0 + } } impl Packet { @@ -226,7 +231,9 @@ impl Packet { #[inline] pub fn write(&self, format: &mut format::context::Output) -> Result { unsafe { - if self.is_empty() { + // FFmpeg allows zero-size packets that still carry side data, such as + // FLAC encoder flush packets with AV_PKT_DATA_NEW_EXTRADATA. + if self.lacks_payload_and_side_data() { return Err(Error::InvalidData); } @@ -241,7 +248,9 @@ impl Packet { #[inline] pub fn write_interleaved(&self, format: &mut format::context::Output) -> Result<(), Error> { unsafe { - if self.is_empty() { + // Keep wrapper behavior aligned with av_interleaved_write_frame(): + // zero-size packets are still valid when they only carry side data. + if self.lacks_payload_and_side_data() { return Err(Error::InvalidData); } @@ -338,4 +347,26 @@ impl<'a> Iterator for SideDataIter<'a> { } } +#[cfg(test)] +mod tests { + use super::Packet; + + #[test] + fn empty_packet_without_side_data_is_still_empty_for_write_checks() { + let packet = Packet::empty(); + + assert!(unsafe { packet.is_empty() }); + assert!(packet.lacks_payload_and_side_data()); + } + + #[test] + fn zero_sized_packet_with_side_data_is_not_treated_as_invalid_empty_packet() { + let mut packet = Packet::empty(); + packet.0.side_data_elems = 1; + + assert!(unsafe { packet.is_empty() }); + assert!(!packet.lacks_payload_and_side_data()); + } +} + impl<'a> ExactSizeIterator for SideDataIter<'a> {}