Why put WriteOneFrameMV() in main() in lencod.c file, while put WriteOneFrameResidue() right after encode_one_macroblock() in encode_one_slice() in the slice.c file?
1) Since img->mpr only contains one Macroblock data, so it can not be put in lencod.c like WriteOneFrameMV() where enc_picture->mv contains one frame data.
img->mpr is changed in encode_one_macroblock_low()-->LumaResidualCoding()/(Line617)-->LumaResidualCoding8x8()-->LumaPrediction(): memcpy(&(curr_mpr[j][block_x]), l0pred, block_size_x * sizeof(imgpel));
2) The best place to put WriteOneFrameResidue() is right after encode_one_macroblock() because enc_picture->imgY/enc_picture->imgUV is changed in three locations:
a) encode_one_macroblock_low()-->LumaResidualCoding()/(Line617)-->LumaResidualCoding8x8()-->pDCT_4x4()/(Line901)<-->dct_4x4()-->SampleReconstruct(): *imgOrg++ = iClip1( max_imgpel_value, rshift_rnd_sf(*m7++, dq_bits) + *imgPred++);
c) encode_one_macroblock_low()-->LumaResidualCoding()/(Line617): memcpy(&enc_picture->imgY[img->pix_y+j][img->pix_x], img->mpr[0][j], MB_BLOCK_SIZE * sizeof (imgpel));
So, we may put WriteOneFrameResidue() right after LumaResidualCoding(), however to generally support other encode_one_macroblock mrthods, we put WriteOneFrameResidue() right after encode_one_macroblock().
Why not use img->m7 as residue data ouput?
Although img->m7 is used as a temporary variable for processing residue data, but it is the never accurate residue data value. img->m7 is changed in two locations:
a) encode_one_macroblock_low()-->LumaResidualCoding()/(Line617)-->LumaResidualCoding8x8()-->ComputeResidue(): *m7++ = *imgOrg++ - *imgPred++; (where m7 has not been quantized)
b) after forward4x4() and quant_4x4(),
If there is nonzero coefficient, img->m7 is changed in inverse4x4() and the value should be rshift_rnd_sf() to get residue data as in SampleReconstruct().
If there is no nonzero coefficient, img->m7 is invalid because only predicted value is used for enc_picture->p_curr_img.
If no residue data output in the global structure, how does JM encode residue data?
The residue data is needed only after transform and quantization in H.264 decoder, so JM14.0 does not keep original residue data in global variable.
The one used for H.264 decoder is defined in img->cofAC/img->cofDC:
which are changed in quant_4x4(),<-->quant_4x4_around() (int* ACLevel = img->cofAC[b8][b4][0]; defined in dct_4x4())
which are used to be VLC coded in main()-->encode_one_frame()-->frame_picture()-->code_a_picture(frame)-->encode_one_slice()-->write_one_macroblock()-->writeMBLayer()-->writeCoeff16x16()-->writeCoeff8x8()-->writeCoeff4x4_CAVLC()
SampleReconstruct (imgpel **curImg, imgpel mpr[16][16], int img_m7[16][16], int mb_y, int mb_x, int opix_y, int opix_x, int width, int height, int max_imgpel_value, int dq_bits)
Useful Links:Rate Control and H.264: http://www.pixeltools.com/rate_control_paper.htmlJM online documents:encoder: http://iphome.hhi.de/suehring/tml/doc/lenc/html/index.html