Update avcodec to 20080825

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27561 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul 2008-09-15 14:11:26 +00:00
parent eaa51ccd98
commit c17be5fb78
24 changed files with 10402 additions and 1330 deletions

@ -0,0 +1,96 @@
/*
* S3 Texture Compression (S3TC) decoding functions
* Copyright (c) 2007 by Ivo van Poorten
*
* see also: http://wiki.multimedia.cx/index.php?title=S3TC
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "s3tc.h"
static inline void dxt1_decode_pixels(const uint8_t *s, uint32_t *d,
unsigned int qstride, unsigned int flag,
uint64_t alpha) {
unsigned int x, y, c0, c1, a = (!flag * 255) << 24;
unsigned int rb0, rb1, rb2, rb3, g0, g1, g2, g3;
uint32_t colors[4], pixels;
c0 = AV_RL16(s);
c1 = AV_RL16(s+2);
rb0 = (c0<<3 | c0<<8) & 0xf800f8;
rb1 = (c1<<3 | c1<<8) & 0xf800f8;
rb0 += (rb0>>5) & 0x070007;
rb1 += (rb1>>5) & 0x070007;
g0 = (c0 <<5) & 0x00fc00;
g1 = (c1 <<5) & 0x00fc00;
g0 += (g0 >>6) & 0x000300;
g1 += (g1 >>6) & 0x000300;
colors[0] = rb0 + g0 + a;
colors[1] = rb1 + g1 + a;
if (c0 > c1 || flag) {
rb2 = (((2*rb0+rb1) * 21) >> 6) & 0xff00ff;
rb3 = (((2*rb1+rb0) * 21) >> 6) & 0xff00ff;
g2 = (((2*g0 +g1 ) * 21) >> 6) & 0x00ff00;
g3 = (((2*g1 +g0 ) * 21) >> 6) & 0x00ff00;
colors[3] = rb3 + g3 + a;
} else {
rb2 = ((rb0+rb1) >> 1) & 0xff00ff;
g2 = ((g0 +g1 ) >> 1) & 0x00ff00;
colors[3] = 0;
}
colors[2] = rb2 + g2 + a;
pixels = AV_RL32(s+4);
for (y=0; y<4; y++) {
for (x=0; x<4; x++) {
a = (alpha & 0x0f) << 28;
a += a >> 4;
d[x] = a + colors[pixels&3];
pixels >>= 2;
alpha >>= 4;
}
d += qstride;
}
}
void ff_decode_dxt1(const uint8_t *s, uint8_t *dst,
const unsigned int w, const unsigned int h,
const unsigned int stride) {
unsigned int bx, by, qstride = stride/4;
uint32_t *d = (uint32_t *) dst;
for (by=0; by < h/4; by++, d += stride-w)
for (bx=0; bx < w/4; bx++, s+=8, d+=4)
dxt1_decode_pixels(s, d, qstride, 0, 0LL);
}
void ff_decode_dxt3(const uint8_t *s, uint8_t *dst,
const unsigned int w, const unsigned int h,
const unsigned int stride) {
unsigned int bx, by, qstride = stride/4;
uint32_t *d = (uint32_t *) dst;
for (by=0; by < h/4; by++, d += stride-w)
for (bx=0; bx < w/4; bx++, s+=16, d+=4)
dxt1_decode_pixels(s+8, d, qstride, 1, AV_RL64(s));
}

@ -0,0 +1,53 @@
/*
* S3 Texture Compression (S3TC) decoding functions
* Copyright (c) 2007 by Ivo van Poorten
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFMPEG_S3TC_H
#define FFMPEG_S3TC_H
#include <stdint.h>
#define FF_S3TC_DXT1 0x31545844
#define FF_S3TC_DXT3 0x33545844
/**
* Decode DXT1 encoded data to RGB32
* @param *src source buffer, has to be aligned on a 4-byte boundary
* @param *dst destination buffer
* @param w width of output image
* @param h height of output image
* @param stride line size of output image
*/
void ff_decode_dxt1(const uint8_t *src, uint8_t *dst,
const unsigned int w, const unsigned int h,
const unsigned int stride);
/**
* Decode DXT3 encoded data to RGB32
* @param *src source buffer, has to be aligned on a 4-byte boundary
* @param *dst destination buffer
* @param w width of output image
* @param h height of output image
* @param stride line size of output image
*/
void ff_decode_dxt3(const uint8_t *src, uint8_t *dst,
const unsigned int w, const unsigned int h,
const unsigned int stride);
#endif /* FFMPEG_S3TC_H */

@ -0,0 +1,36 @@
/*
* SGI image encoder
* Xiaohui Sun <tjnksxh@hotmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFMPEG_SGI_H
#define FFMPEG_SGI_H
/**
* SGI image file signature
*/
#define SGI_MAGIC 474
#define SGI_HEADER_SIZE 512
#define SGI_GRAYSCALE 1
#define SGI_RGB 3
#define SGI_RGBA 4
#endif /* FFMPEG_SGI_H */

@ -0,0 +1,268 @@
/*
* SGI image decoder
* Todd Kirby <doubleshot@pacbell.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "bytestream.h"
#include "sgi.h"
typedef struct SgiState {
AVFrame picture;
unsigned int width;
unsigned int height;
unsigned int depth;
int linesize;
} SgiState;
/**
* Expand an RLE row into a channel.
* @param in_buf input buffer
* @param in_end end of input buffer
* @param out_buf Points to one line after the output buffer.
* @param out_end end of line in output buffer
* @param pixelstride pixel stride of input buffer
* @return size of output in bytes, -1 if buffer overflows
*/
static int expand_rle_row(const uint8_t *in_buf, const uint8_t* in_end,
unsigned char *out_buf, uint8_t* out_end, int pixelstride)
{
unsigned char pixel, count;
unsigned char *orig = out_buf;
while (1) {
if(in_buf + 1 > in_end) return -1;
pixel = bytestream_get_byte(&in_buf);
if (!(count = (pixel & 0x7f))) {
return (out_buf - orig) / pixelstride;
}
/* Check for buffer overflow. */
if(out_buf + pixelstride * count >= out_end) return -1;
if (pixel & 0x80) {
while (count--) {
*out_buf = bytestream_get_byte(&in_buf);
out_buf += pixelstride;
}
} else {
pixel = bytestream_get_byte(&in_buf);
while (count--) {
*out_buf = pixel;
out_buf += pixelstride;
}
}
}
}
/**
* Read a run length encoded SGI image.
* @param out_buf output buffer
* @param in_buf input buffer
* @param in_end end of input buffer
* @param s the current image state
* @return 0 if no error, else return error number.
*/
static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf,
const uint8_t *in_end, SgiState* s)
{
uint8_t *dest_row;
unsigned int len = s->height * s->depth * 4;
const uint8_t *start_table = in_buf;
unsigned int y, z;
unsigned int start_offset;
/* size of RLE offset and length tables */
if(len * 2 > in_end - in_buf) {
return AVERROR_INVALIDDATA;
}
in_buf -= SGI_HEADER_SIZE;
for (z = 0; z < s->depth; z++) {
dest_row = out_buf;
for (y = 0; y < s->height; y++) {
dest_row -= s->linesize;
start_offset = bytestream_get_be32(&start_table);
if(start_offset > in_end - in_buf) {
return AVERROR_INVALIDDATA;
}
if (expand_rle_row(in_buf + start_offset, in_end, dest_row + z,
dest_row + FFABS(s->linesize), s->depth) != s->width)
return AVERROR_INVALIDDATA;
}
}
return 0;
}
/**
* Read an uncompressed SGI image.
* @param out_buf output buffer
* @param out_end end ofoutput buffer
* @param in_buf input buffer
* @param in_end end of input buffer
* @param s the current image state
* @return 0 if read success, otherwise return -1.
*/
static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
const uint8_t *in_buf, const uint8_t *in_end, SgiState* s)
{
int x, y, z;
const uint8_t *ptr;
unsigned int offset = s->height * s->width;
/* Test buffer size. */
if (offset * s->depth > in_end - in_buf) {
return -1;
}
for (y = s->height - 1; y >= 0; y--) {
out_end = out_buf + (y * s->linesize);
for (x = s->width; x > 0; x--) {
ptr = in_buf++;
for(z = 0; z < s->depth; z ++) {
bytestream_put_byte(&out_end, *ptr);
ptr += offset;
}
}
}
return 0;
}
static int decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *in_buf, int buf_size)
{
SgiState *s = avctx->priv_data;
AVFrame *picture = data;
AVFrame *p = &s->picture;
const uint8_t *in_end = in_buf + buf_size;
unsigned int dimension, bytes_per_channel, rle;
int ret = 0;
uint8_t *out_buf, *out_end;
if (buf_size < SGI_HEADER_SIZE){
av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", buf_size);
return -1;
}
/* Test for SGI magic. */
if (bytestream_get_be16(&in_buf) != SGI_MAGIC) {
av_log(avctx, AV_LOG_ERROR, "bad magic number\n");
return -1;
}
rle = bytestream_get_byte(&in_buf);
bytes_per_channel = bytestream_get_byte(&in_buf);
dimension = bytestream_get_be16(&in_buf);
s->width = bytestream_get_be16(&in_buf);
s->height = bytestream_get_be16(&in_buf);
s->depth = bytestream_get_be16(&in_buf);
if (bytes_per_channel != 1) {
av_log(avctx, AV_LOG_ERROR, "wrong channel number\n");
return -1;
}
/* Check for supported image dimensions. */
if (dimension != 2 && dimension != 3) {
av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n");
return -1;
}
if (s->depth == SGI_GRAYSCALE) {
avctx->pix_fmt = PIX_FMT_GRAY8;
} else if (s->depth == SGI_RGB) {
avctx->pix_fmt = PIX_FMT_RGB24;
} else if (s->depth == SGI_RGBA) {
avctx->pix_fmt = PIX_FMT_RGBA;
} else {
av_log(avctx, AV_LOG_ERROR, "wrong picture format\n");
return -1;
}
if (avcodec_check_dimensions(avctx, s->width, s->height))
return -1;
avcodec_set_dimensions(avctx, s->width, s->height);
if (p->data[0])
avctx->release_buffer(avctx, p);
p->reference = 0;
if (avctx->get_buffer(avctx, p) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n");
return -1;
}
p->pict_type = FF_I_TYPE;
p->key_frame = 1;
out_buf = p->data[0];
out_end = out_buf + p->linesize[0] * s->height;
s->linesize = p->linesize[0];
/* Skip header. */
in_buf += SGI_HEADER_SIZE - 12;
if (rle) {
ret = read_rle_sgi(out_end, in_buf, in_end, s);
} else {
ret = read_uncompressed_sgi(out_buf, out_end, in_buf, in_end, s);
}
if (ret == 0) {
*picture = s->picture;
*data_size = sizeof(AVPicture);
return buf_size;
} else {
return -1;
}
}
static av_cold int sgi_init(AVCodecContext *avctx){
SgiState *s = avctx->priv_data;
avcodec_get_frame_defaults(&s->picture);
avctx->coded_frame = &s->picture;
return 0;
}
static av_cold int sgi_end(AVCodecContext *avctx)
{
SgiState * const s = avctx->priv_data;
if (s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
return 0;
}
AVCodec sgi_decoder = {
"sgi",
CODEC_TYPE_VIDEO,
CODEC_ID_SGI,
sizeof(SgiState),
sgi_init,
NULL,
sgi_end,
decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("SGI image"),
};

@ -0,0 +1,157 @@
/*
* SGI image encoder
* Todd Kirby <doubleshot@pacbell.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "bytestream.h"
#include "sgi.h"
#include "rle.h"
#define SGI_SINGLE_CHAN 2
#define SGI_MULTI_CHAN 3
typedef struct SgiContext {
AVFrame picture;
} SgiContext;
static av_cold int encode_init(AVCodecContext *avctx){
SgiContext *s = avctx->priv_data;
avcodec_get_frame_defaults(&s->picture);
avctx->coded_frame = &s->picture;
return 0;
}
static int encode_frame(AVCodecContext *avctx, unsigned char *buf,
int buf_size, void *data) {
SgiContext *s = avctx->priv_data;
AVFrame * const p = &s->picture;
uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf;
int x, y, z, length, tablesize;
unsigned int width, height, depth, dimension;
unsigned char *orig_buf = buf, *end_buf = buf + buf_size;
*p = *(AVFrame*)data;
p->pict_type = FF_I_TYPE;
p->key_frame = 1;
width = avctx->width;
height = avctx->height;
switch (avctx->pix_fmt) {
case PIX_FMT_GRAY8:
dimension = SGI_SINGLE_CHAN;
depth = SGI_GRAYSCALE;
break;
case PIX_FMT_RGB24:
dimension = SGI_MULTI_CHAN;
depth = SGI_RGB;
break;
case PIX_FMT_RGBA:
dimension = SGI_MULTI_CHAN;
depth = SGI_RGBA;
break;
default:
return AVERROR_INVALIDDATA;
}
tablesize = depth * height * 4;
length = tablesize * 2 + SGI_HEADER_SIZE;
if (buf_size < length) {
av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size);
return -1;
}
/* Encode header. */
bytestream_put_be16(&buf, SGI_MAGIC);
bytestream_put_byte(&buf, 1); /* RLE */
bytestream_put_byte(&buf, 1); /* bytes_per_channel */
bytestream_put_be16(&buf, dimension);
bytestream_put_be16(&buf, width);
bytestream_put_be16(&buf, height);
bytestream_put_be16(&buf, depth);
/* The rest are constant in this implementation. */
bytestream_put_be32(&buf, 0L); /* pixmin */
bytestream_put_be32(&buf, 255L); /* pixmax */
bytestream_put_be32(&buf, 0L); /* dummy */
/* name */
memset(buf, 0, SGI_HEADER_SIZE);
buf += 80;
/* colormap */
bytestream_put_be32(&buf, 0L);
/* The rest of the 512 byte header is unused. */
buf += 404;
offsettab = buf;
/* Skip RLE offset table. */
buf += tablesize;
lengthtab = buf;
/* Skip RLE length table. */
buf += tablesize;
/* Make an intermediate consecutive buffer. */
if ((encode_buf = av_malloc(width)) == NULL)
return -1;
for (z = 0; z < depth; z++) {
in_buf = p->data[0] + p->linesize[0] * (height - 1) + z;
for (y = 0; y < height; y++) {
bytestream_put_be32(&offsettab, buf - orig_buf);
for (x = 0; x < width; x++)
encode_buf[x] = in_buf[depth * x];
if((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) {
av_free(encode_buf);
return -1;
}
buf += length;
bytestream_put_byte(&buf, 0);
bytestream_put_be32(&lengthtab, length + 1);
in_buf -= p->linesize[0];
}
}
av_free(encode_buf);
/* total length */
return buf - orig_buf;
}
AVCodec sgi_encoder = {
"sgi",
CODEC_TYPE_VIDEO,
CODEC_ID_SGI,
sizeof(SgiContext),
encode_init,
encode_frame,
NULL,
.pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("SGI image"),
};

@ -0,0 +1,537 @@
/*
* Shorten decoder
* Copyright (c) 2005 Jeff Muizelaar
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file shorten.c
* Shorten decoder
* @author Jeff Muizelaar
*
*/
#define DEBUG
#include <limits.h>
#include "avcodec.h"
#include "bitstream.h"
#include "golomb.h"
#define MAX_CHANNELS 8
#define MAX_BLOCKSIZE 65535
#define OUT_BUFFER_SIZE 16384
#define ULONGSIZE 2
#define WAVE_FORMAT_PCM 0x0001
#define DEFAULT_BLOCK_SIZE 256
#define TYPESIZE 4
#define CHANSIZE 0
#define LPCQSIZE 2
#define ENERGYSIZE 3
#define BITSHIFTSIZE 2
#define TYPE_S16HL 3
#define TYPE_S16LH 5
#define NWRAP 3
#define NSKIPSIZE 1
#define LPCQUANT 5
#define V2LPCQOFFSET (1 << LPCQUANT)
#define FNSIZE 2
#define FN_DIFF0 0
#define FN_DIFF1 1
#define FN_DIFF2 2
#define FN_DIFF3 3
#define FN_QUIT 4
#define FN_BLOCKSIZE 5
#define FN_BITSHIFT 6
#define FN_QLPC 7
#define FN_ZERO 8
#define FN_VERBATIM 9
#define VERBATIM_CKSIZE_SIZE 5
#define VERBATIM_BYTE_SIZE 8
#define CANONICAL_HEADER_SIZE 44
typedef struct ShortenContext {
AVCodecContext *avctx;
GetBitContext gb;
int min_framesize, max_framesize;
int channels;
int32_t *decoded[MAX_CHANNELS];
int32_t *offset[MAX_CHANNELS];
uint8_t *bitstream;
int bitstream_size;
int bitstream_index;
unsigned int allocated_bitstream_size;
int header_size;
uint8_t header[OUT_BUFFER_SIZE];
int version;
int cur_chan;
int bitshift;
int nmean;
int internal_ftype;
int nwrap;
int blocksize;
int bitindex;
int32_t lpcqoffset;
} ShortenContext;
static av_cold int shorten_decode_init(AVCodecContext * avctx)
{
ShortenContext *s = avctx->priv_data;
s->avctx = avctx;
avctx->sample_fmt = SAMPLE_FMT_S16;
return 0;
}
static int allocate_buffers(ShortenContext *s)
{
int i, chan;
for (chan=0; chan<s->channels; chan++) {
if(FFMAX(1, s->nmean) >= UINT_MAX/sizeof(int32_t)){
av_log(s->avctx, AV_LOG_ERROR, "nmean too large\n");
return -1;
}
if(s->blocksize + s->nwrap >= UINT_MAX/sizeof(int32_t) || s->blocksize + s->nwrap <= (unsigned)s->nwrap){
av_log(s->avctx, AV_LOG_ERROR, "s->blocksize + s->nwrap too large\n");
return -1;
}
s->offset[chan] = av_realloc(s->offset[chan], sizeof(int32_t)*FFMAX(1, s->nmean));
s->decoded[chan] = av_realloc(s->decoded[chan], sizeof(int32_t)*(s->blocksize + s->nwrap));
for (i=0; i<s->nwrap; i++)
s->decoded[chan][i] = 0;
s->decoded[chan] += s->nwrap;
}
return 0;
}
static inline unsigned int get_uint(ShortenContext *s, int k)
{
if (s->version != 0)
k = get_ur_golomb_shorten(&s->gb, ULONGSIZE);
return get_ur_golomb_shorten(&s->gb, k);
}
static void fix_bitshift(ShortenContext *s, int32_t *buffer)
{
int i;
if (s->bitshift != 0)
for (i = 0; i < s->blocksize; i++)
buffer[s->nwrap + i] <<= s->bitshift;
}
static void init_offset(ShortenContext *s)
{
int32_t mean = 0;
int chan, i;
int nblock = FFMAX(1, s->nmean);
/* initialise offset */
switch (s->internal_ftype)
{
case TYPE_S16HL:
case TYPE_S16LH:
mean = 0;
break;
default:
av_log(s->avctx, AV_LOG_ERROR, "unknown audio type");
abort();
}
for (chan = 0; chan < s->channels; chan++)
for (i = 0; i < nblock; i++)
s->offset[chan][i] = mean;
}
static inline int get_le32(GetBitContext *gb)
{
return bswap_32(get_bits_long(gb, 32));
}
static inline short get_le16(GetBitContext *gb)
{
return bswap_16(get_bits_long(gb, 16));
}
static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header_size)
{
GetBitContext hb;
int len;
int chunk_size;
short wave_format;
init_get_bits(&hb, header, header_size*8);
if (get_le32(&hb) != MKTAG('R','I','F','F')) {
av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n");
return -1;
}
chunk_size = get_le32(&hb);
if (get_le32(&hb) != MKTAG('W','A','V','E')) {
av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n");
return -1;
}
while (get_le32(&hb) != MKTAG('f','m','t',' ')) {
len = get_le32(&hb);
skip_bits(&hb, 8*len);
}
len = get_le32(&hb);
if (len < 16) {
av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n");
return -1;
}
wave_format = get_le16(&hb);
switch (wave_format) {
case WAVE_FORMAT_PCM:
break;
default:
av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n");
return -1;
}
avctx->channels = get_le16(&hb);
avctx->sample_rate = get_le32(&hb);
avctx->bit_rate = get_le32(&hb) * 8;
avctx->block_align = get_le16(&hb);
avctx->bits_per_sample = get_le16(&hb);
if (avctx->bits_per_sample != 16) {
av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample\n");
return -1;
}
len -= 16;
if (len > 0)
av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len);
return 0;
}
static int16_t * interleave_buffer(int16_t *samples, int nchan, int blocksize, int32_t **buffer) {
int i, chan;
for (i=0; i<blocksize; i++)
for (chan=0; chan < nchan; chan++)
*samples++ = FFMIN(buffer[chan][i], 32768);
return samples;
}
static void decode_subframe_lpc(ShortenContext *s, int channel, int residual_size, int pred_order)
{
int sum, i, j;
int coeffs[pred_order];
for (i=0; i<pred_order; i++)
coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT);
for (i=0; i < s->blocksize; i++) {
sum = s->lpcqoffset;
for (j=0; j<pred_order; j++)
sum += coeffs[j] * s->decoded[channel][i-j-1];
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + (sum >> LPCQUANT);
}
}
static int shorten_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
ShortenContext *s = avctx->priv_data;
int i, input_buf_size = 0;
int16_t *samples = data;
if(s->max_framesize == 0){
s->max_framesize= 1024; // should hopefully be enough for the first header
s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
}
if(1 && s->max_framesize){//FIXME truncated
buf_size= FFMIN(buf_size, s->max_framesize - s->bitstream_size);
input_buf_size= buf_size;
if(s->bitstream_index + s->bitstream_size + buf_size > s->allocated_bitstream_size){
// printf("memmove\n");
memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
s->bitstream_index=0;
}
memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
buf= &s->bitstream[s->bitstream_index];
buf_size += s->bitstream_size;
s->bitstream_size= buf_size;
if(buf_size < s->max_framesize){
//dprintf(avctx, "wanna more data ... %d\n", buf_size);
*data_size = 0;
return input_buf_size;
}
}
init_get_bits(&s->gb, buf, buf_size*8);
skip_bits(&s->gb, s->bitindex);
if (!s->blocksize)
{
int maxnlpc = 0;
/* shorten signature */
if (get_bits_long(&s->gb, 32) != bswap_32(ff_get_fourcc("ajkg"))) {
av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n");
return -1;
}
s->lpcqoffset = 0;
s->blocksize = DEFAULT_BLOCK_SIZE;
s->channels = 1;
s->nmean = -1;
s->version = get_bits(&s->gb, 8);
s->internal_ftype = get_uint(s, TYPESIZE);
s->channels = get_uint(s, CHANSIZE);
if (s->channels > MAX_CHANNELS) {
av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels);
return -1;
}
/* get blocksize if version > 0 */
if (s->version > 0) {
int skip_bytes;
s->blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE));
maxnlpc = get_uint(s, LPCQSIZE);
s->nmean = get_uint(s, 0);
skip_bytes = get_uint(s, NSKIPSIZE);
for (i=0; i<skip_bytes; i++) {
skip_bits(&s->gb, 8);
}
}
s->nwrap = FFMAX(NWRAP, maxnlpc);
if (allocate_buffers(s))
return -1;
init_offset(s);
if (s->version > 1)
s->lpcqoffset = V2LPCQOFFSET;
if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) {
av_log(s->avctx, AV_LOG_ERROR, "missing verbatim section at beginning of stream\n");
return -1;
}
s->header_size = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE);
if (s->header_size >= OUT_BUFFER_SIZE || s->header_size < CANONICAL_HEADER_SIZE) {
av_log(s->avctx, AV_LOG_ERROR, "header is wrong size: %d\n", s->header_size);
return -1;
}
for (i=0; i<s->header_size; i++)
s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);
if (decode_wave_header(avctx, s->header, s->header_size) < 0)
return -1;
s->cur_chan = 0;
s->bitshift = 0;
}
else
{
int cmd;
int len;
cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);
switch (cmd) {
case FN_ZERO:
case FN_DIFF0:
case FN_DIFF1:
case FN_DIFF2:
case FN_DIFF3:
case FN_QLPC:
{
int residual_size = 0;
int channel = s->cur_chan;
int32_t coffset;
if (cmd != FN_ZERO) {
residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE);
/* this is a hack as version 0 differed in defintion of get_sr_golomb_shorten */
if (s->version == 0)
residual_size--;
}
if (s->nmean == 0)
coffset = s->offset[channel][0];
else {
int32_t sum = (s->version < 2) ? 0 : s->nmean / 2;
for (i=0; i<s->nmean; i++)
sum += s->offset[channel][i];
coffset = sum / s->nmean;
if (s->version >= 2)
coffset >>= FFMIN(1, s->bitshift);
}
switch (cmd) {
case FN_ZERO:
for (i=0; i<s->blocksize; i++)
s->decoded[channel][i] = 0;
break;
case FN_DIFF0:
for (i=0; i<s->blocksize; i++)
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + coffset;
break;
case FN_DIFF1:
for (i=0; i<s->blocksize; i++)
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + s->decoded[channel][i - 1];
break;
case FN_DIFF2:
for (i=0; i<s->blocksize; i++)
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 2*s->decoded[channel][i-1]
- s->decoded[channel][i-2];
break;
case FN_DIFF3:
for (i=0; i<s->blocksize; i++)
s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 3*s->decoded[channel][i-1]
- 3*s->decoded[channel][i-2]
+ s->decoded[channel][i-3];
break;
case FN_QLPC:
{
int pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE);
for (i=0; i<pred_order; i++)
s->decoded[channel][i - pred_order] -= coffset;
decode_subframe_lpc(s, channel, residual_size, pred_order);
if (coffset != 0)
for (i=0; i < s->blocksize; i++)
s->decoded[channel][i] += coffset;
}
}
if (s->nmean > 0) {
int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2;
for (i=0; i<s->blocksize; i++)
sum += s->decoded[channel][i];
for (i=1; i<s->nmean; i++)
s->offset[channel][i-1] = s->offset[channel][i];
if (s->version < 2)
s->offset[channel][s->nmean - 1] = sum / s->blocksize;
else
s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift;
}
for (i=-s->nwrap; i<0; i++)
s->decoded[channel][i] = s->decoded[channel][i + s->blocksize];
fix_bitshift(s, s->decoded[channel]);
s->cur_chan++;
if (s->cur_chan == s->channels) {
samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
s->cur_chan = 0;
goto frame_done;
}
break;
}
break;
case FN_VERBATIM:
len = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE);
while (len--) {
get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);
}
break;
case FN_BITSHIFT:
s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE);
break;
case FN_BLOCKSIZE:
s->blocksize = get_uint(s, av_log2(s->blocksize));
break;
case FN_QUIT:
*data_size = 0;
return buf_size;
break;
default:
av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);
return -1;
break;
}
}
frame_done:
*data_size = (int8_t *)samples - (int8_t *)data;
// s->last_blocksize = s->blocksize;
s->bitindex = get_bits_count(&s->gb) - 8*((get_bits_count(&s->gb))/8);
i= (get_bits_count(&s->gb))/8;
if (i > buf_size) {
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size);
s->bitstream_size=0;
s->bitstream_index=0;
return -1;
}
if (s->bitstream_size) {
s->bitstream_index += i;
s->bitstream_size -= i;
return input_buf_size;
} else
return i;
}
static av_cold int shorten_decode_close(AVCodecContext *avctx)
{
ShortenContext *s = avctx->priv_data;
int i;
for (i = 0; i < s->channels; i++) {
s->decoded[i] -= s->nwrap;
av_freep(&s->decoded[i]);
av_freep(&s->offset[i]);
}
av_freep(&s->bitstream);
return 0;
}
static void shorten_flush(AVCodecContext *avctx){
ShortenContext *s = avctx->priv_data;
s->bitstream_size=
s->bitstream_index= 0;
}
AVCodec shorten_decoder = {
"shorten",
CODEC_TYPE_AUDIO,
CODEC_ID_SHORTEN,
sizeof(ShortenContext),
shorten_decode_init,
NULL,
shorten_decode_close,
shorten_decode_frame,
.flush= shorten_flush,
.long_name= NULL_IF_CONFIG_SMALL("Shorten"),
};

@ -3,29 +3,31 @@
*
* Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
*
* This library is free software; you can redistribute it and/or
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file simple_idct.c
* simpleidct in C.
*/
/*
based upon some outcommented c code from mpeg2dec (idct_mmx.c
written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>)
written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>)
*/
#include "avcodec.h"
#include "dsputil.h"
@ -75,21 +77,21 @@
static inline void idctRowCondDC (DCTELEM * row)
{
int a0, a1, a2, a3, b0, b1, b2, b3;
#ifdef FAST_64BIT
int a0, a1, a2, a3, b0, b1, b2, b3;
#ifdef HAVE_FAST_64BIT
uint64_t temp;
#else
uint32_t temp;
#endif
#ifdef FAST_64BIT
#ifdef HAVE_FAST_64BIT
#ifdef WORDS_BIGENDIAN
#define ROW0_MASK 0xffff000000000000LL
#else
#define ROW0_MASK 0xffffLL
#endif
if(sizeof(DCTELEM)==2){
if ( ((((uint64_t *)row)[0] & ~ROW0_MASK) |
if ( ((((uint64_t *)row)[0] & ~ROW0_MASK) |
((uint64_t *)row)[1]) == 0) {
temp = (row[0] << 3) & 0xffff;
temp += temp << 16;
@ -97,7 +99,7 @@ static inline void idctRowCondDC (DCTELEM * row)
((uint64_t *)row)[0] = temp;
((uint64_t *)row)[1] = temp;
return;
}
}
}else{
if (!(row[1]|row[2]|row[3]|row[4]|row[5]|row[6]|row[7])) {
row[0]=row[1]=row[2]=row[3]=row[4]=row[5]=row[6]=row[7]= row[0] << 3;
@ -108,7 +110,7 @@ static inline void idctRowCondDC (DCTELEM * row)
if(sizeof(DCTELEM)==2){
if (!(((uint32_t*)row)[1] |
((uint32_t*)row)[2] |
((uint32_t*)row)[3] |
((uint32_t*)row)[3] |
row[1])) {
temp = (row[0] << 3) & 0xffff;
temp += temp << 16;
@ -125,9 +127,9 @@ static inline void idctRowCondDC (DCTELEM * row)
#endif
a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1));
a1 = a0;
a2 = a0;
a3 = a0;
a1 = a0;
a2 = a0;
a3 = a0;
/* no need to optimize : gcc does it */
a0 += W2 * row[2];
@ -144,12 +146,12 @@ static inline void idctRowCondDC (DCTELEM * row)
MUL16(b3, W7, row[1]);
MAC16(b3, -W5, row[3]);
#ifdef FAST_64BIT
#ifdef HAVE_FAST_64BIT
temp = ((uint64_t*)row)[1];
#else
temp = ((uint32_t*)row)[2] | ((uint32_t*)row)[3];
#endif
if (temp != 0) {
if (temp != 0) {
a0 += W4*row[4] + W6*row[6];
a1 += - W4*row[4] - W2*row[6];
a2 += - W4*row[4] + W2*row[6];
@ -157,38 +159,38 @@ static inline void idctRowCondDC (DCTELEM * row)
MAC16(b0, W5, row[5]);
MAC16(b0, W7, row[7]);
MAC16(b1, -W1, row[5]);
MAC16(b1, -W5, row[7]);
MAC16(b2, W7, row[5]);
MAC16(b2, W3, row[7]);
MAC16(b3, W3, row[5]);
MAC16(b3, -W1, row[7]);
}
}
row[0] = (a0 + b0) >> ROW_SHIFT;
row[7] = (a0 - b0) >> ROW_SHIFT;
row[1] = (a1 + b1) >> ROW_SHIFT;
row[6] = (a1 - b1) >> ROW_SHIFT;
row[2] = (a2 + b2) >> ROW_SHIFT;
row[5] = (a2 - b2) >> ROW_SHIFT;
row[3] = (a3 + b3) >> ROW_SHIFT;
row[4] = (a3 - b3) >> ROW_SHIFT;
row[0] = (a0 + b0) >> ROW_SHIFT;
row[7] = (a0 - b0) >> ROW_SHIFT;
row[1] = (a1 + b1) >> ROW_SHIFT;
row[6] = (a1 - b1) >> ROW_SHIFT;
row[2] = (a2 + b2) >> ROW_SHIFT;
row[5] = (a2 - b2) >> ROW_SHIFT;
row[3] = (a3 + b3) >> ROW_SHIFT;
row[4] = (a3 - b3) >> ROW_SHIFT;
}
static inline void idctSparseColPut (uint8_t *dest, int line_size,
static inline void idctSparseColPut (uint8_t *dest, int line_size,
DCTELEM * col)
{
int a0, a1, a2, a3, b0, b1, b2, b3;
uint8_t *cm = cropTbl + MAX_NEG_CROP;
int a0, a1, a2, a3, b0, b1, b2, b3;
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
/* XXX: I did that only to give same values as previous code */
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 += + W2*col[8*2];
a1 += + W6*col[8*2];
@ -205,33 +207,33 @@ static inline void idctSparseColPut (uint8_t *dest, int line_size,
MAC16(b2, - W1, col[8*3]);
MAC16(b3, - W5, col[8*3]);
if(col[8*4]){
if(col[8*4]){
a0 += + W4*col[8*4];
a1 += - W4*col[8*4];
a2 += - W4*col[8*4];
a3 += + W4*col[8*4];
}
}
if (col[8*5]) {
if (col[8*5]) {
MAC16(b0, + W5, col[8*5]);
MAC16(b1, - W1, col[8*5]);
MAC16(b2, + W7, col[8*5]);
MAC16(b3, + W3, col[8*5]);
}
}
if(col[8*6]){
if(col[8*6]){
a0 += + W6*col[8*6];
a1 += - W2*col[8*6];
a2 += + W2*col[8*6];
a3 += - W6*col[8*6];
}
}
if (col[8*7]) {
if (col[8*7]) {
MAC16(b0, + W7, col[8*7]);
MAC16(b1, - W5, col[8*7]);
MAC16(b2, + W3, col[8*7]);
MAC16(b3, - W1, col[8*7]);
}
}
dest[0] = cm[(a0 + b0) >> COL_SHIFT];
dest += line_size;
@ -250,17 +252,17 @@ static inline void idctSparseColPut (uint8_t *dest, int line_size,
dest[0] = cm[(a0 - b0) >> COL_SHIFT];
}
static inline void idctSparseColAdd (uint8_t *dest, int line_size,
static inline void idctSparseColAdd (uint8_t *dest, int line_size,
DCTELEM * col)
{
int a0, a1, a2, a3, b0, b1, b2, b3;
uint8_t *cm = cropTbl + MAX_NEG_CROP;
int a0, a1, a2, a3, b0, b1, b2, b3;
uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
/* XXX: I did that only to give same values as previous code */
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 += + W2*col[8*2];
a1 += + W6*col[8*2];
@ -277,33 +279,33 @@ static inline void idctSparseColAdd (uint8_t *dest, int line_size,
MAC16(b2, - W1, col[8*3]);
MAC16(b3, - W5, col[8*3]);
if(col[8*4]){
if(col[8*4]){
a0 += + W4*col[8*4];
a1 += - W4*col[8*4];
a2 += - W4*col[8*4];
a3 += + W4*col[8*4];
}
}
if (col[8*5]) {
if (col[8*5]) {
MAC16(b0, + W5, col[8*5]);
MAC16(b1, - W1, col[8*5]);
MAC16(b2, + W7, col[8*5]);
MAC16(b3, + W3, col[8*5]);
}
}
if(col[8*6]){
if(col[8*6]){
a0 += + W6*col[8*6];
a1 += - W2*col[8*6];
a2 += + W2*col[8*6];
a3 += - W6*col[8*6];
}
}
if (col[8*7]) {
if (col[8*7]) {
MAC16(b0, + W7, col[8*7]);
MAC16(b1, - W5, col[8*7]);
MAC16(b2, + W3, col[8*7]);
MAC16(b3, - W1, col[8*7]);
}
}
dest[0] = cm[dest[0] + ((a0 + b0) >> COL_SHIFT)];
dest += line_size;
@ -324,13 +326,13 @@ static inline void idctSparseColAdd (uint8_t *dest, int line_size,
static inline void idctSparseCol (DCTELEM * col)
{
int a0, a1, a2, a3, b0, b1, b2, b3;
int a0, a1, a2, a3, b0, b1, b2, b3;
/* XXX: I did that only to give same values as previous code */
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 += + W2*col[8*2];
a1 += + W6*col[8*2];
@ -347,33 +349,33 @@ static inline void idctSparseCol (DCTELEM * col)
MAC16(b2, - W1, col[8*3]);
MAC16(b3, - W5, col[8*3]);
if(col[8*4]){
if(col[8*4]){
a0 += + W4*col[8*4];
a1 += - W4*col[8*4];
a2 += - W4*col[8*4];
a3 += + W4*col[8*4];
}
}
if (col[8*5]) {
if (col[8*5]) {
MAC16(b0, + W5, col[8*5]);
MAC16(b1, - W1, col[8*5]);
MAC16(b2, + W7, col[8*5]);
MAC16(b3, + W3, col[8*5]);
}
}
if(col[8*6]){
if(col[8*6]){
a0 += + W6*col[8*6];
a1 += - W2*col[8*6];
a2 += + W2*col[8*6];
a3 += - W6*col[8*6];
}
}
if (col[8*7]) {
if (col[8*7]) {
MAC16(b0, + W7, col[8*7]);
MAC16(b1, - W5, col[8*7]);
MAC16(b2, + W3, col[8*7]);
MAC16(b3, - W1, col[8*7]);
}
}
col[0 ] = ((a0 + b0) >> COL_SHIFT);
col[8 ] = ((a1 + b1) >> COL_SHIFT);
@ -385,32 +387,32 @@ static inline void idctSparseCol (DCTELEM * col)
col[56] = ((a0 - b0) >> COL_SHIFT);
}
void simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
void ff_simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
for(i=0; i<8; i++)
idctRowCondDC(block + i*8);
for(i=0; i<8; i++)
idctSparseColPut(dest + i, line_size, block + i);
}
void simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
void ff_simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
for(i=0; i<8; i++)
idctRowCondDC(block + i*8);
for(i=0; i<8; i++)
idctSparseColAdd(dest + i, line_size, block + i);
}
void simple_idct(DCTELEM *block)
void ff_simple_idct(DCTELEM *block)
{
int i;
for(i=0; i<8; i++)
idctRowCondDC(block + i*8);
for(i=0; i<8; i++)
idctSparseCol(block + i);
}
@ -426,10 +428,10 @@ void simple_idct(DCTELEM *block)
and the butterfly must be multiplied by 0.5 * sqrt(2.0) */
#define C_SHIFT (4+1+12)
static inline void idct4col(uint8_t *dest, int line_size, const DCTELEM *col)
static inline void idct4col_put(uint8_t *dest, int line_size, const DCTELEM *col)
{
int c0, c1, c2, c3, a0, a1, a2, a3;
const uint8_t *cm = cropTbl + MAX_NEG_CROP;
const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
a0 = col[8*0];
a1 = col[8*2];
@ -463,11 +465,11 @@ static inline void idct4col(uint8_t *dest, int line_size, const DCTELEM *col)
/* XXX: I think a 1.0/sqrt(2) normalization should be needed to
compensate the extra butterfly stage - I don't have the full DV
specification */
void simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block)
void ff_simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
DCTELEM *ptr;
/* butterfly */
ptr = block;
for(i=0;i<4;i++) {
@ -489,8 +491,8 @@ void simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block)
/* IDCT4 and store */
for(i=0;i<8;i++) {
idct4col(dest + i, 2 * line_size, block + i);
idct4col(dest + line_size + i, 2 * line_size, block + 8 + i);
idct4col_put(dest + i, 2 * line_size, block + i);
idct4col_put(dest + line_size + i, 2 * line_size, block + 8 + i);
}
}
@ -509,7 +511,7 @@ void simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block)
static inline void idct4col_add(uint8_t *dest, int line_size, const DCTELEM *col)
{
int c0, c1, c2, c3, a0, a1, a2, a3;
const uint8_t *cm = cropTbl + MAX_NEG_CROP;
const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
a0 = col[8*0];
a1 = col[8*1];
@ -537,7 +539,7 @@ static inline void idct4col_add(uint8_t *dest, int line_size, const DCTELEM *col
static inline void idct4row(DCTELEM *row)
{
int c0, c1, c2, c3, a0, a1, a2, a3;
//const uint8_t *cm = cropTbl + MAX_NEG_CROP;
//const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
a0 = row[0];
a1 = row[1];
@ -553,7 +555,7 @@ static inline void idct4row(DCTELEM *row)
row[3]= (c0 - c1) >> R_SHIFT;
}
void simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block)
void ff_simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
@ -568,7 +570,7 @@ void simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block)
}
}
void simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block)
void ff_simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
@ -583,3 +585,17 @@ void simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block)
}
}
void ff_simple_idct44_add(uint8_t *dest, int line_size, DCTELEM *block)
{
int i;
/* IDCT4 on each line */
for(i=0; i<4; i++) {
idct4row(block + i*8);
}
/* IDCT4 and store */
for(i=0; i<4; i++){
idct4col_add(dest + i, line_size, block + i);
}
}

@ -3,34 +3,45 @@
*
* Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
*
* This library is free software; you can redistribute it and/or
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file simple_idct.h
* simple idct header.
*/
void simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block);
void simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block);
#ifndef FFMPEG_SIMPLE_IDCT_H
#define FFMPEG_SIMPLE_IDCT_H
#include <stdint.h>
#include "dsputil.h"
void ff_simple_idct_put(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct_add(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct_mmx(int16_t *block);
void ff_simple_idct_add_mmx(uint8_t *dest, int line_size, int16_t *block);
void ff_simple_idct_put_mmx(uint8_t *dest, int line_size, int16_t *block);
void simple_idct(DCTELEM *block);
void ff_simple_idct(DCTELEM *block);
void simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct248_put(uint8_t *dest, int line_size, DCTELEM *block);
void simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block);
void simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct84_add(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct48_add(uint8_t *dest, int line_size, DCTELEM *block);
void ff_simple_idct44_add(uint8_t *dest, int line_size, DCTELEM *block);
#endif /* FFMPEG_SIMPLE_IDCT_H */

@ -0,0 +1,716 @@
/*
* Smacker decoder
* Copyright (c) 2006 Konstantin Shishkov
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file smacker.c
* Smacker decoder
*/
/*
* Based on http://wiki.multimedia.cx/index.php?title=Smacker
*/
#include <stdio.h>
#include <stdlib.h>
#include "avcodec.h"
#define ALT_BITSTREAM_READER_LE
#include "bitstream.h"
#include "bytestream.h"
#define SMKTREE_BITS 9
#define SMK_NODE 0x80000000
/*
* Decoder context
*/
typedef struct SmackVContext {
AVCodecContext *avctx;
AVFrame pic;
int *mmap_tbl, *mclr_tbl, *full_tbl, *type_tbl;
int mmap_last[3], mclr_last[3], full_last[3], type_last[3];
} SmackVContext;
/**
* Context used for code reconstructing
*/
typedef struct HuffContext {
int length;
int maxlength;
int current;
uint32_t *bits;
int *lengths;
int *values;
} HuffContext;
/* common parameters used for decode_bigtree */
typedef struct DBCtx {
VLC *v1, *v2;
int *recode1, *recode2;
int escapes[3];
int *last;
int lcur;
} DBCtx;
/* possible runs of blocks */
static const int block_runs[64] = {
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 128, 256, 512, 1024, 2048 };
enum SmkBlockTypes {
SMK_BLK_MONO = 0,
SMK_BLK_FULL = 1,
SMK_BLK_SKIP = 2,
SMK_BLK_FILL = 3 };
/**
* Decode local frame tree
*/
static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length)
{
if(!get_bits1(gb)){ //Leaf
if(hc->current >= 256){
av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n");
return -1;
}
if(length){
hc->bits[hc->current] = prefix;
hc->lengths[hc->current] = length;
} else {
hc->bits[hc->current] = 0;
hc->lengths[hc->current] = 0;
}
hc->values[hc->current] = get_bits(gb, 8);
hc->current++;
if(hc->maxlength < length)
hc->maxlength = length;
return 0;
} else { //Node
int r;
length++;
r = smacker_decode_tree(gb, hc, prefix, length);
if(r)
return r;
return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length);
}
}
/**
* Decode header tree
*/
static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, DBCtx *ctx)
{
if(!get_bits1(gb)){ //Leaf
int val, i1, i2, b1, b2;
if(hc->current >= hc->length){
av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n");
return -1;
}
b1 = get_bits_count(gb);
i1 = get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3);
b1 = get_bits_count(gb) - b1;
b2 = get_bits_count(gb);
i2 = get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3);
b2 = get_bits_count(gb) - b2;
val = ctx->recode1[i1] | (ctx->recode2[i2] << 8);
if(val == ctx->escapes[0]) {
ctx->last[0] = hc->current;
val = 0;
} else if(val == ctx->escapes[1]) {
ctx->last[1] = hc->current;
val = 0;
} else if(val == ctx->escapes[2]) {
ctx->last[2] = hc->current;
val = 0;
}
hc->values[hc->current++] = val;
return 1;
} else { //Node
int r = 0, t;
t = hc->current++;
r = smacker_decode_bigtree(gb, hc, ctx);
if(r < 0)
return r;
hc->values[t] = SMK_NODE | r;
r++;
r += smacker_decode_bigtree(gb, hc, ctx);
return r;
}
}
/**
* Store large tree as FFmpeg's vlc codes
*/
static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size)
{
int res;
HuffContext huff;
HuffContext tmp1, tmp2;
VLC vlc[2];
int escapes[3];
DBCtx ctx;
if(size >= UINT_MAX>>4){ // (((size + 3) >> 2) + 3) << 2 must not overflow
av_log(smk->avctx, AV_LOG_ERROR, "size too large\n");
return -1;
}
tmp1.length = 256;
tmp1.maxlength = 0;
tmp1.current = 0;
tmp1.bits = av_mallocz(256 * 4);
tmp1.lengths = av_mallocz(256 * sizeof(int));
tmp1.values = av_mallocz(256 * sizeof(int));
tmp2.length = 256;
tmp2.maxlength = 0;
tmp2.current = 0;
tmp2.bits = av_mallocz(256 * 4);
tmp2.lengths = av_mallocz(256 * sizeof(int));
tmp2.values = av_mallocz(256 * sizeof(int));
memset(&vlc[0], 0, sizeof(VLC));
memset(&vlc[1], 0, sizeof(VLC));
if(get_bits1(gb)) {
smacker_decode_tree(gb, &tmp1, 0, 0);
skip_bits1(gb);
res = init_vlc(&vlc[0], SMKTREE_BITS, tmp1.length,
tmp1.lengths, sizeof(int), sizeof(int),
tmp1.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE);
if(res < 0) {
av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n");
return -1;
}
} else {
av_log(smk->avctx, AV_LOG_ERROR, "Skipping low bytes tree\n");
}
if(get_bits1(gb)){
smacker_decode_tree(gb, &tmp2, 0, 0);
skip_bits1(gb);
res = init_vlc(&vlc[1], SMKTREE_BITS, tmp2.length,
tmp2.lengths, sizeof(int), sizeof(int),
tmp2.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE);
if(res < 0) {
av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n");
return -1;
}
} else {
av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n");
}
escapes[0] = get_bits(gb, 8);
escapes[0] |= get_bits(gb, 8) << 8;
escapes[1] = get_bits(gb, 8);
escapes[1] |= get_bits(gb, 8) << 8;
escapes[2] = get_bits(gb, 8);
escapes[2] |= get_bits(gb, 8) << 8;
last[0] = last[1] = last[2] = -1;
ctx.escapes[0] = escapes[0];
ctx.escapes[1] = escapes[1];
ctx.escapes[2] = escapes[2];
ctx.v1 = &vlc[0];
ctx.v2 = &vlc[1];
ctx.recode1 = tmp1.values;
ctx.recode2 = tmp2.values;
ctx.last = last;
huff.length = ((size + 3) >> 2) + 3;
huff.maxlength = 0;
huff.current = 0;
huff.values = av_mallocz(huff.length * sizeof(int));
smacker_decode_bigtree(gb, &huff, &ctx);
skip_bits1(gb);
if(ctx.last[0] == -1) ctx.last[0] = huff.current++;
if(ctx.last[1] == -1) ctx.last[1] = huff.current++;
if(ctx.last[2] == -1) ctx.last[2] = huff.current++;
*recodes = huff.values;
if(vlc[0].table)
free_vlc(&vlc[0]);
if(vlc[1].table)
free_vlc(&vlc[1]);
av_free(tmp1.bits);
av_free(tmp1.lengths);
av_free(tmp1.values);
av_free(tmp2.bits);
av_free(tmp2.lengths);
av_free(tmp2.values);
return 0;
}
static int decode_header_trees(SmackVContext *smk) {
GetBitContext gb;
int mmap_size, mclr_size, full_size, type_size;
mmap_size = AV_RL32(smk->avctx->extradata);
mclr_size = AV_RL32(smk->avctx->extradata + 4);
full_size = AV_RL32(smk->avctx->extradata + 8);
type_size = AV_RL32(smk->avctx->extradata + 12);
init_get_bits(&gb, smk->avctx->extradata + 16, (smk->avctx->extradata_size - 16) * 8);
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping MMAP tree\n");
smk->mmap_tbl = av_malloc(sizeof(int) * 2);
smk->mmap_tbl[0] = 0;
smk->mmap_last[0] = smk->mmap_last[1] = smk->mmap_last[2] = 1;
} else {
smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size);
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n");
smk->mclr_tbl = av_malloc(sizeof(int) * 2);
smk->mclr_tbl[0] = 0;
smk->mclr_last[0] = smk->mclr_last[1] = smk->mclr_last[2] = 1;
} else {
smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size);
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n");
smk->full_tbl = av_malloc(sizeof(int) * 2);
smk->full_tbl[0] = 0;
smk->full_last[0] = smk->full_last[1] = smk->full_last[2] = 1;
} else {
smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size);
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n");
smk->type_tbl = av_malloc(sizeof(int) * 2);
smk->type_tbl[0] = 0;
smk->type_last[0] = smk->type_last[1] = smk->type_last[2] = 1;
} else {
smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size);
}
return 0;
}
static av_always_inline void last_reset(int *recode, int *last) {
recode[last[0]] = recode[last[1]] = recode[last[2]] = 0;
}
/* get code and update history */
static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) {
register int *table = recode;
int v, b;
b = get_bits_count(gb);
while(*table & SMK_NODE) {
if(get_bits1(gb))
table += (*table) & (~SMK_NODE);
table++;
}
v = *table;
b = get_bits_count(gb) - b;
if(v != recode[last[0]]) {
recode[last[2]] = recode[last[1]];
recode[last[1]] = recode[last[0]];
recode[last[0]] = v;
}
return v;
}
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size)
{
SmackVContext * const smk = avctx->priv_data;
uint8_t *out;
uint32_t *pal;
GetBitContext gb;
int blocks, blk, bw, bh;
int i;
int stride;
if(buf_size <= 769)
return 0;
if(smk->pic.data[0])
avctx->release_buffer(avctx, &smk->pic);
smk->pic.reference = 1;
smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
if(avctx->reget_buffer(avctx, &smk->pic) < 0){
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
/* make the palette available on the way out */
pal = (uint32_t*)smk->pic.data[1];
smk->pic.palette_has_changed = buf[0] & 1;
smk->pic.key_frame = !!(buf[0] & 2);
if(smk->pic.key_frame)
smk->pic.pict_type = FF_I_TYPE;
else
smk->pic.pict_type = FF_P_TYPE;
buf++;
for(i = 0; i < 256; i++)
*pal++ = bytestream_get_be24(&buf);
buf_size -= 769;
last_reset(smk->mmap_tbl, smk->mmap_last);
last_reset(smk->mclr_tbl, smk->mclr_last);
last_reset(smk->full_tbl, smk->full_last);
last_reset(smk->type_tbl, smk->type_last);
init_get_bits(&gb, buf, buf_size * 8);
blk = 0;
bw = avctx->width >> 2;
bh = avctx->height >> 2;
blocks = bw * bh;
out = smk->pic.data[0];
stride = smk->pic.linesize[0];
while(blk < blocks) {
int type, run, mode;
uint16_t pix;
type = smk_get_code(&gb, smk->type_tbl, smk->type_last);
run = block_runs[(type >> 2) & 0x3F];
switch(type & 3){
case SMK_BLK_MONO:
while(run-- && blk < blocks){
int clr, map;
int hi, lo;
clr = smk_get_code(&gb, smk->mclr_tbl, smk->mclr_last);
map = smk_get_code(&gb, smk->mmap_tbl, smk->mmap_last);
out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;
hi = clr >> 8;
lo = clr & 0xFF;
for(i = 0; i < 4; i++) {
if(map & 1) out[0] = hi; else out[0] = lo;
if(map & 2) out[1] = hi; else out[1] = lo;
if(map & 4) out[2] = hi; else out[2] = lo;
if(map & 8) out[3] = hi; else out[3] = lo;
map >>= 4;
out += stride;
}
blk++;
}
break;
case SMK_BLK_FULL:
mode = 0;
if(avctx->codec_tag == MKTAG('S', 'M', 'K', '4')) { // In case of Smacker v4 we have three modes
if(get_bits1(&gb)) mode = 1;
else if(get_bits1(&gb)) mode = 2;
}
while(run-- && blk < blocks){
out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;
switch(mode){
case 0:
for(i = 0; i < 4; i++) {
pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);
AV_WL16(out+2,pix);
pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);
AV_WL16(out,pix);
out += stride;
}
break;
case 1:
pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);
out[0] = out[1] = pix & 0xFF;
out[2] = out[3] = pix >> 8;
out += stride;
out[0] = out[1] = pix & 0xFF;
out[2] = out[3] = pix >> 8;
out += stride;
pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);
out[0] = out[1] = pix & 0xFF;
out[2] = out[3] = pix >> 8;
out += stride;
out[0] = out[1] = pix & 0xFF;
out[2] = out[3] = pix >> 8;
out += stride;
break;
case 2:
for(i = 0; i < 2; i++) {
uint16_t pix1, pix2;
pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last);
pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last);
AV_WL16(out,pix1);
AV_WL16(out+2,pix2);
out += stride;
AV_WL16(out,pix1);
AV_WL16(out+2,pix2);
out += stride;
}
break;
}
blk++;
}
break;
case SMK_BLK_SKIP:
while(run-- && blk < blocks)
blk++;
break;
case SMK_BLK_FILL:
mode = type >> 8;
while(run-- && blk < blocks){
uint32_t col;
out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;
col = mode * 0x01010101;
for(i = 0; i < 4; i++) {
*((uint32_t*)out) = col;
out += stride;
}
blk++;
}
break;
}
}
*data_size = sizeof(AVFrame);
*(AVFrame*)data = smk->pic;
/* always report that the buffer was completely consumed */
return buf_size;
}
/*
*
* Init smacker decoder
*
*/
static av_cold int decode_init(AVCodecContext *avctx)
{
SmackVContext * const c = avctx->priv_data;
c->avctx = avctx;
c->pic.data[0] = NULL;
if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
return 1;
}
avctx->pix_fmt = PIX_FMT_PAL8;
/* decode huffman trees from extradata */
if(avctx->extradata_size < 16){
av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n");
return -1;
}
decode_header_trees(c);
return 0;
}
/*
*
* Uninit smacker decoder
*
*/
static av_cold int decode_end(AVCodecContext *avctx)
{
SmackVContext * const smk = avctx->priv_data;
av_freep(&smk->mmap_tbl);
av_freep(&smk->mclr_tbl);
av_freep(&smk->full_tbl);
av_freep(&smk->type_tbl);
if (smk->pic.data[0])
avctx->release_buffer(avctx, &smk->pic);
return 0;
}
static av_cold int smka_decode_init(AVCodecContext *avctx)
{
avctx->sample_fmt = SAMPLE_FMT_S16;
return 0;
}
/**
* Decode Smacker audio data
*/
static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size)
{
GetBitContext gb;
HuffContext h[4];
VLC vlc[4];
int16_t *samples = data;
int val;
int i, res;
int unp_size;
int bits, stereo;
int pred[2] = {0, 0};
unp_size = AV_RL32(buf);
init_get_bits(&gb, buf + 4, (buf_size - 4) * 8);
if(!get_bits1(&gb)){
av_log(avctx, AV_LOG_INFO, "Sound: no data\n");
*data_size = 0;
return 1;
}
stereo = get_bits1(&gb);
bits = get_bits1(&gb);
if (unp_size & 0xC0000000 || (unp_size << !bits) > *data_size) {
av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n");
return -1;
}
memset(vlc, 0, sizeof(VLC) * 4);
memset(h, 0, sizeof(HuffContext) * 4);
// Initialize
for(i = 0; i < (1 << (bits + stereo)); i++) {
h[i].length = 256;
h[i].maxlength = 0;
h[i].current = 0;
h[i].bits = av_mallocz(256 * 4);
h[i].lengths = av_mallocz(256 * sizeof(int));
h[i].values = av_mallocz(256 * sizeof(int));
skip_bits1(&gb);
smacker_decode_tree(&gb, &h[i], 0, 0);
skip_bits1(&gb);
if(h[i].current > 1) {
res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length,
h[i].lengths, sizeof(int), sizeof(int),
h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE);
if(res < 0) {
av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n");
return -1;
}
}
}
if(bits) { //decode 16-bit data
for(i = stereo; i >= 0; i--)
pred[i] = bswap_16(get_bits(&gb, 16));
for(i = 0; i < stereo; i++)
*samples++ = pred[i];
for(i = 0; i < unp_size / 2; i++) {
if(i & stereo) {
if(vlc[2].table)
res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3);
else
res = 0;
val = h[2].values[res];
if(vlc[3].table)
res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3);
else
res = 0;
val |= h[3].values[res] << 8;
pred[1] += (int16_t)val;
*samples++ = pred[1];
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
else
res = 0;
val = h[0].values[res];
if(vlc[1].table)
res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);
else
res = 0;
val |= h[1].values[res] << 8;
pred[0] += val;
*samples++ = pred[0];
}
}
} else { //8-bit data
for(i = stereo; i >= 0; i--)
pred[i] = get_bits(&gb, 8);
for(i = 0; i < stereo; i++)
*samples++ = (pred[i] - 0x80) << 8;
for(i = 0; i < unp_size; i++) {
if(i & stereo){
if(vlc[1].table)
res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);
else
res = 0;
pred[1] += (int8_t)h[1].values[res];
*samples++ = (pred[1] - 0x80) << 8;
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
else
res = 0;
pred[0] += (int8_t)h[0].values[res];
*samples++ = (pred[0] - 0x80) << 8;
}
}
unp_size *= 2;
}
for(i = 0; i < 4; i++) {
if(vlc[i].table)
free_vlc(&vlc[i]);
if(h[i].bits)
av_free(h[i].bits);
if(h[i].lengths)
av_free(h[i].lengths);
if(h[i].values)
av_free(h[i].values);
}
*data_size = unp_size;
return buf_size;
}
AVCodec smacker_decoder = {
"smackvid",
CODEC_TYPE_VIDEO,
CODEC_ID_SMACKVIDEO,
sizeof(SmackVContext),
decode_init,
NULL,
decode_end,
decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Smacker video"),
};
AVCodec smackaud_decoder = {
"smackaud",
CODEC_TYPE_AUDIO,
CODEC_ID_SMACKAUDIO,
0,
smka_decode_init,
NULL,
NULL,
smka_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Smacker audio"),
};

@ -2,20 +2,21 @@
* Quicktime Graphics (SMC) Video Decoder
* Copyright (C) 2003 the ffmpeg project
*
* This library is free software; you can redistribute it and/or
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
@ -32,9 +33,7 @@
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "avcodec.h"
#include "dsputil.h"
#define CPAIR 2
#define CQUAD 4
@ -45,10 +44,9 @@
typedef struct SmcContext {
AVCodecContext *avctx;
DSPContext dsp;
AVFrame frame;
unsigned char *buf;
const unsigned char *buf;
int size;
/* SMC color tables */
@ -58,11 +56,6 @@ typedef struct SmcContext {
} SmcContext;
#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
(((uint8_t*)(x))[1] << 16) | \
(((uint8_t*)(x))[2] << 8) | \
((uint8_t*)(x))[3])
#define GET_BLOCK_COUNT() \
(opcode & 0x10) ? (1 + s->buf[stream_ptr++]) : 1 + (opcode & 0x0F);
@ -77,7 +70,7 @@ typedef struct SmcContext {
total_blocks--; \
if (total_blocks < 0) \
{ \
printf("warning: block counter just went negative (this should not happen)\n"); \
av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \
return; \
} \
}
@ -123,27 +116,27 @@ static void smc_decode_stream(SmcContext *s)
s->avctx->palctrl->palette_changed = 0;
}
chunk_size = BE_32(&s->buf[stream_ptr]) & 0x00FFFFFF;
chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF;
stream_ptr += 4;
if (chunk_size != s->size)
printf("warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
chunk_size, s->size);
chunk_size = s->size;
total_blocks = (s->avctx->width * s->avctx->height) / (4 * 4);
total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
/* traverse through the blocks */
while (total_blocks) {
/* sanity checks */
/* make sure stream ptr hasn't gone out of bounds */
if (stream_ptr > chunk_size) {
printf("SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)\n",
av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (stream ptr = %d, chunk size = %d)\n",
stream_ptr, chunk_size);
return;
}
/* make sure the row pointer hasn't gone wild */
if (row_ptr >= image_size) {
printf("SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
row_ptr, image_size);
return;
}
@ -166,14 +159,14 @@ static void smc_decode_stream(SmcContext *s)
/* sanity check */
if ((row_ptr == 0) && (pixel_ptr == 0)) {
printf("encountered repeat block opcode (%02X) but no blocks rendered yet\n",
av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n",
opcode & 0xF0);
break;
}
/* figure out where the previous block started */
if (pixel_ptr == 0)
prev_block_ptr1 =
prev_block_ptr1 =
(row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
else
prev_block_ptr1 = row_ptr + pixel_ptr - 4;
@ -200,14 +193,14 @@ static void smc_decode_stream(SmcContext *s)
/* sanity check */
if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
printf("encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
opcode & 0xF0);
break;
}
/* figure out where the previous 2 blocks started */
if (pixel_ptr == 0)
prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
s->avctx->width - 4 * 2;
else if (pixel_ptr == 4)
prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
@ -281,7 +274,7 @@ static void smc_decode_stream(SmcContext *s)
color_table_index = CPAIR * s->buf[stream_ptr++];
while (n_blocks--) {
color_flags = BE_16(&s->buf[stream_ptr]);
color_flags = AV_RB16(&s->buf[stream_ptr]);
stream_ptr += 2;
flag_mask = 0x8000;
block_ptr = row_ptr + pixel_ptr;
@ -324,14 +317,14 @@ static void smc_decode_stream(SmcContext *s)
color_table_index = CQUAD * s->buf[stream_ptr++];
while (n_blocks--) {
color_flags = BE_32(&s->buf[stream_ptr]);
color_flags = AV_RB32(&s->buf[stream_ptr]);
stream_ptr += 4;
/* flag mask actually acts as a bit shift count here */
flag_mask = 30;
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++) {
pixel = color_table_index +
pixel = color_table_index +
((color_flags >> flag_mask) & 0x03);
flag_mask -= 2;
pixels[block_ptr++] = s->color_quads[pixel];
@ -399,7 +392,7 @@ static void smc_decode_stream(SmcContext *s)
flag_mask = 21;
}
for (pixel_x = 0; pixel_x < 4; pixel_x++) {
pixel = color_table_index +
pixel = color_table_index +
((color_flags >> flag_mask) & 0x07);
flag_mask -= 3;
pixels[block_ptr++] = s->color_octets[pixel];
@ -427,20 +420,18 @@ static void smc_decode_stream(SmcContext *s)
break;
case 0xF0:
printf("0xF0 opcode seen in SMC chunk (xine developers would like to know)\n");
av_log(s->avctx, AV_LOG_INFO, "0xF0 opcode seen in SMC chunk (contact the developers)\n");
break;
}
}
}
static int smc_decode_init(AVCodecContext *avctx)
static av_cold int smc_decode_init(AVCodecContext *avctx)
{
SmcContext *s = (SmcContext *)avctx->priv_data;
SmcContext *s = avctx->priv_data;
s->avctx = avctx;
avctx->pix_fmt = PIX_FMT_PAL8;
avctx->has_b_frames = 0;
dsputil_init(&s->dsp, avctx);
s->frame.data[0] = NULL;
@ -449,22 +440,18 @@ static int smc_decode_init(AVCodecContext *avctx)
static int smc_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
const uint8_t *buf, int buf_size)
{
SmcContext *s = (SmcContext *)avctx->priv_data;
/* no supplementary picture */
if (buf_size == 0)
return 0;
SmcContext *s = avctx->priv_data;
s->buf = buf;
s->size = buf_size;
s->frame.reference = 1;
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
if (avctx->reget_buffer(avctx, &s->frame)) {
printf ("reget_buffer() failed\n");
av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return -1;
}
@ -477,9 +464,9 @@ static int smc_decode_frame(AVCodecContext *avctx,
return buf_size;
}
static int smc_decode_end(AVCodecContext *avctx)
static av_cold int smc_decode_end(AVCodecContext *avctx)
{
SmcContext *s = (SmcContext *)avctx->priv_data;
SmcContext *s = avctx->priv_data;
if (s->frame.data[0])
avctx->release_buffer(avctx, &s->frame);
@ -497,4 +484,5 @@ AVCodec smc_decoder = {
smc_decode_end,
smc_decode_frame,
CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,174 @@
/*
* Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
* Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFMPEG_SNOW_H
#define FFMPEG_SNOW_H
#include "dsputil.h"
#define MID_STATE 128
#define MAX_DECOMPOSITIONS 8
#define MAX_PLANES 4
#define QSHIFT 5
#define QROOT (1<<QSHIFT)
#define LOSSLESS_QLOG -128
#define FRAC_BITS 4
#define MAX_REF_FRAMES 8
#define LOG2_OBMC_MAX 8
#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
#define DWT_97 0
#define DWT_53 1
/** Used to minimize the amount of memory used in order to optimize cache performance. **/
struct slice_buffer_s {
IDWTELEM * * line; ///< For use by idwt and predict_slices.
IDWTELEM * * data_stack; ///< Used for internal purposes.
int data_stack_top;
int line_count;
int line_width;
int data_count;
IDWTELEM * base_buffer; ///< Buffer that this structure is caching.
};
#define liftS lift
#if 1
#define W_AM 3
#define W_AO 0
#define W_AS 1
#undef liftS
#define W_BM 1
#define W_BO 8
#define W_BS 4
#define W_CM 1
#define W_CO 0
#define W_CS 0
#define W_DM 3
#define W_DO 4
#define W_DS 3
#elif 0
#define W_AM 55
#define W_AO 16
#define W_AS 5
#define W_BM 3
#define W_BO 32
#define W_BS 6
#define W_CM 127
#define W_CO 64
#define W_CS 7
#define W_DM 7
#define W_DO 8
#define W_DS 4
#elif 0
#define W_AM 97
#define W_AO 32
#define W_AS 6
#define W_BM 63
#define W_BO 512
#define W_BS 10
#define W_CM 13
#define W_CO 8
#define W_CS 4
#define W_DM 15
#define W_DO 16
#define W_DS 5
#else
#define W_AM 203
#define W_AO 64
#define W_AS 7
#define W_BM 217
#define W_BO 2048
#define W_BS 12
#define W_CM 113
#define W_CO 64
#define W_CS 7
#define W_DM 227
#define W_DO 128
#define W_DS 9
#endif
extern void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width);
extern void ff_snow_horizontal_compose97i(IDWTELEM *b, int width);
extern void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8);
#ifdef CONFIG_SNOW_ENCODER
int w53_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h);
int w97_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h);
#else
static int w53_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {assert (0);}
static int w97_32_c(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {assert (0);}
#endif
/* C bits used by mmx/sse2/altivec */
static av_always_inline void snow_interleave_line_header(int * i, int width, IDWTELEM * low, IDWTELEM * high){
(*i) = (width) - 2;
if (width & 1){
low[(*i)+1] = low[((*i)+1)>>1];
(*i)--;
}
}
static av_always_inline void snow_interleave_line_footer(int * i, IDWTELEM * low, IDWTELEM * high){
for (; (*i)>=0; (*i)-=2){
low[(*i)+1] = high[(*i)>>1];
low[*i] = low[(*i)>>1];
}
}
static av_always_inline void snow_horizontal_compose_lift_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w, int lift_high, int mul, int add, int shift){
for(; i<w; i++){
dst[i] = src[i] - ((mul * (ref[i] + ref[i + 1]) + add) >> shift);
}
if((width^lift_high)&1){
dst[w] = src[w] - ((mul * 2 * ref[w] + add) >> shift);
}
}
static av_always_inline void snow_horizontal_compose_liftS_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w){
for(; i<w; i++){
dst[i] = src[i] + ((ref[i] + ref[(i+1)]+W_BO + 4 * src[i]) >> W_BS);
}
if(width&1){
dst[w] = src[w] + ((2 * ref[w] + W_BO + 4 * src[w]) >> W_BS);
}
}
#endif /* FFMPEG_SNOW_H */

@ -0,0 +1,978 @@
/*
* Simple free lossless/lossy audio codec
* Copyright (c) 2004 Alex Beregszaszi
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "bitstream.h"
#include "golomb.h"
/**
* @file sonic.c
* Simple free lossless/lossy audio codec
* Based on Paul Francis Harrison's Bonk (http://www.logarithmic.net/pfh/bonk)
* Written and designed by Alex Beregszaszi
*
* TODO:
* - CABAC put/get_symbol
* - independent quantizer for channels
* - >2 channels support
* - more decorrelation types
* - more tap_quant tests
* - selectable intlist writers/readers (bonk-style, golomb, cabac)
*/
#define MAX_CHANNELS 2
#define MID_SIDE 0
#define LEFT_SIDE 1
#define RIGHT_SIDE 2
typedef struct SonicContext {
int lossless, decorrelation;
int num_taps, downsampling;
double quantization;
int channels, samplerate, block_align, frame_size;
int *tap_quant;
int *int_samples;
int *coded_samples[MAX_CHANNELS];
// for encoding
int *tail;
int tail_size;
int *window;
int window_size;
// for decoding
int *predictor_k;
int *predictor_state[MAX_CHANNELS];
} SonicContext;
#define LATTICE_SHIFT 10
#define SAMPLE_SHIFT 4
#define LATTICE_FACTOR (1 << LATTICE_SHIFT)
#define SAMPLE_FACTOR (1 << SAMPLE_SHIFT)
#define BASE_QUANT 0.6
#define RATE_VARIATION 3.0
static inline int divide(int a, int b)
{
if (a < 0)
return -( (-a + b/2)/b );
else
return (a + b/2)/b;
}
static inline int shift(int a,int b)
{
return (a+(1<<(b-1))) >> b;
}
static inline int shift_down(int a,int b)
{
return (a>>b)+((a<0)?1:0);
}
#if 1
static inline int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part)
{
int i;
for (i = 0; i < entries; i++)
set_se_golomb(pb, buf[i]);
return 1;
}
static inline int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part)
{
int i;
for (i = 0; i < entries; i++)
buf[i] = get_se_golomb(gb);
return 1;
}
#else
#define ADAPT_LEVEL 8
static int bits_to_store(uint64_t x)
{
int res = 0;
while(x)
{
res++;
x >>= 1;
}
return res;
}
static void write_uint_max(PutBitContext *pb, unsigned int value, unsigned int max)
{
int i, bits;
if (!max)
return;
bits = bits_to_store(max);
for (i = 0; i < bits-1; i++)
put_bits(pb, 1, value & (1 << i));
if ( (value | (1 << (bits-1))) <= max)
put_bits(pb, 1, value & (1 << (bits-1)));
}
static unsigned int read_uint_max(GetBitContext *gb, int max)
{
int i, bits, value = 0;
if (!max)
return 0;
bits = bits_to_store(max);
for (i = 0; i < bits-1; i++)
if (get_bits1(gb))
value += 1 << i;
if ( (value | (1<<(bits-1))) <= max)
if (get_bits1(gb))
value += 1 << (bits-1);
return value;
}
static int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part)
{
int i, j, x = 0, low_bits = 0, max = 0;
int step = 256, pos = 0, dominant = 0, any = 0;
int *copy, *bits;
copy = av_mallocz(4* entries);
if (!copy)
return -1;
if (base_2_part)
{
int energy = 0;
for (i = 0; i < entries; i++)
energy += abs(buf[i]);
low_bits = bits_to_store(energy / (entries * 2));
if (low_bits > 15)
low_bits = 15;
put_bits(pb, 4, low_bits);
}
for (i = 0; i < entries; i++)
{
put_bits(pb, low_bits, abs(buf[i]));
copy[i] = abs(buf[i]) >> low_bits;
if (copy[i] > max)
max = abs(copy[i]);
}
bits = av_mallocz(4* entries*max);
if (!bits)
{
// av_free(copy);
return -1;
}
for (i = 0; i <= max; i++)
{
for (j = 0; j < entries; j++)
if (copy[j] >= i)
bits[x++] = copy[j] > i;
}
// store bitstream
while (pos < x)
{
int steplet = step >> 8;
if (pos + steplet > x)
steplet = x - pos;
for (i = 0; i < steplet; i++)
if (bits[i+pos] != dominant)
any = 1;
put_bits(pb, 1, any);
if (!any)
{
pos += steplet;
step += step / ADAPT_LEVEL;
}
else
{
int interloper = 0;
while (((pos + interloper) < x) && (bits[pos + interloper] == dominant))
interloper++;
// note change
write_uint_max(pb, interloper, (step >> 8) - 1);
pos += interloper + 1;
step -= step / ADAPT_LEVEL;
}
if (step < 256)
{
step = 65536 / step;
dominant = !dominant;
}
}
// store signs
for (i = 0; i < entries; i++)
if (buf[i])
put_bits(pb, 1, buf[i] < 0);
// av_free(bits);
// av_free(copy);
return 0;
}
static int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part)
{
int i, low_bits = 0, x = 0;
int n_zeros = 0, step = 256, dominant = 0;
int pos = 0, level = 0;
int *bits = av_mallocz(4* entries);
if (!bits)
return -1;
if (base_2_part)
{
low_bits = get_bits(gb, 4);
if (low_bits)
for (i = 0; i < entries; i++)
buf[i] = get_bits(gb, low_bits);
}
// av_log(NULL, AV_LOG_INFO, "entries: %d, low bits: %d\n", entries, low_bits);
while (n_zeros < entries)
{
int steplet = step >> 8;
if (!get_bits1(gb))
{
for (i = 0; i < steplet; i++)
bits[x++] = dominant;
if (!dominant)
n_zeros += steplet;
step += step / ADAPT_LEVEL;
}
else
{
int actual_run = read_uint_max(gb, steplet-1);
// av_log(NULL, AV_LOG_INFO, "actual run: %d\n", actual_run);
for (i = 0; i < actual_run; i++)
bits[x++] = dominant;
bits[x++] = !dominant;
if (!dominant)
n_zeros += actual_run;
else
n_zeros++;
step -= step / ADAPT_LEVEL;
}
if (step < 256)
{
step = 65536 / step;
dominant = !dominant;
}
}
// reconstruct unsigned values
n_zeros = 0;
for (i = 0; n_zeros < entries; i++)
{
while(1)
{
if (pos >= entries)
{
pos = 0;
level += 1 << low_bits;
}
if (buf[pos] >= level)
break;
pos++;
}
if (bits[i])
buf[pos] += 1 << low_bits;
else
n_zeros++;
pos++;
}
// av_free(bits);
// read signs
for (i = 0; i < entries; i++)
if (buf[i] && get_bits1(gb))
buf[i] = -buf[i];
// av_log(NULL, AV_LOG_INFO, "zeros: %d pos: %d\n", n_zeros, pos);
return 0;
}
#endif
static void predictor_init_state(int *k, int *state, int order)
{
int i;
for (i = order-2; i >= 0; i--)
{
int j, p, x = state[i];
for (j = 0, p = i+1; p < order; j++,p++)
{
int tmp = x + shift_down(k[j] * state[p], LATTICE_SHIFT);
state[p] += shift_down(k[j]*x, LATTICE_SHIFT);
x = tmp;
}
}
}
static int predictor_calc_error(int *k, int *state, int order, int error)
{
int i, x = error - shift_down(k[order-1] * state[order-1], LATTICE_SHIFT);
#if 1
int *k_ptr = &(k[order-2]),
*state_ptr = &(state[order-2]);
for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--)
{
int k_value = *k_ptr, state_value = *state_ptr;
x -= shift_down(k_value * state_value, LATTICE_SHIFT);
state_ptr[1] = state_value + shift_down(k_value * x, LATTICE_SHIFT);
}
#else
for (i = order-2; i >= 0; i--)
{
x -= shift_down(k[i] * state[i], LATTICE_SHIFT);
state[i+1] = state[i] + shift_down(k[i] * x, LATTICE_SHIFT);
}
#endif
// don't drift too far, to avoid overflows
if (x > (SAMPLE_FACTOR<<16)) x = (SAMPLE_FACTOR<<16);
if (x < -(SAMPLE_FACTOR<<16)) x = -(SAMPLE_FACTOR<<16);
state[0] = x;
return x;
}
#ifdef CONFIG_ENCODERS
// Heavily modified Levinson-Durbin algorithm which
// copes better with quantization, and calculates the
// actual whitened result as it goes.
static void modified_levinson_durbin(int *window, int window_entries,
int *out, int out_entries, int channels, int *tap_quant)
{
int i;
int *state = av_mallocz(4* window_entries);
memcpy(state, window, 4* window_entries);
for (i = 0; i < out_entries; i++)
{
int step = (i+1)*channels, k, j;
double xx = 0.0, xy = 0.0;
#if 1
int *x_ptr = &(window[step]), *state_ptr = &(state[0]);
j = window_entries - step;
for (;j>=0;j--,x_ptr++,state_ptr++)
{
double x_value = *x_ptr, state_value = *state_ptr;
xx += state_value*state_value;
xy += x_value*state_value;
}
#else
for (j = 0; j <= (window_entries - step); j++);
{
double stepval = window[step+j], stateval = window[j];
// xx += (double)window[j]*(double)window[j];
// xy += (double)window[step+j]*(double)window[j];
xx += stateval*stateval;
xy += stepval*stateval;
}
#endif
if (xx == 0.0)
k = 0;
else
k = (int)(floor(-xy/xx * (double)LATTICE_FACTOR / (double)(tap_quant[i]) + 0.5));
if (k > (LATTICE_FACTOR/tap_quant[i]))
k = LATTICE_FACTOR/tap_quant[i];
if (-k > (LATTICE_FACTOR/tap_quant[i]))
k = -(LATTICE_FACTOR/tap_quant[i]);
out[i] = k;
k *= tap_quant[i];
#if 1
x_ptr = &(window[step]);
state_ptr = &(state[0]);
j = window_entries - step;
for (;j>=0;j--,x_ptr++,state_ptr++)
{
int x_value = *x_ptr, state_value = *state_ptr;
*x_ptr = x_value + shift_down(k*state_value,LATTICE_SHIFT);
*state_ptr = state_value + shift_down(k*x_value, LATTICE_SHIFT);
}
#else
for (j=0; j <= (window_entries - step); j++)
{
int stepval = window[step+j], stateval=state[j];
window[step+j] += shift_down(k * stateval, LATTICE_SHIFT);
state[j] += shift_down(k * stepval, LATTICE_SHIFT);
}
#endif
}
av_free(state);
}
#endif /* CONFIG_ENCODERS */
static const int samplerate_table[] =
{ 44100, 22050, 11025, 96000, 48000, 32000, 24000, 16000, 8000 };
#ifdef CONFIG_ENCODERS
static inline int code_samplerate(int samplerate)
{
switch (samplerate)
{
case 44100: return 0;
case 22050: return 1;
case 11025: return 2;
case 96000: return 3;
case 48000: return 4;
case 32000: return 5;
case 24000: return 6;
case 16000: return 7;
case 8000: return 8;
}
return -1;
}
static av_cold int sonic_encode_init(AVCodecContext *avctx)
{
SonicContext *s = avctx->priv_data;
PutBitContext pb;
int i, version = 0;
if (avctx->channels > MAX_CHANNELS)
{
av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n");
return -1; /* only stereo or mono for now */
}
if (avctx->channels == 2)
s->decorrelation = MID_SIDE;
if (avctx->codec->id == CODEC_ID_SONIC_LS)
{
s->lossless = 1;
s->num_taps = 32;
s->downsampling = 1;
s->quantization = 0.0;
}
else
{
s->num_taps = 128;
s->downsampling = 2;
s->quantization = 1.0;
}
// max tap 2048
if ((s->num_taps < 32) || (s->num_taps > 1024) ||
((s->num_taps>>5)<<5 != s->num_taps))
{
av_log(avctx, AV_LOG_ERROR, "Invalid number of taps\n");
return -1;
}
// generate taps
s->tap_quant = av_mallocz(4* s->num_taps);
for (i = 0; i < s->num_taps; i++)
s->tap_quant[i] = (int)(sqrt(i+1));
s->channels = avctx->channels;
s->samplerate = avctx->sample_rate;
s->block_align = (int)(2048.0*s->samplerate/44100)/s->downsampling;
s->frame_size = s->channels*s->block_align*s->downsampling;
s->tail = av_mallocz(4* s->num_taps*s->channels);
if (!s->tail)
return -1;
s->tail_size = s->num_taps*s->channels;
s->predictor_k = av_mallocz(4 * s->num_taps);
if (!s->predictor_k)
return -1;
for (i = 0; i < s->channels; i++)
{
s->coded_samples[i] = av_mallocz(4* s->block_align);
if (!s->coded_samples[i])
return -1;
}
s->int_samples = av_mallocz(4* s->frame_size);
s->window_size = ((2*s->tail_size)+s->frame_size);
s->window = av_mallocz(4* s->window_size);
if (!s->window)
return -1;
avctx->extradata = av_mallocz(16);
if (!avctx->extradata)
return -1;
init_put_bits(&pb, avctx->extradata, 16*8);
put_bits(&pb, 2, version); // version
if (version == 1)
{
put_bits(&pb, 2, s->channels);
put_bits(&pb, 4, code_samplerate(s->samplerate));
}
put_bits(&pb, 1, s->lossless);
if (!s->lossless)
put_bits(&pb, 3, SAMPLE_SHIFT); // XXX FIXME: sample precision
put_bits(&pb, 2, s->decorrelation);
put_bits(&pb, 2, s->downsampling);
put_bits(&pb, 5, (s->num_taps >> 5)-1); // 32..1024
put_bits(&pb, 1, 0); // XXX FIXME: no custom tap quant table
flush_put_bits(&pb);
avctx->extradata_size = put_bits_count(&pb)/8;
av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n",
version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling);
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
avctx->coded_frame->key_frame = 1;
avctx->frame_size = s->block_align*s->downsampling;
return 0;
}
static av_cold int sonic_encode_close(AVCodecContext *avctx)
{
SonicContext *s = avctx->priv_data;
int i;
av_freep(&avctx->coded_frame);
for (i = 0; i < s->channels; i++)
av_free(s->coded_samples[i]);
av_free(s->predictor_k);
av_free(s->tail);
av_free(s->tap_quant);
av_free(s->window);
av_free(s->int_samples);
return 0;
}
static int sonic_encode_frame(AVCodecContext *avctx,
uint8_t *buf, int buf_size, void *data)
{
SonicContext *s = avctx->priv_data;
PutBitContext pb;
int i, j, ch, quant = 0, x = 0;
short *samples = data;
init_put_bits(&pb, buf, buf_size*8);
// short -> internal
for (i = 0; i < s->frame_size; i++)
s->int_samples[i] = samples[i];
if (!s->lossless)
for (i = 0; i < s->frame_size; i++)
s->int_samples[i] = s->int_samples[i] << SAMPLE_SHIFT;
switch(s->decorrelation)
{
case MID_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
{
s->int_samples[i] += s->int_samples[i+1];
s->int_samples[i+1] -= shift(s->int_samples[i], 1);
}
break;
case LEFT_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
s->int_samples[i+1] -= s->int_samples[i];
break;
case RIGHT_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
s->int_samples[i] -= s->int_samples[i+1];
break;
}
memset(s->window, 0, 4* s->window_size);
for (i = 0; i < s->tail_size; i++)
s->window[x++] = s->tail[i];
for (i = 0; i < s->frame_size; i++)
s->window[x++] = s->int_samples[i];
for (i = 0; i < s->tail_size; i++)
s->window[x++] = 0;
for (i = 0; i < s->tail_size; i++)
s->tail[i] = s->int_samples[s->frame_size - s->tail_size + i];
// generate taps
modified_levinson_durbin(s->window, s->window_size,
s->predictor_k, s->num_taps, s->channels, s->tap_quant);
if (intlist_write(&pb, s->predictor_k, s->num_taps, 0) < 0)
return -1;
for (ch = 0; ch < s->channels; ch++)
{
x = s->tail_size+ch;
for (i = 0; i < s->block_align; i++)
{
int sum = 0;
for (j = 0; j < s->downsampling; j++, x += s->channels)
sum += s->window[x];
s->coded_samples[ch][i] = sum;
}
}
// simple rate control code
if (!s->lossless)
{
double energy1 = 0.0, energy2 = 0.0;
for (ch = 0; ch < s->channels; ch++)
{
for (i = 0; i < s->block_align; i++)
{
double sample = s->coded_samples[ch][i];
energy2 += sample*sample;
energy1 += fabs(sample);
}
}
energy2 = sqrt(energy2/(s->channels*s->block_align));
energy1 = sqrt(2.0)*energy1/(s->channels*s->block_align);
// increase bitrate when samples are like a gaussian distribution
// reduce bitrate when samples are like a two-tailed exponential distribution
if (energy2 > energy1)
energy2 += (energy2-energy1)*RATE_VARIATION;
quant = (int)(BASE_QUANT*s->quantization*energy2/SAMPLE_FACTOR);
// av_log(avctx, AV_LOG_DEBUG, "quant: %d energy: %f / %f\n", quant, energy1, energy2);
if (quant < 1)
quant = 1;
if (quant > 65535)
quant = 65535;
set_ue_golomb(&pb, quant);
quant *= SAMPLE_FACTOR;
}
// write out coded samples
for (ch = 0; ch < s->channels; ch++)
{
if (!s->lossless)
for (i = 0; i < s->block_align; i++)
s->coded_samples[ch][i] = divide(s->coded_samples[ch][i], quant);
if (intlist_write(&pb, s->coded_samples[ch], s->block_align, 1) < 0)
return -1;
}
// av_log(avctx, AV_LOG_DEBUG, "used bytes: %d\n", (put_bits_count(&pb)+7)/8);
flush_put_bits(&pb);
return (put_bits_count(&pb)+7)/8;
}
#endif //CONFIG_ENCODERS
#ifdef CONFIG_DECODERS
static av_cold int sonic_decode_init(AVCodecContext *avctx)
{
SonicContext *s = avctx->priv_data;
GetBitContext gb;
int i, version;
s->channels = avctx->channels;
s->samplerate = avctx->sample_rate;
if (!avctx->extradata)
{
av_log(avctx, AV_LOG_ERROR, "No mandatory headers present\n");
return -1;
}
init_get_bits(&gb, avctx->extradata, avctx->extradata_size);
version = get_bits(&gb, 2);
if (version > 1)
{
av_log(avctx, AV_LOG_ERROR, "Unsupported Sonic version, please report\n");
return -1;
}
if (version == 1)
{
s->channels = get_bits(&gb, 2);
s->samplerate = samplerate_table[get_bits(&gb, 4)];
av_log(avctx, AV_LOG_INFO, "Sonicv2 chans: %d samprate: %d\n",
s->channels, s->samplerate);
}
if (s->channels > MAX_CHANNELS)
{
av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n");
return -1;
}
s->lossless = get_bits1(&gb);
if (!s->lossless)
skip_bits(&gb, 3); // XXX FIXME
s->decorrelation = get_bits(&gb, 2);
s->downsampling = get_bits(&gb, 2);
s->num_taps = (get_bits(&gb, 5)+1)<<5;
if (get_bits1(&gb)) // XXX FIXME
av_log(avctx, AV_LOG_INFO, "Custom quant table\n");
s->block_align = (int)(2048.0*(s->samplerate/44100))/s->downsampling;
s->frame_size = s->channels*s->block_align*s->downsampling;
// avctx->frame_size = s->block_align;
av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n",
version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling);
// generate taps
s->tap_quant = av_mallocz(4* s->num_taps);
for (i = 0; i < s->num_taps; i++)
s->tap_quant[i] = (int)(sqrt(i+1));
s->predictor_k = av_mallocz(4* s->num_taps);
for (i = 0; i < s->channels; i++)
{
s->predictor_state[i] = av_mallocz(4* s->num_taps);
if (!s->predictor_state[i])
return -1;
}
for (i = 0; i < s->channels; i++)
{
s->coded_samples[i] = av_mallocz(4* s->block_align);
if (!s->coded_samples[i])
return -1;
}
s->int_samples = av_mallocz(4* s->frame_size);
avctx->sample_fmt = SAMPLE_FMT_S16;
return 0;
}
static av_cold int sonic_decode_close(AVCodecContext *avctx)
{
SonicContext *s = avctx->priv_data;
int i;
av_free(s->int_samples);
av_free(s->tap_quant);
av_free(s->predictor_k);
for (i = 0; i < s->channels; i++)
{
av_free(s->predictor_state[i]);
av_free(s->coded_samples[i]);
}
return 0;
}
static int sonic_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
SonicContext *s = avctx->priv_data;
GetBitContext gb;
int i, quant, ch, j;
short *samples = data;
if (buf_size == 0) return 0;
// av_log(NULL, AV_LOG_INFO, "buf_size: %d\n", buf_size);
init_get_bits(&gb, buf, buf_size*8);
intlist_read(&gb, s->predictor_k, s->num_taps, 0);
// dequantize
for (i = 0; i < s->num_taps; i++)
s->predictor_k[i] *= s->tap_quant[i];
if (s->lossless)
quant = 1;
else
quant = get_ue_golomb(&gb) * SAMPLE_FACTOR;
// av_log(NULL, AV_LOG_INFO, "quant: %d\n", quant);
for (ch = 0; ch < s->channels; ch++)
{
int x = ch;
predictor_init_state(s->predictor_k, s->predictor_state[ch], s->num_taps);
intlist_read(&gb, s->coded_samples[ch], s->block_align, 1);
for (i = 0; i < s->block_align; i++)
{
for (j = 0; j < s->downsampling - 1; j++)
{
s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, 0);
x += s->channels;
}
s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, s->coded_samples[ch][i] * quant);
x += s->channels;
}
for (i = 0; i < s->num_taps; i++)
s->predictor_state[ch][i] = s->int_samples[s->frame_size - s->channels + ch - i*s->channels];
}
switch(s->decorrelation)
{
case MID_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
{
s->int_samples[i+1] += shift(s->int_samples[i], 1);
s->int_samples[i] -= s->int_samples[i+1];
}
break;
case LEFT_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
s->int_samples[i+1] += s->int_samples[i];
break;
case RIGHT_SIDE:
for (i = 0; i < s->frame_size; i += s->channels)
s->int_samples[i] += s->int_samples[i+1];
break;
}
if (!s->lossless)
for (i = 0; i < s->frame_size; i++)
s->int_samples[i] = shift(s->int_samples[i], SAMPLE_SHIFT);
// internal -> short
for (i = 0; i < s->frame_size; i++)
samples[i] = av_clip_int16(s->int_samples[i]);
align_get_bits(&gb);
*data_size = s->frame_size * 2;
return (get_bits_count(&gb)+7)/8;
}
#endif
#ifdef CONFIG_ENCODERS
AVCodec sonic_encoder = {
"sonic",
CODEC_TYPE_AUDIO,
CODEC_ID_SONIC,
sizeof(SonicContext),
sonic_encode_init,
sonic_encode_frame,
sonic_encode_close,
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Sonic"),
};
AVCodec sonic_ls_encoder = {
"sonicls",
CODEC_TYPE_AUDIO,
CODEC_ID_SONIC_LS,
sizeof(SonicContext),
sonic_encode_init,
sonic_encode_frame,
sonic_encode_close,
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"),
};
#endif
#ifdef CONFIG_DECODERS
AVCodec sonic_decoder = {
"sonic",
CODEC_TYPE_AUDIO,
CODEC_ID_SONIC,
sizeof(SonicContext),
sonic_decode_init,
NULL,
sonic_decode_close,
sonic_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Sonic"),
};
#endif

@ -2,51 +2,55 @@
* Sunplus JPEG tables
* Copyright (c) 2003 the ffmpeg project
*
* This library is free software; you can redistribute it and/or
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SP5X_H
#define SP5X_H
#ifndef FFMPEG_SP5X_H
#define FFMPEG_SP5X_H
static uint8_t sp5x_data_sof[] =
#include <stdint.h>
static const uint8_t sp5x_data_sof[] =
{
0xFF, 0xC0, /* SOF */
0x00, 0x11, /* len */
0x08, /* bits */
0x00, 0xf0, /* height (default: 240) */
0x01, 0x40, /* width (default: 240) */
0x03, /* nb components */
0xFF, 0xC0, /* SOF */
0x00, 0x11, /* len */
0x08, /* bits */
0x00, 0xf0, /* height (default: 240) */
0x01, 0x40, /* width (default: 240) */
0x03, /* nb components */
0x01, 0x22, 0x00, /* 21 vs 22 ? */
0x02, 0x11, 0x01,
0x03, 0x11, 0x01
};
static uint8_t sp5x_data_sos[] =
static const uint8_t sp5x_data_sos[] =
{
0xFF, 0xDA, /* SOS */
0x00, 0x0C, /* len */
0x03, /* nb components */
0xFF, 0xDA, /* SOS */
0x00, 0x0C, /* len */
0x03, /* nb components */
0x01, 0x00,
0x02, 0x11,
0x03, 0x11,
0x00, /* Ss */
0x3F, /* Se */
0x00 /* Ah/Al */
0x00, /* Ss */
0x3F, /* Se */
0x00 /* Ah/Al */
};
static uint8_t sp5x_data_dqt[] =
static const uint8_t sp5x_data_dqt[] =
{
0xFF, 0xDB, /* DQT */
0x00, 0x84, /* len */
@ -70,9 +74,9 @@ static uint8_t sp5x_data_dqt[] =
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
};
static uint8_t sp5x_data_dht[] = {
0xFF, 0xC4, /* DHT */
0x01, 0xA2, /* len */
static const uint8_t sp5x_data_dht[] = {
0xFF, 0xC4, /* DHT */
0x01, 0xA2, /* len */
0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
@ -128,7 +132,7 @@ static uint8_t sp5x_data_dht[] = {
};
static uint8_t sp5x_quant_table[20][64]=
static const uint8_t sp5x_quant_table[20][64]=
{
/* index 0, Q50 */
{ 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
@ -233,7 +237,7 @@ static uint8_t sp5x_quant_table[20][64]=
#if 0
/* 4NF-M, not ZigZag */
static uint8_t sp5x_quant_table_orig[18][64] =
static const uint8_t sp5x_quant_table_orig[18][64] =
{
/* index 0, Q50 */
{ 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55,
@ -257,7 +261,7 @@ static uint8_t sp5x_quant_table_orig[18][64] =
/* index 2, Q80 */
{ 6, 4, 4, 6, 10, 16, 20, 24, 5, 5, 6, 8, 10, 23, 24, 22,
6, 5, 6, 10, 16, 23, 28, 22, 6, 7, 9, 12, 20, 35, 32, 25,
6, 5, 6, 10, 16, 23, 28, 22, 6, 7, 9, 12, 20, 35, 32, 25,
7, 9, 15, 22, 27, 44, 41, 31, 10, 14, 22, 26, 32, 42, 45, 37,
20, 26, 31, 35, 41, 48, 48, 40, 29, 37, 38, 39, 45, 40, 41, 40 },
{ 7, 7, 10, 19, 40, 40, 40, 40, 7, 8, 10, 26, 40, 40, 40, 40,
@ -267,7 +271,7 @@ static uint8_t sp5x_quant_table_orig[18][64] =
/* index 3, Q85 */
{ 5, 3, 3, 5, 7, 12, 15, 18, 4, 4, 4, 6, 8, 17, 18, 17,
4, 4, 5, 7, 12, 17, 21, 17, 4, 5, 7, 9, 15, 26, 24, 19,
4, 4, 5, 7, 12, 17, 21, 17, 4, 5, 7, 9, 15, 26, 24, 19,
5, 7, 11, 17, 20, 33, 31, 23, 7, 11, 17, 19, 24, 31, 34, 28,
15, 19, 23, 26, 31, 36, 36, 30, 22, 28, 29, 29, 34, 30, 31, 30 },
{ 5, 5, 7, 14, 30, 30, 30, 30, 5, 6, 8, 20, 30, 30, 30, 30,
@ -327,4 +331,4 @@ static uint8_t sp5x_quant_table_orig[18][64] =
};
#endif
#endif /* SP5X_H */
#endif /* FFMPEG_SP5X_H */

@ -0,0 +1,215 @@
/*
* Sunplus JPEG decoder (SP5X)
* Copyright (c) 2003 Alex Beregszaszi
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file sp5xdec.c
* Sunplus JPEG decoder (SP5X).
*/
#include "avcodec.h"
#include "mjpeg.h"
#include "mjpegdec.h"
#include "sp5x.h"
static int sp5x_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
#if 0
MJpegDecodeContext *s = avctx->priv_data;
#endif
const int qscale = 5;
const uint8_t *buf_ptr, *buf_end;
uint8_t *recoded;
int i = 0, j = 0;
if (!avctx->width || !avctx->height)
return -1;
buf_ptr = buf;
buf_end = buf + buf_size;
#if 1
recoded = av_mallocz(buf_size + 1024);
if (!recoded)
return -1;
/* SOI */
recoded[j++] = 0xFF;
recoded[j++] = 0xD8;
memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt));
memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64);
memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64);
j += sizeof(sp5x_data_dqt);
memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht));
j += sizeof(sp5x_data_dht);
memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof));
AV_WB16(recoded+j+5, avctx->coded_height);
AV_WB16(recoded+j+7, avctx->coded_width);
j += sizeof(sp5x_data_sof);
memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos));
j += sizeof(sp5x_data_sos);
if(avctx->codec_id==CODEC_ID_AMV)
for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++)
recoded[j++] = buf[i];
else
for (i = 14; i < buf_size && j < buf_size+1024-2; i++)
{
recoded[j++] = buf[i];
if (buf[i] == 0xff)
recoded[j++] = 0;
}
/* EOI */
recoded[j++] = 0xFF;
recoded[j++] = 0xD9;
avctx->flags &= ~CODEC_FLAG_EMU_EDGE;
i = ff_mjpeg_decode_frame(avctx, data, data_size, recoded, j);
av_free(recoded);
#else
/* SOF */
s->bits = 8;
s->width = avctx->coded_width;
s->height = avctx->coded_height;
s->nb_components = 3;
s->component_id[0] = 0;
s->h_count[0] = 2;
s->v_count[0] = 2;
s->quant_index[0] = 0;
s->component_id[1] = 1;
s->h_count[1] = 1;
s->v_count[1] = 1;
s->quant_index[1] = 1;
s->component_id[2] = 2;
s->h_count[2] = 1;
s->v_count[2] = 1;
s->quant_index[2] = 1;
s->h_max = 2;
s->v_max = 2;
s->qscale_table = av_mallocz((s->width+15)/16);
avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420;
s->interlaced = 0;
s->picture.reference = 0;
if (avctx->get_buffer(avctx, &s->picture) < 0)
{
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
s->picture.pict_type = FF_I_TYPE;
s->picture.key_frame = 1;
for (i = 0; i < 3; i++)
s->linesize[i] = s->picture.linesize[i] << s->interlaced;
/* DQT */
for (i = 0; i < 64; i++)
{
j = s->scantable.permutated[i];
s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i];
}
s->qscale[0] = FFMAX(
s->quant_matrixes[0][s->scantable.permutated[1]],
s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1;
for (i = 0; i < 64; i++)
{
j = s->scantable.permutated[i];
s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i];
}
s->qscale[1] = FFMAX(
s->quant_matrixes[1][s->scantable.permutated[1]],
s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1;
/* DHT */
/* SOS */
s->comp_index[0] = 0;
s->nb_blocks[0] = s->h_count[0] * s->v_count[0];
s->h_scount[0] = s->h_count[0];
s->v_scount[0] = s->v_count[0];
s->dc_index[0] = 0;
s->ac_index[0] = 0;
s->comp_index[1] = 1;
s->nb_blocks[1] = s->h_count[1] * s->v_count[1];
s->h_scount[1] = s->h_count[1];
s->v_scount[1] = s->v_count[1];
s->dc_index[1] = 1;
s->ac_index[1] = 1;
s->comp_index[2] = 2;
s->nb_blocks[2] = s->h_count[2] * s->v_count[2];
s->h_scount[2] = s->h_count[2];
s->v_scount[2] = s->v_count[2];
s->dc_index[2] = 1;
s->ac_index[2] = 1;
for (i = 0; i < 3; i++)
s->last_dc[i] = 1024;
s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8);
s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8);
init_get_bits(&s->gb, buf+14, (buf_size-14)*8);
return mjpeg_decode_scan(s);
#endif
return i;
}
AVCodec sp5x_decoder = {
"sp5x",
CODEC_TYPE_VIDEO,
CODEC_ID_SP5X,
sizeof(MJpegDecodeContext),
ff_mjpeg_decode_init,
NULL,
ff_mjpeg_decode_end,
sp5x_decode_frame,
CODEC_CAP_DR1,
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"),
};
AVCodec amv_decoder = {
"amv",
CODEC_TYPE_VIDEO,
CODEC_ID_AMV,
sizeof(MJpegDecodeContext),
ff_mjpeg_decode_init,
NULL,
ff_mjpeg_decode_end,
sp5x_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("AMV Video"),
};

@ -0,0 +1,196 @@
/*
* Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder
* Copyright (c) 2007, 2008 Ivo van Poorten
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#define RT_OLD 0
#define RT_STANDARD 1
#define RT_BYTE_ENCODED 2
#define RT_FORMAT_RGB 3
#define RT_FORMAT_TIFF 4
#define RT_FORMAT_IFF 5
typedef struct SUNRASTContext {
AVFrame picture;
} SUNRASTContext;
static av_cold int sunrast_init(AVCodecContext *avctx) {
SUNRASTContext *s = avctx->priv_data;
avcodec_get_frame_defaults(&s->picture);
avctx->coded_frame= &s->picture;
return 0;
}
static int sunrast_decode_frame(AVCodecContext *avctx, void *data,
int *data_size, const uint8_t *buf, int buf_size) {
SUNRASTContext * const s = avctx->priv_data;
AVFrame *picture = data;
AVFrame * const p = &s->picture;
unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen;
uint8_t *ptr;
const uint8_t *bufstart = buf;
if (AV_RB32(buf) != 0x59a66a95) {
av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n");
return -1;
}
w = AV_RB32(buf+4);
h = AV_RB32(buf+8);
depth = AV_RB32(buf+12);
type = AV_RB32(buf+20);
maptype = AV_RB32(buf+24);
maplength = AV_RB32(buf+28);
if (type > RT_BYTE_ENCODED && type <= RT_FORMAT_IFF) {
av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n");
return -1;
}
if (type > RT_FORMAT_IFF) {
av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n");
return -1;
}
if (maptype & ~1) {
av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n");
return -1;
}
buf += 32;
switch (depth) {
case 1:
avctx->pix_fmt = PIX_FMT_MONOWHITE;
break;
case 8:
avctx->pix_fmt = PIX_FMT_PAL8;
break;
case 24:
avctx->pix_fmt = PIX_FMT_BGR24;
break;
default:
av_log(avctx, AV_LOG_ERROR, "invalid depth\n");
return -1;
}
if (p->data[0])
avctx->release_buffer(avctx, p);
if (avcodec_check_dimensions(avctx, w, h))
return -1;
if (w != avctx->width || h != avctx->height)
avcodec_set_dimensions(avctx, w, h);
if (avctx->get_buffer(avctx, p) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
p->pict_type = FF_I_TYPE;
if (depth != 8 && maplength) {
av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n");
} else if (depth == 8) {
unsigned int len = maplength / 3;
if (!maplength) {
av_log(avctx, AV_LOG_ERROR, "colormap expected\n");
return -1;
}
if (maplength % 3 || maplength > 768) {
av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n");
return -1;
}
ptr = p->data[1];
for (x=0; x<len; x++, ptr+=4)
*(uint32_t *)ptr = (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x];
}
buf += maplength;
ptr = p->data[0];
stride = p->linesize[0];
/* scanlines are aligned on 16 bit boundaries */
len = (depth * w + 7) >> 3;
alen = len + (len&1);
if (type == RT_BYTE_ENCODED) {
int value, run;
uint8_t *end = ptr + h*stride;
x = 0;
while (ptr != end) {
run = 1;
if ((value = *buf++) == 0x80) {
run = *buf++ + 1;
if (run != 1)
value = *buf++;
}
while (run--) {
if (x < len)
ptr[x] = value;
if (++x >= alen) {
x = 0;
ptr += stride;
if (ptr == end)
break;
}
}
}
} else {
for (y=0; y<h; y++) {
memcpy(ptr, buf, len);
ptr += stride;
buf += alen;
}
}
*picture = s->picture;
*data_size = sizeof(AVFrame);
return buf - bufstart;
}
static av_cold int sunrast_end(AVCodecContext *avctx) {
SUNRASTContext *s = avctx->priv_data;
if(s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
return 0;
}
AVCodec sunrast_decoder = {
"sunrast",
CODEC_TYPE_VIDEO,
CODEC_ID_SUNRAST,
sizeof(SUNRASTContext),
sunrast_init,
NULL,
sunrast_end,
sunrast_decode_frame,
0,
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),
};

@ -1,841 +1,43 @@
/*
*
* SVQ1 decoder
* ported to MPlayer by Arpi <arpi@thot.banki.hu>
* ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* Copyright (C) 2002 the xine project
* Copyright (C) 2002 the ffmpeg project
*
* This library is free software; you can redistribute it and/or
*
* SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Ported to mplayer by Arpi <arpi@thot.banki.hu>
* Ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1.c
* Sorenson Vector Quantizer #1 (SVQ1) video decoder.
* Sorenson Vector Quantizer #1 (SVQ1) video codec.
* For more information of the SVQ1 algorithm, visit:
* http://www.pcisys.net/~melanson/codecs/
*/
//#define DEBUG_SVQ1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "bswap.h"
static VLC svq1_block_type;
static VLC svq1_motion_component;
static VLC svq1_intra_multistage[6];
static VLC svq1_inter_multistage[6];
static VLC svq1_intra_mean;
static VLC svq1_inter_mean;
#define MEDIAN(a,b,c) (((a < b) != (b >= c)) ? b : (((a < c) != (c > b)) ? c : a))
#define SVQ1_BLOCK_SKIP 0
#define SVQ1_BLOCK_INTER 1
#define SVQ1_BLOCK_INTER_4V 2
#define SVQ1_BLOCK_INTRA 3
/* motion vector (prediction) */
typedef struct svq1_pmv_s {
int x;
int y;
} svq1_pmv_t;
#include "svq1.h"
#include "svq1_cb.h"
#include "svq1_vlc.h"
static const uint16_t checksum_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
static const uint8_t string_table[256] = {
0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54,
0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D,
0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06,
0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F,
0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0,
0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9,
0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2,
0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B,
0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9,
0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0,
0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B,
0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2,
0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D,
0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44,
0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F,
0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16,
0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB,
0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92,
0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9,
0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0,
0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F,
0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36,
0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D,
0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64,
0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26,
0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F,
0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74,
0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D,
0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82,
0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB,
0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0,
0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9
};
#define SVQ1_PROCESS_VECTOR()\
for (; level > 0; i++) {\
/* process next depth */\
if (i == m) {\
m = n;\
if (--level == 0)\
break;\
}\
/* divide block if next bit set */\
if (get_bits (bitbuf, 1) == 0)\
break;\
/* add child nodes */\
list[n++] = list[i];\
list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1));\
}
#define SVQ1_ADD_CODEBOOK()\
/* add codebook entries to vector */\
for (j=0; j < stages; j++) {\
n3 = codebook[entries[j]] ^ 0x80808080;\
n1 += ((n3 & 0xFF00FF00) >> 8);\
n2 += (n3 & 0x00FF00FF);\
}\
\
/* clip to [0..255] */\
if (n1 & 0xFF00FF00) {\
n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n1 += 0x7F007F00;\
n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n1 &= (n3 & 0x00FF00FF);\
}\
\
if (n2 & 0xFF00FF00) {\
n3 = ((( n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n2 += 0x7F007F00;\
n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n2 &= (n3 & 0x00FF00FF);\
}
#define SVQ1_DO_CODEBOOK_INTRA()\
for (y=0; y < height; y++) {\
for (x=0; x < (width / 4); x++, codebook++) {\
n1 = n4;\
n2 = n4;\
SVQ1_ADD_CODEBOOK()\
/* store result */\
dst[x] = (n1 << 8) | n2;\
}\
dst += (pitch / 4);\
}
#define SVQ1_DO_CODEBOOK_NONINTRA()\
for (y=0; y < height; y++) {\
for (x=0; x < (width / 4); x++, codebook++) {\
n3 = dst[x];\
/* add mean value to vector */\
n1 = ((n3 & 0xFF00FF00) >> 8) + n4;\
n2 = (n3 & 0x00FF00FF) + n4;\
SVQ1_ADD_CODEBOOK()\
/* store result */\
dst[x] = (n1 << 8) | n2;\
}\
dst += (pitch / 4);\
}
#define SVQ1_CALC_CODEBOOK_ENTRIES(cbook)\
codebook = (const uint32_t *) cbook[level];\
bit_cache = get_bits (bitbuf, 4*stages);\
/* calculate codebook entries for this vector */\
for (j=0; j < stages; j++) {\
entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1);\
}\
mean -= (stages * 128);\
n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF);
static int svq1_decode_block_intra (GetBitContext *bitbuf, uint8_t *pixels, int pitch ) {
uint32_t bit_cache;
uint8_t *list[63];
uint32_t *dst;
const uint32_t *codebook;
int entries[6];
int i, j, m, n;
int mean, stages;
unsigned x, y, width, height, level;
uint32_t n1, n2, n3, n4;
/* initialize list for breadth first processing of vectors */
list[0] = pixels;
/* recursively process vector */
for (i=0, m=1, n=1, level=5; i < n; i++) {
SVQ1_PROCESS_VECTOR();
/* destination address and vector size */
dst = (uint32_t *) list[i];
width = 1 << ((4 + level) /2);
height = 1 << ((3 + level) /2);
/* get number of stages (-1 skips vector, 0 for mean only) */
stages = get_vlc2(bitbuf, svq1_intra_multistage[level].table, 3, 3) - 1;
if (stages == -1) {
for (y=0; y < height; y++) {
memset (&dst[y*(pitch / 4)], 0, width);
}
continue; /* skip vector */
}
if ((stages > 0) && (level >= 4)) {
#ifdef DEBUG_SVQ1
printf("Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level);
#endif
return -1; /* invalid vector */
}
mean = get_vlc2(bitbuf, svq1_intra_mean.table, 8, 3);
if (stages == 0) {
for (y=0; y < height; y++) {
memset (&dst[y*(pitch / 4)], mean, width);
}
} else {
SVQ1_CALC_CODEBOOK_ENTRIES(svq1_intra_codebooks);
SVQ1_DO_CODEBOOK_INTRA()
}
}
return 0;
}
static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels, int pitch ) {
uint32_t bit_cache;
uint8_t *list[63];
uint32_t *dst;
const uint32_t *codebook;
int entries[6];
int i, j, m, n;
int mean, stages;
int x, y, width, height, level;
uint32_t n1, n2, n3, n4;
/* initialize list for breadth first processing of vectors */
list[0] = pixels;
/* recursively process vector */
for (i=0, m=1, n=1, level=5; i < n; i++) {
SVQ1_PROCESS_VECTOR();
/* destination address and vector size */
dst = (uint32_t *) list[i];
width = 1 << ((4 + level) /2);
height = 1 << ((3 + level) /2);
/* get number of stages (-1 skips vector, 0 for mean only) */
stages = get_vlc2(bitbuf, svq1_inter_multistage[level].table, 3, 2) - 1;
if (stages == -1) continue; /* skip vector */
if ((stages > 0) && (level >= 4)) {
#ifdef DEBUG_SVQ1
printf("Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level);
#endif
return -1; /* invalid vector */
}
mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256;
SVQ1_CALC_CODEBOOK_ENTRIES(svq1_inter_codebooks);
SVQ1_DO_CODEBOOK_NONINTRA()
}
return 0;
}
static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq1_pmv_t **pmv) {
int diff;
int i;
for (i=0; i < 2; i++) {
/* get motion code */
diff = get_vlc2(bitbuf, svq1_motion_component.table, 7, 2) - 32;
/* add median of motion vector predictors and clip result */
if (i == 1)
mv->y = ((diff + MEDIAN(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26;
else
mv->x = ((diff + MEDIAN(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26;
}
return 0;
}
static void svq1_skip_block (uint8_t *current, uint8_t *previous, int pitch, int x, int y) {
uint8_t *src;
uint8_t *dst;
int i;
src = &previous[x + y*pitch];
dst = current;
for (i=0; i < 16; i++) {
memcpy (dst, src, 16);
src += pitch;
dst += pitch;
}
}
static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion, int x, int y) {
uint8_t *src;
uint8_t *dst;
svq1_pmv_t mv;
svq1_pmv_t *pmv[3];
int result;
/* predict and decode motion vector */
pmv[0] = &motion[0];
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 2];
pmv[2] = &motion[(x / 8) + 4];
}
result = svq1_decode_motion_vector (bitbuf, &mv, pmv);
if (result != 0)
return result;
motion[0].x =
motion[(x / 8) + 2].x =
motion[(x / 8) + 3].x = mv.x;
motion[0].y =
motion[(x / 8) + 2].y =
motion[(x / 8) + 3].y = mv.y;
if(y + (mv.y >> 1)<0)
mv.y= 0;
if(x + (mv.x >> 1)<0)
mv.x= 0;
#if 0
int w= (s->width+15)&~15;
int h= (s->height+15)&~15;
if(x + (mv.x >> 1)<0 || y + (mv.y >> 1)<0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16> h)
printf("%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1));
#endif
src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch];
dst = current;
s->dsp.put_pixels_tab[0][((mv.y & 1) << 1) | (mv.x & 1)](dst,src,pitch,16);
return 0;
}
static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion,int x, int y) {
uint8_t *src;
uint8_t *dst;
svq1_pmv_t mv;
svq1_pmv_t *pmv[4];
int i, result;
/* predict and decode motion vector (0) */
pmv[0] = &motion[0];
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 2];
pmv[2] = &motion[(x / 8) + 4];
}
result = svq1_decode_motion_vector (bitbuf, &mv, pmv);
if (result != 0)
return result;
/* predict and decode motion vector (1) */
pmv[0] = &mv;
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 3];
}
result = svq1_decode_motion_vector (bitbuf, &motion[0], pmv);
if (result != 0)
return result;
/* predict and decode motion vector (2) */
pmv[1] = &motion[0];
pmv[2] = &motion[(x / 8) + 1];
result = svq1_decode_motion_vector (bitbuf, &motion[(x / 8) + 2], pmv);
if (result != 0)
return result;
/* predict and decode motion vector (3) */
pmv[2] = &motion[(x / 8) + 2];
pmv[3] = &motion[(x / 8) + 3];
result = svq1_decode_motion_vector (bitbuf, pmv[3], pmv);
if (result != 0)
return result;
/* form predictions */
for (i=0; i < 4; i++) {
int mvx= pmv[i]->x + (i&1)*16;
int mvy= pmv[i]->y + (i>>1)*16;
///XXX /FIXME cliping or padding?
if(y + (mvy >> 1)<0)
mvy= 0;
if(x + (mvx >> 1)<0)
mvx= 0;
#if 0
int w= (s->width+15)&~15;
int h= (s->height+15)&~15;
if(x + (mvx >> 1)<0 || y + (mvy >> 1)<0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8> h)
printf("%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1));
#endif
src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch];
dst = current;
s->dsp.put_pixels_tab[1][((mvy & 1) << 1) | (mvx & 1)](dst,src,pitch,8);
/* select next block */
if (i & 1) {
current += 8*(pitch - 1);
} else {
current += 8;
}
}
return 0;
}
static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion, int x, int y) {
uint32_t block_type;
int result = 0;
/* get block type */
block_type = get_vlc2(bitbuf, svq1_block_type.table, 2, 2);
/* reset motion vectors */
if (block_type == SVQ1_BLOCK_SKIP || block_type == SVQ1_BLOCK_INTRA) {
motion[0].x =
motion[0].y =
motion[(x / 8) + 2].x =
motion[(x / 8) + 2].y =
motion[(x / 8) + 3].x =
motion[(x / 8) + 3].y = 0;
}
switch (block_type) {
case SVQ1_BLOCK_SKIP:
svq1_skip_block (current, previous, pitch, x, y);
break;
case SVQ1_BLOCK_INTER:
result = svq1_motion_inter_block (s, bitbuf, current, previous, pitch, motion, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
printf("Error in svq1_motion_inter_block %i\n",result);
#endif
break;
}
result = svq1_decode_block_non_intra (bitbuf, current, pitch);
break;
case SVQ1_BLOCK_INTER_4V:
result = svq1_motion_inter_4v_block (s, bitbuf, current, previous, pitch, motion, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
printf("Error in svq1_motion_inter_4v_block %i\n",result);
#endif
break;
}
result = svq1_decode_block_non_intra (bitbuf, current, pitch);
break;
case SVQ1_BLOCK_INTRA:
result = svq1_decode_block_intra (bitbuf, current, pitch);
break;
}
return result;
}
/* standard video sizes */
static struct { int width; int height; } svq1_frame_size_table[8] = {
const svq1_frame_size_t ff_svq1_frame_size_table[8] = {
{ 160, 120 }, { 128, 96 }, { 176, 144 }, { 352, 288 },
{ 704, 576 }, { 240, 180 }, { 320, 240 }, { -1, -1 }
};
static uint16_t svq1_packet_checksum (uint8_t *data, int length, int value) {
int i;
for (i=0; i < length; i++) {
value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8);
}
return value;
}
static uint16_t svq1_component_checksum (uint16_t *pixels, int pitch,
int width, int height, int value) {
int x, y;
for (y=0; y < height; y++) {
for (x=0; x < width; x++) {
value = checksum_table[pixels[x] ^ (value >> 8)] ^ ((value & 0xFF) << 8);
}
pixels += pitch;
}
return value;
}
static void svq1_parse_string (GetBitContext *bitbuf, uint8_t *out) {
uint8_t seed;
int i;
out[0] = get_bits (bitbuf, 8);
seed = string_table[out[0]];
for (i=1; i <= out[0]; i++) {
out[i] = get_bits (bitbuf, 8) ^ seed;
seed = string_table[out[i] ^ seed];
}
}
static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) {
int frame_size_code;
int temporal_reference;
temporal_reference = get_bits (bitbuf, 8);
/* frame type */
s->pict_type= get_bits (bitbuf, 2)+1;
if(s->pict_type==4)
return -1;
if (s->pict_type == I_TYPE) {
/* unknown fields */
if (s->f_code == 0x50 || s->f_code == 0x60) {
int csum = get_bits (bitbuf, 16);
csum = svq1_packet_checksum ((uint8_t *)bitbuf->buffer, bitbuf->size_in_bits>>3, csum);
// printf ("%s checksum (%02x) for packet data\n",
// (csum == 0) ? "correct" : "incorrect", csum);
}
if ((s->f_code ^ 0x10) >= 0x50) {
char msg[256];
svq1_parse_string (bitbuf, (char *) msg);
av_log(s->avctx, AV_LOG_INFO, "embedded message: \"%s\"\n", (char *) msg);
}
skip_bits (bitbuf, 2);
skip_bits (bitbuf, 2);
skip_bits1 (bitbuf);
/* load frame size */
frame_size_code = get_bits (bitbuf, 3);
if (frame_size_code == 7) {
/* load width, height (12 bits each) */
s->width = get_bits (bitbuf, 12);
s->height = get_bits (bitbuf, 12);
if (!s->width || !s->height)
return -1;
} else {
/* get width, height from table */
s->width = svq1_frame_size_table[frame_size_code].width;
s->height = svq1_frame_size_table[frame_size_code].height;
}
}
/* unknown fields */
if (get_bits (bitbuf, 1) == 1) {
skip_bits1 (bitbuf); /* use packet checksum if (1) */
skip_bits1 (bitbuf); /* component checksums after image data if (1) */
if (get_bits (bitbuf, 2) != 0)
return -1;
}
if (get_bits (bitbuf, 1) == 1) {
skip_bits1 (bitbuf);
skip_bits (bitbuf, 4);
skip_bits1 (bitbuf);
skip_bits (bitbuf, 2);
while (get_bits (bitbuf, 1) == 1) {
skip_bits (bitbuf, 8);
}
}
return 0;
}
static int svq1_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
MpegEncContext *s=avctx->priv_data;
uint8_t *current, *previous;
int result, i, x, y, width, height;
AVFrame *pict = data;
/* initialize bit buffer */
init_get_bits(&s->gb,buf,buf_size*8);
/* decode frame header */
s->f_code = get_bits (&s->gb, 22);
if ((s->f_code & ~0x70) || !(s->f_code & 0x60))
return -1;
/* swap some header bytes (why?) */
if (s->f_code != 0x20) {
uint32_t *src = (uint32_t *) (buf + 4);
for (i=0; i < 4; i++) {
src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i];
}
}
result = svq1_decode_frame_header (&s->gb, s);
if (result != 0)
{
#ifdef DEBUG_SVQ1
printf("Error in svq1_decode_frame_header %i\n",result);
#endif
return result;
}
//FIXME this avoids some confusion for "B frames" without 2 references
//this should be removed after libavcodec can handle more flaxible picture types & ordering
if(s->pict_type==B_TYPE && s->last_picture_ptr==NULL) return buf_size;
if(avctx->hurry_up && s->pict_type==B_TYPE) return buf_size;
if(MPV_frame_start(s, avctx) < 0)
return -1;
/* decode y, u and v components */
for (i=0; i < 3; i++) {
int linesize;
if (i == 0) {
width = (s->width+15)&~15;
height = (s->height+15)&~15;
linesize= s->linesize;
} else {
if(s->flags&CODEC_FLAG_GRAY) break;
width = (s->width/4+15)&~15;
height = (s->height/4+15)&~15;
linesize= s->uvlinesize;
}
current = s->current_picture.data[i];
if(s->pict_type==B_TYPE){
previous = s->next_picture.data[i];
}else{
previous = s->last_picture.data[i];
}
if (s->pict_type == I_TYPE) {
/* keyframe */
for (y=0; y < height; y+=16) {
for (x=0; x < width; x+=16) {
result = svq1_decode_block_intra (&s->gb, &current[x], linesize);
if (result != 0)
{
#ifdef DEBUG_SVQ1
printf("Error in svq1_decode_block %i (keyframe)\n",result);
#endif
return result;
}
}
current += 16*linesize;
}
} else {
svq1_pmv_t pmv[width/8+3];
/* delta frame */
memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv_t));
for (y=0; y < height; y+=16) {
for (x=0; x < width; x+=16) {
result = svq1_decode_delta_block (s, &s->gb, &current[x], previous,
linesize, pmv, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
printf("Error in svq1_decode_delta_block %i\n",result);
#endif
return result;
}
}
pmv[0].x =
pmv[0].y = 0;
current += 16*linesize;
}
}
}
*pict = *(AVFrame*)&s->current_picture;
MPV_frame_end(s);
*data_size=sizeof(AVFrame);
return buf_size;
}
static int svq1_decode_init(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
int i;
s->avctx = avctx;
s->width = (avctx->width+3)&~3;
s->height = (avctx->height+3)&~3;
s->codec_id= avctx->codec->id;
avctx->pix_fmt = PIX_FMT_YUV410P;
avctx->has_b_frames= 1; // not true, but DP frames and these behave like unidirectional b frames
if (MPV_common_init(s) < 0) return -1;
init_vlc(&svq1_block_type, 2, 4,
&svq1_block_type_vlc[0][1], 2, 1,
&svq1_block_type_vlc[0][0], 2, 1);
init_vlc(&svq1_motion_component, 7, 65,
&svq1_motion_component_vlc[0][1], 4, 2,
&svq1_motion_component_vlc[0][0], 4, 2);
for (i = 0; i < 6; i++) {
init_vlc(&svq1_intra_multistage[i], 3, 8,
&svq1_intra_multistage_vlc[i][0][1], 2, 1,
&svq1_intra_multistage_vlc[i][0][0], 2, 1);
init_vlc(&svq1_inter_multistage[i], 3, 8,
&svq1_inter_multistage_vlc[i][0][1], 2, 1,
&svq1_inter_multistage_vlc[i][0][0], 2, 1);
}
init_vlc(&svq1_intra_mean, 8, 256,
&svq1_intra_mean_vlc[0][1], 4, 2,
&svq1_intra_mean_vlc[0][0], 4, 2);
init_vlc(&svq1_inter_mean, 9, 512,
&svq1_inter_mean_vlc[0][1], 4, 2,
&svq1_inter_mean_vlc[0][0], 4, 2);
return 0;
}
static int svq1_decode_end(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
MPV_common_end(s);
return 0;
}
AVCodec svq1_decoder = {
"svq1",
CODEC_TYPE_VIDEO,
CODEC_ID_SVQ1,
sizeof(MpegEncContext),
svq1_decode_init,
NULL,
svq1_decode_end,
svq1_decode_frame,
CODEC_CAP_DR1,
.flush= ff_mpeg_flush,
};

@ -0,0 +1,61 @@
/*
* SVQ1 decoder
* ported to MPlayer by Arpi <arpi@thot.banki.hu>
* ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* Copyright (C) 2002 the xine project
* Copyright (C) 2002 the ffmpeg project
*
* SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1.h
* Sorenson Vector Quantizer #1 (SVQ1) video codec.
* For more information of the SVQ1 algorithm, visit:
* http://www.pcisys.net/~melanson/codecs/
*/
#ifndef FFMPEG_SVQ1_H
#define FFMPEG_SVQ1_H
#include <stdint.h>
#define SVQ1_BLOCK_SKIP 0
#define SVQ1_BLOCK_INTER 1
#define SVQ1_BLOCK_INTER_4V 2
#define SVQ1_BLOCK_INTRA 3
typedef struct {
int width;
int height;
} svq1_frame_size_t;
extern const int8_t* const ff_svq1_inter_codebooks[6];
extern const int8_t* const ff_svq1_intra_codebooks[6];
extern const uint8_t ff_svq1_block_type_vlc[4][2];
extern const uint8_t ff_svq1_intra_multistage_vlc[6][8][2];
extern const uint8_t ff_svq1_inter_multistage_vlc[6][8][2];
extern const uint16_t ff_svq1_intra_mean_vlc[256][2];
extern const uint16_t ff_svq1_inter_mean_vlc[512][2];
extern const svq1_frame_size_t ff_svq1_frame_size_table[8];
#endif /* FFMPEG_SVQ1_H */

@ -1,32 +1,39 @@
/*
*
* SVQ1 decoder
* ported to MPlayer by Arpi <arpi@thot.banki.hu>
* ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* Copyright (C) 2002 the xine project
* Copyright (C) 2002 the ffmpeg project
*
* This library is free software; you can redistribute it and/or
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Ported to mplayer by Arpi <arpi@thot.banki.hu>
* Ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1_cb.h
* svq1 code books.
*/
#ifndef FFMPEG_SVQ1_CB_H
#define FFMPEG_SVQ1_CB_H
#include <stdint.h>
#include <stdlib.h>
/* 6x16-entry codebook for inter-coded 4x2 vectors */
static const int8_t svq1_inter_codebook_4x2[768] = {
7, 2, -6, -7, 7, 3, -3, -4, -7, -2, 7, 8, -8, -4, 3, 4,
@ -764,9 +771,10 @@ static const int8_t svq1_inter_codebook_8x8[6144] = {
};
/* list of codebooks for inter-coded vectors */
static const uint8_t* const svq1_inter_codebooks[4] = {
const int8_t* const ff_svq1_inter_codebooks[6] = {
svq1_inter_codebook_4x2, svq1_inter_codebook_4x4,
svq1_inter_codebook_8x4, svq1_inter_codebook_8x8
svq1_inter_codebook_8x4, svq1_inter_codebook_8x8,
NULL, NULL,
};
/* 6x16-entry codebook for intra-coded 4x2 vectors */
@ -1506,7 +1514,10 @@ static const int8_t svq1_intra_codebook_8x8[6144] = {
};
/* list of codebooks for intra-coded vectors */
static const uint8_t* const svq1_intra_codebooks[4] = {
const int8_t* const ff_svq1_intra_codebooks[6] = {
svq1_intra_codebook_4x2, svq1_intra_codebook_4x4,
svq1_intra_codebook_8x4, svq1_intra_codebook_8x8
svq1_intra_codebook_8x4, svq1_intra_codebook_8x8,
NULL, NULL,
};
#endif /* FFMPEG_SVQ1_CB_H */

@ -1,37 +1,37 @@
#ifndef SVQ1_VLC_H
#define SVQ1_VLC_H
/*
* copyright (C) 2003 the ffmpeg project
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFMPEG_SVQ1_VLC_H
#define FFMPEG_SVQ1_VLC_H
#include <stdint.h>
/* values in this table range from 0..3; adjust retrieved value by +0 */
static const uint8_t svq1_block_type_vlc[4][2] = {
const uint8_t ff_svq1_block_type_vlc[4][2] = {
/* { code, length } */
{ 0x1, 1 }, { 0x1, 2 }, { 0x1, 3 }, { 0x0, 3 }
};
/* values in this table range from -32..32; adjust retrieved value by -32 */
static const uint16_t svq1_motion_component_vlc[65][2] = {
/* { code, length } */
{ 0x5, 13 }, { 0x7, 13 }, { 0x5, 12 }, { 0x7, 12 },
{ 0x9, 12 }, { 0xB, 12 }, { 0xD, 12 }, { 0xF, 12 },
{ 0x9, 11 }, { 0xB, 11 }, { 0xD, 11 }, { 0xF, 11 },
{ 0x11, 11 }, { 0x13, 11 }, { 0x15, 11 }, { 0x17, 11 },
{ 0x19, 11 }, { 0x1B, 11 }, { 0x1D, 11 }, { 0x1F, 11 },
{ 0x21, 11 }, { 0x23, 11 }, { 0x13, 10 }, { 0x15, 10 },
{ 0x17, 10 }, { 0x7, 8 }, { 0x9, 8 }, { 0xB, 8 },
{ 0x7, 7 }, { 0x3, 5 }, { 0x3, 4 }, { 0x3, 3 },
{ 0x1, 1 }, { 0x2, 3 }, { 0x2, 4 }, { 0x2, 5 },
{ 0x6, 7 }, { 0xA, 8 }, { 0x8, 8 }, { 0x6, 8 },
{ 0x16, 10 }, { 0x14, 10 }, { 0x12, 10 }, { 0x22, 11 },
{ 0x20, 11 }, { 0x1E, 11 }, { 0x1C, 11 }, { 0x1A, 11 },
{ 0x18, 11 }, { 0x16, 11 }, { 0x14, 11 }, { 0x12, 11 },
{ 0x10, 11 }, { 0xE, 11 }, { 0xC, 11 }, { 0xA, 11 },
{ 0x8, 11 }, { 0xE, 12 }, { 0xC, 12 }, { 0xA, 12 },
{ 0x8, 12 }, { 0x6, 12 }, { 0x4, 12 }, { 0x6, 13 },
{ 0x4, 13 }
};
/* values in this table range from -1..6; adjust retrieved value by -1 */
static const uint8_t svq1_intra_multistage_vlc[6][8][2] = {
const uint8_t ff_svq1_intra_multistage_vlc[6][8][2] = {
/* { code, length } */
{
{ 0x1, 5 }, { 0x1, 1 }, { 0x3, 3 }, { 0x2, 3 },
@ -55,7 +55,7 @@ static const uint8_t svq1_intra_multistage_vlc[6][8][2] = {
};
/* values in this table range from -1..6; adjust retrieved value by -1 */
static const uint8_t svq1_inter_multistage_vlc[6][8][2] = {
const uint8_t ff_svq1_inter_multistage_vlc[6][8][2] = {
/* { code, length } */
{
{ 0x3, 2 }, { 0x5, 3 }, { 0x4, 3 }, { 0x3, 3 },
@ -79,7 +79,7 @@ static const uint8_t svq1_inter_multistage_vlc[6][8][2] = {
};
/* values in this table range from 0..255; adjust retrieved value by +0 */
static const uint16_t svq1_intra_mean_vlc[256][2] = {
const uint16_t ff_svq1_intra_mean_vlc[256][2] = {
/* { code, length } */
{ 0x37, 6 }, { 0x56, 7 }, { 0x1, 17 }, { 0x1, 20 },
{ 0x2, 20 }, { 0x3, 20 }, { 0x0, 20 }, { 0x4, 20 },
@ -148,7 +148,7 @@ static const uint16_t svq1_intra_mean_vlc[256][2] = {
};
/* values in this table range from -256..255; adjust retrieved value by -256 */
static const uint16_t svq1_inter_mean_vlc[512][2] = {
const uint16_t ff_svq1_inter_mean_vlc[512][2] = {
/* { code, length } */
{ 0x5A, 22 }, { 0xD4, 22 }, { 0xD5, 22 }, { 0xD6, 22 },
{ 0xD7, 22 }, { 0xD8, 22 }, { 0xD9, 22 }, { 0xDA, 22 },
@ -280,4 +280,4 @@ static const uint16_t svq1_inter_mean_vlc[512][2] = {
{ 0x3, 22 }, { 0x2, 22 }, { 0x1, 22 }, { 0x0, 22 }
};
#endif
#endif /* FFMPEG_SVQ1_VLC_H */

@ -0,0 +1,830 @@
/*
* SVQ1 decoder
* ported to MPlayer by Arpi <arpi@thot.banki.hu>
* ported to libavcodec by Nick Kurshev <nickols_k@mail.ru>
*
* Copyright (C) 2002 the xine project
* Copyright (C) 2002 the ffmpeg project
*
* SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1.c
* Sorenson Vector Quantizer #1 (SVQ1) video codec.
* For more information of the SVQ1 algorithm, visit:
* http://www.pcisys.net/~melanson/codecs/
*/
//#define DEBUG_SVQ1
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "svq1.h"
#undef NDEBUG
#include <assert.h>
extern const uint8_t mvtab[33][2];
static VLC svq1_block_type;
static VLC svq1_motion_component;
static VLC svq1_intra_multistage[6];
static VLC svq1_inter_multistage[6];
static VLC svq1_intra_mean;
static VLC svq1_inter_mean;
/* motion vector (prediction) */
typedef struct svq1_pmv_s {
int x;
int y;
} svq1_pmv_t;
static const uint16_t checksum_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
static const uint8_t string_table[256] = {
0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54,
0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D,
0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06,
0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F,
0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0,
0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9,
0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2,
0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B,
0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9,
0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0,
0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B,
0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2,
0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D,
0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44,
0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F,
0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16,
0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB,
0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92,
0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9,
0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0,
0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F,
0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36,
0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D,
0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64,
0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26,
0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F,
0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74,
0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D,
0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82,
0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB,
0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0,
0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9
};
#define SVQ1_PROCESS_VECTOR()\
for (; level > 0; i++) {\
/* process next depth */\
if (i == m) {\
m = n;\
if (--level == 0)\
break;\
}\
/* divide block if next bit set */\
if (get_bits1 (bitbuf) == 0)\
break;\
/* add child nodes */\
list[n++] = list[i];\
list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1));\
}
#define SVQ1_ADD_CODEBOOK()\
/* add codebook entries to vector */\
for (j=0; j < stages; j++) {\
n3 = codebook[entries[j]] ^ 0x80808080;\
n1 += ((n3 & 0xFF00FF00) >> 8);\
n2 += (n3 & 0x00FF00FF);\
}\
\
/* clip to [0..255] */\
if (n1 & 0xFF00FF00) {\
n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n1 += 0x7F007F00;\
n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n1 &= (n3 & 0x00FF00FF);\
}\
\
if (n2 & 0xFF00FF00) {\
n3 = ((( n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n2 += 0x7F007F00;\
n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;\
n2 &= (n3 & 0x00FF00FF);\
}
#define SVQ1_DO_CODEBOOK_INTRA()\
for (y=0; y < height; y++) {\
for (x=0; x < (width / 4); x++, codebook++) {\
n1 = n4;\
n2 = n4;\
SVQ1_ADD_CODEBOOK()\
/* store result */\
dst[x] = (n1 << 8) | n2;\
}\
dst += (pitch / 4);\
}
#define SVQ1_DO_CODEBOOK_NONINTRA()\
for (y=0; y < height; y++) {\
for (x=0; x < (width / 4); x++, codebook++) {\
n3 = dst[x];\
/* add mean value to vector */\
n1 = ((n3 & 0xFF00FF00) >> 8) + n4;\
n2 = (n3 & 0x00FF00FF) + n4;\
SVQ1_ADD_CODEBOOK()\
/* store result */\
dst[x] = (n1 << 8) | n2;\
}\
dst += (pitch / 4);\
}
#define SVQ1_CALC_CODEBOOK_ENTRIES(cbook)\
codebook = (const uint32_t *) cbook[level];\
bit_cache = get_bits (bitbuf, 4*stages);\
/* calculate codebook entries for this vector */\
for (j=0; j < stages; j++) {\
entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1);\
}\
mean -= (stages * 128);\
n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF);
static int svq1_decode_block_intra (GetBitContext *bitbuf, uint8_t *pixels, int pitch ) {
uint32_t bit_cache;
uint8_t *list[63];
uint32_t *dst;
const uint32_t *codebook;
int entries[6];
int i, j, m, n;
int mean, stages;
unsigned x, y, width, height, level;
uint32_t n1, n2, n3, n4;
/* initialize list for breadth first processing of vectors */
list[0] = pixels;
/* recursively process vector */
for (i=0, m=1, n=1, level=5; i < n; i++) {
SVQ1_PROCESS_VECTOR();
/* destination address and vector size */
dst = (uint32_t *) list[i];
width = 1 << ((4 + level) /2);
height = 1 << ((3 + level) /2);
/* get number of stages (-1 skips vector, 0 for mean only) */
stages = get_vlc2(bitbuf, svq1_intra_multistage[level].table, 3, 3) - 1;
if (stages == -1) {
for (y=0; y < height; y++) {
memset (&dst[y*(pitch / 4)], 0, width);
}
continue; /* skip vector */
}
if ((stages > 0) && (level >= 4)) {
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level);
#endif
return -1; /* invalid vector */
}
mean = get_vlc2(bitbuf, svq1_intra_mean.table, 8, 3);
if (stages == 0) {
for (y=0; y < height; y++) {
memset (&dst[y*(pitch / 4)], mean, width);
}
} else {
SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_intra_codebooks);
SVQ1_DO_CODEBOOK_INTRA()
}
}
return 0;
}
static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels, int pitch ) {
uint32_t bit_cache;
uint8_t *list[63];
uint32_t *dst;
const uint32_t *codebook;
int entries[6];
int i, j, m, n;
int mean, stages;
int x, y, width, height, level;
uint32_t n1, n2, n3, n4;
/* initialize list for breadth first processing of vectors */
list[0] = pixels;
/* recursively process vector */
for (i=0, m=1, n=1, level=5; i < n; i++) {
SVQ1_PROCESS_VECTOR();
/* destination address and vector size */
dst = (uint32_t *) list[i];
width = 1 << ((4 + level) /2);
height = 1 << ((3 + level) /2);
/* get number of stages (-1 skips vector, 0 for mean only) */
stages = get_vlc2(bitbuf, svq1_inter_multistage[level].table, 3, 2) - 1;
if (stages == -1) continue; /* skip vector */
if ((stages > 0) && (level >= 4)) {
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level);
#endif
return -1; /* invalid vector */
}
mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256;
SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_inter_codebooks);
SVQ1_DO_CODEBOOK_NONINTRA()
}
return 0;
}
static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq1_pmv_t **pmv) {
int diff;
int i;
for (i=0; i < 2; i++) {
/* get motion code */
diff = get_vlc2(bitbuf, svq1_motion_component.table, 7, 2);
if(diff<0)
return -1;
else if(diff){
if(get_bits1(bitbuf)) diff= -diff;
}
/* add median of motion vector predictors and clip result */
if (i == 1)
mv->y = ((diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26;
else
mv->x = ((diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26;
}
return 0;
}
static void svq1_skip_block (uint8_t *current, uint8_t *previous, int pitch, int x, int y) {
uint8_t *src;
uint8_t *dst;
int i;
src = &previous[x + y*pitch];
dst = current;
for (i=0; i < 16; i++) {
memcpy (dst, src, 16);
src += pitch;
dst += pitch;
}
}
static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion, int x, int y) {
uint8_t *src;
uint8_t *dst;
svq1_pmv_t mv;
svq1_pmv_t *pmv[3];
int result;
/* predict and decode motion vector */
pmv[0] = &motion[0];
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 2];
pmv[2] = &motion[(x / 8) + 4];
}
result = svq1_decode_motion_vector (bitbuf, &mv, pmv);
if (result != 0)
return result;
motion[0].x =
motion[(x / 8) + 2].x =
motion[(x / 8) + 3].x = mv.x;
motion[0].y =
motion[(x / 8) + 2].y =
motion[(x / 8) + 3].y = mv.y;
if(y + (mv.y >> 1)<0)
mv.y= 0;
if(x + (mv.x >> 1)<0)
mv.x= 0;
#if 0
int w= (s->width+15)&~15;
int h= (s->height+15)&~15;
if(x + (mv.x >> 1)<0 || y + (mv.y >> 1)<0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16> h)
av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1));
#endif
src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch];
dst = current;
s->dsp.put_pixels_tab[0][((mv.y & 1) << 1) | (mv.x & 1)](dst,src,pitch,16);
return 0;
}
static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion,int x, int y) {
uint8_t *src;
uint8_t *dst;
svq1_pmv_t mv;
svq1_pmv_t *pmv[4];
int i, result;
/* predict and decode motion vector (0) */
pmv[0] = &motion[0];
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 2];
pmv[2] = &motion[(x / 8) + 4];
}
result = svq1_decode_motion_vector (bitbuf, &mv, pmv);
if (result != 0)
return result;
/* predict and decode motion vector (1) */
pmv[0] = &mv;
if (y == 0) {
pmv[1] =
pmv[2] = pmv[0];
}
else {
pmv[1] = &motion[(x / 8) + 3];
}
result = svq1_decode_motion_vector (bitbuf, &motion[0], pmv);
if (result != 0)
return result;
/* predict and decode motion vector (2) */
pmv[1] = &motion[0];
pmv[2] = &motion[(x / 8) + 1];
result = svq1_decode_motion_vector (bitbuf, &motion[(x / 8) + 2], pmv);
if (result != 0)
return result;
/* predict and decode motion vector (3) */
pmv[2] = &motion[(x / 8) + 2];
pmv[3] = &motion[(x / 8) + 3];
result = svq1_decode_motion_vector (bitbuf, pmv[3], pmv);
if (result != 0)
return result;
/* form predictions */
for (i=0; i < 4; i++) {
int mvx= pmv[i]->x + (i&1)*16;
int mvy= pmv[i]->y + (i>>1)*16;
///XXX /FIXME clipping or padding?
if(y + (mvy >> 1)<0)
mvy= 0;
if(x + (mvx >> 1)<0)
mvx= 0;
#if 0
int w= (s->width+15)&~15;
int h= (s->height+15)&~15;
if(x + (mvx >> 1)<0 || y + (mvy >> 1)<0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8> h)
av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1));
#endif
src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch];
dst = current;
s->dsp.put_pixels_tab[1][((mvy & 1) << 1) | (mvx & 1)](dst,src,pitch,8);
/* select next block */
if (i & 1) {
current += 8*(pitch - 1);
} else {
current += 8;
}
}
return 0;
}
static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
uint8_t *current, uint8_t *previous, int pitch,
svq1_pmv_t *motion, int x, int y) {
uint32_t block_type;
int result = 0;
/* get block type */
block_type = get_vlc2(bitbuf, svq1_block_type.table, 2, 2);
/* reset motion vectors */
if (block_type == SVQ1_BLOCK_SKIP || block_type == SVQ1_BLOCK_INTRA) {
motion[0].x =
motion[0].y =
motion[(x / 8) + 2].x =
motion[(x / 8) + 2].y =
motion[(x / 8) + 3].x =
motion[(x / 8) + 3].y = 0;
}
switch (block_type) {
case SVQ1_BLOCK_SKIP:
svq1_skip_block (current, previous, pitch, x, y);
break;
case SVQ1_BLOCK_INTER:
result = svq1_motion_inter_block (s, bitbuf, current, previous, pitch, motion, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_block %i\n",result);
#endif
break;
}
result = svq1_decode_block_non_intra (bitbuf, current, pitch);
break;
case SVQ1_BLOCK_INTER_4V:
result = svq1_motion_inter_4v_block (s, bitbuf, current, previous, pitch, motion, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_4v_block %i\n",result);
#endif
break;
}
result = svq1_decode_block_non_intra (bitbuf, current, pitch);
break;
case SVQ1_BLOCK_INTRA:
result = svq1_decode_block_intra (bitbuf, current, pitch);
break;
}
return result;
}
static uint16_t svq1_packet_checksum (const uint8_t *data, const int length, int value) {
int i;
for (i=0; i < length; i++) {
value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8);
}
return value;
}
static void svq1_parse_string (GetBitContext *bitbuf, uint8_t *out) {
uint8_t seed;
int i;
out[0] = get_bits (bitbuf, 8);
seed = string_table[out[0]];
for (i=1; i <= out[0]; i++) {
out[i] = get_bits (bitbuf, 8) ^ seed;
seed = string_table[out[i] ^ seed];
}
}
static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) {
int frame_size_code;
int temporal_reference;
temporal_reference = get_bits (bitbuf, 8);
/* frame type */
s->pict_type= get_bits (bitbuf, 2)+1;
if(s->pict_type==4)
return -1;
if (s->pict_type == FF_I_TYPE) {
/* unknown fields */
if (s->f_code == 0x50 || s->f_code == 0x60) {
int csum = get_bits (bitbuf, 16);
csum = svq1_packet_checksum (bitbuf->buffer, bitbuf->size_in_bits>>3, csum);
// av_log(s->avctx, AV_LOG_INFO, "%s checksum (%02x) for packet data\n",
// (csum == 0) ? "correct" : "incorrect", csum);
}
if ((s->f_code ^ 0x10) >= 0x50) {
uint8_t msg[256];
svq1_parse_string (bitbuf, msg);
av_log(s->avctx, AV_LOG_INFO, "embedded message: \"%s\"\n", (char *) msg);
}
skip_bits (bitbuf, 2);
skip_bits (bitbuf, 2);
skip_bits1 (bitbuf);
/* load frame size */
frame_size_code = get_bits (bitbuf, 3);
if (frame_size_code == 7) {
/* load width, height (12 bits each) */
s->width = get_bits (bitbuf, 12);
s->height = get_bits (bitbuf, 12);
if (!s->width || !s->height)
return -1;
} else {
/* get width, height from table */
s->width = ff_svq1_frame_size_table[frame_size_code].width;
s->height = ff_svq1_frame_size_table[frame_size_code].height;
}
}
/* unknown fields */
if (get_bits1 (bitbuf) == 1) {
skip_bits1 (bitbuf); /* use packet checksum if (1) */
skip_bits1 (bitbuf); /* component checksums after image data if (1) */
if (get_bits (bitbuf, 2) != 0)
return -1;
}
if (get_bits1 (bitbuf) == 1) {
skip_bits1 (bitbuf);
skip_bits (bitbuf, 4);
skip_bits1 (bitbuf);
skip_bits (bitbuf, 2);
while (get_bits1 (bitbuf) == 1) {
skip_bits (bitbuf, 8);
}
}
return 0;
}
static int svq1_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
MpegEncContext *s=avctx->priv_data;
uint8_t *current, *previous;
int result, i, x, y, width, height;
AVFrame *pict = data;
/* initialize bit buffer */
init_get_bits(&s->gb,buf,buf_size*8);
/* decode frame header */
s->f_code = get_bits (&s->gb, 22);
if ((s->f_code & ~0x70) || !(s->f_code & 0x60))
return -1;
/* swap some header bytes (why?) */
if (s->f_code != 0x20) {
uint32_t *src = (uint32_t *) (buf + 4);
for (i=0; i < 4; i++) {
src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i];
}
}
result = svq1_decode_frame_header (&s->gb, s);
if (result != 0)
{
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_frame_header %i\n",result);
#endif
return result;
}
//FIXME this avoids some confusion for "B frames" without 2 references
//this should be removed after libavcodec can handle more flexible picture types & ordering
if(s->pict_type==FF_B_TYPE && s->last_picture_ptr==NULL) return buf_size;
if(avctx->hurry_up && s->pict_type==FF_B_TYPE) return buf_size;
if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==FF_B_TYPE)
||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=FF_I_TYPE)
|| avctx->skip_frame >= AVDISCARD_ALL)
return buf_size;
if(MPV_frame_start(s, avctx) < 0)
return -1;
/* decode y, u and v components */
for (i=0; i < 3; i++) {
int linesize;
if (i == 0) {
width = (s->width+15)&~15;
height = (s->height+15)&~15;
linesize= s->linesize;
} else {
if(s->flags&CODEC_FLAG_GRAY) break;
width = (s->width/4+15)&~15;
height = (s->height/4+15)&~15;
linesize= s->uvlinesize;
}
current = s->current_picture.data[i];
if(s->pict_type==FF_B_TYPE){
previous = s->next_picture.data[i];
}else{
previous = s->last_picture.data[i];
}
if (s->pict_type == FF_I_TYPE) {
/* keyframe */
for (y=0; y < height; y+=16) {
for (x=0; x < width; x+=16) {
result = svq1_decode_block_intra (&s->gb, &current[x], linesize);
if (result != 0)
{
//#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_block %i (keyframe)\n",result);
//#endif
return result;
}
}
current += 16*linesize;
}
} else {
svq1_pmv_t pmv[width/8+3];
/* delta frame */
memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv_t));
for (y=0; y < height; y+=16) {
for (x=0; x < width; x+=16) {
result = svq1_decode_delta_block (s, &s->gb, &current[x], previous,
linesize, pmv, x, y);
if (result != 0)
{
#ifdef DEBUG_SVQ1
av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_delta_block %i\n",result);
#endif
return result;
}
}
pmv[0].x =
pmv[0].y = 0;
current += 16*linesize;
}
}
}
*pict = *(AVFrame*)&s->current_picture;
MPV_frame_end(s);
*data_size=sizeof(AVFrame);
return buf_size;
}
static av_cold int svq1_decode_init(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
int i;
MPV_decode_defaults(s);
s->avctx = avctx;
s->width = (avctx->width+3)&~3;
s->height = (avctx->height+3)&~3;
s->codec_id= avctx->codec->id;
avctx->pix_fmt = PIX_FMT_YUV410P;
avctx->has_b_frames= 1; // not true, but DP frames and these behave like unidirectional b frames
s->flags= avctx->flags;
if (MPV_common_init(s) < 0) return -1;
init_vlc(&svq1_block_type, 2, 4,
&ff_svq1_block_type_vlc[0][1], 2, 1,
&ff_svq1_block_type_vlc[0][0], 2, 1, 1);
init_vlc(&svq1_motion_component, 7, 33,
&mvtab[0][1], 2, 1,
&mvtab[0][0], 2, 1, 1);
for (i = 0; i < 6; i++) {
init_vlc(&svq1_intra_multistage[i], 3, 8,
&ff_svq1_intra_multistage_vlc[i][0][1], 2, 1,
&ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, 1);
init_vlc(&svq1_inter_multistage[i], 3, 8,
&ff_svq1_inter_multistage_vlc[i][0][1], 2, 1,
&ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, 1);
}
init_vlc(&svq1_intra_mean, 8, 256,
&ff_svq1_intra_mean_vlc[0][1], 4, 2,
&ff_svq1_intra_mean_vlc[0][0], 4, 2, 1);
init_vlc(&svq1_inter_mean, 9, 512,
&ff_svq1_inter_mean_vlc[0][1], 4, 2,
&ff_svq1_inter_mean_vlc[0][0], 4, 2, 1);
return 0;
}
static av_cold int svq1_decode_end(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
MPV_common_end(s);
return 0;
}
AVCodec svq1_decoder = {
"svq1",
CODEC_TYPE_VIDEO,
CODEC_ID_SVQ1,
sizeof(MpegEncContext),
svq1_decode_init,
NULL,
svq1_decode_end,
svq1_decode_frame,
CODEC_CAP_DR1,
.flush= ff_mpeg_flush,
.pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1"),
};

@ -0,0 +1,589 @@
/*
* SVQ1 Encoder
* Copyright (C) 2004 Mike Melanson <melanson@pcisys.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1enc.c
* Sorenson Vector Quantizer #1 (SVQ1) video codec.
* For more information of the SVQ1 algorithm, visit:
* http://www.pcisys.net/~melanson/codecs/
*/
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "svq1.h"
#include "svq1enc_cb.h"
#undef NDEBUG
#include <assert.h>
typedef struct SVQ1Context {
MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independent of MpegEncContext, so this will be removed then (FIXME/XXX)
AVCodecContext *avctx;
DSPContext dsp;
AVFrame picture;
AVFrame current_picture;
AVFrame last_picture;
PutBitContext pb;
GetBitContext gb;
PutBitContext reorder_pb[6]; //why ooh why this sick breadth first order, everything is slower and more complex
int frame_width;
int frame_height;
/* Y plane block dimensions */
int y_block_width;
int y_block_height;
/* U & V plane (C planes) block dimensions */
int c_block_width;
int c_block_height;
uint16_t *mb_type;
uint32_t *dummy;
int16_t (*motion_val8[3])[2];
int16_t (*motion_val16[3])[2];
int64_t rd_total;
} SVQ1Context;
static void svq1_write_header(SVQ1Context *s, int frame_type)
{
int i;
/* frame code */
put_bits(&s->pb, 22, 0x20);
/* temporal reference (sure hope this is a "don't care") */
put_bits(&s->pb, 8, 0x00);
/* frame type */
put_bits(&s->pb, 2, frame_type - 1);
if (frame_type == FF_I_TYPE) {
/* no checksum since frame code is 0x20 */
/* no embedded string either */
/* output 5 unknown bits (2 + 2 + 1) */
put_bits(&s->pb, 5, 2); /* 2 needed by quicktime decoder */
for (i = 0; i < 7; i++)
{
if ((ff_svq1_frame_size_table[i].width == s->frame_width) &&
(ff_svq1_frame_size_table[i].height == s->frame_height))
{
put_bits(&s->pb, 3, i);
break;
}
}
if (i == 7)
{
put_bits(&s->pb, 3, 7);
put_bits(&s->pb, 12, s->frame_width);
put_bits(&s->pb, 12, s->frame_height);
}
}
/* no checksum or extra data (next 2 bits get 0) */
put_bits(&s->pb, 2, 0);
}
#define QUALITY_THRESHOLD 100
#define THRESHOLD_MULTIPLIER 0.6
#if defined(HAVE_ALTIVEC)
#undef vector
#endif
static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra){
int count, y, x, i, j, split, best_mean, best_score, best_count;
int best_vector[6];
int block_sum[7]= {0, 0, 0, 0, 0, 0};
int w= 2<<((level+2)>>1);
int h= 2<<((level+1)>>1);
int size=w*h;
int16_t block[7][256];
const int8_t *codebook_sum, *codebook;
const uint16_t (*mean_vlc)[2];
const uint8_t (*multistage_vlc)[2];
best_score=0;
//FIXME optimize, this doenst need to be done multiple times
if(intra){
codebook_sum= svq1_intra_codebook_sum[level];
codebook= ff_svq1_intra_codebooks[level];
mean_vlc= ff_svq1_intra_mean_vlc;
multistage_vlc= ff_svq1_intra_multistage_vlc[level];
for(y=0; y<h; y++){
for(x=0; x<w; x++){
int v= src[x + y*stride];
block[0][x + w*y]= v;
best_score += v*v;
block_sum[0] += v;
}
}
}else{
codebook_sum= svq1_inter_codebook_sum[level];
codebook= ff_svq1_inter_codebooks[level];
mean_vlc= ff_svq1_inter_mean_vlc + 256;
multistage_vlc= ff_svq1_inter_multistage_vlc[level];
for(y=0; y<h; y++){
for(x=0; x<w; x++){
int v= src[x + y*stride] - ref[x + y*stride];
block[0][x + w*y]= v;
best_score += v*v;
block_sum[0] += v;
}
}
}
best_count=0;
best_score -= ((block_sum[0]*block_sum[0])>>(level+3));
best_mean= (block_sum[0] + (size>>1)) >> (level+3);
if(level<4){
for(count=1; count<7; count++){
int best_vector_score= INT_MAX;
int best_vector_sum=-999, best_vector_mean=-999;
const int stage= count-1;
const int8_t *vector;
for(i=0; i<16; i++){
int sum= codebook_sum[stage*16 + i];
int sqr, diff, score;
vector = codebook + stage*size*16 + i*size;
sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], size);
diff= block_sum[stage] - sum;
score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow
if(score < best_vector_score){
int mean= (diff + (size>>1)) >> (level+3);
assert(mean >-300 && mean<300);
mean= av_clip(mean, intra?0:-256, 255);
best_vector_score= score;
best_vector[stage]= i;
best_vector_sum= sum;
best_vector_mean= mean;
}
}
assert(best_vector_mean != -999);
vector= codebook + stage*size*16 + best_vector[stage]*size;
for(j=0; j<size; j++){
block[stage+1][j] = block[stage][j] - vector[j];
}
block_sum[stage+1]= block_sum[stage] - best_vector_sum;
best_vector_score +=
lambda*(+ 1 + 4*count
+ multistage_vlc[1+count][1]
+ mean_vlc[best_vector_mean][1]);
if(best_vector_score < best_score){
best_score= best_vector_score;
best_count= count;
best_mean= best_vector_mean;
}
}
}
split=0;
if(best_score > threshold && level){
int score=0;
int offset= (level&1) ? stride*h/2 : w/2;
PutBitContext backup[6];
for(i=level-1; i>=0; i--){
backup[i]= s->reorder_pb[i];
}
score += encode_block(s, src , ref , decoded , stride, level-1, threshold>>1, lambda, intra);
score += encode_block(s, src + offset, ref + offset, decoded + offset, stride, level-1, threshold>>1, lambda, intra);
score += lambda;
if(score < best_score){
best_score= score;
split=1;
}else{
for(i=level-1; i>=0; i--){
s->reorder_pb[i]= backup[i];
}
}
}
if (level > 0)
put_bits(&s->reorder_pb[level], 1, split);
if(!split){
assert((best_mean >= 0 && best_mean<256) || !intra);
assert(best_mean >= -256 && best_mean<256);
assert(best_count >=0 && best_count<7);
assert(level<4 || best_count==0);
/* output the encoding */
put_bits(&s->reorder_pb[level],
multistage_vlc[1 + best_count][1],
multistage_vlc[1 + best_count][0]);
put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1],
mean_vlc[best_mean][0]);
for (i = 0; i < best_count; i++){
assert(best_vector[i]>=0 && best_vector[i]<16);
put_bits(&s->reorder_pb[level], 4, best_vector[i]);
}
for(y=0; y<h; y++){
for(x=0; x<w; x++){
decoded[x + y*stride]= src[x + y*stride] - block[best_count][x + w*y] + best_mean;
}
}
}
return best_score;
}
static int svq1_encode_plane(SVQ1Context *s, int plane, unsigned char *src_plane, unsigned char *ref_plane, unsigned char *decoded_plane,
int width, int height, int src_stride, int stride)
{
int x, y;
int i;
int block_width, block_height;
int level;
int threshold[6];
const int lambda= (s->picture.quality*s->picture.quality) >> (2*FF_LAMBDA_SHIFT);
/* figure out the acceptable level thresholds in advance */
threshold[5] = QUALITY_THRESHOLD;
for (level = 4; level >= 0; level--)
threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER;
block_width = (width + 15) / 16;
block_height = (height + 15) / 16;
if(s->picture.pict_type == FF_P_TYPE){
s->m.avctx= s->avctx;
s->m.current_picture_ptr= &s->m.current_picture;
s->m.last_picture_ptr = &s->m.last_picture;
s->m.last_picture.data[0]= ref_plane;
s->m.linesize=
s->m.last_picture.linesize[0]=
s->m.new_picture.linesize[0]=
s->m.current_picture.linesize[0]= stride;
s->m.width= width;
s->m.height= height;
s->m.mb_width= block_width;
s->m.mb_height= block_height;
s->m.mb_stride= s->m.mb_width+1;
s->m.b8_stride= 2*s->m.mb_width+1;
s->m.f_code=1;
s->m.pict_type= s->picture.pict_type;
s->m.me_method= s->avctx->me_method;
s->m.me.scene_change_score=0;
s->m.flags= s->avctx->flags;
// s->m.out_format = FMT_H263;
// s->m.unrestricted_mv= 1;
s->m.lambda= s->picture.quality;
s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
if(!s->motion_val8[plane]){
s->motion_val8 [plane]= av_mallocz((s->m.b8_stride*block_height*2 + 2)*2*sizeof(int16_t));
s->motion_val16[plane]= av_mallocz((s->m.mb_stride*(block_height + 2) + 1)*2*sizeof(int16_t));
}
s->m.mb_type= s->mb_type;
//dummies, to avoid segfaults
s->m.current_picture.mb_mean= (uint8_t *)s->dummy;
s->m.current_picture.mb_var= (uint16_t*)s->dummy;
s->m.current_picture.mc_mb_var= (uint16_t*)s->dummy;
s->m.current_picture.mb_type= s->dummy;
s->m.current_picture.motion_val[0]= s->motion_val8[plane] + 2;
s->m.p_mv_table= s->motion_val16[plane] + s->m.mb_stride + 1;
s->m.dsp= s->dsp; //move
ff_init_me(&s->m);
s->m.me.dia_size= s->avctx->dia_size;
s->m.first_slice_line=1;
for (y = 0; y < block_height; y++) {
uint8_t src[stride*16];
s->m.new_picture.data[0]= src - y*16*stride; //ugly
s->m.mb_y= y;
for(i=0; i<16 && i + 16*y<height; i++){
memcpy(&src[i*stride], &src_plane[(i+16*y)*src_stride], width);
for(x=width; x<16*block_width; x++)
src[i*stride+x]= src[i*stride+x-1];
}
for(; i<16 && i + 16*y<16*block_height; i++)
memcpy(&src[i*stride], &src[(i-1)*stride], 16*block_width);
for (x = 0; x < block_width; x++) {
s->m.mb_x= x;
ff_init_block_index(&s->m);
ff_update_block_index(&s->m);
ff_estimate_p_frame_motion(&s->m, x, y);
}
s->m.first_slice_line=0;
}
ff_fix_long_p_mvs(&s->m);
ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code, CANDIDATE_MB_TYPE_INTER, 0);
}
s->m.first_slice_line=1;
for (y = 0; y < block_height; y++) {
uint8_t src[stride*16];
for(i=0; i<16 && i + 16*y<height; i++){
memcpy(&src[i*stride], &src_plane[(i+16*y)*src_stride], width);
for(x=width; x<16*block_width; x++)
src[i*stride+x]= src[i*stride+x-1];
}
for(; i<16 && i + 16*y<16*block_height; i++)
memcpy(&src[i*stride], &src[(i-1)*stride], 16*block_width);
s->m.mb_y= y;
for (x = 0; x < block_width; x++) {
uint8_t reorder_buffer[3][6][7*32];
int count[3][6];
int offset = y * 16 * stride + x * 16;
uint8_t *decoded= decoded_plane + offset;
uint8_t *ref= ref_plane + offset;
int score[4]={0,0,0,0}, best;
uint8_t temp[16*stride];
if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 3000){ //FIXME check size
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return -1;
}
s->m.mb_x= x;
ff_init_block_index(&s->m);
ff_update_block_index(&s->m);
if(s->picture.pict_type == FF_I_TYPE || (s->m.mb_type[x + y*s->m.mb_stride]&CANDIDATE_MB_TYPE_INTRA)){
for(i=0; i<6; i++){
init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], 7*32);
}
if(s->picture.pict_type == FF_P_TYPE){
const uint8_t *vlc= ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA];
put_bits(&s->reorder_pb[5], vlc[1], vlc[0]);
score[0]= vlc[1]*lambda;
}
score[0]+= encode_block(s, src+16*x, NULL, temp, stride, 5, 64, lambda, 1);
for(i=0; i<6; i++){
count[0][i]= put_bits_count(&s->reorder_pb[i]);
flush_put_bits(&s->reorder_pb[i]);
}
}else
score[0]= INT_MAX;
best=0;
if(s->picture.pict_type == FF_P_TYPE){
const uint8_t *vlc= ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER];
int mx, my, pred_x, pred_y, dxy;
int16_t *motion_ptr;
motion_ptr= h263_pred_motion(&s->m, 0, 0, &pred_x, &pred_y);
if(s->m.mb_type[x + y*s->m.mb_stride]&CANDIDATE_MB_TYPE_INTER){
for(i=0; i<6; i++)
init_put_bits(&s->reorder_pb[i], reorder_buffer[1][i], 7*32);
put_bits(&s->reorder_pb[5], vlc[1], vlc[0]);
s->m.pb= s->reorder_pb[5];
mx= motion_ptr[0];
my= motion_ptr[1];
assert(mx>=-32 && mx<=31);
assert(my>=-32 && my<=31);
assert(pred_x>=-32 && pred_x<=31);
assert(pred_y>=-32 && pred_y<=31);
ff_h263_encode_motion(&s->m, mx - pred_x, 1);
ff_h263_encode_motion(&s->m, my - pred_y, 1);
s->reorder_pb[5]= s->m.pb;
score[1] += lambda*put_bits_count(&s->reorder_pb[5]);
dxy= (mx&1) + 2*(my&1);
s->dsp.put_pixels_tab[0][dxy](temp+16, ref + (mx>>1) + stride*(my>>1), stride, 16);
score[1]+= encode_block(s, src+16*x, temp+16, decoded, stride, 5, 64, lambda, 0);
best= score[1] <= score[0];
vlc= ff_svq1_block_type_vlc[SVQ1_BLOCK_SKIP];
score[2]= s->dsp.sse[0](NULL, src+16*x, ref, stride, 16);
score[2]+= vlc[1]*lambda;
if(score[2] < score[best] && mx==0 && my==0){
best=2;
s->dsp.put_pixels_tab[0][0](decoded, ref, stride, 16);
for(i=0; i<6; i++){
count[2][i]=0;
}
put_bits(&s->pb, vlc[1], vlc[0]);
}
}
if(best==1){
for(i=0; i<6; i++){
count[1][i]= put_bits_count(&s->reorder_pb[i]);
flush_put_bits(&s->reorder_pb[i]);
}
}else{
motion_ptr[0 ] = motion_ptr[1 ]=
motion_ptr[2 ] = motion_ptr[3 ]=
motion_ptr[0+2*s->m.b8_stride] = motion_ptr[1+2*s->m.b8_stride]=
motion_ptr[2+2*s->m.b8_stride] = motion_ptr[3+2*s->m.b8_stride]=0;
}
}
s->rd_total += score[best];
for(i=5; i>=0; i--){
ff_copy_bits(&s->pb, reorder_buffer[best][i], count[best][i]);
}
if(best==0){
s->dsp.put_pixels_tab[0][0](decoded, temp, stride, 16);
}
}
s->m.first_slice_line=0;
}
return 0;
}
static av_cold int svq1_encode_init(AVCodecContext *avctx)
{
SVQ1Context * const s = avctx->priv_data;
dsputil_init(&s->dsp, avctx);
avctx->coded_frame= (AVFrame*)&s->picture;
s->frame_width = avctx->width;
s->frame_height = avctx->height;
s->y_block_width = (s->frame_width + 15) / 16;
s->y_block_height = (s->frame_height + 15) / 16;
s->c_block_width = (s->frame_width / 4 + 15) / 16;
s->c_block_height = (s->frame_height / 4 + 15) / 16;
s->avctx= avctx;
s->m.avctx= avctx;
s->m.me.scratchpad= av_mallocz((avctx->width+64)*2*16*2*sizeof(uint8_t));
s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
s->mb_type = av_mallocz((s->y_block_width+1)*s->y_block_height*sizeof(int16_t));
s->dummy = av_mallocz((s->y_block_width+1)*s->y_block_height*sizeof(int32_t));
h263_encode_init(&s->m); //mv_penalty
return 0;
}
static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
int buf_size, void *data)
{
SVQ1Context * const s = avctx->priv_data;
AVFrame *pict = data;
AVFrame * const p= (AVFrame*)&s->picture;
AVFrame temp;
int i;
if(avctx->pix_fmt != PIX_FMT_YUV410P){
av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
return -1;
}
if(!s->current_picture.data[0]){
avctx->get_buffer(avctx, &s->current_picture);
avctx->get_buffer(avctx, &s->last_picture);
}
temp= s->current_picture;
s->current_picture= s->last_picture;
s->last_picture= temp;
init_put_bits(&s->pb, buf, buf_size);
*p = *pict;
p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ? FF_P_TYPE : FF_I_TYPE;
p->key_frame = p->pict_type == FF_I_TYPE;
svq1_write_header(s, p->pict_type);
for(i=0; i<3; i++){
if(svq1_encode_plane(s, i,
s->picture.data[i], s->last_picture.data[i], s->current_picture.data[i],
s->frame_width / (i?4:1), s->frame_height / (i?4:1),
s->picture.linesize[i], s->current_picture.linesize[i]) < 0)
return -1;
}
// align_put_bits(&s->pb);
while(put_bits_count(&s->pb) & 31)
put_bits(&s->pb, 1, 0);
flush_put_bits(&s->pb);
return put_bits_count(&s->pb) / 8;
}
static av_cold int svq1_encode_end(AVCodecContext *avctx)
{
SVQ1Context * const s = avctx->priv_data;
int i;
av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", s->rd_total/(double)(avctx->width*avctx->height*avctx->frame_number));
av_freep(&s->m.me.scratchpad);
av_freep(&s->m.me.map);
av_freep(&s->m.me.score_map);
av_freep(&s->mb_type);
av_freep(&s->dummy);
for(i=0; i<3; i++){
av_freep(&s->motion_val8[i]);
av_freep(&s->motion_val16[i]);
}
return 0;
}
AVCodec svq1_encoder = {
"svq1",
CODEC_TYPE_VIDEO,
CODEC_ID_SVQ1,
sizeof(SVQ1Context),
svq1_encode_init,
svq1_encode_frame,
svq1_encode_end,
.pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, PIX_FMT_NONE},
.long_name= NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1"),
};

@ -0,0 +1,96 @@
/*
* SVQ1 Encoder
* Copyright (C) 2004 Mike Melanson <melanson@pcisys.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* 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
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file svq1enc_cb.h
* svq1 code books.
*/
#ifndef FFMPEG_SVQ1ENC_CB_H
#define FFMPEG_SVQ1ENC_CB_H
#include <stdint.h>
static const int8_t svq1_inter_codebook_sum[4][16*6] = {
{
-1, 1, -2, 0, 1, -1, -1, -1, -2, -1, 1, -1, -1, 0, -1, -1,
0, -1, -1, -1, -1, 0, -1, 0, 0, 0, -3, 1, -1, 0, 1, -1,
1, -1, 2, 2, 1, 1, 2, 0, 0, 0, -1, 1, 1, 0, 0, 0,
1, -1, 0, 1, -1, 1, 1, 0, 1, 0, -1, 1, 1, 0, 0, 0,
-2, 0, 0, -2, 0, 0, -2, 0, -2, -1, -2, -1, 0, 0, -1, 0,
1, 0, 1, -1, 2, 2, 1, 2, 2, 1, 0, 1, 1, 0, 1, 1,
},{
-2, 1, -1, -1, 1, 0, 1, -1, -1, -1, 1, -1, 0, -1, 0, -1,
0, 0, 0, -2, 0, 1, 0, -1, -1, 0, 2, -3, 1, -2, 3, -1,
2, 0, 2, 1, 1, -1, 1, 1, 0, 0, 1, 1, 2, -2, 1, 0,
-2, -1, 2, -2, -2, 0, -3, 0, -1, 0, -1, 0, -1, 0, -2, -3,
1, -2, -2, -1, 1, -1, -1, 1, -1, 1, 1, 0, -2, 0, 1, 1,
1, 1, 2, 1, 0, 0, -1, 0, 0, 1, 0, 1, -1, 1, 0, 2,
},{
0, 0, 0, -3, 1, 1, 1, -3, 0, -1, 0, -3, 1, -3, 0, -2,
1, 2, -1, -3, 0, -3, 1, -1, 0, -1, 0, 0, 1, 2, 1, 1,
-1, 2, -3, 3, 1, 0, -5, 1, 0, -1, -3, 1, 0, 2, 0, -3,
4, 2, 0, -2, 1, -2, 3, -2, 1, 1, 0, -1, 2, 5, 3, 1,
-1, 0, 2, -3, -2, 0, 0, -2, 2, -3, -1, -1, 2, 1, 0, -2,
3, -1, 1, -1, 2, 4, 0, 1, 0, 1, 0, -1, -3, -2, -1, 0,
},{
0, 2, -1, -1, 2, -4, -2, 3, 0, -1, -5, 1, 0, 1, 0, 6,
-2, 2, 0, 1, 1, -1, -1, -2, 1, -2, -1, 0, 2, -2, -2, -1,
-4, 2, -1, -3, -1, -2, 2, -1, 2, -1, 2, 0, 3, -3, -3, 0,
-3, 0, 0, -2, 4, -4, 0, -1, 4, 0, -2, -2, 3, -2, 0, 4,
5, 0, 1, 0, -3, 3, 3, 2, 0, 0, 1, 2, -5, -2, -3, 0,
-3, 2, -2, 2, -2, 4, 7, -3, 4, 2, 3, 2, -1, 0, -3, 1,
}
};
static const int8_t svq1_intra_codebook_sum[4][16*6] = {
{
0, 0, 0, -1, -1, -1, -1, -2, 0, -1, -1, 0, -1, 0, 1, 0,
1, 0, -1, 1, 0, 0, -1, 1, -1, 0, 0, 0, -1, 1, 0, 0,
-1, 0, 0, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, 0, -1, 1,
0, 1, 0, 0, 1, -1, 0, 0, 0, -1, 1, 0, 1, 0, -2, 1,
0, -1, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 0, 0,
0, 1, 1, 0, 0, -1, 0, 1, 0, 0, 0, 0, -1, 1, 1, -1,
},{
-1, -2, 0, -1, 1, 0, -1, 0, -1, -4, -1, -2, -1, -2, 1, -2,
0, 0, 4, -2, -1, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 0,
1, 1, 0, -1, -1, -1, 1, 0, -1, -3, -3, 1, -1, 1, -2, -1,
1, -1, 0, 1, 2, 1, -1, -1, 1, 1, 1, 2, 1, 0, 1, -2,
-2, 0, -1, -2, -2, 0, -1, -1, -1, 0, 1, 0, -1, -1, 0, -1,
0, 2, 1, 2, 2, 1, -1, 1, 0, 2, 0, -1, 1, 0, 0, 0,
},{
-2, 0, -1, -1, 1, 1, -2, 0, -2, 0, 1, -2, -2, 1, -1, -1,
3, -2, 0, -3, -4, -3, 2, 1, 0, 3, -2, 2, 3, 2, 2, -1,
-3, 1, 0, 1, 0, 0, 0, 1, -2, 1, -2, -2, -1, -2, -2, 2,
0, -4, 0, 2, -1, 0, 2, 2, 2, 1, 0, -1, -1, 1, -3, 2,
2, 1, 0, 3, 1, -1, 1, 3, 1, 0, 1, 1, 2, -1, 1, -1,
-2, -1, 0, -1, 1, -1, 1, -2, -2, -1, -1, -3, 1, -4, -3, 1,
},{
-2, 0, -2, 3, -1, -1, 0, 2, 2, -1, -3, 2, 1, 0, -2, -1,
-3, -2, -2, 1, 2, -3, 0, 1, -5, -2, -3, 0, -2, -1, 2, 0,
-1, -1, 0, -2, 1, 3, -7, -2, -2, -1, 2, -1, 0, 3, 1, 3,
1, 0, 0, 1, 2, 3, 1, 2, 0, -2, -2, 1, 1, 2, 2, 3,
4, 1, -1, 2, -2, 4, 0, 0, 0, 4, 2, 0, -2, -2, 2, -4,
-1, 5, -2, -2, -3, 2, -3, -1, 3, -3, 0, 4, 3, 0, 1, -2,
}
};
#endif /* FFMPEG_SVQ1ENC_CB_H */

File diff suppressed because it is too large Load Diff