< draft-bankoski-vp8-bitstream-04.txt   draft-bankoski-vp8-bitstream-05.txt >
Network Working Group J. Bankoski Network Working Group J. Bankoski
Internet-Draft J. Koleszar Internet-Draft J. Koleszar
Intended status: Informational L. Quillio Intended status: Informational L. Quillio
Expires: December 18, 2011 J. Salonen Expires: February 3, 2012 J. Salonen
P. Wilkins P. Wilkins
Y. Xu Y. Xu
Google Inc. Google Inc.
June 16, 2011 August 2, 2011
VP8 Data Format and Decoding Guide VP8 Data Format and Decoding Guide
draft-bankoski-vp8-bitstream-04 draft-bankoski-vp8-bitstream-05
Abstract Abstract
This document describes the VP8 compressed video data format, This document describes the VP8 compressed video data format,
together with a discussion of the decoding procedure for the format. together with a discussion of the decoding procedure for the 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.
skipping to change at page 1, line 35 skipping to change at page 1, line 35
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 December 18, 2011. This Internet-Draft will expire on February 3, 2012.
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
skipping to change at page 3, line 43 skipping to change at page 3, line 43
20.5. dixie.h . . . . . . . . . . . . . . . . . . . . . . . . 163 20.5. dixie.h . . . . . . . . . . . . . . . . . . . . . . . . 163
20.6. dixie_loopfilter.c . . . . . . . . . . . . . . . . . . . 170 20.6. dixie_loopfilter.c . . . . . . . . . . . . . . . . . . . 170
20.7. dixie_loopfilter.h . . . . . . . . . . . . . . . . . . . 182 20.7. dixie_loopfilter.h . . . . . . . . . . . . . . . . . . . 182
20.8. idct_add.c . . . . . . . . . . . . . . . . . . . . . . . 182 20.8. idct_add.c . . . . . . . . . . . . . . . . . . . . . . . 182
20.9. idct_add.h . . . . . . . . . . . . . . . . . . . . . . . 186 20.9. idct_add.h . . . . . . . . . . . . . . . . . . . . . . . 186
20.10. mem.h . . . . . . . . . . . . . . . . . . . . . . . . . 186 20.10. mem.h . . . . . . . . . . . . . . . . . . . . . . . . . 186
20.11. modemv.c . . . . . . . . . . . . . . . . . . . . . . . . 188 20.11. modemv.c . . . . . . . . . . . . . . . . . . . . . . . . 188
20.12. modemv.h . . . . . . . . . . . . . . . . . . . . . . . . 203 20.12. modemv.h . . . . . . . . . . . . . . . . . . . . . . . . 203
20.13. modemv_data.h . . . . . . . . . . . . . . . . . . . . . 203 20.13. modemv_data.h . . . . . . . . . . . . . . . . . . . . . 203
20.14. predict.c . . . . . . . . . . . . . . . . . . . . . . . 208 20.14. predict.c . . . . . . . . . . . . . . . . . . . . . . . 208
20.15. predict.h . . . . . . . . . . . . . . . . . . . . . . . 238 20.15. predict.h . . . . . . . . . . . . . . . . . . . . . . . 239
20.16. tokens.c . . . . . . . . . . . . . . . . . . . . . . . . 238 20.16. tokens.c . . . . . . . . . . . . . . . . . . . . . . . . 239
20.17. tokens.h . . . . . . . . . . . . . . . . . . . . . . . . 248 20.17. tokens.h . . . . . . . . . . . . . . . . . . . . . . . . 250
20.18. vp8_prob_data.h . . . . . . . . . . . . . . . . . . . . 257 20.18. vp8_prob_data.h . . . . . . . . . . . . . . . . . . . . 250
20.19. vpx_codec_internal.h . . . . . . . . . . . . . . . . . . 266 20.19. vpx_codec_internal.h . . . . . . . . . . . . . . . . . . 259
20.20. vpx_decoder.h . . . . . . . . . . . . . . . . . . . . . 276 20.20. vpx_decoder.h . . . . . . . . . . . . . . . . . . . . . 269
20.21. vpx_integer.h . . . . . . . . . . . . . . . . . . . . . 283 20.21. vpx_decoder_compat.h . . . . . . . . . . . . . . . . . . 276
20.22. AUTHORS . . . . . . . . . . . . . . . . . . . . . . . . 285 20.22. vpx_image.c . . . . . . . . . . . . . . . . . . . . . . 290
20.23. LICENSE . . . . . . . . . . . . . . . . . . . . . . . . 286 20.23. vpx_image.h . . . . . . . . . . . . . . . . . . . . . . 296
20.24. PATENTS . . . . . . . . . . . . . . . . . . . . . . . . 287 20.24. vpx_integer.h . . . . . . . . . . . . . . . . . . . . . 302
21. References . . . . . . . . . . . . . . . . . . . . . . . . . 289 20.25. AUTHORS . . . . . . . . . . . . . . . . . . . . . . . . 303
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 290 20.26. LICENSE . . . . . . . . . . . . . . . . . . . . . . . . 305
20.27. PATENTS . . . . . . . . . . . . . . . . . . . . . . . . 306
21. Security Considerations . . . . . . . . . . . . . . . . . . . 307
22. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 308
23. Informative References . . . . . . . . . . . . . . . . . . . 309
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 310
1. Introduction 1. Introduction
This document describes the VP8 compressed video data format, This document describes the VP8 compressed video data format,
together with a discussion of the decoding procedure for the format. together with a discussion of the decoding procedure for the format.
It is intended to be used in conjunction with and as a guide to the It is intended to be used in conjunction with and as a guide to the
reference decoder source code provided in Attachment One. If there reference decoder source code provided in Attachment One. If there
are any conflicts between this narrative and the reference source are any conflicts between this narrative 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
skipping to change at page 8, line 26 skipping to change at page 8, line 26
that the zeroth DCT coefficients of the Y subblocks. This "higher- that the zeroth DCT coefficients of the Y subblocks. This "higher-
level" WHT is a substitute for the explicit specification of those level" WHT is a substitute for the explicit specification of those
coefficients, in exactly the same way as the DCT of a subblock coefficients, in exactly the same way as the DCT of a subblock
substitutes for the specification of the pixel values comprising the substitutes for the specification of the pixel values comprising the
subblock. We consider this 4x4 array as a second-order subblock subblock. We consider this 4x4 array as a second-order subblock
called Y2, and think of a macroblock as containing 24 "real" called Y2, and think of a macroblock as containing 24 "real"
subblocks and, sometimes, a 25th "virtual" subblock. This is dealt subblocks and, sometimes, a 25th "virtual" subblock. This is dealt
with further in Chapter 13. with further in Chapter 13.
The frame layout used by the reference decoder may be found in the The frame layout used by the reference decoder may be found in the
file yv12config.h. file vpx_image.h.
3. Compressed Frame Types 3. Compressed Frame Types
There are only two types of frames in VP8. There are only two types of frames in VP8.
Intraframes (also called key frames and, in MPEG terminology, Intraframes (also called key frames and, in MPEG terminology,
I-frames) are decoded without reference to any other frame in a I-frames) are decoded without reference to any other frame in a
sequence, that is, the decompressor reconstructs such frames sequence, that is, the decompressor reconstructs such frames
beginning from its "default" state. Key frames provide random access beginning from its "default" state. Key frames provide random access
(or seeking) points in a video stream. (or seeking) points in a video stream.
skipping to change at page 15, line 40 skipping to change at page 15, line 40
straightforward, many of the details are quite complex. The straightforward, many of the details are quite complex. The
management of probabilities is particularly elaborate. Not only do management of probabilities is particularly elaborate. Not only do
the various modes of intra-prediction and motion vector specification the various modes of intra-prediction and motion vector specification
have associated probabilities but they, together with the coding of have associated probabilities but they, together with the coding of
DCT coefficients and motion vectors, often base these probabilities DCT coefficients and motion vectors, often base these probabilities
on a variety of contextual information (calculated from what has been on a variety of contextual information (calculated from what has been
decoded so far), as well as on explicit modification via the frame decoded so far), as well as on explicit modification via the frame
header. header.
The "top-level" of decoding and frame reconstruction is implemented The "top-level" of decoding and frame reconstruction is implemented
in the reference decoder files onyxd_if.c and decodframe.c. in the reference decoder files dixie.c.
This concludes our summary of decoding and reconstruction; we This concludes our summary of decoding and reconstruction; we
continue by discussing the individual aspects in more depth. continue by discussing the individual aspects in more depth.
A reasonable "divide and conquer" approach to implementation of a A reasonable "divide and conquer" approach to implementation of a
decoder is to begin by decoding streams composed exclusively of key decoder is to begin by decoding streams composed exclusively of key
frames. After that works reliably, interframe handling can be added frames. After that works reliably, interframe handling can be added
more easily than if complete functionality were attempted more easily than if complete functionality were attempted
immediately. In accordance with this, we first discuss components immediately. In accordance with this, we first discuss components
needed to decode key frames (most of which are also used in the needed to decode key frames (most of which are also used in the
skipping to change at page 24, line 31 skipping to change at page 24, line 31
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.
Another (logically equivalent) implementation may be found in the Another (logically equivalent) implementation may be found in the
reference decoder files dboolhuff.h and dboolhuff.c. reference decoder files bool_decoder.h.
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* Encoder first */ /* Encoder first */
typedef struct { typedef struct {
uint8 *output; /* ptr to next byte to be written */ uint8 *output; /* ptr to next byte to be written */
uint32 range; /* 128 <= range <= 255 */ uint32 range; /* 128 <= range <= 255 */
uint32 bottom; /* minimum value of remaining output */ uint32 bottom; /* minimum value of remaining output */
int bit_count; /* # of shifts before an output byte int bit_count; /* # of shifts before an output byte
skipping to change at page 32, line 32 skipping to change at page 32, line 32
/* Descend tree until leaf is reached */ /* Descend tree until leaf is reached */
while( ( i = t[ i + read_bool( d, p[i>>1]) ] ) > 0) {} while( ( i = t[ i + read_bool( d, p[i>>1]) ] ) > 0) {}
return -i; /* return value is negation of nonpositive index */ return -i; /* return value is negation of nonpositive index */
} }
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
Tree-based decoding is implemented in the reference decoder file Tree-based decoding is implemented in the reference decoder file
tree_reader.h. bool_decoder.h.
8.2. Tree Coding Example 8.2. Tree Coding Example
As a multi-part example, without getting too far into the semantics As a multi-part example, without getting too far into the semantics
of macroblock decoding (which is of course taken up below), we look of macroblock decoding (which is of course taken up below), we look
at the "mode" coding for intra-predicted macroblocks. at the "mode" coding for intra-predicted macroblocks.
It so happens that, because of a difference in statistics, the Y (or It so happens that, because of a difference in statistics, the Y (or
luma) mode encoding uses two different trees: one for key frames and luma) mode encoding uses two different trees: one for key frames and
another for interframes. This is the only instance in VP8 of the another for interframes. This is the only instance in VP8 of the
skipping to change at page 35, line 12 skipping to change at page 35, line 12
probability table layouts as described in this document (and in the probability table layouts as described in this document (and in the
reference code) for all tree-coded data in VP8. reference code) for all tree-coded data in VP8.
9. Frame Header 9. Frame Header
The uncompressed data chunk at the start of each frame and the first The uncompressed data chunk at the start of each frame and the first
part of the first data partition contains information pertaining to part of the first data partition contains information pertaining to
the frame as a whole. We list the fields in the order of occurrence, the frame as a whole. We list the fields in the order of occurrence,
giving details for some of the fields. Other details are postponed giving details for some of the fields. Other details are postponed
until a more logical point in our overall description. Most of the until a more logical point in our overall description. Most of the
header decoding occurs in the reference decoder file decodeframe.c. header decoding occurs in the reference decoder file dixie.c.
9.1. Uncompressed Data Chunk 9.1. Uncompressed Data Chunk
The uncompressed data chunk comprises a common (for key frames and The uncompressed data chunk comprises a common (for key frames and
interframes) 3-byte frame tag that contains four fields, as follows: interframes) 3-byte frame tag that contains four fields, as follows:
1. A 1-bit frame type (0 for key frames, 1 for interframes). 1. A 1-bit frame type (0 for key frames, 1 for interframes).
2. A 3-bit version number (0 - 3 are defined as four different 2. A 3-bit version number (0 - 3 are defined as four different
profiles with different decoding complexity; other values may be profiles with different decoding complexity; other values may be
skipping to change at page 44, line 52 skipping to change at page 44, line 52
| | | | | |
| F | If true, followed by three L(8)s updating the | | F | If true, followed by three L(8)s updating the |
| | probabilities for the different types of intra-prediction | | | probabilities for the different types of intra-prediction |
| | for the chroma planes. These probabilities correspond to | | | for the chroma planes. These probabilities correspond to |
| | the even positions in the uv_mode_tree array given above. | | | the even positions in the uv_mode_tree array given above. |
| | | | | |
| X | Motion vector probability update. The details will be | | X | Motion vector probability update. The details will be |
| | given after the discussion of motion vector decoding. | | | given after the discussion of motion vector decoding. |
+-------+-----------------------------------------------------------+ +-------+-----------------------------------------------------------+
Decoding of this portion (only) of the frame header is handled in the Decoding of this portion of the frame header is handled in the
reference decoder file decodemv.c. reference decoder file dixie.c.
9.11. Remaining Frame Header Data (Key Frame) 9.11. Remaining Frame Header Data (Key Frame)
+-------+-----------------------------------------------------------+ +-------+-----------------------------------------------------------+
| Index | Description | | Index | Description |
+-------+-----------------------------------------------------------+ +-------+-----------------------------------------------------------+
| L(1) | mb_no_coeff_skip. This flag indicates at the frame level | | L(1) | mb_no_coeff_skip. This flag indicates at the frame level |
| | if skipping of macroblocks with no non-zero coefficients | | | if skipping of macroblocks with no non-zero coefficients |
| | is enabled. If it is set to 0 then prob_skip_false is | | | is enabled. If it is set to 0 then prob_skip_false is |
| | not read and mb_skip_coeff is forced to 0 for all | | | not read and mb_skip_coeff is forced to 0 for all |
| | macroblocks (see Sections 11.1 and 12.1). | | | macroblocks (see Sections 11.1 and 12.1). |
| | | | | |
| L(8) | prob_skip_false = Probability used for decoding a | | L(8) | prob_skip_false = Probability used for decoding a |
| | macroblock level flag, which indicates if a macroblock | | | macroblock level flag, which indicates if a macroblock |
| | has any non-zero coefficients. Only read if | | | has any non-zero coefficients. Only read if |
| | mb_no_coeff_skip is 1. | | | mb_no_coeff_skip is 1. |
+-------+-----------------------------------------------------------+ +-------+-----------------------------------------------------------+
Decoding of this portion of the frame header is handled in the Decoding of this portion of the frame header is handled in the
reference decoder file demode.c. reference decoder file modemv.c.
This completes the layout of the frame header. The remainder of the This completes the layout of the frame header. The remainder of the
first data partition consists of macroblock-level prediction data. first data partition consists of macroblock-level prediction data.
After the frame header is processed, all probabilities needed to After the frame header is processed, all probabilities needed to
decode the prediction and residue data are known and will not change decode the prediction and residue data are known and will not change
until the next frame. until the next frame.
10. Segment-based Feature Adjustments 10. Segment-based Feature Adjustments
skipping to change at page 46, line 41 skipping to change at page 46, line 41
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
... combined with a 3-entry probability table ... combined with a 3-entry probability table
mb_segment_tree_probs[3]. The macroblock's segment_id is used later mb_segment_tree_probs[3]. The macroblock's segment_id is used later
in the decoding process to look into the segment_feature_data table in the decoding process to look into the segment_feature_data table
and determine how the quantizer and loop filter levels are adjusted. and determine how the quantizer and loop filter levels are adjusted.
The decoding of segment_id, together with the parsing of intra- The decoding of segment_id, together with the parsing of intra-
prediction modes (which is taken up next), is implemented in the prediction modes (which is taken up next), is implemented in the
reference decoder file demode.c. reference decoder file modemv.c.
11. Key Frame Macroblock Prediction Records 11. Key Frame Macroblock Prediction Records
After the features described above, the macroblock prediction record After the features described above, the macroblock prediction record
next specifies the prediction mode used for the macroblock. next specifies the prediction mode used for the macroblock.
11.1. mb_skip_coeff 11.1. mb_skip_coeff
The single bool flag is decoded using prob_skip_false if and only if The single bool flag is decoded using prob_skip_false if and only if
mb_no_coeff_skip is set to 1 (see sections 9.10 and 9.11). If mb_no_coeff_skip is set to 1 (see sections 9.10 and 9.11). If
skipping to change at page 59, line 36 skipping to change at page 59, line 36
} while( ++r < 8); } while( ++r < 8);
} }
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
Note that the process could equivalently be described as propagating Note that the process could equivalently be described as propagating
the vertical differences between pixels in L (starting from P), using the vertical differences between pixels in L (starting from P), using
the pixels from A to start each column. the pixels from A to start each column.
An implementation of chroma intra-prediction may be found in the An implementation of chroma intra-prediction may be found in the
reference decoder file reconintra.c. reference decoder file predict.c.
Unlike DC_PRED, for macroblocks on the top row or left edge TM_PRED Unlike DC_PRED, for macroblocks on the top row or left edge TM_PRED
does use the out-of-bounds values of 127 and 129 (respectively) does use the out-of-bounds values of 127 and 129 (respectively)
defined for V_PRED and H_PRED. defined for V_PRED and H_PRED.
12.3. Luma Prediction 12.3. Luma Prediction
The prediction processes for the first four 16x16 luma modes The prediction processes for the first four 16x16 luma modes
(DC_PRED, V_PRED, H_PRED, and TM_PRED) are essentially identical to (DC_PRED, V_PRED, H_PRED, and TM_PRED) are essentially identical to
the corresponding chroma prediction processes described above, the the corresponding chroma prediction processes described above, the
only difference being that we are predicting a single 16x16 luma only difference being that we are predicting a single 16x16 luma
block instead of two 8x8 chroma blocks. block instead of two 8x8 chroma blocks.
Thus, the row "A" and column "L" here contain 16 pixels, the DC Thus, the row "A" and column "L" here contain 16 pixels, the DC
prediction is calculated using 16 or 32 pixels (and shf is 4 or 5), prediction is calculated using 16 or 32 pixels (and shf is 4 or 5),
and we of course fill the entire prediction buffer, that is, 16 rows and we of course fill the entire prediction buffer, that is, 16 rows
(or columns) containing 16 pixels each. The reference implementation (or columns) containing 16 pixels each. The reference implementation
of 16x16 luma prediction is also in reconintra.c. of 16x16 luma prediction is also in predict.c.
In the remaining luma mode (B_PRED), each 4x4 Y subblock is In the remaining luma mode (B_PRED), each 4x4 Y subblock is
independently predicted using one of ten modes (listed, along with independently predicted using one of ten modes (listed, along with
their encodings, in Chapter 11). their encodings, in Chapter 11).
Also, unlike the full-macroblock modes already described, some of the Also, unlike the full-macroblock modes already described, some of the
subblock modes use prediction pixels above and to the right of the subblock modes use prediction pixels above and to the right of the
current subblock. In detail, each 4x4 subblock "B" is predicted current subblock. In detail, each 4x4 subblock "B" is predicted
using (at most) the 4-pixel column "L" immediately to the left of B using (at most) the 4-pixel column "L" immediately to the left of B
and the 8-pixel row "A" immediately above B, consisting of the 4 and the 8-pixel row "A" immediately above B, consisting of the 4
skipping to change at page 74, line 34 skipping to change at page 74, line 34
if( read_bool( d, coef_update_probs [i] [j] [k] [t])) if( read_bool( d, coef_update_probs [i] [j] [k] [t]))
coef_probs [i] [j] [k] [t] = read_literal( d, 8); coef_probs [i] [j] [k] [t] = read_literal( d, 8);
} while( ++t < num_dct_tokens - 1); } while( ++t < num_dct_tokens - 1);
} while( ++k < 3); } while( ++k < 3);
} while( ++j < 8); } while( ++j < 8);
} while( ++i < 4); } while( ++i < 4);
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
The (constant) update probabilities are as follows (they may also be The (constant) update probabilities are as follows:
found in the reference decoder file coef_update_probs.c).
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
const Prob coef_update_probs [4] [8] [3] [num_dct_tokens-1] = const Prob coef_update_probs [4] [8] [3] [num_dct_tokens-1] =
{ {
{ {
{ {
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
skipping to change at page 82, line 4 skipping to change at page 81, line 51
{ 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128}, { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
{ 141, 84, 213, 252, 201, 202, 255, 219, 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} { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128}
}, },
{ {
{ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{ 244, 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} { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}
} }
} }
}; };
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
14. DCT and WHT Inversion and Macroblock Reconstruction 14. DCT and WHT Inversion and Macroblock Reconstruction
14.1. Dequantization 14.1. Dequantization
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 dequant_data.h, 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,
16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 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, 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, 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, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
skipping to change at page 84, line 41 skipping to change at page 84, line 41
181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229,
234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284, 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284,
}; };
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
Lookup values from the above two tables are directly used the DC and Lookup values from the above two tables are directly used the DC and
AC coefficients in Y1 respectively. For Y2 and chroma, values from AC coefficients in Y1 respectively. For Y2 and chroma, values from
above tables undergo either a scaling process or clamping processing above tables undergo either a scaling process or clamping processing
before the multiplies. Details to these scaling and clamping can be before the multiplies. Details to these scaling and clamping can be
found related lookup functions in quant_common.c. found related lookup functions in dixie.c.
14.2. Inverse Transforms 14.2. Inverse Transforms
If the Y2 residue block exists (i.e., the macroblock luma mode is not If the Y2 residue block exists (i.e., the macroblock luma mode is not
SPLITMV or B_PRED), it is inverted first (using the inverse WHT) and SPLITMV or B_PRED), it is inverted first (using the inverse WHT) and
the element of the result at row i, column j is used as the 0th the element of the result at row i, column j is used as the 0th
coefficient of the Y subblock at position (i, j), that is, the Y coefficient of the Y subblock at position (i, j), that is, the Y
subblock whose index is (i * 4) + j. As discussed in Chapter 13, if subblock whose index is (i * 4) + j. As discussed in Chapter 13, if
the luma mode is B_PRED or SPLITMV, the 0th Y coefficients are part the luma mode is B_PRED or SPLITMV, the 0th Y coefficients are part
of the residue signal for the subblocks themselves. of the residue signal for the subblocks themselves.
skipping to change at page 91, line 33 skipping to change at page 91, line 33
entirely at the option of the implementor (and/or user) and has no entirely at the option of the implementor (and/or user) and has no
effect on decoding per se. effect on decoding per se.
The baseline frame level parameters controlling the loop filter are The baseline frame level parameters controlling the loop filter are
defined in the frame header (Chapter 9.4) along with a mechanism for defined in the frame header (Chapter 9.4) along with a mechanism for
adjustment based on a macroblock's prediction mode and/or reference adjustment based on a macroblock's prediction mode and/or reference
frame. The first is a flag selecting the type of filter (normal or frame. The first is a flag selecting the type of filter (normal or
simple), the other two are numbers (loop_filter_level and simple), the other two are numbers (loop_filter_level and
sharpness_level) that adjust the strength or sensitivity of the sharpness_level) that adjust the strength or sensitivity of the
filter. As described in Chapters 9.3 and 10, loop_filter_level may filter. As described in Chapters 9.3 and 10, loop_filter_level may
be also overridden on a per-macroblock basis using segmentation. also be overridden on a per-macroblock basis using segmentation.
Loop filtering is one of the more computationally-intensive aspects Loop filtering is one of the more computationally-intensive aspects
of VP8 decoding. This is the reason for the existence of the of VP8 decoding. This is the reason for the existence of the
optional less-demanding simple filter type. Also, the loop filter is optional, less-demanding simple filter type.
completely disabled if the loop_filter_level in the frame header is
zero; macroblock-level overrides are ignored in this case. (It is of Note carefully that loop filtering must be skipped entirely if
course possible for a compressor to encode a frame in which only a loop_filter_level at either the frame header level or macroblock
few macroblocks are loop filtered: The global loop_filter_level must override level is 0. In no case should the loop filter be run with a
be non-zero and each macroblock can select one of four levels, most value of 0; it should instead be skipped.
of which could be zero.)
To facilitate efficient implementation, the VP8 decoding algorithms To facilitate efficient implementation, the VP8 decoding algorithms
generally, and the loop filter especially, were designed with SIMD generally, and the loop filter especially, were designed with SIMD
("Single Instruction Multiple Datum" or "integer vector") processors ("Single Instruction Multiple Datum" or "integer vector") processors
in mind. The reference decoder implementation of loop filtering in mind. The reference decoder implementation of loop filtering
(found in loopfilter.c) is, in effect, a portable SIMD specification (found in loopfilter.c) is, in effect, a portable SIMD specification
of the loop filtering algorithms intended to simplify a realization of the loop filtering algorithms intended to simplify a realization
on an actual SIMD processor. on an actual SIMD processor.
Unfortunately, the approach taken there does not lead to maximal Unfortunately, the approach taken there does not lead to maximal
skipping to change at page 116, line 43 skipping to change at page 116, line 43
ZERO4x4 uses a zero motion vector and predicts the current subset ZERO4x4 uses a zero motion vector and predicts the current subset
using the corresponding subset from the prediction frame. using the corresponding subset from the prediction frame.
NEW4x4 is exactly like NEWMV except applied only to the current NEW4x4 is exactly like NEWMV except applied only to the current
subset. It is followed by a 2-dimensional motion vector offset subset. It is followed by a 2-dimensional motion vector offset
(described in the next chapter) that is added to the best vector (described in the next chapter) that is added to the best vector
returned by the earlier call to find_near_mvs to form the motion returned by the earlier call to find_near_mvs to form the motion
vector in effect for the subset. vector in effect for the subset.
Parsing of both inter-prediction modes and motion vectors (described Parsing of both inter-prediction modes and motion vectors (described
next) can be found in the reference decoder file decodemv.c. next) can be found in the reference decoder file modemv.c.
17. Motion Vector Decoding 17. Motion Vector Decoding
As discussed above, motion vectors appear in two places in the VP8 As discussed above, motion vectors appear in two places in the VP8
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
skipping to change at page 122, line 14 skipping to change at page 122, line 14
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
(Section 14) and loop filtering (Section 15). (Section 14) and loop filtering (Section 15).
The management of inter-predicted subblocks may be found in the The management of inter-predicted subblocks and sub-pixel
reference decoder file reconinter.c; sub-pixel interpolation is interpolation may be found in the reference decoder file predict.c.
implemented in filter_c.c.
18.1. Bounds on and Adjustment of Motion Vectors 18.1. Bounds on and Adjustment of Motion Vectors
Since each motion vector is differentially encoded from a neighboring Since each motion vector is differentially encoded from a neighboring
block or macroblock and the only clamp is to ensure that the block or macroblock and the only clamp is to ensure that the
referenced motion vector represents a valid location inside a referenced motion vector represents a valid location inside a
reference frame buffer, it is technically possible within the VP8 reference frame buffer, it is technically possible within the VP8
format for a block or macroblock to have arbitrarily large motion format for a block or macroblock to have arbitrarily large motion
vectors, up to the size of the input image plus the extended border vectors, up to the size of the input image plus the extended border
areas. For practical reasons, VP8 imposes a motion vector size range areas. For practical reasons, VP8 imposes a motion vector size range
limit of [-4096, 4095] full pixels, regardless of image size (VP8 limit of -4096 to 4095 full pixels, regardless of image size (VP8
defines 14 raw bits for width and height; 16383x16383 is the maximum defines 14 raw bits for width and height; 16383x16383 is the maximum
possible image size). Bitstream-compliant encoders and decoders possible image size). Bitstream-compliant encoders and decoders
shall enforce this limit. 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 -2046 to +2046, inclusive. integer in the range -2046 to +2046, inclusive.
skipping to change at page 147, line 7 skipping to change at page 147, line 7
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 (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 (Section 13.2) range defined by token (Section 13.2)
o sign indicates the sign of the coefficient (Section 13.2) o sign indicates the sign of the coefficient (Section 13.2)
20. Attachment One: Reference Decoder Source Code 20. Attachment One: Reference Decoder Source Code
Note that the code in this attachment may exhibit bugs, and should be
considered a draft until this document reaches RFC status.
20.1. bit_ops.h 20.1. bit_ops.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
skipping to change at page 170, line 22 skipping to change at page 170, line 22
unsigned int sz); unsigned int sz);
#define CLAMP_255(x) ((x)<0?0:((x)>255?255:(x))) #define CLAMP_255(x) ((x)<0?0:((x)>255?255:(x)))
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.6. dixie_loopfilter.c 20.6. dixie_loopfilter.c
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may * found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "dixie.h" #include "dixie.h"
#include "dixie_loopfilter.h" #include "dixie_loopfilter.h"
#define ABS(x) ((x) >= 0 ? (x) : -(x)) #define ABS(x) ((x) >= 0 ? (x) : -(x))
#define p3 pixels[-4*stride] #define p3 pixels[-4*stride]
#define p2 pixels[-3*stride] #define p2 pixels[-3*stride]
#define p1 pixels[-2*stride] #define p1 pixels[-2*stride]
#define p0 pixels[-1*stride] #define p0 pixels[-1*stride]
#define q0 pixels[ 0*stride] #define q0 pixels[ 0*stride]
#define q1 pixels[ 1*stride] #define q1 pixels[ 1*stride]
#define q2 pixels[ 2*stride] #define q2 pixels[ 2*stride]
#define q3 pixels[ 3*stride] #define q3 pixels[ 3*stride]
#define static #define static
static int static int
saturate_int8(int x) saturate_int8(int x)
{ {
if (x < -128) if (x < -128)
return -128; return -128;
if (x > 127) if (x > 127)
return 127; return 127;
return x; return x;
} }
static int static int
saturate_uint8(int x) saturate_uint8(int x)
{ {
if (x < 0) if (x < 0)
return 0; return 0;
if (x > 255) if (x > 255)
return 255; return 255;
return x; return x;
} }
static int static int
high_edge_variance(unsigned char *pixels, 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 stride,
int hev_threshold) int filter_limit)
{ {
return ABS(p1 - p0) > hev_threshold || return (ABS(p0 - q0) * 2 + (ABS(p1 - q1) >> 1)) <= filter_limit;
ABS(q1 - q0) > hev_threshold; }
}
static int static int
simple_threshold(unsigned char *pixels, normal_threshold(unsigned char *pixels,
int stride, int stride,
int filter_limit) int edge_limit,
{ int interior_limit)
return (ABS(p0 - q0) * 2 + (ABS(p1 - q1) >> 1)) <= filter_limit; {
} int E = edge_limit;
int I = interior_limit;
static int return simple_threshold(pixels, stride, 2 * E + I)
normal_threshold(unsigned char *pixels, && ABS(p3 - p2) <= I && ABS(p2 - p1) <= I
int stride, && ABS(p1 - p0) <= I && ABS(q3 - q2) <= I
int edge_limit, && ABS(q2 - q1) <= I && ABS(q1 - q0) <= I;
int interior_limit) }
{
int E = edge_limit;
int I = interior_limit;
return simple_threshold(pixels, stride, 2 * E + I) static void
&& ABS(p3 - p2) <= I && ABS(p2 - p1) <= I filter_common(unsigned char *pixels,
&& ABS(p1 - p0) <= I && ABS(q3 - q2) <= I int stride,
&& ABS(q2 - q1) <= I && ABS(q1 - q0) <= I; int use_outer_taps)
} {
int a, f1, f2;
static void a = 3 * (q0 - p0);
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);
if (use_outer_taps) a = saturate_int8(a);
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;
f1 = ((a + 4 > 127) ? 127 : a + 4) >> 3; p0 = saturate_uint8(p0 + f2);
f2 = ((a + 3 > 127) ? 127 : a + 3) >> 3; q0 = saturate_uint8(q0 - f1);
p0 = saturate_uint8(p0 + f2); if (!use_outer_taps)
q0 = saturate_uint8(q0 - f1); {
/* 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);
}
}
if (!use_outer_taps) static void
{ filter_mb_edge(unsigned char *pixels,
/* This handles the case of subblock_filter() int stride)
* (from the bitstream guide. {
*/ int w, a;
a = (f1 + 1) >> 1;
p1 = saturate_uint8(p1 + a);
q1 = saturate_uint8(q1 - a);
}
}
static void w = saturate_int8(saturate_int8(p1 - q1) + 3 * (q0 - p0));
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 = (27 * w + 63) >> 7; a = (18 * w + 63) >> 7;
p0 = saturate_uint8(p0 + a); p1 = saturate_uint8(p1 + a);
q0 = saturate_uint8(q0 - a); q1 = saturate_uint8(q1 - a);
a = (18 * w + 63) >> 7; a = (9 * w + 63) >> 7;
p1 = saturate_uint8(p1 + a); p2 = saturate_uint8(p2 + a);
q1 = saturate_uint8(q1 - a); q2 = saturate_uint8(q2 - 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;
static void for (i = 0; i < 8 * size; i++)
filter_mb_v_edge(unsigned char *src, {
int stride, if (normal_threshold(src, 1, edge_limit, interior_limit))
int edge_limit, {
int interior_limit, if (high_edge_variance(src, 1, hev_threshold))
int hev_threshold, filter_common(src, 1, 1);
int size) else
{ filter_mb_edge(src, 1);
int i; }
for (i = 0; i < 8 * size; i++) src += stride;
{ }
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;
static void for (i = 0; i < 8 * size; i++)
filter_subblock_v_edge(unsigned char *src, {
int stride, if (normal_threshold(src, 1, edge_limit, interior_limit))
int edge_limit, filter_common(src, 1,
int interior_limit, high_edge_variance(src, 1, hev_threshold));
int hev_threshold,
int size)
{
int i;
for (i = 0; i < 8 * size; i++) src += stride;
{ }
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;
static void for (i = 0; i < 8 * size; i++)
filter_mb_h_edge(unsigned char *src, {
int stride, if (normal_threshold(src, stride, edge_limit,
int edge_limit, interior_limit))
int interior_limit, {
int hev_threshold, if (high_edge_variance(src, stride, hev_threshold))
int size) filter_common(src, stride, 1);
{ else
int i; filter_mb_edge(src, stride);
}
for (i = 0; i < 8 * size; i++) src += 1;
{ }
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;
static void for (i = 0; i < 8 * size; i++)
filter_subblock_h_edge(unsigned char *src, {
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 stride,
int edge_limit, int filter_limit)
int interior_limit, {
int hev_threshold, int i;
int size)
{
int i;
for (i = 0; i < 8 * size; i++) for (i = 0; i < 16; i++)
{ {
if (normal_threshold(src, stride, edge_limit, interior_limit)) if (simple_threshold(src, 1, filter_limit))
filter_common(src, stride, filter_common(src, 1, 1);
high_edge_variance(src, stride,
hev_threshold));
src += 1; src += stride;
} }
} }
static void static void
filter_v_edge_simple(unsigned char *src, filter_h_edge_simple(unsigned char *src,
int stride, int stride,
int filter_limit) int filter_limit)
{ {
int i; int i;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
if (simple_threshold(src, 1, filter_limit)) if (simple_threshold(src, stride, filter_limit))
filter_common(src, 1, 1); filter_common(src, stride, 1);
src += stride; src += 1;
}
}
static void }
filter_h_edge_simple(unsigned char *src, }
int stride,
int filter_limit)
{
int i;
for (i = 0; i < 16; i++) static void
{ calculate_filter_parameters(struct vp8_decoder_ctx *ctx,
if (simple_threshold(src, stride, filter_limit)) struct mb_info *mbi,
filter_common(src, stride, 1); int *edge_limit_,
int *interior_limit_,
int *hev_threshold_)
{
int filter_level, interior_limit, hev_threshold;
src += 1; /* Reference code/spec seems to conflate filter_level and
} * edge_limit
} */
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 filter_level = ctx->loopfilter_hdr.level;
* 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->segment_hdr.enabled) if (filter_level > 63)
{ filter_level = 63;
if (!ctx->segment_hdr.abs) else if (filter_level < 0)
filter_level += filter_level = 0;
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) if (ctx->loopfilter_hdr.delta_enabled)
{ {
filter_level += filter_level +=
ctx->loopfilter_hdr.ref_delta[mbi->base.ref_frame]; ctx->loopfilter_hdr.ref_delta[mbi->base.ref_frame];
if (mbi->base.ref_frame == CURRENT_FRAME) if (mbi->base.ref_frame == CURRENT_FRAME)
{ {
if (mbi->base.y_mode == B_PRED) if (mbi->base.y_mode == B_PRED)
filter_level += ctx->loopfilter_hdr.mode_delta[0]; filter_level += ctx->loopfilter_hdr.mode_delta[0];
} }
else if (mbi->base.y_mode == ZEROMV) else if (mbi->base.y_mode == ZEROMV)
filter_level += ctx->loopfilter_hdr.mode_delta[1]; filter_level += ctx->loopfilter_hdr.mode_delta[1];
else if (mbi->base.y_mode == SPLITMV) else if (mbi->base.y_mode == SPLITMV)
filter_level += ctx->loopfilter_hdr.mode_delta[3]; filter_level += ctx->loopfilter_hdr.mode_delta[3];
else
filter_level += ctx->loopfilter_hdr.mode_delta[2];
}
if (filter_level > 63) else
filter_level = 63; filter_level += ctx->loopfilter_hdr.mode_delta[2];
else if (filter_level < 0) }
filter_level = 0;
interior_limit = filter_level; if (filter_level > 63)
filter_level = 63;
else if (filter_level < 0)
filter_level = 0;
if (ctx->loopfilter_hdr.sharpness) interior_limit = filter_level;
{
interior_limit >>= ctx->loopfilter_hdr.sharpness > 4 ? 2 : 1;
if (interior_limit > 9 - ctx->loopfilter_hdr.sharpness) if (ctx->loopfilter_hdr.sharpness)
interior_limit = 9 - ctx->loopfilter_hdr.sharpness; {
} interior_limit >>= ctx->loopfilter_hdr.sharpness > 4 ? 2 : 1;
if (interior_limit < 1) if (interior_limit > 9 - ctx->loopfilter_hdr.sharpness)
interior_limit = 1; interior_limit = 9 - ctx->loopfilter_hdr.sharpness;
}
hev_threshold = (filter_level >= 15); if (interior_limit < 1)
interior_limit = 1;
if (filter_level >= 40) hev_threshold = (filter_level >= 15);
hev_threshold++;
if (filter_level >= 20 && !ctx->frame_hdr.is_keyframe) if (filter_level >= 40)
hev_threshold++; hev_threshold++;
*edge_limit_ = filter_level; if (filter_level >= 20 && !ctx->frame_hdr.is_keyframe)
*interior_limit_ = interior_limit; hev_threshold++;
*hev_threshold_ = hev_threshold;
}
static void *edge_limit_ = filter_level;
filter_row_normal(struct vp8_decoder_ctx *ctx, *interior_limit_ = interior_limit;
unsigned int row, *hev_threshold_ = hev_threshold;
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 */ static void
stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y]; filter_row_normal(struct vp8_decoder_ctx *ctx,
uv_stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U]; unsigned int row,
y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y]; unsigned int start_col,
u = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_U]; unsigned int num_cols)
v = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_V]; {
y += (stride * row + start_col) * 16; unsigned char *y, *u, *v;
u += (uv_stride * row + start_col) * 8; int stride, uv_stride;
v += (uv_stride * row + start_col) * 8; struct mb_info *mbi;
mbi = ctx->mb_info_rows[row] + start_col; unsigned int 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 /* Adjust pointers based on row, start_col */
* enabled. stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
*/ uv_stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U];
calculate_filter_parameters(ctx, mbi, &edge_limit, y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
&interior_limit, &hev_threshold); 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;
if (edge_limit) for (col = start_col; col < start_col + num_cols; col++)
{ {
if (col) int edge_limit, interior_limit, hev_threshold;
{
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 /* TODO: only need to recalculate every MB if segmentation is
* number of coefficients decoded, not the skip flag as * enabled.
* coded in the bitstream. The tokens task is expected to */
* set 31 if there is *any* non-zero data. calculate_filter_parameters(ctx, mbi, &edge_limit,
*/ &interior_limit, &hev_threshold);
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 if (edge_limit)
|| mbi->base.y_mode == SPLITMV {
|| mbi->base.y_mode == B_PRED) if (col)
{ {
filter_subblock_h_edge(y + 4 * stride, stride, filter_mb_v_edge(y, stride, edge_limit + 2,
edge_limit, interior_limit, interior_limit, hev_threshold, 2);
hev_threshold, 2); filter_mb_v_edge(u, uv_stride, edge_limit + 2,
filter_subblock_h_edge(y + 8 * stride, stride, interior_limit, hev_threshold, 1);
edge_limit, interior_limit, filter_mb_v_edge(v, uv_stride, edge_limit + 2,
hev_threshold, 2); interior_limit, hev_threshold, 1);
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; /* NOTE: This conditional is actually dependent on the
u += 8; * number of coefficients decoded, not the skip flag as
v += 8; * coded in the bitstream. The tokens task is expected to
mbi++; * 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);
}
static void if (row)
filter_row_simple(struct vp8_decoder_ctx *ctx, {
unsigned int row, filter_mb_h_edge(y, stride, edge_limit + 2,
unsigned int start_col, interior_limit, hev_threshold, 2);
unsigned int num_cols) filter_mb_h_edge(u, uv_stride, edge_limit + 2,
{ interior_limit, hev_threshold, 1);
unsigned char *y; filter_mb_h_edge(v, uv_stride, edge_limit + 2,
int stride; interior_limit, hev_threshold, 1);
struct mb_info *mbi; }
unsigned int col;
/* Adjust pointers based on row, start_col */ if (mbi->base.eob_mask
stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y]; || mbi->base.y_mode == SPLITMV
y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y]; || mbi->base.y_mode == B_PRED)
y += (stride * row + start_col) * 16; {
mbi = ctx->mb_info_rows[row] + start_col; 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);
}
}
for (col = start_col; col < start_col + num_cols; col++) y += 16;
{ u += 8;
int edge_limit, interior_limit, hev_threshold; 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;
/* TODO: only need to recalculate every MB if segmentation is /* Adjust pointers based on row, start_col */
* enabled. stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
*/ y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
calculate_filter_parameters(ctx, mbi, &edge_limit, y += (stride * row + start_col) * 16;
&interior_limit, &hev_threshold); mbi = ctx->mb_info_rows[row] + start_col;
if (edge_limit) for (col = start_col; col < start_col + num_cols; col++)
{ {
int edge_limit, interior_limit, hev_threshold;
/* NOTE: This conditional is actually dependent on the /* TODO: only need to recalculate every MB if segmentation is
* number of coefficients decoded, not the skip flag as * enabled.
* coded in the bitstream. The tokens task is expected to */
* set 31 if there is *any* non-zero data. calculate_filter_parameters(ctx, mbi, &edge_limit,
*/ &interior_limit, &hev_threshold);
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) if (edge_limit)
filter_v_edge_simple(y, stride, mb_limit); {
if (filter_subblocks) /* NOTE: This conditional is actually dependent on the
{ * number of coefficients decoded, not the skip flag as
filter_v_edge_simple(y + 4, stride, b_limit); * coded in the bitstream. The tokens task is expected to
filter_v_edge_simple(y + 8, stride, b_limit); * set 31 if there is *any* non-zero data.
filter_v_edge_simple(y + 12, stride, b_limit); */
} 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 (row) if (col)
filter_h_edge_simple(y, stride, mb_limit); filter_v_edge_simple(y, stride, mb_limit);
if (filter_subblocks) if (filter_subblocks)
{ {
filter_h_edge_simple(y + 4 * stride, stride, b_limit); filter_v_edge_simple(y + 4, stride, b_limit);
filter_h_edge_simple(y + 8 * stride, stride, b_limit); filter_v_edge_simple(y + 8, stride, b_limit);
filter_h_edge_simple(y + 12 * stride, stride, b_limit); filter_v_edge_simple(y + 12, stride, b_limit);
} }
}
y += 16; if (row)
mbi++; filter_h_edge_simple(y, stride, mb_limit);
}
}
void if (filter_subblocks)
vp8_dixie_loopfilter_process_row(struct vp8_decoder_ctx *ctx, {
unsigned int row, filter_h_edge_simple(y + 4 * stride, stride,
unsigned int start_col, b_limit);
unsigned int num_cols) filter_h_edge_simple(y + 8 * stride, stride,
{ b_limit);
if (ctx->loopfilter_hdr.use_simple) filter_h_edge_simple(y + 12 * stride, stride,
filter_row_simple(ctx, row, start_col, num_cols); b_limit);
else }
filter_row_normal(ctx, row, start_col, num_cols); }
}
---- End code block ---------------------------------------- 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 ----------------------------------------
20.7. dixie_loopfilter.h 20.7. dixie_loopfilter.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
skipping to change at page 188, line 8 skipping to change at page 188, line 8
*/ */
#if defined(__GNUC__) && __GNUC__ #if defined(__GNUC__) && __GNUC__
#define UNINITIALIZED_IS_SAFE(x) x=x #define UNINITIALIZED_IS_SAFE(x) x=x
#else #else
#define UNINITIALIZED_IS_SAFE(x) x #define UNINITIALIZED_IS_SAFE(x) x
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.11. modemv.c 20.11. modemv.c
---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may * found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "dixie.h" #include "dixie.h"
#include "modemv_data.h" #include "modemv_data.h"
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
struct mv_clamp_rect struct mv_clamp_rect
{ {
int to_left, to_right, to_top, to_bottom; int to_left, to_right, to_top, to_bottom;
}; };
static union mv static union mv
clamp_mv(union mv raw, const struct mv_clamp_rect *bounds) clamp_mv(union mv raw, const struct mv_clamp_rect *bounds)
{ {
union mv newmv; union mv newmv;
newmv.d.x = (raw.d.x < bounds->to_left) newmv.d.x = (raw.d.x < bounds->to_left)
? bounds->to_left : raw.d.x; ? bounds->to_left : raw.d.x;
newmv.d.x = (raw.d.x > bounds->to_right) newmv.d.x = (raw.d.x > bounds->to_right)
? bounds->to_right : newmv.d.x; ? bounds->to_right : newmv.d.x;
newmv.d.y = (raw.d.y < bounds->to_top) newmv.d.y = (raw.d.y < bounds->to_top)
? bounds->to_top : raw.d.y; ? bounds->to_top : raw.d.y;
newmv.d.y = (raw.d.y > bounds->to_bottom) newmv.d.y = (raw.d.y > bounds->to_bottom)
? bounds->to_bottom : newmv.d.y; ? bounds->to_bottom : newmv.d.y;
return newmv; return newmv;
} }
static int static int
read_segment_id(struct bool_decoder *bool, read_segment_id(struct bool_decoder *bool,
struct vp8_segment_hdr *seg) struct vp8_segment_hdr *seg)
{ {
return bool_get(bool, seg->tree_probs[0]) return bool_get(bool, seg->tree_probs[0])
? 2 + bool_get(bool, seg->tree_probs[2]) ? 2 + bool_get(bool, seg->tree_probs[2])
: bool_get(bool, seg->tree_probs[1]); : bool_get(bool, seg->tree_probs[1]);
} }
static enum prediction_mode static enum prediction_mode
above_block_mode(const struct mb_info *this, above_block_mode(const struct mb_info *this,
const struct mb_info *above, const struct mb_info *above,
unsigned int b) unsigned int b)
{ {
if (b < 4) if (b < 4)
{ {
switch (above->base.y_mode) switch (above->base.y_mode)
{ {
case DC_PRED: case DC_PRED:
return B_DC_PRED; return B_DC_PRED;
case V_PRED: case V_PRED:
return B_VE_PRED; return B_VE_PRED;
case H_PRED: case H_PRED:
return B_HE_PRED; return B_HE_PRED;
case TM_PRED: case TM_PRED:
return B_TM_PRED; return B_TM_PRED;
case B_PRED: case B_PRED:
return above->split.modes[b+12]; return above->split.modes[b+12];
default: default:
assert(0); assert(0);
} }
} }
return this->split.modes[b-4]; return this->split.modes[b-4];
} }
static enum prediction_mode static enum prediction_mode
left_block_mode(const struct mb_info *this, left_block_mode(const struct mb_info *this,
const struct mb_info *left, const struct mb_info *left,
unsigned int b) unsigned int b)
{ {
if (!(b & 3)) if (!(b & 3))
{ {
switch (left->base.y_mode) switch (left->base.y_mode)
{ {
case DC_PRED: case DC_PRED:
return B_DC_PRED; return B_DC_PRED;
case V_PRED: case V_PRED:
return B_VE_PRED; return B_VE_PRED;
case H_PRED: case H_PRED:
return B_HE_PRED; return B_HE_PRED;
case TM_PRED: case TM_PRED:
return B_TM_PRED; return B_TM_PRED;
case B_PRED: case B_PRED:
return left->split.modes[b+3]; return left->split.modes[b+3];
default: default:
assert(0); assert(0);
} }
} }
return this->split.modes[b-1]; return this->split.modes[b-1];
} }
static void static void
decode_kf_mb_mode(struct mb_info *this, decode_kf_mb_mode(struct mb_info *this,
struct mb_info *left, struct mb_info *left,
struct mb_info *above, struct mb_info *above,
struct bool_decoder *bool) struct bool_decoder *bool)
{ {
int y_mode, uv_mode; int y_mode, uv_mode;
y_mode = bool_read_tree(bool, kf_y_mode_tree, kf_y_mode_probs); y_mode = bool_read_tree(bool, kf_y_mode_tree, kf_y_mode_probs);
if (y_mode == B_PRED) if (y_mode == B_PRED)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
enum prediction_mode a = above_block_mode(this, above, i); enum prediction_mode a = above_block_mode(this, above,
enum prediction_mode l = left_block_mode(this, left, i); i);
enum prediction_mode b; enum prediction_mode l = left_block_mode(this, left, i);
enum prediction_mode b;
b = bool_read_tree(bool, b_mode_tree, b = bool_read_tree(bool, b_mode_tree,
kf_b_mode_probs[a][l]); kf_b_mode_probs[a][l]);
this->split.modes[i] = b; this->split.modes[i] = b;
} }
} }
uv_mode = bool_read_tree(bool, uv_mode_tree, kf_uv_mode_probs); uv_mode = bool_read_tree(bool, uv_mode_tree, kf_uv_mode_probs);
this->base.y_mode = y_mode; this->base.y_mode = y_mode;
this->base.uv_mode = uv_mode; this->base.uv_mode = uv_mode;
this->base.mv.raw = 0; this->base.mv.raw = 0;
this->base.ref_frame = 0; this->base.ref_frame = 0;
} }
static void static void
decode_intra_mb_mode(struct mb_info *this, decode_intra_mb_mode(struct mb_info *this,
struct vp8_entropy_hdr *hdr, struct vp8_entropy_hdr *hdr,
struct bool_decoder *bool) struct bool_decoder *bool)
{ {
/* Like decode_kf_mb_mode, but with probabilities transmitted in the /* Like decode_kf_mb_mode, but with probabilities transmitted in
* bitstream and no context on the above/left block mode. * the bitstream and no context on the above/left block mode.
*/ */
int y_mode, uv_mode; int y_mode, uv_mode;
y_mode = bool_read_tree(bool, y_mode_tree, hdr->y_mode_probs); y_mode = bool_read_tree(bool, y_mode_tree, hdr->y_mode_probs);
if (y_mode == B_PRED) if (y_mode == B_PRED)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
enum prediction_mode b; enum prediction_mode b;
b = bool_read_tree(bool, b_mode_tree, default_b_mode_probs); b = bool_read_tree(bool, b_mode_tree,
this->split.modes[i] = b; default_b_mode_probs);
} this->split.modes[i] = b;
} }
}
uv_mode = bool_read_tree(bool, uv_mode_tree, hdr->uv_mode_probs); uv_mode = bool_read_tree(bool, uv_mode_tree, hdr->uv_mode_probs);
this->base.y_mode = y_mode; this->base.y_mode = y_mode;
this->base.uv_mode = uv_mode; this->base.uv_mode = uv_mode;
this->base.mv.raw = 0; this->base.mv.raw = 0;
this->base.ref_frame = CURRENT_FRAME; this->base.ref_frame = CURRENT_FRAME;
} }
static int static int
read_mv_component(struct bool_decoder *bool, read_mv_component(struct bool_decoder *bool,
const unsigned char mvc[MV_PROB_CNT]) const unsigned char mvc[MV_PROB_CNT])
{ {
enum {IS_SHORT, SIGN, SHORT, BITS = SHORT + 8 - 1, LONG_WIDTH = 10}; enum {IS_SHORT, SIGN, SHORT, BITS = SHORT + 8 - 1,
int x = 0; LONG_WIDTH = 10};
int x = 0;
if (bool_get(bool, mvc[IS_SHORT])) /* Large */ if (bool_get(bool, mvc[IS_SHORT])) /* Large */
{ {
int i = 0; int i = 0;
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
x += bool_get(bool, mvc[BITS + i]) << i; x += bool_get(bool, mvc[BITS + i]) << i;
/* Skip bit 3, which is sometimes implicit */ /* Skip bit 3, which is sometimes implicit */
for (i = LONG_WIDTH - 1; i > 3; i--) for (i = LONG_WIDTH - 1; i > 3; i--)
x += bool_get(bool, mvc[BITS + i]) << i; x += bool_get(bool, mvc[BITS + i]) << i;
if (!(x & 0xFFF0) || bool_get(bool, mvc[BITS + 3])) if (!(x & 0xFFF0) || bool_get(bool, mvc[BITS + 3]))
x += 8; x += 8;
} }
else /* small */ else /* small */
x = bool_read_tree(bool, small_mv_tree, mvc + SHORT); x = bool_read_tree(bool, small_mv_tree, mvc + SHORT);
if (x && bool_get(bool, mvc[SIGN])) if (x && bool_get(bool, mvc[SIGN]))
x = -x; x = -x;
return x << 1; return x << 1;
} }
static mv_t static mv_t
above_block_mv(const struct mb_info *this, above_block_mv(const struct mb_info *this,
const struct mb_info *above, const struct mb_info *above,
unsigned int b) unsigned int b)
{ {
if (b < 4) if (b < 4)
{ {
if (above->base.y_mode == SPLITMV) if (above->base.y_mode == SPLITMV)
return above->split.mvs[b+12]; return above->split.mvs[b+12];
return above->base.mv; return above->base.mv;
} }
return this->split.mvs[b-4]; return this->split.mvs[b-4];
} }
static mv_t static mv_t
left_block_mv(const struct mb_info *this, left_block_mv(const struct mb_info *this,
const struct mb_info *left, const struct mb_info *left,
unsigned int b) unsigned int b)
{ {
if (!(b & 3)) if (!(b & 3))
{ {
if (left->base.y_mode == SPLITMV) if (left->base.y_mode == SPLITMV)
return left->split.mvs[b+3]; return left->split.mvs[b+3];
return left->base.mv; return left->base.mv;
} }
return this->split.mvs[b-1];
}
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;
static enum prediction_mode if (lea && lez)
submv_ref(struct bool_decoder *bool, union mv l, union mv a) ctx = SUBMVREF_LEFT_ABOVE_ZED;
{ else if (lea)
enum subblock_mv_ref ctx = SUBMVREF_LEFT_ABOVE_SAME;
{ else if (aez)
SUBMVREF_NORMAL, ctx = SUBMVREF_ABOVE_ZED;
SUBMVREF_LEFT_ZED, else if (lez)
SUBMVREF_ABOVE_ZED, ctx = SUBMVREF_LEFT_ZED;
SUBMVREF_LEFT_ABOVE_SAME,
SUBMVREF_LEFT_ABOVE_ZED
};
int lez = !(l.raw); return bool_read_tree(bool, submv_ref_tree,
int aez = !(a.raw); submv_ref_probs2[ctx]);
int lea = l.raw == a.raw; }
enum subblock_mv_ref ctx = SUBMVREF_NORMAL;
if (lea && lez) static void
ctx = SUBMVREF_LEFT_ABOVE_ZED; read_mv(struct bool_decoder *bool,
else if (lea) union mv *mv,
ctx = SUBMVREF_LEFT_ABOVE_SAME; mv_component_probs_t mvc[2])
else if (aez) {
ctx = SUBMVREF_ABOVE_ZED; mv->d.y = read_mv_component(bool, mvc[0]);
else if (lez) mv->d.x = read_mv_component(bool, mvc[1]);
ctx = SUBMVREF_LEFT_ZED; }
return bool_read_tree(bool, submv_ref_tree, submv_ref_probs2[ctx]); 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;
}
}
static void enum near_mv_v
read_mv(struct bool_decoder *bool, {
union mv *mv, CNT_BEST = 0,
mv_component_probs_t mvc[2]) CNT_ZEROZERO = 0,
{ CNT_NEAREST,
mv->d.y = read_mv_component(bool, mvc[0]); CNT_NEAR,
mv->d.x = read_mv_component(bool, mvc[1]); CNT_SPLITMV
} };
static void static void
mv_bias(const struct mb_info *mb, find_near_mvs(const struct mb_info *this,
const unsigned int sign_bias[3], const struct mb_info *left,
enum reference_frame ref_frame, const struct mb_info *above,
union mv *mv) 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 */
if (sign_bias[mb->base.ref_frame] ^ sign_bias[ref_frame]) mv[0].raw = mv[1].raw = mv[2].raw = 0;
{ cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
mv->d.x *= -1;
mv->d.y *= -1;
}
}
enum near_mv_v /* Process above */
{ if (above->base.ref_frame != CURRENT_FRAME)
CNT_BEST = 0, {
CNT_ZEROZERO = 0, if (above->base.mv.raw)
CNT_NEAREST, {
CNT_NEAR, (++mv)->raw = above->base.mv.raw;
CNT_SPLITMV mv_bias(above, sign_bias, this->base.ref_frame, mv);
}; ++cntx;
}
static void *cntx += 2;
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 */ /* Process left */
if (above->base.ref_frame != CURRENT_FRAME) if (left->base.ref_frame != CURRENT_FRAME)
{ {
if (above->base.mv.raw) if (left->base.mv.raw)
{ {
(++mv)->raw = above->base.mv.raw; union mv this_mv;
mv_bias(above, sign_bias, this->base.ref_frame, mv);
++cntx;
}
*cntx += 2; this_mv.raw = left->base.mv.raw;
} mv_bias(left, sign_bias, this->base.ref_frame, &this_mv);
/* 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; if (this_mv.raw != mv->raw)
mv_bias(left, sign_bias, this->base.ref_frame, &this_mv); {
(++mv)->raw = this_mv.raw;
++cntx;
}
if (this_mv.raw != mv->raw) *cntx += 2;
{ }
(++mv)->raw = this_mv.raw; else
++cntx; cnt[CNT_ZEROZERO] += 2;
} }
*cntx += 2; /* Process above left */
} if (aboveleft->base.ref_frame != CURRENT_FRAME)
else {
cnt[CNT_ZEROZERO] += 2; if (aboveleft->base.mv.raw)
} {
union mv this_mv;
/* Process above left */ this_mv.raw = aboveleft->base.mv.raw;
if (aboveleft->base.ref_frame != CURRENT_FRAME) mv_bias(aboveleft, sign_bias, this->base.ref_frame,
{ &this_mv);
if (aboveleft->base.mv.raw)
{
union mv this_mv;
this_mv.raw = aboveleft->base.mv.raw; if (this_mv.raw != mv->raw)
mv_bias(aboveleft, sign_bias, this->base.ref_frame, {
&this_mv); (++mv)->raw = this_mv.raw;
++cntx;
}
if (this_mv.raw != mv->raw) *cntx += 1;
{ }
(++mv)->raw = this_mv.raw; else
++cntx; cnt[CNT_ZEROZERO] += 1;
} }
*cntx += 1; /* If we have three distinct MV's ... */
} if (cnt[CNT_SPLITMV])
else {
cnt[CNT_ZEROZERO] += 1; /* See if above-left MV can be merged with NEAREST */
} if (mv->raw == near_mvs[CNT_NEAREST].raw)
cnt[CNT_NEAREST] += 1;
}
/* If we have three distinct MV's ... */ cnt[CNT_SPLITMV] = ((above->base.y_mode == SPLITMV)
if (cnt[CNT_SPLITMV]) + (left->base.y_mode == SPLITMV)) * 2
{ + (aboveleft->base.y_mode == 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) /* Swap near and nearest if necessary */
+ (left->base.y_mode == SPLITMV)) * 2 if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
+ (aboveleft->base.y_mode == SPLITMV); {
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;
}
/* Swap near and nearest if necessary */ /* Use near_mvs[CNT_BEST] to store the "best" MV. Note that this
if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) * storage shares the same address as near_mvs[CNT_ZEROZERO].
{ */
int tmp; if (cnt[CNT_NEAREST] >= cnt[CNT_BEST])
tmp = cnt[CNT_NEAREST]; near_mvs[CNT_BEST] = near_mvs[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 static void
* storage shares the same address as near_mvs[CNT_ZEROZERO]. decode_split_mv(struct mb_info *this,
*/ const struct mb_info *left,
if (cnt[CNT_NEAREST] >= cnt[CNT_BEST]) const struct mb_info *above,
near_mvs[CNT_BEST] = near_mvs[CNT_NEAREST]; struct vp8_entropy_hdr *hdr,
} union mv *best_mv,
struct bool_decoder *bool)
{
const int *partition;
int j, k, mask, partition_id;
static void partition_id = bool_read_tree(bool, split_mv_tree,
decode_split_mv(struct mb_info *this, split_mv_probs);
const struct mb_info *left, partition = mv_partitions[partition_id];
const struct mb_info *above, this->base.partitioning = partition_id;
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); for (j = 0, mask = 0; mask < 65535; j++)
partition = mv_partitions[partition_id]; {
this->base.partitioning = partition_id; union mv mv, left_mv, above_mv;
enum prediction_mode subblock_mode;
for (j = 0, mask = 0; mask < 65535; j++) /* Find the first subblock in this partition. */
{ for (k = 0; j != partition[k]; k++);
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 */ /* Decode the next MV */
left_mv = left_block_mv(this, left, k); left_mv = left_block_mv(this, left, k);
above_mv = above_block_mv(this, above, k); above_mv = above_block_mv(this, above, k);
subblock_mode = submv_ref(bool, left_mv, above_mv); subblock_mode = submv_ref(bool, left_mv, above_mv);
switch (subblock_mode) switch (subblock_mode)
{ {
case LEFT4X4: case LEFT4X4:
mv = left_mv; mv = left_mv;
break; break;
case ABOVE4X4: case ABOVE4X4:
mv = above_mv; mv = above_mv;
break; break;
case ZERO4X4: case ZERO4X4:
mv.raw = 0; mv.raw = 0;
break; break;
case NEW4X4: case NEW4X4:
read_mv(bool, &mv, hdr->mv_probs); read_mv(bool, &mv, hdr->mv_probs);
mv.d.x += best_mv->d.x; mv.d.x += best_mv->d.x;
mv.d.y += best_mv->d.y; mv.d.y += best_mv->d.y;
break; break;
default: default:
assert(0); assert(0);
} }
/* Fill the MV's for this partition */ /* Fill the MV's for this partition */
for (; k < 16; k++) for (; k < 16; k++)
if (j == partition[k]) if (j == partition[k])
{ {
this->split.mvs[k] = mv; this->split.mvs[k] = mv;
mask |= 1 << k; mask |= 1 << k;
} }
} }
} }
static int static int
need_mc_border(union mv mv, int l, int t, int b_w, int w, int h) need_mc_border(union mv mv, int l, int t, int b_w, int w, int h)
{ {
int b, r; 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 top-left pixel */ /* Get distance to edge for bottom-right pixel */
l += (mv.d.x >> 3); r = w - (l + b_w);
t += (mv.d.y >> 3); b = h - (t + b_w);
/* 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); return (l >> 1 < 2 || r >> 1 < 3 || t >> 1 < 2 || b >> 1 < 3);
} }
static void static void
decode_mvs(struct vp8_decoder_ctx *ctx, decode_mvs(struct vp8_decoder_ctx *ctx,
struct mb_info *this, struct mb_info *this,
const struct mb_info *left, const struct mb_info *left,
const struct mb_info *above, const struct mb_info *above,
const struct mv_clamp_rect *bounds, const struct mv_clamp_rect *bounds,
struct bool_decoder *bool) struct bool_decoder *bool)
{ {
struct vp8_entropy_hdr *hdr = &ctx->entropy_hdr; struct vp8_entropy_hdr *hdr = &ctx->entropy_hdr;
union mv near_mvs[4]; union mv near_mvs[4];
union mv clamped_best_mv; union mv clamped_best_mv;
int mv_cnts[4]; int mv_cnts[4];
unsigned char probs[4]; unsigned char probs[4];
enum {BEST, NEAREST, NEAR}; enum {BEST, NEAREST, NEAR};
int x, y, w, h, b; int x, y, w, h, b;
this->base.ref_frame = bool_get(bool, hdr->prob_last) this->base.ref_frame = bool_get(bool, hdr->prob_last)
? 2 + bool_get(bool, hdr->prob_gf) ? 2 + bool_get(bool, hdr->prob_gf)
: 1; : 1;
find_near_mvs(this, this - 1, above, ctx->reference_hdr.sign_bias, find_near_mvs(this, this - 1, above,
near_mvs, mv_cnts); ctx->reference_hdr.sign_bias, near_mvs, mv_cnts);
probs[0] = mv_counts_to_probs[mv_cnts[0]][0]; probs[0] = mv_counts_to_probs[mv_cnts[0]][0];
probs[1] = mv_counts_to_probs[mv_cnts[1]][1]; probs[1] = mv_counts_to_probs[mv_cnts[1]][1];
probs[2] = mv_counts_to_probs[mv_cnts[2]][2]; probs[2] = mv_counts_to_probs[mv_cnts[2]][2];
probs[3] = mv_counts_to_probs[mv_cnts[3]][3]; probs[3] = mv_counts_to_probs[mv_cnts[3]][3];
this->base.y_mode = bool_read_tree(bool, mv_ref_tree, probs); this->base.y_mode = bool_read_tree(bool, mv_ref_tree, probs);
this->base.uv_mode = this->base.y_mode; this->base.uv_mode = this->base.y_mode;
this->base.need_mc_border = 0; this->base.need_mc_border = 0;
x = (-bounds->to_left - 128) >> 3; x = (-bounds->to_left - 128) >> 3;
y = (-bounds->to_top - 128) >> 3; y = (-bounds->to_top - 128) >> 3;
w = ctx->mb_cols * 16; w = ctx->mb_cols * 16;
h = ctx->mb_rows * 16; h = ctx->mb_rows * 16;
switch (this->base.y_mode) switch (this->base.y_mode)
{ {
case NEARESTMV: case NEARESTMV:
this->base.mv = clamp_mv(near_mvs[NEAREST], bounds); this->base.mv = clamp_mv(near_mvs[NEAREST], bounds);
break; 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}}};
case NEARMV: clamped_best_mv = clamp_mv(near_mvs[BEST], bounds);
this->base.mv = clamp_mv(near_mvs[NEAR], bounds); decode_split_mv(this, left, above, hdr, &clamped_best_mv,
break; bool);
case ZEROMV: this->base.mv = this->split.mvs[15];
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); for (b = 0; b < 16; b++)
decode_split_mv(this, left, above, hdr, &clamped_best_mv, bool); {
this->base.mv = this->split.mvs[15]; 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;
for (b = 0; b < 16; b++) if (need_mc_border(this->split.mvs[b],
{ x + (b & 3) * 4, y + (b & ~3), 4, w, h))
chroma_mv[(b>>1&1) + (b>>2&2)].d.x += {
this->split.mvs[b].d.x; this->base.need_mc_border = 1;
chroma_mv[(b>>1&1) + (b>>2&2)].d.y += break;
this->split.mvs[b].d.y; }
}
if (need_mc_border(this->split.mvs[b], for (b = 0; b < 4; b++)
x + (b & 3) * 4, y + (b & ~3), 4, w, h)) {
{ chroma_mv[b].d.x += 4 + 8 * (chroma_mv[b].d.x >> 31);
this->base.need_mc_border = 1; chroma_mv[b].d.y += 4 + 8 * (chroma_mv[b].d.y >> 31);
break; chroma_mv[b].d.x /= 4;
} chroma_mv[b].d.y /= 4;
}
for (b = 0; b < 4; b++) //note we're passing in non-subsampled coordinates
{ if (need_mc_border(chroma_mv[b],
chroma_mv[b].d.x += 4 + 8 * (chroma_mv[b].d.x >> 31); x + (b & 1) * 8, y + (b >> 1) * 8, 16, w, h))
chroma_mv[b].d.y += 4 + 8 * (chroma_mv[b].d.y >> 31); {
chroma_mv[b].d.x /= 4; this->base.need_mc_border = 1;
chroma_mv[b].d.y /= 4; break;
}
}
//note we're passing in non-subsampled coordinates return; //skip need_mc_border check
if (need_mc_border(chroma_mv[b], }
x + (b & 1) * 8, y + (b >> 1) * 8, 16, w, h)) default:
{ assert(0);
this->base.need_mc_border = 1; }
break;
} if (need_mc_border(this->base.mv, x, y, 16, w, h))
} this->base.need_mc_border = 1;
}
return; //skip need_mc_border check void
} vp8_dixie_modemv_process_row(struct vp8_decoder_ctx *ctx,
default: struct bool_decoder *bool,
assert(0); int row,
} int start_col,
int num_cols)
{
struct mb_info *above, *this;
unsigned int col;
struct mv_clamp_rect bounds;
if (need_mc_border(this->base.mv, x, y, 16, w, h)) this = ctx->mb_info_rows[row] + start_col;
this->base.need_mc_border = 1; above = ctx->mb_info_rows[row - 1] + start_col;
}
void /* Calculate the eighth-pel MV bounds using a 1 MB border. */
vp8_dixie_modemv_process_row(struct vp8_decoder_ctx *ctx, bounds.to_left = -((start_col + 1) << 7);
struct bool_decoder *bool, bounds.to_right = (ctx->mb_cols - start_col) << 7;
int row, bounds.to_top = -((row + 1) << 7);
int start_col, bounds.to_bottom = (ctx->mb_rows - row) << 7;
int num_cols)
{
struct mb_info *above, *this;
unsigned int col;
struct mv_clamp_rect bounds;
this = ctx->mb_info_rows[row] + start_col; for (col = start_col; col < start_col + num_cols; col++)
above = ctx->mb_info_rows[row - 1] + start_col; {
if (ctx->segment_hdr.update_map)
this->base.segment_id = read_segment_id(bool,
&ctx->segment_hdr);
/* Calculate the eighth-pel MV bounds using a 1 MB border. */ if (ctx->entropy_hdr.coeff_skip_enabled)
bounds.to_left = -((start_col + 1) << 7); this->base.skip_coeff = bool_get(bool,
bounds.to_right = (ctx->mb_cols - start_col) << 7; ctx->entropy_hdr.coeff_skip_prob);
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->frame_hdr.is_keyframe)
{ {
if (ctx->segment_hdr.update_map) if (!ctx->segment_hdr.update_map)
this->base.segment_id = read_segment_id(bool, this->base.segment_id = 0;
&ctx->segment_hdr);
if (ctx->entropy_hdr.coeff_skip_enabled) decode_kf_mb_mode(this, this - 1, above, bool);
this->base.skip_coeff = bool_get(bool, }
ctx->entropy_hdr.coeff_skip_prob); 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);
if (ctx->frame_hdr.is_keyframe) bounds.to_left -= 16 << 3;
{ bounds.to_right -= 16 << 3;
if (!ctx->segment_hdr.update_map) }
this->base.segment_id = 0;
decode_kf_mb_mode(this, this - 1, above, bool); /* Advance to next mb */
} this++;
else above++;
{ }
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; void
bounds.to_right -= 16 << 3; vp8_dixie_modemv_init(struct vp8_decoder_ctx *ctx)
} {
unsigned int mbi_w, mbi_h, i;
struct mb_info *mbi;
/* Advance to next mb */ mbi_w = ctx->mb_cols + 1; /* For left border col */
this++; mbi_h = ctx->mb_rows + 1; /* For above border row */
above++;
}
}
void if (ctx->frame_hdr.frame_size_updated)
vp8_dixie_modemv_init(struct vp8_decoder_ctx *ctx) {
{ free(ctx->mb_info_storage);
unsigned int mbi_w, mbi_h, i; ctx->mb_info_storage = NULL;
struct mb_info *mbi; free(ctx->mb_info_rows_storage);
ctx->mb_info_rows_storage = NULL;
}
mbi_w = ctx->mb_cols + 1; /* For left border col */ if (!ctx->mb_info_storage)
mbi_h = ctx->mb_rows + 1; /* For above border row */ ctx->mb_info_storage = calloc(mbi_w * mbi_h,
sizeof(*ctx->mb_info_storage));
if (ctx->frame_hdr.frame_size_updated) if (!ctx->mb_info_rows_storage)
{ ctx->mb_info_rows_storage = calloc(mbi_h,
free(ctx->mb_info_storage); sizeof(*ctx->mb_info_rows_storage));
ctx->mb_info_storage = NULL;
free(ctx->mb_info_rows_storage);
ctx->mb_info_rows_storage = NULL;
}
if (!ctx->mb_info_storage) /* Set up row pointers */
ctx->mb_info_storage = calloc(mbi_w * mbi_h, mbi = ctx->mb_info_storage + 1;
sizeof(*ctx->mb_info_storage));
if (!ctx->mb_info_rows_storage) for (i = 0; i < mbi_h; i++)
ctx->mb_info_rows_storage = calloc(mbi_h, {
sizeof(*ctx->mb_info_rows_storage)); ctx->mb_info_rows_storage[i] = mbi;
mbi += mbi_w;
}
/* Set up row pointers */ ctx->mb_info_rows = ctx->mb_info_rows_storage + 1;
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;
}
void ---- End code block ----------------------------------------
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;
}
20.12. modemv.h 20.12. modemv.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
skipping to change at page 203, line 39 skipping to change at page 203, line 40
int row, int row,
int start_col, int start_col,
int num_cols); int num_cols);
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.13. modemv_data.h 20.13. modemv_data.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
static const unsigned char kf_y_mode_probs[] = { 145, 156, 163, 128}; 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_uv_mode_probs[] = { 142, 114, 183};
static const unsigned char kf_b_mode_probs[10][10][9] = static const unsigned char kf_b_mode_probs[10][10][9] =
{ {
{ /* above mode 0 */ { /* above mode 0 */
{ /* left mode 0 */ 231, 120, 48, 89, 115, 113, 120, 152, 112}, { /* 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 1 */ 152, 179, 64, 126, 170, 118, 46, 70, 95},
{ /* left mode 2 */ 175, 69, 143, 80, 85, 82, 72, 155, 103}, { /* 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 3 */ 56, 58, 10, 171, 218, 189, 17, 13, 152},
{ /* left mode 4 */ 144, 71, 10, 38, 171, 213, 144, 34, 26}, { /* 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 5 */ 114, 26, 17, 163, 44, 195, 21, 10, 173},
{ /* left mode 6 */ 121, 24, 80, 195, 26, 62, 44, 64, 85}, { /* 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 7 */ 170, 46, 55, 19, 136, 160, 33, 206, 71},
{ /* left mode 8 */ 63, 20, 8, 114, 114, 208, 12, 9, 226}, { /* left mode 8 */ 63, 20, 8, 114, 114, 208, 12, 9, 226},
{ /* left mode 9 */ 81, 40, 11, 96, 182, 84, 29, 16, 36} { /* left mode 9 */ 81, 40, 11, 96, 182, 84, 29, 16, 36}
}, },
{ /* above mode 1 */ { /* above mode 1 */
{ /* left mode 0 */ 134, 183, 89, 137, 98, 101, 106, 165, 148}, { /* 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 1 */ 72, 187, 100, 130, 157, 111, 32, 75, 80},
{ /* left mode 2 */ 66, 102, 167, 99, 74, 62, 40, 234, 128}, { /* 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 3 */ 41, 53, 9, 178, 241, 141, 26, 8, 107},
{ /* left mode 4 */ 104, 79, 12, 27, 217, 255, 87, 17, 7}, { /* 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 5 */ 74, 43, 26, 146, 73, 166, 49, 23, 157},
{ /* left mode 6 */ 65, 38, 105, 160, 51, 52, 31, 115, 128}, { /* 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 7 */ 87, 68, 71, 44, 114, 51, 15, 186, 23},
{ /* left mode 8 */ 47, 41, 14, 110, 182, 183, 21, 17, 194}, { /* left mode 8 */ 47, 41, 14, 110, 182, 183, 21, 17, 194},
{ /* left mode 9 */ 66, 45, 25, 102, 197, 189, 23, 18, 22} { /* left mode 9 */ 66, 45, 25, 102, 197, 189, 23, 18, 22}
}, },
{ /* above mode 2 */ { /* above mode 2 */
{ /* left mode 0 */ 88, 88, 147, 150, 42, 46, 45, 196, 205}, { /* 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 1 */ 43, 97, 183, 117, 85, 38, 35, 179, 61},
{ /* left mode 2 */ 39, 53, 200, 87, 26, 21, 43, 232, 171}, { /* 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 3 */ 56, 34, 51, 104, 114, 102, 29, 93, 77},
{ /* left mode 4 */ 107, 54, 32, 26, 51, 1, 81, 43, 31}, { /* 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 5 */ 39, 28, 85, 171, 58, 165, 90, 98, 64},
{ /* left mode 6 */ 34, 22, 116, 206, 23, 34, 43, 166, 73}, { /* 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 7 */ 68, 25, 106, 22, 64, 171, 36, 225, 114},
{ /* left mode 8 */ 34, 19, 21, 102, 132, 188, 16, 76, 124}, { /* left mode 8 */ 34, 19, 21, 102, 132, 188, 16, 76, 124},
{ /* left mode 9 */ 62, 18, 78, 95, 85, 57, 50, 48, 51} { /* left mode 9 */ 62, 18, 78, 95, 85, 57, 50, 48, 51}
}, },
{ /* above mode 3 */ { /* above mode 3 */
{ /* left mode 0 */ 193, 101, 35, 159, 215, 111, 89, 46, 111}, { /* 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 1 */ 60, 148, 31, 172, 219, 228, 21, 18, 111},
{ /* left mode 2 */ 112, 113, 77, 85, 179, 255, 38, 120, 114}, { /* 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 3 */ 40, 42, 1, 196, 245, 209, 10, 25, 109},
{ /* left mode 4 */ 100, 80, 8, 43, 154, 1, 51, 26, 71}, { /* 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 5 */ 88, 43, 29, 140, 166, 213, 37, 43, 154},
{ /* left mode 6 */ 61, 63, 30, 155, 67, 45, 68, 1, 209}, { /* 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 7 */ 142, 78, 78, 16, 255, 128, 34, 197, 171},
{ /* left mode 8 */ 41, 40, 5, 102, 211, 183, 4, 1, 221}, { /* left mode 8 */ 41, 40, 5, 102, 211, 183, 4, 1, 221},
{ /* left mode 9 */ 51, 50, 17, 168, 209, 192, 23, 25, 82} { /* left mode 9 */ 51, 50, 17, 168, 209, 192, 23, 25, 82}
}, },
{ /* above mode 4 */ { /* above mode 4 */
{ /* left mode 0 */ 125, 98, 42, 88, 104, 85, 117, 175, 82}, { /* 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 1 */ 95, 84, 53, 89, 128, 100, 113, 101, 45},
{ /* left mode 2 */ 75, 79, 123, 47, 51, 128, 81, 171, 1}, { /* 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 3 */ 57, 17, 5, 71, 102, 57, 53, 41, 49},
{ /* left mode 4 */ 115, 21, 2, 10, 102, 255, 166, 23, 6}, { /* 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 5 */ 38, 33, 13, 121, 57, 73, 26, 1, 85},
{ /* left mode 6 */ 41, 10, 67, 138, 77, 110, 90, 47, 114}, { /* 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 7 */ 101, 29, 16, 10, 85, 128, 101, 196, 26},
{ /* left mode 8 */ 57, 18, 10, 102, 102, 213, 34, 20, 43}, { /* left mode 8 */ 57, 18, 10, 102, 102, 213, 34, 20, 43},
{ /* left mode 9 */ 117, 20, 15, 36, 163, 128, 68, 1, 26} { /* left mode 9 */ 117, 20, 15, 36, 163, 128, 68, 1, 26}
}, },
{ /* above mode 5 */ { /* above mode 5 */
{ /* left mode 0 */ 138, 31, 36, 171, 27, 166, 38, 44, 229}, { /* 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 1 */ 67, 87, 58, 169, 82, 115, 26, 59, 179},
{ /* left mode 2 */ 63, 59, 90, 180, 59, 166, 93, 73, 154}, { /* 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 3 */ 40, 40, 21, 116, 143, 209, 34, 39, 175},
{ /* left mode 4 */ 57, 46, 22, 24, 128, 1, 54, 17, 37}, { /* 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 5 */ 47, 15, 16, 183, 34, 223, 49, 45, 183},
{ /* left mode 6 */ 46, 17, 33, 183, 6, 98, 15, 32, 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 7 */ 65, 32, 73, 115, 28, 128, 23, 128, 205},
{ /* left mode 8 */ 40, 3, 9, 115, 51, 192, 18, 6, 223}, { /* left mode 8 */ 40, 3, 9, 115, 51, 192, 18, 6, 223},
{ /* left mode 9 */ 87, 37, 9, 115, 59, 77, 64, 21, 47} { /* left mode 9 */ 87, 37, 9, 115, 59, 77, 64, 21, 47}
}, },
{ /* above mode 6 */ { /* above mode 6 */
{ /* left mode 0 */ 104, 55, 44, 218, 9, 54, 53, 130, 226}, { /* 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 1 */ 64, 90, 70, 205, 40, 41, 23, 26, 57},
{ /* left mode 2 */ 54, 57, 112, 184, 5, 41, 38, 166, 213}, { /* 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 3 */ 30, 34, 26, 133, 152, 116, 10, 32, 134},
{ /* left mode 4 */ 75, 32, 12, 51, 192, 255, 160, 43, 51}, { /* 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 5 */ 39, 19, 53, 221, 26, 114, 32, 73, 255},
{ /* left mode 6 */ 31, 9, 65, 234, 2, 15, 1, 118, 73}, { /* 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 7 */ 88, 31, 35, 67, 102, 85, 55, 186, 85},
{ /* left mode 8 */ 56, 21, 23, 111, 59, 205, 45, 37, 192}, { /* left mode 8 */ 56, 21, 23, 111, 59, 205, 45, 37, 192},
{ /* left mode 9 */ 55, 38, 70, 124, 73, 102, 1, 34, 98} { /* left mode 9 */ 55, 38, 70, 124, 73, 102, 1, 34, 98}
}, },
{ /* above mode 7 */ { /* above mode 7 */
{ /* left mode 0 */ 102, 61, 71, 37, 34, 53, 31, 243, 192}, { /* 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 1 */ 69, 60, 71, 38, 73, 119, 28, 222, 37},
{ /* left mode 2 */ 68, 45, 128, 34, 1, 47, 11, 245, 171}, { /* 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 3 */ 62, 17, 19, 70, 146, 85, 55, 62, 70},
{ /* left mode 4 */ 75, 15, 9, 9, 64, 255, 184, 119, 16}, { /* 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 5 */ 37, 43, 37, 154, 100, 163, 85, 160, 1},
{ /* left mode 6 */ 63, 9, 92, 136, 28, 64, 32, 201, 85}, { /* 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 7 */ 86, 6, 28, 5, 64, 255, 25, 248, 1},
{ /* left mode 8 */ 56, 8, 17, 132, 137, 255, 55, 116, 128}, { /* left mode 8 */ 56, 8, 17, 132, 137, 255, 55, 116, 128},
{ /* left mode 9 */ 58, 15, 20, 82, 135, 57, 26, 121, 40} { /* left mode 9 */ 58, 15, 20, 82, 135, 57, 26, 121, 40}
}, },
{ /* above mode 8 */ { /* above mode 8 */
{ /* left mode 0 */ 164, 50, 31, 137, 154, 133, 25, 35, 218}, { /* 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 1 */ 51, 103, 44, 131, 131, 123, 31, 6, 158},
{ /* left mode 2 */ 86, 40, 64, 135, 148, 224, 45, 183, 128}, { /* 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 3 */ 22, 26, 17, 131, 240, 154, 14, 1, 209},
{ /* left mode 4 */ 83, 12, 13, 54, 192, 255, 68, 47, 28}, { /* 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 5 */ 45, 16, 21, 91, 64, 222, 7, 1, 197},
{ /* left mode 6 */ 56, 21, 39, 155, 60, 138, 23, 102, 213}, { /* 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 7 */ 85, 26, 85, 85, 128, 128, 32, 146, 171},
{ /* left mode 8 */ 18, 11, 7, 63, 144, 171, 4, 4, 246}, { /* left mode 8 */ 18, 11, 7, 63, 144, 171, 4, 4, 246},
{ /* left mode 9 */ 35, 27, 10, 146, 174, 171, 12, 26, 128} { /* left mode 9 */ 35, 27, 10, 146, 174, 171, 12, 26, 128}
}, },
{ /* above mode 9 */ { /* above mode 9 */
{ /* left mode 0 */ 190, 80, 35, 99, 180, 80, 126, 54, 45}, { /* 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 1 */ 85, 126, 47, 87, 176, 51, 41, 20, 32},
{ /* left mode 2 */ 101, 75, 128, 139, 118, 146, 116, 128, 85}, { /* 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 3 */ 56, 41, 15, 176, 236, 85, 37, 9, 62},
{ /* left mode 4 */ 146, 36, 19, 30, 171, 255, 97, 27, 20}, { /* 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 5 */ 71, 30, 17, 119, 118, 255, 17, 18, 138},
{ /* left mode 6 */ 101, 38, 60, 138, 55, 70, 43, 26, 142}, { /* 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 7 */ 138, 45, 61, 62, 219, 1, 81, 188, 64},
{ /* left mode 8 */ 32, 41, 20, 117, 151, 142, 20, 21, 163}, { /* left mode 8 */ 32, 41, 20, 117, 151, 142, 20, 21, 163},
{ /* left mode 9 */ 112, 19, 12, 61, 195, 128, 48, 4, 24} { /* left mode 9 */ 112, 19, 12, 61, 195, 128, 48, 4, 24}
} }
}; };
static const int kf_y_mode_tree[] = static const int kf_y_mode_tree[] =
{ {
-B_PRED, 2, -B_PRED, 2,
4, 6, 4, 6,
-DC_PRED, -V_PRED, -DC_PRED, -V_PRED,
-H_PRED, -TM_PRED -H_PRED, -TM_PRED
}; };
static const int y_mode_tree[] = static const int y_mode_tree[] =
{ {
-DC_PRED, 2, -DC_PRED, 2,
4, 6, 4, 6,
-V_PRED, -H_PRED, -V_PRED, -H_PRED,
-TM_PRED, -B_PRED -TM_PRED, -B_PRED
}; };
static const int uv_mode_tree[6] = static const int uv_mode_tree[6] =
{ {
-DC_PRED, 2, -DC_PRED, 2,
-V_PRED, 4, -V_PRED, 4,
-H_PRED, -TM_PRED -H_PRED, -TM_PRED
}; };
static const int b_mode_tree[18] = static const int b_mode_tree[18] =
{ {
-B_DC_PRED, 2, /* 0 = DC_NODE */ -B_DC_PRED, 2, /* 0 = DC_NODE */
-B_TM_PRED, 4, /* 1 = TM_NODE */ -B_TM_PRED, 4, /* 1 = TM_NODE */
-B_VE_PRED, 6, /* 2 = VE_NODE */ -B_VE_PRED, 6, /* 2 = VE_NODE */
8, 12, /* 3 = COM_NODE */ 8, 12, /* 3 = COM_NODE */
-B_HE_PRED, 10, /* 4 = HE_NODE */ -B_HE_PRED, 10, /* 4 = HE_NODE */
-B_RD_PRED, -B_VR_PRED, /* 5 = RD_NODE */ -B_RD_PRED, -B_VR_PRED, /* 5 = RD_NODE */
-B_LD_PRED, 14, /* 6 = LD_NODE */ -B_LD_PRED, 14, /* 6 = LD_NODE */
-B_VL_PRED, 16, /* 7 = VL_NODE */ -B_VL_PRED, 16, /* 7 = VL_NODE */
-B_HD_PRED, -B_HU_PRED /* 8 = HD_NODE */ -B_HD_PRED, -B_HU_PRED /* 8 = HD_NODE */
}; };
static const int small_mv_tree[14] = static const int small_mv_tree[14] =
{ {
2, 8, 2, 8,
4, 6, 4, 6,
-0, -1, -0, -1,
-2, -3, -2, -3,
10, 12, 10, 12,
-4, -5, -4, -5,
-6, -7 -6, -7
}; };
static const int mv_ref_tree[8] = static const int mv_ref_tree[8] =
{ {
-ZEROMV, 2, -ZEROMV, 2,
-NEARESTMV, 4, -NEARESTMV, 4,
-NEARMV, 6, -NEARMV, 6,
-NEWMV, -SPLITMV -NEWMV, -SPLITMV
}; };
static const int submv_ref_tree[6] = static const int submv_ref_tree[6] =
{ {
-LEFT4X4, 2, -LEFT4X4, 2,
-ABOVE4X4, 4, -ABOVE4X4, 4,
-ZERO4X4, -NEW4X4 -ZERO4X4, -NEW4X4
}; };
static const int split_mv_tree[6] = static const int split_mv_tree[6] =
{ {
-3, 2, -3, 2,
-2, 4, -2, 4,
-0, -1 -0, -1
}; };
static const unsigned char default_b_mode_probs[] = static const unsigned char default_b_mode_probs[] =
{ 120, 90, 79, 133, 87, 85, 80, 111, 151}; { 120, 90, 79, 133, 87, 85, 80, 111, 151};
static const unsigned char mv_counts_to_probs[6][4] = static const unsigned char mv_counts_to_probs[6][4] =
{ {
{ 7, 1, 1, 143 }, { 7, 1, 1, 143 },
{ 14, 18, 14, 107 }, { 14, 18, 14, 107 },
{ 135, 64, 57, 68 }, { 135, 64, 57, 68 },
{ 60, 56, 128, 65 }, { 60, 56, 128, 65 },
{ 159, 134, 128, 34 }, { 159, 134, 128, 34 },
{ 234, 188, 128, 28 } { 234, 188, 128, 28 }
}; };
static const unsigned char split_mv_probs[3] = static const unsigned char split_mv_probs[3] =
{ 110, 111, 150}; { 110, 111, 150};
static const unsigned char submv_ref_probs2[5][3] = static const unsigned char submv_ref_probs2[5][3] =
{ {
{ 147, 136, 18 }, { 147, 136, 18 },
{ 106, 145, 1 }, { 106, 145, 1 },
{ 179, 121, 1 }, { 179, 121, 1 },
{ 223, 1, 34 }, { 223, 1, 34 },
{ 208, 1, 1 } { 208, 1, 1 }
}; };
const static int mv_partitions[4][16] = 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, 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, 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, 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 } {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
}; };
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.14. predict.c 20.14. predict.c
---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may * found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "dixie.h" #include "dixie.h"
#include "predict.h" #include "predict.h"
#include "idct_add.h" #include "idct_add.h"
#include "mem.h" #include "mem.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
enum enum
{ {
BORDER_PIXELS = 16, BORDER_PIXELS = 16,
}; };
static const filter_t sixtap_filters[8] = static const filter_t sixtap_filters[8] =
{ {
{ 0, 0, 128, 0, 0, 0 }, { 0, 0, 128, 0, 0, 0 },
{ 0, -6, 123, 12, -1, 0 }, { 0, -6, 123, 12, -1, 0 },
{ 2, -11, 108, 36, -8, 1 }, { 2, -11, 108, 36, -8, 1 },
{ 0, -9, 93, 50, -6, 0 }, { 0, -9, 93, 50, -6, 0 },
{ 3, -16, 77, 77, -16, 3 }, { 3, -16, 77, 77, -16, 3 },
{ 0, -6, 50, 93, -9, 0 }, { 0, -6, 50, 93, -9, 0 },
{ 1, -8, 36, 108, -11, 2 }, { 1, -8, 36, 108, -11, 2 },
{ 0, -1, 12, 123, -6, 0 }, { 0, -1, 12, 123, -6, 0 },
}; };
static const filter_t bilinear_filters[8] = static const filter_t bilinear_filters[8] =
{ {
{ 0, 0, 128, 0, 0, 0 }, { 0, 0, 128, 0, 0, 0 },
{ 0, 0, 112, 16, 0, 0 }, { 0, 0, 112, 16, 0, 0 },
{ 0, 0, 96, 32, 0, 0 }, { 0, 0, 96, 32, 0, 0 },
{ 0, 0, 80, 48, 0, 0 }, { 0, 0, 80, 48, 0, 0 },
{ 0, 0, 64, 64, 0, 0 }, { 0, 0, 64, 64, 0, 0 },
{ 0, 0, 48, 80, 0, 0 }, { 0, 0, 48, 80, 0, 0 },
{ 0, 0, 32, 96, 0, 0 }, { 0, 0, 32, 96, 0, 0 },
{ 0, 0, 16, 112, 0, 0 } { 0, 0, 16, 112, 0, 0 }
}; };
static void static void
predict_h_nxn(unsigned char *predict, predict_h_nxn(unsigned char *predict,
int stride, int stride,
int n) int n)
{ {
unsigned char *left = predict - 1; unsigned char *left = predict - 1;
int i, j; int i, j;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
predict[i *stride + j] = left[i * stride]; predict[i *stride + j] = left[i * stride];
} }
static void static void
predict_v_nxn(unsigned char *predict, predict_v_nxn(unsigned char *predict,
int stride, int stride,
int n) int n)
{ {
unsigned char *above = predict - stride; unsigned char *above = predict - stride;
int i, j; int i, j;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
predict[i *stride + j] = above[j]; predict[i *stride + j] = above[j];
} }
static void static void
predict_tm_nxn(unsigned char *predict, predict_tm_nxn(unsigned char *predict,
int stride, int stride,
int n) int n)
{ {
/* Transposes the left column to the top row for later consumption /* Transposes the left column to the top row for later
* by the idct/recon stage * consumption by the idct/recon stage
*/ */
unsigned char *left = predict - 1; unsigned char *left = predict - 1;
unsigned char *above = predict - stride; unsigned char *above = predict - stride;
unsigned char p = above[-1]; unsigned char p = above[-1];
int i, j; int i, j;
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
{ {
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
predict[i] = CLAMP_255(*left + above[i] - p); predict[i] = CLAMP_255(*left + above[i] - p);
predict += stride; predict += stride;
left += stride; left += stride;
} }
} }
static void static void
predict_dc_nxn(unsigned char *predict, predict_dc_nxn(unsigned char *predict,
int stride, int stride,
int n) int n)
{ {
unsigned char *left = predict - 1; unsigned char *left = predict - 1;
unsigned char *above = predict - stride; unsigned char *above = predict - stride;
int i, j, dc = 0; int i, j, dc = 0;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
dc += *left + above[i]; dc += *left + above[i];
left += stride; left += stride;
} }
switch (n) switch (n)
{ {
case 16: case 16:
dc = (dc + 16) >> 5; dc = (dc + 16) >> 5;
break; break;
case 8: case 8:
dc = (dc + 8) >> 4; dc = (dc + 8) >> 4;
break; break;
case 4: case 4:
dc = (dc + 4) >> 3; dc = (dc + 4) >> 3;
break; break;
} }
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
for (j = 0; j < n; j++) for (j = 0; j < n; j++)
predict[i *stride + j] = dc; predict[i *stride + j] = dc;
} }
static void static void
predict_ve_4x4(unsigned char *predict, predict_ve_4x4(unsigned char *predict,
int stride) int stride)
{ {
unsigned char *above = predict - stride; unsigned char *above = predict - stride;
int i, j; int i, j;
predict[0] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2; predict[0] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
predict[1] = (above[ 0] + 2 * above[1] + above[2] + 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[2] = (above[ 1] + 2 * above[2] + above[3] + 2) >> 2;
predict[3] = (above[ 2] + 2 * above[3] + above[4] + 2) >> 2; predict[3] = (above[ 2] + 2 * above[3] + above[4] + 2) >> 2;
for (i = 1; i < 4; i++) for (i = 1; i < 4; i++)
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
predict[i *stride + j] = predict[j]; predict[i *stride + j] = predict[j];
} }
static void static void
predict_he_4x4(unsigned char *predict, predict_he_4x4(unsigned char *predict,
int stride) int stride)
{ {
unsigned char *left = predict - 1; unsigned char *left = predict - 1;
predict[0] = predict[0] =
predict[1] = predict[1] =
predict[2] = predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2; predict[3] = (left[-stride] + 2 * left[0] +
predict += stride; left[stride] + 2) >> 2;
left += stride; predict += stride;
left += stride;
predict[0] = predict[0] =
predict[1] = predict[1] =
predict[2] = predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2; predict[3] = (left[-stride] + 2 * left[0] +
predict += stride; left[stride] + 2) >> 2;
left += stride; predict += stride;
left += stride;
predict[0] = predict[0] =
predict[1] = predict[1] =
predict[2] = predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[stride] + 2) >> 2; predict[3] = (left[-stride] + 2 * left[0] +
predict += stride; left[stride] + 2) >> 2;
left += stride; predict += stride;
left += stride;
predict[0] = predict[0] =
predict[1] = predict[1] =
predict[2] = predict[2] =
predict[3] = (left[-stride] + 2 * left[0] + left[0] + 2) >> 2; predict[3] = (left[-stride] + 2 * left[0] + left[0] + 2) >> 2;
} }
static void static void
predict_ld_4x4(unsigned char *predict, predict_ld_4x4(unsigned char *predict,
int stride) int stride)
{ {
unsigned char *above = predict - stride; unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6; int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
predict[0] = pred0 = (above[0] + 2 * above[1] + above[2] + 2) >> 2; predict[0] = pred0 = (above[0] + 2 * above[1] +
predict[1] = pred1 = (above[1] + 2 * above[2] + above[3] + 2) >> 2; above[2] + 2) >> 2;
predict[2] = pred2 = (above[2] + 2 * above[3] + above[4] + 2) >> 2; predict[1] = pred1 = (above[1] + 2 * above[2] +
predict[3] = pred3 = (above[3] + 2 * above[4] + above[5] + 2) >> 2; above[3] + 2) >> 2;
predict += stride; 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[0] = pred1;
predict[1] = pred2; predict[1] = pred2;
predict[2] = pred3; predict[2] = pred3;
predict[3] = pred4 = (above[4] + 2 * above[5] + above[6] + 2) >> 2; predict[3] = pred4 = (above[4] + 2 * above[5] +
predict += stride; above[6] + 2) >> 2;
predict += stride;
predict[0] = pred2; predict[0] = pred2;
predict[1] = pred3; predict[1] = pred3;
predict[2] = pred4; predict[2] = pred4;
predict[3] = pred5 = (above[5] + 2 * above[6] + above[7] + 2) >> 2; predict[3] = pred5 = (above[5] + 2 * above[6] +
predict += stride; above[7] + 2) >> 2;
predict += stride;
predict[0] = pred3; predict[0] = pred3;
predict[1] = pred4; predict[1] = pred4;
predict[2] = pred5; predict[2] = pred5;
predict[3] = pred6 = (above[6] + 2 * above[7] + above[7] + 2) >> 2; 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 = static void
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2; predict_rd_4x4(unsigned char *predict,
predict[1] = pred1 = int stride)
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2; {
predict[2] = pred2 = unsigned char *left = predict - 1;
(above[ 0] + 2 * above[ 1] + above[2] + 2) >> 2; unsigned char *above = predict - stride;
predict[3] = pred3 = int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
(above[ 1] + 2 * above[ 2] + above[3] + 2) >> 2;
predict += stride;
predict[0] = pred4 = predict[0] = pred0 =
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2; (left[ 0] + 2 * above[-1] + above[0] + 2) >> 2;
predict[1] = pred0; predict[1] = pred1 =
predict[2] = pred1; (above[-1] + 2 * above[ 0] + above[1] + 2) >> 2;
predict[3] = pred2; predict[2] = pred2 =
predict += stride; (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] = pred5 = predict[0] = pred4 =
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2; (left[stride] + 2 * left[0] + above[-1] + 2) >> 2;
predict[1] = pred4; predict[1] = pred0;
predict[2] = pred0; predict[2] = pred1;
predict[3] = pred1; predict[3] = pred2;
predict += stride; predict += stride;
predict[0] = pred6 = predict[0] = pred5 =
(left[stride*3] + 2 * left[stride*2] + left[stride] + 2) >> 2; (left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2;
predict[1] = pred5; predict[1] = pred4;
predict[2] = pred4; predict[2] = pred0;
predict[3] = pred0; predict[3] = pred1;
} predict += stride;
static void predict[0] = pred6 = (left[stride*3] + 2 * left[stride*2] +
predict_vr_4x4(unsigned char *predict, left[stride] + 2) >> 2;
int stride) predict[1] = pred5;
{ predict[2] = pred4;
unsigned char *left = predict - 1; predict[3] = pred0;
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; static void
predict[1] = pred1 = (above[ 0] + above[1] + 1) >> 1; predict_vr_4x4(unsigned char *predict,
predict[2] = pred2 = (above[ 1] + above[2] + 1) >> 1; int stride)
predict[3] = pred3 = (above[ 2] + above[3] + 1) >> 1; {
predict += stride; unsigned char *left = predict - 1;
unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred4 = predict[0] = pred0 = (above[-1] + above[0] + 1) >> 1;
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2; predict[1] = pred1 = (above[ 0] + above[1] + 1) >> 1;
predict[1] = pred5 = predict[2] = pred2 = (above[ 1] + above[2] + 1) >> 1;
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2; predict[3] = pred3 = (above[ 2] + above[3] + 1) >> 1;
predict[2] = pred6 = predict += stride;
(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 = predict[0] = pred4 = (left[ 0] + 2 * above[-1] +
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2; above[0] + 2) >> 2;
predict[1] = pred0; predict[1] = pred5 = (above[-1] + 2 * above[ 0] +
predict[2] = pred1; above[1] + 2) >> 2;
predict[3] = pred2; predict[2] = pred6 = (above[ 0] + 2 * above[ 1] +
predict += stride; above[2] + 2) >> 2;
predict[3] = pred7 = (above[ 1] + 2 * above[ 2] +
above[3] + 2) >> 2;
predict += stride;
predict[0] = pred9 = predict[0] = pred8 =
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2; (left[stride] + 2 * left[0] + above[-1] + 2) >> 2;
predict[1] = pred4; predict[1] = pred0;
predict[2] = pred5; predict[2] = pred1;
predict[3] = pred6; predict[3] = pred2;
} predict += stride;
static void predict[0] = pred9 =
predict_vl_4x4(unsigned char *predict, (left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2;
int stride) predict[1] = pred4;
{ predict[2] = pred5;
unsigned char *above = predict - stride; predict[3] = pred6;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6, }
pred7, pred8, pred9;
predict[0] = pred0 = (above[0] + above[1] + 1) >> 1; static void
predict[1] = pred1 = (above[1] + above[2] + 1) >> 1; predict_vl_4x4(unsigned char *predict,
predict[2] = pred2 = (above[2] + above[3] + 1) >> 1; int stride)
predict[3] = pred3 = (above[3] + above[4] + 1) >> 1; {
predict += stride; unsigned char *above = predict - stride;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred4 = predict[0] = pred0 = (above[0] + above[1] + 1) >> 1;
(above[0] + 2 * above[1] + above[2] + 2) >> 2; predict[1] = pred1 = (above[1] + above[2] + 1) >> 1;
predict[1] = pred5 = predict[2] = pred2 = (above[2] + above[3] + 1) >> 1;
(above[1] + 2 * above[2] + above[3] + 2) >> 2; predict[3] = pred3 = (above[3] + above[4] + 1) >> 1;
predict[2] = pred6 = predict += stride;
(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[0] = pred4 = (above[0] + 2 * above[1] +
predict[1] = pred2; above[2] + 2) >> 2;
predict[2] = pred3; predict[1] = pred5 = (above[1] + 2 * above[2] +
predict[3] = pred8 = (above[4] + 2 * above[5] + above[6] + 2) >> 2; above[3] + 2) >> 2;
predict += stride; 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] = pred5; predict[0] = pred1;
predict[1] = pred6; predict[1] = pred2;
predict[2] = pred7; predict[2] = pred3;
predict[3] = pred9 = (above[5] + 2 * above[6] + above[7] + 2) >> 2; predict[3] = pred8 = (above[4] + 2 * above[5] +
} above[6] + 2) >> 2;
predict += stride;
static void predict[0] = pred5;
predict_hd_4x4(unsigned char *predict, predict[1] = pred6;
int stride) predict[2] = pred7;
{ predict[3] = pred9 = (above[5] + 2 * above[6] +
unsigned char *left = predict - 1; above[7] + 2) >> 2;
unsigned char *above = predict - stride; }
int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
pred7, pred8, pred9;
predict[0] = pred0 = static void
(left[ 0] + above[-1] + 1) >> 1; predict_hd_4x4(unsigned char *predict,
predict[1] = pred1 = int stride)
(left[ 0] + 2 * above[-1] + above[0] + 2) >> 2; {
predict[2] = pred2 = unsigned char *left = predict - 1;
(above[-1] + 2 * above[ 0] + above[1] + 2) >> 2; unsigned char *above = predict - stride;
predict[3] = pred3 = int pred0, pred1, pred2, pred3, pred4, pred5, pred6,
(above[ 0] + 2 * above[ 1] + above[2] + 2) >> 2; pred7, pred8, pred9;
predict += stride;
predict[0] = pred4 = predict[0] = pred0 = (left[ 0] + above[-1] + 1) >> 1;
(left[stride] + left[0] + 1) >> 1; predict[1] = pred1 = (left[ 0] + 2 * above[-1] +
predict[1] = pred5 = above[0] + 2) >> 2;
(left[stride] + 2 * left[0] + above[-1] + 2) >> 2; predict[2] = pred2 = (above[-1] + 2 * above[ 0] +
predict[2] = pred0; above[1] + 2) >> 2;
predict[3] = pred1; predict[3] = pred3 = (above[ 0] + 2 * above[ 1] +
predict += stride; above[2] + 2) >> 2;
predict += stride;
predict[0] = pred6 = predict[0] = pred4 = (left[stride] + left[0] + 1) >> 1;
(left[stride*2] + left[stride] + 1) >> 1; predict[1] = pred5 = (left[stride] + 2 * left[0] +
predict[1] = pred7 = above[-1] + 2) >> 2;
(left[stride*2] + 2 * left[stride] + left[0] + 2) >> 2; predict[2] = pred0;
predict[2] = pred4; predict[3] = pred1;
predict[3] = pred5; predict += stride;
predict += stride;
predict[0] = pred8 = predict[0] = pred6 = (left[stride*2] + left[stride] + 1) >> 1;
(left[stride*3] + left[stride*2] + 1) >> 1; predict[1] = pred7 = (left[stride*2] + 2 * left[stride] +
predict[1] = pred9 = left[0] + 2) >> 2;
(left[stride*3] + 2 * left[stride*2] + left[stride] + 2) >> 2; predict[2] = pred4;
predict[2] = pred6; predict[3] = pred5;
predict[3] = pred7; predict += stride;
}
static void predict[0] = pred8 = (left[stride*3] + left[stride*2] + 1) >> 1;
predict_hu_4x4(unsigned char *predict, predict[1] = pred9 = (left[stride*3] + 2 * left[stride*2] +
int stride) left[stride] + 2) >> 2;
{ predict[2] = pred6;
unsigned char *left = predict - 1; predict[3] = pred7;
int pred0, pred1, pred2, pred3, pred4, pred5, pred6; }
predict[0] = pred0 = static void
(left[stride*0] + left[stride*1] + 1) >> 1; predict_hu_4x4(unsigned char *predict,
predict[1] = pred1 = int stride)
(left[stride*0] + 2 * left[stride*1] + left[stride*2] + 2) >> 2; {
predict[2] = pred2 = unsigned char *left = predict - 1;
(left[stride*1] + left[stride*2] + 1) >> 1; int pred0, pred1, pred2, pred3, pred4, pred5, pred6;
predict[3] = pred3 =
(left[stride*1] + 2 * left[stride*2] + left[stride*3] + 2) >> 2;
predict += stride;
predict[0] = pred2; predict[0] = pred0 = (left[stride*0] +
predict[1] = pred3; left[stride*1] + 1) >> 1;
predict[2] = pred4 = predict[1] = pred1 = (left[stride*0] + 2 * left[stride*1] +
(left[stride*2] + left[stride*3] + 1) >> 1; left[stride*2] + 2) >> 2;
predict[3] = pred5 = predict[2] = pred2 = (left[stride*1] + left[stride*2] + 1) >> 1;
(left[stride*2] + 2 * left[stride*3] + left[stride*3] + 2) >> 2; predict[3] = pred3 = (left[stride*1] + 2 * left[stride*2] +
predict += stride; left[stride*3] + 2) >> 2;
predict += stride;
predict[0] = pred4; predict[0] = pred2;
predict[1] = pred5; predict[1] = pred3;
predict[2] = pred6 = left[stride*3]; predict[2] = pred4 = (left[stride*2] + left[stride*3] + 1) >> 1;
predict[3] = pred6; predict[3] = pred5 = (left[stride*2] + 2 * left[stride*3] +
predict += stride; left[stride*3] + 2) >> 2;
predict[0] = pred6; predict += stride;
predict[1] = pred6;
predict[2] = pred6;
predict[3] = pred6;
}
static void predict[0] = pred4;
predict_h_16x16(unsigned char *predict, int stride) predict[1] = pred5;
{ predict[2] = pred6 = left[stride*3];
predict_h_nxn(predict, stride, 16); predict[3] = pred6;
} predict += stride;
static void predict[0] = pred6;
predict_v_16x16(unsigned char *predict, int stride) predict[1] = pred6;
{ predict[2] = pred6;
predict_v_nxn(predict, stride, 16); predict[3] = pred6;
} }
static void static void
predict_tm_16x16(unsigned char *predict, int stride) predict_h_16x16(unsigned char *predict, int stride)
{ {
predict_tm_nxn(predict, stride, 16); predict_h_nxn(predict, stride, 16);
} }
static void static void
predict_h_8x8(unsigned char *predict, int stride) predict_v_16x16(unsigned char *predict, int stride)
{ {
predict_h_nxn(predict, stride, 8); predict_v_nxn(predict, stride, 16);
} }
static void static void
predict_v_8x8(unsigned char *predict, int stride) predict_tm_16x16(unsigned char *predict, int stride)
{ {
predict_v_nxn(predict, stride, 8); predict_tm_nxn(predict, stride, 16);
} }
static void static void
predict_tm_8x8(unsigned char *predict, int stride) predict_h_8x8(unsigned char *predict, int stride)
{ {
predict_tm_nxn(predict, stride, 8); predict_h_nxn(predict, stride, 8);
} }
static void
predict_tm_4x4(unsigned char *predict, int stride)
{
predict_tm_nxn(predict, stride, 4);
}
static void static void
copy_down(unsigned char *recon, predict_v_8x8(unsigned char *predict, int stride)
int stride) {
{ predict_v_nxn(predict, stride, 8);
/* Copy the four pixels above-right of subblock 3 to }
* above-right of subblocks 7, 11, and 15 static void
*/ predict_tm_8x8(unsigned char *predict, int stride)
uint32_t tmp, *copy = (void *)(recon + 16 - stride); {
predict_tm_nxn(predict, stride, 8);
}
stride = stride / sizeof(unsigned int); static void
tmp = *copy; predict_tm_4x4(unsigned char *predict, int stride)
copy += stride * 4; {
*copy = tmp; predict_tm_nxn(predict, stride, 4);
copy += stride * 4; }
*copy = tmp;
copy += stride * 4;
*copy = tmp;
}
static void static void
b_pred(unsigned char *predict, copy_down(unsigned char *recon,
int stride, int stride)
struct mb_info *mbi, {
short *coeffs) /* Copy the four pixels above-right of subblock 3 to
{ * above-right of subblocks 7, 11, and 15
int i; */
uint32_t tmp, *copy = (void *)(recon + 16 - stride);
copy_down(predict, stride); stride = stride / sizeof(unsigned int);
tmp = *copy;
copy += stride * 4;
*copy = tmp;
copy += stride * 4;
*copy = tmp;
copy += stride * 4;
*copy = tmp;
}
for (i = 0; i < 16; i++) static void
{ b_pred(unsigned char *predict,
unsigned char *b_predict = predict + (i & 3) * 4; int stride,
struct mb_info *mbi,
short *coeffs)
{
int i;
switch (mbi->split.modes[i]) copy_down(predict, stride);
{
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); for (i = 0; i < 16; i++)
coeffs += 16; {
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);
}
if ((i & 3) == 3) vp8_dixie_idct_add(b_predict, b_predict, stride, coeffs);
{ coeffs += 16;
predict += stride * 4;
}
}
}
static void if ((i & 3) == 3)
fixup_dc_coeffs(struct mb_info *mbi, {
short *coeffs) predict += stride * 4;
{ }
short y2[16]; }
int i; }
vp8_dixie_walsh(coeffs + 24 * 16, y2); static void
for (i = 0; i < 16; i++) fixup_dc_coeffs(struct mb_info *mbi,
coeffs[i*16] = y2[i]; short *coeffs)
} {
short y2[16];
int i;
static void vp8_dixie_walsh(coeffs + 24 * 16, y2);
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) for (i = 0; i < 16; i++)
{ coeffs[i*16] = y2[i];
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); 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;
for (i = 0; i < 16; i++) switch (mbi->base.y_mode)
{ {
vp8_dixie_idct_add(predict, predict, stride, coeffs); case DC_PRED:
coeffs += 16; predict_dc_nxn(predict, stride, 16);
predict += 4; 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);
}
if ((i & 3) == 3) fixup_dc_coeffs(mbi, coeffs);
predict += stride * 4 - 16;
}
} 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) static void
{ predict_intra_chroma(unsigned char *predict_u,
case DC_PRED: unsigned char *predict_v,
predict_dc_nxn(predict_u, stride, 8); int stride,
predict_dc_nxn(predict_v, stride, 8); struct mb_info *mbi,
break; short *coeffs)
case V_PRED: {
predict_v_8x8(predict_u, stride); int i;
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; 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);
}
for (i = 16; i < 20; i++) coeffs += 16 * 16;
{
vp8_dixie_idct_add(predict_u, predict_u, stride, coeffs);
coeffs += 16;
predict_u += 4;
if (i & 1) for (i = 16; i < 20; i++)
predict_u += stride * 4 - 8; {
} vp8_dixie_idct_add(predict_u, predict_u, stride, coeffs);
coeffs += 16;
predict_u += 4;
for (i = 20; i < 24; i++) if (i & 1)
{ predict_u += stride * 4 - 8;
vp8_dixie_idct_add(predict_v, predict_v, stride, coeffs); }
coeffs += 16;
predict_v += 4;
if (i & 1) for (i = 20; i < 24; i++)
predict_v += stride * 4 - 8; {
} 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,
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, int output_stride,
const unsigned char *reference, const unsigned char *reference,
int reference_stride, int reference_stride,
int cols, int cols,
int rows, int rows,
const filter_t filter int mx,
int my,
const filter_t filters[8]
) )
{ {
int r, c, temp; DECLARE_ALIGNED(16, unsigned char, temp[16*(16+5)]);
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++) sixtap_horiz(temp, 16,
{ reference - 2 * reference_stride, reference_stride,
for (c = 0; c < cols; c++) cols, rows + 5, filters[mx]);
{ sixtap_vert(output, output_stride,
temp = (reference[-2*reference_stride] * filter[0]) + temp + 2 * 16, 16,
(reference[-1*reference_stride] * filter[1]) + cols, rows, filters[my]);
(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; struct img_index
output += output_stride; {
} unsigned char *y, *u, *v;
} int stride, uv_stride;
};
static void static const unsigned char *
sixtap_2d(unsigned char *output, filter_block(unsigned char *output,
int output_stride, const unsigned char *reference,
const unsigned char *reference, int stride,
int reference_stride, const union mv *mv,
int cols, const filter_t filters[8])
int rows, {
int mx, int mx, my;
int my,
const filter_t filters[8]
)
{
DECLARE_ALIGNED(16, unsigned char, temp[16*(16+5)]);
sixtap_horiz(temp, 16, /* Handle 0,0 as a special case. TODO: does this make it any
reference - 2 * reference_stride, reference_stride, * faster?
cols, rows + 5, filters[mx]); */
if (!mv->raw)
return reference;
sixtap_vert(output, output_stride, mx = mv->d.x & 7;
temp + 2 * 16, 16, my = mv->d.y & 7;
cols, rows, filters[my]); reference += ((mv->d.y >> 3) * stride) + (mv->d.x >> 3);
}
struct img_index if (mx | my)
{ {
unsigned char *y, *u, *v; sixtap_2d(output, stride, reference, stride, 4, 4, mx, my,
int stride, uv_stride; filters);
}; reference = output;
}
static const unsigned char * return reference;
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; static void
my = mv->d.y & 7; recon_1_block(unsigned char *output,
reference += ((mv->d.y >> 3) * stride) + (mv->d.x >> 3); 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;
if (mx | my) predict = filter_block(output, reference, stride, mv, filters);
{ vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b);
sixtap_2d(output, stride, reference, stride, 4, 4, mx, my, }
filters);
reference = output;
}
return reference; static mv_t
} calculate_chroma_splitmv(struct mb_info *mbi,
int b,
int full_pixel)
{
int temp;
union mv mv;
static void temp = mbi->split.mvs[b].d.x +
recon_1_block(unsigned char *output, mbi->split.mvs[b+1].d.x +
const unsigned char *reference, mbi->split.mvs[b+4].d.x +
int stride, mbi->split.mvs[b+5].d.x;
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); if (temp < 0)
vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b); temp -= 4;
} else
temp += 4;
static mv_t mv.d.x = temp / 8;
calculate_chroma_splitmv(struct mb_info *mbi,
int b,
int full_pixel)
{
int temp;
union mv mv;
temp = mbi->split.mvs[b].d.x + temp = mbi->split.mvs[b].d.y +
mbi->split.mvs[b+1].d.x + mbi->split.mvs[b+1].d.y +
mbi->split.mvs[b+4].d.x + mbi->split.mvs[b+4].d.y +
mbi->split.mvs[b+5].d.x; mbi->split.mvs[b+5].d.y;
if (temp < 0) if (temp < 0)
temp -= 4; temp -= 4;
else
temp += 4;
mv.d.x = temp / 8; else
temp += 4;
temp = mbi->split.mvs[b].d.y + mv.d.y = temp / 8;
mbi->split.mvs[b+1].d.y +
mbi->split.mvs[b+4].d.y +
mbi->split.mvs[b+5].d.y;
if (temp < 0) if (full_pixel)
temp -= 4; {
else mv.d.x &= ~7;
temp += 4; mv.d.y &= ~7;
}
mv.d.y = temp / 8; return mv;
}
if (full_pixel) /* Note: We rely on the reconstructed border having the same stride
{ * as the reference buffer because the filter_block can't adjust the
mv.d.x &= ~7; * stride with its return value, only the reference pointer.
mv.d.y &= ~7; */
} 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;
return mv; /* Get a pointer to the start of the real data for this row */
} ref_row = src - x - y * stride;
/* Note: We rely on the reconstructed border having the same stride as if (y >= h)
* the reference buffer because the filter_block can't adjust the ref_row += (h - 1) * stride;
* stride with its return value, only the reference pointer. else if (y > 0)
*/ ref_row += y * stride;
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 */ do
ref_row = src - x - y * stride; {
int left, right = 0, copy;
if (y >= h) left = x < 0 ? -x : 0;
ref_row += (h - 1) * stride; if (left > b_w)
else if (y > 0) left = b_w;
ref_row += y * stride;
do if (x + b_w > w)
{ right = x + b_w - w;
int left, right = 0, copy;
left = x < 0 ? -x : 0; if (right > b_w)
right = b_w;
if (left > b_w) copy = b_w - left - right;
left = b_w;
if (x + b_w > w) if (left)
right = x + b_w - w; memset(dst, ref_row[0], left);
if (right > b_w) if (copy)
right = b_w; memcpy(dst + left, ref_row + x + left, copy);
copy = b_w - left - right; if (right)
memset(dst + left + copy, ref_row[w-1], right);
if (left) dst += stride;
memset(dst, ref_row[0], left); y++;
if (copy) if (y < h && y > 0)
memcpy(dst + left, ref_row + x + left, copy); ref_row += stride;
}
while (--b_h);
}
if (right) static void
memset(dst + left + copy, ref_row[w-1], right); 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;
dst += stride; x += mv->d.x >> 3;
y++; y += mv->d.y >> 3;
if (y < h && y > 0) /* Need two pixels left/above, 3 right/below for 6-tap */
ref_row += stride; if (x < 2 || x + b_w - 1 + 3 >= w || y < 2 ||
} y + b_h - 1 + 3 >= h)
while (--b_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;
}
static void predict = filter_block(output, reference, stride, mv, filters);
recon_1_edge_block(unsigned char *output, vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b);
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; static void
y += mv->d.y >> 3; 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;
/* Need two pixels left/above, 3 right/below for 6-tap */ x = mb_col * 16;
if (x < 2 || x + b_w - 1 + 3 >= w || y < 2 || y + b_h - 1 + 3 >= h) y = mb_row * 16;
{ w = ctx->mb_cols * 16;
reference += (mv->d.x >> 3) + (mv->d.y >> 3) * stride; h = ctx->mb_rows * 16;
build_mc_border(emul_block, output = img->y;
reference - 2 - 2 * stride, stride, reference_offset = ctx->ref_frame_offsets[mbi->base.ref_frame];
x - 2, y - 2, b_w + 5, b_h + 5, w, h); reference = output + reference_offset;
reference = emul_block + 2 * stride + 2;
reference -= (mv->d.x >> 3) + (mv->d.y >> 3) * stride;
}
predict = filter_block(output, reference, stride, mv, filters); if (mbi->base.y_mode != SPLITMV)
vp8_dixie_idct_add(output, predict, stride, coeffs + 16 * b); {
} union mv uvmv;
static void uvmv = mbi->base.mv;
predict_inter_emulated_edge(struct vp8_decoder_ctx *ctx, uvmv.d.x = (uvmv.d.x + 1 + (uvmv.d.x >> 31) * 2) / 2;
struct img_index *img, uvmv.d.y = (uvmv.d.y + 1 + (uvmv.d.y >> 31) * 2) / 2;
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; if (full_pixel)
y = mb_row * 16; {
w = ctx->mb_cols * 16; uvmv.d.x &= ~7;
h = ctx->mb_rows * 16; uvmv.d.y &= ~7;
output = img->y; }
reference_offset = ctx->ref_frame_offsets[mbi->base.ref_frame];
reference = output + reference_offset;
if (mbi->base.y_mode != SPLITMV) chroma_mv[0] = uvmv;
{ chroma_mv[1] = uvmv;
union mv 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);
}
uvmv = mbi->base.mv; /* Luma */
uvmv.d.x = (uvmv.d.x + 1 + (uvmv.d.x >> 31) * 2) / 2; for (b = 0; b < 16; b++)
uvmv.d.y = (uvmv.d.y + 1 + (uvmv.d.y >> 31) * 2) / 2; {
union mv *ymv;
if (full_pixel) if (mbi->base.y_mode != SPLITMV)
{ ymv = &mbi->base.mv;
uvmv.d.x &= ~7; else
uvmv.d.y &= ~7; ymv = mbi->split.mvs + b;
}
chroma_mv[0] = uvmv; recon_1_edge_block(output, emul_block, reference,
chroma_mv[1] = uvmv; img->stride, ymv, ctx->subpixel_filters, coeffs,
chroma_mv[2] = uvmv; mbi, x, y, w, h, b);
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 */ x += 4;
for (b = 0; b < 16; b++) output += 4;
{ reference += 4;
union mv *ymv;
if (mbi->base.y_mode != SPLITMV) if ((b & 3) == 3)
ymv = &mbi->base.mv; {
else x -= 16;
ymv = mbi->split.mvs + b; y += 4;
output += 4 * img->stride - 16;
reference += 4 * img->stride - 16;
}
}
recon_1_edge_block(output, emul_block, reference, img->stride, x = mb_col * 16;
ymv, ctx->subpixel_filters, y = mb_row * 16;
coeffs, mbi, x, y, w, h, b);
x += 4; /* Chroma */
output += 4; x >>= 1;
reference += 4; y >>= 1;
w >>= 1;
h >>= 1;
if ((b & 3) == 3) for (b = 0; b < 4; b++)
{ {
x -= 16; recon_1_edge_block(u, emul_block, u + reference_offset,
y += 4; img->uv_stride,
output += 4 * img->stride - 16; &chroma_mv[b], ctx->subpixel_filters,
reference += 4 * img->stride - 16; coeffs, mbi, x, y, w, h, b + 16);
} recon_1_edge_block(v, emul_block, v + reference_offset,
} img->uv_stride,
x = mb_col * 16; &chroma_mv[b], ctx->subpixel_filters,
y = mb_row * 16; coeffs, mbi, x, y, w, h, b + 20);
u += 4;
v += 4;
x += 4;
/* Chroma */ if (b & 1)
x >>= 1; {
y >>= 1; x -= 8;
w >>= 1; y += 4;
h >>= 1; u += 4 * img->uv_stride - 8;
v += 4 * img->uv_stride - 8;
}
}
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) static void
{ predict_inter(struct vp8_decoder_ctx *ctx,
x -= 8; struct img_index *img,
y += 4; short *coeffs,
u += 4 * img->uv_stride - 8; struct mb_info *mbi)
v += 4 * img->uv_stride - 8; {
} 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;
static void uvmv = mbi->base.mv;
predict_inter(struct vp8_decoder_ctx *ctx, uvmv.d.x = (uvmv.d.x + 1 + (uvmv.d.x >> 31) * 2) / 2;
struct img_index *img, uvmv.d.y = (uvmv.d.y + 1 + (uvmv.d.y >> 31) * 2) / 2;
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; if (full_pixel)
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; uvmv.d.x &= ~7;
uvmv.d.y &= ~7;
}
if (full_pixel) chroma_mv[0] =
{ chroma_mv[1] =
uvmv.d.x &= ~7; chroma_mv[2] =
uvmv.d.y &= ~7; 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);
}
chroma_mv[0] = reference_offset = ctx->ref_frame_offsets[mbi->base.ref_frame];
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;
for (b = 0; b < 16; b++) if (mbi->base.y_mode != SPLITMV)
{ ymv = &mbi->base.mv;
union mv *ymv; else
ymv = mbi->split.mvs + b;
if (mbi->base.y_mode != SPLITMV) recon_1_block(y, y + reference_offset, img->stride,
ymv = &mbi->base.mv; ymv, ctx->subpixel_filters, coeffs, mbi, b);
else y += 4;
ymv = mbi->split.mvs + b;
recon_1_block(y, y + reference_offset, img->stride, if ((b & 3) == 3)
ymv, ctx->subpixel_filters, coeffs, mbi, b); y += 4 * img->stride - 16;
y += 4; }
if ((b & 3) == 3) for (b = 0; b < 4; b++)
y += 4 * img->stride - 16; {
} 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;
for (b = 0; b < 4; b++) if (b & 1)
{ {
recon_1_block(u, u + reference_offset, u += 4 * img->uv_stride - 8;
img->uv_stride, &chroma_mv[b], v += 4 * img->uv_stride - 8;
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) void
{ vp8_dixie_release_ref_frame(struct ref_cnt_img *rcimg)
u += 4 * img->uv_stride - 8; {
v += 4 * img->uv_stride - 8; if (rcimg)
} {
} assert(rcimg->ref_cnt);
} rcimg->ref_cnt--;
}
}
void struct ref_cnt_img *
vp8_dixie_release_ref_frame(struct ref_cnt_img *rcimg) vp8_dixie_ref_frame(struct ref_cnt_img *rcimg)
{ {
if (rcimg) rcimg->ref_cnt++;
{ return rcimg;
assert(rcimg->ref_cnt); }
rcimg->ref_cnt--;
}
}
struct ref_cnt_img * struct ref_cnt_img *
vp8_dixie_ref_frame(struct ref_cnt_img *rcimg) vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames)
{ {
rcimg->ref_cnt++; int i;
return rcimg;
}
struct ref_cnt_img * for (i = 0; i < NUM_REF_FRAMES; i++)
vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames) if (frames[i].ref_cnt == 0)
{ {
int i; frames[i].ref_cnt = 1;
return &frames[i];
}
for (i = 0; i < NUM_REF_FRAMES; i++) assert(0);
if (frames[i].ref_cnt == 0) return NULL;
{ }
frames[i].ref_cnt = 1;
return &frames[i];
} 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;
assert(0); if (mode == DC_PRED && row)
return NULL; {
} unsigned char *above = predict - stride;
static void for (i = 0; i < width; i++)
fixup_left(unsigned char *predict, {
int width, *left = above[i];
int stride, left += stride;
unsigned int row, }
enum prediction_mode mode) }
{ else
/* 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 /* Need to re-set the above row, in case the above MB was
* above row, unless this is also row 0, in which case we use * DC_PRED.
* 129. */
*/ left -= stride;
unsigned char *left = predict - 1; for (i = -1; i < width; i++)
int i; {
*left = 129;
left += stride;
}
}
}
if (mode == DC_PRED && row) static void
{ fixup_above(unsigned char *predict,
unsigned char *above = predict - stride; 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;
for (i = 0; i < width; i++) if (mode == DC_PRED && col)
{ {
*left = above[i]; unsigned char *left = predict - 1;
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++) for (i = 0; i < width; i++)
{ {
*left = 129; above[i] = *left;
left += stride; left += stride;
} }
} }
} else
static void /* Need to re-set the left col, in case the last MB was
fixup_above(unsigned char *predict, * DC_PRED.
int width, */
int stride, memset(above - 1, 127, width + 1);
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) memset(above + width, 127, 4); // for above-right subblock modes
{ }
unsigned char *left = predict - 1;
for (i = 0; i < width; i++) void
{ vp8_dixie_predict_init(struct vp8_decoder_ctx *ctx)
above[i] = *left; {
left += stride; int i;
} unsigned char *this_frame_base;
}
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 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;
void vpx_img_free(&ctx->frame_strg[i].img);
vp8_dixie_predict_init(struct vp8_decoder_ctx *ctx) ctx->frame_strg[i].ref_cnt = 0;
{ ctx->ref_frames[i] = NULL;
int i; if (!vpx_img_alloc(&ctx->frame_strg[i].img,
unsigned char *this_frame_base; IMG_FMT_I420, w, h, 16))
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate %dx%d"
" framebuffer",
w, h);
if (ctx->frame_hdr.frame_size_updated) vpx_img_set_rect(&ctx->frame_strg[i].img, BORDER_PIXELS,
{ BORDER_PIXELS, ctx->frame_hdr.kf.w,
for (i = 0; i < NUM_REF_FRAMES; i++) ctx->frame_hdr.kf.h);
{
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, if (ctx->frame_hdr.version)
BORDER_PIXELS, BORDER_PIXELS, ctx->subpixel_filters = bilinear_filters;
ctx->frame_hdr.kf.w, ctx->frame_hdr.kf.h); 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]);
if (ctx->frame_hdr.version) ctx->ref_frames[CURRENT_FRAME] =
ctx->subpixel_filters = bilinear_filters; vp8_dixie_find_free_ref_frame(ctx->frame_strg);
else this_frame_base = ctx->ref_frames[CURRENT_FRAME]->img.img_data;
ctx->subpixel_filters = sixtap_filters;
}
/* Find a free framebuffer to predict into */ /* Calculate offsets to the other reference frames */
if (ctx->ref_frames[CURRENT_FRAME]) for (i = 0; i < NUM_REF_FRAMES; i++)
vp8_dixie_release_ref_frame(ctx->ref_frames[CURRENT_FRAME]); {
struct ref_cnt_img *ref = ctx->ref_frames[i];
ctx->ref_frames[CURRENT_FRAME] = ctx->ref_frame_offsets[i] =
vp8_dixie_find_free_ref_frame(ctx->frame_strg); ref ? ref->img.img_data - this_frame_base : 0;
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] = /* TODO: No need to do this on every frame... */
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;
void for (i = 0; i < NUM_REF_FRAMES; i++)
vp8_dixie_predict_destroy(struct vp8_decoder_ctx *ctx) {
{ vpx_img_free(&ctx->frame_strg[i].img);
int i; ctx->frame_strg[i].ref_cnt = 0;
for (i = 0; i < NUM_REF_FRAMES; i++) ctx->ref_frames[i] = NULL;
{ }
vpx_img_free(&ctx->frame_strg[i].img); }
ctx->frame_strg[i].ref_cnt = 0;
ctx->ref_frames[i] = NULL;
}
}
void void
vp8_dixie_predict_process_row(struct vp8_decoder_ctx *ctx, vp8_dixie_predict_process_row(struct vp8_decoder_ctx *ctx,
unsigned int row, unsigned int row,
unsigned int start_col, unsigned int start_col,
unsigned int num_cols) unsigned int num_cols)
{ {
struct img_index img; struct img_index img;
struct mb_info *mbi; struct mb_info *mbi;
unsigned int col; unsigned int col;
short *coeffs; short *coeffs;
/* Adjust pointers based on row, start_col */ /* Adjust pointers based on row, start_col */
img.stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y]; img.stride =
img.uv_stride = ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U]; ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_Y];
img.y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y]; img.uv_stride =
img.u = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_U]; ctx->ref_frames[CURRENT_FRAME]->img.stride[PLANE_U];
img.v = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_V]; img.y = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_Y];
img.y += (img.stride * row + start_col) * 16; img.u = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_U];
img.u += (img.uv_stride * row + start_col) * 8; img.v = ctx->ref_frames[CURRENT_FRAME]->img.planes[PLANE_V];
img.v += (img.uv_stride * row + start_col) * 8; img.y += (img.stride * row + start_col) * 16;
mbi = ctx->mb_info_rows[row] + start_col; img.u += (img.uv_stride * row + start_col) * 8;
coeffs = ctx->tokens[row & (ctx->token_hdr.partitions - 1)].coeffs img.v += (img.uv_stride * row + start_col) * 8;
+ 25 * 16 * start_col; 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 */ /* Fix up the out-of-frame pixels */
if (start_col == 0) if (start_col == 0)
{ {
fixup_left(img.y, 16, img.stride, row, mbi->base.y_mode); 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.u, 8, img.uv_stride, row, mbi->base.uv_mode);
fixup_left(img.v, 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) if (row == 0)
*(img.y - img.stride - 1) = 127; *(img.y - img.stride - 1) = 127;
} }
for (col = start_col; col < start_col + num_cols; col++) for (col = start_col; col < start_col + num_cols; col++)
{ {
if (row == 0) if (row == 0)
{ {
fixup_above(img.y, 16, img.stride, col, mbi->base.y_mode); fixup_above(img.y, 16, img.stride, col,
fixup_above(img.u, 8, img.uv_stride, col, mbi->base.y_mode);
mbi->base.uv_mode); fixup_above(img.u, 8, img.uv_stride, col,
fixup_above(img.v, 8, img.uv_stride, col, mbi->base.uv_mode);
mbi->base.uv_mode); fixup_above(img.v, 8, img.uv_stride, col,
} mbi->base.uv_mode);
}
if (mbi->base.y_mode <= B_PRED) if (mbi->base.y_mode <= B_PRED)
{ {
predict_intra_luma(img.y, img.stride, mbi, coeffs); predict_intra_luma(img.y, img.stride, mbi, coeffs);
predict_intra_chroma(img.u, img.v, img.uv_stride, mbi, predict_intra_chroma(img.u, img.v, img.uv_stride, mbi,
coeffs); coeffs);
} }
else else
{ {
if (mbi->base.y_mode != SPLITMV) // && != BPRED if (mbi->base.y_mode != SPLITMV) // && != BPRED
fixup_dc_coeffs(mbi, coeffs); fixup_dc_coeffs(mbi, coeffs);
if (mbi->base.need_mc_border) if (mbi->base.need_mc_border)
predict_inter_emulated_edge(ctx, &img, coeffs, mbi, col, predict_inter_emulated_edge(ctx, &img, coeffs, mbi,
row); col, row);
else else
predict_inter(ctx, &img, coeffs, mbi); predict_inter(ctx, &img, coeffs, mbi);
} }
/* Advance to the next macroblock */ /* Advance to the next macroblock */
mbi++; mbi++;
img.y += 16; img.y += 16;
img.u += 8; img.u += 8;
img.v += 8; img.v += 8;
coeffs += 25 * 16; 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;
}
}
if (col == ctx->mb_cols) ---- End code block ----------------------------------------
{
/* 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;
}
}
20.15. predict.h 20.15. predict.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
skipping to change at page 238, line 47 skipping to change at page 239, line 48
struct ref_cnt_img * struct ref_cnt_img *
vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames); vp8_dixie_find_free_ref_frame(struct ref_cnt_img *frames);
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.16. tokens.c 20.16. tokens.c
/* ---- Begin code block --------------------------------------
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. /*
* * 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 * Use of this source code is governed by a BSD-style license
* tree. An additional intellectual property rights grant can be * that can be found in the LICENSE file in the root of the source
* found in the file PATENTS. All contributing project authors may * tree. An additional intellectual property rights grant can be
* be found in the AUTHORS file in the root of the source tree. * 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 "vpx_codec_internal.h"
#include "tokens.h" #include "dixie.h"
#include <stdlib.h> #include "tokens.h"
#include <string.h> #include <stdlib.h>
#include <malloc.h> #include <string.h>
#include <malloc.h>
enum enum
{ {
EOB_CONTEXT_NODE, EOB_CONTEXT_NODE,
ZERO_CONTEXT_NODE, ZERO_CONTEXT_NODE,
ONE_CONTEXT_NODE, ONE_CONTEXT_NODE,
LOW_VAL_CONTEXT_NODE, LOW_VAL_CONTEXT_NODE,
TWO_CONTEXT_NODE, TWO_CONTEXT_NODE,
THREE_CONTEXT_NODE, THREE_CONTEXT_NODE,
HIGH_LOW_CONTEXT_NODE, HIGH_LOW_CONTEXT_NODE,
CAT_ONE_CONTEXT_NODE, CAT_ONE_CONTEXT_NODE,
CAT_THREEFOUR_CONTEXT_NODE, CAT_THREEFOUR_CONTEXT_NODE,
CAT_THREE_CONTEXT_NODE, CAT_THREE_CONTEXT_NODE,
CAT_FIVE_CONTEXT_NODE CAT_FIVE_CONTEXT_NODE
}; };
enum enum
{ {
ZERO_TOKEN, ZERO_TOKEN,
ONE_TOKEN, ONE_TOKEN,
TWO_TOKEN, TWO_TOKEN,
THREE_TOKEN, THREE_TOKEN,
FOUR_TOKEN, FOUR_TOKEN,
DCT_VAL_CATEGORY1, DCT_VAL_CATEGORY1,
DCT_VAL_CATEGORY2, DCT_VAL_CATEGORY2,
DCT_VAL_CATEGORY3, DCT_VAL_CATEGORY3,
DCT_VAL_CATEGORY4, DCT_VAL_CATEGORY4,
DCT_VAL_CATEGORY5, DCT_VAL_CATEGORY5,
DCT_VAL_CATEGORY6, DCT_VAL_CATEGORY6,
DCT_EOB_TOKEN, DCT_EOB_TOKEN,
MAX_ENTROPY_TOKENS MAX_ENTROPY_TOKENS
}; };
struct extrabits struct extrabits
{ {
short min_val; short min_val;
short length; short length;
unsigned char probs[12]; unsigned char probs[12];
}; };
static const unsigned int left_context_index[25] = static const unsigned int left_context_index[25] =
{ {
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 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 4, 4, 5, 5, 6, 6, 7, 7, 8
}; };
static const unsigned int above_context_index[25] = static const unsigned int above_context_index[25] =
{ {
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 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 4, 5, 4, 5, 6, 7, 6, 7, 8
}; };
#define X(n) ((n) * PREV_COEF_CONTEXTS * ENTROPY_NODES) #define X(n) ((n) * PREV_COEF_CONTEXTS * ENTROPY_NODES)
static const unsigned int bands_x[16] = static const unsigned int bands_x[16] =
{ {
X(0), X(1), X(2), X(3), X(6), X(4), X(5), X(6), 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) X(6), X(6), X(6), X(6), X(6), X(6), X(6), X(7)
}; };
#undef X #undef X
static const struct extrabits extrabits[MAX_ENTROPY_TOKENS] = static const struct extrabits extrabits[MAX_ENTROPY_TOKENS] =
{ {
{ 0, -1, { 0, 0, 0, 0, 0, 0, { 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ZERO_TOKEN 0, 0, 0, 0, 0, 0 } }, //ZERO_TOKEN
{ 1, 0, { 0, 0, 0, 0, 0, 0, { 1, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //ONE_TOKEN 0, 0, 0, 0, 0, 0 } }, //ONE_TOKEN
{ 2, 0, { 0, 0, 0, 0, 0, 0, { 2, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //TWO_TOKEN 0, 0, 0, 0, 0, 0 } }, //TWO_TOKEN
{ 3, 0, { 0, 0, 0, 0, 0, 0, { 3, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //THREE_TOKEN 0, 0, 0, 0, 0, 0 } }, //THREE_TOKEN
{ 4, 0, { 0, 0, 0, 0, 0, 0, { 4, 0, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //FOUR_TOKEN 0, 0, 0, 0, 0, 0 } }, //FOUR_TOKEN
{ 5, 0, { 159, 0, 0, 0, 0, 0, { 5, 0, {159, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY1 0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY1
{ 7, 1, { 145, 165, 0, 0, 0, 0, { 7, 1, {145, 165, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY2 0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY2
{ 11, 2, { 140, 148, 173, 0, 0, 0, {11, 2, {140, 148, 173, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY3 0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY3
{ 19, 3, { 135, 140, 155, 176, 0, 0, {19, 3, {135, 140, 155, 176, 0, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY4 0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY4
{ 35, 4, { 130, 134, 141, 157, 180, 0, {35, 4, {130, 134, 141, 157, 180, 0,
0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY5 0, 0, 0, 0, 0, 0 } }, //DCT_VAL_CATEGORY5
{ 67, 10, { 129, 130, 133, 140, 153, 177, {67, 10, {129, 130, 133, 140, 153, 177,
196, 230, 243, 254, 254, 0 } }, //DCT_VAL_CATEGORY6 196, 230, 243, 254, 254, 0 } }, //DCT_VAL_CATEGORY6
{ 0, -1, { 0, 0, 0, 0, 0, 0, { 0, -1, { 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 } }, // EOB TOKEN 0, 0, 0, 0, 0, 0 } }, // EOB TOKEN
}; };
static const unsigned int zigzag[16] = static const unsigned int zigzag[16] =
{ {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
}; };
#define DECODE_AND_APPLYSIGN(value_to_sign) \ #define DECODE_AND_APPLYSIGN(value_to_sign) \
v = (bool_get_bit(bool) ? -value_to_sign \ v = (bool_get_bit(bool) ? -value_to_sign \
: value_to_sign) * dqf[!!c]; : value_to_sign) * dqf[!!c];
#define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \ #define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) goto branch; if (!bool_get(bool, probability)) goto branch;
#define DECODE_AND_LOOP_IF_ZERO(probability,branch) \ #define DECODE_AND_LOOP_IF_ZERO(probability,branch) \
if (!bool_get(bool, probability)) \ if (!bool_get(bool, probability)) \
{ \ { \
prob = type_probs; \ prob = type_probs; \
if(c<15) {\ if(c<15) {\
++c; \ ++c; \
prob += bands_x[c]; \ prob += bands_x[c]; \
goto branch; \ goto branch; \
}\ }\
else \ else \
goto BLOCK_FINISHED; /*for malformed input */\ goto BLOCK_FINISHED; /* for malformed input */\
} }
#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \ #define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
DECODE_AND_APPLYSIGN(val) \ DECODE_AND_APPLYSIGN(val) \
prob = type_probs + (ENTROPY_NODES*2); \ prob = type_probs + (ENTROPY_NODES*2); \
if(c < 15){\ if(c < 15){\
b_tokens[zigzag[c]] = v; \ b_tokens[zigzag[c]] = v; \
++c; \ ++c; \
goto DO_WHILE; }\ goto DO_WHILE; }\
b_tokens[zigzag[15]] = v; \ b_tokens[zigzag[15]] = v; \
goto BLOCK_FINISHED; goto BLOCK_FINISHED;
#define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\ #define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\
val += bool_get(bool, extrabits[t].probs[bits_count]) << bits_count; val += bool_get(bool, extrabits[t].probs[bits_count]) << \
bits_count;
static int static int
decode_mb_tokens(struct bool_decoder *bool, decode_mb_tokens(struct bool_decoder *bool,
token_entropy_ctx_t left, token_entropy_ctx_t left,
token_entropy_ctx_t above, token_entropy_ctx_t above,
short *tokens, short *tokens,
enum prediction_mode mode, enum prediction_mode mode,
coeff_probs_table_t probs, coeff_probs_table_t probs,
short factor[TOKEN_BLOCK_TYPES][2]) short factor[TOKEN_BLOCK_TYPES][2])
{ {
int i, stop, type; int i, stop, type;
int c, t, v; int c, t, v;
int val, bits_count; int val, bits_count;
int eob_mask; int eob_mask;
short *b_tokens; /* tokens for this block */ short *b_tokens; // tokens for this block
unsigned char *type_probs; /* probabilities for this block type */ unsigned char *type_probs; // probabilities for this block type
unsigned char *prob; unsigned char *prob;
short *dqf; short *dqf;
eob_mask = 0; eob_mask = 0;
if (mode != B_PRED && mode != SPLITMV) if (mode != B_PRED && mode != SPLITMV)
{ {
i = 24; i = 24;
stop = 24; stop = 24;
type = 1; type = 1;
b_tokens = tokens + 24 * 16; b_tokens = tokens + 24 * 16;
dqf = factor[TOKEN_BLOCK_Y2]; dqf = factor[TOKEN_BLOCK_Y2];
} }
else else
{ {
i = 0; i = 0;
stop = 16; stop = 16;
type = 3; type = 3;
b_tokens = tokens; b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1]; dqf = factor[TOKEN_BLOCK_Y1];
} }
/* Save a pointer to the coefficient probs for the current type. /* Save a pointer to the coefficient probs for the current type.
* Need to repeat this whenever type changes. * Need to repeat this whenever type changes.
*/ */
type_probs = probs[type][0][0]; type_probs = probs[type][0][0];
BLOCK_LOOP: BLOCK_LOOP:
t = left[left_context_index[i]] + above[above_context_index[i]]; t = left[left_context_index[i]] + above[above_context_index[i]];
c = !type; /* all blocks start at 0 except type 0, which starts c = !type; /* all blocks start at 0 except type 0, which starts
* at 1. */ * at 1. */
prob = type_probs; prob = type_probs;
prob += t * ENTROPY_NODES; prob += t * ENTROPY_NODES;
DO_WHILE: DO_WHILE:
prob += bands_x[c]; prob += bands_x[c];
DECODE_AND_BRANCH_IF_ZERO(prob[EOB_CONTEXT_NODE], BLOCK_FINISHED); DECODE_AND_BRANCH_IF_ZERO(prob[EOB_CONTEXT_NODE],
BLOCK_FINISHED);
CHECK_0_: 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;
DECODE_AND_LOOP_IF_ZERO(prob[ZERO_CONTEXT_NODE], CHECK_0_); do
DECODE_AND_BRANCH_IF_ZERO(prob[ONE_CONTEXT_NODE], {
ONE_CONTEXT_NODE_0_); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6,
DECODE_AND_BRANCH_IF_ZERO(prob[LOW_VAL_CONTEXT_NODE], bits_count);
LOW_VAL_CONTEXT_NODE_0_); bits_count -- ;
DECODE_AND_BRANCH_IF_ZERO(prob[HIGH_LOW_CONTEXT_NODE], }
HIGH_LOW_CONTEXT_NODE_0_); while (bits_count >= 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_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
{
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_FIVE_CONTEXT_NODE_0_: CAT_THREEFOUR_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY5].min_val; DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREE_CONTEXT_NODE],
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4); CAT_THREE_CONTEXT_NODE_0_);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3); val = extrabits[DCT_VAL_CATEGORY4].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_THREEFOUR_CONTEXT_NODE_0_: CAT_THREE_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_THREE_CONTEXT_NODE], val = extrabits[DCT_VAL_CATEGORY3].min_val;
CAT_THREE_CONTEXT_NODE_0_); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2);
val = extrabits[DCT_VAL_CATEGORY4].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0);
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2); DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
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_: HIGH_LOW_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY3].min_val; DECODE_AND_BRANCH_IF_ZERO(prob[CAT_ONE_CONTEXT_NODE],
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2); CAT_ONE_CONTEXT_NODE_0_);
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_: val = extrabits[DCT_VAL_CATEGORY2].min_val;
DECODE_AND_BRANCH_IF_ZERO(prob[CAT_ONE_CONTEXT_NODE], DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1);
CAT_ONE_CONTEXT_NODE_0_); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
val = extrabits[DCT_VAL_CATEGORY2].min_val; CAT_ONE_CONTEXT_NODE_0_:
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1); val = extrabits[DCT_VAL_CATEGORY1].min_val;
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val); DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
CAT_ONE_CONTEXT_NODE_0_: LOW_VAL_CONTEXT_NODE_0_:
val = extrabits[DCT_VAL_CATEGORY1].min_val; DECODE_AND_BRANCH_IF_ZERO(prob[TWO_CONTEXT_NODE],
DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0); TWO_CONTEXT_NODE_0_);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val); DECODE_AND_BRANCH_IF_ZERO(prob[THREE_CONTEXT_NODE],
THREE_CONTEXT_NODE_0_);
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4);
LOW_VAL_CONTEXT_NODE_0_: THREE_CONTEXT_NODE_0_:
DECODE_AND_BRANCH_IF_ZERO(prob[TWO_CONTEXT_NODE], DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3);
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_: TWO_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3); DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2);
TWO_CONTEXT_NODE_0_: ONE_CONTEXT_NODE_0_:
DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2); DECODE_AND_APPLYSIGN(1);
prob = type_probs + ENTROPY_NODES;
ONE_CONTEXT_NODE_0_: if (c < 15)
DECODE_AND_APPLYSIGN(1); {
prob = type_probs + ENTROPY_NODES; b_tokens[zigzag[c]] = v;
++c;
goto DO_WHILE;
}
if (c < 15) b_tokens[zigzag[15]] = v;
{ BLOCK_FINISHED:
b_tokens[zigzag[c]] = v; eob_mask |= (c > 1) << i;
++c; t = (c != !type); // any nonzero data?
goto DO_WHILE; eob_mask |= t << 31;
}
b_tokens[zigzag[15]] = v; left[left_context_index[i]] = above[above_context_index[i]] = t;
BLOCK_FINISHED: b_tokens += 16;
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; i++;
b_tokens += 16;
i++; if (i < stop)
if (i < stop) goto BLOCK_LOOP;
goto BLOCK_LOOP;
if (i == 25) if (i == 25)
{ {
type = 0; type = 0;
i = 0; i = 0;
stop = 16; stop = 16;
type_probs = probs[type][0][0]; type_probs = probs[type][0][0];
b_tokens = tokens; b_tokens = tokens;
dqf = factor[TOKEN_BLOCK_Y1]; dqf = factor[TOKEN_BLOCK_Y1];
goto BLOCK_LOOP; goto BLOCK_LOOP;
} }
if (i == 16) if (i == 16)
{ {
type = 2; type = 2;
type_probs = probs[type][0][0]; type_probs = probs[type][0][0];
stop = 24; stop = 24;
dqf = factor[TOKEN_BLOCK_UV]; dqf = factor[TOKEN_BLOCK_UV];
goto BLOCK_LOOP; goto BLOCK_LOOP;
} }
return eob_mask; return eob_mask;
} }
static void static void
reset_row_context(token_entropy_ctx_t *left) reset_row_context(token_entropy_ctx_t *left)
{ {
memset(left, 0, sizeof(*left)); memset(left, 0, sizeof(*left));
} }
static void static void
reset_above_context(token_entropy_ctx_t *above, unsigned int cols) reset_above_context(token_entropy_ctx_t *above, unsigned int cols)
{ {
memset(above, 0, cols * sizeof(*above)); memset(above, 0, cols * sizeof(*above));
} }
static void static void
reset_mb_context(token_entropy_ctx_t *left, reset_mb_context(token_entropy_ctx_t *left,
token_entropy_ctx_t *above, token_entropy_ctx_t *above,
enum prediction_mode mode) enum prediction_mode mode)
{ {
/* Reset the macroblock context on the left and right. We have to /* Reset the macroblock context on the left and right. We have to
* preserve the context of the second order block if this mode * preserve the context of the second order block if this mode
* would not have updated it. * would not have updated it.
*/ */
memset(left, 0, sizeof((*left)[0]) * 8); memset(left, 0, sizeof((*left)[0]) * 8);
memset(above, 0, sizeof((*above)[0]) * 8); memset(above, 0, sizeof((*above)[0]) * 8);
if (mode != B_PRED && mode != SPLITMV) if (mode != B_PRED && mode != SPLITMV)
{ {
(*left)[8] = 0; (*left)[8] = 0;
(*above)[8] = 0; (*above)[8] = 0;
} }
} }
void void
vp8_dixie_tokens_process_row(struct vp8_decoder_ctx *ctx, vp8_dixie_tokens_process_row(struct vp8_decoder_ctx *ctx,
unsigned int partition, unsigned int partition,
unsigned int row, unsigned int row,
unsigned int start_col, unsigned int start_col,
unsigned int num_cols) unsigned int num_cols)
{ {
struct token_decoder *tokens = &ctx->tokens[partition]; struct token_decoder *tokens = &ctx->tokens[partition];
short *coeffs = tokens->coeffs + 25 * 16 * start_col; short coeffs = tokens->coeffs + 25 * 16 * start_col;
unsigned int col; unsigned int col;
token_entropy_ctx_t *above = ctx->above_token_entropy_ctx token_entropy_ctx_t *above = ctx->above_token_entropy_ctx
+ start_col; + start_col;
token_entropy_ctx_t *left = &tokens->left_token_entropy_ctx; token_entropy_ctx_t *left = &tokens->left_token_entropy_ctx;
struct mb_info *mbi = ctx->mb_info_rows[row] + start_col; struct mb_info *mbi = ctx->mb_info_rows[row] + start_col;
if (row == 0) if (row == 0)
reset_above_context(above, num_cols); reset_above_context(above, num_cols);
if (start_col == 0) if (start_col == 0)
reset_row_context(left); reset_row_context(left);
for (col = start_col; col < start_col + num_cols; col++) for (col = start_col; col < start_col + num_cols; col++)
{ {
memset(coeffs, 0, 25 * 16 * sizeof(short)); memset(coeffs, 0, 25 * 16 * sizeof(short));
if (mbi->base.skip_coeff) if (mbi->base.skip_coeff)
{ {
reset_mb_context(left, above, mbi->base.y_mode); reset_mb_context(left, above, mbi->base.y_mode);
mbi->base.eob_mask = 0; mbi->base.eob_mask = 0;
} }
else else
{ {
struct dequant_factors *dqf; struct dequant_factors *dqf;
dqf = ctx->dequant_factors + mbi->base.segment_id; dqf = ctx->dequant_factors + mbi->base.segment_id;
mbi->base.eob_mask = mbi->base.eob_mask =
decode_mb_tokens(&tokens->bool, decode_mb_tokens(&tokens->bool,
*left, *above, *left, *above,
coeffs, coeffs,
mbi->base.y_mode, mbi->base.y_mode,
ctx->entropy_hdr.coeff_probs, ctx->entropy_hdr.coeff_probs,
dqf->factor); dqf->factor);
} }
above++; above++;
mbi++; mbi++;
coeffs += 25 * 16; coeffs += 25 * 16;
} }
} }
void void
vp8_dixie_tokens_init(struct vp8_decoder_ctx *ctx) vp8_dixie_tokens_init(struct vp8_decoder_ctx *ctx)
{ {
unsigned int partitions = ctx->token_hdr.partitions; unsigned int partitions = ctx->token_hdr.partitions;
if (ctx->frame_hdr.frame_size_updated) if (ctx->frame_hdr.frame_size_updated)
{ {
unsigned int i; unsigned int i;
unsigned int coeff_row_sz = unsigned int coeff_row_sz =
ctx->mb_cols * 25 * 16 * sizeof(short); ctx->mb_cols * 25 * 16 * sizeof(short);
for (i = 0; i < partitions; i++) for (i = 0; i < partitions; i++)
{ {
free(ctx->tokens[i].coeffs); free(ctx->tokens[i].coeffs);
ctx->tokens[i].coeffs = memalign(16, coeff_row_sz); ctx->tokens[i].coeffs = memalign(16, coeff_row_sz);
if (!ctx->tokens[i].coeffs) if (!ctx->tokens[i].coeffs)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR, vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR,
NULL); NULL);
} }
free(ctx->above_token_entropy_ctx); free(ctx->above_token_entropy_ctx);
ctx->above_token_entropy_ctx = ctx->above_token_entropy_ctx =
calloc(ctx->mb_cols, sizeof(*ctx->above_token_entropy_ctx)); calloc(ctx->mb_cols,
sizeof(*ctx->above_token_entropy_ctx));
if (!ctx->above_token_entropy_ctx) if (!ctx->above_token_entropy_ctx)
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR, NULL); vpx_internal_error(&ctx->error,
} VPX_CODEC_MEM_ERROR, NULL);
} }
}
void void
vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx) vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx)
{ {
int i; int i;
for (i = 0; i < MAX_PARTITIONS; i++) for (i = 0; i < MAX_PARTITIONS; i++)
free(ctx->tokens[i].coeffs); free(ctx->tokens[i].coeffs);
free(ctx->above_token_entropy_ctx); free(ctx->above_token_entropy_ctx);
} }
---- End code block ----------------------------------------
20.17. tokens.h 20.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 = * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
calloc(ctx->mb_cols, sizeof(*ctx->above_token_entropy_ctx)); *
* 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 TOKENS_H
#define TOKENS_H
if (!ctx->above_token_entropy_ctx) void
vpx_internal_error(&ctx->error, VPX_CODEC_MEM_ERROR, NULL); vp8_dixie_tokens_init(struct vp8_decoder_ctx *ctx);
}
}
void void
vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx) vp8_dixie_tokens_destroy(struct vp8_decoder_ctx *ctx);
{
int i;
for (i = 0; i < MAX_PARTITIONS; i++) void
free(ctx->tokens[i].coeffs); vp8_dixie_tokens_process_row(struct vp8_decoder_ctx *ctx,
unsigned int partition,
unsigned int row,
unsigned int start_col,
unsigned int num_cols);
free(ctx->above_token_entropy_ctx); #endif
}
---- End code block ----------------------------------------
20.18. vp8_prob_data.h 20.18. vp8_prob_data.h
---- Begin code block --------------------------------------
static const static const
unsigned char k_coeff_entropy_update_probs[BLOCK_TYPES][COEF_BANDS] unsigned char k_coeff_entropy_update_probs[BLOCK_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS] [PREV_COEF_CONTEXTS]
[ENTROPY_NODES] = [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, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 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, }, {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{223, 241, 252, 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, }, {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, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 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, 255, 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, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{250, 255, 254, 255, 254, 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, }, {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},
{ },
{ {
{217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, }, {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, }, {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
{223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, }, {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
}, },
{ {
{255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {252, 253, 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},
}, },
{ {
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, }, {249, 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, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 255, 255, 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},
}, },
{ {
{255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, }, {255, 255, 255, 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},
{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, },
},
},
{
{
{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 static const
unsigned char k_default_y_mode_probs [] = unsigned char k_default_y_mode_probs [] =
{ 112, 86, 140, 37}; { 112, 86, 140, 37};
static const static const
unsigned char k_default_uv_mode_probs [] = unsigned char k_default_uv_mode_probs [] =
{ 162, 101, 204}; { 162, 101, 204};
static const static const
unsigned char k_default_coeff_probs [BLOCK_TYPES][COEF_BANDS] unsigned char k_default_coeff_probs [BLOCK_TYPES][COEF_BANDS]
[PREV_COEF_CONTEXTS][ENTROPY_NODES] = [PREV_COEF_CONTEXTS][ENTROPY_NODES] =
{ {
{ /* block type 0 */ { /* block type 0 */
{ /* coeff band 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}, { 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 */ { /* coeff band 1 */
{ 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128}, { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
{ 189, 129, 242, 255, 227, 213, 255, 219, 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} { 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 */ { /* coeff band 2 */
{ 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
{ 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128}, { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
{ 238, 1, 255, 128, 128, 128, 128, 128, 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 static const
unsigned char k_mv_entropy_update_probs[2][MV_PROB_CNT] = unsigned char k_mv_entropy_update_probs[2][MV_PROB_CNT] =
{ {
{ {
237, 237,
246, 246,
253, 253, 254, 254, 254, 254, 254, 253, 253, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 250, 250, 252, 254, 254 254, 254, 254, 254, 254, 250, 250, 252, 254, 254
}, },
{ {
231, 231,
243, 243,
245, 253, 254, 254, 254, 254, 254, 245, 253, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 251, 251, 254, 254, 254 254, 254, 254, 254, 254, 251, 251, 254, 254, 254
} }
}; };
static const static const
unsigned char k_default_mv_probs[2][MV_PROB_CNT] = unsigned char k_default_mv_probs[2][MV_PROB_CNT] =
{ {
{ /* row */ { // row
162, /* is short */ 162, // is short
128, /* sign */ 128, // sign
225, 146, 172, 147, 214, 39, 156, /* short tree */ 225, 146, 172, 147, 214, 39, 156, // short tree
128, 129, 132, 75, 145, 178, 206, 239, 254, 254 /* long bits */ 128, 129, 132, 75, 145, 178, 206, 239, 254, 254 // long bits
}, },
{ {
164, 164,
128, 128,
204, 170, 119, 235, 140, 230, 228, 204, 170, 119, 235, 140, 230, 228,
128, 130, 130, 74, 148, 180, 203, 236, 254, 254 128, 130, 130, 74, 148, 180, 203, 236, 254, 254
} }
}; };
---- End code block ----------------------------------------
20.19. vpx_codec_internal.h 20.19. vpx_codec_internal.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may * found in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
/*!\file decoder_impl.h /*!\file vpx_codec_internal.h
* \brief Describes the decoder algorithm interface for algorithm * \brief Describes the decoder algorithm interface for algorithm
* implementations. * implementations.
* *
* This file defines the private structures and data types that are * This file defines the private structures and data types that are
* only relevant to implementing an algorithm, as opposed to using * only relevant to implementing an algorithm, as opposed to using
* it. * it.
* *
* To create a decoder algorithm class, an interface structure is put * To create a decoder algorithm class, an interface structure is put
* into the global namespace: * into the global namespace:
* <pre> * <pre>
skipping to change at page 283, line 35 skipping to change at page 276, line 38
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT #if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
#include "vpx_decoder_compat.h" #include "vpx_decoder_compat.h"
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.21. vpx_integer.h 20.21. vpx_decoder_compat.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The WebM 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 Common Decoder Algorithm Interface
* 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 codecs.
* @{
*/
/*!\file
* \brief Provides a compatibility layer between version 1 and 2 of
* this API.
*
* This interface has been deprecated. Only existing code should make
* use of this interface, and therefore, it is only thinly
* documented. Existing code should be ported to the vpx_codec_* API.
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VPX_DECODER_COMPAT_H
#define VPX_DECODER_COMPAT_H
/*!\brief Decoder algorithm return codes */
typedef enum {
/*!\brief Operation completed without error */
VPX_DEC_OK = VPX_CODEC_OK,
/*!\brief Unspecified error */
VPX_DEC_ERROR = VPX_CODEC_ERROR,
/*!\brief Memory operation failed */
VPX_DEC_MEM_ERROR = VPX_CODEC_MEM_ERROR,
/*!\brief ABI version mismatch */
VPX_DEC_ABI_MISMATCH = VPX_CODEC_ABI_MISMATCH,
/*!\brief The given bitstream is not supported.
*
* The bitstream was unable to be parsed at the highest
* level. The decoder is unable to proceed. This error \ref
* SHOULD be treated as fatal to the stream.
*/
VPX_DEC_UNSUP_BITSTREAM = VPX_CODEC_UNSUP_BITSTREAM,
/*!\brief Encoded bitstream uses an unsupported feature
*
* The decoder does not implement a feature required by the
* encoder. This return code should only be used for features
* that prevent future pictures from being properly decoded.
* This error \ref MAY be treated as fatal to the stream or
* \ref MAY be treated as fatal to the current GOP.
*/
VPX_DEC_UNSUP_FEATURE = VPX_CODEC_UNSUP_FEATURE,
/*!\brief The coded data for this stream is corrupt or
* incomplete
*
* There was a problem decoding the current frame. This
* return code should only be used for failures that prevent
* future pictures from being properly decoded. This error
* \ref MAY be treated as fatal to the stream or \ref MAY be
* treated as fatal to the current GOP. If decoding is
* continued for the current GOP, artifacts may be present.
*/
VPX_DEC_CORRUPT_FRAME = VPX_CODEC_CORRUPT_FRAME,
/*!\brief An application-supplied parameter is not valid.
*
*/
VPX_DEC_INVALID_PARAM = VPX_CODEC_INVALID_PARAM,
/*!\brief An iterator reached the end of list.
*
*/
VPX_DEC_LIST_END = VPX_CODEC_LIST_END
}
vpx_dec_err_t;
/*! \brief Decoder capabilities bitfield
*
* Each decoder advertises the capabilities it supports as part
* of its ::vpx_dec_iface_t interface structure. Capabilities
* are extra interfaces or functionality, and are not required
* to be supported by a decoder.
*
* The available flags are specified by VPX_DEC_CAP_* defines.
*/
typedef int vpx_dec_caps_t;
#define VPX_DEC_CAP_PUT_SLICE 0x0001 /**< Will issue put_slice
callbacks */
#define VPX_DEC_CAP_PUT_FRAME 0x0002 /**< Will issue put_frame
callbacks */
#define VPX_DEC_CAP_XMA 0x0004 /**< Supports eXternal Memory
Allocation */
/*!\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.
*/
#if 1
typedef vpx_codec_stream_info_t vpx_dec_stream_info_t;
#else
typedef struct
{
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_dec_stream_info_t;
#endif
/*!\brief Decoder interface structure.
*
* Contains function pointers and other data private to the
* decoder implementation. This structure is opaque to the
* application.
*/
typedef const struct vpx_codec_iface vpx_dec_iface_t;
typedef struct vpx_codec_priv vpx_dec_priv_t;
/*!\brief Iterator
*
* Opaque storage used for iterating over lists.
*/
typedef vpx_codec_iter_t vpx_dec_iter_t;
/*!\brief Decoder context structure
*
* All decoders \ref MUST support this context structure fully.
* In general, this data should be considered private to the
* decoder algorithm, and not be manipulated or examined by the
* calling application. Applications may reference the 'name'
* member to get a printable description of the algorithm.
*/
#if 1
typedef vpx_codec_ctx_t vpx_dec_ctx_t;
#else
typedef struct
{
const char *name; /**< Printable interface name */
vpx_dec_iface_t *iface; /**< Interface pointers */
vpx_dec_err_t err; /**< Last returned error */
vpx_dec_priv_t *priv; /**< Algorithm private storage */
} vpx_dec_ctx_t;
#endif
/*!\brief Return the build configuration
*
* Returns a printable string containing an encoded version of
* the build configuration. This may be useful to vpx support.
*
*/
const char *vpx_dec_build_config(void) DEPRECATED;
/*!\brief Return the name for a given interface
*
* Returns a human readable string for name of the given decoder
* interface.
*
* \param[in] iface Interface pointer
*
*/
const char *vpx_dec_iface_name(
vpx_dec_iface_t *iface) DEPRECATED;
/*!\brief Convert error number to printable string
*
* Returns a human readable string for the last error returned
* by the algorithm. The returned error will be one line and will
* not contain any newline characters.
*
*
* \param[in] err Error number.
*
*/
const char *vpx_dec_err_to_string(vpx_dec_err_t err) DEPRECATED;
/*!\brief Retrieve error synopsis for decoder context
*
* Returns a human readable string for the last error returned by
* the algorithm. The returned error will be one line and will
* not contain any newline characters.
*
*
* \param[in] ctx Pointer to this instance's context.
*
*/
const char *vpx_dec_error(vpx_dec_ctx_t *ctx) DEPRECATED;
/*!\brief Retrieve detailed error information for decoder context
*
* Returns a human readable string providing detailed information
* about the last error.
*
* \param[in] ctx Pointer to this instance's context.
*
* \retval NULL
* No detailed information is available.
*/
const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx) DEPRECATED;
/* REQUIRED FUNCTIONS
*
* The following functions are required to be implemented for all
* decoders. They represent the base case functionality expected
* of all decoders.
*/
/*!\brief Initialize a decoder instance
*
* Initializes a decoder context using the given interface.
* Applications should call the vpx_dec_init convenience macro
* instead of this function directly, to ensure that the ABI
* version number parameter is properly initialized.
*
* \param[in] ctx Pointer to this instance's context.
* \param[in] iface Pointer to the algorithm interface to use.
* \param[in] ver ABI version number. Must be set to
* VPX_DECODER_ABI_VERSION
* \retval #VPX_DEC_OK
* The decoder algorithm initialized.
* \retval #VPX_DEC_MEM_ERROR
* Memory allocation failed.
*/
vpx_dec_err_t vpx_dec_init_ver(
vpx_dec_ctx_t *ctx,
vpx_dec_iface_t *iface,
int ver) DEPRECATED;
#define vpx_dec_init(ctx, iface) \
vpx_dec_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
/*!\brief Destroy a decoder instance
*
* Destroys a decoder context, freeing any associated memory
* buffers.
*
* \param[in] ctx Pointer to this instance's context
*
* \retval #VPX_DEC_OK
* The decoder algorithm initialized.
* \retval #VPX_DEC_MEM_ERROR
* Memory allocation failed.
*/
vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx) DEPRECATED;
/*!\brief Get the capabilities of an algorithm.
*
* Retrieves the capabilities bitfield from the algorithm's
* interface.
*
* \param[in] iface Pointer to the algorithm interface
*
*/
vpx_dec_caps_t vpx_dec_get_caps(
vpx_dec_iface_t *iface) DEPRECATED;
/*!\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 algorithm 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_DEC_OK
* Bitstream is parsable and stream information updated
*/
vpx_dec_err_t vpx_dec_peek_stream_info(
vpx_dec_iface_t *iface,
const uint8_t *data,
unsigned int data_sz,
vpx_dec_stream_info_t *si) DEPRECATED;
/*!\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_DEC_OK
* Bitstream is parsable and stream information updated
*/
vpx_dec_err_t vpx_dec_get_stream_info(
vpx_dec_ctx_t *ctx,
vpx_dec_stream_info_t *si) DEPRECATED;
/*!\brief Control algorithm
*
* 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 wrapper function dispatches the request to the helper
* function associated with the given ctrl_id. It tries to call
* this function transparently, but will return #VPX_DEC_ERROR if
* the request could not be dispatched.
*
* \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_DEC_OK
* The control request was processed.
* \retval #VPX_DEC_ERROR
* The control request was not processed.
* \retval #VPX_DEC_INVALID_PARAM
* The data was not valid.
*/
vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx,
int ctrl_id,
void *data) DEPRECATED;
/*!\brief Decode data
*
* Processes a buffer of coded data. If the processing results in
* a new decoded frame becoming available, #VPX_DEC_CB_PUT_SLICE
* and #VPX_DEC_CB_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_DEC_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] rel_pts PTS relative to the previous frame, in
* us. If unknown or unavailable, set to
* zero.
*
* \return Returns #VPX_DEC_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_dec_err_t for recoverability
* capabilities.
*/
vpx_dec_err_t vpx_dec_decode(
vpx_dec_ctx_t *ctx,
uint8_t *data,
unsigned int data_sz,
void *user_priv,
int rel_pts) DEPRECATED;
/*!\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_dec_decode call, and remains valid until the next call
* to vpx_dec_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_dec_get_frame(vpx_dec_ctx_t *ctx,
vpx_dec_iter_t *iter) DEPRECATED;
/*!\defgroup cap_put_frame Frame-Based Decoding Functions
*
* The following functions are required to be implemented for all
* decoders that advertise the VPX_DEC_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_DEC_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_dec_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_DEC_OK
* Callback successfully registered.
* \retval #VPX_DEC_ERROR
* Decoder context not initialized, or algorithm not capable
* of posting slice completion.
*/
vpx_dec_err_t vpx_dec_register_put_frame_cb(
vpx_dec_ctx_t *ctx,
vpx_dec_put_frame_cb_fn_t cb,
void *user_priv) DEPRECATED;
/*!@} - 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_DEC_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_DEC_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. The
*/
typedef void (*vpx_dec_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_DEC_OK
* Callback successfully registered.
* \retval #VPX_DEC_ERROR
* Decoder context not initialized, or algorithm not capable
* of posting slice completion.
*/
vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx,
vpx_dec_put_slice_cb_fn_t cb,
void *user_priv) DEPRECATED;
/*!@} - end defgroup cap_put_slice*/
/*!\defgroup cap_xma External Memory Allocation Functions
*
* The following functions are required to be implemented for all
* decoders that advertise the VPX_DEC_CAP_XMA capability.
* Calling these functions for codecs that don't advertise this
* capability will result in an error code being returned,
* usually VPX_DEC_ERROR
* @{
*/
/*!\brief Memory Map Entry
*
* This structure is used to contain the properties of a memory
* segment. It is populated by the decoder in the request phase,
* and by the calling application once the requested allocation
* has been performed.
*/
#if 1
#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by
allocation */
#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be
readable */
#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if
available */
typedef struct vpx_codec_mmap vpx_dec_mmap_t;
#else
typedef struct vpx_dec_mmap
{
/*
* The following members are set by the codec when requesting
* a segment
*/
unsigned int id; /**< identifier for the segment's
contents */
unsigned long sz; /**< size of the segment, in bytes */
unsigned int align; /**< required alignment of the
segment, in bytes */
unsigned int flags; /**< bitfield containing segment
properties */
#define VPX_DEC_MEM_ZERO 0x1 /**< Segment must be zeroed by
allocation */
#define VPX_DEC_MEM_WRONLY 0x2 /**< Segment need not be
readable */
#define VPX_DEC_MEM_FAST 0x4 /**< Place in fast memory, if
available */
/* The following members are to be filled in by the
* allocation function */
void *base; /**< pointer to the allocated
segment */
void (*dtor)(struct vpx_dec_mmap *map); /**< destructor to
call */
void *priv; /**< allocator private storage */
} vpx_dec_mmap_t;
#endif
/*!\brief Initialize a decoder instance in external allocation
* mode
*
* Initializes a decoder context using the given interface.
* Applications should call the vpx_dec_xma_init convenience
* macro instead of this function directly, to ensure that the
* ABI version number parameter is properly initialized.
*
* \param[in] ctx Pointer to this instance's context.
* \param[in] iface Pointer to the algorithm interface to
* use.
* \param[in] ver ABI version number. Must be set to
* VPX_DECODER_ABI_VERSION
* \retval #VPX_DEC_OK
* The decoder algorithm initialized.
* \retval #VPX_DEC_ERROR
* Decoder does not support XMA mode.
*/
vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx,
vpx_dec_iface_t *iface,
int ver) DEPRECATED;
#define vpx_dec_xma_init(ctx, iface) \
vpx_dec_xma_init_ver(ctx, iface, VPX_DECODER_ABI_VERSION)
/*!\brief Iterate over the list of segments to allocate.
*
* Iterates over a list of the segments to allocate. The iterator
* storage should be initialized to NULL to start the iteration.
* Iteration is complete when this function returns
* VPX_DEC_LIST_END. The amount of memory needed to allocate is
* dependent upon the size of the encoded stream. This means that
* the stream info structure must be known at allocation time. It
* can be populated with the vpx_dec_peek_stream_info() function.
* In cases where the stream to be decoded is not available at
* allocation time, a fixed size must be requested. The decoder
* will not be able to decode streams larger than the size used
* at allocation time.
*
* \param[in] ctx Pointer to this instance's context.
* \param[out] mmap Pointer to the memory map entry to
* populate.
* \param[in] si Pointer to the stream info.
* \param[in out] iter Iterator storage, initialized to NULL
*
* \retval #VPX_DEC_OK
* The memory map entry was populated.
* \retval #VPX_DEC_ERROR
* Decoder does not support XMA mode.
* \retval #VPX_DEC_MEM_ERROR
* Unable to determine segment size from stream info.
*/
vpx_dec_err_t vpx_dec_get_mem_map(
vpx_dec_ctx_t *ctx,
vpx_dec_mmap_t *mmap,
const vpx_dec_stream_info_t *si,
vpx_dec_iter_t *iter) DEPRECATED;
/*!\brief Identify allocated segments to decoder instance
*
* Stores a list of allocated segments in the decoder. Segments
* \ref MUST be passed in the order they are read from
* vpx_dec_get_mem_map(), but may be passed in groups of any
* size. Segments \ref MUST be set only once. The allocation
* function \ref MUST ensure that the vpx_dec_mmap_t::base member
* is non-NULL. If the segment requires cleanup handling (e.g.,
* calling free() or close()) then the vpx_dec_mmap_t::dtor
* member \ref MUST be populated.
*
* \param[in] ctx Pointer to this instance's context.
* \param[in] mmaps Pointer to the first memory map
* entry in the list.
* \param[in] num_maps Number of entries being set at this
* time
*
* \retval #VPX_DEC_OK
* The segment was stored in the decoder context.
* \retval #VPX_DEC_ERROR
* Decoder does not support XMA mode.
* \retval #VPX_DEC_MEM_ERROR
* Segment base address was not set, or segment was already
* stored.
*/
vpx_dec_err_t vpx_dec_set_mem_map(
vpx_dec_ctx_t *ctx,
vpx_dec_mmap_t *mmaps,
unsigned int num_maps) DEPRECATED;
/*!@} - end defgroup cap_xma*/
/*!@} - end defgroup decoder*/
#endif
#ifdef __cplusplus
}
#endif
---- End code block ----------------------------------------
20.22. vpx_image.c
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The WebM 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 <stdlib.h>
#include <string.h>
#include "vpx/vpx_image.h"
static vpx_image_t *img_alloc_helper(vpx_image_t *img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int stride_align,
unsigned char *img_data)
{
unsigned int h, w, s, xcs, ycs, bps;
int align;
/* Treat align==0 like align==1 */
if (!stride_align)
stride_align = 1;
/* Validate alignment (must be power of 2) */
if (stride_align & (stride_align - 1))
goto fail;
/* Get sample size for this format */
switch (fmt)
{
case VPX_IMG_FMT_RGB32:
case VPX_IMG_FMT_RGB32_LE:
case VPX_IMG_FMT_ARGB:
case VPX_IMG_FMT_ARGB_LE:
bps = 32;
break;
case VPX_IMG_FMT_RGB24:
case VPX_IMG_FMT_BGR24:
bps = 24;
break;
case VPX_IMG_FMT_RGB565:
case VPX_IMG_FMT_RGB565_LE:
case VPX_IMG_FMT_RGB555:
case VPX_IMG_FMT_RGB555_LE:
case VPX_IMG_FMT_UYVY:
case VPX_IMG_FMT_YUY2:
case VPX_IMG_FMT_YVYU:
bps = 16;
break;
case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_YV12:
case VPX_IMG_FMT_VPXI420:
case VPX_IMG_FMT_VPXYV12:
bps = 12;
break;
default:
bps = 16;
break;
}
/* Get chroma shift values for this format */
switch (fmt)
{
case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_YV12:
case VPX_IMG_FMT_VPXI420:
case VPX_IMG_FMT_VPXYV12:
xcs = 1;
break;
default:
xcs = 0;
break;
}
switch (fmt)
{
case VPX_IMG_FMT_I420:
case VPX_IMG_FMT_YV12:
case VPX_IMG_FMT_VPXI420:
case VPX_IMG_FMT_VPXYV12:
ycs = 1;
break;
default:
ycs = 0;
break;
}
/* Calculate storage sizes given the chroma subsampling */
align = (1 << xcs) - 1;
w = (d_w + align) & ~align;
align = (1 << ycs) - 1;
h = (d_h + align) & ~align;
s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8;
s = (s + stride_align - 1) & ~(stride_align - 1);
/* Allocate the new image */
if (!img)
{
img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));
if (!img)
goto fail;
img->self_allocd = 1;
}
else
{
memset(img, 0, sizeof(vpx_image_t));
}
img->img_data = img_data;
if (!img_data)
{
img->img_data = malloc((fmt & VPX_IMG_FMT_PLANAR) ?
h * w * bps / 8 : h * s);
img->img_data_owner = 1;
}
if (!img->img_data)
goto fail;
img->fmt = fmt;
img->w = w;
img->h = h;
img->x_chroma_shift = xcs;
img->y_chroma_shift = ycs;
img->bps = bps;
/* Calculate strides */
img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s;
img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs;
/* Default viewport to entire image */
if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
return img;
fail:
vpx_img_free(img);
return NULL;
}
vpx_image_t *vpx_img_alloc(vpx_image_t *img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int stride_align)
{
return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
}
vpx_image_t *vpx_img_wrap(vpx_image_t *img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int stride_align,
unsigned char *img_data)
{
return img_alloc_helper(img, fmt, d_w, d_h, stride_align,
img_data);
}
int vpx_img_set_rect(vpx_image_t *img,
unsigned int x,
unsigned int y,
unsigned int w,
unsigned int h)
{
unsigned char *data;
if (x + w <= img->w && y + h <= img->h)
{
img->d_w = w;
img->d_h = h;
/* Calculate plane pointers */
if (!(img->fmt & VPX_IMG_FMT_PLANAR))
{
img->planes[VPX_PLANE_PACKED] =
img->img_data + x * img->bps / 8 + y *
img->stride[VPX_PLANE_PACKED];
}
else
{
data = img->img_data;
if (img->fmt & VPX_IMG_FMT_HAS_ALPHA)
{
img->planes[VPX_PLANE_ALPHA] =
data + x + y * img->stride[VPX_PLANE_ALPHA];
data += img->h * img->stride[VPX_PLANE_ALPHA];
}
img->planes[VPX_PLANE_Y] =
data + x + y * img->stride[VPX_PLANE_Y];
data += img->h * img->stride[VPX_PLANE_Y];
if (!(img->fmt & VPX_IMG_FMT_UV_FLIP))
{
img->planes[VPX_PLANE_U] = data
+ (x >> img->x_chroma_shift)
+ (y >> img->y_chroma_shift) *
img->stride[VPX_PLANE_U];
data += (img->h >> img->y_chroma_shift) *
img->stride[VPX_PLANE_U];
img->planes[VPX_PLANE_V] = data
+ (x >> img->x_chroma_shift)
+ (y >> img->y_chroma_shift) *
img->stride[VPX_PLANE_V];
}
else
{
img->planes[VPX_PLANE_V] = data
+ (x >> img->x_chroma_shift)
+ (y >> img->y_chroma_shift) *
img->stride[VPX_PLANE_V];
data += (img->h >> img->y_chroma_shift) *
img->stride[VPX_PLANE_V];
img->planes[VPX_PLANE_U] = data
+ (x >> img->x_chroma_shift)
+ (y >> img->y_chroma_shift) *
img->stride[VPX_PLANE_U];
}
}
return 0;
}
return -1;
}
void vpx_img_flip(vpx_image_t *img)
{
/* Note: In the calculation pointer adjustment calculation, we
* want the rhs to be promoted to a signed type. Section 6.3.1.8
* of the ISO C99 standard indicates that if the adjustment
* parameter is unsigned, the stride parameter will be promoted
* to unsigned, causing errors when the lhs is a larger type than
* the rhs.
*/
img->planes[VPX_PLANE_Y] += (signed)
(img->d_h - 1) * img->stride[VPX_PLANE_Y];
img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y];
img->planes[VPX_PLANE_U] += (signed)
((img->d_h >> img->y_chroma_shift) - 1)
* img->stride[VPX_PLANE_U];
img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U];
img->planes[VPX_PLANE_V] += (signed)
((img->d_h >> img->y_chroma_shift) - 1) *
img->stride[VPX_PLANE_V];
img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V];
img->planes[VPX_PLANE_ALPHA] += (signed)
(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA];
img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA];
}
void vpx_img_free(vpx_image_t *img)
{
if (img)
{
if (img->img_data && img->img_data_owner)
free(img->img_data);
if (img->self_allocd)
free(img);
}
}
---- End code block ----------------------------------------
20.23. vpx_image.h
---- Begin code block --------------------------------------
/*
* Copyright (c) 2010 The WebM 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
* \brief Describes the vpx image descriptor and associated
* operations
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VPX_IMAGE_H
#define VPX_IMAGE_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_IMAGE_ABI_VERSION (1) /**<\hideinitializer*/
#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar
format */
#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U plane
in memory */
#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel
component */
/*!\brief List of supported image formats */
typedef enum vpx_img_fmt {
VPX_IMG_FMT_NONE,
VPX_IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */
VPX_IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */
VPX_IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */
VPX_IMGFMT_RGB555, /**< 16 bit per pixel, 555 */
VPX_IMG_FMT_UYVY, /**< UYVY packed YUV */
VPX_IMG_FMT_YUY2, /**< YUYV packed YUV */
VPX_IMG_FMT_YVYU, /**< YVYU packed YUV */
VPX_IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */
VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
VPX_IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */
VPX_IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */
VPX_IMG_FMT_RGB565_LE, /**< 16 bit per pixel,
gggbbbbb rrrrrggg */
VPX_IMG_FMT_RGB555_LE, /**< 16 bit per pixel,
gggbbbbb 0rrrrrgg */
VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR |
VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2,
VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR |
VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with
vpx color space */
VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4 /** < planar
4:2:0 format with vpx color space */
}
vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
/** \deprecated Use #VPX_IMG_FMT_PLANAR */
#define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR
/** \deprecated Use #VPX_IMG_FMT_UV_FLIP */
#define IMG_FMT_UV_FLIP VPX_IMG_FMT_UV_FLIP
/** \deprecated Use #VPX_IMG_FMT_HAS_ALPHA */
#define IMG_FMT_HAS_ALPHA VPX_IMG_FMT_HAS_ALPHA
/*!\brief Deprecated list of supported image formats
* \deprecated New code should use #vpx_img_fmt
*/
#define img_fmt vpx_img_fmt
/*!\brief alias for enum img_fmt.
* \deprecated New code should use #vpx_img_fmt_t
*/
#define img_fmt_t vpx_img_fmt_t
/** \deprecated Use #VPX_IMG_FMT_NONE */
#define IMG_FMT_NONE VPX_IMG_FMT_NONE
/** \deprecated Use #VPX_IMG_FMT_RGB24 */
#define IMG_FMT_RGB24 VPX_IMG_FMT_RGB24
/** \deprecated Use #VPX_IMG_FMT_RGB32 */
#define IMG_FMT_RGB32 VPX_IMG_FMT_RGB32
/** \deprecated Use #VPX_IMG_FMT_RGB565 */
#define IMG_FMT_RGB565 VPX_IMG_FMT_RGB565
/** \deprecated Use #VPX_IMG_FMT_RGB555 */
#define IMG_FMT_RGB555 VPX_IMG_FMT_RGB555
/** \deprecated Use #VPX_IMG_FMT_UYVY */
#define IMG_FMT_UYVY VPX_IMG_FMT_UYVY
/** \deprecated Use #VPX_IMG_FMT_YUY2 */
#define IMG_FMT_YUY2 VPX_IMG_FMT_YUY2
/** \deprecated Use #VPX_IMG_FMT_YVYU */
#define IMG_FMT_YVYU VPX_IMG_FMT_YVYU
/** \deprecated Use #VPX_IMG_FMT_BGR24 */
#define IMG_FMT_BGR24 VPX_IMG_FMT_BGR24
/**< \deprecated Use #VPX_IMG_FMT_RGB32_LE */
#define IMG_FMT_RGB32_LE VPX_IMG_FMT_RGB32_LE
/** \deprecated Use #VPX_IMG_FMT_ARGB */
#define IMG_FMT_ARGB VPX_IMG_FMT_ARGB
/** \deprecated Use #VPX_IMG_FMT_ARGB_LE */
#define IMG_FMT_ARGB_LE VPX_IMG_FMT_ARGB_LE
/** \deprecated Use #VPX_IMG_FMT_RGB565_LE */
#define IMG_FMT_RGB565_LE VPX_IMG_FMT_RGB565_LE
/** \deprecated Use #VPX_IMG_FMT_RGB555_LE */
#define IMG_FMT_RGB555_LE VPX_IMG_FMT_RGB555_LE
/** \deprecated Use #VPX_IMG_FMT_YV12 */
#define IMG_FMT_YV12 VPX_IMG_FMT_YV12
/** \deprecated Use #VPX_IMG_FMT_I420 */
#define IMG_FMT_I420 VPX_IMG_FMT_I420
/** \deprecated Use #VPX_IMG_FMT_VPXYV12 */
#define IMG_FMT_VPXYV12 VPX_IMG_FMT_VPXYV12
/** \deprecated Use #VPX_IMG_FMT_VPXI420 */
#define IMG_FMT_VPXI420 VPX_IMG_FMT_VPXI420
#endif /* VPX_CODEC_DISABLE_COMPAT */
/**\brief Image Descriptor */
typedef struct vpx_image
{
vpx_img_fmt_t fmt; /**< Image Format */
/* Image storage dimensions */
unsigned int w; /**< Stored image width */
unsigned int h; /**< Stored image height */
/* Image display dimensions */
unsigned int d_w; /**< Displayed image width */
unsigned int d_h; /**< Displayed image height */
/* Chroma subsampling info */
unsigned int x_chroma_shift; /**< subsampling order, X */
unsigned int y_chroma_shift; /**< subsampling order, Y */
/* Image data pointers. */
#define VPX_PLANE_PACKED 0 /**< To be used for all packed formats */
#define VPX_PLANE_Y 0 /**< Y (Luminance) plane */
#define VPX_PLANE_U 1 /**< U (Chroma) plane */
#define VPX_PLANE_V 2 /**< V (Chroma) plane */
#define VPX_PLANE_ALPHA 3 /**< A (Transparency) plane */
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
#define PLANE_PACKED VPX_PLANE_PACKED
#define PLANE_Y VPX_PLANE_Y
#define PLANE_U VPX_PLANE_U
#define PLANE_V VPX_PLANE_V
#define PLANE_ALPHA VPX_PLANE_ALPHA
#endif
unsigned char *planes[4]; /**< pointer to the top left pixel
q for each plane */
int stride[4]; /**< stride between rows for each plane */
int bps; /**< bits per sample (for packed formats) */
/* The following member may be set by the application to
* associate data with this image.
*/
void *user_priv; /**< may be set by the application to
associate data with this image. */
/* The following members should be treated as private. */
unsigned char *img_data; /**< private */
int img_data_owner; /**< private */
int self_allocd; /**< private */
} vpx_image_t; /**< alias for struct vpx_image */
/**\brief Representation of a rectangle on a surface */
typedef struct vpx_image_rect
{
unsigned int x; /**< leftmost column */
unsigned int y; /**< topmost row */
unsigned int w; /**< width */
unsigned int h; /**< height */
} vpx_image_rect_t; /**< alias for struct vpx_image_rect */
/*!\brief Open a descriptor, allocating storage for the
* underlying image
*
* Returns a descriptor for storing an image of the given format.
* The storage for the descriptor is allocated on the heap.
*
* \param[in] img Pointer to storage for descriptor. If
* this parameter is NULL, the storage
* for the descriptor will be allocated
* on the heap.
* \param[in] fmt Format for the image
* \param[in] d_w Width of the image
* \param[in] d_h Height of the image
* \param[in] align Alignment, in bytes, of each row in
* the image.
*
* \return Returns a pointer to the initialized image descriptor.
* If the img parameter is non-null, the value of the img
* parameter will be returned.
*/
vpx_image_t *vpx_img_alloc(vpx_image_t *img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int align);
/*!\brief Open a descriptor, using existing storage for the
* underlying image
*
* Returns a descriptor for storing an image of the given format.
* The storage for descriptor has been allocated elsewhere, and a
* descriptor is desired to "wrap" that storage.
*
* \param[in] img Pointer to storage for descriptor. If
* this parameter is NULL, the storage
* for the descriptor will be
* allocated on the heap.
* \param[in] fmt Format for the image
* \param[in] d_w Width of the image
* \param[in] d_h Height of the image
* \param[in] align Alignment, in bytes, of each row in
* the image.
* \param[in] img_data Storage to use for the image
*
* \return Returns a pointer to the initialized image descriptor.
* If the img parameter is non-null, the value of the img
* parameter will be returned.
*/
vpx_image_t *vpx_img_wrap(vpx_image_t *img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int align,
unsigned char *img_data);
/*!\brief Set the rectangle identifying the displayed portion of
* the image
*
* Updates the displayed rectangle (aka viewport) on the image
* surface to match the specified coordinates and size.
*
* \param[in] img Image descriptor
* \param[in] x leftmost column
* \param[in] y topmost row
* \param[in] w width
* \param[in] h height
*
* \return 0 if the requested rectangle is valid, nonzero
* otherwise.
*/
int vpx_img_set_rect(vpx_image_t *img,
unsigned int x,
unsigned int y,
unsigned int w,
unsigned int h);
/*!\brief Flip the image vertically (top for bottom)
*
* Adjusts the image descriptor's pointers and strides to make
* the image be referenced upside-down.
*
* \param[in] img Image descriptor
*/
void vpx_img_flip(vpx_image_t *img);
/*!\brief Close an image descriptor
*
* Frees all allocated storage associated with an image
* descriptor.
*
* \param[in] img Image descriptor
*/
void vpx_img_free(vpx_image_t *img);
#endif
#ifdef __cplusplus
}
#endif
---- End code block ----------------------------------------
20.24. vpx_integer.h
---- Begin code block -------------------------------------- ---- Begin code block --------------------------------------
/* /*
* Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be * tree. An additional intellectual property rights grant can be
* found in the file PATENTS. All contributing project authors may * found in the file PATENTS. All contributing project authors may
skipping to change at page 285, line 4 skipping to change at page 303, line 39
#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) #if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#endif #endif
---- End code block ---------------------------------------- ---- End code block ----------------------------------------
20.22. AUTHORS 20.25. AUTHORS
Aaron Watry <awatry@gmail.com> Aaron Watry <awatry@gmail.com>
Adrian Grange <agrange@google.com> Adrian Grange <agrange@google.com>
Alex Converse <alex.converse@gmail.com> Alex Converse <alex.converse@gmail.com>
Andoni Morales Alastruey <ylatuya@gmail.com> Andoni Morales Alastruey <ylatuya@gmail.com>
Andres Mejia <mcitadel@gmail.com> Andres Mejia <mcitadel@gmail.com>
Attila Nagy <attilanagy@google.com> Attila Nagy <attilanagy@google.com>
Fabio Pedretti <fabio.ped@libero.it> Fabio Pedretti <fabio.ped@libero.it>
Frank Galligan <fgalligan@google.com> Frank Galligan <fgalligan@google.com>
Fredrik Soederquist <fs@opera.com> Fredrik Soederquist <fs@opera.com>
skipping to change at page 286, line 44 skipping to change at page 305, line 32
Yaowu Xu <yaowu@google.com> Yaowu Xu <yaowu@google.com>
Yunqing Wang <yunqingwang@google.com> Yunqing Wang <yunqingwang@google.com>
Google Inc. Google Inc.
The Mozilla Foundation The Mozilla Foundation
The Xiph.Org Foundation The Xiph.Org Foundation
20.23. LICENSE 20.26. LICENSE
Copyright (c) 2010, Google Inc. All rights reserved. Copyright (c) 2010, Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
o Redistributions of source code must retain the above copyright o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
skipping to change at page 287, line 30 skipping to change at page 306, line 18
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
20.24. PATENTS 20.27. PATENTS
Additional IP Rights Grant (Patents) Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by "This implementation" means the copyrightable works distributed by
Google as part of the WebM Project. Google as part of the WebM Project.
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, transfer, and otherwise run, modify and propagate the import, transfer, and otherwise run, modify and propagate the
skipping to change at page 289, line 5 skipping to change at page 307, line 5
modification of this implementation. If you or your agent or modification of this implementation. If you or your agent or
exclusive licensee institute or order or agree to the institution of exclusive licensee institute or order or agree to the institution of
patent litigation against any entity (including a cross-claim or patent litigation against any entity (including a cross-claim or
counterclaim in a lawsuit) alleging that this implementation of VP8 counterclaim in a lawsuit) alleging that this implementation of VP8
or any code incorporated within this implementation of VP8 or any code incorporated within this implementation of VP8
constitutes direct or contributory patent infringement, or inducement constitutes direct or contributory patent infringement, or inducement
of patent infringement, then any patent rights granted to you under of patent infringement, then any patent rights granted to you under
this License for this implementation of VP8 shall terminate as of the this License for this implementation of VP8 shall terminate as of the
date such litigation is filed. date such litigation is filed.
21. References 21. Security Considerations
A VP8 decoder should take appropriate security considerations into
account, as outlined in [RFC4732] and [RFC3552]. It is extremely
important that a decoder be robust against malicious payloads.
Malicious payloads must not cause the decoder to overrun its
allocated memory or to consume inordinate resources. Although
encoder issues are typically rarer, the same applies to an encoder.
Malicious stream data must not cause the encoder to misbehave, as
this might allow an attacker access to transcoding gateways.
22. IANA Considerations
This document has no actions for IANA.
23. Informative References
[Bell] Bell, T., Cleary, J., and I. Witten, "Text Compression",
1990.
[ITU-R_BT.601] [ITU-R_BT.601]
International Telecommunication Union, "ITU BT.601: Studio International Telecommunication Union, "ITU BT.601: Studio
encoding parameters of digital television for standard 4:3 encoding parameters of digital television for standard 4:3
and wide screen 16:9 aspect ratios", January 2007. and wide screen 16:9 aspect ratios", January 2007.
[Bell] Bell, T., Cleary, J., and I. Witten, "Text Compression",
1990.
[Kernighan] [Kernighan]
Kernighan, B. and D. Ritchie, "The C Programming Language Kernighan, B. and D. Ritchie, "The C Programming Language
(2nd edition)", April 1988. (2nd edition)", April 1988.
[Loeffler] [Loeffler]
Loeffler, C., Ligtenberg , A., and G. Moschytz, "Practical Loeffler, C., Ligtenberg , A., and G. Moschytz, "Practical
Fast 1-D DCT Algorithms with 11 Multiplications", Fast 1-D DCT Algorithms with 11 Multiplications",
May 1989. May 1989.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC3552] Rescorla, E. and B. Korver, "Guidelines for Writing RFC
Text on Security Considerations", BCP 72, RFC 3552,
July 2003.
[RFC3979] Bradner, S., "Intellectual Property Rights in IETF
Technology", BCP 79, RFC 3979, March 2005.
[RFC4732] Handley, M., Rescorla, E., and IAB, "Internet Denial-of-
Service Considerations", RFC 4732, December 2006.
[RFC5378] Bradner, S. and J. Contreras, "Rights Contributors Provide
to the IETF Trust", BCP 78, RFC 5378, November 2008.
[Shannon] Shannon, C., "A Mathematical Theory of Communication", [Shannon] Shannon, C., "A Mathematical Theory of Communication",
Bell System Technical Journal Vol. 27, pp. 379-423, 623- Bell System Technical Journal Vol. 27, pp. 379-423, 623-
656, July, October 1948. 656, July, October 1948.
Authors' Addresses Authors' Addresses
James Bankoski James Bankoski
Google Inc. Google Inc.
Email: jimbankoski@google.com Email: jimbankoski@google.com
 End of changes. 488 change blocks. 
3648 lines changed or deleted 4534 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/