Opened 9 years ago

Closed 9 years ago

#860 closed defect (fixed)

inferSigCoeffFlag discrepancy with HM?

Reported by: Parabola Owned by: bbross
Priority: minor Milestone:
Component: Text Version: D9 (K1003) v9
Keywords: Cc: bbross, wjhan, jct-vc@…

Description

We have code with very similar structure to the draft standard pseudocode. This pseudocode in the text seems incorrect:

inferSigCoeffFlag = 0
if( ( i < lastSubBlock ) && ( i > 0 ) ) {

coded_sub_block_flag[ xS ][ yS ]
inferSigCoeffFlag = 1

}

To make our implementation agree with HM, we had to do this instead:

inferSigCoeffFlag = 0
if( ( i < lastSubBlock ) && ( i > 0 ) ) {

coded_sub_block_flag[ xS ][ yS ]
inferSigCoeffFlag = coded_sub_block_flag[ xS ][ yS ]

}

Now this could be indicative of a problem elsewhere in the draft standard description or possibly in a mistake our own implementation but we thought it worth flagging up.

Change History (7)

comment:1 Changed 9 years ago by DefaultCC Plugin

  • Cc bbross wjhan jct-vc@… added

comment:2 Changed 9 years ago by tung.nguyen

Can you specify the problem in more detail?
I don't understand the intended behaviour from the proposed change.

Best regards,
-Tung

comment:3 Changed 9 years ago by Parabola

Hello Tung,
The problem is that HM and text do not agree. At Parabola, we have decoder code that is very similar to text syntactic description and, unless we make the change described above, our code cannot parse HM bitstreams properly. If the change seems nonsensical from your point of view, I should go back and double check that there isn't some other discrepancy in our implementation causing our decoder mis-parsing when inferSigCoeffFlag is initialised to 1.
Cheers - John

comment:4 Changed 9 years ago by bbross

Hi John, I think I got the problem with inferSigCoeffFlag here. Let me describe it first before we go ahead to solve this.

Problem:

When coded_sub_block_flag is parsed, inferSigCoeffFlag is set to 1. This inferSigCoeffFlag is kicking in only at two places
Syntax: In significant_coeff_flag parsing syntax condition:
" ( coded_sub_block_flag[ xS ][ yS ] && ( n > 0 | | !inferSigCoeffFlag ) )"
where, due to the OR, it is only checked for the DC position of a sub-block (n==0)
Semantics: In significant_coeff_flag semantics when it is inferred:
"...or both of the following conditions are true, significant_coeff_flag[ xC ][ yC ] is inferred to be equal to 1.
– ( xC & 3, yC & 3 ) is equal to ( 0, 0 )
– inferSigCoeffFlag is equal to 1"
This means again for the DC of a sub-block (( xC & 3, yC & 3 ) is equal to ( 0, 0 ))


Now we can assume two cases for a sub-block not being the first or the last in scan order, i.e. coded_sub_block_flag is parsed:

  1. coded_sub_block_flag is parsed and equal to 0 -> inferSigCoeffFlag =1
  2. coded_sub_block_flag is parsed and equal to 1 -> inferSigCoeffFlag =1

Going further to the semantics of coded_sub_block_flag we get the following interpretation (already including proposed fix from #847):

  1. "If coded_sub_block_flag[ xS ][ yS ] is equal to 0, the 16 transform coefficient levels of the sub-block at location ( xS, yS ) are inferred to be equal to 0;"
  1. "– Otherwise (coded_sub_block_flag[ xS ][ yS ] is equal to 1), the following applies.
  1. a) If ( xS, yS ) is equal to ( 0, 0 ) and ( LastSignificantCoeffX, LastSignificantCoeffY ) is not equal to ( 0, 0 ), at least one of the 16 significant_coeff_flag syntax elements is present for the sub-block at location ( xS, yS ) .
  1. b) Otherwise, at least one of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) has a non zero value.

Where 2. a) does not apply in the example because it only kicks in for the first sub-block for which coded_sub_block_flag is not parsed. This leaves us with:

  1. the 16 transform coefficient levels of the sub-block at location ( xS, yS ) are inferred to be equal to 0
  2. at least one of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) has a non zero value

Lets see how this complies with the parsing of significant_coeff_flag mentioned in the beginning of the problem formulation:
"if( coded_sub_block_flag[ xS ][ yS ] && ( n > 0 | | !inferSigCoeffFlag ) ) {

significant_coeff_flag[ xC ][ yC ]
if( significant_coeff_flag[ xC ][ yC ] )

inferSigCoeffFlag = 0

}"
For or two cases we get:

  1. Since coded_sub_block_flag is equal to 0, all significant_coeff_flags are not parsed but inferred instead. Looking again at the inference rules in the significant_coeff_flag semantics, we see that for the DC, both conditions to infer significant_coeff_flag[ xC ][ yC ] to be equal to 1 are fulfilled (see above: ( xC & 3, yC & 3 ) is equal to ( 0, 0 ) and inferSigCoeffFlag is equal to 1) while for all other scan positions, significant_coeff_flag[ xC ][ yC is inferred to be equal to 0.
  1. For all sub-block scan positions except the DC, significant_coeff_flag is parsed. Depending on its value, case 1 needs to be divided into two sub-cases:
  1. a) all significant_coeff_flags parsed are equal to 0 which means that when parsing the DC (n==0), inferSigCoeffFlag is still equal to 1 and thus !inferSigCoeffFlag kicks in leading to significant_coeff_flag not being parsed but inferred instead. Looking at the inference rules in the significant_coeff_flag semantics, we see that both conditions to infer significant_coeff_flag[ xC ][ yC ] to be equal to 1 are fulfilled (see above: ( xC & 3, yC & 3 ) is equal to ( 0, 0 ) and inferSigCoeffFlag is equal to 1).
  1. b) at least one significant_coeff_flag parsed is equal to 1 which means that inferSigCoeffFlag is set equal to 0 leading to the DC significant_coeff_flag beeing parsed.

Comparing the semantics of coded_sub_block_flag with the actually parsing/inferring of significant_coeff_flags we get the following:

  1. 15 of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) are equal to 0 because all significant_coeff_flags are inferred to be equal to 0 but the DC is inferred to be at least equal to 1 (significant_coeff_flag ifor the DC is inferred to be equal to 1) -> This case does not comply with: "the 16 transform coefficient levels of the sub-block at location ( xS, yS ) are inferred to be equal to 0"
  1. a) 15 of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) are equal to 0 because all parsed significant_coeff_flags are equal to 0 but the DC is inferred to be at least equal to 1 (significant_coeff_flag ifor the DC is inferred to be equal to 1) -> This case fully complies with: "at least one of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) has a non zero value."
  1. b) At least one parsed significant_coeff_flag at a non-DC position is equal to 1 -> This case also fully complies with "at least one of the 16 transform coefficient levels of the sub-block at location ( xS, yS ) has a non zero value."

Solution:

Now that we know where the problem is, I see two ways of solving that:

  1. Your SW implementation with setting inferSigCoeffFlag = coded_sub_block_flag[ xS ][ yS ]. This change would only affect case 1. where the mismatch occurs and instead of inferring significant_coefficient_flag to be equal to 1, it is inferred to be equal to 0 because inferSigCoeffFlag is not equal to 1 anymore.
  2. Since this is a problem of syntax element inference which is typically done in semantics, I would prefer a different approach by changing significant_coeff_flag semantics where the value of the syntax element is inferred:

"...or all of the following conditions are true, significant_coeff_flag[ xC ][ yC ] is inferred to be equal to 1.
– ( xC & 3, yC & 3 ) is equal to ( 0, 0 )
– inferSigCoeffFlag is equal to 1
– coded_sub_block_flag[ xS ][ yS ] is equal to 1"
Further, during the analysis of the problem I think the name of the variable inferSigCoeffFlag is a bit misleading since it only applies to the DC (Dc) of a sub-block (Sb). Thus I would also propose to rename the variable to something like: inferSbDcSigCoeffFlag.

Wow, I guess the is the longest comment to a ticket I've ever written. Please check whether my understanding of the problem is correct as well as the suggested solution II.

comment:5 Changed 9 years ago by nnguyen

Ben, thanks for the thorough description of the problem. The inferSigCoeffFlag is meant to be used by the decoder to infer the significance of the DC of a sub-block (containing at least one non-zero coefficient) to be 1. As such, I agree with your suggested solution.

comment:6 Changed 9 years ago by Parabola

Ben, I tested your second solution in our product by changing the conditions for inferring significant_coeff_flag[ xC ][ yC ] equal to 1. On a limited set of bitstreams, it seems to work fine and is preferable to my original workaround. And I support any change of nomenclature that aids understanding of the text.

comment:7 Changed 9 years ago by bbross

  • Resolution set to fixed
  • Status changed from new to closed
Note: See TracTickets for help on using tickets.

This list contains all users that will be notified about changes made to this ticket.

These roles will be notified: Reporter, Owner, Subscriber, Participant

  • Benjamin Bross(Owner, Subscriber, Participant)
  • jct-vc@…(Subscriber)
  • John Funnell(Reporter, Participant)
  • karl.sharman@…(Always)
  • Karsten Suehring(Always)
  • Nguyen Nguyen(Participant)
  • Tung Nguyen(Participant)
  • Woo-Jin Han(Subscriber)