justdan96 / tsMuxer

tsMuxer is a transport stream muxer for remuxing/muxing elementary streams, EVO/VOB/MPG, MKV/MKA, MP4/MOV, TS, M2TS to TS to M2TS. Supported video codecs H.264/AVC, H.265/HEVC, VC-1, MPEG2. Supported audio codecs AAC, AC3 / E-AC3(DD+), DTS/ DTS-HD.
Apache License 2.0
853 stars 144 forks source link

Avoid shifting by 32 bits in BitStreamWriter #602

Closed lighterowl closed 2 years ago

lighterowl commented 2 years ago

Left-shifting by an amount which is more or equal to the type's width is undefined in both C and C++. This could happen in BitStreamWriter when m_bitWrited was zero, and resulted in inconsistent results between Intel and ARM targets.

On Intel, the amount of bits to shift is explicitly masked to its lower 5 (for 32-bit values) or 6 (for 64-bit values) bits. This is documented in the instruction set reference. Effectively, the amount of bits to be shifted is the actual amount modulo 32 or 64. In this particular case, asking the CPU to shift by 32 bits left the value unchanged.

ARM does not place any requirements on the behaviour of the CPU when the amount to shift is larger than 32/64 - the instruction set reference just says that the register is supposed to be "holding a shift amount from 0 to 31 in its bottom 5 bits. ". However, MSVC documentation suggests that values in registers might appear to "wrap around" when shifting by more than 32 or 64 bits, which is indeed what was observed here.

The fix essentially amounts to emulating Intel behaviour (as it was the original development platform and presumably most assumptions were made with it in mind, even if unknowingly) by not touching the value if the amount of bits to shift is 32.