[x264-devel] Potential bug in transform bypass 8x8
Alain Champenois
achampen at matrox.com
Mon Jun 3 22:04:31 CEST 2013
Good day x264-dev,
I was reviewing H264 transform bypass functionality (lossless) implementation in
x264 and base on my understanding of the H264 specifications, x264 doesn't implement
I_PRED_8x8_V or I_PRED_8x8_H modes correctly.
For all intra 8x8 predictions, the spec mentions the filtered samples should be used
but x264 is using the source samples when doing I_PRED_8x8_V or I_PRED_8x8_H
modes in lossless (see detail explication below).
Here is the snippet of code from x264 macroblock.c handling 8x8 for lossless:
void x264_predict_lossless_8x8( x264_t *h, pixel *p_dst, int p, int idx, int i_mode, pixel edge[36] )
...
if( i_mode == I_PRED_8x8_V )
h->mc.copy[PIXEL_8x8]( p_dst, FDEC_STRIDE, p_src-stride, stride, 8 );
else if( i_mode == I_PRED_8x8_H )
h->mc.copy[PIXEL_8x8]( p_dst, FDEC_STRIDE, p_src-1, stride, 8 );
else
h->predict_8x8[i_mode]( p_dst, edge );
...
For I_PRED_8x8_V and I_PRED_8x8_H modes, the source samples stored in 'p_src' are used
instead of the filtered samples stored in 'edge' which is not conform with the spec.
x264 lossless streams are compatible with libavcodec because both are doing the
same implementation in this case (ie: using source samples instead of filtered
samples). I've also confirmed that CoreAvc has the same implementation as libavcodec.
On the other side, JM 18.5 implementation (encoder and decoder) does match my
understanding of the H264 spec, and when I disabled 8x8 transform during encoding
(using --no-8x8dct), x264 streams become compatible with JM decoder (lossless).
I've also tested the reverse (encoding with JM with 8x8 transform disabled and
decoding with libavcodec) and it's also working.
JM and x264/libavcodec are therefore currently compatible for lossless only when
intra 8x8 transform is disabled (tested in 420/422/444 and 8/10 bits).
The command line I used to show the problem was:
x264 --crf 0 --input-csp i420 --input-res 352x288 crowdrun_cif.yuv -o crowdrun_cif.264
but the issue can be reproduce with any YUV of 1 frame (MB intra 8x8 being very
common). The difference can be seen by decoding with JM 18.5 and comparing with
the source YUV.
Could someone confirmed that this is real issue of x264 (and livavcodec) not being
compliant with the H264 spec in transform bypass 8x8.
Regards
Alain
## Information about transform 8x8 in Rec ITU-T H.264 (01/2012)
From the spec, the 8x8 prediction is always generated with filtered version of
the neighbouring samples. This prediction is sum with the residual process to get
the reconstructed picture.
For all 8x8 luma blocks of the luma component of a macroblock with luma8x8BlkIdx= 0..3
# Intra prediction
- Get the 25 neighbouring samples p[x,y] section 8.3.2.2
- Apply filtering on p[x,y] and return in p'[x,y] section 8.3.2.2.1
- Generate the prediction from p'[x,y] and return Pred8x8L[x,y] section 8.3.2.2.2 to 8.3.2.2.10
- Output PredL=Pred8x8L from the intra prediction. section 8.3.2 (8-71)
# Transform coefficient
- PrelL as input into the transform coefficient decoding section 8.5
- if(TransformBypassModeFlag==1) section 8.5.3 item 3.
- Apply the intra residual transform-bypass decoding process
and return rij section 8.5.14
- Sum the residual to the prediction and return uij=PrelL+rij section 8.5.3 item 5. (8-303)
- Do the picture reconstruction prior to the deblocking
process with uij section 8.5.13
More information about the x264-devel
mailing list