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:
parent
eaa51ccd98
commit
c17be5fb78
96
src/add-ons/media/plugins/avcodec/libavcodec/s3tc.c
Normal file
96
src/add-ons/media/plugins/avcodec/libavcodec/s3tc.c
Normal file
@ -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));
|
||||
}
|
53
src/add-ons/media/plugins/avcodec/libavcodec/s3tc.h
Normal file
53
src/add-ons/media/plugins/avcodec/libavcodec/s3tc.h
Normal file
@ -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 */
|
36
src/add-ons/media/plugins/avcodec/libavcodec/sgi.h
Normal file
36
src/add-ons/media/plugins/avcodec/libavcodec/sgi.h
Normal file
@ -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 */
|
268
src/add-ons/media/plugins/avcodec/libavcodec/sgidec.c
Normal file
268
src/add-ons/media/plugins/avcodec/libavcodec/sgidec.c
Normal file
@ -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"),
|
||||
};
|
||||
|
157
src/add-ons/media/plugins/avcodec/libavcodec/sgienc.c
Normal file
157
src/add-ons/media/plugins/avcodec/libavcodec/sgienc.c
Normal file
@ -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"),
|
||||
};
|
||||
|
537
src/add-ons/media/plugins/avcodec/libavcodec/shorten.c
Normal file
537
src/add-ons/media/plugins/avcodec/libavcodec/shorten.c
Normal file
@ -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 */
|
||||
|
716
src/add-ons/media/plugins/avcodec/libavcodec/smacker.c
Normal file
716
src/add-ons/media/plugins/avcodec/libavcodec/smacker.c
Normal file
@ -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)"),
|
||||
};
|
||||
|
4825
src/add-ons/media/plugins/avcodec/libavcodec/snow.c
Normal file
4825
src/add-ons/media/plugins/avcodec/libavcodec/snow.c
Normal file
File diff suppressed because it is too large
Load Diff
174
src/add-ons/media/plugins/avcodec/libavcodec/snow.h
Normal file
174
src/add-ons/media/plugins/avcodec/libavcodec/snow.h
Normal file
@ -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 */
|
978
src/add-ons/media/plugins/avcodec/libavcodec/sonic.c
Normal file
978
src/add-ons/media/plugins/avcodec/libavcodec/sonic.c
Normal file
@ -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 */
|
||||
|
215
src/add-ons/media/plugins/avcodec/libavcodec/sp5xdec.c
Normal file
215
src/add-ons/media/plugins/avcodec/libavcodec/sp5xdec.c
Normal file
@ -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"),
|
||||
};
|
196
src/add-ons/media/plugins/avcodec/libavcodec/sunrast.c
Normal file
196
src/add-ons/media/plugins/avcodec/libavcodec/sunrast.c
Normal file
@ -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, ¤t[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, ¤t[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,
|
||||
};
|
||||
|
61
src/add-ons/media/plugins/avcodec/libavcodec/svq1.h
Normal file
61
src/add-ons/media/plugins/avcodec/libavcodec/svq1.h
Normal file
@ -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 */
|
||||
|
830
src/add-ons/media/plugins/avcodec/libavcodec/svq1dec.c
Normal file
830
src/add-ons/media/plugins/avcodec/libavcodec/svq1dec.c
Normal file
@ -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, ¤t[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, ¤t[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"),
|
||||
};
|
589
src/add-ons/media/plugins/avcodec/libavcodec/svq1enc.c
Normal file
589
src/add-ons/media/plugins/avcodec/libavcodec/svq1enc.c
Normal file
@ -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"),
|
||||
};
|
96
src/add-ons/media/plugins/avcodec/libavcodec/svq1enc_cb.h
Normal file
96
src/add-ons/media/plugins/avcodec/libavcodec/svq1enc_cb.h
Normal file
@ -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
Loading…
x
Reference in New Issue
Block a user