You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.8KB

  1. /*
  2. * Lagarith range decoder
  3. * Copyright (c) 2009 Nathan Caldwell <saintdev (at) gmail.com>
  4. * Copyright (c) 2009 David Conrad
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * Libav is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. /**
  23. * @file
  24. * Lagarith range decoder
  25. * @author Nathan Caldwell
  26. * @author David Conrad
  27. */
  28. #ifndef AVCODEC_LAGARITHRAC_H
  29. #define AVCODEC_LAGARITHRAC_H
  30. #include <stdint.h>
  31. #include "libavutil/common.h"
  32. #include "libavutil/intreadwrite.h"
  33. #include "avcodec.h"
  34. #include "bitstream.h"
  35. typedef struct lag_rac {
  36. AVCodecContext *avctx;
  37. unsigned low;
  38. unsigned range;
  39. unsigned scale; /**< Number of bits of precision in range. */
  40. unsigned hash_shift; /**< Number of bits to shift to calculate hash for radix search. */
  41. const uint8_t *bytestream_start; /**< Start of input bytestream. */
  42. const uint8_t *bytestream; /**< Current position in input bytestream. */
  43. const uint8_t *bytestream_end; /**< End position of input bytestream. */
  44. uint32_t prob[258]; /**< Table of cumulative probability for each symbol. */
  45. uint8_t range_hash[256]; /**< Hash table mapping upper byte to approximate symbol. */
  46. } lag_rac;
  47. void ff_lag_rac_init(lag_rac *l, BitstreamContext *bc, int length);
  48. /* TODO: Optimize */
  49. static inline void lag_rac_refill(lag_rac *l)
  50. {
  51. while (l->range <= 0x800000) {
  52. l->low <<= 8;
  53. l->range <<= 8;
  54. l->low |= 0xff & (AV_RB16(l->bytestream) >> 1);
  55. if (l->bytestream < l->bytestream_end)
  56. l->bytestream++;
  57. }
  58. }
  59. /**
  60. * Decode a single byte from the compressed plane described by *l.
  61. * @param l pointer to lag_rac for the current plane
  62. * @return next byte of decoded data
  63. */
  64. static inline uint8_t lag_get_rac(lag_rac *l)
  65. {
  66. unsigned range_scaled, low_scaled, div;
  67. int val;
  68. uint8_t shift;
  69. lag_rac_refill(l);
  70. range_scaled = l->range >> l->scale;
  71. if (l->low < range_scaled * l->prob[255]) {
  72. /* val = 0 is frequent enough to deserve a shortcut */
  73. if (l->low < range_scaled * l->prob[1]) {
  74. val = 0;
  75. } else {
  76. /* FIXME __builtin_clz is ~20% faster here, but not allowed in generic code. */
  77. shift = 30 - av_log2(range_scaled);
  78. div = ((range_scaled << shift) + (1 << 23) - 1) >> 23;
  79. /* low>>24 ensures that any cases too big for exact FASTDIV are
  80. * under- rather than over-estimated
  81. */
  82. low_scaled = FASTDIV(l->low - (l->low >> 24), div);
  83. shift -= l->hash_shift;
  84. shift &= 31;
  85. low_scaled = (low_scaled << shift) | (low_scaled >> (32 - shift));
  86. /* low_scaled is now a lower bound of low/range_scaled */
  87. val = l->range_hash[(uint8_t) low_scaled];
  88. while (l->low >= range_scaled * l->prob[val + 1])
  89. val++;
  90. }
  91. l->range = range_scaled * (l->prob[val + 1] - l->prob[val]);
  92. } else {
  93. val = 255;
  94. l->range -= range_scaled * l->prob[255];
  95. }
  96. if (!l->range)
  97. l->range = 0x80;
  98. l->low -= range_scaled * l->prob[val];
  99. return val;
  100. }
  101. #endif /* AVCODEC_LAGARITHRAC_H */