chromium / webm / bitstream-guide / refs/heads/ietf / . / text_src / 18.01__vp8-bitstream__bounds-on-and-adjustment-of-motion-vectors.txt

#### 18.1 Bounds on and Adjustment of Motion Vectors {#h-18-01} | |

Since each motion vector is differentially encoded from a neighboring block or macroblock and the only clamp is to ensure that the referenced motion vector represents a valid location inside a reference frame buffer, it is technically possible within the VP8 format for a block or macroblock to have arbitrarily large motion vectors, up to the size of the input image plus the extended border areas. For practical reasons, VP8 imposes a motion vector size range limit of [-4096, 4095] full pixels, regardless of image size (VP8 defines 14 raw bits for width and height; 16383x16383 is the maximum possible image size). Bitstream-compliant encoders and decoders shall enforce this limit. | |

Because the motion vectors applied to the chroma subblocks have 1/8 pixel resolution, the synthetic pixel calculation, outlined in Chapter 5 and detailed below, uses this resolution for the luma subblocks as well. In accordance, the stored luma motion vectors are all doubled, each component of each luma vector becoming an even integer in the range -2046 to +2046, inclusive. | |

The vector applied to each chroma subblock is calculated by averaging the vectors for the 4 luma subblocks occupying the same visible area as the chroma subblock in the usual correspondence, that is, the vector for U and V block 0 is the average of the vectors for the Y subblocks { 0, 1, 4, 5}, chroma block 1 corresponds to Y blocks { 2, 3, 6, 7}, chroma block 2 to Y blocks { 8, 9, 12, 13}, and chroma block 3 to Y blocks { 10, 11, 14, 15}. | |

In detail, each of the two components of the vectors for each of the chroma subblocks is calculated from the corresponding luma vector components as follows: | |

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |

int avg( int c1, int c2, int c3, int c4) | |

{ | |

int s = c1 + c2 + c3 + c4; | |

/* The shift divides by 8 (not 4) because chroma pixels | |

have twice the diameter of luma pixels. The handling | |

of negative motion vector components is slightly | |

cumbersome because, strictly speaking, right shifts | |

of negative numbers are not well-defined in C. */ | |

return s >= 0 ? (s + 4) >> 3 : -( (-s + 4) >> 3); | |

} | |

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |

{:lang="c"} | |

Furthermore, if the version number in the frame tag specifies only full-pel chroma motion vectors, then the fractional parts of both components of the vector are truncated to zero, as illustrated in the following pseudo-code (assuming 3 bits of fraction for both luma and chroma vectors): | |

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |

x = x & (~7); | |

y = y & (~7); | |

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |

{:lang="c"} | |

Earlier in this document we described the `vp8_clamp_mv()` function to limit "nearest" and "near" motion vector predictors inside specified margins within the frame boundaries. Additional clamping is performed for `NEW_MV` macroblocks, for which the final motion vector is clamped again after combining the "best" predictor and the differential vector decoded from the stream. | |

However, the secondary clamping is not performed for `SPLIT_MV` macroblocks, meaning that any subblock's motion vector within the `SPLIT_MV` macroblock may point outside the clamping zone. These non-clamped vectors are also used when determining the decoding tree context for subsequent subblocks' modes in the `vp8_mvCont()` function. | |