blob: 9c6ef75b69e5836475181b03a3eee8507b86aa83
1 | /* |
2 | * Range coder |
3 | * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * Range coder. |
25 | * based upon |
26 | * "Range encoding: an algorithm for removing redundancy from a digitised |
27 | * message. |
28 | * G. N. N. Martin Presented in March 1979 to the Video & |
29 | * Data Recording Conference, |
30 | * IBM UK Scientific Center held in Southampton July 24-27 1979." |
31 | */ |
32 | |
33 | #include <string.h> |
34 | |
35 | #include "libavutil/attributes.h" |
36 | #include "libavutil/avassert.h" |
37 | #include "libavutil/intreadwrite.h" |
38 | |
39 | #include "avcodec.h" |
40 | #include "rangecoder.h" |
41 | |
42 | av_cold void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size) |
43 | { |
44 | c->bytestream_start = |
45 | c->bytestream = buf; |
46 | c->bytestream_end = buf + buf_size; |
47 | c->low = 0; |
48 | c->range = 0xFF00; |
49 | c->outstanding_count = 0; |
50 | c->outstanding_byte = -1; |
51 | } |
52 | |
53 | av_cold void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, |
54 | int buf_size) |
55 | { |
56 | /* cast to avoid compiler warning */ |
57 | ff_init_range_encoder(c, (uint8_t *)buf, buf_size); |
58 | |
59 | c->low = AV_RB16(c->bytestream); |
60 | c->bytestream += 2; |
61 | } |
62 | |
63 | void ff_build_rac_states(RangeCoder *c, int factor, int max_p) |
64 | { |
65 | const int64_t one = 1LL << 32; |
66 | int64_t p; |
67 | int last_p8, p8, i; |
68 | |
69 | memset(c->zero_state, 0, sizeof(c->zero_state)); |
70 | memset(c->one_state, 0, sizeof(c->one_state)); |
71 | |
72 | last_p8 = 0; |
73 | p = one / 2; |
74 | for (i = 0; i < 128; i++) { |
75 | p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one |
76 | if (p8 <= last_p8) |
77 | p8 = last_p8 + 1; |
78 | if (last_p8 && last_p8 < 256 && p8 <= max_p) |
79 | c->one_state[last_p8] = p8; |
80 | |
81 | p += ((one - p) * factor + one / 2) >> 32; |
82 | last_p8 = p8; |
83 | } |
84 | |
85 | for (i = 256 - max_p; i <= max_p; i++) { |
86 | if (c->one_state[i]) |
87 | continue; |
88 | |
89 | p = (i * one + 128) >> 8; |
90 | p += ((one - p) * factor + one / 2) >> 32; |
91 | p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one |
92 | if (p8 <= i) |
93 | p8 = i + 1; |
94 | if (p8 > max_p) |
95 | p8 = max_p; |
96 | c->one_state[i] = p8; |
97 | } |
98 | |
99 | for (i = 1; i < 255; i++) |
100 | c->zero_state[i] = 256 - c->one_state[256 - i]; |
101 | } |
102 | |
103 | /* Return the number of bytes written. */ |
104 | int ff_rac_terminate(RangeCoder *c) |
105 | { |
106 | c->range = 0xFF; |
107 | c->low += 0xFF; |
108 | renorm_encoder(c); |
109 | c->range = 0xFF; |
110 | renorm_encoder(c); |
111 | |
112 | av_assert1(c->low == 0); |
113 | av_assert1(c->range >= 0x100); |
114 | |
115 | return c->bytestream - c->bytestream_start; |
116 | } |
117 |