-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
has_more_rbsp_data is broken / fix trailing bits handling #28
Comments
Hmm, here's a thought. If all the readers were
I still don't see a way I'm in love with of having all the methods be trailing bit-aware. There's the seeking backward I described but that's kind of complicated. We could also have a second RBSP reader that marks the point where we're sure there's another one in the stream and compare their positions, but that's still complicated, and it doubles the RBSP decoding overhead. But maybe it's just not important to have them all be trailing bit-aware. |
Fixes dholroyd#28. DO NOT MERGE YET: depends on a locally-modified bitstream-io.
For dholroyd#28. DO NOT MERGE YET: depends on a locally-modified bitstream-io.
This is useful for querying the position within a H.264 bitstream relative to the final one bit; details in dholroyd/h264-reader#28. The default #![derive(Clone)] behavior is nice: BitReader will be Clone iff the backing std::io::Read is also Clone. Out of paranoia, I added a test that clone works properly and that it's still possible to instantiate a BitReader with a non-Clone R.
The problem
The call to
PicParameterSetExtra::read
is commented-out/broken.h264-reader/src/nal/pps.rs
Line 252 in aa5bb36
h264-reader/src/nal/pps.rs
Lines 173 to 176 in aa5bb36
I think I understand the problem now. Before I changed it,
has_more_rbsp_data
did the following:h264-reader/src/rbsp.rs
Lines 287 to 289 in c96301c
(
position
andtotal_size
are in bits. The current version is harder to read but similar in effect.)This isn't right: it says if there are more bits left in the RBSP, which sounds reasonable, but the spec says it should mean has more non-trailing bits (Rec. ITU-T H.264 (03/2010) section 7.2):
For most NALs, the trailing bits are guaranteed to be only in the last byte in the RBSP. For slice NALs, there are sometimes
cabac_zero_word
s afterward. (Seerbsp_slice_trailing_bits
, section 7.3.2.10.) In either case, it should stop at the last one bit of the RBSP.Better behavior
has_more_rbsp_data
should return the correct result on a completely-buffered non-slice NAL. Ideally it always returns the correct result, includingWouldBlock
in ambiguous cases on partially-buffered NALs.BitStreamReader
functions were aware of the trailing bits and returned EOF on hitting them, or (when parsing a partially-buffered NAL)WouldBlock
on the last one bit we know of. This might help catch bugs in parsing at least. But it doesn't seem straightforward to implement (see below).finish
method which errors if it's not positioned exactly at the trailing bits.Implementation ideas
Unfortunately
bitstream_io::BitRead
doesn't have a way to peek at the queued unaligned bits non-destructively or when unaligned to access the underlyingreader
(to check its position). Those might be reasonable feature requests, or we could usebitstream_io::BitQueue
directly.I don't see a straightforward, efficient way to just check there's still a one bit left in the stream via readahead.
edit: no, I got confused. It supports any numeric type (up tobitstream_io::BitQueue
only supports storing 32 bits, and I thinkBitReader
might be using all of that already.u128
).We could probably do this by using it directly but it might require re-implementing more ofedit 2: no, but anyway this would require unbounded lookahead, as the RBSP can have several zero bytes in a row. That's no good.BitReader
than I was hoping for.We could look backward in the RBSP to find the trailing bits position (as the spec mentions in 7.4.1.1: "identification of the end of the SODB within the NAL unit by searching the RBSP for the rbsp_stop_one_bit starting at the end of the RBSP"). It'd mean adjusting my interface proposal in #4 because getting the NAL bytes via a
BufStream
doesn't allow this. And looking backward is slightly messy on slice NALs because there can be an emulation prevention three byte in the CABAC words (see the note on H.264 7.4.2.10) and those don't count. (But we only really care about the headers of slice NALs anyway, not consuming those NALs fully, so maybe it doesn't matter.) But it's at least possible to find the right bit in the NAL bit stream. And I think we could map that intorbsp::RbspBitReader
calls doing the right thing ifbitstream_io
would just let us access the reader (to check if we've hit that NAL byte position in question) and count the number of queued bits.The
finish
method seems relatively straightforward to do without even any changes tobitstream_io::BitRead
's interface. There's aBitRead::byte_aligned
; we can get the bits until then and make sure the first is one and the rest are zero. Then we can useBitReader::into_reader
to ensure the remaining RBSP bytes (if any) are zero.The text was updated successfully, but these errors were encountered: