< draft-bankoski-vp8-bitstream-00.txt   draft-bankoski-vp8-bitstream-01.txt >
Network Working Group J. Bankoski Network Working Group J. Bankoski
Internet-Draft P. Wilkins Internet-Draft P. Wilkins
Intended status: Informational Y. Xu Intended status: Informational Y. Xu
Expires: July 10, 2011 Google, Inc. Expires: September 12, 2011 Google, Inc.
January 6, 2011 March 11, 2011
VP8 Data Format and Decoding Guide VP8 Data Format and Decoding Guide
draft-bankoski-vp8-bitstream-00 draft-bankoski-vp8-bitstream-01
Abstract Abstract
This document describes the VP8 compressed video data format created This document describes the VP8 compressed video data format,
by Google On2, together with a discussion of the decoding procedure together with a discussion of the decoding procedure for the format.
for this format.
Status of this Memo Status of this Memo
This Internet-Draft is submitted in full conformance with the This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at http://datatracker.ietf.org/drafts/current/. Drafts is at http://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on July 10, 2011. This Internet-Draft will expire on September 12, 2011.
Copyright Notice Copyright Notice
Copyright (c) 2011 IETF Trust and the persons identified as the Copyright (c) 2011 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of (http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. to this document.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 5
2. Format Overview . . . . . . . . . . . . . . . . . . . . . . . 6 2. Format Overview . . . . . . . . . . . . . . . . . . . . . . . 7
3. Compressed Frame Types . . . . . . . . . . . . . . . . . . . 8 3. Compressed Frame Types . . . . . . . . . . . . . . . . . . . 9
4. Overview of Compressed Data Format . . . . . . . . . . . . . 9 4. Overview of Compressed Data Format . . . . . . . . . . . . . 10
5. Overview of the Decoding Process . . . . . . . . . . . . . . 11 5. Overview of the Decoding Process . . . . . . . . . . . . . . 12
6. Description of Algorithms . . . . . . . . . . . . . . . . . . 16 6. Description of Algorithms . . . . . . . . . . . . . . . . . . 17
7. Boolean Entropy Decoder . . . . . . . . . . . . . . . . . . . 19 7. Boolean Entropy Decoder . . . . . . . . . . . . . . . . . . . 20
7.1. Underlying Theory of Coding . . . . . . . . . . . . . . . 20 7.1. Underlying Theory of Coding . . . . . . . . . . . . . . 21
7.2. Practical Algorithm Description . . . . . . . . . . . . . 21 7.2. Practical Algorithm Description . . . . . . . . . . . . 22
7.3. Actual Implementation . . . . . . . . . . . . . . . . . . 23 7.3. Actual Implementation . . . . . . . . . . . . . . . . . 24
8. Compressed Data Components . . . . . . . . . . . . . . . . . 28 8. Compressed Data Components . . . . . . . . . . . . . . . . . 29
8.1. Tree Coding Implementation . . . . . . . . . . . . . . . 30 8.1. Tree Coding Implementation . . . . . . . . . . . . . . . 31
8.2. Tree Coding Example . . . . . . . . . . . . . . . . . . . 31 8.2. Tree Coding Example . . . . . . . . . . . . . . . . . . 32
9. Frame Header . . . . . . . . . . . . . . . . . . . . . . . . 34 9. Frame Header . . . . . . . . . . . . . . . . . . . . . . . . 35
9.1. Uncompressed Data Chunk . . . . . . . . . . . . . . . . . 34 9.1. Uncompressed Data Chunk . . . . . . . . . . . . . . . . 35
9.2. Color Space and Pixel Type (Key Frames-only) . . . . . . 37 9.2. Color Space and Pixel Type (Key Frames-only) . . . . . . 38
9.3. Segment-based Adjustments . . . . . . . . . . . . . . . . 37 9.3. Segment-based Adjustments . . . . . . . . . . . . . . . 38
9.4. Loop Filter Type and Levels . . . . . . . . . . . . . . . 38 9.4. Loop Filter Type and Levels . . . . . . . . . . . . . . 39
9.5. Token Partition and Partition Data Offsets . . . . . . . 39 9.5. Token Partition and Partition Data Offsets . . . . . . . 40
9.6. Dequantization Indices . . . . . . . . . . . . . . . . . 40 9.6. Dequantization Indices . . . . . . . . . . . . . . . . . 41
9.7. Refresh Golden Frame and AltRef Frame . . . . . . . . . . 41 9.7. Refresh Golden Frame and AltRef Frame . . . . . . . . . 42
9.8. Refresh Last Frame Buffer . . . . . . . . . . . . . . . . 43 9.8. Refresh Last Frame Buffer . . . . . . . . . . . . . . . 43
9.9. DCT Coefficient Probability Update . . . . . . . . . . . 43 9.9. DCT Coefficient Probability Update . . . . . . . . . . . 43
9.10. Remaining Frame Header Data (non-Key Frame) . . . . . . . 43 9.10. Remaining Frame Header Data (non-Key Frame) . . . . . . 44
9.11. Remaining Frame Header Data (Key Frame) . . . . . . . . . 44 9.11. Remaining Frame Header Data (Key Frame) . . . . . . . . 45
10. Segment-based Feature Adjustments . . . . . . . . . . . . . . 45 10. Segment-based Feature Adjustments . . . . . . . . . . . . . . 46
11. Key Frame Macroblock Prediction Records . . . . . . . . . . . 46 11. Key Frame Macroblock Prediction Records . . . . . . . . . . . 47
11.1. mb_skip_coeff . . . . . . . . . . . . . . . . . . . . . . 46 11.1. mb_skip_coeff . . . . . . . . . . . . . . . . . . . . . 47
11.2. Luma Modes . . . . . . . . . . . . . . . . . . . . . . . 46 11.2. Luma Modes . . . . . . . . . . . . . . . . . . . . . . . 47
11.3. Subblock Mode Contexts . . . . . . . . . . . . . . . . . 49 11.3. Subblock Mode Contexts . . . . . . . . . . . . . . . . . 50
11.4. Chroma Modes . . . . . . . . . . . . . . . . . . . . . . 50 11.4. Chroma Modes . . . . . . . . . . . . . . . . . . . . . . 51
11.5. Subblock Mode Probability Table . . . . . . . . . . . . . 51 11.5. Subblock Mode Probability Table . . . . . . . . . . . . 52
12. Intraframe Prediction . . . . . . . . . . . . . . . . . . . . 55 12. Intraframe Prediction . . . . . . . . . . . . . . . . . . . . 56
12.1. mb_skip_coeff . . . . . . . . . . . . . . . . . . . . . . 55 12.1. mb_skip_coeff . . . . . . . . . . . . . . . . . . . . . 56
12.2. Chroma Prediction . . . . . . . . . . . . . . . . . . . . 56 12.2. Chroma Prediction . . . . . . . . . . . . . . . . . . . 57
12.3. Luma Prediction . . . . . . . . . . . . . . . . . . . . . 58 12.3. Luma Prediction . . . . . . . . . . . . . . . . . . . . 59
13. DCT Coefficient Decoding . . . . . . . . . . . . . . . . . . 64 13. DCT Coefficient Decoding . . . . . . . . . . . . . . . . . . 66
13.1. MB Without non-Zero Coefficient Values . . . . . . . . . 64 13.1. MB Without non-Zero Coefficient Values . . . . . . . . . 66
13.2. Coding of Individual Coefficient Values . . . . . . . . . 65 13.2. Coding of Individual Coefficient Values . . . . . . . . 67
13.3. Token Probabilities . . . . . . . . . . . . . . . . . . . 67 13.3. Token Probabilities . . . . . . . . . . . . . . . . . . 69
13.4. Token Probability Updates . . . . . . . . . . . . . . . . 71 13.4. Token Probability Updates . . . . . . . . . . . . . . . 73
13.5. Default Token Probability Table . . . . . . . . . . . . . 76 13.5. Default Token Probability Table . . . . . . . . . . . . 78
14. DCT and WHT Inversion and Macroblock Reconstruction . . . . . 81 14. DCT and WHT Inversion and Macroblock Reconstruction . . . . . 83
14.1. Dequantization . . . . . . . . . . . . . . . . . . . . . 81 14.1. Dequantization . . . . . . . . . . . . . . . . . . . . . 83
14.2. Inverse Transforms . . . . . . . . . . . . . . . . . . . 82 14.2. Inverse Transforms . . . . . . . . . . . . . . . . . . . 84
14.3. Implementation of the WHT Inversion . . . . . . . . . . . 83 14.3. Implementation of the WHT Inversion . . . . . . . . . . 85
14.4. Implementation of the DCT Inversion . . . . . . . . . . . 85 14.4. Implementation of the DCT Inversion . . . . . . . . . . 87
14.5. Summation of Predictor and Residue . . . . . . . . . . . 88 14.5. Summation of Predictor and Residue . . . . . . . . . . . 90
15. Loop Filter . . . . . . . . . . . . . . . . . . . . . . . . . 89 15. Loop Filter . . . . . . . . . . . . . . . . . . . . . . . . . 91
15.1. Filter Geometry and Overall Procedure . . . . . . . . . . 90 15.1. Filter Geometry and Overall Procedure . . . . . . . . . 92
15.2. Simple Filter . . . . . . . . . . . . . . . . . . . . . . 92 15.2. Simple Filter . . . . . . . . . . . . . . . . . . . . . 94
15.3. Normal Filter . . . . . . . . . . . . . . . . . . . . . . 96 15.3. Normal Filter . . . . . . . . . . . . . . . . . . . . . 98
15.4. Calculation of Control Parameters . . . . . . . . . . . . 101 15.4. Calculation of Control Parameters . . . . . . . . . . . 103
16. Interframe Macroblock Prediction Records . . . . . . . . . . 103 16. Interframe Macroblock Prediction Records . . . . . . . . . . 105
16.1. Intra-Predicted Macroblocks . . . . . . . . . . . . . . . 103 16.1. Intra-Predicted Macroblocks . . . . . . . . . . . . . . 105
16.2. Inter-Predicted Macroblocks . . . . . . . . . . . . . . . 104 16.2. Inter-Predicted Macroblocks . . . . . . . . . . . . . . 106
16.3. Mode and Motion Vector Contexts . . . . . . . . . . . . . 105 16.3. Mode and Motion Vector Contexts . . . . . . . . . . . . 107
16.4. Split Prediction . . . . . . . . . . . . . . . . . . . . 111 16.4. Split Prediction . . . . . . . . . . . . . . . . . . . . 113
17. Motion Vector Decoding . . . . . . . . . . . . . . . . . . . 115 17. Motion Vector Decoding . . . . . . . . . . . . . . . . . . . 117
17.1. Coding of Each Component . . . . . . . . . . . . . . . . 115 17.1. Coding of Each Component . . . . . . . . . . . . . . . . 117
17.2. Probability Updates . . . . . . . . . . . . . . . . . . . 117 17.2. Probability Updates . . . . . . . . . . . . . . . . . . 119
18. Interframe Prediction . . . . . . . . . . . . . . . . . . . . 120 18. Interframe Prediction . . . . . . . . . . . . . . . . . . . . 122
18.1. Bounds on and Adjustment of Motion Vectors . . . . . . . 120 18.1. Bounds on and Adjustment of Motion Vectors . . . . . . . 122
18.2. Prediction Subblocks . . . . . . . . . . . . . . . . . . 121 18.2. Prediction Subblocks . . . . . . . . . . . . . . . . . . 123
18.3. Sub-pixel Interpolation . . . . . . . . . . . . . . . . . 122 18.3. Sub-pixel Interpolation . . . . . . . . . . . . . . . . 124
18.4. Filter Properties . . . . . . . . . . . . . . . . . . . . 125 18.4. Filter Properties . . . . . . . . . . . . . . . . . . . 127
19. Annex A: Bitstream Syntax . . . . . . . . . . . . . . . . . . 128 19. Annex A: Bitstream Syntax . . . . . . . . . . . . . . . . . . 130
19.1. Uncompressed Data Chunk . . . . . . . . . . . . . . . . . 128 19.1. Uncompressed Data Chunk . . . . . . . . . . . . . . . . 130
19.2. Frame Header . . . . . . . . . . . . . . . . . . . . . . 130 19.2. Frame Header . . . . . . . . . . . . . . . . . . . . . . 132
19.3. Macroblock Data . . . . . . . . . . . . . . . . . . . . . 142 19.3. Macroblock Data . . . . . . . . . . . . . . . . . . . . 144
20. License . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 20. Patent License . . . . . . . . . . . . . . . . . . . . . . . 148
21. Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . 148 21. Attachment One: Reference Decoder Source Code . . . . . . . . 149
22. References . . . . . . . . . . . . . . . . . . . . . . . . . 149 21.1. bit_ops.h . . . . . . . . . . . . . . . . . . . . . . . 149
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 150 21.2. bool_decoder.h . . . . . . . . . . . . . . . . . . . . . 149
21.3. dequant_data.h . . . . . . . . . . . . . . . . . . . . . 153
21.4. dixie.c . . . . . . . . . . . . . . . . . . . . . . . . 153
21.5. dixie.h . . . . . . . . . . . . . . . . . . . . . . . . 165
21.6. dixie_loopfilter.c . . . . . . . . . . . . . . . . . . . 172
21.7. dixie_loopfilter.h . . . . . . . . . . . . . . . . . . . 184
21.8. idct_add.c . . . . . . . . . . . . . . . . . . . . . . . 184
21.9. idct_add.h . . . . . . . . . . . . . . . . . . . . . . . 188
21.10. mem.h . . . . . . . . . . . . . . . . . . . . . . . . . 188
21.11. modemv.c . . . . . . . . . . . . . . . . . . . . . . . . 190
21.12. modemv.h . . . . . . . . . . . . . . . . . . . . . . . . 205
21.13. modemv_data.h . . . . . . . . . . . . . . . . . . . . . 205
21.14. predict.c . . . . . . . . . . . . . . . . . . . . . . . 210
21.15. predict.h . . . . . . . . . . . . . . . . . . . . . . . 240
21.16. tokens.c . . . . . . . . . . . . . . . . . . . . . . . . 240
21.17. tokens.h . . . . . . . . . . . . . . . . . . . . . . . . 250
21.18. vp8_prob_data.h . . . . . . . . . . . . . . . . . . . . 259
21.19. vpx_codec_internal.h . . . . . . . . . . . . . . . . . . 268
21.20. vpx_decoder.h . . . . . . . . . . . . . . . . . . . . . 278
21.21. vpx_integer.h . . . . . . . . . . . . . . . . . . . . . 285
22. References . . . . . . . . . . . . . . . . . . . . . . . . . 288
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 289
1. Introduction 1. Introduction
IMPORTANT NOTE: Portions of this document contain mathematical This document describes the VP8 compressed video data format,
expressions, code blocks and other non-narrative content that may not together with a discussion of the decoding procedure for the format.
render suitably in the text-only RFC format. Formatted versions of It is intended to be used in conjunction with and as a guide to the
this document's content is available at http://www.webmproject.org/. reference decoder source code provided in Attachment One. If there
are any conflicts between this narrative and the reference source
* * *
This document describes the VP8 compressed video data format created
by Google On2, together with a discussion of the decoding procedure
for this format. It is intended to be used in conjunction with and
as a guide to the reference decoder provided by Google On2. If there
are any conflicts between this document and the reference source
code, the reference source code should be considered correct. The code, the reference source code should be considered correct. The
bitstream is defined by the reference source code and not this bitstream is defined by the reference source code and not this
document. narrative.
Like many modern video compression schemes, VP8 is based on Like many modern video compression schemes, VP8 is based on
decomposition of frames into square subblocks of pixels, prediction decomposition of frames into square subblocks of pixels, prediction
of such subblocks using previously constructed blocks, and adjustment of such subblocks using previously constructed blocks, and adjustment
of such predictions (as well as synthesis of unpredicted blocks) of such predictions (as well as synthesis of unpredicted blocks)
using a discrete cosine transform (hereafter abbreviated as DCT). In using a discrete cosine transform (hereafter abbreviated as DCT). In
one special case, however, VP8 uses a "Walsh-Hadamard" (hereafter one special case, however, VP8 uses a "Walsh-Hadamard" transform
abbreviated as WHT) transform instead of a DCT. (hereafter abbreviated as WHT) instead of a DCT.
Roughly speaking, such systems reduce datarate by exploiting the Roughly speaking, such systems reduce datarate by exploiting the
temporal and spatial coherence of most video signals. It is more temporal and spatial coherence of most video signals. It is more
efficient to specify the location of a visually similar portion of a efficient to specify the location of a visually similar portion of a
prior frame than it is to specify pixel values. The frequency prior frame than it is to specify pixel values. The frequency
segregation provided by the DCT and WHT facilitate the exploitation segregation provided by the DCT and WHT facilitate the exploitation
of both spatial coherence in the original signal and the tolerance of of both spatial coherence in the original signal and the tolerance of
the human visual system to moderate losses of fidelity in the the human visual system to moderate losses of fidelity in the
reconstituted signal. reconstituted signal.
skipping to change at page 6, line 21 skipping to change at page 7, line 21
course exactly twice the coordinates of the corresponding chroma course exactly twice the coordinates of the corresponding chroma
pixels. When we refer to pixels or pixel distances without pixels. When we refer to pixels or pixel distances without
specifying a plane, we are implicitly referring to the Y plane or to specifying a plane, we are implicitly referring to the Y plane or to
the complete image, both of which have the same (full) resolution. the complete image, both of which have the same (full) resolution.
As is usually the case, the pixels are simply a large array of bytes As is usually the case, the pixels are simply a large array of bytes
stored in rows from top to bottom, each row being stored from left to stored in rows from top to bottom, each row being stored from left to
right. This "left to right" then "top to bottom" raster-scan order right. This "left to right" then "top to bottom" raster-scan order
is reflected in the layout of the compressed data as well. is reflected in the layout of the compressed data as well.
Provision has been made for the support of two different YUV color Provision has been made in the VP8 bitstream header for the support
formats in the VP8 bitstream header, however only one format is of a secondary YUV color format, in the form of a reserved bit.
supported in the first release of VP8.
The YUV formats differ in terms of their conversion to and from RGB
color space. The first corresponds to the traditional YUV color
space similar to the YCrCb color space defined in ITU-R BT.601. The
second (currently unsupported) format corresponds to a new YUV color
space whose digital conversion to and from RGB can be implemented
without multiplications and divides. The VP8 Decoder should decode
and pass the information on to the processes that convert the YUV
output to RGB color space.
Occasionally, at very low datarates, a compression system may decide Occasionally, at very low datarates, a compression system may decide
to reduce the resolution of the input signal to facilitate efficient to reduce the resolution of the input signal to facilitate efficient
compression. The VP8 data format supports this via optional compression. The VP8 data format supports this via optional
upscaling of its internal reconstruction buffer prior to output (this upscaling of its internal reconstruction buffer prior to output (this
is completely distinct from the optional postprocessing discussed is completely distinct from the optional postprocessing discussed
earlier, which has nothing to do with decoding per se). This earlier, which has nothing to do with decoding per se). This
upsampling restores the video frames to their original resolution. upsampling restores the video frames to their original resolution.
In other words, the compression/decompression system can be viewed as In other words, the compression/decompression system can be viewed as
a "black box", where the input and output is always at a given a "black box", where the input and output is always at a given
skipping to change at page 14, line 12 skipping to change at page 15, line 12
corrected with the DCT/WHT residue), a filtering step (the loop corrected with the DCT/WHT residue), a filtering step (the loop
filter) is applied to the entire frame. The purpose of the loop filter) is applied to the entire frame. The purpose of the loop
filter is to reduce blocking artifacts at the boundaries between filter is to reduce blocking artifacts at the boundaries between
macroblocks and between subblocks of the macroblocks. The term loop macroblocks and between subblocks of the macroblocks. The term loop
filter is used because this filter is part of the "coding loop," that filter is used because this filter is part of the "coding loop," that
is, it affects the reconstructed frame buffers that are used to is, it affects the reconstructed frame buffers that are used to
predict ensuing frames. This is distinguished from the predict ensuing frames. This is distinguished from the
postprocessing filters discussed earlier which affect only the viewed postprocessing filters discussed earlier which affect only the viewed
video and do not "feed into" subsequent frames. video and do not "feed into" subsequent frames.
Next, if signaled in the data, the current frame (or individual Next, if signaled in the data, the current frame may replace the
macroblocks within the current frame) may replace the golden frame golden frame prediction buffer and/or the altref frame buffer.
prediction buffer and/or the altref frame buffer.
The halos of the frame buffers are next filled as specified above. The halos of the frame buffers are next filled as specified above.
Finally, at least as far as decoding is concerned, the (references Finally, at least as far as decoding is concerned, the (references
to) the "current" and "last" frame buffers should be exchanged in to) the "current" and "last" frame buffers should be exchanged in
preparation for the next frame. preparation for the next frame.
Various processes may be required (or desired) before viewing the Various processes may be required (or desired) before viewing the
generated frame. As discussed in the frame dimension information generated frame. As discussed in the frame dimension information
below, truncation and/or upscaling of the frame may be required. below, truncation and/or upscaling of the frame may be required.
Some playback systems may require a different frame format (RGB, Some playback systems may require a different frame format (RGB,
skipping to change at page 16, line 18 skipping to change at page 17, line 18
source code, is to specify a platform-independent procedure for the source code, is to specify a platform-independent procedure for the
decoding and reconstruction of a VP8 video stream, many (small) decoding and reconstruction of a VP8 video stream, many (small)
algorithms must be described exactly. algorithms must be described exactly.
Due to its near-universality, terseness, ability to easily describe Due to its near-universality, terseness, ability to easily describe
calculation at specific precisions, and the fact that On2's reference calculation at specific precisions, and the fact that On2's reference
VP8 decoder is written in C, these algorithm fragments are written VP8 decoder is written in C, these algorithm fragments are written
using the C programming language, augmented with a few simple using the C programming language, augmented with a few simple
definitions below. definitions below.
The standard (and best) reference for C is The C Programming The standard (and best) reference for C is [Kernighan].
Language, written by Brian W. Kernighan and Dennis M. Ritchie, and
published by Prentice-Hall.
Many code fragments will be presented in this document. Some will be Many code fragments will be presented in this document. Some will be
nearly identical to corresponding sections of the reference decoder; nearly identical to corresponding sections of the reference decoder;
others will differ. Roughly speaking, there are three reasons for others will differ. Roughly speaking, there are three reasons for
such differences: such differences:
1. For reasons of efficiency, the reference decoder version may be 1. For reasons of efficiency, the reference decoder version may be
less obvious. less obvious.
2. The reference decoder often uses large data structures to 2. The reference decoder often uses large data structures to
skipping to change at page 17, line 45 skipping to change at page 18, line 45
VP8 represents probabilities as unsigned 8-bit numbers. */ VP8 represents probabilities as unsigned 8-bit numbers. */
typedef uint8 Prob; typedef uint8 Prob;
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
We occasionally need to discuss mathematical functions involving We occasionally need to discuss mathematical functions involving
honest-to-goodness "infinite precision" real numbers. The DCT is honest-to-goodness "infinite precision" real numbers. The DCT is
first described via the cosine function cos; the ratio of the lengths first described via the cosine function cos; the ratio of the lengths
of the circumference and diameter of a circle is denoted pi; at one of the circumference and diameter of a circle is denoted pi; at one
point, we take a (base 1//2) logarithm denoted log; and pow( x, y) point, we take a (base 1/2) logarithm denoted log; and pow( x, y)
denotes x raised to the power y. If x = 2 and y is a small non- denotes x raised to the power y. If x = 2 and y is a small non-
negative integer, pow( 2, y) may be expressed in C as 1 << y. negative integer, pow( 2, y) may be expressed in C as 1 << y.
Finally, we sometimes need to divide signed integers by powers of Finally, we sometimes need to divide signed integers by powers of
two, that is, we occasionally right-shift signed numbers. The two, that is, we occasionally right-shift signed numbers. The
behavior of such shifts (i.e., the propagation of the sign bit) is, behavior of such shifts (i.e., the propagation of the sign bit) is,
perhaps surprisingly, not defined by the C language itself and is perhaps surprisingly, not defined by the C language itself and is
left up to individual compilers. Because of the utility of this left up to individual compilers. Because of the utility of this
frequently needed operation, it is at least arguable that it should frequently needed operation, it is at least arguable that it should
be defined by the language (to naturally propagate the sign bit) and, be defined by the language (to naturally propagate the sign bit) and,
skipping to change at page 19, line 28 skipping to change at page 20, line 28
compress a sequence of bools for which the probability of their being compress a sequence of bools for which the probability of their being
zero or one can be well-estimated (via constant or previously-coded zero or one can be well-estimated (via constant or previously-coded
information) at the time they are written, using identical information) at the time they are written, using identical
corresponding probabilities at the time they are read. corresponding probabilities at the time they are read.
As the reader is probably aware, if a bool is much more likely to be As the reader is probably aware, if a bool is much more likely to be
zero than one (for instance), it can, on average, be faithfully zero than one (for instance), it can, on average, be faithfully
encoded using much less than one bit per value. The bool_encoder encoded using much less than one bit per value. The bool_encoder
exploits this. exploits this.
In the 1940s, Claude Shannon proved that there is a lower bound for In the 1940s, [Shannon] proved that there is a lower bound for the
the average datarate of a faithful encoding of a sequence of bools average datarate of a faithful encoding of a sequence of bools (whose
(whose probability distributions are known and are independent of probability distributions are known and are independent of each
each other) and also that there are encoding algorithms that other) and also that there are encoding algorithms that approximate
approximate this lower bound as closely as one wishes. this lower bound as closely as one wishes.
If we encode a sequence of bools whose probability of being zero is p If we encode a sequence of bools whose probability of being zero is p
(and whose probability of being 1 is 1-p), the lowest possible (and whose probability of being 1 is 1-p), the lowest possible
datarate per value is datarate per value is
plog(p) + (1-p)log(1-p); plog(p) + (1-p)log(1-p);
taking the logarithms to the base 1//2 expresses the datarate in taking the logarithms to the base 1/2 expresses the datarate in bits/
bits/value. value.
We give two simple examples. At one extreme, if p=1//2, then log(p) We give two simple examples. At one extreme, if p=1/2, then log(p) =
= log(1-p) = 1 and the lowest possible datarate per bool is 1//2 + log(1-p) = 1 and the lowest possible datarate per bool is 1/2 + 1/2 =
1//2 = 1, that is, we cannot do any better than simply literally 1, that is, we cannot do any better than simply literally writing out
writing out bits. At another extreme, if p is very small, say p=1// bits. At another extreme, if p is very small, say p=1/1024, then
1024, then log(p)=10, log(1-p) is roughly .0014, and the lowest log(p)=10, log(1-p) is roughly .0014, and the lowest possible
possible datarate is approximately 10//1024 + .0014, roughly 1/100 of datarate is approximately 10/1024 + .0014, roughly 1/100 of a bit per
a bit per bool. bool.
Because most of the bools in the VP8 datastream have zero- Because most of the bools in the VP8 datastream have zero-
probabilities nowhere near 1//2, the compression provided by the probabilities nowhere near 1/2, the compression provided by the
bool_encoder is critical to the performance of VP8. bool_encoder is critical to the performance of VP8.
The bool coder used by VP8 is a variant of an arithmetic coder. An The bool coder used by VP8 is a variant of an arithmetic coder. An
excellent discussion of arithmetic coding (and other lossless excellent discussion of arithmetic coding (and other lossless
compression techniques) can be found in the book Text Compression by compression techniques) can be found in [Bell].
Timothy C. Bell, John G. Cleary, and Ian H. Witten, published in 1990
by Prentice-Hall.
7.1. Underlying Theory of Coding 7.1. Underlying Theory of Coding
The basic idea used by the bool coder is to consider the entire data The basic idea used by the bool coder is to consider the entire data
stream (either of the partitions in our case) as the binary expansion stream (either of the partitions in our case) as the binary expansion
of a single number x with 0 <= x < 1. The bits (or bytes) in x are of a single number x with 0 <= x < 1. The bits (or bytes) in x are
of course written from high to low order and if b[j] (B[j]) is the of course written from high to low order and if b[j] (B[j]) is the
j^(th) bit (byte) in the partition, the value x is simply the sum j^(th) bit (byte) in the partition, the value x is simply the sum
(starting with j = 1) of pow(2, -j) * b[j] or pow(256, -j) * B[j]. (starting with j = 1) of pow(2, -j) * b[j] or pow(256, -j) * B[j].
skipping to change at page 21, line 31 skipping to change at page 22, line 29
must be expressed at finite precision and, second, that the decoder must be expressed at finite precision and, second, that the decoder
be able to detect each individual modification to the value interval be able to detect each individual modification to the value interval
via examination of a fixed amount of input. As a practical matter, via examination of a fixed amount of input. As a practical matter,
many of the implementation details stem from the fact that the coder many of the implementation details stem from the fact that the coder
can function using only a small "window" to incrementally read or can function using only a small "window" to incrementally read or
write the arbitrarily precise number x. write the arbitrarily precise number x.
7.2. Practical Algorithm Description 7.2. Practical Algorithm Description
VP8's bool coder works with 8-bit probabilities p. The range of such VP8's bool coder works with 8-bit probabilities p. The range of such
p is 0 <= p <= 255; the actual probability represented by p is p is 0 <= p <= 255; the actual probability represented by p is p/256.
p//256. Also, the coder is designed so that decoding of a bool Also, the coder is designed so that decoding of a bool requires no
requires no more than an 8-bit comparison and so that the state of more than an 8-bit comparison and so that the state of both the
both the encoder and decoder can be easily represented using a small encoder and decoder can be easily represented using a small number of
number of unsigned 16-bit integers. unsigned 16-bit integers.
The details are most easily understood if we first describe the The details are most easily understood if we first describe the
algorithm using bit-at-a-time input and output. Aside from the algorithm using bit-at-a-time input and output. Aside from the
ability to maintain a position in this bitstream and write/read bits, ability to maintain a position in this bitstream and write/read bits,
the encoder also needs the ability to add 1 to the bits already the encoder also needs the ability to add 1 to the bits already
output; after writing n bits, adding 1 to the existing output is the output; after writing n bits, adding 1 to the existing output is the
same thing as adding pow( 2, -n) to x. same thing as adding pow( 2, -n) to x.
Together with the bit position, the encoder must maintain two Together with the bit position, the encoder must maintain two
unsigned 8-bit numbers which we call "bottom" and "range". Writing w unsigned 8-bit numbers which we call bottom and range. Writing w for
for the n bits already written and S = pow( 2, - n - 8) for the scale the n bits already written and S = pow( 2, - n - 8) for the scale of
of the current bit position one byte out, we have the following the current bit position one byte out, we have the following
constraint on all future values v of w (including the final value v = constraint on all future values v of w (including the final value v =
x): x):
w + ( S * "bottom" ) <= v < w + ( S * ( "bottom" + "range" ) ) w + ( S * bottom ) <= v < w + ( S * ( bottom + range ) )
Thus, appending "bottom" to the already-written bits w gives the left
endpoint of the interval of possible values, appending "bottom" + Thus, appending bottom to the already-written bits w gives the left
"range" gives the right endpoint, "range" itself (scaled to the endpoint of the interval of possible values, appending bottom + range
current output position) is the length of the interval. gives the right endpoint, range itself (scaled to the current output
position) is the length of the interval.
So that our probabilistic encodings are reasonably accurate, we do So that our probabilistic encodings are reasonably accurate, we do
not let "range" vary by more than a factor of two: It stays within not let range vary by more than a factor of two: It stays within the
the bounds 128 <= "range" <= 255. bounds 128 <= range <= 255.
The process for encoding a boolean value "val" whose probability of The process for encoding a boolean value val whose probability of
being zero is "prob" / 256 -- and whose probability of being one is ( being zero is prob / 256 -- and whose probability of being one is (
256 - "prob" ) / 256 -- with 1 <= "prob" <= 255 is as follows. 256 - prob ) / 256 -- with 1 <= prob <= 255 is as follows.
Using an unsigned 16-bit multiply followed by an unsigned right Using an unsigned 16-bit multiply followed by an unsigned right
shift, we calculate an unsigned 8-bit "split" value: shift, we calculate an unsigned 8-bit split value:
split = 1 + ((("range" - 1) * "probability")]] >> 8) split = 1 + (((range - 1) * probability)]] >> 8)
"split" is approximately ( "prob" / 256 ) * "range" and lies within split is approximately ( prob / 256 ) * range and lies within the
the bounds 1 <= "split" <= "range" - 1. These bounds ensure the bounds 1 <= split <= range - 1. These bounds ensure the correctness
correctness of the decoding procedure described below. of the decoding procedure described below.
If "val" is false, we leave the left interval endpoint "bottom" alone If the incoming boolean val to be encoded is false, we leave the left
and reduce "range", replacing it by "split". If "val" is true, we interval endpoint bottom alone and reduce range, replacing it by
move up the left endpoint to "bottom" + "split", propagating any split. If the incoming val is true, we move up the left endpoint to
carry to the already-written value "w" (this is where we need the bottom + split, propagating any carry to the already-written value w
ability to add 1 to "w"), and reduce "range" to "range" - "split". (this is where we need the ability to add 1 to w), and reduce range
to range - split.
Regardless of the value encoded, "range" has been reduced and now has Regardless of the value encoded, range has been reduced and now has
the bounds 1 <= "range" <= 254. If "range" < 128, the encoder the bounds 1 <= range <= 254. If range < 128, the encoder doubles it
doubles it and shifts the high-order bit out of "bottom" to the and shifts the high-order bit out of bottom to the output as it also
output as it also doubles "bottom", repeating this process one bit at doubles bottom, repeating this process one bit at a time until 128 <=
a time until 128 <= "range" <= 255. Once this is completed, the range <= 255. Once this is completed, the encoder is ready to accept
encoder is ready to accept another bool, maintaining the constraints another bool, maintaining the constraints described above.
described above.
After encoding the last bool, the partition may be completed by After encoding the last bool, the partition may be completed by
appending "bottom" to the bitstream. appending bottom to the bitstream.
The decoder mimics the state of the encoder. It maintains, together The decoder mimics the state of the encoder. It maintains, together
with an input bit position, two unsigned 8-bit numbers, a "range" with an input bit position, two unsigned 8-bit numbers, a range
identical to that maintained by the encoder and a "value". Decoding identical to that maintained by the encoder and a value. Decoding
one bool at a time, the decoder (in effect) tracks the same left one bool at a time, the decoder (in effect) tracks the same left
interval endpoint as does the encoder and subtracts it from the interval endpoint as does the encoder and subtracts it from the
remaining input. Appending the unread portion of the bitstream to remaining input. Appending the unread portion of the bitstream to
the 8-bit "value" gives the difference between the actual value the 8-bit value gives the difference between the actual value encoded
encoded and the known left endpoint. and the known left endpoint.
The decoder is initialized by setting "range" = 255 and reading the The decoder is initialized by setting range = 255 and reading the
first 16 input bits into "value". The decoder maintains "range" and first 16 input bits into value. The decoder maintains range and
calculates "split" in exactly the same way as does the encoder. calculates split in exactly the same way as does the encoder.
To decode a bool, it compares "value" to "split"; if "value" < To decode a bool, it compares value to split; if value < split, the
"split", the bool is zero, and "range" is replaced with "split". If bool is zero, and range is replaced with split. If value >= split,
"value" >= "split", the bool is one, "range" is replaced with "range" the bool is one, range is replaced with range - split, and value is
- "split", and "value" is replaced with "value" - "split". replaced with value - split.
Again, "range" is doubled one bit at a time until it is at least 128. Again, range is doubled one bit at a time until it is at least 128.
The "value" is doubled in parallel, shifting a new input bit into the The value is doubled in parallel, shifting a new input bit into the
"bottom" each time. bottom each time.
Writing "Value" for "value" together with the unread input bits and Writing Value for value together with the unread input bits and Range
"Range" for "range" extended indefinitely on the right by zeros, the for range extended indefinitely on the right by zeros, the condition
condition "Value" < "Range" is maintained at all times by the Value < Range is maintained at all times by the decoder. In
decoder. In particular, the bits shifted out of "value" as it is particular, the bits shifted out of value as it is doubled are always
doubled are always zero. zero.
7.3. Actual Implementation 7.3. Actual Implementation
The C code below gives complete implementations of the encoder and The C code below gives complete implementations of the encoder and
decoder described above. While they are logically identical to the decoder described above. While they are logically identical to the
"bit-at-a-time" versions, they internally buffer a couple of extra "bit-at-a-time" versions, they internally buffer a couple of extra
bytes of the bitstream. This allows I/O to be done (more bytes of the bitstream. This allows I/O to be done (more
practically) a byte at a time and drastically reduces the number of practically) a byte at a time and drastically reduces the number of
carries the encoder has to propagate into the already-written data. carries the encoder has to propagate into the already-written data.
skipping to change at page 25, line 4 skipping to change at page 25, line 50
e->range <<= 1; e->range <<= 1;
if( e->bottom & (1 << 31)) /* detect carry */ if( e->bottom & (1 << 31)) /* detect carry */
add_one_to_output( e->output); add_one_to_output( e->output);
e->bottom <<= 1; /* before shifting bottom */ e->bottom <<= 1; /* before shifting bottom */
if( !--e->bit_count) { /* write out high byte of bottom ... */ if( !--e->bit_count) { /* write out high byte of bottom ... */
*e->output++ = (uint8) (e->bottom >> 24); *e->output++ = (uint8) (e->bottom >> 24);
e->bottom &= (1 << 24) - 1; /* ... keeping low 3 bytes */
e->bottom &= (1 << 24) - 1; /* ... keeping low 3 bytes */
e->bit_count = 8; /* 8 shifts until next output */ e->bit_count = 8; /* 8 shifts until next output */
} }
} }
} }
/* Call this function (exactly once) after encoding the last /* Call this function (exactly once) after encoding the last
bool value for the partition being written */ bool value for the partition being written */
void flush_bool_encoder( bool_encoder *e) void flush_bool_encoder( bool_encoder *e)
{ {
skipping to change at page 25, line 40 skipping to change at page 26, line 38
} }
/* Decoder state exactly parallels that of the encoder. /* Decoder state exactly parallels that of the encoder.
"value", together with the remaining input, equals the "value", together with the remaining input, equals the
complete encoded number x less the left endpoint of the complete encoded number x less the left endpoint of the
current coding interval. */ current coding interval. */
typedef struct { typedef struct {
uint8 *input; /* pointer to next compressed data byte */ uint8 *input; /* pointer to next compressed data byte */
uint32 range; /* always identical to encoder's range */ uint32 range; /* always identical to encoder's range */
uint32 value; /* contains at least 24 significant bits */ uint32 value; /* contains at least 8 significant bits */
int bit_count; /* # of bits shifted out of int bit_count; /* # of bits shifted out of
value, at most 7 */ value, at most 7 */
} bool_decoder; } bool_decoder;
/* Call this function before reading any bools from the /* Call this function before reading any bools from the
partition.*/ partition.*/
void init_bool_decoder( bool_decoder *d, uint8 *start_partition) void init_bool_decoder( bool_decoder *d, uint8 *start_partition)
{ {
{ {
int i = 0; int i = 0;
d->value = 0; /* value = first 24 input bytes */ d->value = 0; /* value = first 2 input bytes */
while( ++i <= 24) while( ++i <= 2)
d->value = (d->value << 8) | *start_partition++; d->value = (d->value << 8) | *start_partition++;
} }
d->input = start_partition; /* ptr to next byte to be read */ d->input = start_partition; /* ptr to next byte to be read */
d->range = 255; /* initial range is full */ d->range = 255; /* initial range is full */
d->bit_count = 0; /* have not yet shifted out any bits */ d->bit_count = 0; /* have not yet shifted out any bits */
} }
/* Main function reads a bool encoded at probability prob/256, /* Main function reads a bool encoded at probability prob/256,
which of course must agree with the probability used when the which of course must agree with the probability used when the
skipping to change at page 28, line 20 skipping to change at page 29, line 20
describe here. describe here.
We sometimes use these descriptions in C expressions within data We sometimes use these descriptions in C expressions within data
format specifications. In this context, they refer to the return format specifications. In this context, they refer to the return
value of a call to an appropriate bool_decoder d, reading (as always) value of a call to an appropriate bool_decoder d, reading (as always)
from its current reference point. from its current reference point.
+--------------+-------+--------------------------------------------+ +--------------+-------+--------------------------------------------+
| Call | Alt. | Return | | Call | Alt. | Return |
+--------------+-------+--------------------------------------------+ +--------------+-------+--------------------------------------------+
| Bool(p) | B(p) | Bool with probability p of being 0. | | Bool(p) | B(p) | Bool with probability p/256 of being 0. |
| | | Abbreviated B(p). Return value of | | | | Return value of read_bool(d, p). |
| | | read_bool(d, p). |
| | | | | | | |
| Flag | F | A one-bit flag (same thing as a B(128) or | | Flag | F | A one-bit flag (same thing as a B(128) or |
| | | an L(1)). Abbreviated F. Return value of | | | | an L(1)). Abbreviated F. Return value of |
| | | read_bool(d, 128). | | | | read_bool(d, 128). |
| | | | | | | |
| Lit(n) | L(n) | Unsigned n-bit number encoded as n flags | | Lit(n) | L(n) | Unsigned n-bit number encoded as n flags |
| | | (a "literal"). Abbreviated L(n). The bits | | | | (a "literal"). Abbreviated L(n). The bits |
| | | are read from high to low order. Return | | | | are read from high to low order. Return |
| | | value of read_literal(d, n). | | | | value of read_literal(d, n). |
| | | | | | | |
skipping to change at page 37, line 18 skipping to change at page 38, line 18
| Field | Value | | Field | Value |
+-------+------------------------------------------+ +-------+------------------------------------------+
| L(1) | 1-bit color space type specification | | L(1) | 1-bit color space type specification |
| | | | | |
| L(1) | 1-bit pixel value clamping specification | | L(1) | 1-bit pixel value clamping specification |
+-------+------------------------------------------+ +-------+------------------------------------------+
The color space type bit is encoded as the following: The color space type bit is encoded as the following:
o 0 - YUV color space similar to the YCrCb color space defined in o 0 - YUV color space similar to the YCrCb color space defined in
ITU-R BT.601 [ITU-R_BT.601]
o 1 - YUV color space whose digital conversion to RGB does not
involve multiplication and division
It should be noted that in either case, the actual conversion between
YUV and RGB is not part of this specification.
Note: In the initial release of VP8 only color space type 0 is o 1 - Reserved for future use
supported.
The pixel value clamping type bit is encoded as the following: The pixel value clamping type bit is encoded as the following:
o 0 - Decoders are required to clamp the reconstructed pixel values o 0 - Decoders are required to clamp the reconstructed pixel values
to between 0 and 255 (inclusive). to between 0 and 255 (inclusive).
o 1 - Reconstructed pixel values are guaranteed to be between 0 and o 1 - Reconstructed pixel values are guaranteed to be between 0 and
255, no clamping is necessary. 255, no clamping is necessary.
Information in this subsection does not appear in interframes. Information in this subsection does not appear in interframes.
skipping to change at page 37, line 51 skipping to change at page 38, line 44
This subsection contains probability and value information for This subsection contains probability and value information for
implementing segment adaptive adjustments to default decoder implementing segment adaptive adjustments to default decoder
behaviors. The data in this section is used in the decoding of the behaviors. The data in this section is used in the decoding of the
ensuing per-segment information and applies to the entire frame. ensuing per-segment information and applies to the entire frame.
When segment adaptive adjustments are enabled, each macroblock will When segment adaptive adjustments are enabled, each macroblock will
be assigned a segment ID. Macroblocks with the same segment ID be assigned a segment ID. Macroblocks with the same segment ID
belong to same segment, and have the same adaptive adjustments over belong to same segment, and have the same adaptive adjustments over
default baseline values for the frame. The adjustments can be default baseline values for the frame. The adjustments can be
quantization level or loop filter strength. quantization level or loop filter strength.
The context for decoding this feature is provided by section B of the The context for decoding this feature at macroblock level is provided
frame header. It contains: by a subsection in the frame header, which contains::
1. A segmentation_enabled Flag which if 1 (0), enables (disables) 1. A segmentation_enabled Flag which if 1 (0), enables (disables)
the feature for this frame. The remaining fields occur if the the feature for this frame. The remaining fields occur if the
feature is enabled. feature is enabled.
2. L(1) indicates if the segment map is updated for the current 2. L(1) indicates if the segment map is updated for the current
frame (update_mb_segmentaton_map) frame (update_mb_segmentaton_map)
3. L(1) indicates if the segment feature data items are updated for 3. L(1) indicates if the segment feature data items are updated for
the current frame the current frame
skipping to change at page 41, line 22 skipping to change at page 42, line 4
flag is true */ flag is true */
y2ac_delta = F? delta(): 0; /* Y2 ac delta specified if y2ac_delta = F? delta(): 0; /* Y2 ac delta specified if
flag is true */ flag is true */
uvdc_delta = F? delta(): 0; /* chroma dc delta specified uvdc_delta = F? delta(): 0; /* chroma dc delta specified
if flag is true */ if flag is true */
uvac_delta = F? delta(): 0; /* chroma ac delta specified uvac_delta = F? delta(): 0; /* chroma ac delta specified
if flag is true */ if flag is true */
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
Where delta() is the process to read 5 bits from the bitstream to Where delta() is the process to read 5 bits from the bitstream to
determine a signed delta value: determine a signed delta value:
+-------+--------------------------------------------------+ +-------+--------------------------------------------------+
| Index | Description | | Index | Description |
+-------+--------------------------------------------------+ +-------+--------------------------------------------------+
| L(4) | Magnitude of delta | | L(4) | Magnitude of delta |
| | | | | |
| L(1) | Sign of delta, 0 for positive and 1 for negative | | L(1) | Sign of delta, 0 for positive and 1 for negative |
+-------+--------------------------------------------------+ +-------+--------------------------------------------------+
9.7. Refresh Golden Frame and AltRef Frame 9.7. Refresh Golden Frame and AltRef Frame
For key frames, both golden frame and altref frame are refreshed/ For key frames, both golden frame and altref frame are refreshed/
replaced by the current reconstructed frame, by default. For non-key replaced by the current reconstructed frame, by default. For non-key
frames, VP8 uses two bits to indicate whether the two frame buffers frames, VP8 uses two bits to indicate whether the two frame buffers
are refreshed, using the reconstructed current frame: are refreshed, using the reconstructed current frame:
+-------+-----------------------------------------------------------+ +-------+----------------------------------------------------------+
| Index | Description | | Index | Description |
+-------+-----------------------------------------------------------+ +-------+----------------------------------------------------------+
| L(1) | Whether golden frame is refreshed (0 complete. This flag | | L(1) | Whether golden frame is refreshed (0 for no, 1 for yes). |
| | does not occur for no, 1 for yes). | | | |
| | | | L(1) | Whether altref frame is refreshed (0 for no, 1 for yes). |
| L(1) | Whether altref frame is refreshed (0 for no, 1 for yes). | +-------+----------------------------------------------------------+
+-------+-----------------------------------------------------------+
When the flag for golden frame is 0, VP8 uses 2 more bits in the When the flag for golden frame is 0, VP8 uses 2 more bits in the
bitstream to indicate whether the buffer (and which buffer) is copied bitstream to indicate whether the buffer (and which buffer) is copied
to the golden frame, or if no buffer is copied: to the golden frame, or if no buffer is copied:
+-------+------------------------------------------+ +-------+------------------------------------------+
| Index | Description | | Index | Description |
+-------+------------------------------------------+ +-------+------------------------------------------+
| L(2) | Buffer copy flag for golden frame buffer | | L(2) | Buffer copy flag for golden frame buffer |
+-------+------------------------------------------+ +-------+------------------------------------------+
skipping to change at page 48, line 38 skipping to change at page 49, line 38
intra_bmode; intra_bmode;
/* Coding tree for the above, with implied codings as comments */ /* Coding tree for the above, with implied codings as comments */
const tree_index bmode_tree [2 * (num_intra_bmodes - 1)] = const tree_index bmode_tree [2 * (num_intra_bmodes - 1)] =
{ {
-B_DC_PRED, 2, /* B_DC_PRED = "0" */ -B_DC_PRED, 2, /* B_DC_PRED = "0" */
-B_TM_PRED, 4, /* B_TM_PRED = "10" */ -B_TM_PRED, 4, /* B_TM_PRED = "10" */
-B_VE_PRED, 6, /* B_VE_PRED = "110" */ -B_VE_PRED, 6, /* B_VE_PRED = "110" */
8, 12, 8, 12,
-B_HE_PRED, 10, /* B_HE_PRED = "1110" */ -B_HE_PRED, 10, /* B_HE_PRED = "11100" */
-B_RD_PRED, -B_VR_PRED, /* B_RD_PRED = "111100", -B_RD_PRED, -B_VR_PRED, /* B_RD_PRED = "111010",
B_VR_PRED = "111101" */ B_VR_PRED = "111011" */
-B_LD_PRED, 14, /* B_LD_PRED = "111110" */ -B_LD_PRED, 14, /* B_LD_PRED = "111110" */
-B_VL_PRED, 16 /* B_VL_PRED = "1111110" */ -B_VL_PRED, 16 /* B_VL_PRED = "1111110" */
-B_HD_PRED, -B_HU_PRED /* HD = "11111110", -B_HD_PRED, -B_HU_PRED /* HD = "11111110",
HU = "11111111" */ HU = "11111111" */
}; };
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
The first four modes are smaller versions of the similarly-named The first four modes are smaller versions of the similarly-named
16x16 modes above, albeit with slightly different numbering. The 16x16 modes above, albeit with slightly different numbering. The
skipping to change at page 57, line 23 skipping to change at page 58, line 23
Because the summands are all valid pixels, no "clamp" is necessary in Because the summands are all valid pixels, no "clamp" is necessary in
the calculation of DCvalue. the calculation of DCvalue.
The remaining "True Motion" (TM_PRED) chroma mode gets its name from The remaining "True Motion" (TM_PRED) chroma mode gets its name from
an older technique of video compression used by On2 Technologies, to an older technique of video compression used by On2 Technologies, to
which it bears some relation. In addition to the row "A" and column which it bears some relation. In addition to the row "A" and column
"L", TM_PRED uses the pixel "P" above and to the left of the chroma "L", TM_PRED uses the pixel "P" above and to the left of the chroma
block. block.
In this mode, we propagate the horizontal differences between pixels The following figure gives an example of how TM_PRED works:
in A (starting from P), using the pixels from L to start each row.
The exact algorithm is as follows. ---- Begin code block --------------------------------------
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| P | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L0 | X00 | X01 | X02 | X03 | X04 | X05 | X06 | X07 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L1 | X10 | X11 | X12 | X13 | X14 | X15 | X16 | X17 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L2 | X20 | X21 | X22 | X23 | X24 | X25 | X26 | X27 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L3 | X30 | X31 | X32 | X33 | X34 | X35 | X36 | X37 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L4 | X40 | X41 | X42 | X43 | X44 | X45 | X46 | X47 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L5 | X50 | X51 | X52 | X53 | X54 | X55 | X56 | X57 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L6 | X60 | X61 | X62 | X63 | X64 | X65 | X66 | X67 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| L7 | X70 | X71 | X72 | X73 | X74 | X75 | X76 | X77 |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|
---- End code block ----------------------------------------
Where P, As and Ls represent reconstructed pixel values from
previously coded blocks, and X00 through X77 represent predicted
values for the current block. TM_PRED uses the following equation to
calculate X_ij:
X_ij = L_i + A_j - P (i, j=0, 1, 2, 3)
The exact algorithm is as follows:
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
void TMpred( void TMpred(
Pixel b[8][8], /* chroma (U or V) prediction block */ Pixel b[8][8], /* chroma (U or V) prediction block */
const Pixel A[8], /* row of already-constructed pixels const Pixel A[8], /* row of already-constructed pixels
above block */ above block */
const Pixel L[8], /* column of "" just to the left of const Pixel L[8], /* column of "" just to the left of
block */ block */
const Pixel P /* pixel just to the left of A and const Pixel P /* pixel just to the left of A and
skipping to change at page 59, line 10 skipping to change at page 60, line 40
macroblock, the four "extra" prediction pixels in A above and to the macroblock, the four "extra" prediction pixels in A above and to the
right of B have not yet actually been constructed. right of B have not yet actually been constructed.
Subblocks 7, 11, and 15 are affected. All three of these subblocks Subblocks 7, 11, and 15 are affected. All three of these subblocks
use the same extra pixels as does subblock 3 (at the upper right use the same extra pixels as does subblock 3 (at the upper right
corner of the macroblock), namely the 4 pixels immediately above and corner of the macroblock), namely the 4 pixels immediately above and
to the right of subblock 3. Writing (R,C) for a frame buffer to the right of subblock 3. Writing (R,C) for a frame buffer
position offset from the upper left corner of the current macroblock position offset from the upper left corner of the current macroblock
by R rows and C columns, the extra pixels for all the right-edge by R rows and C columns, the extra pixels for all the right-edge
subblocks (3, 7, 11, and 15) are at positions (-1,16), (-1,17), subblocks (3, 7, 11, and 15) are at positions (-1,16), (-1,17),
(-1,18), and (-1,19). (-1,18), and (-1,19). For the right-most macroblock in each
macroblock row except the top row, the extra pixels shall use the
same value as the pixel at position (-1, 15), which is the right-most
visible pixel on the line immediately above the macroblock row. For
the top macroblock row, all the extra pixels assume a value of 127.
The details of the prediction modes are most easily described in The details of the prediction modes are most easily described in
code. code.
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* Result pixels are often averages of two or three predictor /* Result pixels are often averages of two or three predictor
pixels. The following subroutines are used to calculate pixels. The following subroutines are used to calculate
these averages. Because the arguments are valid pixels, no these averages. Because the arguments are valid pixels, no
clamping is necessary. An actual implementation would clamping is necessary. An actual implementation would
skipping to change at page 81, line 18 skipping to change at page 83, line 18
After decoding the DCTs/WHTs as described above, each (quantized) After decoding the DCTs/WHTs as described above, each (quantized)
coefficient in each subblock is multiplied by one of six coefficient in each subblock is multiplied by one of six
dequantization factors, the choice of factor depending on the plane dequantization factors, the choice of factor depending on the plane
(Y2, Y, or chroma) and position (DC = coefficient zero, AC = any (Y2, Y, or chroma) and position (DC = coefficient zero, AC = any
other coefficient). If the current macroblock has overridden the other coefficient). If the current macroblock has overridden the
quantization level (as described in Chapter 10) then the six factors quantization level (as described in Chapter 10) then the six factors
are looked up from two dequantization tables with appropriate scaling are looked up from two dequantization tables with appropriate scaling
and clamping using the single index supplied by the override. and clamping using the single index supplied by the override.
Otherwise, the frame-level dequantization factors (as described in Otherwise, the frame-level dequantization factors (as described in
Section 9.6 are used. In either case, the multiplies are computed Section 9.6) are used. In either case, the multiplies are computed
and stored using 16-bit signed integers. and stored using 16-bit signed integers.
The two dequantization tables, which may also be found in the The two dequantization tables, which may also be found in the
reference decoder file quant_common.c, are as follows. reference decoder file quant_common.c, are as follows.
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
static const int dc_qlookup[QINDEX_RANGE] = static const int dc_qlookup[QINDEX_RANGE] =
{ {
4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15,
skipping to change at page 83, line 22 skipping to change at page 85, line 22
arrays (that is, a 16x16 Y buffer and two 8x8 chroma buffers). arrays (that is, a 16x16 Y buffer and two 8x8 chroma buffers).
Regarding the inverse DCT implementation given below, this requires a Regarding the inverse DCT implementation given below, this requires a
simple adjustment to the address calculation for the resulting simple adjustment to the address calculation for the resulting
residue pixels. residue pixels.
14.3. Implementation of the WHT Inversion 14.3. Implementation of the WHT Inversion
As previously discussed (see Chapters 2 and 13), for macroblocks As previously discussed (see Chapters 2 and 13), for macroblocks
encoded using prediction modes other than B_PRED and SPLITMV, the DC encoded using prediction modes other than B_PRED and SPLITMV, the DC
values derived from the DCT transform on the 16 Y blocks are values derived from the DCT transform on the 16 Y blocks are
collected to construct a 25th block of a macroblock(16 Y, 4 U, 4 V collected to construct a 25th block of a macroblock (16 Y, 4 U, 4 V
constitute the 24 blocks). This 25th block is transformed using a constitute the 24 blocks). This 25th block is transformed using a
Walsh-Hadamard transform (WHT). Walsh-Hadamard transform (WHT).
The inputs to the inverse WHT (that is, the dequantized The inputs to the inverse WHT (that is, the dequantized
coefficients), the intermediate "horizontally detransformed" signal, coefficients), the intermediate "horizontally detransformed" signal,
and the completely detransformed residue signal are all stored as and the completely detransformed residue signal are all stored as
arrays of 16-bit signed integers. arrays of 16-bit signed integers.
Following the tradition of specifying bitstream format using the Following the tradition of specifying bitstream format using the
decoding process, we specify the inverse WHT in the decoding process decoding process, we specify the inverse WHT in the decoding process
skipping to change at page 85, line 40 skipping to change at page 87, line 40
"C" source code. "C" source code.
The reference decoder WHT inversion may be found in the files The reference decoder WHT inversion may be found in the files
invtrans.c and idctllm.c. invtrans.c and idctllm.c.
14.4. Implementation of the DCT Inversion 14.4. Implementation of the DCT Inversion
All of the DCT inversions are computed in exactly the same way. In All of the DCT inversions are computed in exactly the same way. In
principle, VP8 uses a classical 2D inverse discrete cosine transform, principle, VP8 uses a classical 2D inverse discrete cosine transform,
implemented as two passes of 1-D inverse DCT. The 1-D inverse DCT implemented as two passes of 1-D inverse DCT. The 1-D inverse DCT
was calculated using a similar algorithm to what was described in the was calculated using a similar algorithm to what was described in
paper "Practical Fast 1-D DCT Algorithms with 11 Multiplications" by [Loeffler]. However, the paper only provided the 8-point and 16-
Loeffler, Lightenberg and Moschytz. However, the paper only provided point version of the algorithms, which was adapted by On2 to perform
the 8-point and 16-point version of the algorithms, which was adapted the 4-point 1-D DCT.
by On2 to perform the 4-point 1-D DCT.
Accurate calculation of 1-D DCT of the above algorithm requires Accurate calculation of 1-D DCT of the above algorithm requires
infinite precision. VP8 of course can use only a finite-precision infinite precision. VP8 of course can use only a finite-precision
approximation. Also, the inverse DCT used by VP8 takes care of approximation. Also, the inverse DCT used by VP8 takes care of
normalization of the standard unitary transform, that is, every normalization of the standard unitary transform, that is, every
dequantized coefficient has roughly double the size of the dequantized coefficient has roughly double the size of the
corresponding unitary coefficient. However, at all but the highest corresponding unitary coefficient. However, at all but the highest
datarates, the discrepancy between transmitted and ideal coefficients datarates, the discrepancy between transmitted and ideal coefficients
is due almost entirely to (lossy) compression and not to errors is due almost entirely to (lossy) compression and not to errors
induced by finite-precision arithmetic. induced by finite-precision arithmetic.
skipping to change at page 91, line 46 skipping to change at page 93, line 46
In step 1, for each of the three blocks MY, MU, and MV, we filter In step 1, for each of the three blocks MY, MU, and MV, we filter
each of the (16 luma or 8 chroma) segments straddling the column each of the (16 luma or 8 chroma) segments straddling the column
separating the block from the block immediately to the left of it, separating the block from the block immediately to the left of it,
using the inter-macroblock filter and controls associated to the using the inter-macroblock filter and controls associated to the
loop_filter_level and sharpness_level. loop_filter_level and sharpness_level.
In step 4, we filter across the (three luma and one each for U and V) In step 4, we filter across the (three luma and one each for U and V)
vertical subblock edges described above, this time using the inter- vertical subblock edges described above, this time using the inter-
subblock filter and controls. subblock filter and controls.
Step 2 and 4 are skipped for macroblocks that satisfy the following Step 2 and 4 are skipped for macroblocks that satisfy both of the
two conditions: following two conditions:
1. Macroblock coding mode is neither B_PRED nor SPLTMV; 1. Macroblock coding mode is neither B_PRED nor SPLTMV; and
2. There is no DCT coefficient coded for the whole macroblock. 2. There is no DCT coefficient coded for the whole macroblock.
For these macroblocks, loop filtering for edges between subblocks For these macroblocks, loop filtering for edges between subblocks
internal to a macroblock is effectively skipped. This skip strategy internal to a macroblock is effectively skipped. This skip strategy
significantly reduces VP8 loop-filtering complexity. significantly reduces VP8 loop-filtering complexity.
Edges between macroblocks and those between subblocks are treated Edges between macroblocks and those between subblocks are treated
with different control parameters (and, in the case of the normal with different control parameters (and, in the case of the normal
filter, with different algorithms); luma and chroma edges are also filter, with different algorithms); luma and chroma edges are also
treated with different control parameters. Except for pixel treated with different control parameters. Except for pixel
skipping to change at page 94, line 31 skipping to change at page 96, line 31
computes a value based on the four pixels that straddle the edge (two computes a value based on the four pixels that straddle the edge (two
either side). If that value is below a supplied limit, then, very either side). If that value is below a supplied limit, then, very
roughly speaking, the two pixel values are brought closer to each roughly speaking, the two pixel values are brought closer to each
other, "shaving off" something like a quarter of the difference. The other, "shaving off" something like a quarter of the difference. The
same procedure is used for all segments straddling any type of edge, same procedure is used for all segments straddling any type of edge,
regardless of the nature (inter-macroblock, inter-subblock, luma, or regardless of the nature (inter-macroblock, inter-subblock, luma, or
chroma) of the edge; only the limit value depends on the edge-type. chroma) of the edge; only the limit value depends on the edge-type.
The exact procedure (for a single segment) is as follows; the The exact procedure (for a single segment) is as follows; the
subroutine common_adjust is used by both the simple filter presented subroutine common_adjust is used by both the simple filter presented
here and the normal filters discussed in Section 15.3 (Section 15.3). here and the normal filters discussed in Section 15.3.
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
int8 common_adjust( int8 common_adjust(
int use_outer_taps, /* filter is 2 or 4 taps wide */ int use_outer_taps, /* filter is 2 or 4 taps wide */
const Pixel *P1, /* pixel before P0 */ const Pixel *P1, /* pixel before P0 */
Pixel *P0, /* pixel before edge */ Pixel *P0, /* pixel before edge */
Pixel *Q0, /* pixel after edge */ Pixel *Q0, /* pixel after edge */
const Pixel *Q1 /* pixel after Q0 */ const Pixel *Q1 /* pixel after Q0 */
) { ) {
skipping to change at page 95, line 15 skipping to change at page 97, line 15
When "use_outer_taps" is true (as for the simple filter), When "use_outer_taps" is true (as for the simple filter),
"a" is p1 - 3*p0 + 3*q0 - q1, which can be thought of as "a" is p1 - 3*p0 + 3*q0 - q1, which can be thought of as
a refinement of 2*(q0 - p0) and the adjustment is a refinement of 2*(q0 - p0) and the adjustment is
something like (q0 - p0)/4. */ something like (q0 - p0)/4. */
int8 a = c( ( use_outer_taps? c(p1 - q1) : 0 ) + 3*(q0 - p0) ); int8 a = c( ( use_outer_taps? c(p1 - q1) : 0 ) + 3*(q0 - p0) );
/* b is used to balance the rounding of a/8 in the case where /* b is used to balance the rounding of a/8 in the case where
the "fractional" part "f" of a/8 is exactly 1/2. */ the "fractional" part "f" of a/8 is exactly 1/2. */
cint8 b = (a & 7)==4 ? -1 : 0; cint8 b = (c(a + 3)) >> 3;
/* Divide a by 8, rounding up when f >= 1/2. /* Divide a by 8, rounding up when f >= 1/2.
Although not strictly part of the "C" language, Although not strictly part of the "C" language,
the right-shift is assumed to propagate the sign bit. */ the right-shift is assumed to propagate the sign bit. */
a = c( a + 4) >> 3; a = c( a + 4) >> 3;
/* Subtract "a" from q0, "bringing it closer" to p0. */ /* Subtract "a" from q0, "bringing it closer" to p0. */
*Q0 = s2u( q0 - a); *Q0 = s2u( q0 - a);
/* Add "a" (with adjustment "b") to p0, "bringing it closer" /* Add "a" (with adjustment "b") to p0, "bringing it closer"
to q0. to q0.
The clamp of "a+b", while present in the reference decoder, The clamp of "a+b", while present in the reference decoder,
is superfluous; we have -16 <= a <= 15 at this point. */ is superfluous; we have -16 <= a <= 15 at this point. */
*P0 = s2u( p0 + c( a + b)); *P0 = s2u( p0 + b);
return a; return a;
} }
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
void simple_segment( void simple_segment(
uint8 edge_limit, /* do nothing if edge difference uint8 edge_limit, /* do nothing if edge difference
exceeds limit */ exceeds limit */
skipping to change at page 103, line 41 skipping to change at page 105, line 41
4, 6, /* "1" subtree has 2 descendant subtrees */ 4, 6, /* "1" subtree has 2 descendant subtrees */
-V_PRED, -H_PRED, /* "10" subtree: V_PRED = "100", -V_PRED, -H_PRED, /* "10" subtree: V_PRED = "100",
H_PRED = "101" */ H_PRED = "101" */
-TM_PRED, -B_PRED /* "11" subtree: TM_PRED = "110", -TM_PRED, -B_PRED /* "11" subtree: TM_PRED = "110",
B_PRED = "111" */ B_PRED = "111" */
}; };
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
The probability table used to decode this tree is variable. As The probability table used to decode this tree is variable. As
described in Chapter 9 (Section 9), it (along with the similarly- described in Section 9, it (along with the similarly-treated UV
treated UV table) can be updated by field J of the frame header. table) can be updated by field J of the frame header. Similar to the
Similar to the coefficient-decoding probabilities, such updates are coefficient-decoding probabilities, such updates are cumulative and
cumulative and affect all ensuing frames until the next key frame or affect all ensuing frames until the next key frame or explicit
explicit update. The default probabilities for the Y and UV tables update. The default probabilities for the Y and UV tables are
are
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
Prob ymode_prob [num_ymodes - 1] = { 112, 86, 140, 37}; Prob ymode_prob [num_ymodes - 1] = { 112, 86, 140, 37};
Prob uv_mode_prob [num_uv_modes - 1] = { 162, 101, 204}; Prob uv_mode_prob [num_uv_modes - 1] = { 162, 101, 204};
---- End code block ----------------------------------------
---- End code block ----------------------------------------
These defaults must be restored after detection of a key frame. These defaults must be restored after detection of a key frame.
Just as for key frames, if the Y mode is B_PRED, there next comes an Just as for key frames, if the Y mode is B_PRED, there next comes an
encoding of the intra_bpred mode used by each of the sixteen Y encoding of the intra_bpred mode used by each of the sixteen Y
subblocks. These encodings use the same tree as does that for key subblocks. These encodings use the same tree as does that for key
frames but, in place of the contexts used in key frames, use the frames but, in place of the contexts used in key frames, use the
single fixed probability table single fixed probability table
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
skipping to change at page 115, line 18 skipping to change at page 117, line 18
datastream: applied to whole macroblocks in NEWMV mode and applied to datastream: applied to whole macroblocks in NEWMV mode and applied to
subsets of macroblocks in NEW4x4 mode. The format of the vectors is subsets of macroblocks in NEW4x4 mode. The format of the vectors is
identical in both cases. identical in both cases.
Each vector has two pieces: A vertical component (row) followed by a Each vector has two pieces: A vertical component (row) followed by a
horizontal component (column). The row and column use separate horizontal component (column). The row and column use separate
coding probabilities but are otherwise represented identically. coding probabilities but are otherwise represented identically.
17.1. Coding of Each Component 17.1. Coding of Each Component
Each component is a signed integer "V" representing a vertical or Each component is a signed integer V representing a vertical or
horizontal luma displacement of "V" quarter-pixels (and a chroma horizontal luma displacement of V quarter-pixels (and a chroma
displacement of "V" eighth-pixels). The absolute value of "V", if displacement of V eighth-pixels). The absolute value of V, if non-
non-zero, is followed by a boolean sign. "V" may take any value zero, is followed by a boolean sign. V may take any value between
between -255 and +255, inclusive. -1023 and +1023, inclusive.
The absolute value "A" is coded in one of two different ways The absolute value A is coded in one of two different ways according
according to its size. For 0 <= "A" <= 7, "A" is tree-coded, and for to its size. For 0 <= A <= 7, A is tree-coded, and for 8 <= A <=
8 <= "A" <= 255, the bits in the binary expansion of "A" are coded 1023, the bits in the binary expansion of A are coded using
using independent boolean probabilities. The coding of "A" begins independent boolean probabilities. The coding of A begins with a
with a bool specifying which range is in effect. bool specifying which range is in effect.
Decoding a motion vector component then requires a 17-position Decoding a motion vector component then requires a 19-position
probability table, whose offsets, along with the procedure used to probability table, whose offsets, along with the procedure used to
decode components, are as follows: decode components, are as follows:
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
typedef enum typedef enum
{ {
mvpis_short, /* short (<= 7) vs long (>= 8) */ mvpis_short, /* short (<= 7) vs long (>= 8) */
MVPsign, /* sign for non-zero */ MVPsign, /* sign for non-zero */
MVPshort, /* 8 short values = 7-position tree */ MVPshort, /* 8 short values = 7-position tree */
MVPbits = MVPshort + 7, /* 8 long value bits MVPbits = MVPshort + 7, /* 8 long value bits
w/independent probs */ w/independent probs */
MVPcount = MVPbits + 8 /* 17 probabilities in total */ MVPcount = MVPbits + 10 /* 19 probabilities in total */
} }
MVPindices; MVPindices;
typedef Prob MV_CONTEXT [MVPcount]; /* Decoding spec for typedef Prob MV_CONTEXT [MVPcount]; /* Decoding spec for
a single component */ a single component */
/* Tree used for small absolute values (has expected /* Tree used for small absolute values (has expected
correspondence). */ correspondence). */
const tree_index small_mvtree [2 * (8 - 1)] = const tree_index small_mvtree [2 * (8 - 1)] =
skipping to change at page 116, line 27 skipping to change at page 118, line 27
}; };
/* Read MV component at current decoder position, using /* Read MV component at current decoder position, using
supplied probs. */ supplied probs. */
int read_mvcomponent( bool_decoder *d, const MV_CONTEXT *mvc) int read_mvcomponent( bool_decoder *d, const MV_CONTEXT *mvc)
{ {
const Prob * const p = (const Prob *) mvc; const Prob * const p = (const Prob *) mvc;
int A = 0; int A = 0;
if( read_bool( d, p [mvpis_short])) /* 8 <= A <= 255 */ if( read_bool( d, p [mvpis_short])) /* 8 <= A <= 1023 */
{ {
/* Read bits 0, 1, 2 */ /* Read bits 0, 1, 2 */
int i = 0; int i = 0;
do { A += read_bool( d, p [MVPbits + i]) << i;} do { A += read_bool( d, p [MVPbits + i]) << i;}
while( ++i < 3); while( ++i < 3);
/* Read bits 7, 6, 5, 4 */ /* Read bits 9, 8, 7, 6, 5, 4 */
i = 7; i = 9;
do { A += read_bool( d, p [MVPbits + i]) << i;} do { A += read_bool( d, p [MVPbits + i]) << i;}
while( --i > 3); while( --i > 3);
/* We know that A >= 8 because it is coded long, /* We know that A >= 8 because it is coded long,
so if A <= 15, bit 3 is one and is not so if A <= 15, bit 3 is one and is not
explicitly coded. */ explicitly coded. */
if( !(A & 0xfff0) || read_bool( d, p [MVPbits + 3])) if( !(A & 0xfff0) || read_bool( d, p [MVPbits + 3]))
A += 8; A += 8;
} }
else /* 0 <= A <= 7 */ else /* 0 <= A <= 7 */
A = treed_read( d, small_mvtree, p + MVPshort); A = treed_read( d, small_mvtree, p + MVPshort);
return A && read_bool( r, p [MVPsign]) ? -A : A; return A && read_bool( r, p [MVPsign]) ? -A : A;
} }
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
17.2. Probability Updates 17.2. Probability Updates
The decoder should maintain an array of two MV_CONTEXTs for decoding The decoder should maintain an array of two MV_CONTEXTs for decoding
row and column components, respectively. These MV_CONTEXTs should be row and column components, respectively. These MV_CONTEXTs should be
set to their defaults every key frame. Each individual probability set to their defaults every key frame. Each individual probability
may be updated every interframe (by field "J" of the frame header) may be updated every interframe (by field J of the frame header)
using a constant table of update probabilities. Each optional update using a constant table of update probabilities. Each optional update
is of the form B? P(7), that is, a bool followed by a 7-bit is of the form B? P(7), that is, a bool followed by a 7-bit
probability specification if true. probability specification if true.
As with other dynamic probabilities used by VP8, the updates remain As with other dynamic probabilities used by VP8, the updates remain
in effect until the next key frame or until replaced via another in effect until the next key frame or until replaced via another
update. update.
In detail, the probabilities should then be managed as follows. In detail, the probabilities should then be managed as follows.
skipping to change at page 120, line 12 skipping to change at page 122, line 12
procedure and, with it, the procedure for decoding interframe procedure and, with it, the procedure for decoding interframe
macroblock prediction records. macroblock prediction records.
18. Interframe Prediction 18. Interframe Prediction
Given an inter-prediction specification for the current macroblock, Given an inter-prediction specification for the current macroblock,
that is, a reference frame together with a motion vector for each of that is, a reference frame together with a motion vector for each of
the sixteen Y subblocks, we describe the calculation of the the sixteen Y subblocks, we describe the calculation of the
prediction buffer for the macroblock. Frame reconstruction is then prediction buffer for the macroblock. Frame reconstruction is then
completed via the previously-described processes of residue summation completed via the previously-described processes of residue summation
(Chapter 14 (Section 14)) and loop filtering (Chapter 15 (Section 14) and loop filtering (Section 15).
(Section 15)).
The management of inter-predicted subblocks may be found in the The management of inter-predicted subblocks may be found in the
reference decoder file reconinter.c; sub-pixel interpolation is reference decoder file reconinter.c; sub-pixel interpolation is
implemented in filter_c.c. implemented in filter_c.c.
18.1. Bounds on and Adjustment of Motion Vectors 18.1. Bounds on and Adjustment of Motion Vectors
It is possible within the VP8 format for a block or macroblock to Since each motion vector is differentially encoded from a neighboring
have an arbitrarily large motion vectors, due to the fact that each block or macroblock and the only clamp is to ensure that the
motion vector is differentially encoded without any clamp from a referenced motion vector represents a valid location inside a
neighboring block or macroblock. 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 Because the motion vectors applied to the chroma subblocks have 1/8
pixel resolution, the synthetic pixel calculation, outlined in pixel resolution, the synthetic pixel calculation, outlined in
Chapter 5 and detailed below, uses this resolution for the luma Chapter 5 and detailed below, uses this resolution for the luma
subblocks as well. In accordance, the stored luma motion vectors are subblocks as well. In accordance, the stored luma motion vectors are
all doubled, each component of each luma vector becoming an even all doubled, each component of each luma vector becoming an even
integer in the range -510 to +510, inclusive. integer in the range -2046 to +2046, inclusive.
The vector applied to each chroma subblock is calculated by averaging The vector applied to each chroma subblock is calculated by averaging
the vectors for the 4 luma subblocks occupying the same visible area the vectors for the 4 luma subblocks occupying the same visible area
as the chroma subblock in the usual correspondence, that is, the 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 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, 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 3, 6, 7}, chroma block 2 to Y blocks { 8, 9, 12, 13}, and chroma
block 3 to Y blocks { 10, 11, 14, 15}. block 3 to Y blocks { 10, 11, 14, 15}.
In detail, each of the two components of the vectors for each of the In detail, each of the two components of the vectors for each of the
skipping to change at page 126, line 48 skipping to change at page 128, line 48
The filters chosen by VP8 were chosen, within the constraints of 4 or The filters chosen by VP8 were chosen, within the constraints of 4 or
6 taps and 7-bit precision, to do the best possible job of handling 6 taps and 7-bit precision, to do the best possible job of handling
the low spatial frequencies near the zeroth DC frequency along with the low spatial frequencies near the zeroth DC frequency along with
introducing no resonances (places where the absolute value of the introducing no resonances (places where the absolute value of the
frequency response exceeds one). frequency response exceeds one).
The justification for the foregoing has two parts. First, resonances The justification for the foregoing has two parts. First, resonances
can produce extremely objectionable visible artifacts when, as often can produce extremely objectionable visible artifacts when, as often
happens in actual compressed video streams, filters are applied happens in actual compressed video streams, filters are applied
repeatedly. Second, the vast majority of energy in real-world images repeatedly. Second, the vast majority of energy in real-world images
lies near DC and not at the high-end; also, roughly speaking, human lies near DC and not at the high-end.
perception tends to be more sensitive at these lower spatial
frequencies.
To get slightly more specific, the filters chosen by VP8 are the best To get slightly more specific, the filters chosen by VP8 are the best
resonance-free 4- or 6-tap filters possible, where "best" describes resonance-free 4- or 6-tap filters possible, where "best" describes
the frequency response near the origin: the response at 0 is required the frequency response near the origin: the response at 0 is required
to be 1 and the graph of the response at 0 is as flat as possible. to be 1 and the graph of the response at 0 is as flat as possible.
To provide an intuitively more obvious point of reference, the "best" To provide an intuitively more obvious point of reference, the "best"
2-tap filter is given by simple linear interpolation between the 2-tap filter is given by simple linear interpolation between the
surrounding actual pixels. surrounding actual pixels.
skipping to change at page 128, line 15 skipping to change at page 130, line 15
19. Annex A: Bitstream Syntax 19. Annex A: Bitstream Syntax
This annex presents the bitstream syntax in a tabular form. All the This annex presents the bitstream syntax in a tabular form. All the
information elements have been introduced and explained in the information elements have been introduced and explained in the
previous chapters but are collected here for a quick reference. Each previous chapters but are collected here for a quick reference. Each
syntax element is shortly described after the tabular representation syntax element is shortly described after the tabular representation
along with a reference to the corresponding paragraph in the main along with a reference to the corresponding paragraph in the main
document. The meaning of each syntax element value is not repeated document. The meaning of each syntax element value is not repeated
here. here.
The top-level hierarchy of the bitstream is introduced in Chapter 4 The top-level hierarchy of the bitstream is introduced in Section 4.
(Section 4).
Definition of syntax element coding types can be found in Chapter 8 Definition of syntax element coding types can be found in Section 8.
(Section 8). The types used in the representation in this annex are: The types used in the representation in this annex are:
o f(n), n-bit value from stream (n successive bits, not boolean o f(n), n-bit value from stream (n successive bits, not boolean
encoded) encoded)
o L(n), n-bit number encoded as n booleans (with equal probability o L(n), n-bit number encoded as n booleans (with equal probability
of being 0 or 1) of being 0 or 1)
o B(p), bool with probability p of being 0 o B(p), bool with probability p of being 0
o T, tree-encoded value o T, tree-encoded value
skipping to change at page 132, line 43 skipping to change at page 134, line 43
| | | | | |
| intra_chroma_prob | L(8) | | intra_chroma_prob | L(8) |
| | | | | |
| } | | | } | |
| | | | | |
| mv_prob_update() | | | mv_prob_update() | |
| | | | | |
| } | | | } | |
+--------------------------------------+------+ +--------------------------------------+------+
o color_space defines the YUV color space of the sequence (9.2 o color_space defines the YUV color space of the sequence
(Section 9.2)) (Section 9.2)
o clamping_type specifies if the decoder is required to clamp the o clamping_type specifies if the decoder is required to clamp the
reconstructed pixel values (9.2 (Section 9.2)) reconstructed pixel values (Section 9.2)
o segmentation_enabled enables the segmentation feature for the o segmentation_enabled enables the segmentation feature for the
current frame (9.3 (Section 9.3)) current frame (Section 9.3)
o filter_type determines whether the normal or the simple loop o filter_type determines whether the normal or the simple loop
filter is used (9.4 (Section 9.4), 15 (Section 15)) filter is used (Section 9.4, Section 15)
o loop_filter_level controls the deblocking filter (9.4 o loop_filter_level controls the deblocking filter (Section 9.4,
(Section 9.4), 15 (Section 15)) Section 15)
o sharpness_level controls the deblocking filter (9.4 (Section 9.4), o sharpness_level controls the deblocking filter (Section 9.4,
15 (Section 15)) Section 15)
o log2_nbr_of_dct_partitions determines the number of separate o log2_nbr_of_dct_partitions determines the number of separate
partitions containing the DCT coefficients of the macroblocks (9.5 partitions containing the DCT coefficients of the macroblocks
(Section 9.5)) (Section 9.5)
o refresh_entropy_probs determines whether updated token o refresh_entropy_probs determines whether updated token
probabilities are used only for this frame or until further update probabilities are used only for this frame or until further update
o refresh_golden_frame determines if the current decoded frame o refresh_golden_frame determines if the current decoded frame
refreshes the golden frame (9.7 (Section 9.7)) refreshes the golden frame (Section 9.7)
o refresh_alternate_frame determines if the current decoded frame o refresh_alternate_frame determines if the current decoded frame
refreshes the alternate reference frame (9.7 (Section 9.7)) refreshes the alternate reference frame (Section 9.7)
o copy_buffer_to_golden determines if the golden reference is o copy_buffer_to_golden determines if the golden reference is
replaced by another reference (9.7 (Section 9.7)) replaced by another reference (Section 9.7)
o copy_buffer_to_alternate determines if the alternate reference is o copy_buffer_to_alternate determines if the alternate reference is
replaced by another reference (9.7 (Section 9.7)) replaced by another reference (Section 9.7)
o sign_bias_golden controls the sign of motion vectors when the o sign_bias_golden controls the sign of motion vectors when the
golden frame is referenced (9.7 (Section 9.7)) golden frame is referenced (Section 9.7)
o sign_bias_alternate controls the sign of motion vectors when the o sign_bias_alternate controls the sign of motion vectors when the
alternate frame is referenced (9.7 (Section 9.7)) alternate frame is referenced (Section 9.7)
o refresh_last determines if the current decoded frame refreshes the o refresh_last determines if the current decoded frame refreshes the
last frame reference buffer (9.8 (Section 9.8)) last frame reference buffer (Section 9.8)
o mb_no_coeff_skip enables or disables the skipping of macroblocks o mb_no_coeff_skip enables or disables the skipping of macroblocks
containing no non-zero coefficients (9.10 (Section 9.10)) containing no non-zero coefficients (Section 9.10)
o prob_skip_false the probability that the macroblock is not skipped o prob_skip_false the probability that the macroblock is not skipped
(flag indicating skipped macroblock is false) (9.10 (flag indicating skipped macroblock is false) (Section 9.10)
(Section 9.10))
o prob_intra the probability of an intra macroblock (9.10 o prob_intra the probability of an intra macroblock (Section 9.10)
(Section 9.10))
o prob_last the probability that the last reference frame is used o prob_last the probability that the last reference frame is used
for inter prediction (9.10 (Section 9.10)) for inter prediction (Section 9.10)
o prob_golden the probability that the golden reference frame is o prob_golden the probability that the golden reference frame is
used for inter prediction (9.10 (Section 9.10)) used for inter prediction (Section 9.10)
o intra_16x16_prob_update_flag indicates if the branch probabilies o intra_16x16_prob_update_flag indicates if the branch probabilies
used in the decoding of luma intra prediction mode are updated used in the decoding of luma intra prediction mode are updated
(9.10 (Section 9.10)) (Section 9.10)
o intra_16x16_prob the branch probabilities of the luma intra o intra_16x16_prob the branch probabilities of the luma intra
prediction mode decoding tree prediction mode decoding tree
o intra_chroma_prob_update_flag indicates if the branch probabilies o intra_chroma_prob_update_flag indicates if the branch probabilies
used in the decoding of chroma intra prediction mode are updated used in the decoding of chroma intra prediction mode are updated
(9.10 (Section 9.10)) (Section 9.10)
o intra_chroma_prob the branch probabilities of the chroma intra o intra_chroma_prob the branch probabilities of the chroma intra
prediction mode decoding tree prediction mode decoding tree
+------------------------------------+------+ +------------------------------------+------+
| update_segmentation() | Type | | update_segmentation() | Type |
+------------------------------------+------+ +------------------------------------+------+
| update_mb_segmentation_map | L(1) | | update_mb_segmentation_map | L(1) |
| | | | | |
| update_segment_feature_data | L(1) | | update_segment_feature_data | L(1) |
skipping to change at page 135, line 4 skipping to change at page 136, line 50
| | | | | |
| quantizer_update_sign | L(1) | | quantizer_update_sign | L(1) |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| for (i = 0; i < 4; i++) { | | | for (i = 0; i < 4; i++) { | |
| | | | | |
| loop_filter_update | L(1) | | loop_filter_update | L(1) |
| | |
| if (loop_filter_update) { | | | if (loop_filter_update) { | |
| | | | | |
| lf_update_value | L(6) | | lf_update_value | L(6) |
| | | | | |
| lf_update_sign | L(1) | | lf_update_sign | L(1) |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
skipping to change at page 135, line 34 skipping to change at page 137, line 32
| segment_prob | L(8) | | segment_prob | L(8) |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
+------------------------------------+------+ +------------------------------------+------+
o update_mb_segmentation_map determines if the MB segmentation map o update_mb_segmentation_map determines if the MB segmentation map
is updated in the current frame (9.3 (Section 9.3)) is updated in the current frame (Section 9.3)
o update_segment_feature_data indicates if the segment feature data o update_segment_feature_data indicates if the segment feature data
is updated in the current frame (9.3 (Section 9.3)) is updated in the current frame (Section 9.3)
o segment_feature_mode indicates the feature data update mode, 0 for o segment_feature_mode indicates the feature data update mode, 0 for
delta and 1 for the absolute value (9.3 (Section 9.3)) delta and 1 for the absolute value (Section 9.3)
o quantizer_update indicates if the quantizer value is updated for o quantizer_update indicates if the quantizer value is updated for
the i^(th) segment (9.3 (Section 9.3)) the i^(th) segment (Section 9.3)
o quantizer_update_value indicates the update value for the segment o quantizer_update_value indicates the update value for the segment
quantizer (9.3 (Section 9.3)) quantizer (Section 9.3)
o quantizer_update_sign indicates the update sign for the segment o quantizer_update_sign indicates the update sign for the segment
quantizer (9.3 (Section 9.3)) quantizer (Section 9.3)
o loop_filter_update indicates if the loop filter level value is o loop_filter_update indicates if the loop filter level value is
updated for the i^(th) segment (9.3 (Section 9.3)) updated for the i^(th) segment (Section 9.3)
o lf_update_value indicates the update value for the loop filter o lf_update_value indicates the update value for the loop filter
level (9.3 (Section 9.3)) level (Section 9.3)
o lf_update_sign indicates the update sign for the loop filter level o lf_update_sign indicates the update sign for the loop filter level
(9.3 (Section 9.3)) (Section 9.3)
o segment_prob_update indicates if the branch probabilities used to o segment_prob_update indicates if the branch probabilities used to
decode the segment_id in the MB header are decoded from the stream decode the segment_id in the MB header are decoded from the stream
or use the default value of 255 (9.3 (Section 9.3)) or use the default value of 255 (Section 9.3)
o segment_prob the branch probabilities of the segment_id decoding o segment_prob the branch probabilities of the segment_id decoding
tree (9.3 (Section 9.3)) tree (Section 9.3)
+------------------------------------+------+ +------------------------------------+------+
| mb_lf_adjustments() | Type | | mb_lf_adjustments() | Type |
+------------------------------------+------+ +------------------------------------+------+
| loop_filter_adj_enable | L(1) | | loop_filter_adj_enable | L(1) |
| | | | | |
| if (loop_filter_adj_enable) { | | | if (loop_filter_adj_enable) { | |
| | | | | |
| mode_ref_lf_delta_update | L(1) | | mode_ref_lf_delta_update | L(1) |
| | | | | |
| if (mode_ref_lf_delta_update) { | | | if (mode_ref_lf_delta_update) { | |
skipping to change at page 137, line 50 skipping to change at page 139, line 50
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
+------------------------------------+------+ +------------------------------------+------+
o loop_filter_adj_enable indicates if the MB-level loop filter o loop_filter_adj_enable indicates if the MB-level loop filter
adjustment (based on the used reference frame and coding mode) is adjustment (based on the used reference frame and coding mode) is
on for the current frame (9.4 (Section 9.4)) on for the current frame (Section 9.4)
o mode_ref_lf_delta_update indicates if the delta values used in o mode_ref_lf_delta_update indicates if the delta values used in
adjustment are updated in the current frame (9.4 (Section 9.4)) adjustment are updated in the current frame (Section 9.4)
o ref_frame_delta_update_flag indicates if the adjustment delta o ref_frame_delta_update_flag indicates if the adjustment delta
value corresponding to a certain used reference frame is updated value corresponding to a certain used reference frame is updated
(9.4 (Section 9.4)) (Section 9.4)
o delta_magnitude is the absolute value of the delta value o delta_magnitude is the absolute value of the delta value
o delta_sign is the sign of the delta value o delta_sign is the sign of the delta value
o mb_mode_delta_update_flag indicates if the adjustment delta value o mb_mode_delta_update_flag indicates if the adjustment delta value
corresponding to certain MB prediction mode is updated (9.4 corresponding to certain MB prediction mode is updated
(Section 9.4)) (Section 9.4)
+----------------------------+------+ +----------------------------+------+
| quant_indices() | Type | | quant_indices() | Type |
+----------------------------+------+ +----------------------------+------+
| y_ac_qi | L(7) | | y_ac_qi | L(7) |
| | | | | |
| y_dc_delta_present | L(1) | | y_dc_delta_present | L(1) |
| | | | | |
| if (y_dc_delta_present) { | | | if (y_dc_delta_present) { | |
| | | | | |
| y_dc_delta_magnitude | L(4) | | y_dc_delta_magnitude | L(4) |
skipping to change at page 140, line 7 skipping to change at page 142, line 7
| | | | | |
| uv_ac_delta_magnitude | L(4) | | uv_ac_delta_magnitude | L(4) |
| | | | | |
| uv_ac_delta_sign | L(1) | | uv_ac_delta_sign | L(1) |
| | | | | |
| } | | | } | |
+----------------------------+------+ +----------------------------+------+
o y_ac_qi is the dequantization table index used for the luma AC o y_ac_qi is the dequantization table index used for the luma AC
coefficients (and other coefficient groups if no delta value is coefficients (and other coefficient groups if no delta value is
present) (9.6 (Section 9.6)) present) (Section 9.6)
o y_dc_delta_present indicates if the stream contains a delta value o y_dc_delta_present indicates if the stream contains a delta value
that is added to the baseline index to obtain the luma DC that is added to the baseline index to obtain the luma DC
coefficient dequantization index (9.6 (Section 9.6)) coefficient dequantization index (Section 9.6)
o y_dc_delta_magnitude the magnitude of the delta value (9.6 o y_dc_delta_magnitude the magnitude of the delta value
(Section 9.6)) (Section 9.6)
o y_dc_delta_sign the sign of the delta value (9.6 (Section 9.6)) o y_dc_delta_sign the sign of the delta value (Section 9.6)
o y2_dc_delta_present indicates if the stream contains a delta value o y2_dc_delta_present indicates if the stream contains a delta value
that is added to the baseline index to obtain the Y2 block DC that is added to the baseline index to obtain the Y2 block DC
coefficient dequantization index (9.6 (Section 9.6)) coefficient dequantization index (Section 9.6)
o y2_ac_delta_present indicates if the stream contains a delta value o y2_ac_delta_present indicates if the stream contains a delta value
that is added to the baseline index to obtain the Y2 block AC that is added to the baseline index to obtain the Y2 block AC
coefficient dequantization index (9.6 (Section 9.6)) coefficient dequantization index (Section 9.6)
o uv_dc_delta_present indicates if the stream contains a delta value o uv_dc_delta_present indicates if the stream contains a delta value
that is added to the baseline index to obtain the chroma DC that is added to the baseline index to obtain the chroma DC
coefficient dequantization index (9.6 (Section 9.6)) coefficient dequantization index (Section 9.6)
o uv_ac_delta_present indicates if the stream contains a delta value o uv_ac_delta_present indicates if the stream contains a delta value
that is added to the baseline index to obtain the chroma AC that is added to the baseline index to obtain the chroma AC
coefficient dequantization index (9.6 (Section 9.6)) coefficient dequantization index (Section 9.6)
+-------------------------------+------+ +-------------------------------+------+
| token_prob_update() | Type | | token_prob_update() | Type |
+-------------------------------+------+ +-------------------------------+------+
| for (i = 0; i < 4; i++) { | | | for (i = 0; i < 4; i++) { | |
| | | | | |
| for (j = 0; j < 8; j++) { | | | for (j = 0; j < 8; j++) { | |
| | | | | |
| for (k = 0; k < 3; k++) { | | | for (k = 0; k < 3; k++) { | |
| | | | | |
| for (l = 0; l < 11; l++) { | | | for (l = 0; l < 11; l++) { | |
skipping to change at page 141, line 33 skipping to change at page 143, line 33
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
+-------------------------------+------+ +-------------------------------+------+
o coeff_prob_update_flag indicates if the corresponding branch o coeff_prob_update_flag indicates if the corresponding branch
probability is updated in the current frame (13.4 (Section 13.4)) probability is updated in the current frame (Section 13.4)
o coeff_prob is the new branch probability (13.4 (Section 13.4)) o coeff_prob is the new branch probability (Section 13.4)
+----------------------------+------+ +----------------------------+------+
| mv_prob_update() | Type | | mv_prob_update() | Type |
+----------------------------+------+ +----------------------------+------+
| for (i = 0; i < 2; i++) { | | | for (i = 0; i < 2; i++) { | |
| | | | | |
| for (j = 0; j < 19; j++) { | | | for (j = 0; j < 19; j++) { | |
| | | | | |
| mv_prob_update_flag | L(1) | | mv_prob_update_flag | L(1) |
| | | | | |
| if (mv_prob_update_flag) { | | | if (mv_prob_update_flag) { | |
skipping to change at page 142, line 25 skipping to change at page 144, line 25
| prob | L(7) | | prob | L(7) |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
| | | | | |
| } | | | } | |
+----------------------------+------+ +----------------------------+------+
o mv_prob_update_flag indicates if the corresponding MV decoding o mv_prob_update_flag indicates if the corresponding MV decoding
probability is updated in the current frame (17.2 (Section 17.2)) probability is updated in the current frame (Section 17.2)
o prob is the updated probability (17.2 (Section 17.2)) o prob is the updated probability (Section 17.2)
19.3. Macroblock Data 19.3. Macroblock Data
+---------------------+------+ +---------------------+------+
| Macroblock Data | Type | | Macroblock Data | Type |
+---------------------+------+ +---------------------+------+
| macroblock_header() | | | macroblock_header() | |
| | | | | |
| residual_data() | | | residual_data() | |
+---------------------+------+ +---------------------+------+
skipping to change at page 144, line 20 skipping to change at page 146, line 20
| | | | | |
| intra_b_mode | T | | intra_b_mode | T |
| | | | | |
| } | | | } | |
| | | | | |
| intra_uv_mode | T | | intra_uv_mode | T |
| | | | | |
| } | | | } | |
+-------------------------------+------+ +-------------------------------+------+
o segment_id indicates to which segment the macroblock belongs (10 o segment_id indicates to which segment the macroblock belongs
(Section 10)) (Section 10)
o mb_coeff_skip indicates if the macroblock contains any coded o mb_coeff_skip indicates if the macroblock contains any coded
coefficients or not (11.1 (Section 11.1)) coefficients or not (Section 11.1)
o is_inter_mb indicates if the macroblock is intra or inter coded o is_inter_mb indicates if the macroblock is intra or inter coded
(16 (Section 16)) (Section 16)
o mb_ref_frame_sel1 selects the reference frame to be used; last o mb_ref_frame_sel1 selects the reference frame to be used; last
frame (0), golden/alternate (1) (16.2 (Section 16.2)) frame (0), golden/alternate (1) (Section 16.2)
o mb_ref_frame_sel2 selects whether the golden (0) or alternate o mb_ref_frame_sel2 selects whether the golden (0) or alternate
reference frame (1) is used (16.2 (Section 16.2)) reference frame (1) is used (Section 16.2)
o mv_mode determines the macroblock motion vector mode (16.2 o mv_mode determines the macroblock motion vector mode
(Section 16.2)) (Section 16.2)
o mv_split_mode gives macroblock partitioning specification and o mv_split_mode gives macroblock partitioning specification and
determines number of motion vectors used (numMvs)(16.2 determines number of motion vectors used (numMvs)(Section 16.2)
(Section 16.2))
o sub_mv_mode determines the sub-macroblock motion vector mode for o sub_mv_mode determines the sub-macroblock motion vector mode for
macroblocks coded using SPLITMV motion vector mode (16.2 macroblocks coded using SPLITMV motion vector mode (Section 16.2)
(Section 16.2))
o intra_y_mode selects the luminance intra prediction mode (16.1 o intra_y_mode selects the luminance intra prediction mode
(Section 16.1)) (Section 16.1)
o intra_b_mode selects the sub-macroblock luminance prediction mode o intra_b_mode selects the sub-macroblock luminance prediction mode
for macroblocks coded using B_PRED mode (16.1 (Section 16.1)) for macroblocks coded using B_PRED mode (Section 16.1)
o intra_uv_mode selects the chrominance intra prediction mode (16.1
(Section 16.1))
o intra_uv_mode selects the chrominance intra prediction mode
(Section 16.1)
+----------------------------------------------+------+ +----------------------------------------------+------+
| residual_data() | Type | | residual_data() | Type |
+----------------------------------------------+------+ +----------------------------------------------+------+
| if (!mb_coeff_skip) { | | | if (!mb_coeff_skip) { | |
| | | | | |
| if ( (is_inter_mb && mv_mode != SPLITMV) || | | | if ( (is_inter_mb && mv_mode != SPLITMV) || | |
| | | | | |
| (!is_inter_mb && intra_y_mode != B_PRED) ) { | | | (!is_inter_mb && intra_y_mode != B_PRED) ) { | |
| | | | | |
| residual_block() /* Y2 */ | | | residual_block() /* Y2 */ | |
skipping to change at page 145, line 48 skipping to change at page 147, line 44
| | | | | |
| extra_bits | L(n) | | extra_bits | L(n) |
| | | | | |
| sign | L(1) | | sign | L(1) |
+-------------------------------------+------+ +-------------------------------------+------+
o firstCoeff is 1 for luma blocks of macroblocks containing Y2 o firstCoeff is 1 for luma blocks of macroblocks containing Y2
subblock, otherwise 0 subblock, otherwise 0
o token defines the value of the coefficient, the value range of the o token defines the value of the coefficient, the value range of the
coefficient or the end of block (13.2 (Section 13.2)) coefficient or the end of block (Section 13.2)
o extra_bits determine the value of the coefficient within the value o extra_bits determine the value of the coefficient within the value
range defined by token (13.2 (Section 13.2)) range defined by token (Section 13.2)
o sign indicates the sign of the coefficient (13.2 (Section 13.2)) o sign indicates the sign of the coefficient (Section 13.2)
20. License 20. Patent License
Google hereby grants to You a perpetual, worldwide, non-exclusive, Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this no-charge, royalty-free, irrevocable (except as stated in this
section) patent license to make, have made, use, offer to sell, sell, section) patent license to make, have made, use, offer to sell, sell,
import, and otherwise implementations of this specification where import, and otherwise implementations of this specification where
such license applies only to those patent claims, both currently such license applies only to those patent claims, both currently
owned by Google and acquired in the future, licensable by Google that owned by Google and acquired in the future, licensable by Google that
are necessarily infringed by implementation of this specification. are necessarily infringed by implementation of this specification.
If You or your agent or exclusive licensee institute or order or If You or your agent or exclusive licensee institute or order or
agree to the institution of patent litigation against any entity agree to the institution of patent litigation against any entity
(including a cross-claim or counterclaim in a lawsuit) alleging that (including a cross-claim or counterclaim in a lawsuit) alleging that
any implementation of this specification constitutes direct or any implementation of this specification constitutes direct or
contributory patent infringement, or inducement of patent contributory patent infringement, or inducement of patent
infringement, then any rights granted to You under the License for infringement, then any rights granted to You under the License for
this specification shall terminate as of the date such litigation is this specification shall terminate as of the date such litigation is
filed. filed.
21. Copyright 21. Attachment One: Reference Decoder Source Code
This specification is made available under a Creative Commons Note that the code in this attachment may exhibit bugs, and should be
Attribution 3.0 License [4]. considered a draft until this document reaches RFC status.
21.1. bit_ops.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef BIT_OPS_H
#define BIT_OPS_H
/* Evaluates to a mask with n bits set */
#define BITS_MASK(n) ((1<<(n))-1)
/* Returns len bits, with the LSB at position bit */
#define BITS_GET(val, bit, len) (((val)>>(bit))&BITS_MASK(len))
#endif
---- End code block ----------------------------------------
21.2. bool_decoder.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license and
* patent grant that can be found in the LICENSE file in the root of
* the source tree. All contributing project authors may be found in
* the AUTHORS file in the root of the source tree.
*/
#ifndef BOOL_DECODER_H
#define BOOL_DECODER_H
#include <stddef.h>
struct bool_decoder
{
const unsigned char *input; /* next compressed data byte */
size_t input_len; /* length of the input buffer */
unsigned int range; /* identical to encoder's
* range */
unsigned int value; /* contains at least 8
* significant bits */
int bit_count; /* # of bits shifted out of
* value, max 7 */
};
static void
init_bool_decoder(struct bool_decoder *d,
const unsigned char *start_partition,
size_t sz)
{
if (sz >= 2)
{
d->value = (start_partition[0] << 8) /* first 2 input
* bytes */
| start_partition[1];
d->input = start_partition + 2; /* ptr to next byte */
d->input_len = sz - 2;
}
else
{
d->value = 0;
d->input = NULL;
d->input_len = 0;
}
d->range = 255; /* initial range is full */
d->bit_count = 0; /* have not yet shifted out any bits */
}
static int bool_get(struct bool_decoder *d, int probability)
{
/* range and split are identical to the corresponding values
used by the encoder when this bool was written */
unsigned int split = 1 + (((d->range - 1) * probability) >> 8);
unsigned int SPLIT = split << 8;
int retval; /* will be 0 or 1 */
if (d->value >= SPLIT) /* encoded a one */
{
retval = 1;
d->range -= split; /* reduce range */
d->value -= SPLIT; /* subtract off left endpoint of
* interval */
}
else /* encoded a zero */
{
retval = 0;
d->range = split; /* reduce range, no change in left
* endpoint */
}
while (d->range < 128) /* shift out irrelevant value bits */
{
d->value <<= 1;
d->range <<= 1;
if (++d->bit_count == 8) /* shift in new bits 8 at a time */
{
d->bit_count = 0;
if (d->input_len)
{
d->value |= *d->input++;
d->input_len--;
}
}
}
return retval;
}
static int bool_get_bit(struct bool_decoder *br)
{
return bool_get(br, 128);
}
static int bool_get_uint(struct bool_decoder *br, int bits)
{
int z = 0;
int bit;
for (bit = bits - 1; bit >= 0; bit--)
{
z |= (bool_get_bit(br) << bit);
}
return z;
}
static int bool_get_int(struct bool_decoder *br, int bits)
{
int z = 0;
int bit;
for (bit = bits - 1; bit >= 0; bit--)
{
z |= (bool_get_bit(br) << bit);
}
return bool_get_bit(br) ? -z : z;
}
static int bool_maybe_get_int(struct bool_decoder *br, int bits)
{
return bool_get_bit(br) ? bool_get_int(br, bits) : 0;
}
static int
bool_read_tree(struct bool_decoder *bool,
const int *t,
const unsigned char *p)
{
int i = 0;
while ((i = t[ i + bool_get(bool, p[i>>1])]) > 0) ;
return -i;
}
#endif
---- End code block ----------------------------------------
21.3. dequant_data.h
---- Begin code block --------------------------------------
static const int dc_q_lookup[128] =
{
4, 5, 6, 7, 8, 9, 10, 10,
11, 12, 13, 14, 15, 16, 17, 17,
18, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 25, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36,
37, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 87, 88, 89,
91, 93, 95, 96, 98, 100, 101, 102,
104, 106, 108, 110, 112, 114, 116, 118,
122, 124, 126, 128, 130, 132, 134, 136,
138, 140, 143, 145, 148, 151, 154, 157
};
static const int ac_q_lookup[128] =
{
4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 60,
62, 64, 66, 68, 70, 72, 74, 76,
78, 80, 82, 84, 86, 88, 90, 92,
94, 96, 98, 100, 102, 104, 106, 108,
110, 112, 114, 116, 119, 122, 125, 128,
131, 134, 137, 140, 143, 146, 149, 152,
155, 158, 161, 164, 167, 170, 173, 177,
181, 185, 189, 193, 197, 201, 205, 209,
213, 217, 221, 225, 229, 234, 239, 245,
249, 254, 259, 264, 269, 274, 279, 284
};
---- End code block ----------------------------------------
21.4. dixie.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_codec_internal.h"
#include "bit_ops.h"
#include "dixie.h"
#include "vp8_prob_data.h"
#include "dequant_data.h"
#include "modemv.h"
#include "tokens.h"
#include "predict.h"
#include "dixie_loopfilter.h"
#include <string.h>
#include <assert.h>
enum
{
FRAME_HEADER_SZ = 3,
KEYFRAME_HEADER_SZ = 7
};
#define ARRAY_COPY(a,b) {\
assert(sizeof(a)==sizeof(b));memcpy(a,b,sizeof(a));}
static void
decode_entropy_header(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
struct vp8_entropy_hdr *hdr)
{
int i, j, k, l;
/* Read coefficient probability updates */
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
for (l = 0; l < ENTROPY_NODES; l++)
if (bool_get(bool,
k_coeff_entropy_update_probs
[i][j][k][l]))
hdr->coeff_probs[i][j][k][l] =
bool_get_uint(bool, 8);
/* Read coefficient skip mode probability */
hdr->coeff_skip_enabled = bool_get_bit(bool);
if (hdr->coeff_skip_enabled)
hdr->coeff_skip_prob = bool_get_uint(bool, 8);
/* Parse interframe probability updates */
if (!ctx->frame_hdr.is_keyframe)
{
hdr->prob_inter = bool_get_uint(bool, 8);
hdr->prob_last = bool_get_uint(bool, 8);
hdr->prob_gf = bool_get_uint(bool, 8);
if (bool_get_bit(bool))
for (i = 0; i < 4; i++)
hdr->y_mode_probs[i] = bool_get_uint(bool, 8);
if (bool_get_bit(bool))
for (i = 0; i < 3; i++)
hdr->uv_mode_probs[i] = bool_get_uint(bool, 8);
for (i = 0; i < 2; i++)
for (j = 0; j < MV_PROB_CNT; j++)
if (bool_get(bool, k_mv_entropy_update_probs[i][j]))
{
int x = bool_get_uint(bool, 7);
hdr->mv_probs[i][j] = x ? x << 1 : 1;
}
}
}
static void
decode_reference_header(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
struct vp8_reference_hdr *hdr)
{
unsigned int key = ctx->frame_hdr.is_keyframe;
hdr->refresh_gf = key ? 1 : bool_get_bit(bool);
hdr->refresh_arf = key ? 1 : bool_get_bit(bool);
hdr->copy_gf = key ? 0 : !hdr->refresh_gf
? bool_get_uint(bool, 2) : 0;
hdr->copy_arf = key ? 0 : !hdr->refresh_arf
? bool_get_uint(bool, 2) : 0;
hdr->sign_bias[GOLDEN_FRAME] = key ? 0 : bool_get_bit(bool);
hdr->sign_bias[ALTREF_FRAME] = key ? 0 : bool_get_bit(bool);
hdr->refresh_entropy = bool_get_bit(bool);
hdr->refresh_last = key ? 1 : bool_get_bit(bool);
}
static void
decode_quantizer_header(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
struct vp8_quant_hdr *hdr)
{
int update;
int last_q = hdr->q_index;
hdr->q_index = bool_get_uint(bool, 7);
update = last_q != hdr->q_index;
update |= (hdr->y1_dc_delta_q = bool_maybe_get_int(bool, 4));
update |= (hdr->y2_dc_delta_q = bool_maybe_get_int(bool, 4));
update |= (hdr->y2_ac_delta_q = bool_maybe_get_int(bool, 4));
update |= (hdr->uv_dc_delta_q = bool_maybe_get_int(bool, 4));
update |= (hdr->uv_ac_delta_q = bool_maybe_get_int(bool, 4));
hdr->delta_update = update;
}
static void
decode_and_init_token_partitions(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
const unsigned char *data,
unsigned int sz,
struct vp8_token_hdr *hdr)
{
int i;
hdr->partitions = 1 << bool_get_uint(bool, 2);
if (sz < 3 *(hdr->partitions - 1))
vpx_internal_error(&ctx->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet found parsing partition"
" lengths.");
sz -= 3 * (hdr->partitions - 1);
for (i = 0; i < hdr->partitions; i++)
{
if (i < hdr->partitions - 1)
{
hdr->partition_sz[i] = (data[2] << 16)
| (data[1] << 8) | data[0];
data += 3;
}
else
hdr->partition_sz[i] = sz;
if (sz < hdr->partition_sz[i])
vpx_internal_error(&ctx->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated partition %d", i);
sz -= hdr->partition_sz[i];
}
for (i = 0; i < ctx->token_hdr.partitions; i++)
{
init_bool_decoder(&ctx->tokens[i].bool, data,
ctx->token_hdr.partition_sz[i]);
data += ctx->token_hdr.partition_sz[i];
}
}
static void
decode_loopfilter_header(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
struct vp8_loopfilter_hdr *hdr)
{
if (ctx->frame_hdr.is_keyframe)
memset(hdr, 0, sizeof(*hdr));
hdr->use_simple = bool_get_bit(bool);
hdr->level = bool_get_uint(bool, 6);
hdr->sharpness = bool_get_uint(bool, 3);
hdr->delta_enabled = bool_get_bit(bool);
if (hdr->delta_enabled && bool_get_bit(bool))
{
int i;
for (i = 0; i < BLOCK_CONTEXTS; i++)
hdr->ref_delta[i] = bool_maybe_get_int(bool, 6);
for (i = 0; i < BLOCK_CONTEXTS; i++)
hdr->mode_delta[i] = bool_maybe_get_int(bool, 6);
}
}
static void
decode_segmentation_header(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
struct vp8_segment_hdr *hdr)
{
if (ctx->frame_hdr.is_keyframe)
memset(hdr, 0, sizeof(*hdr));
hdr->enabled = bool_get_bit(bool);
if (hdr->enabled)
{
int i;
hdr->update_map = bool_get_bit(bool);
hdr->update_data = bool_get_bit(bool);
if (hdr->update_data)
{
hdr->abs = bool_get_bit(bool);
for (i = 0; i < MAX_MB_SEGMENTS; i++)
hdr->quant_idx[i] = bool_maybe_get_int(bool, 7);
for (i = 0; i < MAX_MB_SEGMENTS; i++)
hdr->lf_level[i] = bool_maybe_get_int(bool, 6);
}
if (hdr->update_map)
{
for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
hdr->tree_probs[i] = bool_get_bit(bool)
? bool_get_uint(bool, 8)
: 255;
}
}
else
{
hdr->update_map = 0;
hdr->update_data = 0;
}
}
static void
dequant_global_init(struct dequant_factors dqf[MAX_MB_SEGMENTS])
{
int i;
for (i = 0; i < MAX_MB_SEGMENTS; i++)
dqf[i].quant_idx = -1;
}
static int
clamp_q(int q)
{
if (q < 0) return 0;
else if (q > 127) return 127;
return q;
}
static int
dc_q(int q)
{
return dc_q_lookup[clamp_q(q)];
}
static int
ac_q(int q)
{
return ac_q_lookup[clamp_q(q)];
}
static void
dequant_init(struct dequant_factors factors[MAX_MB_SEGMENTS],
const struct vp8_segment_hdr *seg,
const struct vp8_quant_hdr *quant_hdr)
{
int i, q;
struct dequant_factors *dqf = factors;
for (i = 0; i < (seg->enabled ? MAX_MB_SEGMENTS : 1); i++)
{
q = quant_hdr->q_index;
if (seg->enabled)
q = (!seg->abs) ? q + seg->quant_idx[i]
: seg->quant_idx[i];
if (dqf->quant_idx != q || quant_hdr->delta_update)
{
dqf->factor[TOKEN_BLOCK_Y1][0] =
dc_q(q + quant_hdr->y1_dc_delta_q);
dqf->factor[TOKEN_BLOCK_Y1][1] =
ac_q(q);
dqf->factor[TOKEN_BLOCK_UV][0] =
dc_q(q + quant_hdr->uv_dc_delta_q);
dqf->factor[TOKEN_BLOCK_UV][1] =
ac_q(q + quant_hdr->uv_ac_delta_q);
dqf->factor[TOKEN_BLOCK_Y2][0] =
dc_q(q + quant_hdr->y2_dc_delta_q) * 2;
dqf->factor[TOKEN_BLOCK_Y2][1] =
ac_q(q + quant_hdr->y2_ac_delta_q) * 155 / 100;
if (dqf->factor[TOKEN_BLOCK_Y2][1] < 8)
dqf->factor[TOKEN_BLOCK_Y2][1] = 8;
if (dqf->factor[TOKEN_BLOCK_UV][0] > 132)
dqf->factor[TOKEN_BLOCK_UV][0] = 132;
dqf->quant_idx = q;
}
dqf++;
}
}
static void
decode_frame(struct vp8_decoder_ctx *ctx,
const unsigned char *data,
unsigned int sz)
{
vpx_codec_err_t res;
struct bool_decoder bool;
int i, row, partition;
ctx->saved_entropy_valid = 0;
if ((res = vp8_parse_frame_header(data, sz, &ctx->frame_hdr)))
vpx_internal_error(&ctx->error, res,
"Failed to parse frame header");
if (ctx->frame_hdr.is_experimental)
vpx_internal_error(&ctx->error, VPX_CODEC_UNSUP_BITSTREAM,
"Experimental bitstreams not supported.");
data += FRAME_HEADER_SZ;
sz -= FRAME_HEADER_SZ;
if (ctx->frame_hdr.is_keyframe)
{
data += KEYFRAME_HEADER_SZ;
sz -= KEYFRAME_HEADER_SZ;
ctx->mb_cols = (ctx->frame_hdr.kf.w + 15) / 16;
ctx->mb_rows = (ctx->frame_hdr.kf.h + 15) / 16;
}
/* Start the bitreader for the header/entropy partition */
init_bool_decoder(&bool, data, ctx->frame_hdr.part0_sz);
/* Skip the colorspace and clamping bits */
if (ctx->frame_hdr.is_keyframe)
if (bool_get_uint(&bool, 2))
vpx_internal_error(
&ctx->error, VPX_CODEC_UNSUP_BITSTREAM,
"Reserved bits not supported.");
decode_segmentation_header(ctx, &bool, &ctx->segment_hdr);
decode_loopfilter_header(ctx, &bool, &ctx->loopfilter_hdr);
decode_and_init_token_partitions(ctx,
&bool,
data + ctx->frame_hdr.part0_sz,
sz - ctx->frame_hdr.part0_sz,
&ctx->token_hdr);
decode_quantizer_header(ctx, &bool, &ctx->quant_hdr);
decode_reference_header(ctx, &bool, &ctx->reference_hdr);
/* Set keyframe entropy defaults. These get updated on keyframes
* regardless of the refresh_entropy setting.
*/
if (ctx->frame_hdr.is_keyframe)
{
ARRAY_COPY(ctx->entropy_hdr.coeff_probs,
k_default_coeff_probs);
ARRAY_COPY(ctx->entropy_hdr.mv_probs,
k_default_mv_probs);
ARRAY_COPY(ctx->entropy_hdr.y_mode_probs,
k_default_y_mode_probs);
ARRAY_COPY(ctx->entropy_hdr.uv_mode_probs,
k_default_uv_mode_probs);
}
if (!ctx->reference_hdr.refresh_entropy)
{
ctx->saved_entropy = ctx->entropy_hdr;
ctx->saved_entropy_valid = 1;
}
decode_entropy_header(ctx, &bool, &ctx->entropy_hdr);
vp8_dixie_modemv_init(ctx);
vp8_dixie_tokens_init(ctx);
vp8_dixie_predict_init(ctx);
dequant_init(ctx->dequant_factors, &ctx->segment_hdr,
&ctx->quant_hdr);
for (row = 0, partition = 0; row < ctx->mb_rows; row++)
{
vp8_dixie_modemv_process_row(
ctx, &bool, row, 0, ctx->mb_cols);
vp8_dixie_tokens_process_row(ctx, partition, row, 0,
ctx->mb_cols);
vp8_dixie_predict_process_row(ctx, row, 0, ctx->mb_cols);
if (ctx->loopfilter_hdr.level && row)
vp8_dixie_loopfilter_process_row(ctx, row - 1, 0,
ctx->mb_cols);
if (++partition == ctx->token_hdr.partitions)
partition = 0;
}
if (ctx->loopfilter_hdr.level)
vp8_dixie_loopfilter_process_row(
ctx, row - 1, 0, ctx->mb_cols);
ctx->frame_cnt++;
if (!ctx->reference_hdr.refresh_entropy)
{
ctx->entropy_hdr = ctx->saved_entropy;
ctx->saved_entropy_valid = 0;
}
/* Handle reference frame updates */
if (ctx->reference_hdr.copy_arf == 1)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]);
ctx->ref_frames[ALTREF_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[LAST_FRAME]);
}
else if (ctx->reference_hdr.copy_arf == 2)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]);
ctx->ref_frames[ALTREF_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[GOLDEN_FRAME]);
}
if (ctx->reference_hdr.copy_gf == 1)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]);
ctx->ref_frames[GOLDEN_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[LAST_FRAME]);
}
else if (ctx->reference_hdr.copy_gf == 2)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]);
ctx->ref_frames[GOLDEN_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[ALTREF_FRAME]);
}
if (ctx->reference_hdr.refresh_gf)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[GOLDEN_FRAME]);
ctx->ref_frames[GOLDEN_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]);
}
if (ctx->reference_hdr.refresh_arf)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[ALTREF_FRAME]);
ctx->ref_frames[ALTREF_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]);
}
if (ctx->reference_hdr.refresh_last)
{
vp8_dixie_release_ref_frame(ctx->ref_frames[LAST_FRAME]);
ctx->ref_frames[LAST_FRAME] =
vp8_dixie_ref_frame(ctx->ref_frames[CURRENT_FRAME]);
}
}
void
vp8_dixie_decode_init(struct vp8_decoder_ctx *ctx)
{
dequant_global_init(ctx->dequant_factors);
}
#define CHECK_FOR_UPDATE(lval,rval,update_flag) do {\
unsigned int old = lval; \
update_flag |= (old != (lval = rval)); \
} while(0)
vpx_codec_err_t
vp8_parse_frame_header(const unsigned char *data,
unsigned int sz,
struct vp8_frame_hdr *hdr)
{
unsigned long raw;
if (sz < 10)
return VPX_CODEC_CORRUPT_FRAME;
/* The frame header is defined as a three byte little endian
* value
*/
raw = data[0] | (data[1] << 8) | (data[2] << 16);
hdr->is_keyframe = !BITS_GET(raw, 0, 1);
hdr->version = BITS_GET(raw, 1, 2);
hdr->is_experimental = BITS_GET(raw, 3, 1);
hdr->is_shown = BITS_GET(raw, 4, 1);
hdr->part0_sz = BITS_GET(raw, 5, 19);
if (sz <= hdr->part0_sz + (hdr->is_keyframe ? 10 : 3))
return VPX_CODEC_CORRUPT_FRAME;
hdr->frame_size_updated = 0;
if (hdr->is_keyframe)
{
unsigned int update = 0;
/* Keyframe header consists of a three byte sync code
* followed by the width and height and associated scaling
* factors.
*/
if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a)
return VPX_CODEC_UNSUP_BITSTREAM;
raw = data[6] | (data[7] << 8)
| (data[8] << 16) | (data[9] << 24);
CHECK_FOR_UPDATE(hdr->kf.w, BITS_GET(raw, 0, 14),
update);
CHECK_FOR_UPDATE(hdr->kf.scale_w, BITS_GET(raw, 14, 2),
update);
CHECK_FOR_UPDATE(hdr->kf.h, BITS_GET(raw, 16, 14),
update);
CHECK_FOR_UPDATE(hdr->kf.scale_h, BITS_GET(raw, 30, 2),
update);
hdr->frame_size_updated = update;
if (!hdr->kf.w || !hdr->kf.h)
return VPX_CODEC_UNSUP_BITSTREAM;
}
return VPX_CODEC_OK;
}
vpx_codec_err_t
vp8_dixie_decode_frame(struct vp8_decoder_ctx *ctx,
const unsigned char *data,
unsigned int sz)
{
volatile struct vp8_decoder_ctx *ctx_ = ctx;
ctx->error.error_code = VPX_CODEC_OK;
ctx->error.has_detail = 0;
if (!setjmp(ctx->error.jmp))
decode_frame(ctx, data, sz);
return ctx_->error.error_code;
}
void
vp8_dixie_decode_destroy(struct vp8_decoder_ctx *ctx)
{
vp8_dixie_predict_destroy(ctx);
vp8_dixie_tokens_destroy(ctx);
vp8_dixie_modemv_destroy(ctx);
}
---- End code block ----------------------------------------
21.5. dixie.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef DIXIE_H
#define DIXIE_H
#include "vpx_codec_internal.h"
#include "bool_decoder.h"
struct vp8_frame_hdr
{
unsigned int is_keyframe; /* Frame is a keyframe */
unsigned int is_experimental; /* Frame is a keyframe */
unsigned int version; /* Bitstream version */
unsigned int is_shown; /* Frame is to be displayed. */
unsigned int part0_sz; /* Partition 0 length, in bytes */
struct vp8_kf_hdr
{
unsigned int w; /* Width */
unsigned int h; /* Height */
unsigned int scale_w; /* Scaling factor, Width */
unsigned int scale_h; /* Scaling factor, Height */
} kf;
unsigned int frame_size_updated; /* Flag to indicate a resolution
* update.
*/
};
enum
{
MB_FEATURE_TREE_PROBS = 3,
MAX_MB_SEGMENTS = 4
};
struct vp8_segment_hdr
{
unsigned int enabled;
unsigned int update_data;
unsigned int update_map;
unsigned int abs; /* 0=deltas, 1=absolute values */
unsigned int tree_probs[MB_FEATURE_TREE_PROBS];
int lf_level[MAX_MB_SEGMENTS];
int quant_idx[MAX_MB_SEGMENTS];
};
enum
{
BLOCK_CONTEXTS = 4
};
struct vp8_loopfilter_hdr
{
unsigned int use_simple;
unsigned int level;
unsigned int sharpness;
unsigned int delta_enabled;
int ref_delta[BLOCK_CONTEXTS];
int mode_delta[BLOCK_CONTEXTS];
};
enum
{
MAX_PARTITIONS = 8
};
struct vp8_token_hdr
{
unsigned int partitions;
unsigned int partition_sz[MAX_PARTITIONS];
};
struct vp8_quant_hdr
{
unsigned int q_index;
int delta_update;
int y1_dc_delta_q;
int y2_dc_delta_q;
int y2_ac_delta_q;
int uv_dc_delta_q;
int uv_ac_delta_q;
};
struct vp8_reference_hdr
{
unsigned int refresh_last;
unsigned int refresh_gf;
unsigned int refresh_arf;
unsigned int copy_gf;
unsigned int copy_arf;
unsigned int sign_bias[4];
unsigned int refresh_entropy;
};
enum
{
BLOCK_TYPES = 4,
PREV_COEF_CONTEXTS = 3,
COEF_BANDS = 8,
ENTROPY_NODES = 11,
};
typedef unsigned char coeff_probs_table_t[BLOCK_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS]
[ENTROPY_NODES];
enum
{
MV_PROB_CNT = 2 + 8 - 1 + 10 /* from entropymv.h */
};
typedef unsigned char mv_component_probs_t[MV_PROB_CNT];
struct vp8_entropy_hdr
{
coeff_probs_table_t coeff_probs;
mv_component_probs_t mv_probs[2];
unsigned int coeff_skip_enabled;
unsigned char coeff_skip_prob;
unsigned char y_mode_probs[4];
unsigned char uv_mode_probs[3];
unsigned char prob_inter;
unsigned char prob_last;
unsigned char prob_gf;
};
enum reference_frame
{
CURRENT_FRAME,
LAST_FRAME,
GOLDEN_FRAME,
ALTREF_FRAME,
NUM_REF_FRAMES
};
enum prediction_mode
{
/* 16x16 intra modes */
DC_PRED, V_PRED, H_PRED, TM_PRED, B_PRED,
/* 16x16 inter modes */
NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV,
MB_MODE_COUNT,
/* 4x4 intra modes */
B_DC_PRED = 0, B_TM_PRED, B_VE_PRED, B_HE_PRED, B_LD_PRED,
B_RD_PRED, B_VR_PRED, B_VL_PRED, B_HD_PRED, B_HU_PRED,
/* 4x4 inter modes */
LEFT4X4, ABOVE4X4, ZERO4X4, NEW4X4,
B_MODE_COUNT
};
enum splitmv_partitioning
{
SPLITMV_16X8,
SPLITMV_8X16,
SPLITMV_8X8,
SPLITMV_4X4
};
typedef short filter_t[6];
typedef union mv
{
struct
{
int16_t x, y;
} d;
uint32_t raw;
} mv_t;
struct mb_base_info
{
unsigned char y_mode : 4;
unsigned char uv_mode : 4;
unsigned char segment_id : 2;
unsigned char ref_frame : 2;
unsigned char skip_coeff : 1;
unsigned char need_mc_border : 1;
enum splitmv_partitioning partitioning : 2;
union mv mv;
unsigned int eob_mask;
};
struct mb_info
{
struct mb_base_info base;
union
{
union mv mvs[16];
enum prediction_mode modes[16];
} split;
};
/* A "token entropy context" has 4 Y values, 2 U, 2 V, and 1 Y2 */
typedef int token_entropy_ctx_t[4 + 2 + 2 + 1];
struct token_decoder
{
struct bool_decoder bool;
token_entropy_ctx_t left_token_entropy_ctx;
short *coeffs;
};
enum token_block_type
{
TOKEN_BLOCK_Y1,
TOKEN_BLOCK_UV,
TOKEN_BLOCK_Y2,
TOKEN_BLOCK_TYPES,
};
struct dequant_factors
{
int quant_idx;
short factor[TOKEN_BLOCK_TYPES][2]; /* [ Y1, UV, Y2 ]
* [ DC, AC ] */
};
struct ref_cnt_img
{
vpx_image_t img;
unsigned int ref_cnt;
};
struct vp8_decoder_ctx
{
struct vpx_internal_error_info error;
unsigned int frame_cnt;
struct vp8_frame_hdr frame_hdr;
struct vp8_segment_hdr segment_hdr;
struct vp8_loopfilter_hdr loopfilter_hdr;
struct vp8_token_hdr token_hdr;
struct vp8_quant_hdr quant_hdr;
struct vp8_reference_hdr reference_hdr;
struct vp8_entropy_hdr entropy_hdr;
struct vp8_entropy_hdr saved_entropy;
unsigned int saved_entropy_valid;
unsigned int mb_rows;
unsigned int mb_cols;
struct mb_info *mb_info_storage;
struct mb_info **mb_info_rows_storage;
struct mb_info **mb_info_rows;
token_entropy_ctx_t *above_token_entropy_ctx;
struct token_decoder tokens[MAX_PARTITIONS];
struct dequant_factors dequant_factors[MAX_MB_SEGMENTS];
struct ref_cnt_img frame_strg[NUM_REF_FRAMES];
struct ref_cnt_img *ref_frames[NUM_REF_FRAMES];
ptrdiff_t ref_frame_offsets[4];
const filter_t *subpixel_filters;
};
void
vp8_dixie_decode_init(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_decode_destroy(struct vp8_decoder_ctx *ctx);
vpx_codec_err_t
vp8_parse_frame_header(const unsigned char *data,
unsigned int sz,
struct vp8_frame_hdr *hdr);
vpx_codec_err_t
vp8_dixie_decode_frame(struct vp8_decoder_ctx *ctx,
const unsigned char *data,
unsigned int sz);
#define CLAMP_255(x) ((x)<0?0:((x)>255?255:(x)))
#endif
---- End code block ----------------------------------------
21.6. dixie_loopfilter.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "dixie.h"
#include "dixie_loopfilter.h"
#define ABS(x) ((x) >= 0 ? (x) : -(x))
#define p3 pixels[-4*stride]
#define p2 pixels[-3*stride]
#define p1 pixels[-2*stride]
#define p0 pixels[-1*stride]
#define q0 pixels[ 0*stride]
#define q1 pixels[ 1*stride]
#define q2 pixels[ 2*stride]
#define q3 pixels[ 3*stride]
#define static
static int
saturate_int8(int x)
{
if (x < -128)
return -128;
if (x > 127)
return 127;
return x;
}
static int
saturate_uint8(int x)
{
if (x < 0)
return 0;
if (x > 255)
return 255;
return x;
}
static int
high_edge_variance(unsigned char *pixels,
int stride,
int hev_threshold)
{
return ABS(p1 - p0) > hev_threshold ||
ABS(q1 - q0) > hev_threshold;
}
static int
simple_threshold(unsigned char *pixels,
int stride,
int filter_limit)
{
return (ABS(p0 - q0) * 2 + (ABS(p1 - q1) >> 1)) <= filter_limit;
}
static int
normal_threshold(unsigned char *pixels,
int stride,
int edge_limit,
int interior_limit)
{
int E = edge_limit;
int I = interior_limit;
return simple_threshold(pixels, stride, 2 * E + I)
&& ABS(p3 - p2) <= I && ABS(p2 - p1) <= I
&& ABS(p1 - p0) <= I && ABS(q3 - q2) <= I
&& ABS(q2 - q1) <= I && ABS(q1 - q0) <= I;
}
static void
filter_common(unsigned char *pixels,
int stride,
int use_outer_taps)
{
int a, f1, f2;
a = 3 * (q0 - p0);
if (use_outer_taps)
a += saturate_int8(p1 - q1);
a = saturate_int8(a);
f1 = ((a + 4 > 127) ? 127 : a + 4) >> 3;
f2 = ((a + 3 > 127) ? 127 : a + 3) >> 3;
p0 = saturate_uint8(p0 + f2);
q0 = saturate_uint8(q0 - f1);
if (!use_outer_taps)
{
/* This handles the case of subblock_filter()
* (from the bitstream guide.
*/
a = (f1 + 1) >> 1;
p1 = saturate_uint8(p1 + a);
q1 = saturate_uint8(q1 - a);
}
}
static void
filter_mb_edge(unsigned char *pixels,
int stride)
{
int w, a;
w = saturate_int8(saturate_int8(p1 - q1) + 3 * (q0 - p0));
a = (27 * w + 63) >> 7;
p0 = saturate_uint8(p0 + a);
q0 = saturate_uint8(q0 - a);
a = (18 * w + 63) >> 7;
p1 = saturate_uint8(p1 + a);
q1 = saturate_uint8(q1 - a);
a = (9 * w + 63) >> 7;
p2 = saturate_uint8(p2 + a);
q2 = saturate_uint8(q2 - a);
}
static void
filter_mb_v_edge(unsigned char *src,
int stride,
int edge_limit,
int interior_limit,
int hev_threshold,
int size)
{
int i;
for (i = 0; i < 8 * size; i++)
{
if (normal_threshold(src, 1, edge_limit, interior_limit))
{
if (high_edge_variance(src, 1, hev_threshold))
filter_common(src, 1, 1);
else
filter_mb_edge(src, 1);
}
src += stride;
}
}
static void
filter_subblock_v_edge(unsigned char *src,
int stride,
int edge_limit,
int interior_limit,
int hev_threshold,
int size)
{
int i;
for (i = 0; i < 8 * size; i++)
{
if (normal_threshold(src, 1, edge_limit, interior_limit))
filter_common(src, 1,
high_edge_variance(src, 1, hev_threshold));
src += stride;
}
}
static void
filter_mb_h_edge(unsigned char *src,
int stride,
int edge_limit,
int interior_limit,
int hev_threshold,
int size)
{
int i;
for (i = 0; i < 8 * size; i++)
{
if (normal_threshold(src, stride, edge_limit, interior_limit))
{
if (high_edge_variance(src, stride, hev_threshold))
filter_common(src, stride, 1);
else
filter_mb_edge(src, stride);
}
src += 1;
}
}
static void
filter_subblock_h_edge(unsigned char *src,
int stride,
int edge_limit,
int interior_limit,
int hev_threshold,
int size)
{
int i;
for (i = 0; i < 8 * size; i++)
{
if (normal_threshold(src, stride, edge_limit, interior_limit))
filter_common(src, stride,
high_edge_variance(src, stride,
hev_threshold));
src += 1;
}
}
static void
filter_v_edge_simple(unsigned char *src,
int stride,
int filter_limit)
{
int i;
for (i = 0; i < 16; i++)
{
if (simple_threshold(src, 1, filter_limit))
filter_common(src, 1, 1);
src += stride;
}
}
static void
filter_h_edge_simple(unsigned char *src,
int stride,
int filter_limit)
{
int i;
for (i = 0; i < 16; i++)
{
if (simple_threshold(src, stride, filter_limit))
filter_common(src, stride, 1);
src += 1;
}
}
static void
calculate_filter_parameters(struct vp8_decoder_ctx *ctx,
struct mb_info *mbi,
int *edge_limit_,
int *interior_limit_,
int *hev_threshold_)
{
int filter_level, interior_limit, hev_threshold;
/* Reference code/spec seems to conflate filter_level and
* edge_limit
*/
filter_level = ctx->loopfilter_hdr.level;
if (ctx->segment_hdr.enabled)
{
if (!ctx->segment_hdr.abs)
filter_level +=
ctx->segment_hdr.lf_level[mbi->base.segment_id];
else
filter_level =
ctx->segment_hdr.lf_level[mbi->base.segment_id];
}
if (ctx->loopfilter_hdr.delta_enabled)
{
filter_level +=
ctx->loopfilter_hdr.ref_delta[mbi->base.ref_frame];
if (mbi->base.ref_frame == CURRENT_FRAME)
{
if (mbi->base.y_mode == B_PRED)
filter_level += ctx->loopfilter_hdr.mode_delta[0];
}
else if (mbi->base.y_mode == ZEROMV)
filter_level += ctx->loopfilter_hdr.mode_delta[1];
else if (mbi->base.y_mode == SPLITMV)
filter_level += ctx->loopfilter_hdr.mode_delta[3];
else
filter_level += ctx->loopfilter_hdr.mode_delta[2];
}
if (filter_level > 63)
filter_level = 63;
else if (filter_level < 0)
filter_level = 0;
interior_limit = filter_level;
if (ctx->loopfilter_hdr.sharpness)
{
interior_limit >>= ctx->loopfilter_hdr.sharpness > 4 ? 2 : 1;
if (interior_limit > 9 - ctx->loopfilter_hdr.sharpness)
interior_limit = 9 - ctx->loopfilter_hdr.sharpness;
}
if (interior_limit < 1)
interior_limit = 1;
hev_threshold = (filter_level >= 15);
if (filter_level >= 40)
hev_threshold++;
if (filter_level >= 20 && !ctx->frame_hdr.is_keyframe)
hev_threshold++;
*edge_limit_ = filter_level;
*interior_limit_ = interior_limit;
*hev_threshold_ = hev_threshold;
}
static void
filter_row_normal(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
unsigned char *y, *u, *v;
int stride, uv_stride;
struct mb_info *mbi;
unsigned int col;
/* Adjust pointers based on row, start_col */
stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
uv_stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U];
y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
u = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_U];
v = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_V];
y += (stride * row + start_col) * 16;
u += (uv_stride * row + start_col) * 8;
v += (uv_stride * row + start_col) * 8;
mbi = ctx->mb_info_rows[row] + start_col;
for (col = start_col; col < start_col + num_cols; col++)
{
int edge_limit, interior_limit, hev_threshold;
/* TODO: only need to recalculate every MB if segmentation is
* enabled.
*/
calculate_filter_parameters(ctx, mbi, &edge_limit,
&interior_limit, &hev_threshold);
if (edge_limit)
{
if (col)
{
filter_mb_v_edge(y, stride, edge_limit + 2,
interior_limit, hev_threshold, 2);
filter_mb_v_edge(u, uv_stride, edge_limit + 2,
interior_limit, hev_threshold, 1);
filter_mb_v_edge(v, uv_stride, edge_limit + 2,
interior_limit, hev_threshold, 1);
}
/* NOTE: This conditional is actually dependent on the
* number of coefficients decoded, not the skip flag as
* coded in the bitstream. The tokens task is expected to
* set 31 if there is *any* non-zero data.
*/
if (mbi->base.eob_mask
|| mbi->base.y_mode == SPLITMV
|| mbi->base.y_mode == B_PRED)
{
filter_subblock_v_edge(y + 4, stride, edge_limit,
interior_limit, hev_threshold,
2);
filter_subblock_v_edge(y + 8, stride, edge_limit,
interior_limit, hev_threshold,
2);
filter_subblock_v_edge(y + 12, stride, edge_limit,
interior_limit, hev_threshold,
2);
filter_subblock_v_edge(u + 4, uv_stride, edge_limit,
interior_limit, hev_threshold,
1);
filter_subblock_v_edge(v + 4, uv_stride, edge_limit,
interior_limit, hev_threshold,
1);
}
if (row)
{
filter_mb_h_edge(y, stride, edge_limit + 2,
interior_limit, hev_threshold, 2);
filter_mb_h_edge(u, uv_stride, edge_limit + 2,
interior_limit, hev_threshold, 1);
filter_mb_h_edge(v, uv_stride, edge_limit + 2,
interior_limit, hev_threshold, 1);
}
if (mbi->base.eob_mask
|| mbi->base.y_mode == SPLITMV
|| mbi->base.y_mode == B_PRED)
{
filter_subblock_h_edge(y + 4 * stride, stride,
edge_limit, interior_limit,
hev_threshold, 2);
filter_subblock_h_edge(y + 8 * stride, stride,
edge_limit, interior_limit,
hev_threshold, 2);
filter_subblock_h_edge(y + 12 * stride, stride,
edge_limit, interior_limit,
hev_threshold, 2);
filter_subblock_h_edge(u + 4 * uv_stride, uv_stride,
edge_limit, interior_limit,
hev_threshold, 1);
filter_subblock_h_edge(v + 4 * uv_stride, uv_stride,
edge_limit, interior_limit,
hev_threshold, 1);
}
}
y += 16;
u += 8;
v += 8;
mbi++;
}
}
static void
filter_row_simple(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
unsigned char *y;
int stride;
struct mb_info *mbi;
unsigned int col;
/* Adjust pointers based on row, start_col */
stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
y += (stride * row + start_col) * 16;
mbi = ctx->mb_info_rows[row] + start_col;
for (col = start_col; col < start_col + num_cols; col++)
{
int edge_limit, interior_limit, hev_threshold;
/* TODO: only need to recalculate every MB if segmentation is
* enabled.
*/
calculate_filter_parameters(ctx, mbi, &edge_limit,
&interior_limit, &hev_threshold);
if (edge_limit)
{
/* NOTE: This conditional is actually dependent on the
* number of coefficients decoded, not the skip flag as
* coded in the bitstream. The tokens task is expected to
* set 31 if there is *any* non-zero data.
*/
int filter_subblocks = (mbi->base.eob_mask
|| mbi->base.y_mode == SPLITMV
|| mbi->base.y_mode == B_PRED);
int mb_limit = (edge_limit + 2) * 2 + interior_limit;
int b_limit = edge_limit * 2 + interior_limit;
if (col)
filter_v_edge_simple(y, stride, mb_limit);
if (filter_subblocks)
{
filter_v_edge_simple(y + 4, stride, b_limit);
filter_v_edge_simple(y + 8, stride, b_limit);
filter_v_edge_simple(y + 12, stride, b_limit);
}
if (row)
filter_h_edge_simple(y, stride, mb_limit);
if (filter_subblocks)
{
filter_h_edge_simple(y + 4 * stride, stride, b_limit);
filter_h_edge_simple(y + 8 * stride, stride, b_limit);
filter_h_edge_simple(y + 12 * stride, stride, b_limit);
}
}
y += 16;
mbi++;
}
}
void
vp8_dixie_loopfilter_process_row(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
if (ctx->loopfilter_hdr.use_simple)
filter_row_simple(ctx, row, start_col, num_cols);
else
filter_row_normal(ctx, row, start_col, num_cols);
}
---- End code block ----------------------------------------
21.7. dixie_loopfilter.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef DIXIE_LOOPFILTER_H
#define DIXIE_LOOPFILTER_H
void
vp8_dixie_loopfilter_process_row(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols);
#endif
---- End code block ----------------------------------------
21.8. idct_add.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "dixie.h"
#include "idct_add.h"
#include <assert.h>
void
vp8_dixie_walsh(const short *input, short *output)
{
int i;
int a1, b1, c1, d1;
int a2, b2, c2, d2;
const short *ip = input;
short *op = output;
for (i = 0; i < 4; i++)
{
a1 = ip[0] + ip[12];
b1 = ip[4] + ip[8];
c1 = ip[4] - ip[8];
d1 = ip[0] - ip[12];
op[0] = a1 + b1;
op[4] = c1 + d1;
op[8] = a1 - b1;
op[12] = d1 - c1;
ip++;
op++;
}
ip = output;
op = output;
for (i = 0; i < 4; i++)
{
a1 = ip[0] + ip[3];
b1 = ip[1] + ip[2];
c1 = ip[1] - ip[2];
d1 = ip[0] - ip[3];
a2 = a1 + b1;
b2 = c1 + d1;
c2 = a1 - b1;
d2 = d1 - c1;
op[0] = (a2 + 3) >> 3;
op[1] = (b2 + 3) >> 3;
op[2] = (c2 + 3) >> 3;
op[3] = (d2 + 3) >> 3;
ip += 4;
op += 4;
}
}
#define cospi8sqrt2minus1 20091
#define sinpi8sqrt2 35468
#define rounding 0
static void
idct_columns(const short *input, short *output)
{
int i;
int a1, b1, c1, d1;
const short *ip = input;
short *op = output;
int temp1, temp2;
int shortpitch = 4;
for (i = 0; i < 4; i++)
{
a1 = ip[0] + ip[8];
b1 = ip[0] - ip[8];
temp1 = (ip[4] * sinpi8sqrt2 + rounding) >> 16;
temp2 = ip[12] +
((ip[12] * cospi8sqrt2minus1 + rounding) >> 16);
c1 = temp1 - temp2;
temp1 = ip[4] +
((ip[4] * cospi8sqrt2minus1 + rounding) >> 16);
temp2 = (ip[12] * sinpi8sqrt2 + rounding) >> 16;
d1 = temp1 + temp2;
op[shortpitch*0] = a1 + d1;
op[shortpitch*3] = a1 - d1;
op[shortpitch*1] = b1 + c1;
op[shortpitch*2] = b1 - c1;
ip++;
op++;
}
}
void
vp8_dixie_idct_add(unsigned char *recon,
const unsigned char *predict,
int stride,
const short *coeffs)
{
int i;
int a1, b1, c1, d1, temp1, temp2;
short tmp[16];
idct_columns(coeffs, tmp);
coeffs = tmp;
for (i = 0; i < 4; i++)
{
a1 = coeffs[0] + coeffs[2];
b1 = coeffs[0] - coeffs[2];
temp1 = (coeffs[1] * sinpi8sqrt2 + rounding) >> 16;
temp2 = coeffs[3] +
((coeffs[3] * cospi8sqrt2minus1 + rounding) >> 16);
c1 = temp1 - temp2;
temp1 = coeffs[1] +
((coeffs[1] * cospi8sqrt2minus1 + rounding) >> 16);
temp2 = (coeffs[3] * sinpi8sqrt2 + rounding) >> 16;
d1 = temp1 + temp2;
recon[0] = CLAMP_255(predict[0] + ((a1 + d1 + 4) >> 3));
recon[3] = CLAMP_255(predict[3] + ((a1 - d1 + 4) >> 3));
recon[1] = CLAMP_255(predict[1] + ((b1 + c1 + 4) >> 3));
recon[2] = CLAMP_255(predict[2] + ((b1 - c1 + 4) >> 3));
coeffs += 4;
recon += stride;
predict += stride;
}
}
---- End code block ----------------------------------------
21.9. idct_add.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef IDCT_ADD_H
#define IDCT_ADD_H
void
vp8_dixie_idct_add_init(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_idct_add(unsigned char *recon,
const unsigned char *predict,
int stride,
const short *coeffs);
void
vp8_dixie_walsh(const short *in, short *out);
void
vp8_dixie_idct_add_process_row(struct vp8_decoder_ctx *ctx,
short *coeffs,
unsigned int row,
unsigned int start_col,
unsigned int num_cols);
#endif
---- End code block ----------------------------------------
21.10. mem.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_PORTS_MEM_H
#define VPX_PORTS_MEM_H
#include "vpx_config.h"
#include "vpx_integer.h"
#if defined(__GNUC__) && __GNUC__
#define DECLARE_ALIGNED(n,typ,val) typ val __attribute__ \
((aligned (n)))
#elif defined(_MSC_VER)
#define DECLARE_ALIGNED(n,typ,val) __declspec(align(n)) typ val
#else
#warning No alignment directives known for this compiler.
#define DECLARE_ALIGNED(n,typ,val) typ val
#endif
#endif
/* Declare an aligned array on the stack, for situations where the
* stack pointer may not have the alignment we expect. Creates an
* array with a modified name, then defines val to be a pointer, and
* aligns that pointer within the array.
*/
#define DECLARE_ALIGNED_ARRAY(a,typ,val,n)\
typ val##_[(n)+(a)/sizeof(typ)+1];\
typ *val = (typ*)((((intptr_t)val##_)+(a)-1)&((intptr_t)-(a)))
/* Indicates that the usage of the specified variable has been
* audited to assure that it's safe to use uninitialized. Silences
* 'may be used uninitialized' warnings on gcc.
*/
#if defined(__GNUC__) && __GNUC__
#define UNINITIALIZED_IS_SAFE(x) x=x
#else
#define UNINITIALIZED_IS_SAFE(x) x
#endif
---- End code block ----------------------------------------
21.11. modemv.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "dixie.h"
#include "modemv_data.h"
#include <stdlib.h>
#include <assert.h>
struct mv_clamp_rect
{
int to_left, to_right, to_top, to_bottom;
};
static union mv
clamp_mv(union mv raw, const struct mv_clamp_rect *bounds)
{
union mv newmv;
newmv.d.x = (raw.d.x < bounds->to_left)
? bounds->to_left : raw.d.x;
newmv.d.x = (raw.d.x > bounds->to_right)
? bounds->to_right : newmv.d.x;
newmv.d.y = (raw.d.y < bounds->to_top)
? bounds->to_top : raw.d.y;
newmv.d.y = (raw.d.y > bounds->to_bottom)
? bounds->to_bottom : newmv.d.y;
return newmv;
}
static int
read_segment_id(struct bool_decoder *bool,
struct vp8_segment_hdr *seg)
{
return bool_get(bool, seg->tree_probs[0])
? 2 + bool_get(bool, seg->tree_probs[2])
: bool_get(bool, seg->tree_probs[1]);
}
static enum prediction_mode
above_block_mode(const struct mb_info *this,
const struct mb_info *above,
unsigned int b)
{
if (b < 4)
{
switch (above->base.y_mode)
{
case DC_PRED:
return B_DC_PRED;
case V_PRED:
return B_VE_PRED;
case H_PRED:
return B_HE_PRED;
case TM_PRED:
return B_TM_PRED;
case B_PRED:
return above->split.modes[b+12];
default:
assert(0);
}
}
return this->split.modes[b-4];
}
static enum prediction_mode
left_block_mode(const struct mb_info *this,
const struct mb_info *left,
unsigned int b)
{
if (!(b & 3))
{
switch (left->base.y_mode)
{
case DC_PRED:
return B_DC_PRED;
case V_PRED:
return B_VE_PRED;
case H_PRED:
return B_HE_PRED;
case TM_PRED:
return B_TM_PRED;
case B_PRED:
return left->split.modes[b+3];
default:
assert(0);
}
}
return this->split.modes[b-1];
}
static void
decode_kf_mb_mode(struct mb_info *this,
struct mb_info *left,
struct mb_info *above,
struct bool_decoder *bool)
{
int y_mode, uv_mode;
y_mode = bool_read_tree(bool, kf_y_mode_tree, kf_y_mode_probs);
if (y_mode == B_PRED)
{
unsigned int i;
for (i = 0; i < 16; i++)
{
enum prediction_mode a = above_block_mode(this, above, i);
enum prediction_mode l = left_block_mode(this, left, i);
enum prediction_mode b;
b = bool_read_tree(bool, b_mode_tree,
kf_b_mode_probs[a][l]);
this->split.modes[i] = b;
}
}
uv_mode = bool_read_tree(bool, uv_mode_tree, kf_uv_mode_probs);
this->base.y_mode = y_mode;
this->base.uv_mode = uv_mode;
this->base.mv.raw = 0;
this->base.ref_frame = 0;
}
static void
decode_intra_mb_mode(struct mb_info *this,
struct vp8_entropy_hdr *hdr,
struct bool_decoder *bool)
{
/* Like decode_kf_mb_mode, but with probabilities transmitted in the
* bitstream and no context on the above/left block mode.
*/
int y_mode, uv_mode;
y_mode = bool_read_tree(bool, y_mode_tree, hdr->y_mode_probs);
if (y_mode == B_PRED)
{
unsigned int i;
for (i = 0; i < 16; i++)
{
enum prediction_mode b;
b = bool_read_tree(bool, b_mode_tree, default_b_mode_probs);
this->split.modes[i] = b;
}
}
uv_mode = bool_read_tree(bool, uv_mode_tree, hdr->uv_mode_probs);
this->base.y_mode = y_mode;
this->base.uv_mode = uv_mode;
this->base.mv.raw = 0;
this->base.ref_frame = CURRENT_FRAME;
}
static int
read_mv_component(struct bool_decoder *bool,
const unsigned char mvc[MV_PROB_CNT])
{
enum {IS_SHORT, SIGN, SHORT, BITS = SHORT + 8 - 1, LONG_WIDTH = 10};
int x = 0;
if (bool_get(bool, mvc[IS_SHORT])) /* Large */
{
int i = 0;
for (i = 0; i < 3; i++)
x += bool_get(bool, mvc[BITS + i]) << i;
/* Skip bit 3, which is sometimes implicit */
for (i = LONG_WIDTH - 1; i > 3; i--)
x += bool_get(bool, mvc[BITS + i]) << i;
if (!(x & 0xFFF0) || bool_get(bool, mvc[BITS + 3]))
x += 8;
}
else /* small */
x = bool_read_tree(bool, small_mv_tree, mvc + SHORT);
if (x && bool_get(bool, mvc[SIGN]))
x = -x;
return x << 1;
}
static mv_t
above_block_mv(const struct mb_info *this,
const struct mb_info *above,
unsigned int b)
{
if (b < 4)
{
if (above->base.y_mode == SPLITMV)
return above->split.mvs[b+12];
return above->base.mv;
}
return this->split.mvs[b-4];
}
static mv_t
left_block_mv(const struct mb_info *this,
const struct mb_info *left,
unsigned int b)
{
if (!(b & 3))
{
if (left->base.y_mode == SPLITMV)
return left->split.mvs[b+3];
return left->base.mv;
}
return this->split.mvs[b-1];
}
static enum prediction_mode
submv_ref(struct bool_decoder *bool, union mv l, union mv a)
{
enum subblock_mv_ref
{
SUBMVREF_NORMAL,
SUBMVREF_LEFT_ZED,
SUBMVREF_ABOVE_ZED,
SUBMVREF_LEFT_ABOVE_SAME,
SUBMVREF_LEFT_ABOVE_ZED
};
int lez = !(l.raw);
int aez = !(a.raw);
int lea = l.raw == a.raw;
enum subblock_mv_ref ctx = SUBMVREF_NORMAL;
if (lea && lez)
ctx = SUBMVREF_LEFT_ABOVE_ZED;
else if (lea)
ctx = SUBMVREF_LEFT_ABOVE_SAME;
else if (aez)
ctx = SUBMVREF_ABOVE_ZED;
else if (lez)
ctx = SUBMVREF_LEFT_ZED;
return bool_read_tree(bool, submv_ref_tree, submv_ref_probs2[ctx]);
}
static void
read_mv(struct bool_decoder *bool,
union mv *mv,
mv_component_probs_t mvc[2])
{
mv->d.y = read_mv_component(bool, mvc[0]);
mv->d.x = read_mv_component(bool, mvc[1]);
}
static void
mv_bias(const struct mb_info *mb,
const unsigned int sign_bias[3],
enum reference_frame ref_frame,
union mv *mv)
{
if (sign_bias[mb->base.ref_frame] ^ sign_bias[ref_frame])
{
mv->d.x *= -1;
mv->d.y *= -1;
}
}
enum near_mv_v
{
CNT_BEST = 0,
CNT_ZEROZERO = 0,
CNT_NEAREST,
CNT_NEAR,
CNT_SPLITMV
};
static void
find_near_mvs(const struct mb_info *this,
const struct mb_info *left,
const struct mb_info *above,
const unsigned int sign_bias[3],
union mv near_mvs[4],
int cnt[4])
{
const struct mb_info *aboveleft = above - 1;
union mv *mv = near_mvs;
int *cntx = cnt;
/* Zero accumulators */
mv[0].raw = mv[1].raw = mv[2].raw = 0;
cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
/* Process above */
if (above->base.ref_frame != CURRENT_FRAME)
{
if (above->base.mv.raw)
{
(++mv)->raw = above->base.mv.raw;
mv_bias(above, sign_bias, this->base.ref_frame, mv);
++cntx;
}
*cntx += 2;
}
/* Process left */
if (left->base.ref_frame != CURRENT_FRAME)
{
if (left->base.mv.raw)
{
union mv this_mv;
this_mv.raw = left->base.mv.raw;
mv_bias(left, sign_bias, this->base.ref_frame, &this_mv);
if (this_mv.raw != mv->raw)
{
(++mv)->raw = this_mv.raw;
++cntx;
}
*cntx += 2;
}
else
cnt[CNT_ZEROZERO] += 2;
}
/* Process above left */
if (aboveleft->base.ref_frame != CURRENT_FRAME)
{
if (aboveleft->base.mv.raw)
{
union mv this_mv;
this_mv.raw = aboveleft->base.mv.raw;
mv_bias(aboveleft, sign_bias, this->base.ref_frame,
&this_mv);
if (this_mv.raw != mv->raw)
{
(++mv)->raw = this_mv.raw;
++cntx;
}
*cntx += 1;
}
else
cnt[CNT_ZEROZERO] += 1;
}
/* If we have three distinct MV's ... */
if (cnt[CNT_SPLITMV])
{
/* See if above-left MV can be merged with NEAREST */
if (mv->raw == near_mvs[CNT_NEAREST].raw)
cnt[CNT_NEAREST] += 1;
}
cnt[CNT_SPLITMV] = ((above->base.y_mode == SPLITMV)
+ (left->base.y_mode == SPLITMV)) * 2
+ (aboveleft->base.y_mode == SPLITMV);
/* Swap near and nearest if necessary */
if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
{
int tmp;
tmp = cnt[CNT_NEAREST];
cnt[CNT_NEAREST] = cnt[CNT_NEAR];
cnt[CNT_NEAR] = tmp;
tmp = near_mvs[CNT_NEAREST].raw;
near_mvs[CNT_NEAREST].raw = near_mvs[CNT_NEAR].raw;
near_mvs[CNT_NEAR].raw = tmp;
}
/* Use near_mvs[CNT_BEST] to store the "best" MV. Note that this
* storage shares the same address as near_mvs[CNT_ZEROZERO].
*/
if (cnt[CNT_NEAREST] >= cnt[CNT_BEST])
near_mvs[CNT_BEST] = near_mvs[CNT_NEAREST];
}
static void
decode_split_mv(struct mb_info *this,
const struct mb_info *left,
const struct mb_info *above,
struct vp8_entropy_hdr *hdr,
union mv *best_mv,
struct bool_decoder *bool)
{
const int *partition;
int j, k, mask, partition_id;
partition_id = bool_read_tree(bool, split_mv_tree, split_mv_probs);
partition = mv_partitions[partition_id];
this->base.partitioning = partition_id;
for (j = 0, mask = 0; mask < 65535; j++)
{
union mv mv, left_mv, above_mv;
enum prediction_mode subblock_mode;
/* Find the first subblock in this partition. */
for (k = 0; j != partition[k]; k++);
/* Decode the next MV */
left_mv = left_block_mv(this, left, k);
above_mv = above_block_mv(this, above, k);
subblock_mode = submv_ref(bool, left_mv, above_mv);
switch (subblock_mode)
{
case LEFT4X4:
mv = left_mv;
break;
case ABOVE4X4:
mv = above_mv;
break;
case ZERO4X4:
mv.raw = 0;
break;
case NEW4X4:
read_mv(bool, &mv, hdr->mv_probs);
mv.d.x += best_mv->d.x;
mv.d.y += best_mv->d.y;
break;
default:
assert(0);
}
/* Fill the MV's for this partition */
for (; k < 16; k++)
if (j == partition[k])
{
this->split.mvs[k] = mv;
mask |= 1 << k;
}
}
}
static int
need_mc_border(union mv mv, int l, int t, int b_w, int w, int h)
{
int b, r;
/* Get distance to edge for top-left pixel */
l += (mv.d.x >> 3);
t += (mv.d.y >> 3);
/* Get distance to edge for bottom-right pixel */
r = w - (l + b_w);
b = h - (t + b_w);
return (l >> 1 < 2 || r >> 1 < 3 || t >> 1 < 2 || b >> 1 < 3);
}
static void
decode_mvs(struct vp8_decoder_ctx *ctx,
struct mb_info *this,
const struct mb_info *left,
const struct mb_info *above,
const struct mv_clamp_rect *bounds,
struct bool_decoder *bool)
{
struct vp8_entropy_hdr *hdr = &ctx->entropy_hdr;
union mv near_mvs[4];
union mv clamped_best_mv;
int mv_cnts[4];
unsigned char probs[4];
enum {BEST, NEAREST, NEAR};
int x, y, w, h, b;
this->base.ref_frame = bool_get(bool, hdr->prob_last)
? 2 + bool_get(bool, hdr->prob_gf)
: 1;
find_near_mvs(this, this - 1, above, ctx->reference_hdr.sign_bias,
near_mvs, mv_cnts);
probs[0] = mv_counts_to_probs[mv_cnts[0]][0];
probs[1] = mv_counts_to_probs[mv_cnts[1]][1];
probs[2] = mv_counts_to_probs[mv_cnts[2]][2];
probs[3] = mv_counts_to_probs[mv_cnts[3]][3];
this->base.y_mode = bool_read_tree(bool, mv_ref_tree, probs);
this->base.uv_mode = this->base.y_mode;
this->base.need_mc_border = 0;
x = (-bounds->to_left - 128) >> 3;
y = (-bounds->to_top - 128) >> 3;
w = ctx->mb_cols * 16;
h = ctx->mb_rows * 16;
switch (this->base.y_mode)
{
case NEARESTMV:
this->base.mv = clamp_mv(near_mvs[NEAREST], bounds);
break;
case NEARMV:
this->base.mv = clamp_mv(near_mvs[NEAR], bounds);
break;
case ZEROMV:
this->base.mv.raw = 0;
return; //skip need_mc_border check
case NEWMV:
clamped_best_mv = clamp_mv(near_mvs[BEST], bounds);
read_mv(bool, &this->base.mv, hdr->mv_probs);
this->base.mv.d.x += clamped_best_mv.d.x;
this->base.mv.d.y += clamped_best_mv.d.y;
break;
case SPLITMV:
{
union mv chroma_mv[4] = {{{0}}};
clamped_best_mv = clamp_mv(near_mvs[BEST], bounds);
decode_split_mv(this, left, above, hdr, &clamped_best_mv, bool);
this->base.mv = this->split.mvs[15];
for (b = 0; b < 16; b++)
{
chroma_mv[(b>>1&1) + (b>>2&2)].d.x +=
this->split.mvs[b].d.x;
chroma_mv[(b>>1&1) + (b>>2&2)].d.y +=
this->split.mvs[b].d.y;
if (need_mc_border(this->split.mvs[b],
x + (b & 3) * 4, y + (b & ~3), 4, w, h))
{
this->base.need_mc_border = 1;
break;
}
}
for (b = 0; b < 4; b++)
{
chroma_mv[b].d.x += 4 + 8 * (chroma_mv[b].d.x >> 31);
chroma_mv[b].d.y += 4 + 8 * (chroma_mv[b].d.y >> 31);
chroma_mv[b].d.x /= 4;
chroma_mv[b].d.y /= 4;
//note we're passing in non-subsampled coordinates
if (need_mc_border(chroma_mv[b],
x + (b & 1) * 8, y + (b >> 1) * 8, 16, w, h))
{
this->base.need_mc_border = 1;
break;
}
}
return; //skip need_mc_border check
}
default:
assert(0);
}
if (need_mc_border(this->base.mv, x, y, 16, w, h))
this->base.need_mc_border = 1;
}
void
vp8_dixie_modemv_process_row(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
int row,
int start_col,
int num_cols)
{
struct mb_info *above, *this;
unsigned int col;
struct mv_clamp_rect bounds;
this = ctx->mb_info_rows[row] + start_col;
above = ctx->mb_info_rows[row - 1] + start_col;
/* Calculate the eighth-pel MV bounds using a 1 MB border. */
bounds.to_left = -((start_col + 1) << 7);
bounds.to_right = (ctx->mb_cols - start_col) << 7;
bounds.to_top = -((row + 1) << 7);
bounds.to_bottom = (ctx->mb_rows - row) << 7;
for (col = start_col; col < start_col + num_cols; col++)
{
if (ctx->segment_hdr.update_map)
this->base.segment_id = read_segment_id(bool,
&ctx->segment_hdr);
if (ctx->entropy_hdr.coeff_skip_enabled)
this->base.skip_coeff = bool_get(bool,
ctx->entropy_hdr.coeff_skip_prob);
if (ctx->frame_hdr.is_keyframe)
{
if (!ctx->segment_hdr.update_map)
this->base.segment_id = 0;
decode_kf_mb_mode(this, this - 1, above, bool);
}
else
{
if (bool_get(bool, ctx->entropy_hdr.prob_inter))
decode_mvs(ctx, this, this - 1, above, &bounds, bool);
else
decode_intra_mb_mode(this, &ctx->entropy_hdr, bool);
bounds.to_left -= 16 << 3;
bounds.to_right -= 16 << 3;
}
/* Advance to next mb */
this++;
above++;
}
}
void
vp8_dixie_modemv_init(struct vp8_decoder_ctx *ctx)
{
unsigned int mbi_w, mbi_h, i;
struct mb_info *mbi;
mbi_w = ctx->mb_cols + 1; /* For left border col */
mbi_h = ctx->mb_rows + 1; /* For above border row */
if (ctx->frame_hdr.frame_size_updated)
{
free(ctx->mb_info_storage);
ctx->mb_info_storage = NULL;
free(ctx->mb_info_rows_storage);
ctx->mb_info_rows_storage = NULL;
}
if (!ctx->mb_info_storage)
ctx->mb_info_storage = calloc(mbi_w * mbi_h,
sizeof(*ctx->mb_info_storage));
if (!ctx->mb_info_rows_storage)
ctx->mb_info_rows_storage = calloc(mbi_h,
sizeof(*ctx->mb_info_rows_storage));
/* Set up row pointers */
mbi = ctx->mb_info_storage + 1;
for (i = 0; i < mbi_h; i++)
{
ctx->mb_info_rows_storage[i] = mbi;
mbi += mbi_w;
}
ctx->mb_info_rows = ctx->mb_info_rows_storage + 1;
}
void
vp8_dixie_modemv_destroy(struct vp8_decoder_ctx *ctx)
{
free(ctx->mb_info_storage);
ctx->mb_info_storage = NULL;
free(ctx->mb_info_rows_storage);
ctx->mb_info_rows_storage = NULL;
}
---- End code block ----------------------------------------
21.12. modemv.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODEMV_H
#define MODEMV_H
void
vp8_dixie_modemv_init(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_modemv_destroy(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_modemv_process_row(struct vp8_decoder_ctx *ctx,
struct bool_decoder *bool,
int row,
int start_col,
int num_cols);
#endif
---- End code block ----------------------------------------
21.13. modemv_data.h
---- Begin code block --------------------------------------
static const unsigned char kf_y_mode_probs[] = { 145, 156, 163, 128};
static const unsigned char kf_uv_mode_probs[] = { 142, 114, 183};
static const unsigned char kf_b_mode_probs[10][10][9] =
{
{ /* above mode 0 */
{ /* left mode 0 */ 231, 120, 48, 89, 115, 113, 120, 152, 112},
{ /* left mode 1 */ 152, 179, 64, 126, 170, 118, 46, 70, 95},
{ /* left mode 2 */ 175, 69, 143, 80, 85, 82, 72, 155, 103},
{ /* left mode 3 */ 56, 58, 10, 171, 218, 189, 17, 13, 152},
{ /* left mode 4 */ 144, 71, 10, 38, 171, 213, 144, 34, 26},
{ /* left mode 5 */ 114, 26, 17, 163, 44, 195, 21, 10, 173},
{ /* left mode 6 */ 121, 24, 80, 195, 26, 62, 44, 64, 85},
{ /* left mode 7 */ 170, 46, 55, 19, 136, 160, 33, 206, 71},
{ /* left mode 8 */ 63, 20, 8, 114, 114, 208, 12, 9, 226},
{ /* left mode 9 */ 81, 40, 11, 96, 182, 84, 29, 16, 36}
},
{ /* above mode 1 */
{ /* left mode 0 */ 134, 183, 89, 137, 98, 101, 106, 165, 148},
{ /* left mode 1 */ 72, 187, 100, 130, 157, 111, 32, 75, 80},
{ /* left mode 2 */ 66, 102, 167, 99, 74, 62, 40, 234, 128},
{ /* left mode 3 */ 41, 53, 9, 178, 241, 141, 26, 8, 107},
{ /* left mode 4 */ 104, 79, 12, 27, 217, 255, 87, 17, 7},
{ /* left mode 5 */ 74, 43, 26, 146, 73, 166, 49, 23, 157},
{ /* left mode 6 */ 65, 38, 105, 160, 51, 52, 31, 115, 128},
{ /* left mode 7 */ 87, 68, 71, 44, 114, 51, 15, 186, 23},
{ /* left mode 8 */ 47, 41, 14, 110, 182, 183, 21, 17, 194},
{ /* left mode 9 */ 66, 45, 25, 102, 197, 189, 23, 18, 22}
},
{ /* above mode 2 */
{ /* left mode 0 */ 88, 88, 147, 150, 42, 46, 45, 196, 205},
{ /* left mode 1 */ 43, 97, 183, 117, 85, 38, 35, 179, 61},
{ /* left mode 2 */ 39, 53, 200, 87, 26, 21, 43, 232, 171},
{ /* left mode 3 */ 56, 34, 51, 104, 114, 102, 29, 93, 77},
{ /* left mode 4 */ 107, 54, 32, 26, 51, 1, 81, 43, 31},
{ /* left mode 5 */ 39, 28, 85, 171, 58, 165, 90, 98, 64},
{ /* left mode 6 */ 34, 22, 116, 206, 23, 34, 43, 166, 73},
{ /* left mode 7 */ 68, 25, 106, 22, 64, 171, 36, 225, 114},
{ /* left mode 8 */ 34, 19, 21, 102, 132, 188, 16, 76, 124},
{ /* left mode 9 */ 62, 18, 78, 95, 85, 57, 50, 48, 51}
},
{ /* above mode 3 */
{ /* left mode 0 */ 193, 101, 35, 159, 215, 111, 89, 46, 111},
{ /* left mode 1 */ 60, 148, 31, 172, 219, 228, 21, 18, 111},
{ /* left mode 2 */ 112, 113, 77, 85, 179, 255, 38, 120, 114},
{ /* left mode 3 */ 40, 42, 1, 196, 245, 209, 10, 25, 109},
{ /* left mode 4 */ 100, 80, 8, 43, 154, 1, 51, 26, 71},
{ /* left mode 5 */ 88, 43, 29, 140, 166, 213, 37, 43, 154},
{ /* left mode 6 */ 61, 63, 30, 155, 67, 45, 68, 1, 209},
{ /* left mode 7 */ 142, 78, 78, 16, 255, 128, 34, 197, 171},
{ /* left mode 8 */ 41, 40, 5, 102, 211, 183, 4, 1, 221},
{ /* left mode 9 */ 51, 50, 17, 168, 209, 192, 23, 25, 82}
},
{ /* above mode 4 */
{ /* left mode 0 */ 125, 98, 42, 88, 104, 85, 117, 175, 82},
{ /* left mode 1 */ 95, 84, 53, 89, 128, 100, 113, 101, 45},
{ /* left mode 2 */ 75, 79, 123, 47, 51, 128, 81, 171, 1},
{ /* left mode 3 */ 57, 17, 5, 71, 102, 57, 53, 41, 49},
{ /* left mode 4 */ 115, 21, 2, 10, 102, 255, 166, 23, 6},
{ /* left mode 5 */ 38, 33, 13, 121, 57, 73, 26, 1, 85},
{ /* left mode 6 */ 41, 10, 67, 138, 77, 110, 90, 47, 114},
{ /* left mode 7 */ 101, 29, 16, 10, 85, 128, 101, 196, 26},
{ /* left mode 8 */ 57, 18, 10, 102, 102, 213, 34, 20, 43},
{ /* left mode 9 */ 117, 20, 15, 36, 163, 128, 68, 1, 26}
},
{ /* above mode 5 */
{ /* left mode 0 */ 138, 31, 36, 171, 27, 166, 38, 44, 229},
{ /* left mode 1 */ 67, 87, 58, 169, 82, 115, 26, 59, 179},
{ /* left mode 2 */ 63, 59, 90, 180, 59, 166, 93, 73, 154},
{ /* left mode 3 */ 40, 40, 21, 116, 143, 209, 34, 39, 175},
{ /* left mode 4 */ 57, 46, 22, 24, 128, 1, 54, 17, 37},
{ /* left mode 5 */ 47, 15, 16, 183, 34, 223, 49, 45, 183},
{ /* left mode 6 */ 46, 17, 33, 183, 6, 98, 15, 32, 183},
{ /* left mode 7 */ 65, 32, 73, 115, 28, 128, 23, 128, 205},
{ /* left mode 8 */ 40, 3, 9, 115, 51, 192, 18, 6, 223},
{ /* left mode 9 */ 87, 37, 9, 115, 59, 77, 64, 21, 47}
},
{ /* above mode 6 */
{ /* left mode 0 */ 104, 55, 44, 218, 9, 54, 53, 130, 226},
{ /* left mode 1 */ 64, 90, 70, 205, 40, 41, 23, 26, 57},
{ /* left mode 2 */ 54, 57, 112, 184, 5, 41, 38, 166, 213},
{ /* left mode 3 */ 30, 34, 26, 133, 152, 116, 10, 32, 134},
{ /* left mode 4 */ 75, 32, 12, 51, 192, 255, 160, 43, 51},
{ /* left mode 5 */ 39, 19, 53, 221, 26, 114, 32, 73, 255},
{ /* left mode 6 */ 31, 9, 65, 234, 2, 15, 1, 118, 73},
{ /* left mode 7 */ 88, 31, 35, 67, 102, 85, 55, 186, 85},
{ /* left mode 8 */ 56, 21, 23, 111, 59, 205, 45, 37, 192},
{ /* left mode 9 */ 55, 38, 70, 124, 73, 102, 1, 34, 98}
},
{ /* above mode 7 */
{ /* left mode 0 */ 102, 61, 71, 37, 34, 53, 31, 243, 192},
{ /* left mode 1 */ 69, 60, 71, 38, 73, 119, 28, 222, 37},
{ /* left mode 2 */ 68, 45, 128, 34, 1, 47, 11, 245, 171},
{ /* left mode 3 */ 62, 17, 19, 70, 146, 85, 55, 62, 70},
{ /* left mode 4 */ 75, 15, 9, 9, 64, 255, 184, 119, 16},
{ /* left mode 5 */ 37, 43, 37, 154, 100, 163, 85, 160, 1},
{ /* left mode 6 */ 63, 9, 92, 136, 28, 64, 32, 201, 85},
{ /* left mode 7 */ 86, 6, 28, 5, 64, 255, 25, 248, 1},
{ /* left mode 8 */ 56, 8, 17, 132, 137, 255, 55, 116, 128},
{ /* left mode 9 */ 58, 15, 20, 82, 135, 57, 26, 121, 40}
},
{ /* above mode 8 */
{ /* left mode 0 */ 164, 50, 31, 137, 154, 133, 25, 35, 218},
{ /* left mode 1 */ 51, 103, 44, 131, 131, 123, 31, 6, 158},
{ /* left mode 2 */ 86, 40, 64, 135, 148, 224, 45, 183, 128},
{ /* left mode 3 */ 22, 26, 17, 131, 240, 154, 14, 1, 209},
{ /* left mode 4 */ 83, 12, 13, 54, 192, 255, 68, 47, 28},
{ /* left mode 5 */ 45, 16, 21, 91, 64, 222, 7, 1, 197},
{ /* left mode 6 */ 56, 21, 39, 155, 60, 138, 23, 102, 213},
{ /* left mode 7 */ 85, 26, 85, 85, 128, 128, 32, 146, 171},
{ /* left mode 8 */ 18, 11, 7, 63, 144, 171, 4, 4, 246},
{ /* left mode 9 */ 35, 27, 10, 146, 174, 171, 12, 26, 128}
},
{ /* above mode 9 */
{ /* left mode 0 */ 190, 80, 35, 99, 180, 80, 126, 54, 45},
{ /* left mode 1 */ 85, 126, 47, 87, 176, 51, 41, 20, 32},
{ /* left mode 2 */ 101, 75, 128, 139, 118, 146, 116, 128, 85},
{ /* left mode 3 */ 56, 41, 15, 176, 236, 85, 37, 9, 62},
{ /* left mode 4 */ 146, 36, 19, 30, 171, 255, 97, 27, 20},
{ /* left mode 5 */ 71, 30, 17, 119, 118, 255, 17, 18, 138},
{ /* left mode 6 */ 101, 38, 60, 138, 55, 70, 43, 26, 142},
{ /* left mode 7 */ 138, 45, 61, 62, 219, 1, 81, 188, 64},
{ /* left mode 8 */ 32, 41, 20, 117, 151, 142, 20, 21, 163},
{ /* left mode 9 */ 112, 19, 12, 61, 195, 128, 48, 4, 24}
}
};
static const int kf_y_mode_tree[] =
{
-B_PRED, 2,
4, 6,
-DC_PRED, -V_PRED,
-H_PRED, -TM_PRED
};
static const int y_mode_tree[] =
{
-DC_PRED, 2,
4, 6,
-V_PRED, -H_PRED,
-TM_PRED, -B_PRED
};
static const int uv_mode_tree[6] =
{
-DC_PRED, 2,
-V_PRED, 4,
-H_PRED, -TM_PRED
};
static const int b_mode_tree[18] =
{
-B_DC_PRED, 2, /* 0 = DC_NODE */
-B_TM_PRED, 4, /* 1 = TM_NODE */
-B_VE_PRED, 6, /* 2 = VE_NODE */
8, 12, /* 3 = COM_NODE */
-B_HE_PRED, 10, /* 4 = HE_NODE */
-B_RD_PRED, -B_VR_PRED, /* 5 = RD_NODE */
-B_LD_PRED, 14, /* 6 = LD_NODE */
-B_VL_PRED, 16, /* 7 = VL_NODE */
-B_HD_PRED, -B_HU_PRED /* 8 = HD_NODE */
};
static const int small_mv_tree[14] =
{
2, 8,
4, 6,
-0, -1,
-2, -3,
10, 12,
-4, -5,
-6, -7
};
static const int mv_ref_tree[8] =
{
-ZEROMV, 2,
-NEARESTMV, 4,
-NEARMV, 6,
-NEWMV, -SPLITMV
};
static const int submv_ref_tree[6] =
{
-LEFT4X4, 2,
-ABOVE4X4, 4,
-ZERO4X4, -NEW4X4
};
static const int split_mv_tree[6] =
{
-3, 2,
-2, 4,
-0, -1
};
static const unsigned char default_b_mode_probs[] =
{ 120, 90, 79, 133, 87, 85, 80, 111, 151};
static const unsigned char mv_counts_to_probs[6][4] =
{
{ 7, 1, 1, 143 },
{ 14, 18, 14, 107 },
{ 135, 64, 57, 68 },
{ 60, 56, 128, 65 },
{ 159, 134, 128, 34 },
{ 234, 188, 128, 28 }
};
static const unsigned char split_mv_probs[3] =
{ 110, 111, 150};
static const unsigned char submv_ref_probs2[5][3] =
{
{ 147, 136, 18 },
{ 106, 145, 1 },
{ 179, 121, 1 },
{ 223, 1, 34 },
{ 208, 1, 1 }
};
const static int mv_partitions[4][16] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
{0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 },
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
};
---- End code block ----------------------------------------
21.14. predict.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "dixie.h"
#include "predict.h"
#include "idct_add.h"
#include "mem.h"
#include <assert.h>
#include <string.h>
enum
{
BORDER_PIXELS = 16,
};
static const filter_t sixtap_filters[8] =
{
{ 0, 0, 128, 0, 0, 0 },
{ 0, -6, 123, 12, -1, 0 },
{ 2, -11, 108, 36, -8, 1 },
{ 0, -9, 93, 50, -6, 0 },
{ 3, -16, 77, 77, -16, 3 },
{ 0, -6, 50, 93, -9, 0 },
{ 1, -8, 36, 108, -11, 2 },
{ 0, -1, 12, 123, -6, 0 },
};
static const filter_t bilinear_filters[8] =
{
{ 0, 0, 128, 0, 0, 0 },
{ 0, 0, 112, 16, 0, 0 },
{ 0, 0, 96, 32, 0, 0 },
{ 0, 0, 80, 48, 0, 0 },
{ 0, 0, 64, 64, 0, 0 },
{ 0, 0, 48, 80, 0, 0 },
{ 0, 0, 32, 96, 0, 0 },
{ 0, 0, 16, 112, 0, 0 }
};
static void
predict_h_nxn(unsigned char *predict,
int stride,
int n)
{
unsigned char *left = predict - 1;
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
predict[i *stride + j] = left[i * stride];
}
static void
predict_v_nxn(unsigned char *predict,
int stride,
int n)
{
unsigned char *above = predict - stride;
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
predict[i *stride + j] = above[j];
}
static void
predict_tm_nxn(unsigned char *predict,
int stride,
int n)
{
/* Transposes the left column to the top row for later consumption
* by the idct/recon stage
*/
unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
unsigned char p = above[-1];
int i, j;
for (j = 0; j < n; j++)
{
for (i = 0; i < n; i++)
predict[i] = CLAMP_255(*left + above[i] - p);
predict += stride;
left += stride;
}
}
static void
predict_dc_nxn(unsigned char *predict,
int stride,
int n)
{
unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
int i, j, dc = 0;
for (i = 0; i < n; i++)
{
dc += *left + above[i];
left += stride;
}
switch (n)
{
case 16:
dc = (dc + 16) >> 5;
break;
case 8:
dc = (dc + 8) >> 4;
break;
case 4:
dc = (dc + 4) >> 3;
break;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
predict[i *stride + j] = dc;
}
static void
predict_ve_4x4(unsigned char *predict,
int stride)
{
unsigned char *above = predict - stride;
int i, j;
predict[0] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
predict[1] = (above[ 0] + 2 * above[1] + above[2] + 2) >> 2;
predict[2] = (above[ 1] + 2 * above[2] + above[3] + 2) >> 2;
predict[3] = (above[ 2] + 2 * above[3] + above[4] + 2) >> 2;
for (i = 1; i < 4; i++)
for (j = 0; j < 4; j++)
predict[i *stride + j] = predict[j];
}
static void
predict_he_4x4(unsigned char *predict,
int stride)
{
unsigned char *left = predict - 1;
predict[0] =
predict[1] =
predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2;
predict += stride;
left += stride;
predict[0] =
predict[1] =
predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2;
predict += stride;
left += stride;
predict[0] =
predict[1] =
predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2;
predict += stride;
left += stride;
predict[0] =
predict[1] =
predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[0] + 2) >> 2;
}
static void
predict_ld_4x4(unsigned char *predict,
int stride)
{
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
predict[0] = pred0 = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
predict[1] = pred1 = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
predict[2] = pred2 = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
predict[3] = pred3 = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
predict += stride;
predict[0] = pred1;
predict[1] = pred2;
predict[2] = pred3;
predict[3] = pred4 = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
predict += stride;
predict[0] = pred2;
predict[1] = pred3;
predict[2] = pred4;
predict[3] = pred5 = (above[5] + 2 * above[6] + above[7] + 2) >> 2;
predict += stride;
predict[0] = pred3;
predict[1] = pred4;
predict[2] = pred5;
predict[3] = pred6 = (above[6] + 2 * above[7] + above[7] + 2) >> 2;
}
static void
predict_rd_4x4(unsigned char *predict,
int stride)
{
unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
predict[0] = pred0 =
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2;
predict[1] = pred1 =
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2;
predict[2] = pred2 =
(above[ 0] + 2 * above[ 1] + above[2] + 2) >> 2;
predict[3] = pred3 =
(above[ 1] + 2 * above[ 2] + above[3] + 2) >> 2;
predict += stride;
predict[0] = pred4 =
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2;
predict[1] = pred0;
predict[2] = pred1;
predict[3] = pred2;
predict += stride;
predict[0] = pred5 =
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2;
predict[1] = pred4;
predict[2] = pred0;
predict[3] = pred1;
predict += stride;
predict[0] = pred6 =
(left[stride*3] + 2 * left[stride*2] + left[stride] + 2) >> 2;
predict[1] = pred5;
predict[2] = pred4;
predict[3] = pred0;
}
static void
predict_vr_4x4(unsigned char *predict,
int stride)
{
unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred0 = (above[-1] + above[0] + 1) >> 1;
predict[1] = pred1 = (above[ 0] + above[1] + 1) >> 1;
predict[2] = pred2 = (above[ 1] + above[2] + 1) >> 1;
predict[3] = pred3 = (above[ 2] + above[3] + 1) >> 1;
predict += stride;
predict[0] = pred4 =
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2;
predict[1] = pred5 =
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2;
predict[2] = pred6 =
(above[ 0] + 2 * above[ 1] + above[2] + 2) >> 2;
predict[3] = pred7 =
(above[ 1] + 2 * above[ 2] + above[3] + 2) >> 2;
predict += stride;
predict[0] = pred8 =
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2;
predict[1] = pred0;
predict[2] = pred1;
predict[3] = pred2;
predict += stride;
predict[0] = pred9 =
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2;
predict[1] = pred4;
predict[2] = pred5;
predict[3] = pred6;
}
static void
predict_vl_4x4(unsigned char *predict,
int stride)
{
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred0 = (above[0] + above[1] + 1) >> 1;
predict[1] = pred1 = (above[1] + above[2] + 1) >> 1;
predict[2] = pred2 = (above[2] + above[3] + 1) >> 1;
predict[3] = pred3 = (above[3] + above[4] + 1) >> 1;
predict += stride;
predict[0] = pred4 =
(above[0] + 2 * above[1] + above[2] + 2) >> 2;
predict[1] = pred5 =
(above[1] + 2 * above[2] + above[3] + 2) >> 2;
predict[2] = pred6 =
(above[2] + 2 * above[3] + above[4] + 2) >> 2;
predict[3] = pred7 =
(above[3] + 2 * above[4] + above[5] + 2) >> 2;
predict += stride;
predict[0] = pred1;
predict[1] = pred2;
predict[2] = pred3;
predict[3] = pred8 = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
predict += stride;
predict[0] = pred5;
predict[1] = pred6;
predict[2] = pred7;
predict[3] = pred9 = (above[5] + 2 * above[6] + above[7] + 2) >> 2;
}
static void
predict_hd_4x4(unsigned char *predict,
int stride)
{
unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred0 =
(left[ 0] + above[-1] + 1) >> 1;
predict[1] = pred1 =
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2;
predict[2] = pred2 =
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2;
predict[3] = pred3 =
(above[ 0] + 2 * above[ 1] + above[2] + 2) >> 2;
predict += stride;
predict[0] = pred4 =
(left[stride] + left[0] + 1) >> 1;
predict[1] = pred5 =
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2;
predict[2] = pred0;
predict[3] = pred1;
predict += stride;
predict[0] = pred6 =
(left[stride*2] + left[stride] + 1) >> 1;
predict[1] = pred7 =
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2;
predict[2] = pred4;
predict[3] = pred5;
predict += stride;
predict[0] = pred8 =
(left[stride*3] + left[stride*2] + 1) >> 1;
predict[1] = pred9 =
(left[stride*3] + 2 * left[stride*2] + left[stride] + 2) >> 2;
predict[2] = pred6;
predict[3] = pred7;
}
static void
predict_hu_4x4(unsigned char *predict,
int stride)
{
unsigned char *left = predict - 1;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
predict[0] = pred0 =
(left[stride*0] + left[stride*1] + 1) >> 1;
predict[1] = pred1 =
(left[stride*0] + 2 * left[stride*1] + left[stride*2] + 2) >> 2;
predict[2] = pred2 =
(left[stride*1] + left[stride*2] + 1) >> 1;
predict[3] = pred3 =
(left[stride*1] + 2 * left[stride*2] + left[stride*3] + 2) >> 2;
predict += stride;
predict[0] = pred2;
predict[1] = pred3;
predict[2] = pred4 =
(left[stride*2] + left[stride*3] + 1) >> 1;
predict[3] = pred5 =
(left[stride*2] + 2 * left[stride*3] + left[stride*3] + 2) >> 2;
predict += stride;
predict[0] = pred4;
predict[1] = pred5;
predict[2] = pred6 = left[stride*3];
predict[3] = pred6;
predict += stride;
predict[0] = pred6;
predict[1] = pred6;
predict[2] = pred6;
predict[3] = pred6;
}
static void
predict_h_16x16(unsigned char *predict, int stride)
{
predict_h_nxn(predict, stride, 16);
}
static void
predict_v_16x16(unsigned char *predict, int stride)
{
predict_v_nxn(predict, stride, 16);
}
static void
predict_tm_16x16(unsigned char *predict, int stride)
{
predict_tm_nxn(predict, stride, 16);
}
static void
predict_h_8x8(unsigned char *predict, int stride)
{
predict_h_nxn(predict, stride, 8);
}
static void
predict_v_8x8(unsigned char *predict, int stride)
{
predict_v_nxn(predict, stride, 8);
}
static void
predict_tm_8x8(unsigned char *predict, int stride)
{
predict_tm_nxn(predict, stride, 8);
}
static void
predict_tm_4x4(unsigned char *predict, int stride)
{
predict_tm_nxn(predict, stride, 4);
}
static void
copy_down(unsigned char *recon,
int stride)
{
/* Copy the four pixels above-right of subblock 3 to
* above-right of subblocks 7, 11, and 15
*/
uint32_t tmp, *copy = (void *)(recon + 16 - stride);
stride = stride / sizeof(unsigned int);
tmp = *copy;
copy += stride * 4;
*copy = tmp;
copy += stride * 4;
*copy = tmp;
copy += stride * 4;
*copy = tmp;
}
static void
b_pred(unsigned char *predict,
int stride,
struct mb_info *mbi,
short *coeffs)
{
int i;
copy_down(predict, stride);
for (i = 0; i < 16; i++)
{
unsigned char *b_predict = predict + (i & 3) * 4;
switch (mbi->split.modes[i])
{
case B_DC_PRED:
predict_dc_nxn(b_predict, stride, 4);
break;
case B_TM_PRED:
predict_tm_4x4(b_predict, stride);
break;
case B_VE_PRED:
predict_ve_4x4(b_predict, stride);
break;
case B_HE_PRED:
predict_he_4x4(b_predict, stride);
break;
case B_LD_PRED:
predict_ld_4x4(b_predict, stride);
break;
case B_RD_PRED:
predict_rd_4x4(b_predict, stride);
break;
case B_VR_PRED:
predict_vr_4x4(b_predict, stride);
break;
case B_VL_PRED:
predict_vl_4x4(b_predict, stride);
break;
case B_HD_PRED:
predict_hd_4x4(b_predict, stride);
break;
case B_HU_PRED:
predict_hu_4x4(b_predict, stride);
break;
default:
assert(0);
}
vp8_dixie_idct_add(b_predict, b_predict, stride, coeffs);
coeffs += 16;
if ((i & 3) == 3)
{
predict += stride * 4;
}
}
}
static void
fixup_dc_coeffs(struct mb_info *mbi,
short *coeffs)
{
short y2[16];
int i;
vp8_dixie_walsh(coeffs + 24 * 16, y2);
for (i = 0; i < 16; i++)
coeffs[i*16] = y2[i];
}
static void
predict_intra_luma(unsigned char *predict,
int stride,
struct mb_info *mbi,
short *coeffs)
{
if (mbi->base.y_mode == B_PRED)
b_pred(predict, stride, mbi, coeffs);
else
{
int i;
switch (mbi->base.y_mode)
{
case DC_PRED:
predict_dc_nxn(predict, stride, 16);
break;
case V_PRED:
predict_v_16x16(predict, stride);
break;
case H_PRED:
predict_h_16x16(predict, stride);
break;
case TM_PRED:
predict_tm_16x16(predict, stride);
break;
default:
assert(0);
}
fixup_dc_coeffs(mbi, coeffs);
for (i = 0; i < 16; i++)
{
vp8_dixie_idct_add(predict, predict, stride, coeffs);
coeffs += 16;
predict += 4;
if ((i & 3) == 3)
predict += stride * 4 - 16;
}
}
}
static void
predict_intra_chroma(unsigned char *predict_u,
unsigned char *predict_v,
int stride,
struct mb_info *mbi,
short *coeffs)
{
int i;
switch (mbi->base.uv_mode)
{
case DC_PRED:
predict_dc_nxn(predict_u, stride, 8);
predict_dc_nxn(predict_v, stride, 8);
break;
case V_PRED:
predict_v_8x8(predict_u, stride);
predict_v_8x8(predict_v, stride);
break;
case H_PRED:
predict_h_8x8(predict_u, stride);
predict_h_8x8(predict_v, stride);
break;
case TM_PRED:
predict_tm_8x8(predict_u, stride);
predict_tm_8x8(predict_v, stride);
break;
default:
assert(0);
}
coeffs += 16 * 16;
for (i = 16; i < 20; i++)
{
vp8_dixie_idct_add(predict_u, predict_u, stride, coeffs);
coeffs += 16;
predict_u += 4;
if (i & 1)
predict_u += stride * 4 - 8;
}
for (i = 20; i < 24; i++)
{
vp8_dixie_idct_add(predict_v, predict_v, stride, coeffs);
coeffs += 16;
predict_v += 4;
if (i & 1)
predict_v += stride * 4 - 8;
}
}
static void
sixtap_horiz(unsigned char *output,
int output_stride,
const unsigned char *reference,
int reference_stride,
int cols,
int rows,
const filter_t filter
)
{
int r, c, temp;
for (r = 0; r < rows; r++)
{
for (c = 0; c < cols; c++)
{
temp = (reference[-2] * filter[0]) +
(reference[-1] * filter[1]) +
(reference[ 0] * filter[2]) +
(reference[ 1] * filter[3]) +
(reference[ 2] * filter[4]) +
(reference[ 3] * filter[5]) +
64;
temp >>= 7;
output[c] = CLAMP_255(temp);
reference++;
}
reference += reference_stride - cols;
output += output_stride;
}
}
static void
sixtap_vert(unsigned char *output,
int output_stride,
const unsigned char *reference,
int reference_stride,
int cols,
int rows,
const filter_t filter
)
{
int r, c, temp;
for (r = 0; r < rows; r++)
{
for (c = 0; c < cols; c++)
{
temp = (reference[-2*reference_stride] * filter[0]) +
(reference[-1*reference_stride] * filter[1]) +
(reference[ 0*reference_stride] * filter[2]) +
(reference[ 1*reference_stride] * filter[3]) +
(reference[ 2*reference_stride] * filter[4]) +
(reference[ 3*reference_stride] * filter[5]) +
64;
temp >>= 7;
output[c] = CLAMP_255(temp);
reference++;
}
reference += reference_stride - cols;
output += output_stride;
}
}
static void
sixtap_2d(unsigned char *output,
int output_stride,
const unsigned char *reference,
int reference_stride,
int cols,
int rows,
int mx,
int my,
const filter_t filters[8]
)
{
DECLARE_ALIGNED(16, unsigned char, temp[16*(16+5)]);
sixtap_horiz(temp, 16,
reference - 2 * reference_stride, reference_stride,
cols, rows + 5, filters[mx]);
sixtap_vert(output, output_stride,
temp + 2 * 16, 16,
cols, rows, filters[my]);
}
struct img_index
{
unsigned char *y, *u, *v;
int stride, uv_stride;
};
static const unsigned char *
filter_block(unsigned char *output,
const unsigned char *reference,
int stride,
const union mv *mv,
const filter_t filters[8])
{
int mx, my;
/* Handle 0,0 as a special case. TODO: does this make it any
* faster?
*/
if (!mv->raw)
return reference;
mx = mv->d.x & 7;
my = mv->d.y & 7;
reference += ((mv->d.y >> 3) * stride) + (mv->d.x >> 3);
if (mx | my)
{
sixtap_2d(output, stride, reference, stride, 4, 4, mx, my,
filters);
reference = output;
}
return reference;
}
static void
recon_1_block(unsigned char *output,
const unsigned char *reference,
int stride,
const union mv *mv,
const filter_t filters[8],
short *coeffs,
struct mb_info *mbi,
int b
)
{
const unsigned char *predict;
predict = filter_block(output, reference, stride, mv, filters);
vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b);
}
static mv_t
calculate_chroma_splitmv(struct mb_info *mbi,
int b,
int full_pixel)
{
int temp;
union mv mv;
temp = mbi->split.mvs[b].d.x +
mbi->split.mvs[b+1].d.x +
mbi->split.mvs[b+4].d.x +
mbi->split.mvs[b+5].d.x;
if (temp < 0)
temp -= 4;
else
temp += 4;
mv.d.x = temp / 8;
temp = mbi->split.mvs[b].d.y +
mbi->split.mvs[b+1].d.y +
mbi->split.mvs[b+4].d.y +
mbi->split.mvs[b+5].d.y;
if (temp < 0)
temp -= 4;
else
temp += 4;
mv.d.y = temp / 8;
if (full_pixel)
{
mv.d.x &= ~7;
mv.d.y &= ~7;
}
return mv;
}
/* Note: We rely on the reconstructed border having the same stride as
* the reference buffer because the filter_block can't adjust the
* stride with its return value, only the reference pointer.
*/
static void
build_mc_border(unsigned char *dst,
const unsigned char *src,
int stride,
int x,
int y,
int b_w,
int b_h,
int w,
int h
)
{
const unsigned char *ref_row;
/* Get a pointer to the start of the real data for this row */
ref_row = src - x - y * stride;
if (y >= h)
ref_row += (h - 1) * stride;
else if (y > 0)
ref_row += y * stride;
do
{
int left, right = 0, copy;
left = x < 0 ? -x : 0;
if (left > b_w)
left = b_w;
if (x + b_w > w)
right = x + b_w - w;
if (right > b_w)
right = b_w;
copy = b_w - left - right;
if (left)
memset(dst, ref_row[0], left);
if (copy)
memcpy(dst + left, ref_row + x + left, copy);
if (right)
memset(dst + left + copy, ref_row[w-1], right);
dst += stride;
y++;
if (y < h && y > 0)
ref_row += stride;
}
while (--b_h);
}
static void
recon_1_edge_block(unsigned char *output,
unsigned char *emul_block,
const unsigned char *reference,
int stride,
const union mv *mv,
const filter_t filters[8],
short *coeffs,
struct mb_info *mbi,
int x,
int y,
int w,
int h,
int start_b
)
{
const unsigned char *predict;
int b = start_b;
const int b_w = 4;
const int b_h = 4;
x += mv->d.x >> 3;
y += mv->d.y >> 3;
/* Need two pixels left/above, 3 right/below for 6-tap */
if (x < 2 || x + b_w - 1 + 3 >= w || y < 2 || y + b_h - 1 + 3 >= h)
{
reference += (mv->d.x >> 3) + (mv->d.y >> 3) * stride;
build_mc_border(emul_block,
reference - 2 - 2 * stride, stride,
x - 2, y - 2, b_w + 5, b_h + 5, w, h);
reference = emul_block + 2 * stride + 2;
reference -= (mv->d.x >> 3) + (mv->d.y >> 3) * stride;
}
predict = filter_block(output, reference, stride, mv, filters);
vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b);
}
static void
predict_inter_emulated_edge(struct vp8_decoder_ctx *ctx,
struct img_index *img,
short *coeffs,
struct mb_info *mbi,
int mb_col,
int mb_row)
{
/* TODO: move this into its own buffer. This only works because we
* still have a border allocated.
*/
unsigned char *emul_block = ctx->frame_strg[0].img.img_data;
unsigned char *reference;
unsigned char *output;
ptrdiff_t reference_offset;
int w, h, x, y, b;
union mv chroma_mv[4];
unsigned char *u = img->u, *v = img->v;
int full_pixel = ctx->frame_hdr.version == 3;
x = mb_col * 16;
y = mb_row * 16;
w = ctx->mb_cols * 16;
h = ctx->mb_rows * 16;
output = img->y;
reference_offset = ctx->ref_frame_offsets[mbi->base.ref_frame];
reference = output + reference_offset;
if (mbi->base.y_mode != SPLITMV)
{
union mv uvmv;
uvmv = mbi->base.mv;
uvmv.d.x = (uvmv.d.x + 1 + (uvmv.d.x >> 31) * 2) / 2;
uvmv.d.y = (uvmv.d.y + 1 + (uvmv.d.y >> 31) * 2) / 2;
if (full_pixel)
{
uvmv.d.x &= ~7;
uvmv.d.y &= ~7;
}
chroma_mv[0] = uvmv;
chroma_mv[1] = uvmv;
chroma_mv[2] = uvmv;
chroma_mv[3] = uvmv;
}
else
{
chroma_mv[0] = calculate_chroma_splitmv(mbi, 0, full_pixel);
chroma_mv[1] = calculate_chroma_splitmv(mbi, 2, full_pixel);
chroma_mv[2] = calculate_chroma_splitmv(mbi, 8, full_pixel);
chroma_mv[3] = calculate_chroma_splitmv(mbi, 10, full_pixel);
}
/* Luma */
for (b = 0; b < 16; b++)
{
union mv *ymv;
if (mbi->base.y_mode != SPLITMV)
ymv = &mbi->base.mv;
else
ymv = mbi->split.mvs + b;
recon_1_edge_block(output, emul_block, reference, img->stride,
ymv, ctx->subpixel_filters,
coeffs, mbi, x, y, w, h, b);
x += 4;
output += 4;
reference += 4;
if ((b & 3) == 3)
{
x -= 16;
y += 4;
output += 4 * img->stride - 16;
reference += 4 * img->stride - 16;
}
}
x = mb_col * 16;
y = mb_row * 16;
/* Chroma */
x >>= 1;
y >>= 1;
w >>= 1;
h >>= 1;
for (b = 0; b < 4; b++)
{
recon_1_edge_block(u, emul_block, u + reference_offset,
img->uv_stride,
&chroma_mv[b], ctx->subpixel_filters,
coeffs, mbi, x, y, w, h, b + 16);
recon_1_edge_block(v, emul_block, v + reference_offset,
img->uv_stride,
&chroma_mv[b], ctx->subpixel_filters,
coeffs, mbi, x, y, w, h, b + 20);
u += 4;
v += 4;
x += 4;
if (b & 1)
{
x -= 8;
y += 4;
u += 4 * img->uv_stride - 8;
v += 4 * img->uv_stride - 8;
}
}
}
static void
predict_inter(struct vp8_decoder_ctx *ctx,
struct img_index *img,
short *coeffs,
struct mb_info *mbi)
{
unsigned char *y = img->y;
unsigned char *u = img->u;
unsigned char *v = img->v;
ptrdiff_t reference_offset;
union mv chroma_mv[4];
int full_pixel = ctx->frame_hdr.version == 3;
int b;
if (mbi->base.y_mode != SPLITMV)
{
union mv uvmv;
uvmv = mbi->base.mv;
uvmv.d.x = (uvmv.d.x + 1 + (uvmv.d.x >> 31) * 2) / 2;
uvmv.d.y = (uvmv.d.y + 1 + (uvmv.d.y >> 31) * 2) / 2;
if (full_pixel)
{
uvmv.d.x &= ~7;
uvmv.d.y &= ~7;
}
chroma_mv[0] =
chroma_mv[1] =
chroma_mv[2] =
chroma_mv[3] = uvmv;
}
else
{
chroma_mv[0] = calculate_chroma_splitmv(mbi, 0, full_pixel);
chroma_mv[1] = calculate_chroma_splitmv(mbi, 2, full_pixel);
chroma_mv[2] = calculate_chroma_splitmv(mbi, 8, full_pixel);
chroma_mv[3] = calculate_chroma_splitmv(mbi, 10, full_pixel);
}
reference_offset = ctx->ref_frame_offsets[mbi->base.ref_frame];
for (b = 0; b < 16; b++)
{
union mv *ymv;
if (mbi->base.y_mode != SPLITMV)
ymv = &mbi->base.mv;
else
ymv = mbi->split.mvs + b;
recon_1_block(y, y + reference_offset, img->stride,
ymv, ctx->subpixel_filters, coeffs, mbi, b);
y += 4;
if ((b & 3) == 3)
y += 4 * img->stride - 16;
}
for (b = 0; b < 4; b++)
{
recon_1_block(u, u + reference_offset,
img->uv_stride, &chroma_mv[b],
ctx->subpixel_filters, coeffs, mbi, b + 16);
recon_1_block(v, v + reference_offset,
img->uv_stride, &chroma_mv[b],
ctx->subpixel_filters, coeffs, mbi, b + 20);
u += 4;
v += 4;
if (b & 1)
{
u += 4 * img->uv_stride - 8;
v += 4 * img->uv_stride - 8;
}
}
}
void
vp8_dixie_release_ref_frame(struct ref_cnt_img *rcimg)
{
if (rcimg)
{
assert(rcimg->ref_cnt);
rcimg->ref_cnt--;
}
}
struct ref_cnt_img *
vp8_dixie_ref_frame(struct ref_cnt_img *rcimg)
{
rcimg->ref_cnt++;
return rcimg;
}
struct ref_cnt_img *
vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames)
{
int i;
for (i = 0; i < NUM_REF_FRAMES; i++)
if (frames[i].ref_cnt == 0)
{
frames[i].ref_cnt = 1;
return &frames[i];
}
assert(0);
return NULL;
}
static void
fixup_left(unsigned char *predict,
int width,
int stride,
unsigned int row,
enum prediction_mode mode)
{
/* The left column of out-of-frame pixels is taken to be 129,
* unless we're doing DC_PRED, in which case we duplicate the
* above row, unless this is also row 0, in which case we use
* 129.
*/
unsigned char *left = predict - 1;
int i;
if (mode == DC_PRED && row)
{
unsigned char *above = predict - stride;
for (i = 0; i < width; i++)
{
*left = above[i];
left += stride;
}
}
else
{
/* Need to re-set the above row, in case the above MB was
* DC_PRED.
*/
left -= stride;
for (i = -1; i < width; i++)
{
*left = 129;
left += stride;
}
}
}
static void
fixup_above(unsigned char *predict,
int width,
int stride,
unsigned int col,
enum prediction_mode mode)
{
/* The above row of out-of-frame pixels is taken to be 127,
* unless we're doing DC_PRED, in which case we duplicate the
* left col, unless this is also col 0, in which case we use
* 127.
*/
unsigned char *above = predict - stride;
int i;
if (mode == DC_PRED && col)
{
unsigned char *left = predict - 1;
for (i = 0; i < width; i++)
{
above[i] = *left;
left += stride;
}
}
else
/* Need to re-set the left col, in case the last MB was
* DC_PRED.
*/
memset(above - 1, 127, width + 1);
memset(above + width, 127, 4); // for above-right subblock modes
}
void
vp8_dixie_predict_init(struct vp8_decoder_ctx *ctx)
{
int i;
unsigned char *this_frame_base;
if (ctx->frame_hdr.frame_size_updated)
{
for (i = 0; i < NUM_REF_FRAMES; i++)
{
unsigned int w = ctx->mb_cols * 16 + BORDER_PIXELS * 2;
unsigned int h = ctx->mb_rows * 16 + BORDER_PIXELS * 2;
vpx_img_free(&ctx->frame_strg[i].img);
ctx->frame_strg[i].ref_cnt = 0;
ctx->ref_frames[i] = NULL;
if (!vpx_img_alloc(&ctx->frame_strg[i].img,
IMG_FMT_I420, w, h, 16))
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate %dx%d"
" framebuffer",
w, h);
vpx_img_set_rect(&ctx->frame_strg[i].img,
BORDER_PIXELS, BORDER_PIXELS,
ctx->frame_hdr.kf.w, ctx->frame_hdr.kf.h);
}
if (ctx->frame_hdr.version)
ctx->subpixel_filters = bilinear_filters;
else
ctx->subpixel_filters = sixtap_filters;
}
/* Find a free framebuffer to predict into */
if (ctx->ref_frames[CURRENT_FRAME])
vp8_dixie_release_ref_frame(ctx->ref_frames[CURRENT_FRAME]);
ctx->ref_frames[CURRENT_FRAME] =
vp8_dixie_find_free_ref_frame(ctx->frame_strg);
this_frame_base = ctx->ref_frames[CURRENT_FRAME]->img.img_data;
/* Calculate offsets to the other reference frames */
for (i = 0; i < NUM_REF_FRAMES; i++)
{
struct ref_cnt_img *ref = ctx->ref_frames[i];
ctx->ref_frame_offsets[i] =
ref ? ref->img.img_data - this_frame_base : 0;
}
/* TODO: No need to do this on every frame... */
}
void
vp8_dixie_predict_destroy(struct vp8_decoder_ctx *ctx)
{
int i;
for (i = 0; i < NUM_REF_FRAMES; i++)
{
vpx_img_free(&ctx->frame_strg[i].img);
ctx->frame_strg[i].ref_cnt = 0;
ctx->ref_frames[i] = NULL;
}
}
void
vp8_dixie_predict_process_row(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
struct img_index img;
struct mb_info *mbi;
unsigned int col;
short *coeffs;
/* Adjust pointers based on row, start_col */
img.stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
img.uv_stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U];
img.y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
img.u = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_U];
img.v = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_V];
img.y += (img.stride * row + start_col) * 16;
img.u += (img.uv_stride * row + start_col) * 8;
img.v += (img.uv_stride * row + start_col) * 8;
mbi = ctx->mb_info_rows[row] + start_col;
coeffs = ctx->tokens[row & (ctx->token_hdr.partitions - 1)].coeffs
+ 25 * 16 * start_col;
/* Fix up the out-of-frame pixels */
if (start_col == 0)
{
fixup_left(img.y, 16, img.stride, row, mbi->base.y_mode);
fixup_left(img.u, 8, img.uv_stride, row, mbi->base.uv_mode);
fixup_left(img.v, 8, img.uv_stride, row, mbi->base.uv_mode);
if (row == 0)
*(img.y - img.stride - 1) = 127;
}
for (col = start_col; col < start_col + num_cols; col++)
{
if (row == 0)
{
fixup_above(img.y, 16, img.stride, col, mbi->base.y_mode);
fixup_above(img.u, 8, img.uv_stride, col,
mbi->base.uv_mode);
fixup_above(img.v, 8, img.uv_stride, col,
mbi->base.uv_mode);
}
if (mbi->base.y_mode <= B_PRED)
{
predict_intra_luma(img.y, img.stride, mbi, coeffs);
predict_intra_chroma(img.u, img.v, img.uv_stride, mbi,
coeffs);
}
else
{
if (mbi->base.y_mode != SPLITMV) // && != BPRED
fixup_dc_coeffs(mbi, coeffs);
if (mbi->base.need_mc_border)
predict_inter_emulated_edge(ctx, &img, coeffs, mbi, col,
row);
else
predict_inter(ctx, &img, coeffs, mbi);
}
/* Advance to the next macroblock */
mbi++;
img.y += 16;
img.u += 8;
img.v += 8;
coeffs += 25 * 16;
}
if (col == ctx->mb_cols)
{
/* Extend the last row by four pixels for intra prediction.
* This will be propagated later by copy_down.
*/
uint32_t *extend = (uint32_t *)(img.y + 15 * img.stride);
uint32_t val = 0x01010101 * img.y[-1 + 15 * img.stride];
*extend = val;
}
}
---- End code block ----------------------------------------
21.15. predict.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef PREDICT_H
#define PREDICT_H
void
vp8_dixie_predict_init(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_predict_destroy(struct vp8_decoder_ctx *ctx);
void
vp8_dixie_predict_process_row(struct vp8_decoder_ctx *ctx,
unsigned int row,
unsigned int start_col,
unsigned int num_cols);
void
vp8_dixie_release_ref_frame(struct ref_cnt_img *rcimg);
struct ref_cnt_img *
vp8_dixie_ref_frame(struct ref_cnt_img *rcimg);
struct ref_cnt_img *
vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames);
#endif
---- End code block ----------------------------------------
21.16. tokens.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_codec_internal.h"
#include "dixie.h"
#include "tokens.h"
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
enum
{
EOB_CONTEXT_NODE,
ZERO_CONTEXT_NODE,
ONE_CONTEXT_NODE,
LOW_VAL_CONTEXT_NODE,
TWO_CONTEXT_NODE,
THREE_CONTEXT_NODE,
HIGH_LOW_CONTEXT_NODE,
CAT_ONE_CONTEXT_NODE,
CAT_THREEFOUR_CONTEXT_NODE,
CAT_THREE_CONTEXT_NODE,
CAT_FIVE_CONTEXT_NODE
};
enum
{
ZERO_TOKEN,
ONE_TOKEN,
TWO_TOKEN,
THREE_TOKEN,
FOUR_TOKEN,
DCT_VAL_CATEGORY1,
DCT_VAL_CATEGORY2,
DCT_VAL_CATEGORY3,
DCT_VAL_CATEGORY4,
DCT_VAL_CATEGORY5,
DCT_VAL_CATEGORY6,
DCT_EOB_TOKEN,
MAX_ENTROPY_TOKENS
};
struct extrabits
{
short min_val;
short length;
unsigned char probs[12];
};
static const unsigned int left_context_index[25] =
{
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8
};
static const unsigned int above_context_index[25] =
{
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
4, 5, 4, 5, 6, 7, 6, 7, 8
};
#define X(n) ((n) * PREV_COEF_CONTEXTS * ENTROPY_NODES)
static const unsigned int bands_x[16] =
{
X(0), X(1), X(2), X(3), X(6), X(4), X(5), X(6),
X(6), X(6), X(6), X(6), X(6), X(6), X(6), X(7)
};
#undef X
static const struct extrabits extrabits[MAX_ENTROPY_TOKENS] =
{
{ 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ZERO_TOKEN
{ 1, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ONE_TOKEN
{ 2, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //TWO_TOKEN
{ 3, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //THREE_TOKEN
{ 4, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //FOUR_TOKEN
{ 5, 0, { 159, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY1
{ 7, 1, { 145, 165, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY2
{ 11, 2, { 140, 148, 173, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY3
{ 19, 3, { 135, 140, 155, 176, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY4
{ 35, 4, { 130, 134, 141, 157, 180, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY5
{ 67, 10, { 129, 130, 133, 140, 153, 177,
196, 230, 243, 254, 254, 0 } }, //DCT_VAL_CATEGORY6
{ 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, // EOB TOKEN
};
static const unsigned int zigzag[16] =
{
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
#define DECODE_AND_APPLYSIGN(value_to_sign) \
v = (bool_get_bit(bool) ? -value_to_sign \
: value_to_sign) * dqf[!!c];
#define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) goto branch;
#define DECODE_AND_LOOP_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) \
{ \
prob = type_probs; \
if(c<15) {\
++c; \
prob += bands_x[c]; \
goto branch; \
}\
else \
goto BLOCK_FINISHED; /*for malformed input */\
}
#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
DECODE_AND_APPLYSIGN(val) \
prob = type_probs + (ENTROPY_NODES*2); \
if(c < 15){\
b_tokens[zigzag[c]] = v; \
++c; \
goto DO_WHILE; }\
b_tokens[zigzag[15]] = v; \
goto BLOCK_FINISHED;
#define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\
val += bool_get(bool, extrabits[t].probs[bits_count]) << bits_count;
static int
decode_mb_tokens(struct bool_decoder *bool,
token_entropy_ctx_t left,
token_entropy_ctx_t above,
short *tokens,
enum prediction_mode mode,
coeff_probs_table_t probs,
short factor[TOKEN_BLOCK_TYPES][2])
{
int i, stop, type;
int c, t, v;
int val, bits_count;
int eob_mask;
short *b_tokens; /* tokens for this block */
unsigned char *type_probs; /* probabilities for this block type */
unsigned char *prob;
short *dqf;
eob_mask = 0;
if (mode != B_PRED && mode != SPLITMV)
{
i = 24;
stop = 24;
type = 1;
b_tokens = tokens + 24 * 16;
dqf = factor[TOKEN_BLOCK_Y2];
}
else
{
i = 0;
stop = 16;
type = 3;
b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1];
}
/* Save a pointer to the coefficient probs for the current type.
* Need to repeat this whenever type changes.
*/
type_probs = probs[type][0][0];
BLOCK_LOOP:
t = left[left_context_index[i]] + above[above_context_index[i]];
c = !type; /* all blocks start at 0 except type 0, which starts
* at 1. */
prob = type_probs;
prob += t * ENTROPY_NODES;
DO_WHILE:
prob += bands_x[c];
DECODE_AND_BRANCH_IF_ZERO(prob[EOB_CONTEXT_NODE], BLOCK_FINISHED);
CHECK_0_:
DECODE_AND_LOOP_IF_ZERO(prob[ZERO_CONTEXT_NODE], CHECK_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[ONE_CONTEXT_NODE],
ONE_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[LOW_VAL_CONTEXT_NODE],
LOW_VAL_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[HIGH_LOW_CONTEXT_NODE],
HIGH_LOW_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREEFOUR_CONTEXT_NODE],
CAT_THREEFOUR_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_FIVE_CONTEXT_NODE],
CAT_FIVE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY6].min_val;
bits_count = extrabits[DCT_VAL_CATEGORY6].length;
do
{
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6, bits_count);
bits_count -- ;
}
while (bits_count >= 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_FIVE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY5].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_THREEFOUR_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREE_CONTEXT_NODE],
CAT_THREE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY4].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_THREE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY3].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
HIGH_LOW_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_ONE_CONTEXT_NODE],
CAT_ONE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY2].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_ONE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY1].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
LOW_VAL_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[TWO_CONTEXT_NODE],
TWO_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[THREE_CONTEXT_NODE],
THREE_CONTEXT_NODE_0_);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4);
THREE_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3);
TWO_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2);
ONE_CONTEXT_NODE_0_:
DECODE_AND_APPLYSIGN(1);
prob = type_probs + ENTROPY_NODES;
if (c < 15)
{
b_tokens[zigzag[c]] = v;
++c;
goto DO_WHILE;
}
b_tokens[zigzag[15]] = v;
BLOCK_FINISHED:
eob_mask |= (c > 1) << i;
t = (c != !type); // any nonzero data?
eob_mask |= t << 31;
left[left_context_index[i]] = above[above_context_index[i]] = t;
b_tokens += 16;
i++;
if (i < stop)
goto BLOCK_LOOP;
if (i == 25)
{
type = 0;
i = 0;
stop = 16;
type_probs = probs[type][0][0];
b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1];
goto BLOCK_LOOP;
}
if (i == 16)
{
type = 2;
type_probs = probs[type][0][0];
stop = 24;
dqf = factor[TOKEN_BLOCK_UV];
goto BLOCK_LOOP;
}
return eob_mask;
}
static void
reset_row_context(token_entropy_ctx_t *left)
{
memset(left, 0, sizeof(*left));
}
static void
reset_above_context(token_entropy_ctx_t *above, unsigned int cols)
{
memset(above, 0, cols * sizeof(*above));
}
static void
reset_mb_context(token_entropy_ctx_t *left,
token_entropy_ctx_t *above,
enum prediction_mode mode)
{
/* Reset the macroblock context on the left and right. We have to
* preserve the context of the second order block if this mode
* would not have updated it.
*/
memset(left, 0, sizeof((*left)[0]) * 8);
memset(above, 0, sizeof((*above)[0]) * 8);
if (mode != B_PRED && mode != SPLITMV)
{
(*left)[8] = 0;
(*above)[8] = 0;
}
}
void
vp8_dixie_tokens_process_row(struct vp8_decoder_ctx *ctx,
unsigned int partition,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
struct token_decoder *tokens = &ctx->tokens[partition];
short *coeffs = tokens->coeffs + 25 * 16 * start_col;
unsigned int col;
token_entropy_ctx_t *above = ctx->above_token_entropy_ctx
+ start_col;
token_entropy_ctx_t *left = &tokens->left_token_entropy_ctx;
struct mb_info *mbi = ctx->mb_info_rows[row] + start_col;
if (row == 0)
reset_above_context(above, num_cols);
if (start_col == 0)
reset_row_context(left);
for (col = start_col; col < start_col + num_cols; col++)
{
memset(coeffs, 0, 25 * 16 * sizeof(short));
if (mbi->base.skip_coeff)
{
reset_mb_context(left, above, mbi->base.y_mode);
mbi->base.eob_mask = 0;
}
else
{
struct dequant_factors *dqf;
dqf = ctx->dequant_factors + mbi->base.segment_id;
mbi->base.eob_mask =
decode_mb_tokens(&tokens->bool,
*left, *above,
coeffs,
mbi->base.y_mode,
ctx->entropy_hdr.coeff_probs,
dqf->factor);
}
above++;
mbi++;
coeffs += 25 * 16;
}
}
void
vp8_dixie_tokens_init(struct vp8_decoder_ctx *ctx)
{
unsigned int partitions = ctx->token_hdr.partitions;
if (ctx->frame_hdr.frame_size_updated)
{
unsigned int i;
unsigned int coeff_row_sz =
ctx->mb_cols * 25 * 16 * sizeof(short);
for (i = 0; i < partitions; i++)
{
free(ctx->tokens[i].coeffs);
ctx->tokens[i].coeffs = memalign(16, coeff_row_sz);
if (!ctx->tokens[i].coeffs)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR,
NULL);
}
free(ctx->above_token_entropy_ctx);
ctx->above_token_entropy_ctx =
calloc(ctx->mb_cols, sizeof(*ctx->above_token_entropy_ctx));
if (!ctx->above_token_entropy_ctx)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR, NULL);
}
}
void
vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx)
{
int i;
for (i = 0; i < MAX_PARTITIONS; i++)
free(ctx->tokens[i].coeffs);
free(ctx->above_token_entropy_ctx);
}
---- End code block ----------------------------------------
21.17. tokens.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_codec_internal.h"
#include "dixie.h"
#include "tokens.h"
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
enum
{
EOB_CONTEXT_NODE,
ZERO_CONTEXT_NODE,
ONE_CONTEXT_NODE,
LOW_VAL_CONTEXT_NODE,
TWO_CONTEXT_NODE,
THREE_CONTEXT_NODE,
HIGH_LOW_CONTEXT_NODE,
CAT_ONE_CONTEXT_NODE,
CAT_THREEFOUR_CONTEXT_NODE,
CAT_THREE_CONTEXT_NODE,
CAT_FIVE_CONTEXT_NODE
};
enum
{
ZERO_TOKEN,
ONE_TOKEN,
TWO_TOKEN,
THREE_TOKEN,
FOUR_TOKEN,
DCT_VAL_CATEGORY1,
DCT_VAL_CATEGORY2,
DCT_VAL_CATEGORY3,
DCT_VAL_CATEGORY4,
DCT_VAL_CATEGORY5,
DCT_VAL_CATEGORY6,
DCT_EOB_TOKEN,
MAX_ENTROPY_TOKENS
};
struct extrabits
{
short min_val;
short length;
unsigned char probs[12];
};
static const unsigned int left_context_index[25] =
{
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8
};
static const unsigned int above_context_index[25] =
{
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
4, 5, 4, 5, 6, 7, 6, 7, 8
};
#define X(n) ((n) * PREV_COEF_CONTEXTS * ENTROPY_NODES)
static const unsigned int bands_x[16] =
{
X(0), X(1), X(2), X(3), X(6), X(4), X(5), X(6),
X(6), X(6), X(6), X(6), X(6), X(6), X(6), X(7)
};
#undef X
static const struct extrabits extrabits[MAX_ENTROPY_TOKENS] =
{
{ 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ZERO_TOKEN
{ 1, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ONE_TOKEN
{ 2, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //TWO_TOKEN
{ 3, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //THREE_TOKEN
{ 4, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //FOUR_TOKEN
{ 5, 0, { 159, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY1
{ 7, 1, { 145, 165, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY2
{ 11, 2, { 140, 148, 173, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY3
{ 19, 3, { 135, 140, 155, 176, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY4
{ 35, 4, { 130, 134, 141, 157, 180, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY5
{ 67, 10, { 129, 130, 133, 140, 153, 177,
196, 230, 243, 254, 254, 0 } }, //DCT_VAL_CATEGORY6
{ 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, // EOB TOKEN
};
static const unsigned int zigzag[16] =
{
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
#define DECODE_AND_APPLYSIGN(value_to_sign) \
v = (bool_get_bit(bool) ? -value_to_sign \
: value_to_sign) * dqf[!!c];
#define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) goto branch;
#define DECODE_AND_LOOP_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) \
{ \
prob = type_probs; \
if(c<15) {\
++c; \
prob += bands_x[c]; \
goto branch; \
}\
else \
goto BLOCK_FINISHED; /*for malformed input */\
}
#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
DECODE_AND_APPLYSIGN(val) \
prob = type_probs + (ENTROPY_NODES*2); \
if(c < 15){\
b_tokens[zigzag[c]] = v; \
++c; \
goto DO_WHILE; }\
b_tokens[zigzag[15]] = v; \
goto BLOCK_FINISHED;
#define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\
val += bool_get(bool, extrabits[t].probs[bits_count]) << bits_count;
static int
decode_mb_tokens(struct bool_decoder *bool,
token_entropy_ctx_t left,
token_entropy_ctx_t above,
short *tokens,
enum prediction_mode mode,
coeff_probs_table_t probs,
short factor[TOKEN_BLOCK_TYPES][2])
{
int i, stop, type;
int c, t, v;
int val, bits_count;
int eob_mask;
short *b_tokens; /* tokens for this block */
unsigned char *type_probs; /* probabilities for this block type */
unsigned char *prob;
short *dqf;
eob_mask = 0;
if (mode != B_PRED && mode != SPLITMV)
{
i = 24;
stop = 24;
type = 1;
b_tokens = tokens + 24 * 16;
dqf = factor[TOKEN_BLOCK_Y2];
}
else
{
i = 0;
stop = 16;
type = 3;
b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1];
}
/* Save a pointer to the coefficient probs for the current type.
* Need to repeat this whenever type changes.
*/
type_probs = probs[type][0][0];
BLOCK_LOOP:
t = left[left_context_index[i]] + above[above_context_index[i]];
c = !type; /* all blocks start at 0 except type 0, which starts
* at 1. */
prob = type_probs;
prob += t * ENTROPY_NODES;
DO_WHILE:
prob += bands_x[c];
DECODE_AND_BRANCH_IF_ZERO(prob[EOB_CONTEXT_NODE], BLOCK_FINISHED);
CHECK_0_:
DECODE_AND_LOOP_IF_ZERO(prob[ZERO_CONTEXT_NODE], CHECK_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[ONE_CONTEXT_NODE],
ONE_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[LOW_VAL_CONTEXT_NODE],
LOW_VAL_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[HIGH_LOW_CONTEXT_NODE],
HIGH_LOW_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREEFOUR_CONTEXT_NODE],
CAT_THREEFOUR_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_FIVE_CONTEXT_NODE],
CAT_FIVE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY6].min_val;
bits_count = extrabits[DCT_VAL_CATEGORY6].length;
do
{
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6, bits_count);
bits_count -- ;
}
while (bits_count >= 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_FIVE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY5].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_THREEFOUR_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREE_CONTEXT_NODE],
CAT_THREE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY4].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_THREE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY3].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
HIGH_LOW_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_ONE_CONTEXT_NODE],
CAT_ONE_CONTEXT_NODE_0_);
val = extrabits[DCT_VAL_CATEGORY2].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_ONE_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY1].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
LOW_VAL_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[TWO_CONTEXT_NODE],
TWO_CONTEXT_NODE_0_);
DECODE_AND_BRANCH_IF_ZERO(prob[THREE_CONTEXT_NODE],
THREE_CONTEXT_NODE_0_);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4);
THREE_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3);
TWO_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2);
ONE_CONTEXT_NODE_0_:
DECODE_AND_APPLYSIGN(1);
prob = type_probs + ENTROPY_NODES;
if (c < 15)
{
b_tokens[zigzag[c]] = v;
++c;
goto DO_WHILE;
}
b_tokens[zigzag[15]] = v;
BLOCK_FINISHED:
eob_mask |= (c > 1) << i;
t = (c != !type); // any nonzero data?
eob_mask |= t << 31;
left[left_context_index[i]] = above[above_context_index[i]] = t;
b_tokens += 16;
i++;
if (i < stop)
goto BLOCK_LOOP;
if (i == 25)
{
type = 0;
i = 0;
stop = 16;
type_probs = probs[type][0][0];
b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1];
goto BLOCK_LOOP;
}
if (i == 16)
{
type = 2;
type_probs = probs[type][0][0];
stop = 24;
dqf = factor[TOKEN_BLOCK_UV];
goto BLOCK_LOOP;
}
return eob_mask;
}
static void
reset_row_context(token_entropy_ctx_t *left)
{
memset(left, 0, sizeof(*left));
}
static void
reset_above_context(token_entropy_ctx_t *above, unsigned int cols)
{
memset(above, 0, cols * sizeof(*above));
}
static void
reset_mb_context(token_entropy_ctx_t *left,
token_entropy_ctx_t *above,
enum prediction_mode mode)
{
/* Reset the macroblock context on the left and right. We have to
* preserve the context of the second order block if this mode
* would not have updated it.
*/
memset(left, 0, sizeof((*left)[0]) * 8);
memset(above, 0, sizeof((*above)[0]) * 8);
if (mode != B_PRED && mode != SPLITMV)
{
(*left)[8] = 0;
(*above)[8] = 0;
}
}
void
vp8_dixie_tokens_process_row(struct vp8_decoder_ctx *ctx,
unsigned int partition,
unsigned int row,
unsigned int start_col,
unsigned int num_cols)
{
struct token_decoder *tokens = &ctx->tokens[partition];
short *coeffs = tokens->coeffs + 25 * 16 * start_col;
unsigned int col;
token_entropy_ctx_t *above = ctx->above_token_entropy_ctx
+ start_col;
token_entropy_ctx_t *left = &tokens->left_token_entropy_ctx;
struct mb_info *mbi = ctx->mb_info_rows[row] + start_col;
if (row == 0)
reset_above_context(above, num_cols);
if (start_col == 0)
reset_row_context(left);
for (col = start_col; col < start_col + num_cols; col++)
{
memset(coeffs, 0, 25 * 16 * sizeof(short));
if (mbi->base.skip_coeff)
{
reset_mb_context(left, above, mbi->base.y_mode);
mbi->base.eob_mask = 0;
}
else
{
struct dequant_factors *dqf;
dqf = ctx->dequant_factors + mbi->base.segment_id;
mbi->base.eob_mask =
decode_mb_tokens(&tokens->bool,
*left, *above,
coeffs,
mbi->base.y_mode,
ctx->entropy_hdr.coeff_probs,
dqf->factor);
}
above++;
mbi++;
coeffs += 25 * 16;
}
}
void
vp8_dixie_tokens_init(struct vp8_decoder_ctx *ctx)
{
unsigned int partitions = ctx->token_hdr.partitions;
if (ctx->frame_hdr.frame_size_updated)
{
unsigned int i;
unsigned int coeff_row_sz =
ctx->mb_cols * 25 * 16 * sizeof(short);
for (i = 0; i < partitions; i++)
{
free(ctx->tokens[i].coeffs);
ctx->tokens[i].coeffs = memalign(16, coeff_row_sz);
if (!ctx->tokens[i].coeffs)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR,
NULL);
}
free(ctx->above_token_entropy_ctx);
ctx->above_token_entropy_ctx =
calloc(ctx->mb_cols, sizeof(*ctx->above_token_entropy_ctx));
if (!ctx->above_token_entropy_ctx)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR, NULL);
}
}
void
vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx)
{
int i;
for (i = 0; i < MAX_PARTITIONS; i++)
free(ctx->tokens[i].coeffs);
free(ctx->above_token_entropy_ctx);
}
---- End code block ----------------------------------------
21.18. vp8_prob_data.h
---- Begin code block --------------------------------------
static const
unsigned char k_coeff_entropy_update_probs[BLOCK_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS]
[ENTROPY_NODES] =
{
{
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
{249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
{234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, },
{250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, },
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
},
{
{
{217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, },
{234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, },
},
{
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
},
{
{
{186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255, },
{234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255, },
{251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255, },
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
},
{
{
{248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255, },
{248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255, },
},
{
{255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
{248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
},
},
};
static const
unsigned char k_default_y_mode_probs [] =
{ 112, 86, 140, 37};
static const
unsigned char k_default_uv_mode_probs [] =
{ 162, 101, 204};
static const
unsigned char k_default_coeff_probs [BLOCK_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS][ENTROPY_NODES] =
{
{ /* block type 0 */
{ /* coeff band 0 */
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}
},
{ /* coeff band 1 */
{ 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
{ 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
{ 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128}
},
{ /* coeff band 2 */
{ 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
{ 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
{ 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128}
},
{ /* coeff band 3 */
{ 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
{ 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
{ 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128}
},
{ /* coeff band 4 */
{ 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
{ 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
{ 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128}
},
{ /* coeff band 5 */
{ 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
{ 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
{ 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128}
},
{ /* coeff band 6 */
{ 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
{ 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
{ 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128}
},
{ /* coeff band 7 */
{ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}
}
},
{ /* block type 1 */
{ /* coeff band 0 */
{ 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
{ 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
{ 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128}
},
{ /* coeff band 1 */
{ 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
{ 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
{ 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128}
},
{ /* coeff band 2 */
{ 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
{ 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
{ 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128}
},
{ /* coeff band 3 */
{ 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
{ 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
{ 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128}
},
{ /* coeff band 4 */
{ 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
{ 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
{ 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128}
},
{ /* coeff band 5 */
{ 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
{ 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
{ 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128}
},
{ /* coeff band 6 */
{ 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
{ 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
{ 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128}
},
{ /* coeff band 7 */
{ 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
{ 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
{ 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128}
}
},
{ /* block type 2 */
{ /* coeff band 0 */
{ 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
{ 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
{ 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128}
},
{ /* coeff band 1 */
{ 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
{ 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
{ 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128}
},
{ /* coeff band 2 */
{ 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
{ 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
{ 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128}
},
{ /* coeff band 3 */
{ 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
{ 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
{ 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128}
},
{ /* coeff band 4 */
{ 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
{ 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
{ 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}
},
{ /* coeff band 5 */
{ 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128}
},
{ /* coeff band 6 */
{ 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
{ 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
{ 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128}
},
{ /* coeff band 7 */
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}
}
},
{ /* block type 3 */
{ /* coeff band 0 */
{ 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
{ 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
{ 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128}
},
{ /* coeff band 1 */
{ 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
{ 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
{ 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128}
},
{ /* coeff band 2 */
{ 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
{ 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
{ 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128}
},
{ /* coeff band 3 */
{ 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
{ 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
{ 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128}
},
{ /* coeff band 4 */
{ 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
{ 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
{ 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128}
},
{ /* coeff band 5 */
{ 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
{ 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
{ 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128}
},
{ /* coeff band 6 */
{ 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
{ 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
{ 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128}
},
{ /* coeff band 7 */
{ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}
}
}
};
static const
unsigned char k_mv_entropy_update_probs[2][MV_PROB_CNT] =
{
{
237,
246,
253, 253, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 250, 250, 252, 254, 254
},
{
231,
243,
245, 253, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 251, 251, 254, 254, 254
}
};
static const
unsigned char k_default_mv_probs[2][MV_PROB_CNT] =
{
{ /* row */
162, /* is short */
128, /* sign */
225, 146, 172, 147, 214, 39, 156, /* short tree */
128, 129, 132, 75, 145, 178, 206, 239, 254, 254 /* long bits */
},
{
164,
128,
204, 170, 119, 235, 140, 230, 228,
128, 130, 130, 74, 148, 180, 203, 236, 254, 254
}
};
---- End code block ----------------------------------------
21.19. vpx_codec_internal.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*!\file decoder_impl.h
* \brief Describes the decoder algorithm interface for algorithm
* implementations.
*
* This file defines the private structures and data types that are
* only relevant to implementing an algorithm, as opposed to using
* it.
*
* To create a decoder algorithm class, an interface structure is put
* into the global namespace:
* <pre>
* my_codec.c:
* vpx_codec_iface_t my_codec = {
* "My Codec v1.0",
* VPX_CODEC_ALG_ABI_VERSION,
* ...
* };
* </pre>
*
* An application instantiates a specific decoder instance by using
* vpx_codec_init() and a pointer to the algorithm's interface
* structure:
* <pre>
* my_app.c:
* extern vpx_codec_iface_t my_codec;
* {
* vpx_codec_ctx_t algo;
* res = vpx_codec_init(&algo, &my_codec);
* }
* </pre>
*
* Once initialized, the instance is manged using other functions
* from the vpx_codec_* family.
*/
#ifndef VPX_CODEC_INTERNAL_H
#define VPX_CODEC_INTERNAL_H
#include "vpx_decoder.h"
#include <stdarg.h>
/*!\brief Current ABI version number
*
* \internal
* If this file is altered in any way that changes the ABI, this
* value must be bumped. Examples include, but are not limited to,
* changing types, removing or reassigning enums,
* adding/removing/rearranging fields to structures
*/
#define VPX_CODEC_INTERNAL_ABI_VERSION (3)
typedef struct vpx_codec_alg_priv vpx_codec_alg_priv_t;
/*!\brief init function pointer prototype
*
* Performs algorithm-specific initialization of the decoder context.
* This function is called by the generic vpx_codec_init() wrapper
* function, so plugins implementing this interface may trust the
* input parameters to be properly initialized.
*
* \param[in] ctx Pointer to this instance's context
* \retval #VPX_CODEC_OK
* The input stream was recognized and decoder initialized.
* \retval #VPX_CODEC_MEM_ERROR
* Memory operation failed.
*/
typedef vpx_codec_err_t (*vpx_codec_init_fn_t)(vpx_codec_ctx_t *ctx);
/*!\brief destroy function pointer prototype
*
* Performs algorithm-specific destruction of the decoder context.
* This function is called by the generic vpx_codec_destroy() wrapper
* function, so plugins implementing this interface may trust the
* input parameters to be properly initialized.
*
* \param[in] ctx Pointer to this instance's context
* \retval #VPX_CODEC_OK
* The input stream was recognized and decoder initialized.
* \retval #VPX_CODEC_MEM_ERROR
* Memory operation failed.
*/
typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(
vpx_codec_alg_priv_t *ctx);
/*!\brief parse stream info function pointer prototype
*
* Performs high level parsing of the bitstream. This function is
* called by the generic vpx_codec_parse_stream() wrapper function,
* so plugins implementing this interface may trust the input
* parameters to be properly initialized.
*
* \param[in] data Pointer to a block of data to parse
* \param[in] data_sz Size of the data buffer
* \param[in,out] si Pointer to stream info to update. The size
* member \ref MUST be properly initialized,
* but \ref MAY be clobbered by the
* algorithm. This parameter \ref MAY be
* NULL.
*
* \retval #VPX_CODEC_OK
* Bitstream is parsable and stream information updated
*/
typedef vpx_codec_err_t (*vpx_codec_peek_si_fn_t)(
const uint8_t *data,
unsigned int data_sz,
vpx_codec_stream_info_t *si);
/*!\brief Return information about the current stream.
*
* Returns information about the stream that has been parsed during
* decoding.
*
* \param[in] ctx Pointer to this instance's context
* \param[in,out] si Pointer to stream info to update. The size
* member \ref MUST be properly initialized,
* but \ref MAY be clobbered by the
* algorithm. This parameter \ref MAY be
* NULL.
*
* \retval #VPX_CODEC_OK
* Bitstream is parsable and stream information updated
*/
typedef vpx_codec_err_t (*vpx_codec_get_si_fn_t)(
vpx_codec_alg_priv_t *ctx,
vpx_codec_stream_info_t *si);
/*!\brief control function pointer prototype
*
* This function is used to exchange algorithm specific data with the
* decoder instance. This can be used to implement features specific
* to a particular algorithm.
*
* This function is called by the generic vpx_codec_control() wrapper
* function, so plugins implementing this interface may trust the
* input parameters to be properly initialized. However, this
* interface does not provide type safety for the exchanged data or
* assign meanings to the control codes. Those details should be
* specified in the algorithm's header file. In particular, the
* ctrl_id parameter is guaranteed to exist in the algorithm's
* control mapping table, and the data paramter may be NULL.
*
*
* \param[in] ctx Pointer to this instance's context
* \param[in] ctrl_id Algorithm specific control identifier
* \param[in,out] data Data to exchange with algorithm instance.
*
* \retval #VPX_CODEC_OK
* The internal state data was deserialized.
*/
typedef vpx_codec_err_t (*vpx_codec_control_fn_t)(
vpx_codec_alg_priv_t *ctx,
int ctrl_id,
va_list ap);
/*!\brief control function pointer mapping
*
* This structure stores the mapping between control identifiers and
* implementing functions. Each algorithm provides a list of these
* mappings. This list is searched by the vpx_codec_control() wrapper
* function to determine which function to invoke. The special
* value {0, NULL} is used to indicate end-of-list, and must be
* present. The special value {0, <non-null>} can be used as a
* catch-all mapping. This implies that ctrl_id values chosen by the
* algorithm \ref MUST be non-zero.
*/
typedef const struct
{
int ctrl_id;
vpx_codec_control_fn_t fn;
} vpx_codec_ctrl_fn_map_t;
/*!\brief decode data function pointer prototype
*
* Processes a buffer of coded data. If the processing results in a
* new decoded frame becoming available, #VPX_CODEC_CB_PUT_SLICE and
* #VPX_CODEC_CB_PUT_FRAME events are generated as appropriate. This
* function is called by the generic vpx_codec_decode() wrapper
* function, so plugins implementing this interface may trust the
* input parameters to be properly initialized.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] data Pointer to this block of new coded data. If
* NULL, a #VPX_CODEC_CB_PUT_FRAME event is
* posted for the previously decoded frame.
* \param[in] data_sz Size of the coded data, in bytes.
*
* \return Returns #VPX_CODEC_OK if the coded data was processed
* completely and future pictures can be decoded without
* error. Otherwise, see the descriptions of the other error
* codes in ::vpx_codec_err_t for recoverability
* capabilities.
*/
typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(
vpx_codec_alg_priv_t *ctx,
const uint8_t *data,
unsigned int data_sz,
void *user_priv,
long deadline);
/*!\brief Decoded frames iterator
*
* Iterates over a list of the frames available for display. The
* iterator storage should be initialized to NULL to start the
* iteration. Iteration is complete when this function returns NULL.
*
* The list of available frames becomes valid upon completion of the
* vpx_codec_decode call, and remains valid until the next call to
* vpx_codec_decode.
*
* \param[in] ctx Pointer to this instance's context
* \param[in out] iter Iterator storage, initialized to NULL
*
* \return Returns a pointer to an image, if one is ready for
* display. Frames produced will always be in PTS
* (presentation time stamp) order.
*/
typedef vpx_image_t*(*vpx_codec_get_frame_fn_t)(
vpx_codec_alg_priv_t *ctx,
vpx_codec_iter_t *iter);
/*\brief e_xternal Memory Allocation memory map get iterator
*
* Iterates over a list of the memory maps requested by the decoder.
* The iterator storage should be initialized to NULL to start the
* iteration. Iteration is complete when this function returns NULL.
*
* \param[in out] iter Iterator storage, initialized to NULL
*
* \return Returns a pointer to an memory segment descriptor, or NULL
* to indicate end-of-list.
*/
typedef vpx_codec_err_t (*vpx_codec_get_mmap_fn_t)(
const vpx_codec_ctx_t *ctx,
vpx_codec_mmap_t *mmap,
vpx_codec_iter_t *iter);
/*\brief e_xternal Memory Allocation memory map set iterator
*
* Sets a memory descriptor inside the decoder instance.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] mmap Memory map to store.
*
* \retval #VPX_CODEC_OK
* The memory map was accepted and stored.
* \retval #VPX_CODEC_MEM_ERROR
* The memory map was rejected.
*/
typedef vpx_codec_err_t (*vpx_codec_set_mmap_fn_t)(
vpx_codec_ctx_t *ctx,
const vpx_codec_mmap_t *mmap);
typedef vpx_codec_err_t (*vpx_codec_encode_fn_t)(
vpx_codec_alg_priv_t *ctx,
const vpx_image_t *img,
vpx_codec_pts_t pts,
unsigned long duration,
vpx_enc_frame_flags_t flags,
unsigned long deadline);
typedef const vpx_codec_cx_pkt_t*(*vpx_codec_get_cx_data_fn_t)(
vpx_codec_alg_priv_t *ctx,
vpx_codec_iter_t *iter);
typedef vpx_codec_err_t
(*vpx_codec_enc_config_set_fn_t)(
vpx_codec_alg_priv_t *ctx,
const vpx_codec_enc_cfg_t *cfg);
typedef vpx_fixed_buf_t *
(*vpx_codec_get_global_headers_fn_t)(vpx_codec_alg_priv_t *ctx);
typedef vpx_image_t *
(*vpx_codec_get_preview_frame_fn_t)(vpx_codec_alg_priv_t *ctx);
/*!\brief usage configuration mapping
*
* This structure stores the mapping between usage identifiers and
* configuration structures. Each algorithm provides a list of these
* mappings. This list is searched by the
* vpx_codec_enc_config_default() wrapper function to determine which
* config to return. The special value {-1, {0}} is used to indicate
* end-of-list, and must be present. At least one mapping must be
* present, in addition to the end-of-list.
*
*/
typedef const struct
{
int usage;
vpx_codec_enc_cfg_t cfg;
} vpx_codec_enc_cfg_map_t;
#define NOT_IMPLEMENTED 0
/*!\brief Decoder algorithm interface interface
*
* All decoders \ref MUST expose a variable of this type.
*/
struct vpx_codec_iface
{
const char *name;
int abi_version;
vpx_codec_caps_t caps;
vpx_codec_init_fn_t init;
vpx_codec_destroy_fn_t destroy;
vpx_codec_ctrl_fn_map_t *ctrl_maps;
vpx_codec_get_mmap_fn_t get_mmap;
vpx_codec_set_mmap_fn_t set_mmap;
struct
{
vpx_codec_peek_si_fn_t peek_si;
vpx_codec_get_si_fn_t get_si;
vpx_codec_decode_fn_t decode;
vpx_codec_get_frame_fn_t get_frame;
} dec;
struct
{
vpx_codec_enc_cfg_map_t *cfg_maps;
vpx_codec_encode_fn_t encode;
vpx_codec_get_cx_data_fn_t get_cx_data;
vpx_codec_enc_config_set_fn_t cfg_set;
vpx_codec_get_global_headers_fn_t get_glob_hdrs;
vpx_codec_get_preview_frame_fn_t get_preview;
} enc;
};
/*!\brief Callback function pointer / user data pair storage */
typedef struct vpx_codec_priv_cb_pair
{
union
{
vpx_codec_put_frame_cb_fn_t put_frame;
vpx_codec_put_slice_cb_fn_t put_slice;
};
void *user_priv;
} vpx_codec_priv_cb_pair_t;
/*!\brief Instance private storage
*
* This structure is allocated by the algorithm's init function. It
* can be extended in one of two ways. First, a second, algorithm
* specific structure can be allocated and the priv member pointed to
* it. Alternatively, this structure can be made the first member of
* the algorithm specific structure, and the pointer casted to the
* proper type.
*/
struct vpx_codec_priv
{
unsigned int sz;
vpx_codec_iface_t *iface;
struct vpx_codec_alg_priv *alg_priv;
const char *err_detail;
vpx_codec_flags_t init_flags;
struct
{
vpx_codec_priv_cb_pair_t put_frame_cb;
vpx_codec_priv_cb_pair_t put_slice_cb;
} dec;
struct
{
int tbd;
struct vpx_fixed_buf cx_data_dst_buf;
unsigned int cx_data_pad_before;
unsigned int cx_data_pad_after;
vpx_codec_cx_pkt_t cx_data_pkt;
} enc;
};
#undef VPX_CTRL_USE_TYPE
#define VPX_CTRL_USE_TYPE(id, typ) \
static typ id##__value(va_list args) \
{return va_arg(args, typ);} \
static typ id##__convert(void *x)\
{\
union\
{\
void *x;\
typ d;\
} u;\
u.x = x;\
return u.d;\
}
#undef VPX_CTRL_USE_TYPE_DEPRECATED
#define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
static typ id##__value(va_list args) \
{return va_arg(args, typ);} \
static typ id##__convert(void *x)\
{\
union\
{\
void *x;\
typ d;\
} u;\
u.x = x;\
return u.d;\
}
#define CAST(id, arg) id##__value(arg)
#define RECAST(id, x) id##__convert(x)
/* Internal Utility Functions
*
* The following functions are indended to be used inside algorithms
* as utilities for manipulating vpx_codec_* data structures.
*/
struct vpx_codec_pkt_list
{
unsigned int cnt;
unsigned int max;
struct vpx_codec_cx_pkt pkts[1];
};
#define vpx_codec_pkt_list_decl(n)\
union {struct vpx_codec_pkt_list head;\
struct {struct vpx_codec_pkt_list head;\
struct vpx_codec_cx_pkt pkts[n];} alloc;}
#define vpx_codec_pkt_list_init(m)\
(m)->alloc.head.cnt = 0,\
(m)->alloc.head.max = \
sizeof((m)->alloc.pkts) / sizeof((m)->alloc.pkts[0])
int
vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *,
const struct vpx_codec_cx_pkt *);
const vpx_codec_cx_pkt_t*
vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
vpx_codec_iter_t *iter);
#include <stdio.h>
#include <setjmp.h>
struct vpx_internal_error_info
{
vpx_codec_err_t error_code;
int has_detail;
char detail[80];
int setjmp;
jmp_buf jmp;
};
static void vpx_internal_error(struct vpx_internal_error_info *info,
vpx_codec_err_t error,
const char *fmt,
...)
{
va_list ap;
info->error_code = error;
info->has_detail = 0;
if (fmt)
{
size_t sz = sizeof(info->detail);
info->has_detail = 1;
va_start(ap, fmt);
vsnprintf(info->detail, sz - 1, fmt, ap);
va_end(ap);
info->detail[sz-1] = '\0';
}
if (info->setjmp)
longjmp(info->jmp, info->error_code);
}
#endif
---- End code block ----------------------------------------
21.20. vpx_decoder.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*!\defgroup decoder Decoder Algorithm Interface
* \ingroup codec
* This abstraction allows applications using this decoder to easily
* support multiple video formats with minimal code duplication. This
* section describes the interface common to all decoders.
* @{
*/
/*!\file vpx_decoder.h
* \brief Describes the decoder algorithm interface to applications.
*
* This file describes the interface between an application and a
* video decoder algorithm.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VPX_DECODER_H
#define VPX_DECODER_H
#include "vpx_codec.h"
/*!\brief Current ABI version number
*
* \internal
* If this file is altered in any way that changes the ABI, this
* value must be bumped. Examples include, but are not limited
* to, changing types, removing or reassigning enums,
* adding/removing/rearranging fields to structures
*/
#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION)
/*! \brief Decoder capabilities bitfield
*
* Each decoder advertises the capabilities it supports as part
* of its ::vpx_codec_iface_t interface structure. Capabilities
* are extra interfaces or functionality, and are not required
* to be supported by a decoder.
*
* The available flags are specifiedby VPX_CODEC_CAP_* defines.
*/
#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice
callbacks */
#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame
callbacks */
#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded
frame */
/*! \brief Initialization-time Feature Enabling
*
* Certain codec features must be known at initialization time,
* to allow for proper memory allocation.
*
* The available flags are specified by VPX_CODEC_USE_* defines.
*/
#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded
frame */
/*!\brief Stream properties
*
* This structure is used to query or set properties of the
* decoded stream. Algorithms may extend this structure with data
* specific to their bitstream by setting the sz member
* appropriately.
*/
typedef struct vpx_codec_stream_info
{
unsigned int sz; /**< Size of this structure */
unsigned int w; /**< Width (or 0 for unknown/default) */
unsigned int h; /**< Height (or 0 for unknown/default) */
unsigned int is_kf; /**< Current frame is a keyframe */
} vpx_codec_stream_info_t;
/* REQUIRED FUNCTIONS
*
* The following functions are required to be implemented for all
* decoders. They represent the base case functionality expected
* of all decoders.
*/
/*!\brief Initialization Configurations
*
* This structure is used to pass init time configuration options
* to the decoder.
*/
typedef struct vpx_codec_dec_cfg
{
unsigned int threads; /**< Maximum number of threads to use,
default 1 */
unsigned int w; /**< Width */
unsigned int h; /**< Height */
} vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
/*!\brief Initialize a decoder instance
*
* Initializes a decoder context using the given interface.
* Applications should call the vpx_codec_dec_init convenience
* macro instead of this function directly, to ensure that the
* ABI version number parameter is properly initialized.
*
* In XMA mode (activated by setting VPX_CODEC_USE_XMA in the
* flags parameter), the storage pointed to by the cfg parameter
* must be kept readable and stable until all memory maps have
* been set.
*
* \param[in] ctx Pointer to this instance's context.
* \param[in] iface Pointer to the alogrithm interface to
* use.
* \param[in] cfg Configuration to use, if known. May be
* NULL.
* \param[in] flags Bitfield of VPX_CODEC_USE_* flags
* \param[in] ver ABI version number. Must be set to
* VPX_DECODER_ABI_VERSION
* \retval #VPX_CODEC_OK
* The decoder algorithm initialized.
* \retval #VPX_CODEC_MEM_ERROR
* Memory allocation failed.
*/
vpx_codec_err_t vpx_codec_dec_init_ver(
vpx_codec_ctx_t *ctx,
vpx_codec_iface_t *iface,
vpx_codec_dec_cfg_t *cfg,
vpx_codec_flags_t flags,
int ver);
/*!\brief Convenience macro for vpx_codec_dec_init_ver()
*
* Ensures the ABI version parameter is properly set.
*/
#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
vpx_codec_dec_init_ver(ctx, iface, cfg, flags, \
VPX_DECODER_ABI_VERSION)
/*!\brief Parse stream info from a buffer
*
* Performs high level parsing of the bitstream. Construction of
* a decoder context is not necessary. Can be used to determine
* if the bitstream is of the proper format, and to extract
* information from the stream.
*
* \param[in] iface Pointer to the alogrithm interface
* \param[in] data Pointer to a block of data to parse
* \param[in] data_sz Size of the data buffer
* \param[in,out] si Pointer to stream info to update. The
* size member
* \ref MUST be properly initialized, but
* \ref MAY be clobbered by the
* algorithm. This parameter \ref MAY be
* NULL.
*
* \retval #VPX_CODEC_OK
* Bitstream is parsable and stream information updated
*/
vpx_codec_err_t vpx_codec_peek_stream_info(
vpx_codec_iface_t *iface,
const uint8_t *data,
unsigned int data_sz,
vpx_codec_stream_info_t *si);
/*!\brief Return information about the current stream.
*
* Returns information about the stream that has been parsed
* during decoding.
*
* \param[in] ctx Pointer to this instance's context
* \param[in,out] si Pointer to stream info to update. The
* size member \ref MUST be properly
* initialized, but \ref MAY be clobbered
* by the algorithm. This parameter \ref
* MAY be NULL.
*
* \retval #VPX_CODEC_OK
* Bitstream is parsable and stream information updated
*/
vpx_codec_err_t vpx_codec_get_stream_info(
vpx_codec_ctx_t *ctx,
vpx_codec_stream_info_t *si);
/*!\brief Decode data
*
* Processes a buffer of coded data. If the processing results in
* a new decoded frame becoming available, PUT_SLICE and
* PUT_FRAME events may be generated, as appropriate. Encoded
* data \ref MUST be passed in DTS (decode time stamp) order.
* Frames produced will always be in PTS (presentation time
* stamp) order.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] data Pointer to this block of new coded
* data. If NULL, a
* VPX_CODEC_CB_PUT_FRAME event is posted
* for the previously decoded frame.
* \param[in] data_sz Size of the coded data, in bytes.
* \param[in] user_priv Application specific data to associate
* with this frame.
* \param[in] deadline Soft deadline the decoder should
* attempt to meet, in us. Set to zero
* for unlimited.
*
* \return Returns #VPX_CODEC_OK if the coded data was processed
* completely and future pictures can be decoded without
* error. Otherwise, see the descriptions of the other
* error codes in ::vpx_codec_err_t for recoverability
* capabilities.
*/
vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
const uint8_t *data,
unsigned int data_sz,
void *user_priv,
long deadline);
/*!\brief Decoded frames iterator
*
* Iterates over a list of the frames available for display. The
* iterator storage should be initialized to NULL to start the
* iteration. Iteration is complete when this function returns
* NULL.
*
* The list of available frames becomes valid upon completion of
* the vpx_codec_decode call, and remains valid until the next
* call to vpx_codec_decode.
*
* \param[in] ctx Pointer to this instance's context
* \param[in,out] iter Iterator storage, initialized to NULL
*
* \return Returns a pointer to an image, if one is ready for
* display. Frames produced will always be in PTS
* (presentation time stamp) order.
*/
vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
vpx_codec_iter_t *iter);
/*!\defgroup cap_put_frame Frame-Based Decoding Functions
*
* The following functions are required to be implemented for all
* decoders that advertise the VPX_CODEC_CAP_PUT_FRAME
* capability. Calling these functions for codecs that don't
* advertise this capability will result in an error code being
* returned, usually VPX_CODEC_ERROR
* @{
*/
/*!\brief put frame callback prototype
*
* This callback is invoked by the decoder to notify the
* application of the availability of decoded image data.
*/
typedef void (*vpx_codec_put_frame_cb_fn_t)(
void *user_priv,
const vpx_image_t *img);
/*!\brief Register for notification of frame completion.
*
* Registers a given function to be called when a decoded frame
* is available.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] cb Pointer to the callback function
* \param[in] user_priv User's private data
*
* \retval #VPX_CODEC_OK
* Callback successfully registered.
* \retval #VPX_CODEC_ERROR
* Decoder context not initialized, or algorithm not capable
* of posting slice completion.
*/
vpx_codec_err_t vpx_codec_register_put_frame_cb(
vpx_codec_ctx_t *ctx,
vpx_codec_put_frame_cb_fn_t cb,
void *user_priv);
/*!@} - end defgroup cap_put_frame */
/*!\defgroup cap_put_slice Slice-Based Decoding Functions
*
* The following functions are required to be implemented for all
* decoders that advertise the VPX_CODEC_CAP_PUT_SLICE
* capability. Calling these functions for codecs that don't
* advertise this capability will result in an error code being
* returned, usually VPX_CODEC_ERROR
* @{
*/
/*!\brief put slice callback prototype
*
* This callback is invoked by the decoder to notify the
* application of the availability of partially decoded image
* data.
*/
typedef void (*vpx_codec_put_slice_cb_fn_t)(
void *user_priv,
const vpx_image_t *img,
const vpx_image_rect_t *valid,
const vpx_image_rect_t *update);
/*!\brief Register for notification of slice completion.
*
* Registers a given function to be called when a decoded slice
* is available.
*
* \param[in] ctx Pointer to this instance's context
* \param[in] cb Pointer to the callback function
* \param[in] user_priv User's private data
*
* \retval #VPX_CODEC_OK
* Callback successfully registered.
* \retval #VPX_CODEC_ERROR
* Decoder context not initialized, or algorithm not capable
* of posting slice completion.
*/
vpx_codec_err_t vpx_codec_register_put_slice_cb(
vpx_codec_ctx_t *ctx,
vpx_codec_put_slice_cb_fn_t cb,
void *user_priv);
/*!@} - end defgroup cap_put_slice*/
/*!@} - end defgroup decoder*/
#endif
#ifdef __cplusplus
}
#endif
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
#include "vpx_decoder_compat.h"
#endif
---- End code block ----------------------------------------
21.21. vpx_integer.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VPX_INTEGER_H
#define VPX_INTEGER_H
/* get ptrdiff_t, size_t, wchar_t, NULL */
#include <stddef.h>
#if defined(_MSC_VER) || defined(VPX_EMULATE_INTTYPES)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#if defined(_MSC_VER)
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define PRId64 "I64d"
#endif
#ifdef HAVE_ARMV6
typedef unsigned int int_fast16_t;
#else
typedef signed short int_fast16_t;
#endif
typedef signed char int_fast8_t;
typedef unsigned char uint_fast8_t;
#ifndef _UINTPTR_T_DEFINED
typedef unsigned int uintptr_t;
#endif
#else
/* Most platforms have the C99 standard integer types. */
#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS
#endif
#include <stdint.h>
#include <inttypes.h>
#endif
#endif
---- End code block ----------------------------------------
22. References 22. References
[1] International Telecommunication Union, "ITU BT.601: Studio [ITU-R_BT.601]
encoding parameters of digital television for standard 4:3 and International Telecommunication Union, "ITU BT.601: Studio
wide screen 16:9 aspect ratios", January 2007. encoding parameters of digital television for standard 4:3
and wide screen 16:9 aspect ratios", January 2007.
[2] Kernighan, B. and D. Ritchie, "The C Programming Language (2nd [Bell] Bell, T., Cleary, J., and I. Witten, "Text Compression",
edition)", April 1988. 1990.
[3] Shannon, C., "A Mathematical Theory of Communication", Bell [Kernighan]
System Technical Journal Vol. 27, pp. 379-423, 623-656, July, Kernighan, B. and D. Ritchie, "The C Programming Language
October 1948. (2nd edition)", April 1988.
[4] <http://creativecommons.org/licenses/by/3.0/> [Loeffler]
Loeffler, C., Ligtenberg , A., and G. Moschytz, "Practical
Fast 1-D DCT Algorithms with 11 Multiplications",
May 1989.
[Shannon] Shannon, C., "A Mathematical Theory of Communication",
Bell System Technical Journal Vol. 27, pp. 379-423, 623-
656, July, October 1948.
Authors' Addresses Authors' Addresses
James Bankoski James Bankoski
Google, Inc. Google, Inc.
Email: jimbankoski@google.com Email: jimbankoski@google.com
Paul Wilkins Paul Wilkins
Google, Inc. Google, Inc.
 End of changes. 143 change blocks. 
363 lines changed or deleted 6744 lines changed or added

This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/