H.264 CAVLC: run_before > zerosLeft Table 9-10 Fix
Fix H.264 CAVLC decoding errors where run_before exceeds zerosLeft in Table 9-10. Learn validation rules, prevent negative zerosLeft, and implement compliant residual block decoding for H.264/AVC decoders.
H.264 CAVLC: Correctly applying Table 9-10 ‘run_before’ when decoded value exceeds zerosLeft
Implementing an H.264/AVC decoder (ISO/IEC 14496-10:2022) for residual data in macroblocks using CAVLC. The run_before decoding from Table 9-10 produces invalid values greater than zerosLeft, leading to negative zerosLeft.
Problem Details
runValstarts with three values: 0,0,0.zerosLeft= 12 (fromIf(totalCoeff < endIdx - startIdx + 1, total_zeros, 0)).- In the for-loop,
DecodeRunBeforereturns: 3, 13, 0. - Subtracting sequentially:
zerosLeftbecomes -4. - Finally,
runVal(totalCoeff - 1) = zerosLeft(negative value written).
In DecodeRunBefore:
- Reads bits incrementally, matches first VLC in Table 9-10, column 7.
- Failing bitstream:
0000000001→ matchesrun_before = 13(column 7), but 13 >zerosLeft = 12→ negativezerosLeft.
Relevant Code
RunBefore Table (VB.NET)
Private Shared Function Get_RunBefore_Table() As Dictionary(Of Integer, Dictionary(Of String, Integer))
Dim d As New Dictionary(Of Integer, Dictionary(Of String, Integer))()
d.Add(1, New Dictionary(Of String, Integer) From { {"1", 0}, {"0", 1} })
d.Add(2, New Dictionary(Of String, Integer) From { {"1", 0}, {"01", 1}, {"00", 2} })
d.Add(3, New Dictionary(Of String, Integer) From { {"11", 0}, {"10", 1}, {"01", 2}, {"00", 3} })
d.Add(4, New Dictionary(Of String, Integer) From { {"11", 0}, {"10", 1}, {"01", 2}, {"001", 3}, {"000", 4} })
d.Add(5, New Dictionary(Of String, Integer) From { {"11", 0}, {"10", 1}, {"011", 2}, {"010", 3}, {"001", 4}, {"000", 5} })
d.Add(6, New Dictionary(Of String, Integer) From { {"11", 0}, {"10", 1}, {"01", 2}, {"001", 3}, {"0001", 4}, {"0000", 5} })
d.Add(7, New Dictionary(Of String, Integer) From {
{"111", 0}, {"110", 1}, {"101", 2}, {"100", 3}, {"011", 4}, {"010", 5}, {"001", 6}, {"0001", 7},
{"00001", 8}, {"000001", 9}, {"0000001", 10}, {"00000001", 11}, {"000000001", 12}, {"0000000001", 13}, {"00000000001", 14}
})
Return d
End Function
DecodeRunBefore (VB.NET)
Private Function DecodeRunBefore(zerosLeft As Integer, ByRef avc_Bitstream As BitStream, nalUnit As Byte(), ByRef absoluteBitPos As UInteger) As (runBefore As Integer, success As Boolean)
Dim col As Integer
If zerosLeft <= 0 Then Return (0, True)
col = If(zerosLeft >= 7, 7, zerosLeft)
Dim runBeforeTable As Dictionary(Of Integer, Dictionary(Of String, Integer)) = Get_RunBefore_Table()
If Not runBeforeTable.ContainsKey(col) Then Return (0, False)
Dim table As Dictionary(Of String, Integer) = runBeforeTable(col)
Dim bitBuffer As String = String.Empty
Do
Dim bit As Integer = ByteTools.GetBit(nalUnit(avc_Bitstream.BytePos), avc_Bitstream.BitPos, avc_Bitstream, absoluteBitPos)
bitBuffer &= If(bit = 1, "1", "0")
If table.ContainsKey(bitBuffer) Then Return (table(bitBuffer), True)
If bitBuffer.Length > 16 Then Exit Do
Loop
Return (0, False)
End Function
Usage in DecodeResidualBlock_CAVLC (key loop)
Dim zerosLeft As Integer = If(totalCoeff < endIdx - startIdx + 1, total_zeros, 0)
Dim runVal() As Integer = New Integer(totalCoeff - 1) {}
For i As Integer = 0 To totalCoeff - 2
If zerosLeft > 0 Then
Dim res As (runBefore As Integer, success As Boolean) = DecodeRunBefore(zerosLeft, AVC_Bitstream, nalUnit, absoluteBitPos)
If Not res.success Then Throw New Exception("Invalid run_before VLC.")
runVal(i) = res.runBefore
Else
runVal(i) = 0
End If
zerosLeft -= runVal(i)
Next
runVal(totalCoeff - 1) = zerosLeft
Question
Is there a special rule in H.264 CAVLC (e.g., partial unary coding, truncation, prefix-less values) that prevents run_before > zerosLeft? How should Table 9-10 column 7 be applied correctly to avoid negative zerosLeft?
In H.264 CAVLC decoding for residual blocks, Table 9-10’s run_before values must never exceed zerosLeft—doing so signals an invalid bitstream, as your example with 13 > 12 demonstrates. The spec requires using column 7 only when zerosLeft >=7, but always validate the decoded run_before <= zerosLeft afterward to prevent negative zerosLeft. No special truncation or partial coding applies; simply reject oversized values to match compliant decoder behavior.
Contents
- H.264 CAVLC Residual Run Decoding Overview
- Role of zerosLeft in run_before Decoding
- Correct Table 9-10 Application Rules
- Validation: Preventing run_before > zerosLeft
- Updated Code Implementation
- Common Errors and Bitstream Handling
Sources
- Vcodex: H.264/AVC Context Adaptive Variable Length Coding
- Alibaba Cloud: CAVLC and CABAC Introduction
- Springer: CAVLCU GPU Implementation
- CuPDF: CAVLC Example
- Wobbly Cucumber: CAVLC Encoding Tutorial
- Google Patents: US20090316792 Decoding Method
- GitHub: h264-fer residual.cpp
Conclusion
H.264 CAVLC decoding demands strict validation after Table 9-10 lookups: run_before can’t exceed zerosLeft, or it’s a bitstream error. Fix your decoder by adding that check in DecodeRunBefore, update zerosLeft safely, and you’ll avoid negatives while staying spec-compliant. Test with conformance streams—suddenly, those edge cases like “0000000001” won’t crash your residual block parsing.