| < 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/ | ||||