672a19aa |
/*
* Range coder
* Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
* |
b78e7197 |
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or |
672a19aa |
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either |
b78e7197 |
* version 2.1 of the License, or (at your option) any later version. |
672a19aa |
* |
b78e7197 |
* FFmpeg is distributed in the hope that it will be useful, |
672a19aa |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public |
b78e7197 |
* License along with FFmpeg; if not, write to the Free Software |
5509bffa |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
672a19aa |
*/ |
115329f1 |
|
672a19aa |
/** |
ba87f080 |
* @file |
672a19aa |
* Range coder.
* based upon
* "Range encoding: an algorithm for removing redundancy from a digitised
* message.
* G. N. N. Martin Presented in March 1979 to the Video &
* Data Recording Conference,
* IBM UK Scientific Center held in Southampton July 24-27 1979."
*/
#include <string.h>
|
6fee1b90 |
#include "libavutil/attributes.h" |
a5ca3203 |
#include "libavutil/avassert.h" |
abe9adfb |
#include "libavutil/intreadwrite.h"
|
672a19aa |
#include "avcodec.h"
#include "rangecoder.h"
|
6fee1b90 |
av_cold void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size) |
90558e84 |
{
c->bytestream_start =
c->bytestream = buf;
c->bytestream_end = buf + buf_size;
c->low = 0;
c->range = 0xFF00;
c->outstanding_count = 0;
c->outstanding_byte = -1; |
672a19aa |
}
|
6fee1b90 |
av_cold void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf,
int buf_size) |
90558e84 |
{ |
79396ac6 |
/* cast to avoid compiler warning */ |
90558e84 |
ff_init_range_encoder(c, (uint8_t *)buf, buf_size); |
672a19aa |
|
3b08d9d9 |
c->low = AV_RB16(c->bytestream); |
abe9adfb |
c->bytestream += 2; |
c359c519 |
c->overread = 0; |
5f928c52 |
if (c->low >= 0xFF00) {
c->low = 0xFF00; |
96cbaaa5 |
c->bytestream_end = c->bytestream; |
5f928c52 |
} |
672a19aa |
}
|
90558e84 |
void ff_build_rac_states(RangeCoder *c, int factor, int max_p)
{
const int64_t one = 1LL << 32; |
672a19aa |
int64_t p; |
88730be6 |
int last_p8, p8, i; |
672a19aa |
memset(c->zero_state, 0, sizeof(c->zero_state)); |
90558e84 |
memset(c->one_state, 0, sizeof(c->one_state));
last_p8 = 0;
p = one / 2;
for (i = 0; i < 128; i++) {
p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one
if (p8 <= last_p8)
p8 = last_p8 + 1;
if (last_p8 && last_p8 < 256 && p8 <= max_p)
c->one_state[last_p8] = p8;
p += ((one - p) * factor + one / 2) >> 32;
last_p8 = p8; |
672a19aa |
} |
24368c4a |
|
90558e84 |
for (i = 256 - max_p; i <= max_p; i++) {
if (c->one_state[i]) |
672a19aa |
continue;
|
90558e84 |
p = (i * one + 128) >> 8;
p += ((one - p) * factor + one / 2) >> 32;
p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one
if (p8 <= i)
p8 = i + 1;
if (p8 > max_p)
p8 = max_p;
c->one_state[i] = p8; |
672a19aa |
} |
115329f1 |
|
90558e84 |
for (i = 1; i < 255; i++)
c->zero_state[i] = 256 - c->one_state[256 - i]; |
672a19aa |
}
|
90558e84 |
/* Return the number of bytes written. */
int ff_rac_terminate(RangeCoder *c)
{
c->range = 0xFF;
c->low += 0xFF; |
672a19aa |
renorm_encoder(c); |
90558e84 |
c->range = 0xFF; |
672a19aa |
renorm_encoder(c);
|
a5ca3203 |
av_assert1(c->low == 0);
av_assert1(c->range >= 0x100); |
672a19aa |
return c->bytestream - c->bytestream_start;
} |