upload sdk

git-svn-id: svn://kolibrios.org@4349 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge)
2013-12-15 08:09:20 +00:00
parent 6c6781f799
commit 754f9336f0
5801 changed files with 1688660 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
/*
* 012v decoder
*
* Copyright (C) 2012 Carl Eugen Hoyos
*
* 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 "internal.h"
#include "libavutil/intreadwrite.h"
static av_cold int zero12v_decode_init(AVCodecContext *avctx)
{
avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
avctx->bits_per_raw_sample = 10;
if (avctx->codec_tag == MKTAG('a', '1', '2', 'v'))
avpriv_request_sample(avctx, "transparency");
return 0;
}
static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt)
{
int line = 0, ret;
const int width = avctx->width;
AVFrame *pic = data;
uint16_t *y, *u, *v;
const uint8_t *line_end, *src = avpkt->data;
int stride = avctx->width * 8 / 3;
if (width == 1) {
av_log(avctx, AV_LOG_ERROR, "Width 1 not supported.\n");
return AVERROR_INVALIDDATA;
}
if ( avctx->codec_tag == MKTAG('0', '1', '2', 'v')
&& avpkt->size % avctx->height == 0
&& avpkt->size / avctx->height * 3 >= width * 8)
stride = avpkt->size / avctx->height;
if (avpkt->size < avctx->height * stride) {
av_log(avctx, AV_LOG_ERROR, "Packet too small: %d instead of %d\n",
avpkt->size, avctx->height * stride);
return AVERROR_INVALIDDATA;
}
if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
return ret;
pic->pict_type = AV_PICTURE_TYPE_I;
pic->key_frame = 1;
y = (uint16_t *)pic->data[0];
u = (uint16_t *)pic->data[1];
v = (uint16_t *)pic->data[2];
line_end = avpkt->data + stride;
while (line++ < avctx->height) {
while (1) {
uint32_t t = AV_RL32(src);
src += 4;
*u++ = t << 6 & 0xFFC0;
*y++ = t >> 4 & 0xFFC0;
*v++ = t >> 14 & 0xFFC0;
if (src >= line_end - 1) {
*y = 0x80;
src++;
line_end += stride;
y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
break;
}
t = AV_RL32(src);
src += 4;
*y++ = t << 6 & 0xFFC0;
*u++ = t >> 4 & 0xFFC0;
*y++ = t >> 14 & 0xFFC0;
if (src >= line_end - 2) {
if (!(width & 1)) {
*y = 0x80;
src += 2;
}
line_end += stride;
y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
break;
}
t = AV_RL32(src);
src += 4;
*v++ = t << 6 & 0xFFC0;
*y++ = t >> 4 & 0xFFC0;
*u++ = t >> 14 & 0xFFC0;
if (src >= line_end - 1) {
*y = 0x80;
src++;
line_end += stride;
y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
break;
}
t = AV_RL32(src);
src += 4;
*y++ = t << 6 & 0xFFC0;
*v++ = t >> 4 & 0xFFC0;
*y++ = t >> 14 & 0xFFC0;
if (src >= line_end - 2) {
if (width & 1) {
*y = 0x80;
src += 2;
}
line_end += stride;
y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
break;
}
}
}
*got_frame = 1;
return avpkt->size;
}
AVCodec ff_zero12v_decoder = {
.name = "012v",
.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_012V,
.init = zero12v_decode_init,
.decode = zero12v_decode_frame,
.capabilities = CODEC_CAP_DR1,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
/*
* Quicktime Planar RGB (8BPS) Video Decoder
* Copyright (C) 2003 Roberto Togni
*
* 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
* QT 8BPS Video Decoder by Roberto Togni
* For more information about the 8BPS format, visit:
* http://www.pcisys.net/~melanson/codecs/
*
* Supports: PAL8 (RGB 8bpp, paletted)
* : BGR24 (RGB 24bpp) (can also output it as RGB32)
* : RGB32 (RGB 32bpp, 4th plane is alpha)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "avcodec.h"
#include "internal.h"
static const enum AVPixelFormat pixfmt_rgb24[] = {
AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE };
typedef struct EightBpsContext {
AVCodecContext *avctx;
unsigned char planes;
unsigned char planemap[4];
uint32_t pal[256];
} EightBpsContext;
static int decode_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt)
{
AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
EightBpsContext * const c = avctx->priv_data;
const unsigned char *encoded = buf;
unsigned char *pixptr, *pixptr_end;
unsigned int height = avctx->height; // Real image height
unsigned int dlen, p, row;
const unsigned char *lp, *dp, *ep;
unsigned char count;
unsigned int planes = c->planes;
unsigned char *planemap = c->planemap;
int ret;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
ep = encoded + buf_size;
/* Set data pointer after line lengths */
dp = encoded + planes * (height << 1);
for (p = 0; p < planes; p++) {
/* Lines length pointer for this plane */
lp = encoded + p * (height << 1);
/* Decode a plane */
for (row = 0; row < height; row++) {
pixptr = frame->data[0] + row * frame->linesize[0] + planemap[p];
pixptr_end = pixptr + frame->linesize[0];
if (ep - lp < row * 2 + 2)
return AVERROR_INVALIDDATA;
dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2));
/* Decode a row of this plane */
while (dlen > 0) {
if (ep - dp <= 1)
return AVERROR_INVALIDDATA;
if ((count = *dp++) <= 127) {
count++;
dlen -= count + 1;
if (pixptr_end - pixptr < count * planes)
break;
if (ep - dp < count)
return AVERROR_INVALIDDATA;
while (count--) {
*pixptr = *dp++;
pixptr += planes;
}
} else {
count = 257 - count;
if (pixptr_end - pixptr < count * planes)
break;
while (count--) {
*pixptr = *dp;
pixptr += planes;
}
dp++;
dlen -= 2;
}
}
}
}
if (avctx->bits_per_coded_sample <= 8) {
const uint8_t *pal = av_packet_get_side_data(avpkt,
AV_PKT_DATA_PALETTE,
NULL);
if (pal) {
frame->palette_has_changed = 1;
memcpy(c->pal, pal, AVPALETTE_SIZE);
}
memcpy (frame->data[1], c->pal, AVPALETTE_SIZE);
}
*got_frame = 1;
/* always report that the buffer was completely consumed */
return buf_size;
}
static av_cold int decode_init(AVCodecContext *avctx)
{
EightBpsContext * const c = avctx->priv_data;
c->avctx = avctx;
switch (avctx->bits_per_coded_sample) {
case 8:
avctx->pix_fmt = AV_PIX_FMT_PAL8;
c->planes = 1;
c->planemap[0] = 0; // 1st plane is palette indexes
break;
case 24:
avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24);
c->planes = 3;
c->planemap[0] = 2; // 1st plane is red
c->planemap[1] = 1; // 2nd plane is green
c->planemap[2] = 0; // 3rd plane is blue
break;
case 32:
avctx->pix_fmt = AV_PIX_FMT_RGB32;
c->planes = 4;
/* handle planemap setup later for decoding rgb24 data as rbg32 */
break;
default:
av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n",
avctx->bits_per_coded_sample);
return AVERROR_INVALIDDATA;
}
if (avctx->pix_fmt == AV_PIX_FMT_RGB32) {
c->planemap[0] = HAVE_BIGENDIAN ? 1 : 2; // 1st plane is red
c->planemap[1] = HAVE_BIGENDIAN ? 2 : 1; // 2nd plane is green
c->planemap[2] = HAVE_BIGENDIAN ? 3 : 0; // 3rd plane is blue
c->planemap[3] = HAVE_BIGENDIAN ? 0 : 3; // 4th plane is alpha
}
return 0;
}
AVCodec ff_eightbps_decoder = {
.name = "8bps",
.long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_8BPS,
.priv_data_size = sizeof(EightBpsContext),
.init = decode_init,
.decode = decode_frame,
.capabilities = CODEC_CAP_DR1,
};

View File

@@ -0,0 +1,216 @@
/*
* Copyright (C) 2008 Jaikrishnan Menon
* Copyright (C) 2011 Stefano Sabatini
*
* 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
* 8svx audio decoder
* @author Jaikrishnan Menon
*
* supports: fibonacci delta encoding
* : exponential encoding
*
* For more information about the 8SVX format:
* http://netghost.narod.ru/gff/vendspec/iff/iff.txt
* http://sox.sourceforge.net/AudioFormats-11.html
* http://aminet.net/package/mus/misc/wavepak
* http://amigan.1emu.net/reg/8SVX.txt
*
* Samples can be found here:
* http://aminet.net/mods/smpl/
*/
#include "libavutil/avassert.h"
#include "avcodec.h"
#include "internal.h"
#include "libavutil/common.h"
/** decoder context */
typedef struct EightSvxContext {
uint8_t fib_acc[2];
const int8_t *table;
/* buffer used to store the whole first packet.
data is only sent as one large packet */
uint8_t *data[2];
int data_size;
int data_idx;
} EightSvxContext;
static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 };
static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 };
#define MAX_FRAME_SIZE 2048
/**
* Delta decode the compressed values in src, and put the resulting
* decoded samples in dst.
*
* @param[in,out] state starting value. it is saved for use in the next call.
* @param table delta sequence table
*/
static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
uint8_t *state, const int8_t *table)
{
uint8_t val = *state;
while (src_size--) {
uint8_t d = *src++;
val = av_clip_uint8(val + table[d & 0xF]);
*dst++ = val;
val = av_clip_uint8(val + table[d >> 4]);
*dst++ = val;
}
*state = val;
}
/** decode a frame */
static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
EightSvxContext *esc = avctx->priv_data;
AVFrame *frame = data;
int buf_size;
int ch, ret;
int hdr_size = 2;
/* decode and interleave the first packet */
if (!esc->data[0] && avpkt) {
int chan_size = avpkt->size / avctx->channels - hdr_size;
if (avpkt->size % avctx->channels) {
av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
}
if (avpkt->size < (hdr_size + 1) * avctx->channels) {
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
return AVERROR(EINVAL);
}
esc->fib_acc[0] = avpkt->data[1] + 128;
if (avctx->channels == 2)
esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
esc->data_idx = 0;
esc->data_size = chan_size;
if (!(esc->data[0] = av_malloc(chan_size)))
return AVERROR(ENOMEM);
if (avctx->channels == 2) {
if (!(esc->data[1] = av_malloc(chan_size))) {
av_freep(&esc->data[0]);
return AVERROR(ENOMEM);
}
}
memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
if (avctx->channels == 2)
memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
}
if (!esc->data[0]) {
av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
return AVERROR(EINVAL);
}
/* decode next piece of data from the buffer */
buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
if (buf_size <= 0) {
*got_frame_ptr = 0;
return avpkt->size;
}
/* get output buffer */
frame->nb_samples = buf_size * 2;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
for (ch = 0; ch < avctx->channels; ch++) {
delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx],
buf_size, &esc->fib_acc[ch], esc->table);
}
esc->data_idx += buf_size;
*got_frame_ptr = 1;
return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels;
}
static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
{
EightSvxContext *esc = avctx->priv_data;
if (avctx->channels < 1 || avctx->channels > 2) {
av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
return AVERROR_INVALIDDATA;
}
switch (avctx->codec->id) {
case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci; break;
case AV_CODEC_ID_8SVX_EXP: esc->table = exponential; break;
default:
av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id);
return AVERROR_INVALIDDATA;
}
avctx->sample_fmt = AV_SAMPLE_FMT_U8P;
return 0;
}
static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
{
EightSvxContext *esc = avctx->priv_data;
av_freep(&esc->data[0]);
av_freep(&esc->data[1]);
esc->data_size = 0;
esc->data_idx = 0;
return 0;
}
#if CONFIG_EIGHTSVX_FIB_DECODER
AVCodec ff_eightsvx_fib_decoder = {
.name = "8svx_fib",
.long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_8SVX_FIB,
.priv_data_size = sizeof (EightSvxContext),
.init = eightsvx_decode_init,
.decode = eightsvx_decode_frame,
.close = eightsvx_decode_close,
.capabilities = CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
AV_SAMPLE_FMT_NONE },
};
#endif
#if CONFIG_EIGHTSVX_EXP_DECODER
AVCodec ff_eightsvx_exp_decoder = {
.name = "8svx_exp",
.long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_8SVX_EXP,
.priv_data_size = sizeof (EightSvxContext),
.init = eightsvx_decode_init,
.decode = eightsvx_decode_frame,
.close = eightsvx_decode_close,
.capabilities = CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
AV_SAMPLE_FMT_NONE },
};
#endif

View File

@@ -0,0 +1,889 @@
include $(SUBDIR)../config.mak
NAME = avcodec
FFLIBS = avutil
HEADERS = avcodec.h \
avfft.h \
dxva2.h \
old_codec_ids.h \
vaapi.h \
vda.h \
vdpau.h \
version.h \
xvmc.h \
OBJS = allcodecs.o \
audioconvert.o \
avpacket.o \
avpicture.o \
bitstream.o \
bitstream_filter.o \
codec_desc.o \
fmtconvert.o \
imgconvert.o \
mathtables.o \
options.o \
parser.o \
raw.o \
rawdec.o \
resample.o \
resample2.o \
utils.o \
OBJS-$(HAVE_MSVCRT) += file_open.o
# parts needed for many different codecs
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
OBJS-$(CONFIG_AC3DSP) += ac3dsp.o
OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o
OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
OBJS-$(CONFIG_DXVA2) += dxva2.o
OBJS-$(CONFIG_DSPUTIL) += dsputil.o faanidct.o \
simple_idct.o jrevdct.o
OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o
FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o cos_fixed_tables.o
OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \
fft_fixed_32.o fft_init_table.o \
$(FFT-OBJS-yes)
OBJS-$(CONFIG_GOLOMB) += golomb.o
OBJS-$(CONFIG_H264CHROMA) += h264chroma.o
OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o
OBJS-$(CONFIG_H264PRED) += h264pred.o
OBJS-$(CONFIG_H264QPEL) += h264qpel.o
OBJS-$(CONFIG_HPELDSP) += hpeldsp.o
OBJS-$(CONFIG_HUFFMAN) += huffman.o
OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o
OBJS-$(CONFIG_LPC) += lpc.o
OBJS-$(CONFIG_LSP) += lsp.o
OBJS-$(CONFIG_MDCT) += mdct_fixed.o mdct_float.o mdct_fixed_32.o
OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodata.o \
mpegaudiodecheader.o
OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \
mpegaudiodsp_data.o \
mpegaudiodsp_fixed.o \
mpegaudiodsp_float.o
OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideo_motion.o
OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \
motion_est.o ratecontrol.o
OBJS-$(CONFIG_RANGECODER) += rangecoder.o
RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o
OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes)
OBJS-$(CONFIG_SHARED) += log2_tab.o
OBJS-$(CONFIG_SINEWIN) += sinewin.o
OBJS-$(CONFIG_VAAPI) += vaapi.o
OBJS-$(CONFIG_VDPAU) += vdpau.o
OBJS-$(CONFIG_VIDEODSP) += videodsp.o
OBJS-$(CONFIG_VP3DSP) += vp3dsp.o
# decoders/encoders
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps.o \
aacadtsdec.o mpeg4audio.o kbdwin.o \
sbrdsp.o aacpsdsp.o
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \
aacpsy.o aactab.o \
psymodel.o iirfilter.o \
mpeg4audio.o kbdwin.o
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \
ac3.o kbdwin.o
OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o
OBJS-$(CONFIG_AIC_DECODER) += aic.o
OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o
OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o
OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mpeg4audio.o
OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \
celp_math.o acelp_filters.o \
acelp_vectors.o \
acelp_pitch_delay.o
OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \
celp_math.o acelp_filters.o \
acelp_vectors.o \
acelp_pitch_delay.o
OBJS-$(CONFIG_AMV_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpeg.o \
mpegvideo_enc.o motion_est.o \
ratecontrol.o mpeg12data.o \
mpegvideo.o
OBJS-$(CONFIG_ANM_DECODER) += anm.o
OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o
OBJS-$(CONFIG_APE_DECODER) += apedec.o
OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o ass_split.o
OBJS-$(CONFIG_SSA_ENCODER) += assenc.o ass.o
OBJS-$(CONFIG_ASS_DECODER) += assdec.o ass.o ass_split.o
OBJS-$(CONFIG_ASS_ENCODER) += assenc.o ass.o
OBJS-$(CONFIG_ASV1_DECODER) += asvdec.o asv.o mpeg12data.o
OBJS-$(CONFIG_ASV1_ENCODER) += asvenc.o asv.o mpeg12data.o
OBJS-$(CONFIG_ASV2_DECODER) += asvdec.o asv.o mpeg12data.o
OBJS-$(CONFIG_ASV2_ENCODER) += asvenc.o asv.o mpeg12data.o
OBJS-$(CONFIG_ATRAC1_DECODER) += atrac1.o atrac.o
OBJS-$(CONFIG_ATRAC3_DECODER) += atrac3.o atrac.o
OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
OBJS-$(CONFIG_AVS_DECODER) += avs.o
OBJS-$(CONFIG_AVUI_DECODER) += avuidec.o
OBJS-$(CONFIG_AVUI_ENCODER) += avuienc.o
OBJS-$(CONFIG_AYUV_DECODER) += v408dec.o
OBJS-$(CONFIG_AYUV_ENCODER) += v408enc.o
OBJS-$(CONFIG_BETHSOFTVID_DECODER) += bethsoftvideo.o
OBJS-$(CONFIG_BFI_DECODER) += bfi.o
OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o
OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o wma.o wma_common.o
OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o wma_common.o
OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o
OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o
OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o
OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmv.o
OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmv.o
OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brender_pix.o
OBJS-$(CONFIG_C93_DECODER) += c93.o
OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \
cavsdata.o mpeg12data.o
OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o
OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o
OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o
OBJS-$(CONFIG_CLJR_DECODER) += cljr.o
OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o
OBJS-$(CONFIG_CLLC_DECODER) += cllc.o
OBJS-$(CONFIG_COOK_DECODER) += cook.o
OBJS-$(CONFIG_COMFORTNOISE_DECODER) += cngdec.o celp_filters.o
OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o
OBJS-$(CONFIG_CPIA_DECODER) += cpia.o
OBJS-$(CONFIG_CSCD_DECODER) += cscd.o
OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o
OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadsp.o \
synth_filter.o
OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o
OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o \
dirac_arith.o mpeg12data.o dirac_dwt.o
OBJS-$(CONFIG_DFA_DECODER) += dfa.o
OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o
OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o
OBJS-$(CONFIG_DPX_DECODER) += dpx.o
OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o
OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinav.o
OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinav.o
OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o
OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o
OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o
OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o
OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o dv_profile.o
OBJS-$(CONFIG_DVVIDEO_ENCODER) += dv.o dvdata.o dv_profile.o
OBJS-$(CONFIG_DXA_DECODER) += dxa.o
OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o
OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o
OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o
OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o
OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \
mpeg12data.o
OBJS-$(CONFIG_EATGQ_DECODER) += eatgq.o eaidct.o
OBJS-$(CONFIG_EATGV_DECODER) += eatgv.o
OBJS-$(CONFIG_EATQI_DECODER) += eatqi.o eaidct.o mpeg12dec.o \
mpeg12.o mpeg12data.o
OBJS-$(CONFIG_EIGHTBPS_DECODER) += 8bps.o
OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER) += 8svx.o
OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER) += 8svx.o
OBJS-$(CONFIG_ESCAPE124_DECODER) += escape124.o
OBJS-$(CONFIG_ESCAPE130_DECODER) += escape130.o
OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o
OBJS-$(CONFIG_EXR_DECODER) += exr.o
OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o
OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o
OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o huffyuvdec.o
OBJS-$(CONFIG_FFVHUFF_ENCODER) += huffyuv.o huffyuvenc.o
OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o
OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o flacdsp.o
OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o flacdsp.o vorbis_data.o
OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o
OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o
OBJS-$(CONFIG_FLASHSV2_ENCODER) += flashsv2enc.o
OBJS-$(CONFIG_FLASHSV2_DECODER) += flashsv.o
OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o
OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o
OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o
OBJS-$(CONFIG_FRWU_DECODER) += frwu.o
OBJS-$(CONFIG_G2M_DECODER) += g2meet.o mjpeg.o
OBJS-$(CONFIG_G723_1_DECODER) += g723_1.o acelp_vectors.o \
celp_filters.o celp_math.o
OBJS-$(CONFIG_G723_1_ENCODER) += g723_1.o acelp_vectors.o celp_math.o
OBJS-$(CONFIG_G729_DECODER) += g729dec.o lsp.o celp_math.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
OBJS-$(CONFIG_GIF_DECODER) += gifdec.o lzw.o
OBJS-$(CONFIG_GIF_ENCODER) += gif.o lzwenc.o
OBJS-$(CONFIG_GSM_DECODER) += gsmdec.o gsmdec_data.o msgsmdec.o
OBJS-$(CONFIG_GSM_MS_DECODER) += gsmdec.o gsmdec_data.o msgsmdec.o
OBJS-$(CONFIG_H261_DECODER) += h261dec.o h261data.o h261.o
OBJS-$(CONFIG_H261_ENCODER) += h261enc.o h261data.o h261.o
OBJS-$(CONFIG_H263_DECODER) += h263dec.o h263.o ituh263dec.o \
mpeg4video.o mpeg4videodec.o flvdec.o\
intelh263dec.o
OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o mpeg4video.o \
h263.o ituh263enc.o flvenc.o
OBJS-$(CONFIG_H264_DECODER) += h264.o \
h264_loopfilter.o h264_direct.o \
cabac.o h264_sei.o h264_ps.o \
h264_refs.o h264_cavlc.o h264_cabac.o
OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o
OBJS-$(CONFIG_HEVC_DECODER) += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \
hevc_cabac.o hevc_refs.o hevcpred.o \
hevcdsp.o hevc_filter.o cabac.o
OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o
OBJS-$(CONFIG_IAC_DECODER) += imc.o
OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o
OBJS-$(CONFIG_IDF_DECODER) += bintext.o cga_data.o
OBJS-$(CONFIG_IFF_BYTERUN1_DECODER) += iff.o
OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o
OBJS-$(CONFIG_IMC_DECODER) += imc.o
OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o
OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o
OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi_common.o ivi_dsp.o
OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o
OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \
jpeg2000dwt.o
OBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dec.o jpeg2000.o \
jpeg2000dwt.o mqcdec.o mqc.o
OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \
mjpegdec.o mjpeg.o
OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o
OBJS-$(CONFIG_JV_DECODER) += jvdec.o
OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc.o mjpeg.o
OBJS-$(CONFIG_LOCO_DECODER) += loco.o
OBJS-$(CONFIG_MACE3_DECODER) += mace.o
OBJS-$(CONFIG_MACE6_DECODER) += mace.o
OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o
OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \
twinvq.o
OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o
OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o
OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpeg.o
OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o
OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o
OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o
OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o
OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o
OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o ass_split.o
OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec.o
OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o
OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec.o
OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc.o mpegaudio.o \
mpegaudiodata.o mpegaudiodsp_data.o
OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o
OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec.o
OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec.o
OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o
OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o
OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec.o mpeg4audio.o
OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o
OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o
OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o
OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12.o mpeg12data.o \
mpegvideo.o error_resilience.o
OBJS-$(CONFIG_MPEG_XVMC_DECODER) += mpegvideo_xvmc.o
OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o
OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o
OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o
OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o \
timecode.o
OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o
OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o
OBJS-$(CONFIG_MSMPEG4V2_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o \
h263dec.o h263.o ituh263dec.o \
mpeg4videodec.o
OBJS-$(CONFIG_MSMPEG4V2_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \
h263.o
OBJS-$(CONFIG_MSMPEG4V3_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o \
h263dec.o h263.o ituh263dec.o \
mpeg4videodec.o
OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \
h263.o
OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o
OBJS-$(CONFIG_MSA1_DECODER) += mss3.o mss34dsp.o
OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o
OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o
OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o
OBJS-$(CONFIG_MSVIDEO1_ENCODER) += msvideo1enc.o elbg.o
OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o
OBJS-$(CONFIG_MTS2_DECODER) += mss4.o mss34dsp.o
OBJS-$(CONFIG_MVC1_DECODER) += mvcdec.o
OBJS-$(CONFIG_MVC2_DECODER) += mvcdec.o
OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o
OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o
OBJS-$(CONFIG_PAF_VIDEO_DECODER) += paf.o
OBJS-$(CONFIG_PAF_AUDIO_DECODER) += paf.o
OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PAM_ENCODER) += pamenc.o pnm.o
OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o pnm.o
OBJS-$(CONFIG_PCX_DECODER) += pcx.o
OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o
OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PGM_ENCODER) += pnmenc.o pnm.o
OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o pnm.o
OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o
OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o
OBJS-$(CONFIG_PJS_DECODER) += textdec.o ass.o
OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o pngdsp.o
OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o
OBJS-$(CONFIG_PPM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o pnm.o
OBJS-$(CONFIG_PRORES_DECODER) += proresdec2.o proresdsp.o proresdata.o
OBJS-$(CONFIG_PRORES_LGPL_DECODER) += proresdec_lgpl.o proresdsp.o proresdata.o
OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o
OBJS-$(CONFIG_PRORES_AW_ENCODER) += proresenc_anatoliy.o
OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o proresdsp.o
OBJS-$(CONFIG_PTX_DECODER) += ptx.o
OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o \
celp_filters.o acelp_vectors.o \
acelp_filters.o
OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o
OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o
OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o
OBJS-$(CONFIG_QTRLE_DECODER) += qtrle.o
OBJS-$(CONFIG_QTRLE_ENCODER) += qtrleenc.o
OBJS-$(CONFIG_R10K_DECODER) += r210dec.o
OBJS-$(CONFIG_R10K_ENCODER) += r210enc.o
OBJS-$(CONFIG_R210_DECODER) += r210dec.o
OBJS-$(CONFIG_R210_ENCODER) += r210enc.o
OBJS-$(CONFIG_RA_144_DECODER) += ra144dec.o ra144.o celp_filters.o
OBJS-$(CONFIG_RA_144_ENCODER) += ra144enc.o ra144.o celp_filters.o
OBJS-$(CONFIG_RA_288_DECODER) += ra288.o celp_filters.o
OBJS-$(CONFIG_RALF_DECODER) += ralf.o
OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o
OBJS-$(CONFIG_RAWVIDEO_ENCODER) += rawenc.o
OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o ass.o
OBJS-$(CONFIG_RL2_DECODER) += rl2.o
OBJS-$(CONFIG_ROQ_DECODER) += roqvideodec.o roqvideo.o
OBJS-$(CONFIG_ROQ_ENCODER) += roqvideoenc.o roqvideo.o elbg.o
OBJS-$(CONFIG_ROQ_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o
OBJS-$(CONFIG_RPZA_DECODER) += rpza.o
OBJS-$(CONFIG_RV10_DECODER) += rv10.o
OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o
OBJS-$(CONFIG_RV20_DECODER) += rv10.o
OBJS-$(CONFIG_RV20_ENCODER) += rv20enc.o
OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o rv34dsp.o
OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv34dsp.o rv40dsp.o
OBJS-$(CONFIG_SAMI_DECODER) += samidec.o ass.o
OBJS-$(CONFIG_S302M_DECODER) += s302m.o
OBJS-$(CONFIG_S302M_ENCODER) += s302menc.o
OBJS-$(CONFIG_SANM_DECODER) += sanm.o
OBJS-$(CONFIG_SGI_DECODER) += sgidec.o
OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o
OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o
OBJS-$(CONFIG_SHORTEN_DECODER) += shorten.o
OBJS-$(CONFIG_SIPR_DECODER) += sipr.o acelp_pitch_delay.o \
celp_math.o acelp_vectors.o \
acelp_filters.o celp_filters.o \
sipr16k.o
OBJS-$(CONFIG_SMACKAUD_DECODER) += smacker.o
OBJS-$(CONFIG_SMACKER_DECODER) += smacker.o
OBJS-$(CONFIG_SMC_DECODER) += smc.o
OBJS-$(CONFIG_SMVJPEG_DECODER) += smvjpegdec.o
OBJS-$(CONFIG_SNOW_DECODER) += snowdec.o snow.o snow_dwt.o
OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o \
h263.o ituh263enc.o
OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o
OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o
OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o
OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o ass_split.o
OBJS-$(CONFIG_SUBRIP_DECODER) += srtdec.o ass.o
OBJS-$(CONFIG_SUBRIP_ENCODER) += srtenc.o ass_split.o
OBJS-$(CONFIG_SUBVIEWER1_DECODER) += textdec.o ass.o
OBJS-$(CONFIG_SUBVIEWER_DECODER) += subviewerdec.o ass.o
OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o
OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o
OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263.o
OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o \
h263.o ituh263enc.o
OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o h263.o h264.o \
h264_loopfilter.o h264_direct.o \
h264_sei.o h264_ps.o h264_refs.o \
h264_cavlc.o h264_cabac.o cabac.o
OBJS-$(CONFIG_TEXT_DECODER) += textdec.o ass.o
OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o
OBJS-$(CONFIG_TARGA_DECODER) += targa.o
OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o
OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o
OBJS-$(CONFIG_THEORA_DECODER) += xiph.o
OBJS-$(CONFIG_THP_DECODER) += mjpegdec.o mjpeg.o
OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o
OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o
OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o tiff_data.o
OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o
OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o
OBJS-$(CONFIG_TRUEMOTION1_DECODER) += truemotion1.o
OBJS-$(CONFIG_TRUEMOTION2_DECODER) += truemotion2.o
OBJS-$(CONFIG_TRUESPEECH_DECODER) += truespeech.o
OBJS-$(CONFIG_TSCC_DECODER) += tscc.o msrledec.o
OBJS-$(CONFIG_TSCC2_DECODER) += tscc2.o
OBJS-$(CONFIG_TTA_DECODER) += tta.o ttadata.o
OBJS-$(CONFIG_TTA_ENCODER) += ttaenc.o ttadata.o
OBJS-$(CONFIG_TWINVQ_DECODER) += twinvqdec.o twinvq.o
OBJS-$(CONFIG_TXD_DECODER) += txd.o s3tc.o
OBJS-$(CONFIG_ULTI_DECODER) += ulti.o
OBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodec.o utvideo.o
OBJS-$(CONFIG_UTVIDEO_ENCODER) += utvideoenc.o utvideo.o
OBJS-$(CONFIG_V210_DECODER) += v210dec.o
OBJS-$(CONFIG_V210_ENCODER) += v210enc.o
OBJS-$(CONFIG_V308_DECODER) += v308dec.o
OBJS-$(CONFIG_V308_ENCODER) += v308enc.o
OBJS-$(CONFIG_V408_DECODER) += v408dec.o
OBJS-$(CONFIG_V408_ENCODER) += v408enc.o
OBJS-$(CONFIG_V410_DECODER) += v410dec.o
OBJS-$(CONFIG_V410_ENCODER) += v410enc.o
OBJS-$(CONFIG_V210X_DECODER) += v210x.o
OBJS-$(CONFIG_VB_DECODER) += vb.o
OBJS-$(CONFIG_VBLE_DECODER) += vble.o
OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
msmpeg4dec.o msmpeg4.o msmpeg4data.o \
intrax8.o intrax8dsp.o wmv2dsp.o
OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o
OBJS-$(CONFIG_VORBIS_DECODER) += vorbisdec.o vorbisdsp.o vorbis.o \
vorbis_data.o xiph.o
OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \
vorbis_data.o
OBJS-$(CONFIG_VP3_DECODER) += vp3.o
OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \
vp56rac.o
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp56dsp.o \
vp6dsp.o vp56rac.o
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56rac.o
OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9dsp.o vp56rac.o
OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackenc.o
OBJS-$(CONFIG_WEBP_DECODER) += vp8.o vp8dsp.o vp56rac.o
OBJS-$(CONFIG_WEBP_DECODER) += webp.o
OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o
OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o
OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o wma_common.o
OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o wma.o wma_common.o aactab.o
OBJS-$(CONFIG_WMAV1_ENCODER) += wmaenc.o wma.o wma_common.o aactab.o
OBJS-$(CONFIG_WMAV2_DECODER) += wmadec.o wma.o wma_common.o aactab.o
OBJS-$(CONFIG_WMAV2_ENCODER) += wmaenc.o wma.o wma_common.o aactab.o
OBJS-$(CONFIG_WMAVOICE_DECODER) += wmavoice.o \
celp_filters.o \
acelp_vectors.o acelp_filters.o
OBJS-$(CONFIG_WMV1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o
OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2dsp.o \
msmpeg4dec.o msmpeg4.o msmpeg4data.o \
intrax8.o intrax8dsp.o
OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2dsp.o \
msmpeg4.o msmpeg4enc.o msmpeg4data.o
OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o
OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o
OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_XAN_WC3_DECODER) += xan.o
OBJS-$(CONFIG_XAN_WC4_DECODER) += xxan.o
OBJS-$(CONFIG_XBIN_DECODER) += bintext.o cga_data.o
OBJS-$(CONFIG_XBM_DECODER) += xbmdec.o
OBJS-$(CONFIG_XBM_ENCODER) += xbmenc.o
OBJS-$(CONFIG_XFACE_DECODER) += xfacedec.o xface.o
OBJS-$(CONFIG_XFACE_ENCODER) += xfaceenc.o xface.o
OBJS-$(CONFIG_XL_DECODER) += xl.o
OBJS-$(CONFIG_XSUB_DECODER) += xsubdec.o
OBJS-$(CONFIG_XSUB_ENCODER) += xsubenc.o
OBJS-$(CONFIG_XWD_DECODER) += xwddec.o
OBJS-$(CONFIG_XWD_ENCODER) += xwdenc.o
OBJS-$(CONFIG_Y41P_DECODER) += y41pdec.o
OBJS-$(CONFIG_Y41P_ENCODER) += y41penc.o
OBJS-$(CONFIG_YOP_DECODER) += yop.o
OBJS-$(CONFIG_YUV4_DECODER) += yuv4dec.o
OBJS-$(CONFIG_YUV4_ENCODER) += yuv4enc.o
OBJS-$(CONFIG_ZEROCODEC_DECODER) += zerocodec.o
OBJS-$(CONFIG_ZLIB_DECODER) += lcldec.o
OBJS-$(CONFIG_ZLIB_ENCODER) += lclenc.o
OBJS-$(CONFIG_ZMBV_DECODER) += zmbv.o
OBJS-$(CONFIG_ZMBV_ENCODER) += zmbvenc.o
# (AD)PCM decoders/encoders
OBJS-$(CONFIG_PCM_ALAW_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_ALAW_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_BLURAY_DECODER) += pcm-bluray.o
OBJS-$(CONFIG_PCM_DVD_DECODER) += pcm-dvd.o
OBJS-$(CONFIG_PCM_F32BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_F32BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_F32LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_F32LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_F64BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_F64BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_F64LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_F64LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_LXF_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_PLANAR_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S16BE_PLANAR_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S16BE_PLANAR_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S16LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S16LE_PLANAR_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S16LE_PLANAR_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S24BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S24BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S24DAUD_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S24DAUD_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S24LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S24LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S24LE_PLANAR_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S24LE_PLANAR_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S32BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S32BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S32LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S32LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S32LE_PLANAR_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S32LE_PLANAR_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U8_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U8_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U16BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U16BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U16LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U16LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U24BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U24BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U24LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U24LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U32BE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U32BE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_U32LE_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_U32LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_ZORK_DECODER) += pcm.o
OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o
OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o adx.o
OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_DTK_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_MAXIS_XA_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_XAS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_G722_DECODER) += g722.o g722dec.o
OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o g722enc.o
OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o
OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o
OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcmenc.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_RAD_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcmenc.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_IMA_WS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_MS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_MS_ENCODER) += adpcmenc.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_SBPRO_3_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_SBPRO_4_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_SWF_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_SWF_ENCODER) += adpcmenc.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_THP_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o
OBJS-$(CONFIG_VIMA_DECODER) += vima.o adpcm_data.o
# hardware accelerators
OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o vaapi_mpeg.o
OBJS-$(CONFIG_H263_VDPAU_HWACCEL) += vdpau_mpeg4.o
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o vaapi_mpeg.o
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o vaapi_mpeg.o
OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o vaapi_mpeg.o
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
# libavformat dependencies
OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o
OBJS-$(CONFIG_ADX_DEMUXER) += adx.o
OBJS-$(CONFIG_CAF_DEMUXER) += mpeg4audio.o mpegaudiodata.o \
ac3tab.o
OBJS-$(CONFIG_DV_DEMUXER) += dv_profile.o
OBJS-$(CONFIG_DV_MUXER) += dv_profile.o timecode.o
OBJS-$(CONFIG_FLAC_DEMUXER) += flac.o flacdata.o vorbis_data.o \
vorbis_parser.o xiph.o
OBJS-$(CONFIG_FLAC_MUXER) += flac.o flacdata.o vorbis_data.o
OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o
OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o
OBJS-$(CONFIG_ISMV_MUXER) += mpeg4audio.o mpegaudiodata.o
OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o
OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o vorbis_data.o \
flac.o flacdata.o
OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o
OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o mpegaudiodata.o \
flac.o flacdata.o vorbis_data.o xiph.o
OBJS-$(CONFIG_MP2_MUXER) += mpegaudiodata.o mpegaudiodecheader.o
OBJS-$(CONFIG_MP3_MUXER) += mpegaudiodata.o mpegaudiodecheader.o
OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o ac3tab.o timecode.o
OBJS-$(CONFIG_MOV_MUXER) += mpeg4audio.o mpegaudiodata.o
OBJS-$(CONFIG_MPEGTS_MUXER) += mpeg4audio.o
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpeg4audio.o mpegaudiodata.o
OBJS-$(CONFIG_MXF_MUXER) += timecode.o dnxhddata.o
OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o
OBJS-$(CONFIG_OGG_DEMUXER) += xiph.o flac.o flacdata.o \
mpeg12data.o vorbis_parser.o \
dirac.o vorbis_data.o
OBJS-$(CONFIG_OGG_MUXER) += xiph.o flac.o flacdata.o \
vorbis_data.o
OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o xiph.o
OBJS-$(CONFIG_RTPDEC) += mjpeg.o
OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o
OBJS-$(CONFIG_SPDIF_MUXER) += dca.o
OBJS-$(CONFIG_TAK_DEMUXER) += tak.o
OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o mpegaudiodata.o \
xiph.o flac.o flacdata.o \
vorbis_data.o
OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o
# external codec libraries
OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o
OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o
OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o
OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o
OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o
OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o
OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o
OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o
OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \
vorbis_data.o
OBJS-$(CONFIG_LIBOPUS_ENCODER) += libopusenc.o libopus.o \
vorbis_data.o
OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o \
libschroedinger.o
OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o \
libschroedinger.o
OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o
OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o
OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o
OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o
OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o
OBJS-$(CONFIG_LIBUTVIDEO_DECODER) += libutvideodec.o
OBJS-$(CONFIG_LIBUTVIDEO_ENCODER) += libutvideoenc.o
OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o
OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o
OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o
OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \
vorbis_data.o vorbis_parser.o xiph.o
OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o
# parsers
OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \
aacadtsdec.o mpeg4audio.o
OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o
OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \
aac_ac3_parser.o
OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o
OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o
OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o
OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o
OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca.o
OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o
OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o
OBJS-$(CONFIG_DPX_PARSER) += dpx_parser.o
OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o \
vorbis_data.o
OBJS-$(CONFIG_GSM_PARSER) += gsm_parser.o
OBJS-$(CONFIG_H261_PARSER) += h261_parser.o
OBJS-$(CONFIG_H263_PARSER) += h263_parser.o
OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264.o \
cabac.o \
h264_refs.o h264_sei.o h264_direct.o \
h264_loopfilter.o h264_cabac.o \
h264_cavlc.o h264_ps.o
OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o
OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o
OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o
OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \
mpeg4videodec.o mpeg4video.o \
ituh263dec.o h263dec.o
OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o \
mpegaudiodecheader.o mpegaudiodata.o
OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \
mpeg12.o mpeg12data.o
OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o
OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o
OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o
OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \
msmpeg4.o msmpeg4data.o mpeg4video.o \
h263.o
OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o
OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o
OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o
# bitstream filters
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \
mpeg4audio.o
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o mjpeg.o
OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o
OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o
OBJS-$(CONFIG_MP3_HEADER_COMPRESS_BSF) += mp3_header_compress_bsf.o
OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \
mpegaudiodata.o
OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o
OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o
# thread libraries
OBJS-$(HAVE_PTHREADS) += pthread.o
OBJS-$(HAVE_W32THREADS) += pthread.o
OBJS-$(HAVE_OS2THREADS) += pthread.o
OBJS-$(CONFIG_FRAME_THREAD_ENCODER) += frame_thread_encoder.o
SKIPHEADERS += %_tablegen.h \
%_tables.h \
aac_tablegen_decl.h \
fft-internal.h \
old_codec_ids.h \
tableprint.h \
$(ARCH)/vp56_arith.h \
SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
SKIPHEADERS-$(CONFIG_LIBUTVIDEO) += libutvideo.h
SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h
SKIPHEADERS-$(CONFIG_VDA) += vda.h
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h
TESTPROGS = cabac \
fft \
fft-fixed \
fft-fixed32 \
golomb \
iirfilter \
imgconvert \
rangecoder \
snowenc \
TESTPROGS-$(CONFIG_DCT) += dct
TESTPROGS-$(HAVE_MMX) += motion
TESTOBJS = dctref.o
TOOLS = fourcc2pixfmt
HOSTPROGS = aac_tablegen \
aacps_tablegen \
cbrt_tablegen \
cos_tablegen \
dv_tablegen \
motionpixels_tablegen \
mpegaudio_tablegen \
pcm_tablegen \
qdm2_tablegen \
sinewin_tablegen \
CLEANFILES = *_tables.c *_tables.h *_tablegen$(HOSTEXESUF)
$(SUBDIR)dct-test$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o
TRIG_TABLES = cos cos_fixed sin
TRIG_TABLES := $(TRIG_TABLES:%=$(SUBDIR)%_tables.c)
$(TRIG_TABLES): $(SUBDIR)%_tables.c: $(SUBDIR)cos_tablegen$(HOSTEXESUF)
$(M)./$< $* > $@
ifdef CONFIG_SMALL
$(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=1
else
$(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=0
endif
GEN_HEADERS = cbrt_tables.h aacps_tables.h aac_tables.h dv_tables.h \
sinewin_tables.h mpegaudio_tables.h motionpixels_tables.h \
pcm_tables.h qdm2_tables.h
GEN_HEADERS := $(addprefix $(SUBDIR), $(GEN_HEADERS))
$(GEN_HEADERS): $(SUBDIR)%_tables.h: $(SUBDIR)%_tablegen$(HOSTEXESUF)
$(M)./$< > $@
ifdef CONFIG_HARDCODED_TABLES
$(SUBDIR)aacdec.o: $(SUBDIR)cbrt_tables.h
$(SUBDIR)aacps.o: $(SUBDIR)aacps_tables.h
$(SUBDIR)aactab.o: $(SUBDIR)aac_tables.h
$(SUBDIR)dv.o: $(SUBDIR)dv_tables.h
$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h
$(SUBDIR)mpegaudiodec.o: $(SUBDIR)mpegaudio_tables.h
$(SUBDIR)mpegaudiodec_float.o: $(SUBDIR)mpegaudio_tables.h
$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h
$(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h
$(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h
endif

View File

@@ -0,0 +1,52 @@
/*
* a64 video encoder - c64 colors in rgb (Pepto)
* Copyright (c) 2009 Tobias Bindhammer
*
* 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
* a64 video encoder - c64 colors in rgb
*/
#ifndef AVCODEC_A64COLORS_H
#define AVCODEC_A64COLORS_H
#include <stdint.h>
/* c64 palette in RGB */
static const uint8_t a64_palette[16][3] = {
{0x00, 0x00, 0x00},
{0xff, 0xff, 0xff},
{0x68, 0x37, 0x2b},
{0x70, 0xa4, 0xb2},
{0x6f, 0x3d, 0x86},
{0x58, 0x8d, 0x43},
{0x35, 0x28, 0x79},
{0xb8, 0xc7, 0x6f},
{0x6f, 0x4f, 0x25},
{0x43, 0x39, 0x00},
{0x9a, 0x67, 0x59},
{0x44, 0x44, 0x44},
{0x6c, 0x6c, 0x6c},
{0x9a, 0xd2, 0x84},
{0x6c, 0x5e, 0xb5},
{0x95, 0x95, 0x95},
};
#endif /* AVCODEC_A64COLORS_H */

View File

@@ -0,0 +1,423 @@
/*
* a64 video encoder - multicolor modes
* Copyright (c) 2009 Tobias Bindhammer
*
* 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
* a64 video encoder - multicolor modes
*/
#include "a64colors.h"
#include "a64tables.h"
#include "elbg.h"
#include "internal.h"
#include "libavutil/common.h"
#include "libavutil/intreadwrite.h"
#define DITHERSTEPS 8
#define CHARSET_CHARS 256
#define INTERLACED 1
#define CROP_SCREENS 1
#define C64XRES 320
#define C64YRES 200
typedef struct A64Context {
/* general variables */
AVFrame picture;
/* variables for multicolor modes */
AVLFG randctx;
int mc_lifetime;
int mc_use_5col;
unsigned mc_frame_counter;
int *mc_meta_charset;
int *mc_charmap;
int *mc_best_cb;
int mc_luma_vals[5];
uint8_t *mc_charset;
uint8_t *mc_colram;
uint8_t *mc_palette;
int mc_pal_size;
/* pts of the next packet that will be output */
int64_t next_pts;
} A64Context;
/* gray gradient */
static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1};
/* other possible gradients - to be tested */
//static const int mc_colors[5]={0x0,0x8,0xa,0xf,0x7};
//static const int mc_colors[5]={0x0,0x9,0x8,0xa,0x3};
static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest)
{
int blockx, blocky, x, y;
int luma = 0;
int height = FFMIN(avctx->height, C64YRES);
int width = FFMIN(avctx->width , C64XRES);
uint8_t *src = p->data[0];
for (blocky = 0; blocky < C64YRES; blocky += 8) {
for (blockx = 0; blockx < C64XRES; blockx += 8) {
for (y = blocky; y < blocky + 8 && y < C64YRES; y++) {
for (x = blockx; x < blockx + 8 && x < C64XRES; x += 2) {
if(x < width && y < height) {
/* build average over 2 pixels */
luma = (src[(x + 0 + y * p->linesize[0])] +
src[(x + 1 + y * p->linesize[0])]) / 2;
/* write blocks as linear data now so they are suitable for elbg */
dest[0] = luma;
}
dest++;
}
}
}
}
}
static void render_charset(AVCodecContext *avctx, uint8_t *charset,
uint8_t *colrammap)
{
A64Context *c = avctx->priv_data;
uint8_t row1, row2;
int charpos, x, y;
int a, b;
uint8_t pix;
int lowdiff, highdiff;
int *best_cb = c->mc_best_cb;
static uint8_t index1[256];
static uint8_t index2[256];
static uint8_t dither[256];
int i;
int distance;
/* generate lookup-tables for dither and index before looping */
i = 0;
for (a=0; a < 256; a++) {
if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) {
distance = c->mc_luma_vals[i + 1] - c->mc_luma_vals[i];
for(b = 0; b <= distance; b++) {
dither[c->mc_luma_vals[i] + b] = b * (DITHERSTEPS - 1) / distance;
}
i++;
}
if(i >= c->mc_pal_size - 1) dither[a] = 0;
index1[a] = i;
index2[a] = FFMIN(i + 1, c->mc_pal_size - 1);
}
/* and render charset */
for (charpos = 0; charpos < CHARSET_CHARS; charpos++) {
lowdiff = 0;
highdiff = 0;
for (y = 0; y < 8; y++) {
row1 = 0; row2 = 0;
for (x = 0; x < 4; x++) {
pix = best_cb[y * 4 + x];
/* accumulate error for brightest/darkest color */
if (index1[pix] >= 3)
highdiff += pix - c->mc_luma_vals[3];
if (index1[pix] < 1)
lowdiff += c->mc_luma_vals[1] - pix;
row1 <<= 2;
if (INTERLACED) {
row2 <<= 2;
if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 0][x & 3])
row1 |= 3-(index2[pix] & 3);
else
row1 |= 3-(index1[pix] & 3);
if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 1][x & 3])
row2 |= 3-(index2[pix] & 3);
else
row2 |= 3-(index1[pix] & 3);
}
else {
if (multi_dither_patterns[dither[pix]][(y & 3)][x & 3])
row1 |= 3-(index2[pix] & 3);
else
row1 |= 3-(index1[pix] & 3);
}
}
charset[y+0x000] = row1;
if (INTERLACED) charset[y+0x800] = row2;
}
/* do we need to adjust pixels? */
if (highdiff > 0 && lowdiff > 0 && c->mc_use_5col) {
if (lowdiff > highdiff) {
for (x = 0; x < 32; x++)
best_cb[x] = FFMIN(c->mc_luma_vals[3], best_cb[x]);
} else {
for (x = 0; x < 32; x++)
best_cb[x] = FFMAX(c->mc_luma_vals[1], best_cb[x]);
}
charpos--; /* redo now adjusted char */
/* no adjustment needed, all fine */
} else {
/* advance pointers */
best_cb += 32;
charset += 8;
/* remember colorram value */
colrammap[charpos] = (highdiff > 0);
}
}
}
static av_cold int a64multi_close_encoder(AVCodecContext *avctx)
{
A64Context *c = avctx->priv_data;
av_free(c->mc_meta_charset);
av_free(c->mc_best_cb);
av_free(c->mc_charset);
av_free(c->mc_charmap);
av_free(c->mc_colram);
return 0;
}
static av_cold int a64multi_init_encoder(AVCodecContext *avctx)
{
A64Context *c = avctx->priv_data;
int a;
av_lfg_init(&c->randctx, 1);
if (avctx->global_quality < 1) {
c->mc_lifetime = 4;
} else {
c->mc_lifetime = avctx->global_quality /= FF_QP2LAMBDA;
}
av_log(avctx, AV_LOG_INFO, "charset lifetime set to %d frame(s)\n", c->mc_lifetime);
c->mc_frame_counter = 0;
c->mc_use_5col = avctx->codec->id == AV_CODEC_ID_A64_MULTI5;
c->mc_pal_size = 4 + c->mc_use_5col;
/* precalc luma values for later use */
for (a = 0; a < c->mc_pal_size; a++) {
c->mc_luma_vals[a]=a64_palette[mc_colors[a]][0] * 0.30 +
a64_palette[mc_colors[a]][1] * 0.59 +
a64_palette[mc_colors[a]][2] * 0.11;
}
if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * sizeof(int))) ||
!(c->mc_best_cb = av_malloc(CHARSET_CHARS * 32 * sizeof(int))) ||
!(c->mc_charmap = av_mallocz(1000 * c->mc_lifetime * sizeof(int))) ||
!(c->mc_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) ||
!(c->mc_charset = av_malloc(0x800 * (INTERLACED+1) * sizeof(uint8_t)))) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate buffer memory.\n");
return AVERROR(ENOMEM);
}
/* set up extradata */
if (!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for extradata.\n");
return AVERROR(ENOMEM);
}
avctx->extradata_size = 8 * 4;
AV_WB32(avctx->extradata, c->mc_lifetime);
AV_WB32(avctx->extradata + 16, INTERLACED);
avcodec_get_frame_defaults(&c->picture);
avctx->coded_frame = &c->picture;
avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
avctx->coded_frame->key_frame = 1;
if (!avctx->codec_tag)
avctx->codec_tag = AV_RL32("a64m");
c->next_pts = AV_NOPTS_VALUE;
return 0;
}
static void a64_compress_colram(unsigned char *buf, int *charmap, uint8_t *colram)
{
int a;
uint8_t temp;
/* only needs to be done in 5col mode */
/* XXX could be squeezed to 0x80 bytes */
for (a = 0; a < 256; a++) {
temp = colram[charmap[a + 0x000]] << 0;
temp |= colram[charmap[a + 0x100]] << 1;
temp |= colram[charmap[a + 0x200]] << 2;
if (a < 0xe8) temp |= colram[charmap[a + 0x300]] << 3;
buf[a] = temp << 2;
}
}
static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *pict, int *got_packet)
{
A64Context *c = avctx->priv_data;
AVFrame *const p = &c->picture;
int frame;
int x, y;
int b_height;
int b_width;
int req_size, ret;
uint8_t *buf = NULL;
int *charmap = c->mc_charmap;
uint8_t *colram = c->mc_colram;
uint8_t *charset = c->mc_charset;
int *meta = c->mc_meta_charset;
int *best_cb = c->mc_best_cb;
int charset_size = 0x800 * (INTERLACED + 1);
int colram_size = 0x100 * c->mc_use_5col;
int screen_size;
if(CROP_SCREENS) {
b_height = FFMIN(avctx->height,C64YRES) >> 3;
b_width = FFMIN(avctx->width ,C64XRES) >> 3;
screen_size = b_width * b_height;
} else {
b_height = C64YRES >> 3;
b_width = C64XRES >> 3;
screen_size = 0x400;
}
/* no data, means end encoding asap */
if (!pict) {
/* all done, end encoding */
if (!c->mc_lifetime) return 0;
/* no more frames in queue, prepare to flush remaining frames */
if (!c->mc_frame_counter) {
c->mc_lifetime = 0;
}
/* still frames in queue so limit lifetime to remaining frames */
else c->mc_lifetime = c->mc_frame_counter;
/* still new data available */
} else {
/* fill up mc_meta_charset with data until lifetime exceeds */
if (c->mc_frame_counter < c->mc_lifetime) {
*p = *pict;
p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1;
to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter);
c->mc_frame_counter++;
if (c->next_pts == AV_NOPTS_VALUE)
c->next_pts = pict->pts;
/* lifetime is not reached so wait for next frame first */
return 0;
}
}
/* lifetime reached so now convert X frames at once */
if (c->mc_frame_counter == c->mc_lifetime) {
req_size = 0;
/* any frames to encode? */
if (c->mc_lifetime) {
req_size = charset_size + c->mc_lifetime*(screen_size + colram_size);
if ((ret = ff_alloc_packet2(avctx, pkt, req_size)) < 0)
return ret;
buf = pkt->data;
/* calc optimal new charset + charmaps */
ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx);
ff_do_elbg (meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx);
/* create colorram map and a c64 readable charset */
render_charset(avctx, charset, colram);
/* copy charset to buf */
memcpy(buf, charset, charset_size);
/* advance pointers */
buf += charset_size;
charset += charset_size;
}
/* write x frames to buf */
for (frame = 0; frame < c->mc_lifetime; frame++) {
/* copy charmap to buf. buf is uchar*, charmap is int*, so no memcpy here, sorry */
for (y = 0; y < b_height; y++) {
for (x = 0; x < b_width; x++) {
buf[y * b_width + x] = charmap[y * b_width + x];
}
}
/* advance pointers */
buf += screen_size;
req_size += screen_size;
/* compress and copy colram to buf */
if (c->mc_use_5col) {
a64_compress_colram(buf, charmap, colram);
/* advance pointers */
buf += colram_size;
req_size += colram_size;
}
/* advance to next charmap */
charmap += 1000;
}
AV_WB32(avctx->extradata + 4, c->mc_frame_counter);
AV_WB32(avctx->extradata + 8, charset_size);
AV_WB32(avctx->extradata + 12, screen_size + colram_size);
/* reset counter */
c->mc_frame_counter = 0;
pkt->pts = pkt->dts = c->next_pts;
c->next_pts = AV_NOPTS_VALUE;
pkt->size = req_size;
pkt->flags |= AV_PKT_FLAG_KEY;
*got_packet = !!req_size;
}
return 0;
}
#if CONFIG_A64MULTI_ENCODER
AVCodec ff_a64multi_encoder = {
.name = "a64multi",
.long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_A64_MULTI,
.priv_data_size = sizeof(A64Context),
.init = a64multi_init_encoder,
.encode2 = a64multi_encode_frame,
.close = a64multi_close_encoder,
.pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
.capabilities = CODEC_CAP_DELAY,
};
#endif
#if CONFIG_A64MULTI5_ENCODER
AVCodec ff_a64multi5_encoder = {
.name = "a64multi5",
.long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_A64_MULTI5,
.priv_data_size = sizeof(A64Context),
.init = a64multi_init_encoder,
.encode2 = a64multi_encode_frame,
.close = a64multi_close_encoder,
.pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
.capabilities = CODEC_CAP_DELAY,
};
#endif

View File

@@ -0,0 +1,150 @@
/*
* a64 video encoder - tables used by a64 encoders
* Copyright (c) 2009 Tobias Bindhammer
*
* 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
* a64 video encoder - tables used by a64 encoders
*/
#ifndef AVCODEC_A64TABLES_H
#define AVCODEC_A64TABLES_H
#include <stdint.h>
/**
* dither patterns used vor rendering the multicolor charset
*/
static const uint8_t multi_dither_patterns[9][4][4] = {
{
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}
},
{
{1, 0, 0, 0},
{0, 0, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 1}
},
{
{1, 0, 0, 0},
{0, 1, 0, 1},
{0, 0, 1, 0},
{0, 1, 0, 1}
},
{
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1}
},
{
{1, 1, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 1},
{0, 1, 0, 1}
},
{
{0, 1, 1, 1},
{1, 1, 0, 1},
{1, 0, 1, 1},
{1, 1, 1, 0}
},
{
{0, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 1}
},
{
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}
},
};
static const uint8_t interlaced_dither_patterns[9][8][4] = {
{
{0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0},
},
{
{1, 0, 1, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0},
{1, 0, 1, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 0, 0, 0},
},
{
{1, 0, 1, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 1, 0, 1},
{1, 0, 1, 0}, {0, 0, 0, 0},
{0, 0, 0, 0}, {0, 1, 0, 1},
},
{
{1, 0, 1, 0}, {0, 1, 0, 1},
{0, 1, 0, 1}, {0, 0, 0, 0},
{1, 0, 1, 0}, {0, 1, 0, 1},
{0, 1, 0, 1}, {0, 0, 0, 0},
},
{
{1, 0, 1, 0}, {0, 1, 0, 1},
{0, 1, 0, 1}, {1, 0, 1, 0},
{1, 0, 1, 0}, {0, 1, 0, 1},
{0, 1, 0, 1}, {1, 0, 1, 0},
},
{
{1, 0, 1, 0}, {0, 1, 0, 1},
{1, 1, 1, 1}, {1, 0, 1, 0},
{1, 0, 1, 0}, {0, 1, 0, 1},
{1, 1, 1, 1}, {1, 0, 1, 0},
},
{
{1, 0, 1, 0}, {1, 1, 1, 1},
{1, 1, 1, 1}, {0, 1, 0, 1},
{1, 0, 1, 0}, {1, 1, 1, 1},
{1, 1, 1, 1}, {0, 1, 0, 1},
},
{
{1, 1, 1, 1}, {1, 1, 1, 1},
{1, 1, 1, 1}, {0, 1, 0, 1},
{1, 1, 1, 1}, {1, 1, 1, 1},
{1, 1, 1, 1}, {0, 1, 0, 1},
},
{
{1, 1, 1, 1}, {1, 1, 1, 1},
{1, 1, 1, 1}, {1, 1, 1, 1},
{1, 1, 1, 1}, {1, 1, 1, 1},
{1, 1, 1, 1}, {1, 1, 1, 1},
}
};
#endif /* AVCODEC_A64TABLES_H */

View File

@@ -0,0 +1,334 @@
/*
* AAC definitions and structures
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail 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
*/
/**
* @file
* AAC definitions and structures
* @author Oded Shimon ( ods15 ods15 dyndns org )
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
#ifndef AVCODEC_AAC_H
#define AVCODEC_AAC_H
#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "fft.h"
#include "mpeg4audio.h"
#include "sbr.h"
#include "fmtconvert.h"
#include <stdint.h>
#define MAX_CHANNELS 64
#define MAX_ELEM_ID 16
#define TNS_MAX_ORDER 20
#define MAX_LTP_LONG_SFB 40
enum RawDataBlockType {
TYPE_SCE,
TYPE_CPE,
TYPE_CCE,
TYPE_LFE,
TYPE_DSE,
TYPE_PCE,
TYPE_FIL,
TYPE_END,
};
enum ExtensionPayloadID {
EXT_FILL,
EXT_FILL_DATA,
EXT_DATA_ELEMENT,
EXT_DYNAMIC_RANGE = 0xb,
EXT_SBR_DATA = 0xd,
EXT_SBR_DATA_CRC = 0xe,
};
enum WindowSequence {
ONLY_LONG_SEQUENCE,
LONG_START_SEQUENCE,
EIGHT_SHORT_SEQUENCE,
LONG_STOP_SEQUENCE,
};
enum BandType {
ZERO_BT = 0, ///< Scalefactors and spectral data are all zero.
FIRST_PAIR_BT = 5, ///< This and later band types encode two values (rather than four) with one code word.
ESC_BT = 11, ///< Spectral data are coded with an escape sequence.
NOISE_BT = 13, ///< Spectral data are scaled white noise not coded in the bitstream.
INTENSITY_BT2 = 14, ///< Scalefactor data are intensity stereo positions.
INTENSITY_BT = 15, ///< Scalefactor data are intensity stereo positions.
};
#define IS_CODEBOOK_UNSIGNED(x) ((x - 1) & 10)
enum ChannelPosition {
AAC_CHANNEL_OFF = 0,
AAC_CHANNEL_FRONT = 1,
AAC_CHANNEL_SIDE = 2,
AAC_CHANNEL_BACK = 3,
AAC_CHANNEL_LFE = 4,
AAC_CHANNEL_CC = 5,
};
/**
* The point during decoding at which channel coupling is applied.
*/
enum CouplingPoint {
BEFORE_TNS,
BETWEEN_TNS_AND_IMDCT,
AFTER_IMDCT = 3,
};
/**
* Output configuration status
*/
enum OCStatus {
OC_NONE, ///< Output unconfigured
OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE
OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header
OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked
OC_LOCKED, ///< Output configuration locked in place
};
typedef struct OutputConfiguration {
MPEG4AudioConfig m4ac;
uint8_t layout_map[MAX_ELEM_ID*4][3];
int layout_map_tags;
int channels;
uint64_t channel_layout;
enum OCStatus status;
} OutputConfiguration;
/**
* Predictor State
*/
typedef struct PredictorState {
float cor0;
float cor1;
float var0;
float var1;
float r0;
float r1;
} PredictorState;
#define MAX_PREDICTORS 672
#define SCALE_DIV_512 36 ///< scalefactor difference that corresponds to scale difference in 512 times
#define SCALE_ONE_POS 140 ///< scalefactor index that corresponds to scale=1.0
#define SCALE_MAX_POS 255 ///< scalefactor index maximum value
#define SCALE_MAX_DIFF 60 ///< maximum scalefactor difference allowed by standard
#define SCALE_DIFF_ZERO 60 ///< codebook index corresponding to zero scalefactor indices difference
/**
* Long Term Prediction
*/
typedef struct LongTermPrediction {
int8_t present;
int16_t lag;
float coef;
int8_t used[MAX_LTP_LONG_SFB];
} LongTermPrediction;
/**
* Individual Channel Stream
*/
typedef struct IndividualChannelStream {
uint8_t max_sfb; ///< number of scalefactor bands per group
enum WindowSequence window_sequence[2];
uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
int num_window_groups;
uint8_t group_len[8];
LongTermPrediction ltp;
const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window
int num_swb; ///< number of scalefactor window bands
int num_windows;
int tns_max_bands;
int predictor_present;
int predictor_initialized;
int predictor_reset_group;
uint8_t prediction_used[41];
} IndividualChannelStream;
/**
* Temporal Noise Shaping
*/
typedef struct TemporalNoiseShaping {
int present;
int n_filt[8];
int length[8][4];
int direction[8][4];
int order[8][4];
float coef[8][4][TNS_MAX_ORDER];
} TemporalNoiseShaping;
/**
* Dynamic Range Control - decoded from the bitstream but not processed further.
*/
typedef struct DynamicRangeControl {
int pce_instance_tag; ///< Indicates with which program the DRC info is associated.
int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative
int dyn_rng_ctl[17]; ///< DRC magnitude information
int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing.
int band_incr; ///< Number of DRC bands greater than 1 having DRC info.
int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain.
int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines.
int prog_ref_level; /**< A reference level for the long-term program audio level for all
* channels combined.
*/
} DynamicRangeControl;
typedef struct Pulse {
int num_pulse;
int start;
int pos[4];
int amp[4];
} Pulse;
/**
* coupling parameters
*/
typedef struct ChannelCoupling {
enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
int num_coupled; ///< number of target elements
enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
int id_select[8]; ///< element id
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
* [2] list of gains for left channel; [3] lists of gains for both channels
*/
float gain[16][120];
} ChannelCoupling;
/**
* Single Channel Element - used for both SCE and LFE elements.
*/
typedef struct SingleChannelElement {
IndividualChannelStream ics;
TemporalNoiseShaping tns;
Pulse pulse;
enum BandType band_type[128]; ///< band types
int band_type_run_end[120]; ///< band type run end points
float sf[120]; ///< scalefactors
int sf_idx[128]; ///< scalefactor indices (used by encoder)
uint8_t zeroes[128]; ///< band is not coded (used by encoder)
DECLARE_ALIGNED(32, float, coeffs)[1024]; ///< coefficients for IMDCT
DECLARE_ALIGNED(32, float, saved)[1536]; ///< overlap
DECLARE_ALIGNED(32, float, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, float, ltp_state)[3072]; ///< time signal for LTP
PredictorState predictor_state[MAX_PREDICTORS];
float *ret; ///< PCM output
} SingleChannelElement;
/**
* channel element - generic struct for SCE/CPE/CCE/LFE
*/
typedef struct ChannelElement {
// CPE specific
int common_window; ///< Set if channels share a common 'IndividualChannelStream' in bitstream.
int ms_mode; ///< Signals mid/side stereo flags coding mode (used by encoder)
uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band
// shared
SingleChannelElement ch[2];
// CCE specific
ChannelCoupling coup;
SpectralBandReplication sbr;
} ChannelElement;
/**
* main AAC context
*/
struct AACContext {
AVClass *class;
AVCodecContext *avctx;
AVFrame *frame;
int is_saved; ///< Set if elements have stored overlap from previous frame.
DynamicRangeControl che_drc;
/**
* @name Channel element related data
* @{
*/
ChannelElement *che[4][MAX_ELEM_ID];
ChannelElement *tag_che_map[4][MAX_ELEM_ID];
int tags_mapped;
/** @} */
/**
* @name temporary aligned temporary buffers
* (We do not want to have these on the stack.)
* @{
*/
DECLARE_ALIGNED(32, float, buf_mdct)[1024];
/** @} */
/**
* @name Computed / set up during initialization
* @{
*/
FFTContext mdct;
FFTContext mdct_small;
FFTContext mdct_ld;
FFTContext mdct_ltp;
FmtConvertContext fmt_conv;
AVFloatDSPContext fdsp;
int random_state;
/** @} */
/**
* @name Members used for output
* @{
*/
SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement
/** @} */
/**
* @name Japanese DTV specific extension
* @{
*/
int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
/** @} */
DECLARE_ALIGNED(32, float, temp)[128];
OutputConfiguration oc[2];
int warned_num_aac_frames;
/* aacdec functions pointers */
void (*imdct_and_windowing)(AACContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(AACContext *ac, SingleChannelElement *sce);
void (*apply_tns)(float coef[1024], TemporalNoiseShaping *tns,
IndividualChannelStream *ics, int decode);
void (*windowing_and_mdct_ltp)(AACContext *ac, float *out,
float *in, IndividualChannelStream *ics);
void (*update_ltp)(AACContext *ac, SingleChannelElement *sce);
};
void ff_aacdec_init_mips(AACContext *c);
#endif /* AVCODEC_AAC_H */

View File

@@ -0,0 +1,104 @@
/*
* Common AAC and AC-3 parser
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 "libavutil/common.h"
#include "parser.h"
#include "aac_ac3_parser.h"
int ff_aac_ac3_parse(AVCodecParserContext *s1,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
AACAC3ParseContext *s = s1->priv_data;
ParseContext *pc = &s->pc;
int len, i;
int new_frame_start;
get_next:
i=END_NOT_FOUND;
if(s->remaining_size <= buf_size){
if(s->remaining_size && !s->need_next_header){
i= s->remaining_size;
s->remaining_size = 0;
}else{ //we need a header first
len=0;
for(i=s->remaining_size; i<buf_size; i++){
s->state = (s->state<<8) + buf[i];
if((len=s->sync(s->state, s, &s->need_next_header, &new_frame_start)))
break;
}
if(len<=0){
i=END_NOT_FOUND;
}else{
s->state=0;
i-= s->header_size -1;
s->remaining_size = len;
if(!new_frame_start || pc->index+i<=0){
s->remaining_size += i;
goto get_next;
}
}
}
}
if(ff_combine_frame(pc, i, &buf, &buf_size)<0){
s->remaining_size -= FFMIN(s->remaining_size, buf_size);
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
}
*poutbuf = buf;
*poutbuf_size = buf_size;
/* update codec info */
if(s->codec_id)
avctx->codec_id = s->codec_id;
/* Due to backwards compatible HE-AAC the sample rate, channel count,
and total number of samples found in an AAC ADTS header are not
reliable. Bit rate is still accurate because the total frame duration in
seconds is still correct (as is the number of bits in the frame). */
if (avctx->codec_id != AV_CODEC_ID_AAC) {
avctx->sample_rate = s->sample_rate;
/* allow downmixing to stereo (or mono for AC-3) */
if(avctx->request_channels > 0 &&
avctx->request_channels < s->channels &&
(avctx->request_channels <= 2 ||
(avctx->request_channels == 1 &&
(avctx->codec_id == AV_CODEC_ID_AC3 ||
avctx->codec_id == AV_CODEC_ID_EAC3)))) {
avctx->channels = avctx->request_channels;
} else {
avctx->channels = s->channels;
avctx->channel_layout = s->channel_layout;
}
s1->duration = s->samples;
avctx->audio_service_type = s->service_type;
}
avctx->bit_rate = s->bit_rate;
return i;
}

View File

@@ -0,0 +1,66 @@
/*
* Common AAC and AC-3 parser prototypes
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 AVCODEC_AAC_AC3_PARSER_H
#define AVCODEC_AAC_AC3_PARSER_H
#include <stdint.h>
#include "avcodec.h"
#include "parser.h"
typedef enum {
AAC_AC3_PARSE_ERROR_SYNC = -0x1030c0a,
AAC_AC3_PARSE_ERROR_BSID = -0x2030c0a,
AAC_AC3_PARSE_ERROR_SAMPLE_RATE = -0x3030c0a,
AAC_AC3_PARSE_ERROR_FRAME_SIZE = -0x4030c0a,
AAC_AC3_PARSE_ERROR_FRAME_TYPE = -0x5030c0a,
AAC_AC3_PARSE_ERROR_CRC = -0x6030c0a,
AAC_AC3_PARSE_ERROR_CHANNEL_CFG = -0x7030c0a,
} AACAC3ParseError;
typedef struct AACAC3ParseContext {
ParseContext pc;
int frame_size;
int header_size;
int (*sync)(uint64_t state, struct AACAC3ParseContext *hdr_info,
int *need_next_header, int *new_frame_start);
int channels;
int sample_rate;
int bit_rate;
int samples;
uint64_t channel_layout;
int service_type;
int remaining_size;
uint64_t state;
int need_next_header;
enum AVCodecID codec_id;
} AACAC3ParseContext;
int ff_aac_ac3_parse(AVCodecParserContext *s1,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size);
#endif /* AVCODEC_AAC_AC3_PARSER_H */

View File

@@ -0,0 +1,118 @@
/*
* MPEG-2/4 AAC ADTS to MPEG-4 Audio Specific Configuration bitstream filter
* Copyright (c) 2009 Alex Converse <alex.converse@gmail.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
*/
#include "avcodec.h"
#include "aacadtsdec.h"
#include "put_bits.h"
#include "get_bits.h"
#include "mpeg4audio.h"
#include "internal.h"
typedef struct AACBSFContext {
int first_frame_done;
} AACBSFContext;
/**
* This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4
* ADTS header and removes the ADTS header.
*/
static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size,
int keyframe)
{
GetBitContext gb;
PutBitContext pb;
AACADTSHeaderInfo hdr;
AACBSFContext *ctx = bsfc->priv_data;
init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8);
*poutbuf = (uint8_t*) buf;
*poutbuf_size = buf_size;
if (avctx->extradata)
if (show_bits(&gb, 12) != 0xfff)
return 0;
if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
return -1;
}
if (!hdr.crc_absent && hdr.num_aac_frames > 1) {
avpriv_report_missing_feature(avctx,
"Multiple RDBs per frame with CRC");
return AVERROR_PATCHWELCOME;
}
buf += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
if (!ctx->first_frame_done) {
int pce_size = 0;
uint8_t pce_data[MAX_PCE_SIZE];
if (!hdr.chan_config) {
init_get_bits(&gb, buf, buf_size * 8);
if (get_bits(&gb, 3) != 5) {
avpriv_report_missing_feature(avctx,
"PCE-based channel configuration "
"without PCE as first syntax "
"element");
return AVERROR_PATCHWELCOME;
}
init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
flush_put_bits(&pb);
buf_size -= get_bits_count(&gb)/8;
buf += get_bits_count(&gb)/8;
}
avctx->extradata_size = 2 + pce_size;
avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
put_bits(&pb, 5, hdr.object_type);
put_bits(&pb, 4, hdr.sampling_index);
put_bits(&pb, 4, hdr.chan_config);
put_bits(&pb, 1, 0); //frame length - 1024 samples
put_bits(&pb, 1, 0); //does not depend on core coder
put_bits(&pb, 1, 0); //is not extension
flush_put_bits(&pb);
if (pce_size) {
memcpy(avctx->extradata + 2, pce_data, pce_size);
}
ctx->first_frame_done = 1;
}
*poutbuf = (uint8_t*) buf;
*poutbuf_size = buf_size;
return 0;
}
AVBitStreamFilter ff_aac_adtstoasc_bsf = {
.name = "aac_adtstoasc",
.priv_data_size = sizeof(AACBSFContext),
.filter = aac_adtstoasc_filter,
};

View File

@@ -0,0 +1,69 @@
/*
* Audio and Video frame extraction
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 "parser.h"
#include "aac_ac3_parser.h"
#include "aacadtsdec.h"
#include "get_bits.h"
#include "mpeg4audio.h"
static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info,
int *need_next_header, int *new_frame_start)
{
GetBitContext bits;
AACADTSHeaderInfo hdr;
int size;
union {
uint64_t u64;
uint8_t u8[8];
} tmp;
tmp.u64 = av_be2ne64(state);
init_get_bits(&bits, tmp.u8+8-AAC_ADTS_HEADER_SIZE, AAC_ADTS_HEADER_SIZE * 8);
if ((size = avpriv_aac_parse_header(&bits, &hdr)) < 0)
return 0;
*need_next_header = 0;
*new_frame_start = 1;
hdr_info->sample_rate = hdr.sample_rate;
hdr_info->channels = ff_mpeg4audio_channels[hdr.chan_config];
hdr_info->samples = hdr.samples;
hdr_info->bit_rate = hdr.bit_rate;
return size;
}
static av_cold int aac_parse_init(AVCodecParserContext *s1)
{
AACAC3ParseContext *s = s1->priv_data;
s->header_size = AAC_ADTS_HEADER_SIZE;
s->sync = aac_sync;
return 0;
}
AVCodecParser ff_aac_parser = {
.codec_ids = { AV_CODEC_ID_AAC },
.priv_data_size = sizeof(AACAC3ParseContext),
.parser_init = aac_parse_init,
.parser_parse = ff_aac_ac3_parse,
.parser_close = ff_parse_close,
};

View File

@@ -0,0 +1,37 @@
/*
* Generate a header file for hardcoded AAC tables
*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
#include <stdlib.h>
#define CONFIG_HARDCODED_TABLES 0
#include "aac_tablegen.h"
#include "tableprint.h"
int main(void)
{
ff_aac_tableinit();
write_fileheader();
WRITE_ARRAY("const", float, ff_aac_pow2sf_tab);
return 0;
}

View File

@@ -0,0 +1,42 @@
/*
* Header file for hardcoded AAC tables
*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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 AVCODEC_AAC_TABLEGEN_H
#define AVCODEC_AAC_TABLEGEN_H
#include "aac_tablegen_decl.h"
#if CONFIG_HARDCODED_TABLES
#include "libavcodec/aac_tables.h"
#else
#include "libavutil/mathematics.h"
float ff_aac_pow2sf_tab[428];
void ff_aac_tableinit(void)
{
int i;
for (i = 0; i < 428; i++)
ff_aac_pow2sf_tab[i] = pow(2, (i - POW_SF2_ZERO) / 4.0);
}
#endif /* CONFIG_HARDCODED_TABLES */
#endif /* AVCODEC_AAC_TABLEGEN_H */

View File

@@ -0,0 +1,36 @@
/*
* Header file for hardcoded AAC tables
*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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 AVCODEC_AAC_TABLEGEN_DECL_H
#define AVCODEC_AAC_TABLEGEN_DECL_H
#define POW_SF2_ZERO 200 ///< ff_aac_pow2sf_tab index corresponding to pow(2, 0);
#if CONFIG_HARDCODED_TABLES
#define ff_aac_tableinit()
extern const float ff_aac_pow2sf_tab[428];
#else
void ff_aac_tableinit(void);
extern float ff_aac_pow2sf_tab[428];
#endif /* CONFIG_HARDCODED_TABLES */
#endif /* AVCODEC_AAC_TABLEGEN_DECL_H */

View File

@@ -0,0 +1,70 @@
/*
* Audio and Video frame extraction
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
* Copyright (c) 2009 Alex Converse
*
* 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 "aac_ac3_parser.h"
#include "aacadtsdec.h"
#include "get_bits.h"
#include "mpeg4audio.h"
int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr)
{
int size, rdb, ch, sr;
int aot, crc_abs;
if(get_bits(gbc, 12) != 0xfff)
return AAC_AC3_PARSE_ERROR_SYNC;
skip_bits1(gbc); /* id */
skip_bits(gbc, 2); /* layer */
crc_abs = get_bits1(gbc); /* protection_absent */
aot = get_bits(gbc, 2); /* profile_objecttype */
sr = get_bits(gbc, 4); /* sample_frequency_index */
if(!avpriv_mpeg4audio_sample_rates[sr])
return AAC_AC3_PARSE_ERROR_SAMPLE_RATE;
skip_bits1(gbc); /* private_bit */
ch = get_bits(gbc, 3); /* channel_configuration */
skip_bits1(gbc); /* original/copy */
skip_bits1(gbc); /* home */
/* adts_variable_header */
skip_bits1(gbc); /* copyright_identification_bit */
skip_bits1(gbc); /* copyright_identification_start */
size = get_bits(gbc, 13); /* aac_frame_length */
if(size < AAC_ADTS_HEADER_SIZE)
return AAC_AC3_PARSE_ERROR_FRAME_SIZE;
skip_bits(gbc, 11); /* adts_buffer_fullness */
rdb = get_bits(gbc, 2); /* number_of_raw_data_blocks_in_frame */
hdr->object_type = aot + 1;
hdr->chan_config = ch;
hdr->crc_absent = crc_abs;
hdr->num_aac_frames = rdb + 1;
hdr->sampling_index = sr;
hdr->sample_rate = avpriv_mpeg4audio_sample_rates[sr];
hdr->samples = (rdb + 1) * 1024;
hdr->bit_rate = size * 8 * hdr->sample_rate / hdr->samples;
return size;
}

View File

@@ -0,0 +1,54 @@
/*
* AAC ADTS header decoding prototypes and structures
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 AVCODEC_AACADTSDEC_H
#define AVCODEC_AACADTSDEC_H
#include <stdint.h>
#include "get_bits.h"
#define AAC_ADTS_HEADER_SIZE 7
typedef struct AACADTSHeaderInfo {
uint32_t sample_rate;
uint32_t samples;
uint32_t bit_rate;
uint8_t crc_absent;
uint8_t object_type;
uint8_t sampling_index;
uint8_t chan_config;
uint8_t num_aac_frames;
} AACADTSHeaderInfo;
/**
* Parse AAC frame header.
* Parse the ADTS frame header to the end of the variable header, which is
* the first 54 bits.
* @param[in] gbc BitContext containing the first 54 bits of the frame.
* @param[out] hdr Pointer to struct where header info is written.
* @return Returns 0 on success, -1 if there is a sync word mismatch,
* -2 if the version element is invalid, -3 if the sample rate
* element is invalid, or -4 if the bit rate element is invalid.
*/
int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr);
#endif /* AVCODEC_AACADTSDEC_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
/*
* AAC decoder data
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail 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
*/
/**
* @file
* AAC decoder data
* @author Oded Shimon ( ods15 ods15 dyndns org )
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
#ifndef AVCODEC_AACDECTAB_H
#define AVCODEC_AACDECTAB_H
#include "libavutil/channel_layout.h"
#include "aac.h"
#include <stdint.h>
/* @name ltp_coef
* Table of the LTP coefficients
*/
static const float ltp_coef[8] = {
0.570829, 0.696616, 0.813004, 0.911304,
0.984900, 1.067894, 1.194601, 1.369533,
};
/* @name tns_tmp2_map
* Tables of the tmp2[] arrays of LPC coefficients used for TNS.
* The suffix _M_N[] indicate the values of coef_compress and coef_res
* respectively.
* @{
*/
static const float tns_tmp2_map_1_3[4] = {
0.00000000, -0.43388373, 0.64278758, 0.34202015,
};
static const float tns_tmp2_map_0_3[8] = {
0.00000000, -0.43388373, -0.78183150, -0.97492790,
0.98480773, 0.86602539, 0.64278758, 0.34202015,
};
static const float tns_tmp2_map_1_4[8] = {
0.00000000, -0.20791170, -0.40673664, -0.58778524,
0.67369562, 0.52643216, 0.36124167, 0.18374951,
};
static const float tns_tmp2_map_0_4[16] = {
0.00000000, -0.20791170, -0.40673664, -0.58778524,
-0.74314481, -0.86602539, -0.95105654, -0.99452192,
0.99573416, 0.96182561, 0.89516330, 0.79801720,
0.67369562, 0.52643216, 0.36124167, 0.18374951,
};
static const float * const tns_tmp2_map[4] = {
tns_tmp2_map_0_3,
tns_tmp2_map_0_4,
tns_tmp2_map_1_3,
tns_tmp2_map_1_4
};
// @}
static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 };
static const uint8_t aac_channel_layout_map[7][5][3] = {
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, },
{ { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },
{ { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, },
};
static const uint64_t aac_channel_layout[8] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_SURROUND,
AV_CH_LAYOUT_4POINT0,
AV_CH_LAYOUT_5POINT0_BACK,
AV_CH_LAYOUT_5POINT1_BACK,
AV_CH_LAYOUT_7POINT1_WIDE_BACK,
0,
};
#endif /* AVCODEC_AACDECTAB_H */

View File

@@ -0,0 +1,831 @@
/*
* AAC encoder
* Copyright (C) 2008 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
* AAC encoder
*/
/***********************************
* TODOs:
* add sane pulse detection
* add temporal noise shaping
***********************************/
#include "libavutil/float_dsp.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "put_bits.h"
#include "internal.h"
#include "mpeg4audio.h"
#include "kbdwin.h"
#include "sinewin.h"
#include "aac.h"
#include "aactab.h"
#include "aacenc.h"
#include "psymodel.h"
#define AAC_MAX_CHANNELS 6
#define ERROR_IF(cond, ...) \
if (cond) { \
av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \
return AVERROR(EINVAL); \
}
float ff_aac_pow34sf_tab[428];
static const uint8_t swb_size_1024_96[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8,
12, 12, 12, 12, 12, 16, 16, 24, 28, 36, 44,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
static const uint8_t swb_size_1024_64[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8,
12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 36,
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40
};
static const uint8_t swb_size_1024_48[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8,
12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
96
};
static const uint8_t swb_size_1024_32[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8,
12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
};
static const uint8_t swb_size_1024_24[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28,
32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64
};
static const uint8_t swb_size_1024_16[] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28,
32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64
};
static const uint8_t swb_size_1024_8[] = {
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, 28,
32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80
};
static const uint8_t *swb_size_1024[] = {
swb_size_1024_96, swb_size_1024_96, swb_size_1024_64,
swb_size_1024_48, swb_size_1024_48, swb_size_1024_32,
swb_size_1024_24, swb_size_1024_24, swb_size_1024_16,
swb_size_1024_16, swb_size_1024_16, swb_size_1024_8
};
static const uint8_t swb_size_128_96[] = {
4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36
};
static const uint8_t swb_size_128_48[] = {
4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16
};
static const uint8_t swb_size_128_24[] = {
4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20
};
static const uint8_t swb_size_128_16[] = {
4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20
};
static const uint8_t swb_size_128_8[] = {
4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20
};
static const uint8_t *swb_size_128[] = {
/* the last entry on the following row is swb_size_128_64 but is a
duplicate of swb_size_128_96 */
swb_size_128_96, swb_size_128_96, swb_size_128_96,
swb_size_128_48, swb_size_128_48, swb_size_128_48,
swb_size_128_24, swb_size_128_24, swb_size_128_16,
swb_size_128_16, swb_size_128_16, swb_size_128_8
};
/** default channel configurations */
static const uint8_t aac_chan_configs[6][5] = {
{1, TYPE_SCE}, // 1 channel - single channel element
{1, TYPE_CPE}, // 2 channels - channel pair
{2, TYPE_SCE, TYPE_CPE}, // 3 channels - center + stereo
{3, TYPE_SCE, TYPE_CPE, TYPE_SCE}, // 4 channels - front center + stereo + back center
{3, TYPE_SCE, TYPE_CPE, TYPE_CPE}, // 5 channels - front center + stereo + back stereo
{4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_LFE}, // 6 channels - front center + stereo + back stereo + LFE
};
/**
* Table to remap channels from libavcodec's default order to AAC order.
*/
static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = {
{ 0 },
{ 0, 1 },
{ 2, 0, 1 },
{ 2, 0, 1, 3 },
{ 2, 0, 1, 3, 4 },
{ 2, 0, 1, 4, 5, 3 },
};
/**
* Make AAC audio config object.
* @see 1.6.2.1 "Syntax - AudioSpecificConfig"
*/
static void put_audio_specific_config(AVCodecContext *avctx)
{
PutBitContext pb;
AACEncContext *s = avctx->priv_data;
init_put_bits(&pb, avctx->extradata, avctx->extradata_size*8);
put_bits(&pb, 5, 2); //object type - AAC-LC
put_bits(&pb, 4, s->samplerate_index); //sample rate index
put_bits(&pb, 4, s->channels);
//GASpecificConfig
put_bits(&pb, 1, 0); //frame length - 1024 samples
put_bits(&pb, 1, 0); //does not depend on core coder
put_bits(&pb, 1, 0); //is not extension
//Explicitly Mark SBR absent
put_bits(&pb, 11, 0x2b7); //sync extension
put_bits(&pb, 5, AOT_SBR);
put_bits(&pb, 1, 0);
flush_put_bits(&pb);
}
#define WINDOW_FUNC(type) \
static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \
SingleChannelElement *sce, \
const float *audio)
WINDOW_FUNC(only_long)
{
const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
float *out = sce->ret_buf;
fdsp->vector_fmul (out, audio, lwindow, 1024);
fdsp->vector_fmul_reverse(out + 1024, audio + 1024, pwindow, 1024);
}
WINDOW_FUNC(long_start)
{
const float *lwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
float *out = sce->ret_buf;
fdsp->vector_fmul(out, audio, lwindow, 1024);
memcpy(out + 1024, audio + 1024, sizeof(out[0]) * 448);
fdsp->vector_fmul_reverse(out + 1024 + 448, audio + 1024 + 448, swindow, 128);
memset(out + 1024 + 576, 0, sizeof(out[0]) * 448);
}
WINDOW_FUNC(long_stop)
{
const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
const float *swindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
float *out = sce->ret_buf;
memset(out, 0, sizeof(out[0]) * 448);
fdsp->vector_fmul(out + 448, audio + 448, swindow, 128);
memcpy(out + 576, audio + 576, sizeof(out[0]) * 448);
fdsp->vector_fmul_reverse(out + 1024, audio + 1024, lwindow, 1024);
}
WINDOW_FUNC(eight_short)
{
const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
const float *in = audio + 448;
float *out = sce->ret_buf;
int w;
for (w = 0; w < 8; w++) {
fdsp->vector_fmul (out, in, w ? pwindow : swindow, 128);
out += 128;
in += 128;
fdsp->vector_fmul_reverse(out, in, swindow, 128);
out += 128;
}
}
static void (*const apply_window[4])(AVFloatDSPContext *fdsp,
SingleChannelElement *sce,
const float *audio) = {
[ONLY_LONG_SEQUENCE] = apply_only_long_window,
[LONG_START_SEQUENCE] = apply_long_start_window,
[EIGHT_SHORT_SEQUENCE] = apply_eight_short_window,
[LONG_STOP_SEQUENCE] = apply_long_stop_window
};
static void apply_window_and_mdct(AACEncContext *s, SingleChannelElement *sce,
float *audio)
{
int i;
float *output = sce->ret_buf;
apply_window[sce->ics.window_sequence[0]](&s->fdsp, sce, audio);
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE)
s->mdct1024.mdct_calc(&s->mdct1024, sce->coeffs, output);
else
for (i = 0; i < 1024; i += 128)
s->mdct128.mdct_calc(&s->mdct128, sce->coeffs + i, output + i*2);
memcpy(audio, audio + 1024, sizeof(audio[0]) * 1024);
}
/**
* Encode ics_info element.
* @see Table 4.6 (syntax of ics_info)
*/
static void put_ics_info(AACEncContext *s, IndividualChannelStream *info)
{
int w;
put_bits(&s->pb, 1, 0); // ics_reserved bit
put_bits(&s->pb, 2, info->window_sequence[0]);
put_bits(&s->pb, 1, info->use_kb_window[0]);
if (info->window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
put_bits(&s->pb, 6, info->max_sfb);
put_bits(&s->pb, 1, 0); // no prediction
} else {
put_bits(&s->pb, 4, info->max_sfb);
for (w = 1; w < 8; w++)
put_bits(&s->pb, 1, !info->group_len[w]);
}
}
/**
* Encode MS data.
* @see 4.6.8.1 "Joint Coding - M/S Stereo"
*/
static void encode_ms_info(PutBitContext *pb, ChannelElement *cpe)
{
int i, w;
put_bits(pb, 2, cpe->ms_mode);
if (cpe->ms_mode == 1)
for (w = 0; w < cpe->ch[0].ics.num_windows; w += cpe->ch[0].ics.group_len[w])
for (i = 0; i < cpe->ch[0].ics.max_sfb; i++)
put_bits(pb, 1, cpe->ms_mask[w*16 + i]);
}
/**
* Produce integer coefficients from scalefactors provided by the model.
*/
static void adjust_frame_information(ChannelElement *cpe, int chans)
{
int i, w, w2, g, ch;
int start, maxsfb, cmaxsfb;
for (ch = 0; ch < chans; ch++) {
IndividualChannelStream *ics = &cpe->ch[ch].ics;
start = 0;
maxsfb = 0;
cpe->ch[ch].pulse.num_pulse = 0;
for (w = 0; w < ics->num_windows*16; w += 16) {
for (g = 0; g < ics->num_swb; g++) {
//apply M/S
if (cpe->common_window && !ch && cpe->ms_mask[w + g]) {
for (i = 0; i < ics->swb_sizes[g]; i++) {
cpe->ch[0].coeffs[start+i] = (cpe->ch[0].coeffs[start+i] + cpe->ch[1].coeffs[start+i]) / 2.0;
cpe->ch[1].coeffs[start+i] = cpe->ch[0].coeffs[start+i] - cpe->ch[1].coeffs[start+i];
}
}
start += ics->swb_sizes[g];
}
for (cmaxsfb = ics->num_swb; cmaxsfb > 0 && cpe->ch[ch].zeroes[w+cmaxsfb-1]; cmaxsfb--)
;
maxsfb = FFMAX(maxsfb, cmaxsfb);
}
ics->max_sfb = maxsfb;
//adjust zero bands for window groups
for (w = 0; w < ics->num_windows; w += ics->group_len[w]) {
for (g = 0; g < ics->max_sfb; g++) {
i = 1;
for (w2 = w; w2 < w + ics->group_len[w]; w2++) {
if (!cpe->ch[ch].zeroes[w2*16 + g]) {
i = 0;
break;
}
}
cpe->ch[ch].zeroes[w*16 + g] = i;
}
}
}
if (chans > 1 && cpe->common_window) {
IndividualChannelStream *ics0 = &cpe->ch[0].ics;
IndividualChannelStream *ics1 = &cpe->ch[1].ics;
int msc = 0;
ics0->max_sfb = FFMAX(ics0->max_sfb, ics1->max_sfb);
ics1->max_sfb = ics0->max_sfb;
for (w = 0; w < ics0->num_windows*16; w += 16)
for (i = 0; i < ics0->max_sfb; i++)
if (cpe->ms_mask[w+i])
msc++;
if (msc == 0 || ics0->max_sfb == 0)
cpe->ms_mode = 0;
else
cpe->ms_mode = msc < ics0->max_sfb * ics0->num_windows ? 1 : 2;
}
}
/**
* Encode scalefactor band coding type.
*/
static void encode_band_info(AACEncContext *s, SingleChannelElement *sce)
{
int w;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w])
s->coder->encode_window_bands_info(s, sce, w, sce->ics.group_len[w], s->lambda);
}
/**
* Encode scalefactors.
*/
static void encode_scale_factors(AVCodecContext *avctx, AACEncContext *s,
SingleChannelElement *sce)
{
int off = sce->sf_idx[0], diff;
int i, w;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
for (i = 0; i < sce->ics.max_sfb; i++) {
if (!sce->zeroes[w*16 + i]) {
diff = sce->sf_idx[w*16 + i] - off + SCALE_DIFF_ZERO;
av_assert0(diff >= 0 && diff <= 120);
off = sce->sf_idx[w*16 + i];
put_bits(&s->pb, ff_aac_scalefactor_bits[diff], ff_aac_scalefactor_code[diff]);
}
}
}
}
/**
* Encode pulse data.
*/
static void encode_pulses(AACEncContext *s, Pulse *pulse)
{
int i;
put_bits(&s->pb, 1, !!pulse->num_pulse);
if (!pulse->num_pulse)
return;
put_bits(&s->pb, 2, pulse->num_pulse - 1);
put_bits(&s->pb, 6, pulse->start);
for (i = 0; i < pulse->num_pulse; i++) {
put_bits(&s->pb, 5, pulse->pos[i]);
put_bits(&s->pb, 4, pulse->amp[i]);
}
}
/**
* Encode spectral coefficients processed by psychoacoustic model.
*/
static void encode_spectral_coeffs(AACEncContext *s, SingleChannelElement *sce)
{
int start, i, w, w2;
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
start = 0;
for (i = 0; i < sce->ics.max_sfb; i++) {
if (sce->zeroes[w*16 + i]) {
start += sce->ics.swb_sizes[i];
continue;
}
for (w2 = w; w2 < w + sce->ics.group_len[w]; w2++)
s->coder->quantize_and_encode_band(s, &s->pb, sce->coeffs + start + w2*128,
sce->ics.swb_sizes[i],
sce->sf_idx[w*16 + i],
sce->band_type[w*16 + i],
s->lambda);
start += sce->ics.swb_sizes[i];
}
}
}
/**
* Encode one channel of audio data.
*/
static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s,
SingleChannelElement *sce,
int common_window)
{
put_bits(&s->pb, 8, sce->sf_idx[0]);
if (!common_window)
put_ics_info(s, &sce->ics);
encode_band_info(s, sce);
encode_scale_factors(avctx, s, sce);
encode_pulses(s, &sce->pulse);
put_bits(&s->pb, 1, 0); //tns
put_bits(&s->pb, 1, 0); //ssr
encode_spectral_coeffs(s, sce);
return 0;
}
/**
* Write some auxiliary information about the created AAC file.
*/
static void put_bitstream_info(AACEncContext *s, const char *name)
{
int i, namelen, padbits;
namelen = strlen(name) + 2;
put_bits(&s->pb, 3, TYPE_FIL);
put_bits(&s->pb, 4, FFMIN(namelen, 15));
if (namelen >= 15)
put_bits(&s->pb, 8, namelen - 14);
put_bits(&s->pb, 4, 0); //extension type - filler
padbits = -put_bits_count(&s->pb) & 7;
avpriv_align_put_bits(&s->pb);
for (i = 0; i < namelen - 2; i++)
put_bits(&s->pb, 8, name[i]);
put_bits(&s->pb, 12 - padbits, 0);
}
/*
* Copy input samples.
* Channels are reordered from libavcodec's default order to AAC order.
*/
static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
{
int ch;
int end = 2048 + (frame ? frame->nb_samples : 0);
const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
/* copy and remap input samples */
for (ch = 0; ch < s->channels; ch++) {
/* copy last 1024 samples of previous frame to the start of the current frame */
memcpy(&s->planar_samples[ch][1024], &s->planar_samples[ch][2048], 1024 * sizeof(s->planar_samples[0][0]));
/* copy new samples and zero any remaining samples */
if (frame) {
memcpy(&s->planar_samples[ch][2048],
frame->extended_data[channel_map[ch]],
frame->nb_samples * sizeof(s->planar_samples[0][0]));
}
memset(&s->planar_samples[ch][end], 0,
(3072 - end) * sizeof(s->planar_samples[0][0]));
}
}
static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
AACEncContext *s = avctx->priv_data;
float **samples = s->planar_samples, *samples2, *la, *overlap;
ChannelElement *cpe;
int i, ch, w, g, chans, tag, start_ch, ret;
int chan_el_counter[4];
FFPsyWindowInfo windows[AAC_MAX_CHANNELS];
if (s->last_frame == 2)
return 0;
/* add current frame to queue */
if (frame) {
if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
return ret;
}
copy_input_samples(s, frame);
if (s->psypp)
ff_psy_preprocess(s->psypp, s->planar_samples, s->channels);
if (!avctx->frame_number)
return 0;
start_ch = 0;
for (i = 0; i < s->chan_map[0]; i++) {
FFPsyWindowInfo* wi = windows + start_ch;
tag = s->chan_map[i+1];
chans = tag == TYPE_CPE ? 2 : 1;
cpe = &s->cpe[i];
for (ch = 0; ch < chans; ch++) {
IndividualChannelStream *ics = &cpe->ch[ch].ics;
int cur_channel = start_ch + ch;
overlap = &samples[cur_channel][0];
samples2 = overlap + 1024;
la = samples2 + (448+64);
if (!frame)
la = NULL;
if (tag == TYPE_LFE) {
wi[ch].window_type[0] = ONLY_LONG_SEQUENCE;
wi[ch].window_shape = 0;
wi[ch].num_windows = 1;
wi[ch].grouping[0] = 1;
/* Only the lowest 12 coefficients are used in a LFE channel.
* The expression below results in only the bottom 8 coefficients
* being used for 11.025kHz to 16kHz sample rates.
*/
ics->num_swb = s->samplerate_index >= 8 ? 1 : 3;
} else {
wi[ch] = s->psy.model->window(&s->psy, samples2, la, cur_channel,
ics->window_sequence[0]);
}
ics->window_sequence[1] = ics->window_sequence[0];
ics->window_sequence[0] = wi[ch].window_type[0];
ics->use_kb_window[1] = ics->use_kb_window[0];
ics->use_kb_window[0] = wi[ch].window_shape;
ics->num_windows = wi[ch].num_windows;
ics->swb_sizes = s->psy.bands [ics->num_windows == 8];
ics->num_swb = tag == TYPE_LFE ? ics->num_swb : s->psy.num_bands[ics->num_windows == 8];
for (w = 0; w < ics->num_windows; w++)
ics->group_len[w] = wi[ch].grouping[w];
apply_window_and_mdct(s, &cpe->ch[ch], overlap);
}
start_ch += chans;
}
if ((ret = ff_alloc_packet2(avctx, avpkt, 8192 * s->channels)) < 0)
return ret;
do {
int frame_bits;
init_put_bits(&s->pb, avpkt->data, avpkt->size);
if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & CODEC_FLAG_BITEXACT))
put_bitstream_info(s, LIBAVCODEC_IDENT);
start_ch = 0;
memset(chan_el_counter, 0, sizeof(chan_el_counter));
for (i = 0; i < s->chan_map[0]; i++) {
FFPsyWindowInfo* wi = windows + start_ch;
const float *coeffs[2];
tag = s->chan_map[i+1];
chans = tag == TYPE_CPE ? 2 : 1;
cpe = &s->cpe[i];
put_bits(&s->pb, 3, tag);
put_bits(&s->pb, 4, chan_el_counter[tag]++);
for (ch = 0; ch < chans; ch++)
coeffs[ch] = cpe->ch[ch].coeffs;
s->psy.model->analyze(&s->psy, start_ch, coeffs, wi);
for (ch = 0; ch < chans; ch++) {
s->cur_channel = start_ch + ch;
s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda);
}
cpe->common_window = 0;
if (chans > 1
&& wi[0].window_type[0] == wi[1].window_type[0]
&& wi[0].window_shape == wi[1].window_shape) {
cpe->common_window = 1;
for (w = 0; w < wi[0].num_windows; w++) {
if (wi[0].grouping[w] != wi[1].grouping[w]) {
cpe->common_window = 0;
break;
}
}
}
s->cur_channel = start_ch;
if (s->options.stereo_mode && cpe->common_window) {
if (s->options.stereo_mode > 0) {
IndividualChannelStream *ics = &cpe->ch[0].ics;
for (w = 0; w < ics->num_windows; w += ics->group_len[w])
for (g = 0; g < ics->num_swb; g++)
cpe->ms_mask[w*16+g] = 1;
} else if (s->coder->search_for_ms) {
s->coder->search_for_ms(s, cpe, s->lambda);
}
}
adjust_frame_information(cpe, chans);
if (chans == 2) {
put_bits(&s->pb, 1, cpe->common_window);
if (cpe->common_window) {
put_ics_info(s, &cpe->ch[0].ics);
encode_ms_info(&s->pb, cpe);
}
}
for (ch = 0; ch < chans; ch++) {
s->cur_channel = start_ch + ch;
encode_individual_channel(avctx, s, &cpe->ch[ch], cpe->common_window);
}
start_ch += chans;
}
frame_bits = put_bits_count(&s->pb);
if (frame_bits <= 6144 * s->channels - 3) {
s->psy.bitres.bits = frame_bits / s->channels;
break;
}
s->lambda *= avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits;
} while (1);
put_bits(&s->pb, 3, TYPE_END);
flush_put_bits(&s->pb);
avctx->frame_bits = put_bits_count(&s->pb);
// rate control stuff
if (!(avctx->flags & CODEC_FLAG_QSCALE)) {
float ratio = avctx->bit_rate * 1024.0f / avctx->sample_rate / avctx->frame_bits;
s->lambda *= ratio;
s->lambda = FFMIN(s->lambda, 65536.f);
}
if (!frame)
s->last_frame++;
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
avpkt->size = put_bits_count(&s->pb) >> 3;
*got_packet_ptr = 1;
return 0;
}
static av_cold int aac_encode_end(AVCodecContext *avctx)
{
AACEncContext *s = avctx->priv_data;
ff_mdct_end(&s->mdct1024);
ff_mdct_end(&s->mdct128);
ff_psy_end(&s->psy);
if (s->psypp)
ff_psy_preprocess_end(s->psypp);
av_freep(&s->buffer.samples);
av_freep(&s->cpe);
ff_af_queue_close(&s->afq);
return 0;
}
static av_cold int dsp_init(AVCodecContext *avctx, AACEncContext *s)
{
int ret = 0;
avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
// window init
ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024);
ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128);
ff_init_ff_sine_windows(10);
ff_init_ff_sine_windows(7);
if (ret = ff_mdct_init(&s->mdct1024, 11, 0, 32768.0))
return ret;
if (ret = ff_mdct_init(&s->mdct128, 8, 0, 32768.0))
return ret;
return 0;
}
static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s)
{
int ch;
FF_ALLOCZ_OR_GOTO(avctx, s->buffer.samples, 3 * 1024 * s->channels * sizeof(s->buffer.samples[0]), alloc_fail);
FF_ALLOCZ_OR_GOTO(avctx, s->cpe, sizeof(ChannelElement) * s->chan_map[0], alloc_fail);
FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + FF_INPUT_BUFFER_PADDING_SIZE, alloc_fail);
for(ch = 0; ch < s->channels; ch++)
s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch;
return 0;
alloc_fail:
return AVERROR(ENOMEM);
}
static av_cold int aac_encode_init(AVCodecContext *avctx)
{
AACEncContext *s = avctx->priv_data;
int i, ret = 0;
const uint8_t *sizes[2];
uint8_t grouping[AAC_MAX_CHANNELS];
int lengths[2];
avctx->frame_size = 1024;
for (i = 0; i < 16; i++)
if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i])
break;
s->channels = avctx->channels;
ERROR_IF(i == 16,
"Unsupported sample rate %d\n", avctx->sample_rate);
ERROR_IF(s->channels > AAC_MAX_CHANNELS,
"Unsupported number of channels: %d\n", s->channels);
ERROR_IF(avctx->profile != FF_PROFILE_UNKNOWN && avctx->profile != FF_PROFILE_AAC_LOW,
"Unsupported profile %d\n", avctx->profile);
ERROR_IF(1024.0 * avctx->bit_rate / avctx->sample_rate > 6144 * s->channels,
"Too many bits per frame requested\n");
s->samplerate_index = i;
s->chan_map = aac_chan_configs[s->channels-1];
if (ret = dsp_init(avctx, s))
goto fail;
if (ret = alloc_buffers(avctx, s))
goto fail;
avctx->extradata_size = 5;
put_audio_specific_config(avctx);
sizes[0] = swb_size_1024[i];
sizes[1] = swb_size_128[i];
lengths[0] = ff_aac_num_swb_1024[i];
lengths[1] = ff_aac_num_swb_128[i];
for (i = 0; i < s->chan_map[0]; i++)
grouping[i] = s->chan_map[i + 1] == TYPE_CPE;
if (ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths, s->chan_map[0], grouping))
goto fail;
s->psypp = ff_psy_preprocess_init(avctx);
s->coder = &ff_aac_coders[s->options.aac_coder];
if (HAVE_MIPSDSPR1)
ff_aac_coder_init_mips(s);
s->lambda = avctx->global_quality ? avctx->global_quality : 120;
ff_aac_tableinit();
for (i = 0; i < 428; i++)
ff_aac_pow34sf_tab[i] = sqrt(ff_aac_pow2sf_tab[i] * sqrt(ff_aac_pow2sf_tab[i]));
avctx->delay = 1024;
ff_af_queue_init(avctx, &s->afq);
return 0;
fail:
aac_encode_end(avctx);
return ret;
}
#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
static const AVOption aacenc_options[] = {
{"stereo_mode", "Stereo coding method", offsetof(AACEncContext, options.stereo_mode), AV_OPT_TYPE_INT, {.i64 = 0}, -1, 1, AACENC_FLAGS, "stereo_mode"},
{"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
{"ms_off", "Disable Mid/Side coding", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
{"ms_force", "Force Mid/Side for the whole frame if possible", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
{"aac_coder", "", offsetof(AACEncContext, options.aac_coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "aac_coder"},
{"faac", "FAAC-inspired method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAAC}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
{"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
{"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
{"fast", "Constant quantizer", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_coder"},
{NULL}
};
static const AVClass aacenc_class = {
"AAC encoder",
av_default_item_name,
aacenc_options,
LIBAVUTIL_VERSION_INT,
};
/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build
* failures */
static const int mpeg4audio_sample_rates[16] = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 7350
};
AVCodec ff_aac_encoder = {
.name = "aac",
.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACEncContext),
.init = aac_encode_init,
.encode2 = aac_encode_frame,
.close = aac_encode_end,
.supported_samplerates = mpeg4audio_sample_rates,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY |
CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.priv_class = &aacenc_class,
};

View File

@@ -0,0 +1,97 @@
/*
* AAC encoder
* Copyright (C) 2008 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
*/
#ifndef AVCODEC_AACENC_H
#define AVCODEC_AACENC_H
#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "put_bits.h"
#include "aac.h"
#include "audio_frame_queue.h"
#include "psymodel.h"
typedef enum AACCoder {
AAC_CODER_FAAC = 0,
AAC_CODER_ANMR,
AAC_CODER_TWOLOOP,
AAC_CODER_FAST,
AAC_CODER_NB,
}AACCoder;
typedef struct AACEncOptions {
int stereo_mode;
int aac_coder;
} AACEncOptions;
struct AACEncContext;
typedef struct AACCoefficientsEncoder {
void (*search_for_quantizers)(AVCodecContext *avctx, struct AACEncContext *s,
SingleChannelElement *sce, const float lambda);
void (*encode_window_bands_info)(struct AACEncContext *s, SingleChannelElement *sce,
int win, int group_len, const float lambda);
void (*quantize_and_encode_band)(struct AACEncContext *s, PutBitContext *pb, const float *in, int size,
int scale_idx, int cb, const float lambda);
void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe, const float lambda);
} AACCoefficientsEncoder;
extern AACCoefficientsEncoder ff_aac_coders[];
/**
* AAC encoder context
*/
typedef struct AACEncContext {
AVClass *av_class;
AACEncOptions options; ///< encoding options
PutBitContext pb;
FFTContext mdct1024; ///< long (1024 samples) frame transform context
FFTContext mdct128; ///< short (128 samples) frame transform context
AVFloatDSPContext fdsp;
float *planar_samples[6]; ///< saved preprocessed input
int samplerate_index; ///< MPEG-4 samplerate index
int channels; ///< channel count
const uint8_t *chan_map; ///< channel configuration map
ChannelElement *cpe; ///< channel elements
FFPsyContext psy;
struct FFPsyPreprocessContext* psypp;
AACCoefficientsEncoder *coder;
int cur_channel;
int last_frame;
float lambda;
AudioFrameQueue afq;
DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients
DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients
struct {
float *samples;
} buffer;
} AACEncContext;
extern float ff_aac_pow34sf_tab[428];
void ff_aac_coder_init_mips(AACEncContext *c);
#endif /* AVCODEC_AACENC_H */

View File

@@ -0,0 +1,969 @@
/*
* MPEG-4 Parametric Stereo decoding functions
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
#include <stdint.h>
#include "libavutil/common.h"
#include "libavutil/internal.h"
#include "libavutil/mathematics.h"
#include "avcodec.h"
#include "get_bits.h"
#include "aacps.h"
#include "aacps_tablegen.h"
#include "aacpsdata.c"
#define PS_BASELINE 0 ///< Operate in Baseline PS mode
///< Baseline implies 10 or 20 stereo bands,
///< mixing mode A, and no ipd/opd
#define numQMFSlots 32 //numTimeSlots * RATE
static const int8_t num_env_tab[2][4] = {
{ 0, 1, 2, 4, },
{ 1, 2, 3, 4, },
};
static const int8_t nr_iidicc_par_tab[] = {
10, 20, 34, 10, 20, 34,
};
static const int8_t nr_iidopd_par_tab[] = {
5, 11, 17, 5, 11, 17,
};
enum {
huff_iid_df1,
huff_iid_dt1,
huff_iid_df0,
huff_iid_dt0,
huff_icc_df,
huff_icc_dt,
huff_ipd_df,
huff_ipd_dt,
huff_opd_df,
huff_opd_dt,
};
static const int huff_iid[] = {
huff_iid_df0,
huff_iid_df1,
huff_iid_dt0,
huff_iid_dt1,
};
static VLC vlc_ps[10];
#define READ_PAR_DATA(PAR, OFFSET, MASK, ERR_CONDITION) \
/** \
* Read Inter-channel Intensity Difference/Inter-Channel Coherence/ \
* Inter-channel Phase Difference/Overall Phase Difference parameters from the \
* bitstream. \
* \
* @param avctx contains the current codec context \
* @param gb pointer to the input bitstream \
* @param ps pointer to the Parametric Stereo context \
* @param PAR pointer to the parameter to be read \
* @param e envelope to decode \
* @param dt 1: time delta-coded, 0: frequency delta-coded \
*/ \
static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, \
int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \
{ \
int b, num = ps->nr_ ## PAR ## _par; \
VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \
if (dt) { \
int e_prev = e ? e - 1 : ps->num_env_old - 1; \
e_prev = FFMAX(e_prev, 0); \
for (b = 0; b < num; b++) { \
int val = PAR[e_prev][b] + get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \
if (MASK) val &= MASK; \
PAR[e][b] = val; \
if (ERR_CONDITION) \
goto err; \
} \
} else { \
int val = 0; \
for (b = 0; b < num; b++) { \
val += get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \
if (MASK) val &= MASK; \
PAR[e][b] = val; \
if (ERR_CONDITION) \
goto err; \
} \
} \
return 0; \
err: \
av_log(avctx, AV_LOG_ERROR, "illegal "#PAR"\n"); \
return -1; \
}
READ_PAR_DATA(iid, huff_offset[table_idx], 0, FFABS(ps->iid_par[e][b]) > 7 + 8 * ps->iid_quant)
READ_PAR_DATA(icc, huff_offset[table_idx], 0, ps->icc_par[e][b] > 7U)
READ_PAR_DATA(ipdopd, 0, 0x07, 0)
static int ps_read_extension_data(GetBitContext *gb, PSContext *ps, int ps_extension_id)
{
int e;
int count = get_bits_count(gb);
if (ps_extension_id)
return 0;
ps->enable_ipdopd = get_bits1(gb);
if (ps->enable_ipdopd) {
for (e = 0; e < ps->num_env; e++) {
int dt = get_bits1(gb);
read_ipdopd_data(NULL, gb, ps, ps->ipd_par, dt ? huff_ipd_dt : huff_ipd_df, e, dt);
dt = get_bits1(gb);
read_ipdopd_data(NULL, gb, ps, ps->opd_par, dt ? huff_opd_dt : huff_opd_df, e, dt);
}
}
skip_bits1(gb); //reserved_ps
return get_bits_count(gb) - count;
}
static void ipdopd_reset(int8_t *ipd_hist, int8_t *opd_hist)
{
int i;
for (i = 0; i < PS_MAX_NR_IPDOPD; i++) {
opd_hist[i] = 0;
ipd_hist[i] = 0;
}
}
int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb_host, PSContext *ps, int bits_left)
{
int e;
int bit_count_start = get_bits_count(gb_host);
int header;
int bits_consumed;
GetBitContext gbc = *gb_host, *gb = &gbc;
header = get_bits1(gb);
if (header) { //enable_ps_header
ps->enable_iid = get_bits1(gb);
if (ps->enable_iid) {
int iid_mode = get_bits(gb, 3);
if (iid_mode > 5) {
av_log(avctx, AV_LOG_ERROR, "iid_mode %d is reserved.\n",
iid_mode);
goto err;
}
ps->nr_iid_par = nr_iidicc_par_tab[iid_mode];
ps->iid_quant = iid_mode > 2;
ps->nr_ipdopd_par = nr_iidopd_par_tab[iid_mode];
}
ps->enable_icc = get_bits1(gb);
if (ps->enable_icc) {
ps->icc_mode = get_bits(gb, 3);
if (ps->icc_mode > 5) {
av_log(avctx, AV_LOG_ERROR, "icc_mode %d is reserved.\n",
ps->icc_mode);
goto err;
}
ps->nr_icc_par = nr_iidicc_par_tab[ps->icc_mode];
}
ps->enable_ext = get_bits1(gb);
}
ps->frame_class = get_bits1(gb);
ps->num_env_old = ps->num_env;
ps->num_env = num_env_tab[ps->frame_class][get_bits(gb, 2)];
ps->border_position[0] = -1;
if (ps->frame_class) {
for (e = 1; e <= ps->num_env; e++)
ps->border_position[e] = get_bits(gb, 5);
} else
for (e = 1; e <= ps->num_env; e++)
ps->border_position[e] = (e * numQMFSlots >> ff_log2_tab[ps->num_env]) - 1;
if (ps->enable_iid) {
for (e = 0; e < ps->num_env; e++) {
int dt = get_bits1(gb);
if (read_iid_data(avctx, gb, ps, ps->iid_par, huff_iid[2*dt+ps->iid_quant], e, dt))
goto err;
}
} else
memset(ps->iid_par, 0, sizeof(ps->iid_par));
if (ps->enable_icc)
for (e = 0; e < ps->num_env; e++) {
int dt = get_bits1(gb);
if (read_icc_data(avctx, gb, ps, ps->icc_par, dt ? huff_icc_dt : huff_icc_df, e, dt))
goto err;
}
else
memset(ps->icc_par, 0, sizeof(ps->icc_par));
if (ps->enable_ext) {
int cnt = get_bits(gb, 4);
if (cnt == 15) {
cnt += get_bits(gb, 8);
}
cnt *= 8;
while (cnt > 7) {
int ps_extension_id = get_bits(gb, 2);
cnt -= 2 + ps_read_extension_data(gb, ps, ps_extension_id);
}
if (cnt < 0) {
av_log(avctx, AV_LOG_ERROR, "ps extension overflow %d\n", cnt);
goto err;
}
skip_bits(gb, cnt);
}
ps->enable_ipdopd &= !PS_BASELINE;
//Fix up envelopes
if (!ps->num_env || ps->border_position[ps->num_env] < numQMFSlots - 1) {
//Create a fake envelope
int source = ps->num_env ? ps->num_env - 1 : ps->num_env_old - 1;
int b;
if (source >= 0 && source != ps->num_env) {
if (ps->enable_iid) {
memcpy(ps->iid_par+ps->num_env, ps->iid_par+source, sizeof(ps->iid_par[0]));
}
if (ps->enable_icc) {
memcpy(ps->icc_par+ps->num_env, ps->icc_par+source, sizeof(ps->icc_par[0]));
}
if (ps->enable_ipdopd) {
memcpy(ps->ipd_par+ps->num_env, ps->ipd_par+source, sizeof(ps->ipd_par[0]));
memcpy(ps->opd_par+ps->num_env, ps->opd_par+source, sizeof(ps->opd_par[0]));
}
}
if (ps->enable_iid){
for (b = 0; b < ps->nr_iid_par; b++) {
if (FFABS(ps->iid_par[ps->num_env][b]) > 7 + 8 * ps->iid_quant) {
av_log(avctx, AV_LOG_ERROR, "iid_par invalid\n");
goto err;
}
}
}
if (ps->enable_icc){
for (b = 0; b < ps->nr_iid_par; b++) {
if (ps->icc_par[ps->num_env][b] > 7U) {
av_log(avctx, AV_LOG_ERROR, "icc_par invalid\n");
goto err;
}
}
}
ps->num_env++;
ps->border_position[ps->num_env] = numQMFSlots - 1;
}
ps->is34bands_old = ps->is34bands;
if (!PS_BASELINE && (ps->enable_iid || ps->enable_icc))
ps->is34bands = (ps->enable_iid && ps->nr_iid_par == 34) ||
(ps->enable_icc && ps->nr_icc_par == 34);
//Baseline
if (!ps->enable_ipdopd) {
memset(ps->ipd_par, 0, sizeof(ps->ipd_par));
memset(ps->opd_par, 0, sizeof(ps->opd_par));
}
if (header)
ps->start = 1;
bits_consumed = get_bits_count(gb) - bit_count_start;
if (bits_consumed <= bits_left) {
skip_bits_long(gb_host, bits_consumed);
return bits_consumed;
}
av_log(avctx, AV_LOG_ERROR, "Expected to read %d PS bits actually read %d.\n", bits_left, bits_consumed);
err:
ps->start = 0;
skip_bits_long(gb_host, bits_left);
memset(ps->iid_par, 0, sizeof(ps->iid_par));
memset(ps->icc_par, 0, sizeof(ps->icc_par));
memset(ps->ipd_par, 0, sizeof(ps->ipd_par));
memset(ps->opd_par, 0, sizeof(ps->opd_par));
return bits_left;
}
/** Split one subband into 2 subsubbands with a symmetric real filter.
* The filter must have its non-center even coefficients equal to zero. */
static void hybrid2_re(float (*in)[2], float (*out)[32][2], const float filter[8], int len, int reverse)
{
int i, j;
for (i = 0; i < len; i++, in++) {
float re_in = filter[6] * in[6][0]; //real inphase
float re_op = 0.0f; //real out of phase
float im_in = filter[6] * in[6][1]; //imag inphase
float im_op = 0.0f; //imag out of phase
for (j = 0; j < 6; j += 2) {
re_op += filter[j+1] * (in[j+1][0] + in[12-j-1][0]);
im_op += filter[j+1] * (in[j+1][1] + in[12-j-1][1]);
}
out[ reverse][i][0] = re_in + re_op;
out[ reverse][i][1] = im_in + im_op;
out[!reverse][i][0] = re_in - re_op;
out[!reverse][i][1] = im_in - im_op;
}
}
/** Split one subband into 6 subsubbands with a complex filter */
static void hybrid6_cx(PSDSPContext *dsp, float (*in)[2], float (*out)[32][2], const float (*filter)[8][2], int len)
{
int i;
int N = 8;
LOCAL_ALIGNED_16(float, temp, [8], [2]);
for (i = 0; i < len; i++, in++) {
dsp->hybrid_analysis(temp, in, filter, 1, N);
out[0][i][0] = temp[6][0];
out[0][i][1] = temp[6][1];
out[1][i][0] = temp[7][0];
out[1][i][1] = temp[7][1];
out[2][i][0] = temp[0][0];
out[2][i][1] = temp[0][1];
out[3][i][0] = temp[1][0];
out[3][i][1] = temp[1][1];
out[4][i][0] = temp[2][0] + temp[5][0];
out[4][i][1] = temp[2][1] + temp[5][1];
out[5][i][0] = temp[3][0] + temp[4][0];
out[5][i][1] = temp[3][1] + temp[4][1];
}
}
static void hybrid4_8_12_cx(PSDSPContext *dsp, float (*in)[2], float (*out)[32][2], const float (*filter)[8][2], int N, int len)
{
int i;
for (i = 0; i < len; i++, in++) {
dsp->hybrid_analysis(out[0] + i, in, filter, 32, N);
}
}
static void hybrid_analysis(PSDSPContext *dsp, float out[91][32][2],
float in[5][44][2], float L[2][38][64],
int is34, int len)
{
int i, j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 38; j++) {
in[i][j+6][0] = L[0][j][i];
in[i][j+6][1] = L[1][j][i];
}
}
if (is34) {
hybrid4_8_12_cx(dsp, in[0], out, f34_0_12, 12, len);
hybrid4_8_12_cx(dsp, in[1], out+12, f34_1_8, 8, len);
hybrid4_8_12_cx(dsp, in[2], out+20, f34_2_4, 4, len);
hybrid4_8_12_cx(dsp, in[3], out+24, f34_2_4, 4, len);
hybrid4_8_12_cx(dsp, in[4], out+28, f34_2_4, 4, len);
dsp->hybrid_analysis_ileave(out + 27, L, 5, len);
} else {
hybrid6_cx(dsp, in[0], out, f20_0_8, len);
hybrid2_re(in[1], out+6, g1_Q2, len, 1);
hybrid2_re(in[2], out+8, g1_Q2, len, 0);
dsp->hybrid_analysis_ileave(out + 7, L, 3, len);
}
//update in_buf
for (i = 0; i < 5; i++) {
memcpy(in[i], in[i]+32, 6 * sizeof(in[i][0]));
}
}
static void hybrid_synthesis(PSDSPContext *dsp, float out[2][38][64],
float in[91][32][2], int is34, int len)
{
int i, n;
if (is34) {
for (n = 0; n < len; n++) {
memset(out[0][n], 0, 5*sizeof(out[0][n][0]));
memset(out[1][n], 0, 5*sizeof(out[1][n][0]));
for (i = 0; i < 12; i++) {
out[0][n][0] += in[ i][n][0];
out[1][n][0] += in[ i][n][1];
}
for (i = 0; i < 8; i++) {
out[0][n][1] += in[12+i][n][0];
out[1][n][1] += in[12+i][n][1];
}
for (i = 0; i < 4; i++) {
out[0][n][2] += in[20+i][n][0];
out[1][n][2] += in[20+i][n][1];
out[0][n][3] += in[24+i][n][0];
out[1][n][3] += in[24+i][n][1];
out[0][n][4] += in[28+i][n][0];
out[1][n][4] += in[28+i][n][1];
}
}
dsp->hybrid_synthesis_deint(out, in + 27, 5, len);
} else {
for (n = 0; n < len; n++) {
out[0][n][0] = in[0][n][0] + in[1][n][0] + in[2][n][0] +
in[3][n][0] + in[4][n][0] + in[5][n][0];
out[1][n][0] = in[0][n][1] + in[1][n][1] + in[2][n][1] +
in[3][n][1] + in[4][n][1] + in[5][n][1];
out[0][n][1] = in[6][n][0] + in[7][n][0];
out[1][n][1] = in[6][n][1] + in[7][n][1];
out[0][n][2] = in[8][n][0] + in[9][n][0];
out[1][n][2] = in[8][n][1] + in[9][n][1];
}
dsp->hybrid_synthesis_deint(out, in + 7, 3, len);
}
}
/// All-pass filter decay slope
#define DECAY_SLOPE 0.05f
/// Number of frequency bands that can be addressed by the parameter index, b(k)
static const int NR_PAR_BANDS[] = { 20, 34 };
/// Number of frequency bands that can be addressed by the sub subband index, k
static const int NR_BANDS[] = { 71, 91 };
/// Start frequency band for the all-pass filter decay slope
static const int DECAY_CUTOFF[] = { 10, 32 };
/// Number of all-pass filer bands
static const int NR_ALLPASS_BANDS[] = { 30, 50 };
/// First stereo band using the short one sample delay
static const int SHORT_DELAY_BAND[] = { 42, 62 };
/** Table 8.46 */
static void map_idx_10_to_20(int8_t *par_mapped, const int8_t *par, int full)
{
int b;
if (full)
b = 9;
else {
b = 4;
par_mapped[10] = 0;
}
for (; b >= 0; b--) {
par_mapped[2*b+1] = par_mapped[2*b] = par[b];
}
}
static void map_idx_34_to_20(int8_t *par_mapped, const int8_t *par, int full)
{
par_mapped[ 0] = (2*par[ 0] + par[ 1]) / 3;
par_mapped[ 1] = ( par[ 1] + 2*par[ 2]) / 3;
par_mapped[ 2] = (2*par[ 3] + par[ 4]) / 3;
par_mapped[ 3] = ( par[ 4] + 2*par[ 5]) / 3;
par_mapped[ 4] = ( par[ 6] + par[ 7]) / 2;
par_mapped[ 5] = ( par[ 8] + par[ 9]) / 2;
par_mapped[ 6] = par[10];
par_mapped[ 7] = par[11];
par_mapped[ 8] = ( par[12] + par[13]) / 2;
par_mapped[ 9] = ( par[14] + par[15]) / 2;
par_mapped[10] = par[16];
if (full) {
par_mapped[11] = par[17];
par_mapped[12] = par[18];
par_mapped[13] = par[19];
par_mapped[14] = ( par[20] + par[21]) / 2;
par_mapped[15] = ( par[22] + par[23]) / 2;
par_mapped[16] = ( par[24] + par[25]) / 2;
par_mapped[17] = ( par[26] + par[27]) / 2;
par_mapped[18] = ( par[28] + par[29] + par[30] + par[31]) / 4;
par_mapped[19] = ( par[32] + par[33]) / 2;
}
}
static void map_val_34_to_20(float par[PS_MAX_NR_IIDICC])
{
par[ 0] = (2*par[ 0] + par[ 1]) * 0.33333333f;
par[ 1] = ( par[ 1] + 2*par[ 2]) * 0.33333333f;
par[ 2] = (2*par[ 3] + par[ 4]) * 0.33333333f;
par[ 3] = ( par[ 4] + 2*par[ 5]) * 0.33333333f;
par[ 4] = ( par[ 6] + par[ 7]) * 0.5f;
par[ 5] = ( par[ 8] + par[ 9]) * 0.5f;
par[ 6] = par[10];
par[ 7] = par[11];
par[ 8] = ( par[12] + par[13]) * 0.5f;
par[ 9] = ( par[14] + par[15]) * 0.5f;
par[10] = par[16];
par[11] = par[17];
par[12] = par[18];
par[13] = par[19];
par[14] = ( par[20] + par[21]) * 0.5f;
par[15] = ( par[22] + par[23]) * 0.5f;
par[16] = ( par[24] + par[25]) * 0.5f;
par[17] = ( par[26] + par[27]) * 0.5f;
par[18] = ( par[28] + par[29] + par[30] + par[31]) * 0.25f;
par[19] = ( par[32] + par[33]) * 0.5f;
}
static void map_idx_10_to_34(int8_t *par_mapped, const int8_t *par, int full)
{
if (full) {
par_mapped[33] = par[9];
par_mapped[32] = par[9];
par_mapped[31] = par[9];
par_mapped[30] = par[9];
par_mapped[29] = par[9];
par_mapped[28] = par[9];
par_mapped[27] = par[8];
par_mapped[26] = par[8];
par_mapped[25] = par[8];
par_mapped[24] = par[8];
par_mapped[23] = par[7];
par_mapped[22] = par[7];
par_mapped[21] = par[7];
par_mapped[20] = par[7];
par_mapped[19] = par[6];
par_mapped[18] = par[6];
par_mapped[17] = par[5];
par_mapped[16] = par[5];
} else {
par_mapped[16] = 0;
}
par_mapped[15] = par[4];
par_mapped[14] = par[4];
par_mapped[13] = par[4];
par_mapped[12] = par[4];
par_mapped[11] = par[3];
par_mapped[10] = par[3];
par_mapped[ 9] = par[2];
par_mapped[ 8] = par[2];
par_mapped[ 7] = par[2];
par_mapped[ 6] = par[2];
par_mapped[ 5] = par[1];
par_mapped[ 4] = par[1];
par_mapped[ 3] = par[1];
par_mapped[ 2] = par[0];
par_mapped[ 1] = par[0];
par_mapped[ 0] = par[0];
}
static void map_idx_20_to_34(int8_t *par_mapped, const int8_t *par, int full)
{
if (full) {
par_mapped[33] = par[19];
par_mapped[32] = par[19];
par_mapped[31] = par[18];
par_mapped[30] = par[18];
par_mapped[29] = par[18];
par_mapped[28] = par[18];
par_mapped[27] = par[17];
par_mapped[26] = par[17];
par_mapped[25] = par[16];
par_mapped[24] = par[16];
par_mapped[23] = par[15];
par_mapped[22] = par[15];
par_mapped[21] = par[14];
par_mapped[20] = par[14];
par_mapped[19] = par[13];
par_mapped[18] = par[12];
par_mapped[17] = par[11];
}
par_mapped[16] = par[10];
par_mapped[15] = par[ 9];
par_mapped[14] = par[ 9];
par_mapped[13] = par[ 8];
par_mapped[12] = par[ 8];
par_mapped[11] = par[ 7];
par_mapped[10] = par[ 6];
par_mapped[ 9] = par[ 5];
par_mapped[ 8] = par[ 5];
par_mapped[ 7] = par[ 4];
par_mapped[ 6] = par[ 4];
par_mapped[ 5] = par[ 3];
par_mapped[ 4] = (par[ 2] + par[ 3]) / 2;
par_mapped[ 3] = par[ 2];
par_mapped[ 2] = par[ 1];
par_mapped[ 1] = (par[ 0] + par[ 1]) / 2;
par_mapped[ 0] = par[ 0];
}
static void map_val_20_to_34(float par[PS_MAX_NR_IIDICC])
{
par[33] = par[19];
par[32] = par[19];
par[31] = par[18];
par[30] = par[18];
par[29] = par[18];
par[28] = par[18];
par[27] = par[17];
par[26] = par[17];
par[25] = par[16];
par[24] = par[16];
par[23] = par[15];
par[22] = par[15];
par[21] = par[14];
par[20] = par[14];
par[19] = par[13];
par[18] = par[12];
par[17] = par[11];
par[16] = par[10];
par[15] = par[ 9];
par[14] = par[ 9];
par[13] = par[ 8];
par[12] = par[ 8];
par[11] = par[ 7];
par[10] = par[ 6];
par[ 9] = par[ 5];
par[ 8] = par[ 5];
par[ 7] = par[ 4];
par[ 6] = par[ 4];
par[ 5] = par[ 3];
par[ 4] = (par[ 2] + par[ 3]) * 0.5f;
par[ 3] = par[ 2];
par[ 2] = par[ 1];
par[ 1] = (par[ 0] + par[ 1]) * 0.5f;
}
static void decorrelation(PSContext *ps, float (*out)[32][2], const float (*s)[32][2], int is34)
{
LOCAL_ALIGNED_16(float, power, [34], [PS_QMF_TIME_SLOTS]);
LOCAL_ALIGNED_16(float, transient_gain, [34], [PS_QMF_TIME_SLOTS]);
float *peak_decay_nrg = ps->peak_decay_nrg;
float *power_smooth = ps->power_smooth;
float *peak_decay_diff_smooth = ps->peak_decay_diff_smooth;
float (*delay)[PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2] = ps->delay;
float (*ap_delay)[PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2] = ps->ap_delay;
const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20;
const float peak_decay_factor = 0.76592833836465f;
const float transient_impact = 1.5f;
const float a_smooth = 0.25f; ///< Smoothing coefficient
int i, k, m, n;
int n0 = 0, nL = 32;
memset(power, 0, 34 * sizeof(*power));
if (is34 != ps->is34bands_old) {
memset(ps->peak_decay_nrg, 0, sizeof(ps->peak_decay_nrg));
memset(ps->power_smooth, 0, sizeof(ps->power_smooth));
memset(ps->peak_decay_diff_smooth, 0, sizeof(ps->peak_decay_diff_smooth));
memset(ps->delay, 0, sizeof(ps->delay));
memset(ps->ap_delay, 0, sizeof(ps->ap_delay));
}
for (k = 0; k < NR_BANDS[is34]; k++) {
int i = k_to_i[k];
ps->dsp.add_squares(power[i], s[k], nL - n0);
}
//Transient detection
for (i = 0; i < NR_PAR_BANDS[is34]; i++) {
for (n = n0; n < nL; n++) {
float decayed_peak = peak_decay_factor * peak_decay_nrg[i];
float denom;
peak_decay_nrg[i] = FFMAX(decayed_peak, power[i][n]);
power_smooth[i] += a_smooth * (power[i][n] - power_smooth[i]);
peak_decay_diff_smooth[i] += a_smooth * (peak_decay_nrg[i] - power[i][n] - peak_decay_diff_smooth[i]);
denom = transient_impact * peak_decay_diff_smooth[i];
transient_gain[i][n] = (denom > power_smooth[i]) ?
power_smooth[i] / denom : 1.0f;
}
}
//Decorrelation and transient reduction
// PS_AP_LINKS - 1
// -----
// | | Q_fract_allpass[k][m]*z^-link_delay[m] - a[m]*g_decay_slope[k]
//H[k][z] = z^-2 * phi_fract[k] * | | ----------------------------------------------------------------
// | | 1 - a[m]*g_decay_slope[k]*Q_fract_allpass[k][m]*z^-link_delay[m]
// m = 0
//d[k][z] (out) = transient_gain_mapped[k][z] * H[k][z] * s[k][z]
for (k = 0; k < NR_ALLPASS_BANDS[is34]; k++) {
int b = k_to_i[k];
float g_decay_slope = 1.f - DECAY_SLOPE * (k - DECAY_CUTOFF[is34]);
g_decay_slope = av_clipf(g_decay_slope, 0.f, 1.f);
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
for (m = 0; m < PS_AP_LINKS; m++) {
memcpy(ap_delay[k][m], ap_delay[k][m]+numQMFSlots, 5*sizeof(ap_delay[k][m][0]));
}
ps->dsp.decorrelate(out[k], delay[k] + PS_MAX_DELAY - 2, ap_delay[k],
phi_fract[is34][k], Q_fract_allpass[is34][k],
transient_gain[b], g_decay_slope, nL - n0);
}
for (; k < SHORT_DELAY_BAND[is34]; k++) {
int i = k_to_i[k];
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
//H = delay 14
ps->dsp.mul_pair_single(out[k], delay[k] + PS_MAX_DELAY - 14,
transient_gain[i], nL - n0);
}
for (; k < NR_BANDS[is34]; k++) {
int i = k_to_i[k];
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
//H = delay 1
ps->dsp.mul_pair_single(out[k], delay[k] + PS_MAX_DELAY - 1,
transient_gain[i], nL - n0);
}
}
static void remap34(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC],
int8_t (*par)[PS_MAX_NR_IIDICC],
int num_par, int num_env, int full)
{
int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped;
int e;
if (num_par == 20 || num_par == 11) {
for (e = 0; e < num_env; e++) {
map_idx_20_to_34(par_mapped[e], par[e], full);
}
} else if (num_par == 10 || num_par == 5) {
for (e = 0; e < num_env; e++) {
map_idx_10_to_34(par_mapped[e], par[e], full);
}
} else {
*p_par_mapped = par;
}
}
static void remap20(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC],
int8_t (*par)[PS_MAX_NR_IIDICC],
int num_par, int num_env, int full)
{
int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped;
int e;
if (num_par == 34 || num_par == 17) {
for (e = 0; e < num_env; e++) {
map_idx_34_to_20(par_mapped[e], par[e], full);
}
} else if (num_par == 10 || num_par == 5) {
for (e = 0; e < num_env; e++) {
map_idx_10_to_20(par_mapped[e], par[e], full);
}
} else {
*p_par_mapped = par;
}
}
static void stereo_processing(PSContext *ps, float (*l)[32][2], float (*r)[32][2], int is34)
{
int e, b, k;
float (*H11)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H11;
float (*H12)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H12;
float (*H21)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H21;
float (*H22)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H22;
int8_t *opd_hist = ps->opd_hist;
int8_t *ipd_hist = ps->ipd_hist;
int8_t iid_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
int8_t icc_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
int8_t ipd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
int8_t opd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
int8_t (*iid_mapped)[PS_MAX_NR_IIDICC] = iid_mapped_buf;
int8_t (*icc_mapped)[PS_MAX_NR_IIDICC] = icc_mapped_buf;
int8_t (*ipd_mapped)[PS_MAX_NR_IIDICC] = ipd_mapped_buf;
int8_t (*opd_mapped)[PS_MAX_NR_IIDICC] = opd_mapped_buf;
const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20;
const float (*H_LUT)[8][4] = (PS_BASELINE || ps->icc_mode < 3) ? HA : HB;
//Remapping
if (ps->num_env_old) {
memcpy(H11[0][0], H11[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[0][0][0]));
memcpy(H11[1][0], H11[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[1][0][0]));
memcpy(H12[0][0], H12[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[0][0][0]));
memcpy(H12[1][0], H12[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[1][0][0]));
memcpy(H21[0][0], H21[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[0][0][0]));
memcpy(H21[1][0], H21[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[1][0][0]));
memcpy(H22[0][0], H22[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[0][0][0]));
memcpy(H22[1][0], H22[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[1][0][0]));
}
if (is34) {
remap34(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1);
remap34(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1);
if (ps->enable_ipdopd) {
remap34(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0);
remap34(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0);
}
if (!ps->is34bands_old) {
map_val_20_to_34(H11[0][0]);
map_val_20_to_34(H11[1][0]);
map_val_20_to_34(H12[0][0]);
map_val_20_to_34(H12[1][0]);
map_val_20_to_34(H21[0][0]);
map_val_20_to_34(H21[1][0]);
map_val_20_to_34(H22[0][0]);
map_val_20_to_34(H22[1][0]);
ipdopd_reset(ipd_hist, opd_hist);
}
} else {
remap20(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1);
remap20(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1);
if (ps->enable_ipdopd) {
remap20(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0);
remap20(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0);
}
if (ps->is34bands_old) {
map_val_34_to_20(H11[0][0]);
map_val_34_to_20(H11[1][0]);
map_val_34_to_20(H12[0][0]);
map_val_34_to_20(H12[1][0]);
map_val_34_to_20(H21[0][0]);
map_val_34_to_20(H21[1][0]);
map_val_34_to_20(H22[0][0]);
map_val_34_to_20(H22[1][0]);
ipdopd_reset(ipd_hist, opd_hist);
}
}
//Mixing
for (e = 0; e < ps->num_env; e++) {
for (b = 0; b < NR_PAR_BANDS[is34]; b++) {
float h11, h12, h21, h22;
h11 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][0];
h12 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][1];
h21 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][2];
h22 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][3];
if (!PS_BASELINE && ps->enable_ipdopd && 2*b <= NR_PAR_BANDS[is34]) {
//The spec say says to only run this smoother when enable_ipdopd
//is set but the reference decoder appears to run it constantly
float h11i, h12i, h21i, h22i;
float ipd_adj_re, ipd_adj_im;
int opd_idx = opd_hist[b] * 8 + opd_mapped[e][b];
int ipd_idx = ipd_hist[b] * 8 + ipd_mapped[e][b];
float opd_re = pd_re_smooth[opd_idx];
float opd_im = pd_im_smooth[opd_idx];
float ipd_re = pd_re_smooth[ipd_idx];
float ipd_im = pd_im_smooth[ipd_idx];
opd_hist[b] = opd_idx & 0x3F;
ipd_hist[b] = ipd_idx & 0x3F;
ipd_adj_re = opd_re*ipd_re + opd_im*ipd_im;
ipd_adj_im = opd_im*ipd_re - opd_re*ipd_im;
h11i = h11 * opd_im;
h11 = h11 * opd_re;
h12i = h12 * ipd_adj_im;
h12 = h12 * ipd_adj_re;
h21i = h21 * opd_im;
h21 = h21 * opd_re;
h22i = h22 * ipd_adj_im;
h22 = h22 * ipd_adj_re;
H11[1][e+1][b] = h11i;
H12[1][e+1][b] = h12i;
H21[1][e+1][b] = h21i;
H22[1][e+1][b] = h22i;
}
H11[0][e+1][b] = h11;
H12[0][e+1][b] = h12;
H21[0][e+1][b] = h21;
H22[0][e+1][b] = h22;
}
for (k = 0; k < NR_BANDS[is34]; k++) {
float h[2][4];
float h_step[2][4];
int start = ps->border_position[e];
int stop = ps->border_position[e+1];
float width = 1.f / (stop - start);
b = k_to_i[k];
h[0][0] = H11[0][e][b];
h[0][1] = H12[0][e][b];
h[0][2] = H21[0][e][b];
h[0][3] = H22[0][e][b];
if (!PS_BASELINE && ps->enable_ipdopd) {
//Is this necessary? ps_04_new seems unchanged
if ((is34 && k <= 13 && k >= 9) || (!is34 && k <= 1)) {
h[1][0] = -H11[1][e][b];
h[1][1] = -H12[1][e][b];
h[1][2] = -H21[1][e][b];
h[1][3] = -H22[1][e][b];
} else {
h[1][0] = H11[1][e][b];
h[1][1] = H12[1][e][b];
h[1][2] = H21[1][e][b];
h[1][3] = H22[1][e][b];
}
}
//Interpolation
h_step[0][0] = (H11[0][e+1][b] - h[0][0]) * width;
h_step[0][1] = (H12[0][e+1][b] - h[0][1]) * width;
h_step[0][2] = (H21[0][e+1][b] - h[0][2]) * width;
h_step[0][3] = (H22[0][e+1][b] - h[0][3]) * width;
if (!PS_BASELINE && ps->enable_ipdopd) {
h_step[1][0] = (H11[1][e+1][b] - h[1][0]) * width;
h_step[1][1] = (H12[1][e+1][b] - h[1][1]) * width;
h_step[1][2] = (H21[1][e+1][b] - h[1][2]) * width;
h_step[1][3] = (H22[1][e+1][b] - h[1][3]) * width;
}
ps->dsp.stereo_interpolate[!PS_BASELINE && ps->enable_ipdopd](
l[k] + start + 1, r[k] + start + 1,
h, h_step, stop - start);
}
}
}
int ff_ps_apply(AVCodecContext *avctx, PSContext *ps, float L[2][38][64], float R[2][38][64], int top)
{
LOCAL_ALIGNED_16(float, Lbuf, [91], [32][2]);
LOCAL_ALIGNED_16(float, Rbuf, [91], [32][2]);
const int len = 32;
int is34 = ps->is34bands;
top += NR_BANDS[is34] - 64;
memset(ps->delay+top, 0, (NR_BANDS[is34] - top)*sizeof(ps->delay[0]));
if (top < NR_ALLPASS_BANDS[is34])
memset(ps->ap_delay + top, 0, (NR_ALLPASS_BANDS[is34] - top)*sizeof(ps->ap_delay[0]));
hybrid_analysis(&ps->dsp, Lbuf, ps->in_buf, L, is34, len);
decorrelation(ps, Rbuf, Lbuf, is34);
stereo_processing(ps, Lbuf, Rbuf, is34);
hybrid_synthesis(&ps->dsp, L, Lbuf, is34, len);
hybrid_synthesis(&ps->dsp, R, Rbuf, is34, len);
return 0;
}
#define PS_INIT_VLC_STATIC(num, size) \
INIT_VLC_STATIC(&vlc_ps[num], 9, ps_tmp[num].table_size / ps_tmp[num].elem_size, \
ps_tmp[num].ps_bits, 1, 1, \
ps_tmp[num].ps_codes, ps_tmp[num].elem_size, ps_tmp[num].elem_size, \
size);
#define PS_VLC_ROW(name) \
{ name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) }
av_cold void ff_ps_init(void) {
// Syntax initialization
static const struct {
const void *ps_codes, *ps_bits;
const unsigned int table_size, elem_size;
} ps_tmp[] = {
PS_VLC_ROW(huff_iid_df1),
PS_VLC_ROW(huff_iid_dt1),
PS_VLC_ROW(huff_iid_df0),
PS_VLC_ROW(huff_iid_dt0),
PS_VLC_ROW(huff_icc_df),
PS_VLC_ROW(huff_icc_dt),
PS_VLC_ROW(huff_ipd_df),
PS_VLC_ROW(huff_ipd_dt),
PS_VLC_ROW(huff_opd_df),
PS_VLC_ROW(huff_opd_dt),
};
PS_INIT_VLC_STATIC(0, 1544);
PS_INIT_VLC_STATIC(1, 832);
PS_INIT_VLC_STATIC(2, 1024);
PS_INIT_VLC_STATIC(3, 1036);
PS_INIT_VLC_STATIC(4, 544);
PS_INIT_VLC_STATIC(5, 544);
PS_INIT_VLC_STATIC(6, 512);
PS_INIT_VLC_STATIC(7, 512);
PS_INIT_VLC_STATIC(8, 512);
PS_INIT_VLC_STATIC(9, 512);
ps_tableinit();
}
av_cold void ff_ps_ctx_init(PSContext *ps)
{
ff_psdsp_init(&ps->dsp);
}

View File

@@ -0,0 +1,84 @@
/*
* MPEG-4 Parametric Stereo definitions and declarations
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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 AVCODEC_PS_H
#define AVCODEC_PS_H
#include <stdint.h>
#include "aacpsdsp.h"
#include "avcodec.h"
#include "get_bits.h"
#define PS_MAX_NUM_ENV 5
#define PS_MAX_NR_IIDICC 34
#define PS_MAX_NR_IPDOPD 17
#define PS_MAX_SSB 91
#define PS_MAX_AP_BANDS 50
#define PS_QMF_TIME_SLOTS 32
#define PS_MAX_DELAY 14
#define PS_AP_LINKS 3
#define PS_MAX_AP_DELAY 5
typedef struct PSContext {
int start;
int enable_iid;
int iid_quant;
int nr_iid_par;
int nr_ipdopd_par;
int enable_icc;
int icc_mode;
int nr_icc_par;
int enable_ext;
int frame_class;
int num_env_old;
int num_env;
int enable_ipdopd;
int border_position[PS_MAX_NUM_ENV+1];
int8_t iid_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-channel Intensity Difference Parameters
int8_t icc_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-Channel Coherence Parameters
/* ipd/opd is iid/icc sized so that the same functions can handle both */
int8_t ipd_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-channel Phase Difference Parameters
int8_t opd_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Overall Phase Difference Parameters
int is34bands;
int is34bands_old;
DECLARE_ALIGNED(16, float, in_buf)[5][44][2];
DECLARE_ALIGNED(16, float, delay)[PS_MAX_SSB][PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2];
DECLARE_ALIGNED(16, float, ap_delay)[PS_MAX_AP_BANDS][PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2];
DECLARE_ALIGNED(16, float, peak_decay_nrg)[34];
DECLARE_ALIGNED(16, float, power_smooth)[34];
DECLARE_ALIGNED(16, float, peak_decay_diff_smooth)[34];
DECLARE_ALIGNED(16, float, H11)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC];
DECLARE_ALIGNED(16, float, H12)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC];
DECLARE_ALIGNED(16, float, H21)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC];
DECLARE_ALIGNED(16, float, H22)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC];
int8_t opd_hist[PS_MAX_NR_IIDICC];
int8_t ipd_hist[PS_MAX_NR_IIDICC];
PSDSPContext dsp;
} PSContext;
void ff_ps_init(void);
void ff_ps_ctx_init(PSContext *ps);
int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, int bits_left);
int ff_ps_apply(AVCodecContext *avctx, PSContext *ps, float L[2][38][64], float R[2][38][64], int top);
#endif /* AVCODEC_PS_H */

View File

@@ -0,0 +1,93 @@
/*
* Generate a header file for hardcoded Parametric Stereo tables
*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
#include <stdlib.h>
#define CONFIG_HARDCODED_TABLES 0
#include "aacps_tablegen.h"
#include "tableprint.h"
void write_float_3d_array (const void *p, int b, int c, int d)
{
int i;
const float *f = p;
for (i = 0; i < b; i++) {
printf("{\n");
write_float_2d_array(f, c, d);
printf("},\n");
f += c * d;
}
}
void write_float_4d_array (const void *p, int a, int b, int c, int d)
{
int i;
const float *f = p;
for (i = 0; i < a; i++) {
printf("{\n");
write_float_3d_array(f, b, c, d);
printf("},\n");
f += b * c * d;
}
}
int main(void)
{
ps_tableinit();
write_fileheader();
printf("static const float pd_re_smooth[8*8*8] = {\n");
write_float_array(pd_re_smooth, 8*8*8);
printf("};\n");
printf("static const float pd_im_smooth[8*8*8] = {\n");
write_float_array(pd_im_smooth, 8*8*8);
printf("};\n");
printf("static const float HA[46][8][4] = {\n");
write_float_3d_array(HA, 46, 8, 4);
printf("};\n");
printf("static const float HB[46][8][4] = {\n");
write_float_3d_array(HB, 46, 8, 4);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, f20_0_8)[8][8][2] = {\n");
write_float_3d_array(f20_0_8, 8, 8, 2);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, f34_0_12)[12][8][2] = {\n");
write_float_3d_array(f34_0_12, 12, 8, 2);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, f34_1_8)[8][8][2] = {\n");
write_float_3d_array(f34_1_8, 8, 8, 2);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, f34_2_4)[4][8][2] = {\n");
write_float_3d_array(f34_2_4, 4, 8, 2);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, Q_fract_allpass)[2][50][3][2] = {\n");
write_float_4d_array(Q_fract_allpass, 2, 50, 3, 2);
printf("};\n");
printf("static const DECLARE_ALIGNED(16, float, phi_fract)[2][50][2] = {\n");
write_float_3d_array(phi_fract, 2, 50, 2);
printf("};\n");
return 0;
}

View File

@@ -0,0 +1,215 @@
/*
* Header file for hardcoded Parametric Stereo tables
*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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 AACPS_TABLEGEN_H
#define AACPS_TABLEGEN_H
#include <math.h>
#include <stdint.h>
#if CONFIG_HARDCODED_TABLES
#define ps_tableinit()
#include "libavcodec/aacps_tables.h"
#else
#include "libavutil/common.h"
#include "libavutil/libm.h"
#include "libavutil/mathematics.h"
#include "libavutil/mem.h"
#define NR_ALLPASS_BANDS20 30
#define NR_ALLPASS_BANDS34 50
#define PS_AP_LINKS 3
static float pd_re_smooth[8*8*8];
static float pd_im_smooth[8*8*8];
static float HA[46][8][4];
static float HB[46][8][4];
static DECLARE_ALIGNED(16, float, f20_0_8) [ 8][8][2];
static DECLARE_ALIGNED(16, float, f34_0_12)[12][8][2];
static DECLARE_ALIGNED(16, float, f34_1_8) [ 8][8][2];
static DECLARE_ALIGNED(16, float, f34_2_4) [ 4][8][2];
static DECLARE_ALIGNED(16, float, Q_fract_allpass)[2][50][3][2];
static DECLARE_ALIGNED(16, float, phi_fract)[2][50][2];
static const float g0_Q8[] = {
0.00746082949812f, 0.02270420949825f, 0.04546865930473f, 0.07266113929591f,
0.09885108575264f, 0.11793710567217f, 0.125f
};
static const float g0_Q12[] = {
0.04081179924692f, 0.03812810994926f, 0.05144908135699f, 0.06399831151592f,
0.07428313801106f, 0.08100347892914f, 0.08333333333333f
};
static const float g1_Q8[] = {
0.01565675600122f, 0.03752716391991f, 0.05417891378782f, 0.08417044116767f,
0.10307344158036f, 0.12222452249753f, 0.125f
};
static const float g2_Q4[] = {
-0.05908211155639f, -0.04871498374946f, 0.0f, 0.07778723915851f,
0.16486303567403f, 0.23279856662996f, 0.25f
};
static void make_filters_from_proto(float (*filter)[8][2], const float *proto, int bands)
{
int q, n;
for (q = 0; q < bands; q++) {
for (n = 0; n < 7; n++) {
double theta = 2 * M_PI * (q + 0.5) * (n - 6) / bands;
filter[q][n][0] = proto[n] * cos(theta);
filter[q][n][1] = proto[n] * -sin(theta);
}
}
}
static void ps_tableinit(void)
{
static const float ipdopd_sin[] = { 0, M_SQRT1_2, 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2 };
static const float ipdopd_cos[] = { 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2, 0, M_SQRT1_2 };
int pd0, pd1, pd2;
static const float iid_par_dequant[] = {
//iid_par_dequant_default
0.05623413251903, 0.12589254117942, 0.19952623149689, 0.31622776601684,
0.44668359215096, 0.63095734448019, 0.79432823472428, 1,
1.25892541179417, 1.58489319246111, 2.23872113856834, 3.16227766016838,
5.01187233627272, 7.94328234724282, 17.7827941003892,
//iid_par_dequant_fine
0.00316227766017, 0.00562341325190, 0.01, 0.01778279410039,
0.03162277660168, 0.05623413251903, 0.07943282347243, 0.11220184543020,
0.15848931924611, 0.22387211385683, 0.31622776601684, 0.39810717055350,
0.50118723362727, 0.63095734448019, 0.79432823472428, 1,
1.25892541179417, 1.58489319246111, 1.99526231496888, 2.51188643150958,
3.16227766016838, 4.46683592150963, 6.30957344480193, 8.91250938133745,
12.5892541179417, 17.7827941003892, 31.6227766016838, 56.2341325190349,
100, 177.827941003892, 316.227766016837,
};
static const float icc_invq[] = {
1, 0.937, 0.84118, 0.60092, 0.36764, 0, -0.589, -1
};
static const float acos_icc_invq[] = {
0, 0.35685527, 0.57133466, 0.92614472, 1.1943263, M_PI/2, 2.2006171, M_PI
};
int iid, icc;
int k, m;
static const int8_t f_center_20[] = {
-3, -1, 1, 3, 5, 7, 10, 14, 18, 22,
};
static const int8_t f_center_34[] = {
2, 6, 10, 14, 18, 22, 26, 30,
34,-10, -6, -2, 51, 57, 15, 21,
27, 33, 39, 45, 54, 66, 78, 42,
102, 66, 78, 90,102,114,126, 90,
};
static const float fractional_delay_links[] = { 0.43f, 0.75f, 0.347f };
const float fractional_delay_gain = 0.39f;
for (pd0 = 0; pd0 < 8; pd0++) {
float pd0_re = ipdopd_cos[pd0];
float pd0_im = ipdopd_sin[pd0];
for (pd1 = 0; pd1 < 8; pd1++) {
float pd1_re = ipdopd_cos[pd1];
float pd1_im = ipdopd_sin[pd1];
for (pd2 = 0; pd2 < 8; pd2++) {
float pd2_re = ipdopd_cos[pd2];
float pd2_im = ipdopd_sin[pd2];
float re_smooth = 0.25f * pd0_re + 0.5f * pd1_re + pd2_re;
float im_smooth = 0.25f * pd0_im + 0.5f * pd1_im + pd2_im;
float pd_mag = 1 / sqrt(im_smooth * im_smooth + re_smooth * re_smooth);
pd_re_smooth[pd0*64+pd1*8+pd2] = re_smooth * pd_mag;
pd_im_smooth[pd0*64+pd1*8+pd2] = im_smooth * pd_mag;
}
}
}
for (iid = 0; iid < 46; iid++) {
float c = iid_par_dequant[iid]; ///< Linear Inter-channel Intensity Difference
float c1 = (float)M_SQRT2 / sqrtf(1.0f + c*c);
float c2 = c * c1;
for (icc = 0; icc < 8; icc++) {
/*if (PS_BASELINE || ps->icc_mode < 3)*/ {
float alpha = 0.5f * acos_icc_invq[icc];
float beta = alpha * (c1 - c2) * (float)M_SQRT1_2;
HA[iid][icc][0] = c2 * cosf(beta + alpha);
HA[iid][icc][1] = c1 * cosf(beta - alpha);
HA[iid][icc][2] = c2 * sinf(beta + alpha);
HA[iid][icc][3] = c1 * sinf(beta - alpha);
} /* else */ {
float alpha, gamma, mu, rho;
float alpha_c, alpha_s, gamma_c, gamma_s;
rho = FFMAX(icc_invq[icc], 0.05f);
alpha = 0.5f * atan2f(2.0f * c * rho, c*c - 1.0f);
mu = c + 1.0f / c;
mu = sqrtf(1 + (4 * rho * rho - 4)/(mu * mu));
gamma = atanf(sqrtf((1.0f - mu)/(1.0f + mu)));
if (alpha < 0) alpha += M_PI/2;
alpha_c = cosf(alpha);
alpha_s = sinf(alpha);
gamma_c = cosf(gamma);
gamma_s = sinf(gamma);
HB[iid][icc][0] = M_SQRT2 * alpha_c * gamma_c;
HB[iid][icc][1] = M_SQRT2 * alpha_s * gamma_c;
HB[iid][icc][2] = -M_SQRT2 * alpha_s * gamma_s;
HB[iid][icc][3] = M_SQRT2 * alpha_c * gamma_s;
}
}
}
for (k = 0; k < NR_ALLPASS_BANDS20; k++) {
double f_center, theta;
if (k < FF_ARRAY_ELEMS(f_center_20))
f_center = f_center_20[k] * 0.125;
else
f_center = k - 6.5f;
for (m = 0; m < PS_AP_LINKS; m++) {
theta = -M_PI * fractional_delay_links[m] * f_center;
Q_fract_allpass[0][k][m][0] = cos(theta);
Q_fract_allpass[0][k][m][1] = sin(theta);
}
theta = -M_PI*fractional_delay_gain*f_center;
phi_fract[0][k][0] = cos(theta);
phi_fract[0][k][1] = sin(theta);
}
for (k = 0; k < NR_ALLPASS_BANDS34; k++) {
double f_center, theta;
if (k < FF_ARRAY_ELEMS(f_center_34))
f_center = f_center_34[k] / 24.0;
else
f_center = k - 26.5f;
for (m = 0; m < PS_AP_LINKS; m++) {
theta = -M_PI * fractional_delay_links[m] * f_center;
Q_fract_allpass[1][k][m][0] = cos(theta);
Q_fract_allpass[1][k][m][1] = sin(theta);
}
theta = -M_PI*fractional_delay_gain*f_center;
phi_fract[1][k][0] = cos(theta);
phi_fract[1][k][1] = sin(theta);
}
make_filters_from_proto(f20_0_8, g0_Q8, 8);
make_filters_from_proto(f34_0_12, g0_Q12, 12);
make_filters_from_proto(f34_1_8, g1_Q8, 8);
make_filters_from_proto(f34_2_4, g2_Q4, 4);
}
#endif /* CONFIG_HARDCODED_TABLES */
#endif /* AACPS_TABLEGEN_H */

View File

@@ -0,0 +1,163 @@
/*
* MPEG-4 Parametric Stereo data tables
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
static const uint8_t huff_iid_df1_bits[] = {
18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 17, 17, 16, 16, 15, 14, 14,
13, 12, 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7,
8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, 17, 17, 18, 17, 18, 18,
18, 18, 18, 18, 18, 18, 18,
};
static const uint32_t huff_iid_df1_codes[] = {
0x01FEB4, 0x01FEB5, 0x01FD76, 0x01FD77, 0x01FD74, 0x01FD75, 0x01FE8A,
0x01FE8B, 0x01FE88, 0x00FE80, 0x01FEB6, 0x00FE82, 0x00FEB8, 0x007F42,
0x007FAE, 0x003FAF, 0x001FD1, 0x001FE9, 0x000FE9, 0x0007EA, 0x0007FB,
0x0003FB, 0x0001FB, 0x0001FF, 0x00007C, 0x00003C, 0x00001C, 0x00000C,
0x000000, 0x000001, 0x000001, 0x000002, 0x000001, 0x00000D, 0x00001D,
0x00003D, 0x00007D, 0x0000FC, 0x0001FC, 0x0003FC, 0x0003F4, 0x0007EB,
0x000FEA, 0x001FEA, 0x001FD6, 0x003FD0, 0x007FAF, 0x007F43, 0x00FEB9,
0x00FE83, 0x01FEB7, 0x00FE81, 0x01FE89, 0x01FE8E, 0x01FE8F, 0x01FE8C,
0x01FE8D, 0x01FEB2, 0x01FEB3, 0x01FEB0, 0x01FEB1,
};
static const uint8_t huff_iid_dt1_bits[] = {
16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 13,
13, 13, 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, 1, 2, 5, 6, 7, 8,
9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16,
};
static const uint16_t huff_iid_dt1_codes[] = {
0x004ED4, 0x004ED5, 0x004ECE, 0x004ECF, 0x004ECC, 0x004ED6, 0x004ED8,
0x004F46, 0x004F60, 0x002718, 0x002719, 0x002764, 0x002765, 0x00276D,
0x0027B1, 0x0013B7, 0x0013D6, 0x0009C7, 0x0009E9, 0x0009ED, 0x0004EE,
0x0004F7, 0x000278, 0x000139, 0x00009A, 0x00009F, 0x000020, 0x000011,
0x00000A, 0x000003, 0x000001, 0x000000, 0x00000B, 0x000012, 0x000021,
0x00004C, 0x00009B, 0x00013A, 0x000279, 0x000270, 0x0004EF, 0x0004E2,
0x0009EA, 0x0009D8, 0x0013D7, 0x0013D0, 0x0027B2, 0x0027A2, 0x00271A,
0x00271B, 0x004F66, 0x004F67, 0x004F61, 0x004F47, 0x004ED9, 0x004ED7,
0x004ECD, 0x004ED2, 0x004ED3, 0x004ED0, 0x004ED1,
};
static const uint8_t huff_iid_df0_bits[] = {
17, 17, 17, 17, 16, 15, 13, 10, 9, 7, 6, 5, 4, 3, 1, 3, 4, 5,
6, 6, 8, 11, 13, 14, 14, 15, 17, 18, 18,
};
static const uint32_t huff_iid_df0_codes[] = {
0x01FFFB, 0x01FFFC, 0x01FFFD, 0x01FFFA, 0x00FFFC, 0x007FFC, 0x001FFD,
0x0003FE, 0x0001FE, 0x00007E, 0x00003C, 0x00001D, 0x00000D, 0x000005,
0x000000, 0x000004, 0x00000C, 0x00001C, 0x00003D, 0x00003E, 0x0000FE,
0x0007FE, 0x001FFC, 0x003FFC, 0x003FFD, 0x007FFD, 0x01FFFE, 0x03FFFE,
0x03FFFF,
};
static const uint8_t huff_iid_dt0_bits[] = {
19, 19, 19, 20, 20, 20, 17, 15, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7,
9, 11, 13, 14, 17, 19, 20, 20, 20, 20, 20,
};
static const uint32_t huff_iid_dt0_codes[] = {
0x07FFF9, 0x07FFFA, 0x07FFFB, 0x0FFFF8, 0x0FFFF9, 0x0FFFFA, 0x01FFFD,
0x007FFE, 0x000FFE, 0x0003FE, 0x0000FE, 0x00003E, 0x00000E, 0x000002,
0x000000, 0x000006, 0x00001E, 0x00007E, 0x0001FE, 0x0007FE, 0x001FFE,
0x003FFE, 0x01FFFC, 0x07FFF8, 0x0FFFFB, 0x0FFFFC, 0x0FFFFD, 0x0FFFFE,
0x0FFFFF,
};
static const uint8_t huff_icc_df_bits[] = {
14, 14, 12, 10, 7, 5, 3, 1, 2, 4, 6, 8, 9, 11, 13,
};
static const uint16_t huff_icc_df_codes[] = {
0x3FFF, 0x3FFE, 0x0FFE, 0x03FE, 0x007E, 0x001E, 0x0006, 0x0000,
0x0002, 0x000E, 0x003E, 0x00FE, 0x01FE, 0x07FE, 0x1FFE,
};
static const uint8_t huff_icc_dt_bits[] = {
14, 13, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14,
};
static const uint16_t huff_icc_dt_codes[] = {
0x3FFE, 0x1FFE, 0x07FE, 0x01FE, 0x007E, 0x001E, 0x0006, 0x0000,
0x0002, 0x000E, 0x003E, 0x00FE, 0x03FE, 0x0FFE, 0x3FFF,
};
static const uint8_t huff_ipd_df_bits[] = {
1, 3, 4, 4, 4, 4, 4, 4,
};
static const uint8_t huff_ipd_df_codes[] = {
0x01, 0x00, 0x06, 0x04, 0x02, 0x03, 0x05, 0x07,
};
static const uint8_t huff_ipd_dt_bits[] = {
1, 3, 4, 5, 5, 4, 4, 3,
};
static const uint8_t huff_ipd_dt_codes[] = {
0x01, 0x02, 0x02, 0x03, 0x02, 0x00, 0x03, 0x03,
};
static const uint8_t huff_opd_df_bits[] = {
1, 3, 4, 4, 5, 5, 4, 3,
};
static const uint8_t huff_opd_df_codes[] = {
0x01, 0x01, 0x06, 0x04, 0x0F, 0x0E, 0x05, 0x00,
};
static const uint8_t huff_opd_dt_bits[] = {
1, 3, 4, 5, 5, 4, 4, 3,
};
static const uint8_t huff_opd_dt_codes[] = {
0x01, 0x02, 0x01, 0x07, 0x06, 0x00, 0x02, 0x03,
};
static const int8_t huff_offset[] = {
30, 30,
14, 14,
7, 7,
0, 0,
0, 0,
};
///Table 8.48
static const int8_t k_to_i_20[] = {
1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15,
15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19
};
///Table 8.49
static const int8_t k_to_i_34[] = {
0, 1, 2, 3, 4, 5, 6, 6, 7, 2, 1, 0, 10, 10, 4, 5, 6, 7, 8,
9, 10, 11, 12, 9, 14, 11, 12, 13, 14, 15, 16, 13, 16, 17, 18, 19, 20, 21,
22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29,
30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33
};
static const float g1_Q2[] = {
0.0f, 0.01899487526049f, 0.0f, -0.07293139167538f,
0.0f, 0.30596630545168f, 0.5f
};

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
#include "config.h"
#include "libavutil/attributes.h"
#include "aacpsdsp.h"
static void ps_add_squares_c(float *dst, const float (*src)[2], int n)
{
int i;
for (i = 0; i < n; i++)
dst[i] += src[i][0] * src[i][0] + src[i][1] * src[i][1];
}
static void ps_mul_pair_single_c(float (*dst)[2], float (*src0)[2], float *src1,
int n)
{
int i;
for (i = 0; i < n; i++) {
dst[i][0] = src0[i][0] * src1[i];
dst[i][1] = src0[i][1] * src1[i];
}
}
static void ps_hybrid_analysis_c(float (*out)[2], float (*in)[2],
const float (*filter)[8][2],
int stride, int n)
{
int i, j;
for (i = 0; i < n; i++) {
float sum_re = filter[i][6][0] * in[6][0];
float sum_im = filter[i][6][0] * in[6][1];
for (j = 0; j < 6; j++) {
float in0_re = in[j][0];
float in0_im = in[j][1];
float in1_re = in[12-j][0];
float in1_im = in[12-j][1];
sum_re += filter[i][j][0] * (in0_re + in1_re) -
filter[i][j][1] * (in0_im - in1_im);
sum_im += filter[i][j][0] * (in0_im + in1_im) +
filter[i][j][1] * (in0_re - in1_re);
}
out[i * stride][0] = sum_re;
out[i * stride][1] = sum_im;
}
}
static void ps_hybrid_analysis_ileave_c(float (*out)[32][2], float L[2][38][64],
int i, int len)
{
int j;
for (; i < 64; i++) {
for (j = 0; j < len; j++) {
out[i][j][0] = L[0][j][i];
out[i][j][1] = L[1][j][i];
}
}
}
static void ps_hybrid_synthesis_deint_c(float out[2][38][64],
float (*in)[32][2],
int i, int len)
{
int n;
for (; i < 64; i++) {
for (n = 0; n < len; n++) {
out[0][n][i] = in[i][n][0];
out[1][n][i] = in[i][n][1];
}
}
}
static void ps_decorrelate_c(float (*out)[2], float (*delay)[2],
float (*ap_delay)[PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2],
const float phi_fract[2], float (*Q_fract)[2],
const float *transient_gain,
float g_decay_slope,
int len)
{
static const float a[] = { 0.65143905753106f,
0.56471812200776f,
0.48954165955695f };
float ag[PS_AP_LINKS];
int m, n;
for (m = 0; m < PS_AP_LINKS; m++)
ag[m] = a[m] * g_decay_slope;
for (n = 0; n < len; n++) {
float in_re = delay[n][0] * phi_fract[0] - delay[n][1] * phi_fract[1];
float in_im = delay[n][0] * phi_fract[1] + delay[n][1] * phi_fract[0];
for (m = 0; m < PS_AP_LINKS; m++) {
float a_re = ag[m] * in_re;
float a_im = ag[m] * in_im;
float link_delay_re = ap_delay[m][n+2-m][0];
float link_delay_im = ap_delay[m][n+2-m][1];
float fractional_delay_re = Q_fract[m][0];
float fractional_delay_im = Q_fract[m][1];
float apd_re = in_re;
float apd_im = in_im;
in_re = link_delay_re * fractional_delay_re -
link_delay_im * fractional_delay_im - a_re;
in_im = link_delay_re * fractional_delay_im +
link_delay_im * fractional_delay_re - a_im;
ap_delay[m][n+5][0] = apd_re + ag[m] * in_re;
ap_delay[m][n+5][1] = apd_im + ag[m] * in_im;
}
out[n][0] = transient_gain[n] * in_re;
out[n][1] = transient_gain[n] * in_im;
}
}
static void ps_stereo_interpolate_c(float (*l)[2], float (*r)[2],
float h[2][4], float h_step[2][4],
int len)
{
float h0 = h[0][0];
float h1 = h[0][1];
float h2 = h[0][2];
float h3 = h[0][3];
float hs0 = h_step[0][0];
float hs1 = h_step[0][1];
float hs2 = h_step[0][2];
float hs3 = h_step[0][3];
int n;
for (n = 0; n < len; n++) {
//l is s, r is d
float l_re = l[n][0];
float l_im = l[n][1];
float r_re = r[n][0];
float r_im = r[n][1];
h0 += hs0;
h1 += hs1;
h2 += hs2;
h3 += hs3;
l[n][0] = h0 * l_re + h2 * r_re;
l[n][1] = h0 * l_im + h2 * r_im;
r[n][0] = h1 * l_re + h3 * r_re;
r[n][1] = h1 * l_im + h3 * r_im;
}
}
static void ps_stereo_interpolate_ipdopd_c(float (*l)[2], float (*r)[2],
float h[2][4], float h_step[2][4],
int len)
{
float h00 = h[0][0], h10 = h[1][0];
float h01 = h[0][1], h11 = h[1][1];
float h02 = h[0][2], h12 = h[1][2];
float h03 = h[0][3], h13 = h[1][3];
float hs00 = h_step[0][0], hs10 = h_step[1][0];
float hs01 = h_step[0][1], hs11 = h_step[1][1];
float hs02 = h_step[0][2], hs12 = h_step[1][2];
float hs03 = h_step[0][3], hs13 = h_step[1][3];
int n;
for (n = 0; n < len; n++) {
//l is s, r is d
float l_re = l[n][0];
float l_im = l[n][1];
float r_re = r[n][0];
float r_im = r[n][1];
h00 += hs00;
h01 += hs01;
h02 += hs02;
h03 += hs03;
h10 += hs10;
h11 += hs11;
h12 += hs12;
h13 += hs13;
l[n][0] = h00 * l_re + h02 * r_re - h10 * l_im - h12 * r_im;
l[n][1] = h00 * l_im + h02 * r_im + h10 * l_re + h12 * r_re;
r[n][0] = h01 * l_re + h03 * r_re - h11 * l_im - h13 * r_im;
r[n][1] = h01 * l_im + h03 * r_im + h11 * l_re + h13 * r_re;
}
}
av_cold void ff_psdsp_init(PSDSPContext *s)
{
s->add_squares = ps_add_squares_c;
s->mul_pair_single = ps_mul_pair_single_c;
s->hybrid_analysis = ps_hybrid_analysis_c;
s->hybrid_analysis_ileave = ps_hybrid_analysis_ileave_c;
s->hybrid_synthesis_deint = ps_hybrid_synthesis_deint_c;
s->decorrelate = ps_decorrelate_c;
s->stereo_interpolate[0] = ps_stereo_interpolate_c;
s->stereo_interpolate[1] = ps_stereo_interpolate_ipdopd_c;
if (ARCH_ARM)
ff_psdsp_init_arm(s);
if (ARCH_MIPS)
ff_psdsp_init_mips(s);
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2012 Mans Rullgard
*
* 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 LIBAVCODEC_AACPSDSP_H
#define LIBAVCODEC_AACPSDSP_H
#define PS_QMF_TIME_SLOTS 32
#define PS_AP_LINKS 3
#define PS_MAX_AP_DELAY 5
typedef struct PSDSPContext {
void (*add_squares)(float *dst, const float (*src)[2], int n);
void (*mul_pair_single)(float (*dst)[2], float (*src0)[2], float *src1,
int n);
void (*hybrid_analysis)(float (*out)[2], float (*in)[2],
const float (*filter)[8][2],
int stride, int n);
void (*hybrid_analysis_ileave)(float (*out)[32][2], float L[2][38][64],
int i, int len);
void (*hybrid_synthesis_deint)(float out[2][38][64], float (*in)[32][2],
int i, int len);
void (*decorrelate)(float (*out)[2], float (*delay)[2],
float (*ap_delay)[PS_QMF_TIME_SLOTS+PS_MAX_AP_DELAY][2],
const float phi_fract[2], float (*Q_fract)[2],
const float *transient_gain,
float g_decay_slope,
int len);
void (*stereo_interpolate[2])(float (*l)[2], float (*r)[2],
float h[2][4], float h_step[2][4],
int len);
} PSDSPContext;
void ff_psdsp_init(PSDSPContext *s);
void ff_psdsp_init_arm(PSDSPContext *s);
void ff_psdsp_init_mips(PSDSPContext *s);
#endif /* LIBAVCODEC_AACPSDSP_H */

View File

@@ -0,0 +1,965 @@
/*
* AAC encoder psychoacoustic model
* Copyright (C) 2008 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
* AAC encoder psychoacoustic model
*/
#include "libavutil/attributes.h"
#include "libavutil/libm.h"
#include "avcodec.h"
#include "aactab.h"
#include "psymodel.h"
/***********************************
* TODOs:
* try other bitrate controlling mechanism (maybe use ratecontrol.c?)
* control quality for quality-based output
**********************************/
/**
* constants for 3GPP AAC psychoacoustic model
* @{
*/
#define PSY_3GPP_THR_SPREAD_HI 1.5f // spreading factor for low-to-hi threshold spreading (15 dB/Bark)
#define PSY_3GPP_THR_SPREAD_LOW 3.0f // spreading factor for hi-to-low threshold spreading (30 dB/Bark)
/* spreading factor for low-to-hi energy spreading, long block, > 22kbps/channel (20dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_L1 2.0f
/* spreading factor for low-to-hi energy spreading, long block, <= 22kbps/channel (15dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_L2 1.5f
/* spreading factor for low-to-hi energy spreading, short block (15 dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_S 1.5f
/* spreading factor for hi-to-low energy spreading, long block (30dB/Bark) */
#define PSY_3GPP_EN_SPREAD_LOW_L 3.0f
/* spreading factor for hi-to-low energy spreading, short block (20dB/Bark) */
#define PSY_3GPP_EN_SPREAD_LOW_S 2.0f
#define PSY_3GPP_RPEMIN 0.01f
#define PSY_3GPP_RPELEV 2.0f
#define PSY_3GPP_C1 3.0f /* log2(8) */
#define PSY_3GPP_C2 1.3219281f /* log2(2.5) */
#define PSY_3GPP_C3 0.55935729f /* 1 - C2 / C1 */
#define PSY_SNR_1DB 7.9432821e-1f /* -1dB */
#define PSY_SNR_25DB 3.1622776e-3f /* -25dB */
#define PSY_3GPP_SAVE_SLOPE_L -0.46666667f
#define PSY_3GPP_SAVE_SLOPE_S -0.36363637f
#define PSY_3GPP_SAVE_ADD_L -0.84285712f
#define PSY_3GPP_SAVE_ADD_S -0.75f
#define PSY_3GPP_SPEND_SLOPE_L 0.66666669f
#define PSY_3GPP_SPEND_SLOPE_S 0.81818181f
#define PSY_3GPP_SPEND_ADD_L -0.35f
#define PSY_3GPP_SPEND_ADD_S -0.26111111f
#define PSY_3GPP_CLIP_LO_L 0.2f
#define PSY_3GPP_CLIP_LO_S 0.2f
#define PSY_3GPP_CLIP_HI_L 0.95f
#define PSY_3GPP_CLIP_HI_S 0.75f
#define PSY_3GPP_AH_THR_LONG 0.5f
#define PSY_3GPP_AH_THR_SHORT 0.63f
enum {
PSY_3GPP_AH_NONE,
PSY_3GPP_AH_INACTIVE,
PSY_3GPP_AH_ACTIVE
};
#define PSY_3GPP_BITS_TO_PE(bits) ((bits) * 1.18f)
/* LAME psy model constants */
#define PSY_LAME_FIR_LEN 21 ///< LAME psy model FIR order
#define AAC_BLOCK_SIZE_LONG 1024 ///< long block size
#define AAC_BLOCK_SIZE_SHORT 128 ///< short block size
#define AAC_NUM_BLOCKS_SHORT 8 ///< number of blocks in a short sequence
#define PSY_LAME_NUM_SUBBLOCKS 3 ///< Number of sub-blocks in each short block
/**
* @}
*/
/**
* information for single band used by 3GPP TS26.403-inspired psychoacoustic model
*/
typedef struct AacPsyBand{
float energy; ///< band energy
float thr; ///< energy threshold
float thr_quiet; ///< threshold in quiet
float nz_lines; ///< number of non-zero spectral lines
float active_lines; ///< number of active spectral lines
float pe; ///< perceptual entropy
float pe_const; ///< constant part of the PE calculation
float norm_fac; ///< normalization factor for linearization
int avoid_holes; ///< hole avoidance flag
}AacPsyBand;
/**
* single/pair channel context for psychoacoustic model
*/
typedef struct AacPsyChannel{
AacPsyBand band[128]; ///< bands information
AacPsyBand prev_band[128]; ///< bands information from the previous frame
float win_energy; ///< sliding average of channel energy
float iir_state[2]; ///< hi-pass IIR filter state
uint8_t next_grouping; ///< stored grouping scheme for the next frame (in case of 8 short window sequence)
enum WindowSequence next_window_seq; ///< window sequence to be used in the next frame
/* LAME psy model specific members */
float attack_threshold; ///< attack threshold for this channel
float prev_energy_subshort[AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS];
int prev_attack; ///< attack value for the last short block in the previous sequence
}AacPsyChannel;
/**
* psychoacoustic model frame type-dependent coefficients
*/
typedef struct AacPsyCoeffs{
float ath; ///< absolute threshold of hearing per bands
float barks; ///< Bark value for each spectral band in long frame
float spread_low[2]; ///< spreading factor for low-to-high threshold spreading in long frame
float spread_hi [2]; ///< spreading factor for high-to-low threshold spreading in long frame
float min_snr; ///< minimal SNR
}AacPsyCoeffs;
/**
* 3GPP TS26.403-inspired psychoacoustic model specific data
*/
typedef struct AacPsyContext{
int chan_bitrate; ///< bitrate per channel
int frame_bits; ///< average bits per frame
int fill_level; ///< bit reservoir fill level
struct {
float min; ///< minimum allowed PE for bit factor calculation
float max; ///< maximum allowed PE for bit factor calculation
float previous; ///< allowed PE of the previous frame
float correction; ///< PE correction factor
} pe;
AacPsyCoeffs psy_coef[2][64];
AacPsyChannel *ch;
}AacPsyContext;
/**
* LAME psy model preset struct
*/
typedef struct {
int quality; ///< Quality to map the rest of the vaules to.
/* This is overloaded to be both kbps per channel in ABR mode, and
* requested quality in constant quality mode.
*/
float st_lrm; ///< short threshold for L, R, and M channels
} PsyLamePreset;
/**
* LAME psy model preset table for ABR
*/
static const PsyLamePreset psy_abr_map[] = {
/* TODO: Tuning. These were taken from LAME. */
/* kbps/ch st_lrm */
{ 8, 6.60},
{ 16, 6.60},
{ 24, 6.60},
{ 32, 6.60},
{ 40, 6.60},
{ 48, 6.60},
{ 56, 6.60},
{ 64, 6.40},
{ 80, 6.00},
{ 96, 5.60},
{112, 5.20},
{128, 5.20},
{160, 5.20}
};
/**
* LAME psy model preset table for constant quality
*/
static const PsyLamePreset psy_vbr_map[] = {
/* vbr_q st_lrm */
{ 0, 4.20},
{ 1, 4.20},
{ 2, 4.20},
{ 3, 4.20},
{ 4, 4.20},
{ 5, 4.20},
{ 6, 4.20},
{ 7, 4.20},
{ 8, 4.20},
{ 9, 4.20},
{10, 4.20}
};
/**
* LAME psy model FIR coefficient table
*/
static const float psy_fir_coeffs[] = {
-8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2,
-3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2,
-5.52212e-17 * 2, -0.313819 * 2
};
#if ARCH_MIPS
# include "mips/aacpsy_mips.h"
#endif /* ARCH_MIPS */
/**
* Calculate the ABR attack threshold from the above LAME psymodel table.
*/
static float lame_calc_attack_threshold(int bitrate)
{
/* Assume max bitrate to start with */
int lower_range = 12, upper_range = 12;
int lower_range_kbps = psy_abr_map[12].quality;
int upper_range_kbps = psy_abr_map[12].quality;
int i;
/* Determine which bitrates the value specified falls between.
* If the loop ends without breaking our above assumption of 320kbps was correct.
*/
for (i = 1; i < 13; i++) {
if (FFMAX(bitrate, psy_abr_map[i].quality) != bitrate) {
upper_range = i;
upper_range_kbps = psy_abr_map[i ].quality;
lower_range = i - 1;
lower_range_kbps = psy_abr_map[i - 1].quality;
break; /* Upper range found */
}
}
/* Determine which range the value specified is closer to */
if ((upper_range_kbps - bitrate) > (bitrate - lower_range_kbps))
return psy_abr_map[lower_range].st_lrm;
return psy_abr_map[upper_range].st_lrm;
}
/**
* LAME psy model specific initialization
*/
static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx)
{
int i, j;
for (i = 0; i < avctx->channels; i++) {
AacPsyChannel *pch = &ctx->ch[i];
if (avctx->flags & CODEC_FLAG_QSCALE)
pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm;
else
pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->channels / 1000);
for (j = 0; j < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; j++)
pch->prev_energy_subshort[j] = 10.0f;
}
}
/**
* Calculate Bark value for given line.
*/
static av_cold float calc_bark(float f)
{
return 13.3f * atanf(0.00076f * f) + 3.5f * atanf((f / 7500.0f) * (f / 7500.0f));
}
#define ATH_ADD 4
/**
* Calculate ATH value for given frequency.
* Borrowed from Lame.
*/
static av_cold float ath(float f, float add)
{
f /= 1000.0f;
return 3.64 * pow(f, -0.8)
- 6.8 * exp(-0.6 * (f - 3.4) * (f - 3.4))
+ 6.0 * exp(-0.15 * (f - 8.7) * (f - 8.7))
+ (0.6 + 0.04 * add) * 0.001 * f * f * f * f;
}
static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
AacPsyContext *pctx;
float bark;
int i, j, g, start;
float prev, minscale, minath, minsnr, pe_min;
const int chan_bitrate = ctx->avctx->bit_rate / ctx->avctx->channels;
const int bandwidth = ctx->avctx->cutoff ? ctx->avctx->cutoff : AAC_CUTOFF(ctx->avctx);
const float num_bark = calc_bark((float)bandwidth);
ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext));
pctx = (AacPsyContext*) ctx->model_priv_data;
pctx->chan_bitrate = chan_bitrate;
pctx->frame_bits = chan_bitrate * AAC_BLOCK_SIZE_LONG / ctx->avctx->sample_rate;
pctx->pe.min = 8.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f);
pctx->pe.max = 12.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f);
ctx->bitres.size = 6144 - pctx->frame_bits;
ctx->bitres.size -= ctx->bitres.size % 8;
pctx->fill_level = ctx->bitres.size;
minath = ath(3410, ATH_ADD);
for (j = 0; j < 2; j++) {
AacPsyCoeffs *coeffs = pctx->psy_coef[j];
const uint8_t *band_sizes = ctx->bands[j];
float line_to_frequency = ctx->avctx->sample_rate / (j ? 256.f : 2048.0f);
float avg_chan_bits = chan_bitrate * (j ? 128.0f : 1024.0f) / ctx->avctx->sample_rate;
/* reference encoder uses 2.4% here instead of 60% like the spec says */
float bark_pe = 0.024f * PSY_3GPP_BITS_TO_PE(avg_chan_bits) / num_bark;
float en_spread_low = j ? PSY_3GPP_EN_SPREAD_LOW_S : PSY_3GPP_EN_SPREAD_LOW_L;
/* High energy spreading for long blocks <= 22kbps/channel and short blocks are the same. */
float en_spread_hi = (j || (chan_bitrate <= 22.0f)) ? PSY_3GPP_EN_SPREAD_HI_S : PSY_3GPP_EN_SPREAD_HI_L1;
i = 0;
prev = 0.0;
for (g = 0; g < ctx->num_bands[j]; g++) {
i += band_sizes[g];
bark = calc_bark((i-1) * line_to_frequency);
coeffs[g].barks = (bark + prev) / 2.0;
prev = bark;
}
for (g = 0; g < ctx->num_bands[j] - 1; g++) {
AacPsyCoeffs *coeff = &coeffs[g];
float bark_width = coeffs[g+1].barks - coeffs->barks;
coeff->spread_low[0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_LOW);
coeff->spread_hi [0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_HI);
coeff->spread_low[1] = pow(10.0, -bark_width * en_spread_low);
coeff->spread_hi [1] = pow(10.0, -bark_width * en_spread_hi);
pe_min = bark_pe * bark_width;
minsnr = exp2(pe_min / band_sizes[g]) - 1.5f;
coeff->min_snr = av_clipf(1.0f / minsnr, PSY_SNR_25DB, PSY_SNR_1DB);
}
start = 0;
for (g = 0; g < ctx->num_bands[j]; g++) {
minscale = ath(start * line_to_frequency, ATH_ADD);
for (i = 1; i < band_sizes[g]; i++)
minscale = FFMIN(minscale, ath((start + i) * line_to_frequency, ATH_ADD));
coeffs[g].ath = minscale - minath;
start += band_sizes[g];
}
}
pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->channels);
lame_window_init(pctx, ctx->avctx);
return 0;
}
/**
* IIR filter used in block switching decision
*/
static float iir_filter(int in, float state[2])
{
float ret;
ret = 0.7548f * (in - state[0]) + 0.5095f * state[1];
state[0] = in;
state[1] = ret;
return ret;
}
/**
* window grouping information stored as bits (0 - new group, 1 - group continues)
*/
static const uint8_t window_grouping[9] = {
0xB6, 0x6C, 0xD8, 0xB2, 0x66, 0xC6, 0x96, 0x36, 0x36
};
/**
* Tell encoder which window types to use.
* @see 3GPP TS26.403 5.4.1 "Blockswitching"
*/
static av_unused FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx,
const int16_t *audio,
const int16_t *la,
int channel, int prev_type)
{
int i, j;
int br = ctx->avctx->bit_rate / ctx->avctx->channels;
int attack_ratio = br <= 16000 ? 18 : 10;
AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data;
AacPsyChannel *pch = &pctx->ch[channel];
uint8_t grouping = 0;
int next_type = pch->next_window_seq;
FFPsyWindowInfo wi = { { 0 } };
if (la) {
float s[8], v;
int switch_to_eight = 0;
float sum = 0.0, sum2 = 0.0;
int attack_n = 0;
int stay_short = 0;
for (i = 0; i < 8; i++) {
for (j = 0; j < 128; j++) {
v = iir_filter(la[i*128+j], pch->iir_state);
sum += v*v;
}
s[i] = sum;
sum2 += sum;
}
for (i = 0; i < 8; i++) {
if (s[i] > pch->win_energy * attack_ratio) {
attack_n = i + 1;
switch_to_eight = 1;
break;
}
}
pch->win_energy = pch->win_energy*7/8 + sum2/64;
wi.window_type[1] = prev_type;
switch (prev_type) {
case ONLY_LONG_SEQUENCE:
wi.window_type[0] = switch_to_eight ? LONG_START_SEQUENCE : ONLY_LONG_SEQUENCE;
next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : ONLY_LONG_SEQUENCE;
break;
case LONG_START_SEQUENCE:
wi.window_type[0] = EIGHT_SHORT_SEQUENCE;
grouping = pch->next_grouping;
next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE;
break;
case LONG_STOP_SEQUENCE:
wi.window_type[0] = switch_to_eight ? LONG_START_SEQUENCE : ONLY_LONG_SEQUENCE;
next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : ONLY_LONG_SEQUENCE;
break;
case EIGHT_SHORT_SEQUENCE:
stay_short = next_type == EIGHT_SHORT_SEQUENCE || switch_to_eight;
wi.window_type[0] = stay_short ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE;
grouping = next_type == EIGHT_SHORT_SEQUENCE ? pch->next_grouping : 0;
next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE;
break;
}
pch->next_grouping = window_grouping[attack_n];
pch->next_window_seq = next_type;
} else {
for (i = 0; i < 3; i++)
wi.window_type[i] = prev_type;
grouping = (prev_type == EIGHT_SHORT_SEQUENCE) ? window_grouping[0] : 0;
}
wi.window_shape = 1;
if (wi.window_type[0] != EIGHT_SHORT_SEQUENCE) {
wi.num_windows = 1;
wi.grouping[0] = 1;
} else {
int lastgrp = 0;
wi.num_windows = 8;
for (i = 0; i < 8; i++) {
if (!((grouping >> i) & 1))
lastgrp = i;
wi.grouping[lastgrp]++;
}
}
return wi;
}
/* 5.6.1.2 "Calculation of Bit Demand" */
static int calc_bit_demand(AacPsyContext *ctx, float pe, int bits, int size,
int short_window)
{
const float bitsave_slope = short_window ? PSY_3GPP_SAVE_SLOPE_S : PSY_3GPP_SAVE_SLOPE_L;
const float bitsave_add = short_window ? PSY_3GPP_SAVE_ADD_S : PSY_3GPP_SAVE_ADD_L;
const float bitspend_slope = short_window ? PSY_3GPP_SPEND_SLOPE_S : PSY_3GPP_SPEND_SLOPE_L;
const float bitspend_add = short_window ? PSY_3GPP_SPEND_ADD_S : PSY_3GPP_SPEND_ADD_L;
const float clip_low = short_window ? PSY_3GPP_CLIP_LO_S : PSY_3GPP_CLIP_LO_L;
const float clip_high = short_window ? PSY_3GPP_CLIP_HI_S : PSY_3GPP_CLIP_HI_L;
float clipped_pe, bit_save, bit_spend, bit_factor, fill_level;
ctx->fill_level += ctx->frame_bits - bits;
ctx->fill_level = av_clip(ctx->fill_level, 0, size);
fill_level = av_clipf((float)ctx->fill_level / size, clip_low, clip_high);
clipped_pe = av_clipf(pe, ctx->pe.min, ctx->pe.max);
bit_save = (fill_level + bitsave_add) * bitsave_slope;
assert(bit_save <= 0.3f && bit_save >= -0.05000001f);
bit_spend = (fill_level + bitspend_add) * bitspend_slope;
assert(bit_spend <= 0.5f && bit_spend >= -0.1f);
/* The bit factor graph in the spec is obviously incorrect.
* bit_spend + ((bit_spend - bit_spend))...
* The reference encoder subtracts everything from 1, but also seems incorrect.
* 1 - bit_save + ((bit_spend + bit_save))...
* Hopefully below is correct.
*/
bit_factor = 1.0f - bit_save + ((bit_spend - bit_save) / (ctx->pe.max - ctx->pe.min)) * (clipped_pe - ctx->pe.min);
/* NOTE: The reference encoder attempts to center pe max/min around the current pe. */
ctx->pe.max = FFMAX(pe, ctx->pe.max);
ctx->pe.min = FFMIN(pe, ctx->pe.min);
return FFMIN(ctx->frame_bits * bit_factor, ctx->frame_bits + size - bits);
}
static float calc_pe_3gpp(AacPsyBand *band)
{
float pe, a;
band->pe = 0.0f;
band->pe_const = 0.0f;
band->active_lines = 0.0f;
if (band->energy > band->thr) {
a = log2f(band->energy);
pe = a - log2f(band->thr);
band->active_lines = band->nz_lines;
if (pe < PSY_3GPP_C1) {
pe = pe * PSY_3GPP_C3 + PSY_3GPP_C2;
a = a * PSY_3GPP_C3 + PSY_3GPP_C2;
band->active_lines *= PSY_3GPP_C3;
}
band->pe = pe * band->nz_lines;
band->pe_const = a * band->nz_lines;
}
return band->pe;
}
static float calc_reduction_3gpp(float a, float desired_pe, float pe,
float active_lines)
{
float thr_avg, reduction;
if(active_lines == 0.0)
return 0;
thr_avg = exp2f((a - pe) / (4.0f * active_lines));
reduction = exp2f((a - desired_pe) / (4.0f * active_lines)) - thr_avg;
return FFMAX(reduction, 0.0f);
}
static float calc_reduced_thr_3gpp(AacPsyBand *band, float min_snr,
float reduction)
{
float thr = band->thr;
if (band->energy > thr) {
thr = sqrtf(thr);
thr = sqrtf(thr) + reduction;
thr *= thr;
thr *= thr;
/* This deviates from the 3GPP spec to match the reference encoder.
* It performs min(thr_reduced, max(thr, energy/min_snr)) only for bands
* that have hole avoidance on (active or inactive). It always reduces the
* threshold of bands with hole avoidance off.
*/
if (thr > band->energy * min_snr && band->avoid_holes != PSY_3GPP_AH_NONE) {
thr = FFMAX(band->thr, band->energy * min_snr);
band->avoid_holes = PSY_3GPP_AH_ACTIVE;
}
}
return thr;
}
#ifndef calc_thr_3gpp
static void calc_thr_3gpp(const FFPsyWindowInfo *wi, const int num_bands, AacPsyChannel *pch,
const uint8_t *band_sizes, const float *coefs)
{
int i, w, g;
int start = 0;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
float form_factor = 0.0f;
float Temp;
band->energy = 0.0f;
for (i = 0; i < band_sizes[g]; i++) {
band->energy += coefs[start+i] * coefs[start+i];
form_factor += sqrtf(fabs(coefs[start+i]));
}
Temp = band->energy > 0 ? sqrtf((float)band_sizes[g] / band->energy) : 0;
band->thr = band->energy * 0.001258925f;
band->nz_lines = form_factor * sqrtf(Temp);
start += band_sizes[g];
}
}
}
#endif /* calc_thr_3gpp */
#ifndef psy_hp_filter
static void psy_hp_filter(const float *firbuf, float *hpfsmpl, const float *psy_fir_coeffs)
{
int i, j;
for (i = 0; i < AAC_BLOCK_SIZE_LONG; i++) {
float sum1, sum2;
sum1 = firbuf[i + (PSY_LAME_FIR_LEN - 1) / 2];
sum2 = 0.0;
for (j = 0; j < ((PSY_LAME_FIR_LEN - 1) / 2) - 1; j += 2) {
sum1 += psy_fir_coeffs[j] * (firbuf[i + j] + firbuf[i + PSY_LAME_FIR_LEN - j]);
sum2 += psy_fir_coeffs[j + 1] * (firbuf[i + j + 1] + firbuf[i + PSY_LAME_FIR_LEN - j - 1]);
}
/* NOTE: The LAME psymodel expects it's input in the range -32768 to 32768.
* Tuning this for normalized floats would be difficult. */
hpfsmpl[i] = (sum1 + sum2) * 32768.0f;
}
}
#endif /* psy_hp_filter */
/**
* Calculate band thresholds as suggested in 3GPP TS26.403
*/
static void psy_3gpp_analyze_channel(FFPsyContext *ctx, int channel,
const float *coefs, const FFPsyWindowInfo *wi)
{
AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data;
AacPsyChannel *pch = &pctx->ch[channel];
int i, w, g;
float desired_bits, desired_pe, delta_pe, reduction= NAN, spread_en[128] = {0};
float a = 0.0f, active_lines = 0.0f, norm_fac = 0.0f;
float pe = pctx->chan_bitrate > 32000 ? 0.0f : FFMAX(50.0f, 100.0f - pctx->chan_bitrate * 100.0f / 32000.0f);
const int num_bands = ctx->num_bands[wi->num_windows == 8];
const uint8_t *band_sizes = ctx->bands[wi->num_windows == 8];
AacPsyCoeffs *coeffs = pctx->psy_coef[wi->num_windows == 8];
const float avoid_hole_thr = wi->num_windows == 8 ? PSY_3GPP_AH_THR_SHORT : PSY_3GPP_AH_THR_LONG;
//calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation"
calc_thr_3gpp(wi, num_bands, pch, band_sizes, coefs);
//modify thresholds and energies - spread, threshold in quiet, pre-echo control
for (w = 0; w < wi->num_windows*16; w += 16) {
AacPsyBand *bands = &pch->band[w];
/* 5.4.2.3 "Spreading" & 5.4.3 "Spread Energy Calculation" */
spread_en[0] = bands[0].energy;
for (g = 1; g < num_bands; g++) {
bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[0]);
spread_en[w+g] = FFMAX(bands[g].energy, spread_en[w+g-1] * coeffs[g].spread_hi[1]);
}
for (g = num_bands - 2; g >= 0; g--) {
bands[g].thr = FFMAX(bands[g].thr, bands[g+1].thr * coeffs[g].spread_low[0]);
spread_en[w+g] = FFMAX(spread_en[w+g], spread_en[w+g+1] * coeffs[g].spread_low[1]);
}
//5.4.2.4 "Threshold in quiet"
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &bands[g];
band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath);
//5.4.2.5 "Pre-echo control"
if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w)))
band->thr = FFMAX(PSY_3GPP_RPEMIN*band->thr, FFMIN(band->thr,
PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet));
/* 5.6.1.3.1 "Preparatory steps of the perceptual entropy calculation" */
pe += calc_pe_3gpp(band);
a += band->pe_const;
active_lines += band->active_lines;
/* 5.6.1.3.3 "Selection of the bands for avoidance of holes" */
if (spread_en[w+g] * avoid_hole_thr > band->energy || coeffs[g].min_snr > 1.0f)
band->avoid_holes = PSY_3GPP_AH_NONE;
else
band->avoid_holes = PSY_3GPP_AH_INACTIVE;
}
}
/* 5.6.1.3.2 "Calculation of the desired perceptual entropy" */
ctx->ch[channel].entropy = pe;
desired_bits = calc_bit_demand(pctx, pe, ctx->bitres.bits, ctx->bitres.size, wi->num_windows == 8);
desired_pe = PSY_3GPP_BITS_TO_PE(desired_bits);
/* NOTE: PE correction is kept simple. During initial testing it had very
* little effect on the final bitrate. Probably a good idea to come
* back and do more testing later.
*/
if (ctx->bitres.bits > 0)
desired_pe *= av_clipf(pctx->pe.previous / PSY_3GPP_BITS_TO_PE(ctx->bitres.bits),
0.85f, 1.15f);
pctx->pe.previous = PSY_3GPP_BITS_TO_PE(desired_bits);
if (desired_pe < pe) {
/* 5.6.1.3.4 "First Estimation of the reduction value" */
for (w = 0; w < wi->num_windows*16; w += 16) {
reduction = calc_reduction_3gpp(a, desired_pe, pe, active_lines);
pe = 0.0f;
a = 0.0f;
active_lines = 0.0f;
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction);
/* recalculate PE */
pe += calc_pe_3gpp(band);
a += band->pe_const;
active_lines += band->active_lines;
}
}
/* 5.6.1.3.5 "Second Estimation of the reduction value" */
for (i = 0; i < 2; i++) {
float pe_no_ah = 0.0f, desired_pe_no_ah;
active_lines = a = 0.0f;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (band->avoid_holes != PSY_3GPP_AH_ACTIVE) {
pe_no_ah += band->pe;
a += band->pe_const;
active_lines += band->active_lines;
}
}
}
desired_pe_no_ah = FFMAX(desired_pe - (pe - pe_no_ah), 0.0f);
if (active_lines > 0.0f)
reduction += calc_reduction_3gpp(a, desired_pe_no_ah, pe_no_ah, active_lines);
pe = 0.0f;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (active_lines > 0.0f)
band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction);
pe += calc_pe_3gpp(band);
band->norm_fac = band->active_lines / band->thr;
norm_fac += band->norm_fac;
}
}
delta_pe = desired_pe - pe;
if (fabs(delta_pe) > 0.05f * desired_pe)
break;
}
if (pe < 1.15f * desired_pe) {
/* 6.6.1.3.6 "Final threshold modification by linearization" */
norm_fac = 1.0f / norm_fac;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (band->active_lines > 0.5f) {
float delta_sfb_pe = band->norm_fac * norm_fac * delta_pe;
float thr = band->thr;
thr *= exp2f(delta_sfb_pe / band->active_lines);
if (thr > coeffs[g].min_snr * band->energy && band->avoid_holes == PSY_3GPP_AH_INACTIVE)
thr = FFMAX(band->thr, coeffs[g].min_snr * band->energy);
band->thr = thr;
}
}
}
} else {
/* 5.6.1.3.7 "Further perceptual entropy reduction" */
g = num_bands;
while (pe > desired_pe && g--) {
for (w = 0; w < wi->num_windows*16; w+= 16) {
AacPsyBand *band = &pch->band[w+g];
if (band->avoid_holes != PSY_3GPP_AH_NONE && coeffs[g].min_snr < PSY_SNR_1DB) {
coeffs[g].min_snr = PSY_SNR_1DB;
band->thr = band->energy * PSY_SNR_1DB;
pe += band->active_lines * 1.5f - band->pe;
}
}
}
/* TODO: allow more holes (unused without mid/side) */
}
}
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
FFPsyBand *psy_band = &ctx->ch[channel].psy_bands[w+g];
psy_band->threshold = band->thr;
psy_band->energy = band->energy;
}
}
memcpy(pch->prev_band, pch->band, sizeof(pch->band));
}
static void psy_3gpp_analyze(FFPsyContext *ctx, int channel,
const float **coeffs, const FFPsyWindowInfo *wi)
{
int ch;
FFPsyChannelGroup *group = ff_psy_find_group(ctx, channel);
for (ch = 0; ch < group->num_ch; ch++)
psy_3gpp_analyze_channel(ctx, channel + ch, coeffs[ch], &wi[ch]);
}
static av_cold void psy_3gpp_end(FFPsyContext *apc)
{
AacPsyContext *pctx = (AacPsyContext*) apc->model_priv_data;
av_freep(&pctx->ch);
av_freep(&apc->model_priv_data);
}
static void lame_apply_block_type(AacPsyChannel *ctx, FFPsyWindowInfo *wi, int uselongblock)
{
int blocktype = ONLY_LONG_SEQUENCE;
if (uselongblock) {
if (ctx->next_window_seq == EIGHT_SHORT_SEQUENCE)
blocktype = LONG_STOP_SEQUENCE;
} else {
blocktype = EIGHT_SHORT_SEQUENCE;
if (ctx->next_window_seq == ONLY_LONG_SEQUENCE)
ctx->next_window_seq = LONG_START_SEQUENCE;
if (ctx->next_window_seq == LONG_STOP_SEQUENCE)
ctx->next_window_seq = EIGHT_SHORT_SEQUENCE;
}
wi->window_type[0] = ctx->next_window_seq;
ctx->next_window_seq = blocktype;
}
static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
const float *la, int channel, int prev_type)
{
AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data;
AacPsyChannel *pch = &pctx->ch[channel];
int grouping = 0;
int uselongblock = 1;
int attacks[AAC_NUM_BLOCKS_SHORT + 1] = { 0 };
int i;
FFPsyWindowInfo wi = { { 0 } };
if (la) {
float hpfsmpl[AAC_BLOCK_SIZE_LONG];
float const *pf = hpfsmpl;
float attack_intensity[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS];
float energy_subshort[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS];
float energy_short[AAC_NUM_BLOCKS_SHORT + 1] = { 0 };
const float *firbuf = la + (AAC_BLOCK_SIZE_SHORT/4 - PSY_LAME_FIR_LEN);
int att_sum = 0;
/* LAME comment: apply high pass filter of fs/4 */
psy_hp_filter(firbuf, hpfsmpl, psy_fir_coeffs);
/* Calculate the energies of each sub-shortblock */
for (i = 0; i < PSY_LAME_NUM_SUBBLOCKS; i++) {
energy_subshort[i] = pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 1) * PSY_LAME_NUM_SUBBLOCKS)];
assert(pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 2) * PSY_LAME_NUM_SUBBLOCKS + 1)] > 0);
attack_intensity[i] = energy_subshort[i] / pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 2) * PSY_LAME_NUM_SUBBLOCKS + 1)];
energy_short[0] += energy_subshort[i];
}
for (i = 0; i < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; i++) {
float const *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS);
float p = 1.0f;
for (; pf < pfe; pf++)
p = FFMAX(p, fabsf(*pf));
pch->prev_energy_subshort[i] = energy_subshort[i + PSY_LAME_NUM_SUBBLOCKS] = p;
energy_short[1 + i / PSY_LAME_NUM_SUBBLOCKS] += p;
/* NOTE: The indexes below are [i + 3 - 2] in the LAME source.
* Obviously the 3 and 2 have some significance, or this would be just [i + 1]
* (which is what we use here). What the 3 stands for is ambiguous, as it is both
* number of short blocks, and the number of sub-short blocks.
* It seems that LAME is comparing each sub-block to sub-block + 1 in the
* previous block.
*/
if (p > energy_subshort[i + 1])
p = p / energy_subshort[i + 1];
else if (energy_subshort[i + 1] > p * 10.0f)
p = energy_subshort[i + 1] / (p * 10.0f);
else
p = 0.0;
attack_intensity[i + PSY_LAME_NUM_SUBBLOCKS] = p;
}
/* compare energy between sub-short blocks */
for (i = 0; i < (AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS; i++)
if (!attacks[i / PSY_LAME_NUM_SUBBLOCKS])
if (attack_intensity[i] > pch->attack_threshold)
attacks[i / PSY_LAME_NUM_SUBBLOCKS] = (i % PSY_LAME_NUM_SUBBLOCKS) + 1;
/* should have energy change between short blocks, in order to avoid periodic signals */
/* Good samples to show the effect are Trumpet test songs */
/* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */
/* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */
for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++) {
float const u = energy_short[i - 1];
float const v = energy_short[i];
float const m = FFMAX(u, v);
if (m < 40000) { /* (2) */
if (u < 1.7f * v && v < 1.7f * u) { /* (1) */
if (i == 1 && attacks[0] < attacks[i])
attacks[0] = 0;
attacks[i] = 0;
}
}
att_sum += attacks[i];
}
if (attacks[0] <= pch->prev_attack)
attacks[0] = 0;
att_sum += attacks[0];
/* 3 below indicates the previous attack happened in the last sub-block of the previous sequence */
if (pch->prev_attack == 3 || att_sum) {
uselongblock = 0;
for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++)
if (attacks[i] && attacks[i-1])
attacks[i] = 0;
}
} else {
/* We have no lookahead info, so just use same type as the previous sequence. */
uselongblock = !(prev_type == EIGHT_SHORT_SEQUENCE);
}
lame_apply_block_type(pch, &wi, uselongblock);
wi.window_type[1] = prev_type;
if (wi.window_type[0] != EIGHT_SHORT_SEQUENCE) {
wi.num_windows = 1;
wi.grouping[0] = 1;
if (wi.window_type[0] == LONG_START_SEQUENCE)
wi.window_shape = 0;
else
wi.window_shape = 1;
} else {
int lastgrp = 0;
wi.num_windows = 8;
wi.window_shape = 0;
for (i = 0; i < 8; i++) {
if (!((pch->next_grouping >> i) & 1))
lastgrp = i;
wi.grouping[lastgrp]++;
}
}
/* Determine grouping, based on the location of the first attack, and save for
* the next frame.
* FIXME: Move this to analysis.
* TODO: Tune groupings depending on attack location
* TODO: Handle more than one attack in a group
*/
for (i = 0; i < 9; i++) {
if (attacks[i]) {
grouping = i;
break;
}
}
pch->next_grouping = window_grouping[grouping];
pch->prev_attack = attacks[8];
return wi;
}
const FFPsyModel ff_aac_psy_model =
{
.name = "3GPP TS 26.403-inspired model",
.init = psy_3gpp_init,
.window = psy_lame_window,
.analyze = psy_3gpp_analyze,
.end = psy_3gpp_end,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
/*
* AAC Spectral Band Replication function declarations
* Copyright (c) 2008-2009 Robert Swain ( rob opendot cl )
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.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
*/
/**
* @file
* AAC Spectral Band Replication function declarations
* @author Robert Swain ( rob opendot cl )
*/
#ifndef AVCODEC_AACSBR_H
#define AVCODEC_AACSBR_H
#include "get_bits.h"
#include "aac.h"
#include "sbr.h"
/** Initialize SBR. */
void ff_aac_sbr_init(void);
/** Initialize one SBR context. */
void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr);
/** Close one SBR context. */
void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr);
/** Decode one SBR element. */
int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr,
GetBitContext *gb, int crc, int cnt, int id_aac);
/** Apply one SBR element to one AAC element. */
void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac,
float* L, float *R);
void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c);
#endif /* AVCODEC_AACSBR_H */

View File

@@ -0,0 +1,620 @@
/*
* AAC Spectral Band Replication decoding data
* Copyright (c) 2008-2009 Robert Swain ( rob opendot cl )
*
* 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
* AAC Spectral Band Replication decoding data
* @author Robert Swain ( rob opendot cl )
*/
#ifndef AVCODEC_AACSBRDATA_H
#define AVCODEC_AACSBRDATA_H
#include <stdint.h>
#include "libavutil/mem.h"
///< Huffman tables for SBR
static const uint8_t t_huffman_env_1_5dB_bits[121] = {
18, 18, 18, 18, 18, 18, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 17, 18, 16, 17, 18, 17,
16, 16, 16, 16, 15, 14, 14, 13,
13, 12, 11, 10, 9, 8, 7, 6,
5, 4, 3, 2, 2, 3, 4, 5,
6, 7, 8, 9, 10, 12, 13, 14,
14, 15, 16, 17, 16, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19,
};
static const uint32_t t_huffman_env_1_5dB_codes[121] = {
0x3ffd6, 0x3ffd7, 0x3ffd8, 0x3ffd9, 0x3ffda, 0x3ffdb, 0x7ffb8, 0x7ffb9,
0x7ffba, 0x7ffbb, 0x7ffbc, 0x7ffbd, 0x7ffbe, 0x7ffbf, 0x7ffc0, 0x7ffc1,
0x7ffc2, 0x7ffc3, 0x7ffc4, 0x7ffc5, 0x7ffc6, 0x7ffc7, 0x7ffc8, 0x7ffc9,
0x7ffca, 0x7ffcb, 0x7ffcc, 0x7ffcd, 0x7ffce, 0x7ffcf, 0x7ffd0, 0x7ffd1,
0x7ffd2, 0x7ffd3, 0x1ffe6, 0x3ffd4, 0x0fff0, 0x1ffe9, 0x3ffd5, 0x1ffe7,
0x0fff1, 0x0ffec, 0x0ffed, 0x0ffee, 0x07ff4, 0x03ff9, 0x03ff7, 0x01ffa,
0x01ff9, 0x00ffb, 0x007fc, 0x003fc, 0x001fd, 0x000fd, 0x0007d, 0x0003d,
0x0001d, 0x0000d, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000c, 0x0001c,
0x0003c, 0x0007c, 0x000fc, 0x001fc, 0x003fd, 0x00ffa, 0x01ff8, 0x03ff6,
0x03ff8, 0x07ff5, 0x0ffef, 0x1ffe8, 0x0fff2, 0x7ffd4, 0x7ffd5, 0x7ffd6,
0x7ffd7, 0x7ffd8, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd, 0x7ffde,
0x7ffdf, 0x7ffe0, 0x7ffe1, 0x7ffe2, 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffe6,
0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, 0x7ffec, 0x7ffed, 0x7ffee,
0x7ffef, 0x7fff0, 0x7fff1, 0x7fff2, 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6,
0x7fff7, 0x7fff8, 0x7fff9, 0x7fffa, 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe,
0x7ffff,
};
static const uint8_t f_huffman_env_1_5dB_bits[121] = {
19, 19, 20, 20, 20, 20, 20, 20,
20, 19, 20, 20, 20, 20, 19, 20,
19, 19, 20, 18, 20, 20, 20, 19,
20, 20, 20, 19, 20, 19, 18, 19,
18, 18, 17, 18, 17, 17, 17, 16,
16, 16, 15, 15, 14, 13, 13, 12,
12, 11, 10, 9, 9, 8, 7, 6,
5, 4, 3, 2, 2, 3, 4, 5,
6, 8, 8, 9, 10, 11, 11, 11,
12, 12, 13, 13, 14, 14, 16, 16,
17, 17, 18, 18, 18, 18, 18, 18,
18, 20, 19, 20, 20, 20, 20, 20,
20, 19, 20, 20, 20, 20, 19, 20,
18, 20, 20, 19, 19, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20,
20,
};
static const uint32_t f_huffman_env_1_5dB_codes[121] = {
0x7ffe7, 0x7ffe8, 0xfffd2, 0xfffd3, 0xfffd4, 0xfffd5, 0xfffd6, 0xfffd7,
0xfffd8, 0x7ffda, 0xfffd9, 0xfffda, 0xfffdb, 0xfffdc, 0x7ffdb, 0xfffdd,
0x7ffdc, 0x7ffdd, 0xfffde, 0x3ffe4, 0xfffdf, 0xfffe0, 0xfffe1, 0x7ffde,
0xfffe2, 0xfffe3, 0xfffe4, 0x7ffdf, 0xfffe5, 0x7ffe0, 0x3ffe8, 0x7ffe1,
0x3ffe0, 0x3ffe9, 0x1ffef, 0x3ffe5, 0x1ffec, 0x1ffed, 0x1ffee, 0x0fff4,
0x0fff3, 0x0fff0, 0x07ff7, 0x07ff6, 0x03ffa, 0x01ffa, 0x01ff9, 0x00ffa,
0x00ff8, 0x007f9, 0x003fb, 0x001fc, 0x001fa, 0x000fb, 0x0007c, 0x0003c,
0x0001c, 0x0000c, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000d, 0x0001d,
0x0003d, 0x000fa, 0x000fc, 0x001fb, 0x003fa, 0x007f8, 0x007fa, 0x007fb,
0x00ff9, 0x00ffb, 0x01ff8, 0x01ffb, 0x03ff8, 0x03ff9, 0x0fff1, 0x0fff2,
0x1ffea, 0x1ffeb, 0x3ffe1, 0x3ffe2, 0x3ffea, 0x3ffe3, 0x3ffe6, 0x3ffe7,
0x3ffeb, 0xfffe6, 0x7ffe2, 0xfffe7, 0xfffe8, 0xfffe9, 0xfffea, 0xfffeb,
0xfffec, 0x7ffe3, 0xfffed, 0xfffee, 0xfffef, 0xffff0, 0x7ffe4, 0xffff1,
0x3ffec, 0xffff2, 0xffff3, 0x7ffe5, 0x7ffe6, 0xffff4, 0xffff5, 0xffff6,
0xffff7, 0xffff8, 0xffff9, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe,
0xfffff,
};
static const uint8_t t_huffman_env_bal_1_5dB_bits[49] = {
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 12, 11, 9, 7, 5, 3,
1, 2, 4, 6, 8, 11, 12, 15,
16, 16, 16, 16, 16, 16, 16, 17,
17, 17, 17, 17, 17, 17, 17, 17,
17,
};
static const uint32_t t_huffman_env_bal_1_5dB_codes[49] = {
0x0ffe4, 0x0ffe5, 0x0ffe6, 0x0ffe7, 0x0ffe8, 0x0ffe9, 0x0ffea, 0x0ffeb,
0x0ffec, 0x0ffed, 0x0ffee, 0x0ffef, 0x0fff0, 0x0fff1, 0x0fff2, 0x0fff3,
0x0fff4, 0x0ffe2, 0x00ffc, 0x007fc, 0x001fe, 0x0007e, 0x0001e, 0x00006,
0x00000, 0x00002, 0x0000e, 0x0003e, 0x000fe, 0x007fd, 0x00ffd, 0x07ff0,
0x0ffe3, 0x0fff5, 0x0fff6, 0x0fff7, 0x0fff8, 0x0fff9, 0x0fffa, 0x1fff6,
0x1fff7, 0x1fff8, 0x1fff9, 0x1fffa, 0x1fffb, 0x1fffc, 0x1fffd, 0x1fffe,
0x1ffff,
};
static const uint8_t f_huffman_env_bal_1_5dB_bits[49] = {
18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 16,
17, 14, 11, 11, 8, 7, 4, 2,
1, 3, 5, 6, 9, 11, 12, 15,
16, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 19,
19,
};
static const uint32_t f_huffman_env_bal_1_5dB_codes[49] = {
0x3ffe2, 0x3ffe3, 0x3ffe4, 0x3ffe5, 0x3ffe6, 0x3ffe7, 0x3ffe8, 0x3ffe9,
0x3ffea, 0x3ffeb, 0x3ffec, 0x3ffed, 0x3ffee, 0x3ffef, 0x3fff0, 0x0fff7,
0x1fff0, 0x03ffc, 0x007fe, 0x007fc, 0x000fe, 0x0007e, 0x0000e, 0x00002,
0x00000, 0x00006, 0x0001e, 0x0003e, 0x001fe, 0x007fd, 0x00ffe, 0x07ffa,
0x0fff6, 0x3fff1, 0x3fff2, 0x3fff3, 0x3fff4, 0x3fff5, 0x3fff6, 0x3fff7,
0x3fff8, 0x3fff9, 0x3fffa, 0x3fffb, 0x3fffc, 0x3fffd, 0x3fffe, 0x7fffe,
0x7ffff,
};
static const uint8_t t_huffman_env_3_0dB_bits[63] = {
18, 18, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 17, 16, 16, 16, 14, 14, 14,
13, 12, 11, 8, 6, 4, 2, 1,
3, 5, 7, 9, 11, 13, 14, 14,
15, 16, 17, 18, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19,
};
static const uint32_t t_huffman_env_3_0dB_codes[63] = {
0x3ffed, 0x3ffee, 0x7ffde, 0x7ffdf, 0x7ffe0, 0x7ffe1, 0x7ffe2, 0x7ffe3,
0x7ffe4, 0x7ffe5, 0x7ffe6, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb,
0x7ffec, 0x1fff4, 0x0fff7, 0x0fff9, 0x0fff8, 0x03ffb, 0x03ffa, 0x03ff8,
0x01ffa, 0x00ffc, 0x007fc, 0x000fe, 0x0003e, 0x0000e, 0x00002, 0x00000,
0x00006, 0x0001e, 0x0007e, 0x001fe, 0x007fd, 0x01ffb, 0x03ff9, 0x03ffc,
0x07ffa, 0x0fff6, 0x1fff5, 0x3ffec, 0x7ffed, 0x7ffee, 0x7ffef, 0x7fff0,
0x7fff1, 0x7fff2, 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6, 0x7fff7, 0x7fff8,
0x7fff9, 0x7fffa, 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe, 0x7ffff,
};
static const uint8_t f_huffman_env_3_0dB_bits[63] = {
20, 20, 20, 20, 20, 20, 20, 18,
19, 19, 19, 19, 18, 18, 20, 19,
17, 18, 17, 16, 16, 15, 14, 12,
11, 10, 9, 8, 6, 4, 2, 1,
3, 5, 8, 9, 10, 11, 12, 13,
14, 15, 15, 16, 16, 17, 17, 18,
18, 18, 20, 19, 19, 19, 20, 19,
19, 20, 20, 20, 20, 20, 20,
};
static const uint32_t f_huffman_env_3_0dB_codes[63] = {
0xffff0, 0xffff1, 0xffff2, 0xffff3, 0xffff4, 0xffff5, 0xffff6, 0x3fff3,
0x7fff5, 0x7ffee, 0x7ffef, 0x7fff6, 0x3fff4, 0x3fff2, 0xffff7, 0x7fff0,
0x1fff5, 0x3fff0, 0x1fff4, 0x0fff7, 0x0fff6, 0x07ff8, 0x03ffb, 0x00ffd,
0x007fd, 0x003fd, 0x001fd, 0x000fd, 0x0003e, 0x0000e, 0x00002, 0x00000,
0x00006, 0x0001e, 0x000fc, 0x001fc, 0x003fc, 0x007fc, 0x00ffc, 0x01ffc,
0x03ffa, 0x07ff9, 0x07ffa, 0x0fff8, 0x0fff9, 0x1fff6, 0x1fff7, 0x3fff5,
0x3fff6, 0x3fff1, 0xffff8, 0x7fff1, 0x7fff2, 0x7fff3, 0xffff9, 0x7fff7,
0x7fff4, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe, 0xfffff,
};
static const uint8_t t_huffman_env_bal_3_0dB_bits[25] = {
13, 13, 13, 13, 13, 13, 13, 12,
8, 7, 4, 3, 1, 2, 5, 6,
9, 13, 13, 13, 13, 13, 13, 14,
14,
};
static const uint16_t t_huffman_env_bal_3_0dB_codes[25] = {
0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x0ff8,
0x00fe, 0x007e, 0x000e, 0x0006, 0x0000, 0x0002, 0x001e, 0x003e,
0x01fe, 0x1ff9, 0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe,
0x3fff,
};
static const uint8_t f_huffman_env_bal_3_0dB_bits[25] = {
13, 13, 13, 13, 13, 14, 14, 11,
8, 7, 4, 2, 1, 3, 5, 6,
9, 12, 13, 14, 14, 14, 14, 14,
14,
};
static const uint16_t f_huffman_env_bal_3_0dB_codes[25] = {
0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, 0x3ff8, 0x3ff9, 0x07fc,
0x00fe, 0x007e, 0x000e, 0x0002, 0x0000, 0x0006, 0x001e, 0x003e,
0x01fe, 0x0ffa, 0x1ff6, 0x3ffa, 0x3ffb, 0x3ffc, 0x3ffd, 0x3ffe,
0x3fff,
};
static const uint8_t t_huffman_noise_3_0dB_bits[63] = {
13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 11, 8, 6, 4, 3, 1,
2, 5, 8, 10, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 14, 14,
};
static const uint16_t t_huffman_noise_3_0dB_codes[63] = {
0x1fce, 0x1fcf, 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5,
0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, 0x1fdc, 0x1fdd,
0x1fde, 0x1fdf, 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5,
0x1fe6, 0x1fe7, 0x07f2, 0x00fd, 0x003e, 0x000e, 0x0006, 0x0000,
0x0002, 0x001e, 0x00fc, 0x03f8, 0x1fcc, 0x1fe8, 0x1fe9, 0x1fea,
0x1feb, 0x1fec, 0x1fcd, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1,
0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9,
0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe, 0x3fff,
};
static const uint8_t t_huffman_noise_bal_3_0dB_bits[25] = {
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 5, 2, 1, 3, 6, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8,
};
static const uint8_t t_huffman_noise_bal_3_0dB_codes[25] = {
0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
0xf4, 0xf5, 0x1c, 0x02, 0x00, 0x06, 0x3a, 0xf6,
0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
0xff,
};
static const int8_t sbr_offset[6][16] = {
{-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}, // fs_sbr = 16000 Hz
{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13}, // fs_sbr = 22050 Hz
{-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}, // fs_sbr = 24000 Hz
{-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}, // fs_sbr = 32000 Hz
{-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20}, // 44100 Hz <= fs_sbr <= 64000 Hz
{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24}, // 64000 Hz < fs_sbr
};
///< window coefficients for analysis/synthesis QMF banks
static DECLARE_ALIGNED(32, float, sbr_qmf_window_ds)[320];
static DECLARE_ALIGNED(32, float, sbr_qmf_window_us)[640] = {
0.0000000000, -0.0005525286, -0.0005617692, -0.0004947518,
-0.0004875227, -0.0004893791, -0.0005040714, -0.0005226564,
-0.0005466565, -0.0005677802, -0.0005870930, -0.0006132747,
-0.0006312493, -0.0006540333, -0.0006777690, -0.0006941614,
-0.0007157736, -0.0007255043, -0.0007440941, -0.0007490598,
-0.0007681371, -0.0007724848, -0.0007834332, -0.0007779869,
-0.0007803664, -0.0007801449, -0.0007757977, -0.0007630793,
-0.0007530001, -0.0007319357, -0.0007215391, -0.0006917937,
-0.0006650415, -0.0006341594, -0.0005946118, -0.0005564576,
-0.0005145572, -0.0004606325, -0.0004095121, -0.0003501175,
-0.0002896981, -0.0002098337, -0.0001446380, -0.0000617334,
0.0000134949, 0.0001094383, 0.0002043017, 0.0002949531,
0.0004026540, 0.0005107388, 0.0006239376, 0.0007458025,
0.0008608443, 0.0009885988, 0.0011250155, 0.0012577884,
0.0013902494, 0.0015443219, 0.0016868083, 0.0018348265,
0.0019841140, 0.0021461583, 0.0023017254, 0.0024625616,
0.0026201758, 0.0027870464, 0.0029469447, 0.0031125420,
0.0032739613, 0.0034418874, 0.0036008268, 0.0037603922,
0.0039207432, 0.0040819753, 0.0042264269, 0.0043730719,
0.0045209852, 0.0046606460, 0.0047932560, 0.0049137603,
0.0050393022, 0.0051407353, 0.0052461166, 0.0053471681,
0.0054196775, 0.0054876040, 0.0055475714, 0.0055938023,
0.0056220643, 0.0056455196, 0.0056389199, 0.0056266114,
0.0055917128, 0.0055404363, 0.0054753783, 0.0053838975,
0.0052715758, 0.0051382275, 0.0049839687, 0.0048109469,
0.0046039530, 0.0043801861, 0.0041251642, 0.0038456408,
0.0035401246, 0.0032091885, 0.0028446757, 0.0024508540,
0.0020274176, 0.0015784682, 0.0010902329, 0.0005832264,
0.0000276045, -0.0005464280, -0.0011568135, -0.0018039472,
-0.0024826723, -0.0031933778, -0.0039401124, -0.0047222596,
-0.0055337211, -0.0063792293, -0.0072615816, -0.0081798233,
-0.0091325329, -0.0101150215, -0.0111315548, -0.0121849995,
0.0132718220, 0.0143904666, 0.0155405553, 0.0167324712,
0.0179433381, 0.0191872431, 0.0204531793, 0.0217467550,
0.0230680169, 0.0244160992, 0.0257875847, 0.0271859429,
0.0286072173, 0.0300502657, 0.0315017608, 0.0329754081,
0.0344620948, 0.0359697560, 0.0374812850, 0.0390053679,
0.0405349170, 0.0420649094, 0.0436097542, 0.0451488405,
0.0466843027, 0.0482165720, 0.0497385755, 0.0512556155,
0.0527630746, 0.0542452768, 0.0557173648, 0.0571616450,
0.0585915683, 0.0599837480, 0.0613455171, 0.0626857808,
0.0639715898, 0.0652247106, 0.0664367512, 0.0676075985,
0.0687043828, 0.0697630244, 0.0707628710, 0.0717002673,
0.0725682583, 0.0733620255, 0.0741003642, 0.0747452558,
0.0753137336, 0.0758008358, 0.0761992479, 0.0764992170,
0.0767093490, 0.0768173975, 0.0768230011, 0.0767204924,
0.0765050718, 0.0761748321, 0.0757305756, 0.0751576255,
0.0744664394, 0.0736406005, 0.0726774642, 0.0715826364,
0.0703533073, 0.0689664013, 0.0674525021, 0.0657690668,
0.0639444805, 0.0619602779, 0.0598166570, 0.0575152691,
0.0550460034, 0.0524093821, 0.0495978676, 0.0466303305,
0.0434768782, 0.0401458278, 0.0366418116, 0.0329583930,
0.0290824006, 0.0250307561, 0.0207997072, 0.0163701258,
0.0117623832, 0.0069636862, 0.0019765601, -0.0032086896,
-0.0085711749, -0.0141288827, -0.0198834129, -0.0258227288,
-0.0319531274, -0.0382776572, -0.0447806821, -0.0514804176,
-0.0583705326, -0.0654409853, -0.0726943300, -0.0801372934,
-0.0877547536, -0.0955533352, -0.1035329531, -0.1116826931,
-0.1200077984, -0.1285002850, -0.1371551761, -0.1459766491,
-0.1549607071, -0.1640958855, -0.1733808172, -0.1828172548,
-0.1923966745, -0.2021250176, -0.2119735853, -0.2219652696,
-0.2320690870, -0.2423016884, -0.2526480309, -0.2631053299,
-0.2736634040, -0.2843214189, -0.2950716717, -0.3059098575,
-0.3168278913, -0.3278113727, -0.3388722693, -0.3499914122,
0.3611589903, 0.3723795546, 0.3836350013, 0.3949211761,
0.4062317676, 0.4175696896, 0.4289119920, 0.4402553754,
0.4515996535, 0.4629308085, 0.4742453214, 0.4855253091,
0.4967708254, 0.5079817500, 0.5191234970, 0.5302240895,
0.5412553448, 0.5522051258, 0.5630789140, 0.5738524131,
0.5845403235, 0.5951123086, 0.6055783538, 0.6159109932,
0.6261242695, 0.6361980107, 0.6461269695, 0.6559016302,
0.6655139880, 0.6749663190, 0.6842353293, 0.6933282376,
0.7022388719, 0.7109410426, 0.7194462634, 0.7277448900,
0.7358211758, 0.7436827863, 0.7513137456, 0.7587080760,
0.7658674865, 0.7727780881, 0.7794287519, 0.7858353120,
0.7919735841, 0.7978466413, 0.8034485751, 0.8087695004,
0.8138191270, 0.8185776004, 0.8230419890, 0.8272275347,
0.8311038457, 0.8346937361, 0.8379717337, 0.8409541392,
0.8436238281, 0.8459818469, 0.8480315777, 0.8497805198,
0.8511971524, 0.8523047035, 0.8531020949, 0.8535720573,
0.8537385600,
};
/* First eight entries repeated at end to simplify SIMD implementations. */
const DECLARE_ALIGNED(16, float, ff_sbr_noise_table)[][2] = {
{-0.99948153278296, -0.59483417516607}, { 0.97113454393991, -0.67528515225647},
{ 0.14130051758487, -0.95090983575689}, {-0.47005496701697, -0.37340549728647},
{ 0.80705063769351, 0.29653668284408}, {-0.38981478896926, 0.89572605717087},
{-0.01053049862020, -0.66959058036166}, {-0.91266367957293, -0.11522938140034},
{ 0.54840422910309, 0.75221367176302}, { 0.40009252867955, -0.98929400334421},
{-0.99867974711855, -0.88147068645358}, {-0.95531076805040, 0.90908757154593},
{-0.45725933317144, -0.56716323646760}, {-0.72929675029275, -0.98008272727324},
{ 0.75622801399036, 0.20950329995549}, { 0.07069442601050, -0.78247898470706},
{ 0.74496252926055, -0.91169004445807}, {-0.96440182703856, -0.94739918296622},
{ 0.30424629369539, -0.49438267012479}, { 0.66565033746925, 0.64652935542491},
{ 0.91697008020594, 0.17514097332009}, {-0.70774918760427, 0.52548653416543},
{-0.70051415345560, -0.45340028808763}, {-0.99496513054797, -0.90071908066973},
{ 0.98164490790123, -0.77463155528697}, {-0.54671580548181, -0.02570928536004},
{-0.01689629065389, 0.00287506445732}, {-0.86110349531986, 0.42548583726477},
{-0.98892980586032, -0.87881132267556}, { 0.51756627678691, 0.66926784710139},
{-0.99635026409640, -0.58107730574765}, {-0.99969370862163, 0.98369989360250},
{ 0.55266258627194, 0.59449057465591}, { 0.34581177741673, 0.94879421061866},
{ 0.62664209577999, -0.74402970906471}, {-0.77149701404973, -0.33883658042801},
{-0.91592244254432, 0.03687901376713}, {-0.76285492357887, -0.91371867919124},
{ 0.79788337195331, -0.93180971199849}, { 0.54473080610200, -0.11919206037186},
{-0.85639281671058, 0.42429854760451}, {-0.92882402971423, 0.27871809078609},
{-0.11708371046774, -0.99800843444966}, { 0.21356749817493, -0.90716295627033},
{-0.76191692573909, 0.99768118356265}, { 0.98111043100884, -0.95854459734407},
{-0.85913269895572, 0.95766566168880}, {-0.93307242253692, 0.49431757696466},
{ 0.30485754879632, -0.70540034357529}, { 0.85289650925190, 0.46766131791044},
{ 0.91328082618125, -0.99839597361769}, {-0.05890199924154, 0.70741827819497},
{ 0.28398686150148, 0.34633555702188}, { 0.95258164539612, -0.54893416026939},
{-0.78566324168507, -0.75568541079691}, {-0.95789495447877, -0.20423194696966},
{ 0.82411158711197, 0.96654618432562}, {-0.65185446735885, -0.88734990773289},
{-0.93643603134666, 0.99870790442385}, { 0.91427159529618, -0.98290505544444},
{-0.70395684036886, 0.58796798221039}, { 0.00563771969365, 0.61768196727244},
{ 0.89065051931895, 0.52783352697585}, {-0.68683707712762, 0.80806944710339},
{ 0.72165342518718, -0.69259857349564}, {-0.62928247730667, 0.13627037407335},
{ 0.29938434065514, -0.46051329682246}, {-0.91781958879280, -0.74012716684186},
{ 0.99298717043688, 0.40816610075661}, { 0.82368298622748, -0.74036047190173},
{-0.98512833386833, -0.99972330709594}, {-0.95915368242257, -0.99237800466040},
{-0.21411126572790, -0.93424819052545}, {-0.68821476106884, -0.26892306315457},
{ 0.91851997982317, 0.09358228901785}, {-0.96062769559127, 0.36099095133739},
{ 0.51646184922287, -0.71373332873917}, { 0.61130721139669, 0.46950141175917},
{ 0.47336129371299, -0.27333178296162}, { 0.90998308703519, 0.96715662938132},
{ 0.44844799194357, 0.99211574628306}, { 0.66614891079092, 0.96590176169121},
{ 0.74922239129237, -0.89879858826087}, {-0.99571588506485, 0.52785521494349},
{ 0.97401082477563, -0.16855870075190}, { 0.72683747733879, -0.48060774432251},
{ 0.95432193457128, 0.68849603408441}, {-0.72962208425191, -0.76608443420917},
{-0.85359479233537, 0.88738125901579}, {-0.81412430338535, -0.97480768049637},
{-0.87930772356786, 0.74748307690436}, {-0.71573331064977, -0.98570608178923},
{ 0.83524300028228, 0.83702537075163}, {-0.48086065601423, -0.98848504923531},
{ 0.97139128574778, 0.80093621198236}, { 0.51992825347895, 0.80247631400510},
{-0.00848591195325, -0.76670128000486}, {-0.70294374303036, 0.55359910445577},
{-0.95894428168140, -0.43265504344783}, { 0.97079252950321, 0.09325857238682},
{-0.92404293670797, 0.85507704027855}, {-0.69506469500450, 0.98633412625459},
{ 0.26559203620024, 0.73314307966524}, { 0.28038443336943, 0.14537913654427},
{-0.74138124825523, 0.99310339807762}, {-0.01752795995444, -0.82616635284178},
{-0.55126773094930, -0.98898543862153}, { 0.97960898850996, -0.94021446752851},
{-0.99196309146936, 0.67019017358456}, {-0.67684928085260, 0.12631491649378},
{ 0.09140039465500, -0.20537731453108}, {-0.71658965751996, -0.97788200391224},
{ 0.81014640078925, 0.53722648362443}, { 0.40616991671205, -0.26469008598449},
{-0.67680188682972, 0.94502052337695}, { 0.86849774348749, -0.18333598647899},
{-0.99500381284851, -0.02634122068550}, { 0.84329189340667, 0.10406957462213},
{-0.09215968531446, 0.69540012101253}, { 0.99956173327206, -0.12358542001404},
{-0.79732779473535, -0.91582524736159}, { 0.96349973642406, 0.96640458041000},
{-0.79942778496547, 0.64323902822857}, {-0.11566039853896, 0.28587846253726},
{-0.39922954514662, 0.94129601616966}, { 0.99089197565987, -0.92062625581587},
{ 0.28631285179909, -0.91035047143603}, {-0.83302725605608, -0.67330410892084},
{ 0.95404443402072, 0.49162765398743}, {-0.06449863579434, 0.03250560813135},
{-0.99575054486311, 0.42389784469507}, {-0.65501142790847, 0.82546114655624},
{-0.81254441908887, -0.51627234660629}, {-0.99646369485481, 0.84490533520752},
{ 0.00287840603348, 0.64768261158166}, { 0.70176989408455, -0.20453028573322},
{ 0.96361882270190, 0.40706967140989}, {-0.68883758192426, 0.91338958840772},
{-0.34875585502238, 0.71472290693300}, { 0.91980081243087, 0.66507455644919},
{-0.99009048343881, 0.85868021604848}, { 0.68865791458395, 0.55660316809678},
{-0.99484402129368, -0.20052559254934}, { 0.94214511408023, -0.99696425367461},
{-0.67414626793544, 0.49548221180078}, {-0.47339353684664, -0.85904328834047},
{ 0.14323651387360, -0.94145598222488}, {-0.29268293575672, 0.05759224927952},
{ 0.43793861458754, -0.78904969892724}, {-0.36345126374441, 0.64874435357162},
{-0.08750604656825, 0.97686944362527}, {-0.96495267812511, -0.53960305946511},
{ 0.55526940659947, 0.78891523734774}, { 0.73538215752630, 0.96452072373404},
{-0.30889773919437, -0.80664389776860}, { 0.03574995626194, -0.97325616900959},
{ 0.98720684660488, 0.48409133691962}, {-0.81689296271203, -0.90827703628298},
{ 0.67866860118215, 0.81284503870856}, {-0.15808569732583, 0.85279555024382},
{ 0.80723395114371, -0.24717418514605}, { 0.47788757329038, -0.46333147839295},
{ 0.96367554763201, 0.38486749303242}, {-0.99143875716818, -0.24945277239809},
{ 0.83081876925833, -0.94780851414763}, {-0.58753191905341, 0.01290772389163},
{ 0.95538108220960, -0.85557052096538}, {-0.96490920476211, -0.64020970923102},
{-0.97327101028521, 0.12378128133110}, { 0.91400366022124, 0.57972471346930},
{-0.99925837363824, 0.71084847864067}, {-0.86875903507313, -0.20291699203564},
{-0.26240034795124, -0.68264554369108}, {-0.24664412953388, -0.87642273115183},
{ 0.02416275806869, 0.27192914288905}, { 0.82068619590515, -0.85087787994476},
{ 0.88547373760759, -0.89636802901469}, {-0.18173078152226, -0.26152145156800},
{ 0.09355476558534, 0.54845123045604}, {-0.54668414224090, 0.95980774020221},
{ 0.37050990604091, -0.59910140383171}, {-0.70373594262891, 0.91227665827081},
{-0.34600785879594, -0.99441426144200}, {-0.68774481731008, -0.30238837956299},
{-0.26843291251234, 0.83115668004362}, { 0.49072334613242, -0.45359708737775},
{ 0.38975993093975, 0.95515358099121}, {-0.97757125224150, 0.05305894580606},
{-0.17325552859616, -0.92770672250494}, { 0.99948035025744, 0.58285545563426},
{-0.64946246527458, 0.68645507104960}, {-0.12016920576437, -0.57147322153312},
{-0.58947456517751, -0.34847132454388}, {-0.41815140454465, 0.16276422358861},
{ 0.99885650204884, 0.11136095490444}, {-0.56649614128386, -0.90494866361587},
{ 0.94138021032330, 0.35281916733018}, {-0.75725076534641, 0.53650549640587},
{ 0.20541973692630, -0.94435144369918}, { 0.99980371023351, 0.79835913565599},
{ 0.29078277605775, 0.35393777921520}, {-0.62858772103030, 0.38765693387102},
{ 0.43440904467688, -0.98546330463232}, {-0.98298583762390, 0.21021524625209},
{ 0.19513029146934, -0.94239832251867}, {-0.95476662400101, 0.98364554179143},
{ 0.93379635304810, -0.70881994583682}, {-0.85235410573336, -0.08342347966410},
{-0.86425093011245, -0.45795025029466}, { 0.38879779059045, 0.97274429344593},
{ 0.92045124735495, -0.62433652524220}, { 0.89162532251878, 0.54950955570563},
{-0.36834336949252, 0.96458298020975}, { 0.93891760988045, -0.89968353740388},
{ 0.99267657565094, -0.03757034316958}, {-0.94063471614176, 0.41332338538963},
{ 0.99740224117019, -0.16830494996370}, {-0.35899413170555, -0.46633226649613},
{ 0.05237237274947, -0.25640361602661}, { 0.36703583957424, -0.38653265641875},
{ 0.91653180367913, -0.30587628726597}, { 0.69000803499316, 0.90952171386132},
{-0.38658751133527, 0.99501571208985}, {-0.29250814029851, 0.37444994344615},
{-0.60182204677608, 0.86779651036123}, {-0.97418588163217, 0.96468523666475},
{ 0.88461574003963, 0.57508405276414}, { 0.05198933055162, 0.21269661669964},
{-0.53499621979720, 0.97241553731237}, {-0.49429560226497, 0.98183865291903},
{-0.98935142339139, -0.40249159006933}, {-0.98081380091130, -0.72856895534041},
{-0.27338148835532, 0.99950922447209}, { 0.06310802338302, -0.54539587529618},
{-0.20461677199539, -0.14209977628489}, { 0.66223843141647, 0.72528579940326},
{-0.84764345483665, 0.02372316801261}, {-0.89039863483811, 0.88866581484602},
{ 0.95903308477986, 0.76744927173873}, { 0.73504123909879, -0.03747203173192},
{-0.31744434966056, -0.36834111883652}, {-0.34110827591623, 0.40211222807691},
{ 0.47803883714199, -0.39423219786288}, { 0.98299195879514, 0.01989791390047},
{-0.30963073129751, -0.18076720599336}, { 0.99992588229018, -0.26281872094289},
{-0.93149731080767, -0.98313162570490}, { 0.99923472302773, -0.80142993767554},
{-0.26024169633417, -0.75999759855752}, {-0.35712514743563, 0.19298963768574},
{-0.99899084509530, 0.74645156992493}, { 0.86557171579452, 0.55593866696299},
{ 0.33408042438752, 0.86185953874709}, { 0.99010736374716, 0.04602397576623},
{-0.66694269691195, -0.91643611810148}, { 0.64016792079480, 0.15649530836856},
{ 0.99570534804836, 0.45844586038111}, {-0.63431466947340, 0.21079116459234},
{-0.07706847005931, -0.89581437101329}, { 0.98590090577724, 0.88241721133981},
{ 0.80099335254678, -0.36851896710853}, { 0.78368131392666, 0.45506999802597},
{ 0.08707806671691, 0.80938994918745}, {-0.86811883080712, 0.39347308654705},
{-0.39466529740375, -0.66809432114456}, { 0.97875325649683, -0.72467840967746},
{-0.95038560288864, 0.89563219587625}, { 0.17005239424212, 0.54683053962658},
{-0.76910792026848, -0.96226617549298}, { 0.99743281016846, 0.42697157037567},
{ 0.95437383549973, 0.97002324109952}, { 0.99578905365569, -0.54106826257356},
{ 0.28058259829990, -0.85361420634036}, { 0.85256524470573, -0.64567607735589},
{-0.50608540105128, -0.65846015480300}, {-0.97210735183243, -0.23095213067791},
{ 0.95424048234441, -0.99240147091219}, {-0.96926570524023, 0.73775654896574},
{ 0.30872163214726, 0.41514960556126}, {-0.24523839572639, 0.63206633394807},
{-0.33813265086024, -0.38661779441897}, {-0.05826828420146, -0.06940774188029},
{-0.22898461455054, 0.97054853316316}, {-0.18509915019881, 0.47565762892084},
{-0.10488238045009, -0.87769947402394}, {-0.71886586182037, 0.78030982480538},
{ 0.99793873738654, 0.90041310491497}, { 0.57563307626120, -0.91034337352097},
{ 0.28909646383717, 0.96307783970534}, { 0.42188998312520, 0.48148651230437},
{ 0.93335049681047, -0.43537023883588}, {-0.97087374418267, 0.86636445711364},
{ 0.36722871286923, 0.65291654172961}, {-0.81093025665696, 0.08778370229363},
{-0.26240603062237, -0.92774095379098}, { 0.83996497984604, 0.55839849139647},
{-0.99909615720225, -0.96024605713970}, { 0.74649464155061, 0.12144893606462},
{-0.74774595569805, -0.26898062008959}, { 0.95781667469567, -0.79047927052628},
{ 0.95472308713099, -0.08588776019550}, { 0.48708332746299, 0.99999041579432},
{ 0.46332038247497, 0.10964126185063}, {-0.76497004940162, 0.89210929242238},
{ 0.57397389364339, 0.35289703373760}, { 0.75374316974495, 0.96705214651335},
{-0.59174397685714, -0.89405370422752}, { 0.75087906691890, -0.29612672982396},
{-0.98607857336230, 0.25034911730023}, {-0.40761056640505, -0.90045573444695},
{ 0.66929266740477, 0.98629493401748}, {-0.97463695257310, -0.00190223301301},
{ 0.90145509409859, 0.99781390365446}, {-0.87259289048043, 0.99233587353666},
{-0.91529461447692, -0.15698707534206}, {-0.03305738840705, -0.37205262859764},
{ 0.07223051368337, -0.88805001733626}, { 0.99498012188353, 0.97094358113387},
{-0.74904939500519, 0.99985483641521}, { 0.04585228574211, 0.99812337444082},
{-0.89054954257993, -0.31791913188064}, {-0.83782144651251, 0.97637632547466},
{ 0.33454804933804, -0.86231516800408}, {-0.99707579362824, 0.93237990079441},
{-0.22827527843994, 0.18874759397997}, { 0.67248046289143, -0.03646211390569},
{-0.05146538187944, -0.92599700120679}, { 0.99947295749905, 0.93625229707912},
{ 0.66951124390363, 0.98905825623893}, {-0.99602956559179, -0.44654715757688},
{ 0.82104905483590, 0.99540741724928}, { 0.99186510988782, 0.72023001312947},
{-0.65284592392918, 0.52186723253637}, { 0.93885443798188, -0.74895312615259},
{ 0.96735248738388, 0.90891816978629}, {-0.22225968841114, 0.57124029781228},
{-0.44132783753414, -0.92688840659280}, {-0.85694974219574, 0.88844532719844},
{ 0.91783042091762, -0.46356892383970}, { 0.72556974415690, -0.99899555770747},
{-0.99711581834508, 0.58211560180426}, { 0.77638976371966, 0.94321834873819},
{ 0.07717324253925, 0.58638399856595}, {-0.56049829194163, 0.82522301569036},
{ 0.98398893639988, 0.39467440420569}, { 0.47546946844938, 0.68613044836811},
{ 0.65675089314631, 0.18331637134880}, { 0.03273375457980, -0.74933109564108},
{-0.38684144784738, 0.51337349030406}, {-0.97346267944545, -0.96549364384098},
{-0.53282156061942, -0.91423265091354}, { 0.99817310731176, 0.61133572482148},
{-0.50254500772635, -0.88829338134294}, { 0.01995873238855, 0.85223515096765},
{ 0.99930381973804, 0.94578896296649}, { 0.82907767600783, -0.06323442598128},
{-0.58660709669728, 0.96840773806582}, {-0.17573736667267, -0.48166920859485},
{ 0.83434292401346, -0.13023450646997}, { 0.05946491307025, 0.20511047074866},
{ 0.81505484574602, -0.94685947861369}, {-0.44976380954860, 0.40894572671545},
{-0.89746474625671, 0.99846578838537}, { 0.39677256130792, -0.74854668609359},
{-0.07588948563079, 0.74096214084170}, { 0.76343198951445, 0.41746629422634},
{-0.74490104699626, 0.94725911744610}, { 0.64880119792759, 0.41336660830571},
{ 0.62319537462542, -0.93098313552599}, { 0.42215817594807, -0.07712787385208},
{ 0.02704554141885, -0.05417518053666}, { 0.80001773566818, 0.91542195141039},
{-0.79351832348816, -0.36208897989136}, { 0.63872359151636, 0.08128252493444},
{ 0.52890520960295, 0.60048872455592}, { 0.74238552914587, 0.04491915291044},
{ 0.99096131449250, -0.19451182854402}, {-0.80412329643109, -0.88513818199457},
{-0.64612616129736, 0.72198674804544}, { 0.11657770663191, -0.83662833815041},
{-0.95053182488101, -0.96939905138082}, {-0.62228872928622, 0.82767262846661},
{ 0.03004475787316, -0.99738896333384}, {-0.97987214341034, 0.36526129686425},
{-0.99986980746200, -0.36021610299715}, { 0.89110648599879, -0.97894250343044},
{ 0.10407960510582, 0.77357793811619}, { 0.95964737821728, -0.35435818285502},
{ 0.50843233159162, 0.96107691266205}, { 0.17006334670615, -0.76854025314829},
{ 0.25872675063360, 0.99893303933816}, {-0.01115998681937, 0.98496019742444},
{-0.79598702973261, 0.97138411318894}, {-0.99264708948101, -0.99542822402536},
{-0.99829663752818, 0.01877138824311}, {-0.70801016548184, 0.33680685948117},
{-0.70467057786826, 0.93272777501857}, { 0.99846021905254, -0.98725746254433},
{-0.63364968534650, -0.16473594423746}, {-0.16258217500792, -0.95939125400802},
{-0.43645594360633, -0.94805030113284}, {-0.99848471702976, 0.96245166923809},
{-0.16796458968998, -0.98987511890470}, {-0.87979225745213, -0.71725725041680},
{ 0.44183099021786, -0.93568974498761}, { 0.93310180125532, -0.99913308068246},
{-0.93941931782002, -0.56409379640356}, {-0.88590003188677, 0.47624600491382},
{ 0.99971463703691, -0.83889954253462}, {-0.75376385639978, 0.00814643438625},
{ 0.93887685615875, -0.11284528204636}, { 0.85126435782309, 0.52349251543547},
{ 0.39701421446381, 0.81779634174316}, {-0.37024464187437, -0.87071656222959},
{-0.36024828242896, 0.34655735648287}, {-0.93388812549209, -0.84476541096429},
{-0.65298804552119, -0.18439575450921}, { 0.11960319006843, 0.99899346780168},
{ 0.94292565553160, 0.83163906518293}, { 0.75081145286948, -0.35533223142265},
{ 0.56721979748394, -0.24076836414499}, { 0.46857766746029, -0.30140233457198},
{ 0.97312313923635, -0.99548191630031}, {-0.38299976567017, 0.98516909715427},
{ 0.41025800019463, 0.02116736935734}, { 0.09638062008048, 0.04411984381457},
{-0.85283249275397, 0.91475563922421}, { 0.88866808958124, -0.99735267083226},
{-0.48202429536989, -0.96805608884164}, { 0.27572582416567, 0.58634753335832},
{-0.65889129659168, 0.58835634138583}, { 0.98838086953732, 0.99994349600236},
{-0.20651349620689, 0.54593044066355}, {-0.62126416356920, -0.59893681700392},
{ 0.20320105410437, -0.86879180355289}, {-0.97790548600584, 0.96290806999242},
{ 0.11112534735126, 0.21484763313301}, {-0.41368337314182, 0.28216837680365},
{ 0.24133038992960, 0.51294362630238}, {-0.66393410674885, -0.08249679629081},
{-0.53697829178752, -0.97649903936228}, {-0.97224737889348, 0.22081333579837},
{ 0.87392477144549, -0.12796173740361}, { 0.19050361015753, 0.01602615387195},
{-0.46353441212724, -0.95249041539006}, {-0.07064096339021, -0.94479803205886},
{-0.92444085484466, -0.10457590187436}, {-0.83822593578728, -0.01695043208885},
{ 0.75214681811150, -0.99955681042665}, {-0.42102998829339, 0.99720941999394},
{-0.72094786237696, -0.35008961934255}, { 0.78843311019251, 0.52851398958271},
{ 0.97394027897442, -0.26695944086561}, { 0.99206463477946, -0.57010120849429},
{ 0.76789609461795, -0.76519356730966}, {-0.82002421836409, -0.73530179553767},
{ 0.81924990025724, 0.99698425250579}, {-0.26719850873357, 0.68903369776193},
{-0.43311260380975, 0.85321815947490}, { 0.99194979673836, 0.91876249766422},
{-0.80692001248487, -0.32627540663214}, { 0.43080003649976, -0.21919095636638},
{ 0.67709491937357, -0.95478075822906}, { 0.56151770568316, -0.70693811747778},
{ 0.10831862810749, -0.08628837174592}, { 0.91229417540436, -0.65987351408410},
{-0.48972893932274, 0.56289246362686}, {-0.89033658689697, -0.71656563987082},
{ 0.65269447475094, 0.65916004833932}, { 0.67439478141121, -0.81684380846796},
{-0.47770832416973, -0.16789556203025}, {-0.99715979260878, -0.93565784007648},
{-0.90889593602546, 0.62034397054380}, {-0.06618622548177, -0.23812217221359},
{ 0.99430266919728, 0.18812555317553}, { 0.97686402381843, -0.28664534366620},
{ 0.94813650221268, -0.97506640027128}, {-0.95434497492853, -0.79607978501983},
{-0.49104783137150, 0.32895214359663}, { 0.99881175120751, 0.88993983831354},
{ 0.50449166760303, -0.85995072408434}, { 0.47162891065108, -0.18680204049569},
{-0.62081581361840, 0.75000676218956}, {-0.43867015250812, 0.99998069244322},
{ 0.98630563232075, -0.53578899600662}, {-0.61510362277374, -0.89515019899997},
{-0.03841517601843, -0.69888815681179}, {-0.30102157304644, -0.07667808922205},
{ 0.41881284182683, 0.02188098922282}, {-0.86135454941237, 0.98947480909359},
{ 0.67226861393788, -0.13494389011014}, {-0.70737398842068, -0.76547349325992},
{ 0.94044946687963, 0.09026201157416}, {-0.82386352534327, 0.08924768823676},
{-0.32070666698656, 0.50143421908753}, { 0.57593163224487, -0.98966422921509},
{-0.36326018419965, 0.07440243123228}, { 0.99979044674350, -0.14130287347405},
{-0.92366023326932, -0.97979298068180}, {-0.44607178518598, -0.54233252016394},
{ 0.44226800932956, 0.71326756742752}, { 0.03671907158312, 0.63606389366675},
{ 0.52175424682195, -0.85396826735705}, {-0.94701139690956, -0.01826348194255},
{-0.98759606946049, 0.82288714303073}, { 0.87434794743625, 0.89399495655433},
{-0.93412041758744, 0.41374052024363}, { 0.96063943315511, 0.93116709541280},
{ 0.97534253457837, 0.86150930812689}, { 0.99642466504163, 0.70190043427512},
{-0.94705089665984, -0.29580042814306}, { 0.91599807087376, -0.98147830385781},
// Start of duplicated table
{-0.99948153278296, -0.59483417516607}, { 0.97113454393991, -0.67528515225647},
{ 0.14130051758487, -0.95090983575689}, {-0.47005496701697, -0.37340549728647},
{ 0.80705063769351, 0.29653668284408}, {-0.38981478896926, 0.89572605717087},
{-0.01053049862020, -0.66959058036166}, {-0.91266367957293, -0.11522938140034},
};
#endif /* AVCODEC_AACSBRDATA_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
/*
* AAC data declarations
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail 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
*/
/**
* @file
* AAC data declarations
* @author Oded Shimon ( ods15 ods15 dyndns org )
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
#ifndef AVCODEC_AACTAB_H
#define AVCODEC_AACTAB_H
#include "libavutil/mem.h"
#include "aac.h"
#include "aac_tablegen_decl.h"
#include <stdint.h>
/* NOTE:
* Tables in this file are used by the AAC decoder and will be used by the AAC
* encoder.
*/
/* @name window coefficients
* @{
*/
DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_1024)[1024];
DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_512 )[512];
DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128];
const DECLARE_ALIGNED(32, extern float, ff_aac_eld_window)[1920];
// @}
/* @name number of scalefactor window bands for long and short transform windows respectively
* @{
*/
extern const uint8_t ff_aac_num_swb_1024[];
extern const uint8_t ff_aac_num_swb_512 [];
extern const uint8_t ff_aac_num_swb_128 [];
// @}
extern const uint8_t ff_aac_pred_sfb_max [];
extern const uint32_t ff_aac_scalefactor_code[121];
extern const uint8_t ff_aac_scalefactor_bits[121];
extern const uint16_t * const ff_aac_spectral_codes[11];
extern const uint8_t * const ff_aac_spectral_bits [11];
extern const uint16_t ff_aac_spectral_sizes[11];
extern const float *ff_aac_codebook_vectors[];
extern const float *ff_aac_codebook_vector_vals[];
extern const uint16_t *ff_aac_codebook_vector_idx[];
extern const uint16_t * const ff_swb_offset_1024[13];
extern const uint16_t * const ff_swb_offset_512 [13];
extern const uint16_t * const ff_swb_offset_128 [13];
extern const uint8_t ff_tns_max_bands_1024[13];
extern const uint8_t ff_tns_max_bands_128 [13];
#endif /* AVCODEC_AACTAB_H */

View File

@@ -0,0 +1,47 @@
/*
* 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
* AAN (Arai Agui Aakajima) (I)DCT tables
*/
#include <stdint.h>
const uint16_t ff_aanscales[64] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
8867 , 12299, 11585, 10426, 8867, 6967, 4799, 2446,
4520 , 6270, 5906, 5315, 4520, 3552, 2446, 1247
};
const uint16_t ff_inv_aanscales[64] = {
4096, 2953, 3135, 3483, 4096, 5213, 7568, 14846,
2953, 2129, 2260, 2511, 2953, 3759, 5457, 10703,
3135, 2260, 2399, 2666, 3135, 3990, 5793, 11363,
3483, 2511, 2666, 2962, 3483, 4433, 6436, 12625,
4096, 2953, 3135, 3483, 4096, 5213, 7568, 14846,
5213, 3759, 3990, 4433, 5213, 6635, 9633, 18895,
7568, 5457, 5793, 6436, 7568, 9633, 13985, 27432,
14846, 10703, 11363, 12625, 14846, 18895, 27432, 53809,
};

View File

@@ -0,0 +1,32 @@
/*
* 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
* AAN (Arai Agui Nakajima) (I)DCT tables
*/
#ifndef AVCODEC_AANDCTTAB_H
#define AVCODEC_AANDCTTAB_H
#include <stdint.h>
extern const uint16_t ff_aanscales[64];
extern const uint16_t ff_inv_aanscales[64];
#endif /* AVCODEC_AANDCTTAB_H */

View File

@@ -0,0 +1,162 @@
/*
* Autodesk RLE Decoder
* Copyright (C) 2005 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
*/
/**
* @file
* Autodesk RLE Video Decoder by Konstantin Shishkov
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "avcodec.h"
#include "internal.h"
#include "msrledec.h"
typedef struct AascContext {
AVCodecContext *avctx;
GetByteContext gb;
AVFrame *frame;
uint32_t palette[AVPALETTE_COUNT];
int palette_size;
} AascContext;
static av_cold int aasc_decode_init(AVCodecContext *avctx)
{
AascContext *s = avctx->priv_data;
uint8_t *ptr;
int i;
s->avctx = avctx;
switch (avctx->bits_per_coded_sample) {
case 8:
avctx->pix_fmt = AV_PIX_FMT_PAL8;
ptr = avctx->extradata;
s->palette_size = FFMIN(avctx->extradata_size, AVPALETTE_SIZE);
for (i = 0; i < s->palette_size / 4; i++) {
s->palette[i] = 0xFFU << 24 | AV_RL32(ptr);
ptr += 4;
}
break;
case 16:
avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
break;
case 24:
avctx->pix_fmt = AV_PIX_FMT_BGR24;
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", avctx->bits_per_coded_sample);
return -1;
}
s->frame = av_frame_alloc();
if (!s->frame)
return AVERROR(ENOMEM);
return 0;
}
static int aasc_decode_frame(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
AascContext *s = avctx->priv_data;
int compr, i, stride, psize, ret;
if (buf_size < 4) {
av_log(avctx, AV_LOG_ERROR, "frame too short\n");
return AVERROR_INVALIDDATA;
}
if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
return ret;
compr = AV_RL32(buf);
buf += 4;
buf_size -= 4;
psize = avctx->bits_per_coded_sample / 8;
switch (avctx->codec_tag) {
case MKTAG('A', 'A', 'S', '4'):
bytestream2_init(&s->gb, buf - 4, buf_size + 4);
ff_msrle_decode(avctx, (AVPicture*)s->frame, 8, &s->gb);
break;
case MKTAG('A', 'A', 'S', 'C'):
switch (compr) {
case 0:
stride = (avctx->width * psize + psize) & ~psize;
if (buf_size < stride * avctx->height)
return AVERROR_INVALIDDATA;
for (i = avctx->height - 1; i >= 0; i--) {
memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize);
buf += stride;
buf_size -= stride;
}
break;
case 1:
bytestream2_init(&s->gb, buf, buf_size);
ff_msrle_decode(avctx, (AVPicture*)s->frame, 8, &s->gb);
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr);
return AVERROR_INVALIDDATA;
}
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unknown FourCC: %X\n", avctx->codec_tag);
return -1;
}
if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
memcpy(s->frame->data[1], s->palette, s->palette_size);
*got_frame = 1;
if ((ret = av_frame_ref(data, s->frame)) < 0)
return ret;
/* report that the buffer was completely consumed */
return buf_size;
}
static av_cold int aasc_decode_end(AVCodecContext *avctx)
{
AascContext *s = avctx->priv_data;
av_frame_free(&s->frame);
return 0;
}
AVCodec ff_aasc_decoder = {
.name = "aasc",
.long_name = NULL_IF_CONFIG_SMALL("Autodesk RLE"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_AASC,
.priv_data_size = sizeof(AascContext),
.init = aasc_decode_init,
.close = aasc_decode_end,
.decode = aasc_decode_frame,
.capabilities = CODEC_CAP_DR1,
};

View File

@@ -0,0 +1,231 @@
/*
* Common code between the AC-3 encoder and decoder
* Copyright (c) 2000 Fabrice Bellard
*
* 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
* Common code between the AC-3 encoder and decoder.
*/
#include "avcodec.h"
#include "ac3.h"
#include "get_bits.h"
/**
* Starting frequency coefficient bin for each critical band.
*/
const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1] = {
0, 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, 31,
34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
79, 85, 97, 109, 121, 133, 157, 181, 205, 229, 253
};
#if CONFIG_HARDCODED_TABLES
/**
* Map each frequency coefficient bin to the critical band that contains it.
*/
const uint8_t ff_ac3_bin_to_band_tab[253] = {
0,
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, 28, 28, 29, 29, 29, 30, 30, 30,
31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34,
35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36,
37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38,
39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
};
#else /* CONFIG_HARDCODED_TABLES */
uint8_t ff_ac3_bin_to_band_tab[253];
#endif
static inline int calc_lowcomp1(int a, int b0, int b1, int c)
{
if ((b0 + 256) == b1) {
a = c;
} else if (b0 > b1) {
a = FFMAX(a - 64, 0);
}
return a;
}
static inline int calc_lowcomp(int a, int b0, int b1, int bin)
{
if (bin < 7) {
return calc_lowcomp1(a, b0, b1, 384);
} else if (bin < 20) {
return calc_lowcomp1(a, b0, b1, 320);
} else {
return FFMAX(a - 128, 0);
}
}
void ff_ac3_bit_alloc_calc_psd(int8_t *exp, int start, int end, int16_t *psd,
int16_t *band_psd)
{
int bin, band;
/* exponent mapping to PSD */
for (bin = start; bin < end; bin++) {
psd[bin]=(3072 - (exp[bin] << 7));
}
/* PSD integration */
bin = start;
band = ff_ac3_bin_to_band_tab[start];
do {
int v = psd[bin++];
int band_end = FFMIN(ff_ac3_band_start_tab[band+1], end);
for (; bin < band_end; bin++) {
int max = FFMAX(v, psd[bin]);
/* logadd */
int adr = FFMIN(max - ((v + psd[bin] + 1) >> 1), 255);
v = max + ff_ac3_log_add_tab[adr];
}
band_psd[band++] = v;
} while (end > ff_ac3_band_start_tab[band]);
}
int ff_ac3_bit_alloc_calc_mask(AC3BitAllocParameters *s, int16_t *band_psd,
int start, int end, int fast_gain, int is_lfe,
int dba_mode, int dba_nsegs, uint8_t *dba_offsets,
uint8_t *dba_lengths, uint8_t *dba_values,
int16_t *mask)
{
int16_t excite[AC3_CRITICAL_BANDS]; /* excitation */
int band;
int band_start, band_end, begin, end1;
int lowcomp, fastleak, slowleak;
/* excitation function */
band_start = ff_ac3_bin_to_band_tab[start];
band_end = ff_ac3_bin_to_band_tab[end-1] + 1;
if (band_start == 0) {
lowcomp = 0;
lowcomp = calc_lowcomp1(lowcomp, band_psd[0], band_psd[1], 384);
excite[0] = band_psd[0] - fast_gain - lowcomp;
lowcomp = calc_lowcomp1(lowcomp, band_psd[1], band_psd[2], 384);
excite[1] = band_psd[1] - fast_gain - lowcomp;
begin = 7;
for (band = 2; band < 7; band++) {
if (!(is_lfe && band == 6))
lowcomp = calc_lowcomp1(lowcomp, band_psd[band], band_psd[band+1], 384);
fastleak = band_psd[band] - fast_gain;
slowleak = band_psd[band] - s->slow_gain;
excite[band] = fastleak - lowcomp;
if (!(is_lfe && band == 6)) {
if (band_psd[band] <= band_psd[band+1]) {
begin = band + 1;
break;
}
}
}
end1 = FFMIN(band_end, 22);
for (band = begin; band < end1; band++) {
if (!(is_lfe && band == 6))
lowcomp = calc_lowcomp(lowcomp, band_psd[band], band_psd[band+1], band);
fastleak = FFMAX(fastleak - s->fast_decay, band_psd[band] - fast_gain);
slowleak = FFMAX(slowleak - s->slow_decay, band_psd[band] - s->slow_gain);
excite[band] = FFMAX(fastleak - lowcomp, slowleak);
}
begin = 22;
} else {
/* coupling channel */
begin = band_start;
fastleak = (s->cpl_fast_leak << 8) + 768;
slowleak = (s->cpl_slow_leak << 8) + 768;
}
for (band = begin; band < band_end; band++) {
fastleak = FFMAX(fastleak - s->fast_decay, band_psd[band] - fast_gain);
slowleak = FFMAX(slowleak - s->slow_decay, band_psd[band] - s->slow_gain);
excite[band] = FFMAX(fastleak, slowleak);
}
/* compute masking curve */
for (band = band_start; band < band_end; band++) {
int tmp = s->db_per_bit - band_psd[band];
if (tmp > 0) {
excite[band] += tmp >> 2;
}
mask[band] = FFMAX(ff_ac3_hearing_threshold_tab[band >> s->sr_shift][s->sr_code], excite[band]);
}
/* delta bit allocation */
if (dba_mode == DBA_REUSE || dba_mode == DBA_NEW) {
int i, seg, delta;
if (dba_nsegs > 8)
return -1;
band = band_start;
for (seg = 0; seg < dba_nsegs; seg++) {
band += dba_offsets[seg];
if (band >= AC3_CRITICAL_BANDS || dba_lengths[seg] > AC3_CRITICAL_BANDS-band)
return -1;
if (dba_values[seg] >= 4) {
delta = (dba_values[seg] - 3) << 7;
} else {
delta = (dba_values[seg] - 4) << 7;
}
for (i = 0; i < dba_lengths[seg]; i++) {
mask[band++] += delta;
}
}
}
return 0;
}
/**
* Initialize some tables.
* note: This function must remain thread safe because it is called by the
* AVParser init code.
*/
av_cold void ff_ac3_common_init(void)
{
#if !CONFIG_HARDCODED_TABLES
/* compute ff_ac3_bin_to_band_tab from ff_ac3_band_start_tab */
int bin = 0, band;
for (band = 0; band < AC3_CRITICAL_BANDS; band++) {
int band_end = ff_ac3_band_start_tab[band+1];
while (bin < band_end)
ff_ac3_bin_to_band_tab[bin++] = band;
}
#endif /* !CONFIG_HARDCODED_TABLES */
}

View File

@@ -0,0 +1,181 @@
/*
* Common code between the AC-3 encoder and decoder
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* 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
* Common code between the AC-3 encoder and decoder.
*/
#ifndef AVCODEC_AC3_H
#define AVCODEC_AC3_H
#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */
#define AC3_MAX_CHANNELS 7 /**< maximum number of channels, including coupling channel */
#define CPL_CH 0 /**< coupling channel index */
#define AC3_MAX_COEFS 256
#define AC3_BLOCK_SIZE 256
#define AC3_MAX_BLOCKS 6
#define AC3_FRAME_SIZE (AC3_MAX_BLOCKS * 256)
#define AC3_WINDOW_SIZE (AC3_BLOCK_SIZE * 2)
#define AC3_CRITICAL_BANDS 50
#define AC3_MAX_CPL_BANDS 18
#include "libavutil/opt.h"
#include "avcodec.h"
#include "ac3tab.h"
/* exponent encoding strategy */
#define EXP_REUSE 0
#define EXP_NEW 1
#define EXP_D15 1
#define EXP_D25 2
#define EXP_D45 3
/* pre-defined gain values */
#define LEVEL_PLUS_3DB 1.4142135623730950
#define LEVEL_PLUS_1POINT5DB 1.1892071150027209
#define LEVEL_MINUS_1POINT5DB 0.8408964152537145
#define LEVEL_MINUS_3DB 0.7071067811865476
#define LEVEL_MINUS_4POINT5DB 0.5946035575013605
#define LEVEL_MINUS_6DB 0.5000000000000000
#define LEVEL_MINUS_9DB 0.3535533905932738
#define LEVEL_ZERO 0.0000000000000000
#define LEVEL_ONE 1.0000000000000000
/** Delta bit allocation strategy */
typedef enum {
DBA_REUSE = 0,
DBA_NEW,
DBA_NONE,
DBA_RESERVED
} AC3DeltaStrategy;
/** Channel mode (audio coding mode) */
typedef enum {
AC3_CHMODE_DUALMONO = 0,
AC3_CHMODE_MONO,
AC3_CHMODE_STEREO,
AC3_CHMODE_3F,
AC3_CHMODE_2F1R,
AC3_CHMODE_3F1R,
AC3_CHMODE_2F2R,
AC3_CHMODE_3F2R
} AC3ChannelMode;
typedef struct AC3BitAllocParameters {
int sr_code;
int sr_shift;
int slow_gain, slow_decay, fast_decay, db_per_bit, floor;
int cpl_fast_leak, cpl_slow_leak;
} AC3BitAllocParameters;
/**
* @struct AC3HeaderInfo
* Coded AC-3 header values up to the lfeon element, plus derived values.
*/
typedef struct AC3HeaderInfo {
/** @name Coded elements
* @{
*/
uint16_t sync_word;
uint16_t crc1;
uint8_t sr_code;
uint8_t bitstream_id;
uint8_t bitstream_mode;
uint8_t channel_mode;
uint8_t lfe_on;
uint8_t frame_type;
int substreamid; ///< substream identification
int center_mix_level; ///< Center mix level index
int surround_mix_level; ///< Surround mix level index
uint16_t channel_map;
int num_blocks; ///< number of audio blocks
/** @} */
/** @name Derived values
* @{
*/
uint8_t sr_shift;
uint16_t sample_rate;
uint32_t bit_rate;
uint8_t channels;
uint16_t frame_size;
uint64_t channel_layout;
/** @} */
} AC3HeaderInfo;
typedef enum {
EAC3_FRAME_TYPE_INDEPENDENT = 0,
EAC3_FRAME_TYPE_DEPENDENT,
EAC3_FRAME_TYPE_AC3_CONVERT,
EAC3_FRAME_TYPE_RESERVED
} EAC3FrameType;
void ff_ac3_common_init(void);
/**
* Calculate the log power-spectral density of the input signal.
* This gives a rough estimate of signal power in the frequency domain by using
* the spectral envelope (exponents). The psd is also separately grouped
* into critical bands for use in the calculating the masking curve.
* 128 units in psd = -6 dB. The dbknee parameter in AC3BitAllocParameters
* determines the reference level.
*
* @param[in] exp frequency coefficient exponents
* @param[in] start starting bin location
* @param[in] end ending bin location
* @param[out] psd signal power for each frequency bin
* @param[out] band_psd signal power for each critical band
*/
void ff_ac3_bit_alloc_calc_psd(int8_t *exp, int start, int end, int16_t *psd,
int16_t *band_psd);
/**
* Calculate the masking curve.
* First, the excitation is calculated using parameters in s and the signal
* power in each critical band. The excitation is compared with a predefined
* hearing threshold table to produce the masking curve. If delta bit
* allocation information is provided, it is used for adjusting the masking
* curve, usually to give a closer match to a better psychoacoustic model.
*
* @param[in] s adjustable bit allocation parameters
* @param[in] band_psd signal power for each critical band
* @param[in] start starting bin location
* @param[in] end ending bin location
* @param[in] fast_gain fast gain (estimated signal-to-mask ratio)
* @param[in] is_lfe whether or not the channel being processed is the LFE
* @param[in] dba_mode delta bit allocation mode (none, reuse, or new)
* @param[in] dba_nsegs number of delta segments
* @param[in] dba_offsets location offsets for each segment
* @param[in] dba_lengths length of each segment
* @param[in] dba_values delta bit allocation for each segment
* @param[out] mask calculated masking curve
* @return returns 0 for success, non-zero for error
*/
int ff_ac3_bit_alloc_calc_mask(AC3BitAllocParameters *s, int16_t *band_psd,
int start, int end, int fast_gain, int is_lfe,
int dba_mode, int dba_nsegs, uint8_t *dba_offsets,
uint8_t *dba_lengths, uint8_t *dba_values,
int16_t *mask);
#endif /* AVCODEC_AC3_H */

View File

@@ -0,0 +1,194 @@
/*
* AC-3 parser
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 "libavutil/channel_layout.h"
#include "parser.h"
#include "ac3_parser.h"
#include "aac_ac3_parser.h"
#include "get_bits.h"
#define AC3_HEADER_SIZE 7
static const uint8_t eac3_blocks[4] = {
1, 2, 3, 6
};
/**
* Table for center mix levels
* reference: Section 5.4.2.4 cmixlev
*/
static const uint8_t center_levels[4] = { 4, 5, 6, 5 };
/**
* Table for surround mix levels
* reference: Section 5.4.2.5 surmixlev
*/
static const uint8_t surround_levels[4] = { 4, 6, 7, 6 };
int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
{
int frame_size_code;
memset(hdr, 0, sizeof(*hdr));
hdr->sync_word = get_bits(gbc, 16);
if(hdr->sync_word != 0x0B77)
return AAC_AC3_PARSE_ERROR_SYNC;
/* read ahead to bsid to distinguish between AC-3 and E-AC-3 */
hdr->bitstream_id = show_bits_long(gbc, 29) & 0x1F;
if(hdr->bitstream_id > 16)
return AAC_AC3_PARSE_ERROR_BSID;
hdr->num_blocks = 6;
/* set default mix levels */
hdr->center_mix_level = 5; // -4.5dB
hdr->surround_mix_level = 6; // -6.0dB
if(hdr->bitstream_id <= 10) {
/* Normal AC-3 */
hdr->crc1 = get_bits(gbc, 16);
hdr->sr_code = get_bits(gbc, 2);
if(hdr->sr_code == 3)
return AAC_AC3_PARSE_ERROR_SAMPLE_RATE;
frame_size_code = get_bits(gbc, 6);
if(frame_size_code > 37)
return AAC_AC3_PARSE_ERROR_FRAME_SIZE;
skip_bits(gbc, 5); // skip bsid, already got it
hdr->bitstream_mode = get_bits(gbc, 3);
hdr->channel_mode = get_bits(gbc, 3);
if(hdr->channel_mode == AC3_CHMODE_STEREO) {
skip_bits(gbc, 2); // skip dsurmod
} else {
if((hdr->channel_mode & 1) && hdr->channel_mode != AC3_CHMODE_MONO)
hdr-> center_mix_level = center_levels[get_bits(gbc, 2)];
if(hdr->channel_mode & 4)
hdr->surround_mix_level = surround_levels[get_bits(gbc, 2)];
}
hdr->lfe_on = get_bits1(gbc);
hdr->sr_shift = FFMAX(hdr->bitstream_id, 8) - 8;
hdr->sample_rate = ff_ac3_sample_rate_tab[hdr->sr_code] >> hdr->sr_shift;
hdr->bit_rate = (ff_ac3_bitrate_tab[frame_size_code>>1] * 1000) >> hdr->sr_shift;
hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on;
hdr->frame_size = ff_ac3_frame_size_tab[frame_size_code][hdr->sr_code] * 2;
hdr->frame_type = EAC3_FRAME_TYPE_AC3_CONVERT; //EAC3_FRAME_TYPE_INDEPENDENT;
hdr->substreamid = 0;
} else {
/* Enhanced AC-3 */
hdr->crc1 = 0;
hdr->frame_type = get_bits(gbc, 2);
if(hdr->frame_type == EAC3_FRAME_TYPE_RESERVED)
return AAC_AC3_PARSE_ERROR_FRAME_TYPE;
hdr->substreamid = get_bits(gbc, 3);
hdr->frame_size = (get_bits(gbc, 11) + 1) << 1;
if(hdr->frame_size < AC3_HEADER_SIZE)
return AAC_AC3_PARSE_ERROR_FRAME_SIZE;
hdr->sr_code = get_bits(gbc, 2);
if (hdr->sr_code == 3) {
int sr_code2 = get_bits(gbc, 2);
if(sr_code2 == 3)
return AAC_AC3_PARSE_ERROR_SAMPLE_RATE;
hdr->sample_rate = ff_ac3_sample_rate_tab[sr_code2] / 2;
hdr->sr_shift = 1;
} else {
hdr->num_blocks = eac3_blocks[get_bits(gbc, 2)];
hdr->sample_rate = ff_ac3_sample_rate_tab[hdr->sr_code];
hdr->sr_shift = 0;
}
hdr->channel_mode = get_bits(gbc, 3);
hdr->lfe_on = get_bits1(gbc);
hdr->bit_rate = (uint32_t)(8.0 * hdr->frame_size * hdr->sample_rate /
(hdr->num_blocks * 256.0));
hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on;
}
hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode];
if (hdr->lfe_on)
hdr->channel_layout |= AV_CH_LOW_FREQUENCY;
return 0;
}
static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info,
int *need_next_header, int *new_frame_start)
{
int err;
union {
uint64_t u64;
uint8_t u8[8];
} tmp = { av_be2ne64(state) };
AC3HeaderInfo hdr;
GetBitContext gbc;
init_get_bits(&gbc, tmp.u8+8-AC3_HEADER_SIZE, 54);
err = avpriv_ac3_parse_header(&gbc, &hdr);
if(err < 0)
return 0;
hdr_info->sample_rate = hdr.sample_rate;
hdr_info->bit_rate = hdr.bit_rate;
hdr_info->channels = hdr.channels;
hdr_info->channel_layout = hdr.channel_layout;
hdr_info->samples = hdr.num_blocks * 256;
hdr_info->service_type = hdr.bitstream_mode;
if (hdr.bitstream_mode == 0x7 && hdr.channels > 1)
hdr_info->service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
if(hdr.bitstream_id>10)
hdr_info->codec_id = AV_CODEC_ID_EAC3;
else if (hdr_info->codec_id == AV_CODEC_ID_NONE)
hdr_info->codec_id = AV_CODEC_ID_AC3;
*need_next_header = (hdr.frame_type != EAC3_FRAME_TYPE_AC3_CONVERT);
*new_frame_start = (hdr.frame_type != EAC3_FRAME_TYPE_DEPENDENT);
return hdr.frame_size;
}
static av_cold int ac3_parse_init(AVCodecParserContext *s1)
{
AACAC3ParseContext *s = s1->priv_data;
s->header_size = AC3_HEADER_SIZE;
s->sync = ac3_sync;
return 0;
}
AVCodecParser ff_ac3_parser = {
.codec_ids = { AV_CODEC_ID_AC3, AV_CODEC_ID_EAC3 },
.priv_data_size = sizeof(AACAC3ParseContext),
.parser_init = ac3_parse_init,
.parser_parse = ff_aac_ac3_parse,
.parser_close = ff_parse_close,
};

View File

@@ -0,0 +1,41 @@
/*
* AC-3 parser prototypes
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2003 Michael Niedermayer
*
* 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 AVCODEC_AC3_PARSER_H
#define AVCODEC_AC3_PARSER_H
#include "ac3.h"
#include "get_bits.h"
/**
* Parse AC-3 frame header.
* Parse the header up to the lfeon element, which is the first 52 or 54 bits
* depending on the audio coding mode.
* @param[in] gbc BitContext containing the first 54 bits of the frame.
* @param[out] hdr Pointer to struct where header info is written.
* @return Returns 0 on success, -1 if there is a sync word mismatch,
* -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate)
* element is invalid, or -4 if the frmsizecod (bit rate) element is invalid.
*/
int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr);
#endif /* AVCODEC_AC3_PARSER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,241 @@
/*
* Common code between the AC-3 and E-AC-3 decoders
* Copyright (c) 2007 Bartlomiej Wolowiec <bartek.wolowiec@gmail.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
*/
/**
* @file
* Common code between the AC-3 and E-AC-3 decoders.
*
* Summary of MDCT Coefficient Grouping:
* The individual MDCT coefficient indices are often referred to in the
* (E-)AC-3 specification as frequency bins. These bins are grouped together
* into subbands of 12 coefficients each. The subbands are grouped together
* into bands as defined in the bitstream by the band structures, which
* determine the number of bands and the size of each band. The full spectrum
* of 256 frequency bins is divided into 1 DC bin + 21 subbands = 253 bins.
* This system of grouping coefficients is used for channel bandwidth, stereo
* rematrixing, channel coupling, enhanced coupling, and spectral extension.
*
* +-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-+
* |1| |12| | [12|12|12|12] | | | | | | | | | | | | |3|
* +-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-+
* ~~~ ~~~~ ~~~~~~~~~~~~~ ~~~
* | | | |
* | | | 3 unused frequency bins--+
* | | |
* | | +--1 band containing 4 subbands
* | |
* | +--1 subband of 12 frequency bins
* |
* +--DC frequency bin
*/
#ifndef AVCODEC_AC3DEC_H
#define AVCODEC_AC3DEC_H
#include "libavutil/float_dsp.h"
#include "libavutil/lfg.h"
#include "ac3.h"
#include "ac3dsp.h"
#include "get_bits.h"
#include "dsputil.h"
#include "fft.h"
#include "fmtconvert.h"
#define AC3_OUTPUT_LFEON 8
#define SPX_MAX_BANDS 17
/** Large enough for maximum possible frame size when the specification limit is ignored */
#define AC3_FRAME_BUFFER_SIZE 32768
typedef struct AC3DecodeContext {
AVClass *class; ///< class for AVOptions
AVCodecContext *avctx; ///< parent context
GetBitContext gbc; ///< bitstream reader
///@name Bit stream information
///@{
int frame_type; ///< frame type (strmtyp)
int substreamid; ///< substream identification
int frame_size; ///< current frame size, in bytes
int bit_rate; ///< stream bit rate, in bits-per-second
int sample_rate; ///< sample frequency, in Hz
int num_blocks; ///< number of audio blocks
int bitstream_mode; ///< bitstream mode (bsmod)
int channel_mode; ///< channel mode (acmod)
int channel_layout; ///< channel layout
int lfe_on; ///< lfe channel in use
int channel_map; ///< custom channel map
int center_mix_level; ///< Center mix level index
int surround_mix_level; ///< Surround mix level index
int eac3; ///< indicates if current frame is E-AC-3
///@}
int preferred_stereo_downmix;
float ltrt_center_mix_level;
float ltrt_surround_mix_level;
float loro_center_mix_level;
float loro_surround_mix_level;
///@name Frame syntax parameters
int snr_offset_strategy; ///< SNR offset strategy (snroffststr)
int block_switch_syntax; ///< block switch syntax enabled (blkswe)
int dither_flag_syntax; ///< dither flag syntax enabled (dithflage)
int bit_allocation_syntax; ///< bit allocation model syntax enabled (bamode)
int fast_gain_syntax; ///< fast gain codes enabled (frmfgaincode)
int dba_syntax; ///< delta bit allocation syntax enabled (dbaflde)
int skip_syntax; ///< skip field syntax enabled (skipflde)
///@}
///@name Standard coupling
int cpl_in_use[AC3_MAX_BLOCKS]; ///< coupling in use (cplinu)
int cpl_strategy_exists[AC3_MAX_BLOCKS];///< coupling strategy exists (cplstre)
int channel_in_cpl[AC3_MAX_CHANNELS]; ///< channel in coupling (chincpl)
int phase_flags_in_use; ///< phase flags in use (phsflginu)
int phase_flags[AC3_MAX_CPL_BANDS]; ///< phase flags (phsflg)
int num_cpl_bands; ///< number of coupling bands (ncplbnd)
uint8_t cpl_band_sizes[AC3_MAX_CPL_BANDS]; ///< number of coeffs in each coupling band
int firstchincpl; ///< first channel in coupling
int first_cpl_coords[AC3_MAX_CHANNELS]; ///< first coupling coordinates states (firstcplcos)
int cpl_coords[AC3_MAX_CHANNELS][AC3_MAX_CPL_BANDS]; ///< coupling coordinates (cplco)
///@}
///@name Spectral extension
///@{
int spx_in_use; ///< spectral extension in use (spxinu)
uint8_t channel_uses_spx[AC3_MAX_CHANNELS]; ///< channel uses spectral extension (chinspx)
int8_t spx_atten_code[AC3_MAX_CHANNELS]; ///< spx attenuation code (spxattencod)
int spx_src_start_freq; ///< spx start frequency bin
int spx_dst_end_freq; ///< spx end frequency bin
int spx_dst_start_freq; ///< spx starting frequency bin for copying (copystartmant)
///< the copy region ends at the start of the spx region.
int num_spx_bands; ///< number of spx bands (nspxbnds)
uint8_t spx_band_sizes[SPX_MAX_BANDS]; ///< number of bins in each spx band
uint8_t first_spx_coords[AC3_MAX_CHANNELS]; ///< first spx coordinates states (firstspxcos)
float spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact)
float spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact)
///@}
///@name Adaptive hybrid transform
int channel_uses_aht[AC3_MAX_CHANNELS]; ///< channel AHT in use (chahtinu)
int pre_mantissa[AC3_MAX_CHANNELS][AC3_MAX_COEFS][AC3_MAX_BLOCKS]; ///< pre-IDCT mantissas
///@}
///@name Channel
int fbw_channels; ///< number of full-bandwidth channels
int channels; ///< number of total channels
int lfe_ch; ///< index of LFE channel
float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients
int downmixed; ///< indicates if coeffs are currently downmixed
int output_mode; ///< output channel configuration
int out_channels; ///< number of output channels
///@}
///@name Dynamic range
float dynamic_range[2]; ///< dynamic range
float drc_scale; ///< percentage of dynamic range compression to be applied
///@}
///@name Bandwidth
int start_freq[AC3_MAX_CHANNELS]; ///< start frequency bin (strtmant)
int end_freq[AC3_MAX_CHANNELS]; ///< end frequency bin (endmant)
///@}
///@name Rematrixing
int num_rematrixing_bands; ///< number of rematrixing bands (nrematbnd)
int rematrixing_flags[4]; ///< rematrixing flags (rematflg)
///@}
///@name Exponents
int num_exp_groups[AC3_MAX_CHANNELS]; ///< Number of exponent groups (nexpgrp)
int8_t dexps[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< decoded exponents
int exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS]; ///< exponent strategies (expstr)
///@}
///@name Bit allocation
AC3BitAllocParameters bit_alloc_params; ///< bit allocation parameters
int first_cpl_leak; ///< first coupling leak state (firstcplleak)
int snr_offset[AC3_MAX_CHANNELS]; ///< signal-to-noise ratio offsets (snroffst)
int fast_gain[AC3_MAX_CHANNELS]; ///< fast gain values/SMR's (fgain)
uint8_t bap[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< bit allocation pointers
int16_t psd[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< scaled exponents
int16_t band_psd[AC3_MAX_CHANNELS][AC3_CRITICAL_BANDS]; ///< interpolated exponents
int16_t mask[AC3_MAX_CHANNELS][AC3_CRITICAL_BANDS]; ///< masking curve values
int dba_mode[AC3_MAX_CHANNELS]; ///< delta bit allocation mode
int dba_nsegs[AC3_MAX_CHANNELS]; ///< number of delta segments
uint8_t dba_offsets[AC3_MAX_CHANNELS][8]; ///< delta segment offsets
uint8_t dba_lengths[AC3_MAX_CHANNELS][8]; ///< delta segment lengths
uint8_t dba_values[AC3_MAX_CHANNELS][8]; ///< delta values for each segment
///@}
///@name Zero-mantissa dithering
int dither_flag[AC3_MAX_CHANNELS]; ///< dither flags (dithflg)
AVLFG dith_state; ///< for dither generation
///@}
///@name IMDCT
int block_switch[AC3_MAX_CHANNELS]; ///< block switch flags (blksw)
FFTContext imdct_512; ///< for 512 sample IMDCT
FFTContext imdct_256; ///< for 256 sample IMDCT
///@}
///@name Optimization
DSPContext dsp; ///< for optimization
AVFloatDSPContext fdsp;
AC3DSPContext ac3dsp;
FmtConvertContext fmt_conv; ///< optimized conversion functions
///@}
float *outptr[AC3_MAX_CHANNELS];
float *xcfptr[AC3_MAX_CHANNELS];
float *dlyptr[AC3_MAX_CHANNELS];
///@name Aligned arrays
DECLARE_ALIGNED(16, int32_t, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients
DECLARE_ALIGNED(32, float, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients
DECLARE_ALIGNED(32, float, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block
DECLARE_ALIGNED(32, float, window)[AC3_BLOCK_SIZE]; ///< window coefficients
DECLARE_ALIGNED(32, float, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing
DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing
DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread
///@}
} AC3DecodeContext;
/**
* Parse the E-AC-3 frame header.
* This parses both the bit stream info and audio frame header.
*/
int ff_eac3_parse_header(AC3DecodeContext *s);
/**
* Decode mantissas in a single channel for the entire frame.
* This is used when AHT mode is enabled.
*/
void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch);
/**
* Apply spectral extension to each channel by copying lower frequency
* coefficients to higher frequency bins and applying side information to
* approximate the original high frequency signal.
*/
void ff_eac3_apply_spectral_extension(AC3DecodeContext *s);
#endif /* AVCODEC_AC3DEC_H */

View File

@@ -0,0 +1,60 @@
/*
* AC-3 and E-AC-3 decoder tables
* Copyright (c) 2007 Bartlomiej Wolowiec <bartek.wolowiec@gmail.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
*/
/**
* @file
* Tables taken directly from the AC-3 spec.
*/
#include "ac3dec_data.h"
#include "ac3.h"
/**
* Table used to ungroup 3 values stored in 5 bits.
* Used by bap=1 mantissas and GAQ.
* ff_ac3_ungroup_3_in_5_bits_tab[i] = { i/9, (i%9)/3, (i%9)%3 }
*/
const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3] = {
{ 0, 0, 0 }, { 0, 0, 1 }, { 0, 0, 2 }, { 0, 1, 0 },
{ 0, 1, 1 }, { 0, 1, 2 }, { 0, 2, 0 }, { 0, 2, 1 },
{ 0, 2, 2 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 0, 2 },
{ 1, 1, 0 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 2, 0 },
{ 1, 2, 1 }, { 1, 2, 2 }, { 2, 0, 0 }, { 2, 0, 1 },
{ 2, 0, 2 }, { 2, 1, 0 }, { 2, 1, 1 }, { 2, 1, 2 },
{ 2, 2, 0 }, { 2, 2, 1 }, { 2, 2, 2 }, { 3, 0, 0 },
{ 3, 0, 1 }, { 3, 0, 2 }, { 3, 1, 0 }, { 3, 1, 1 }
};
const uint8_t ff_eac3_hebap_tab[64] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
8, 8, 9, 9, 9, 10, 10, 10, 10, 11,
11, 11, 11, 12, 12, 12, 12, 13, 13, 13,
13, 14, 14, 14, 14, 15, 15, 15, 15, 16,
16, 16, 16, 17, 17, 17, 17, 18, 18, 18,
18, 18, 18, 18, 18, 19, 19, 19, 19, 19,
19, 19, 19, 19,
};
/**
* Table E2.15 Default Spectral Extension Banding Structure
*/
const uint8_t ff_eac3_default_spx_band_struct[17] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };

View File

@@ -0,0 +1,32 @@
/*
* AC-3 and E-AC-3 decoder tables
* Copyright (c) 2007 Bartlomiej Wolowiec <bartek.wolowiec@gmail.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 AVCODEC_AC3DEC_DATA_H
#define AVCODEC_AC3DEC_DATA_H
#include <stdint.h>
extern const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3];
extern const uint8_t ff_eac3_hebap_tab[64];
extern const uint8_t ff_eac3_default_spx_band_struct[17];
#endif /* AVCODEC_AC3DEC_DATA_H */

View File

@@ -0,0 +1,263 @@
/*
* AC-3 DSP utils
* Copyright (c) 2011 Justin Ruggles
*
* 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 "libavutil/avassert.h"
#include "avcodec.h"
#include "ac3.h"
#include "ac3dsp.h"
#include "mathops.h"
static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs)
{
int blk, i;
if (!num_reuse_blocks)
return;
for (i = 0; i < nb_coefs; i++) {
uint8_t min_exp = *exp;
uint8_t *exp1 = exp + 256;
for (blk = 0; blk < num_reuse_blocks; blk++) {
uint8_t next_exp = *exp1;
if (next_exp < min_exp)
min_exp = next_exp;
exp1 += 256;
}
*exp++ = min_exp;
}
}
static int ac3_max_msb_abs_int16_c(const int16_t *src, int len)
{
int i, v = 0;
for (i = 0; i < len; i++)
v |= abs(src[i]);
return v;
}
static void ac3_lshift_int16_c(int16_t *src, unsigned int len,
unsigned int shift)
{
uint32_t *src32 = (uint32_t *)src;
const uint32_t mask = ~(((1 << shift) - 1) << 16);
int i;
len >>= 1;
for (i = 0; i < len; i += 8) {
src32[i ] = (src32[i ] << shift) & mask;
src32[i+1] = (src32[i+1] << shift) & mask;
src32[i+2] = (src32[i+2] << shift) & mask;
src32[i+3] = (src32[i+3] << shift) & mask;
src32[i+4] = (src32[i+4] << shift) & mask;
src32[i+5] = (src32[i+5] << shift) & mask;
src32[i+6] = (src32[i+6] << shift) & mask;
src32[i+7] = (src32[i+7] << shift) & mask;
}
}
static void ac3_rshift_int32_c(int32_t *src, unsigned int len,
unsigned int shift)
{
do {
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
*src++ >>= shift;
len -= 8;
} while (len > 0);
}
static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len)
{
const float scale = 1 << 24;
do {
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
*dst++ = lrintf(*src++ * scale);
len -= 8;
} while (len > 0);
}
static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd,
int start, int end,
int snr_offset, int floor,
const uint8_t *bap_tab, uint8_t *bap)
{
int bin, band, band_end;
/* special case, if snr offset is -960, set all bap's to zero */
if (snr_offset == -960) {
memset(bap, 0, AC3_MAX_COEFS);
return;
}
bin = start;
band = ff_ac3_bin_to_band_tab[start];
do {
int m = (FFMAX(mask[band] - snr_offset - floor, 0) & 0x1FE0) + floor;
band_end = ff_ac3_band_start_tab[++band];
band_end = FFMIN(band_end, end);
for (; bin < band_end; bin++) {
int address = av_clip((psd[bin] - m) >> 5, 0, 63);
bap[bin] = bap_tab[address];
}
} while (end > band_end);
}
static void ac3_update_bap_counts_c(uint16_t mant_cnt[16], uint8_t *bap,
int len)
{
while (len-- > 0)
mant_cnt[bap[len]]++;
}
DECLARE_ALIGNED(16, const uint16_t, ff_ac3_bap_bits)[16] = {
0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16
};
static int ac3_compute_mantissa_size_c(uint16_t mant_cnt[6][16])
{
int blk, bap;
int bits = 0;
for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
// bap=1 : 3 mantissas in 5 bits
bits += (mant_cnt[blk][1] / 3) * 5;
// bap=2 : 3 mantissas in 7 bits
// bap=4 : 2 mantissas in 7 bits
bits += ((mant_cnt[blk][2] / 3) + (mant_cnt[blk][4] >> 1)) * 7;
// bap=3 : 1 mantissa in 3 bits
bits += mant_cnt[blk][3] * 3;
// bap=5 to 15 : get bits per mantissa from table
for (bap = 5; bap < 16; bap++)
bits += mant_cnt[blk][bap] * ff_ac3_bap_bits[bap];
}
return bits;
}
static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs)
{
int i;
for (i = 0; i < nb_coefs; i++) {
int v = abs(coef[i]);
exp[i] = v ? 23 - av_log2(v) : 24;
}
}
static void ac3_sum_square_butterfly_int32_c(int64_t sum[4],
const int32_t *coef0,
const int32_t *coef1,
int len)
{
int i;
sum[0] = sum[1] = sum[2] = sum[3] = 0;
for (i = 0; i < len; i++) {
int lt = coef0[i];
int rt = coef1[i];
int md = lt + rt;
int sd = lt - rt;
MAC64(sum[0], lt, lt);
MAC64(sum[1], rt, rt);
MAC64(sum[2], md, md);
MAC64(sum[3], sd, sd);
}
}
static void ac3_sum_square_butterfly_float_c(float sum[4],
const float *coef0,
const float *coef1,
int len)
{
int i;
sum[0] = sum[1] = sum[2] = sum[3] = 0;
for (i = 0; i < len; i++) {
float lt = coef0[i];
float rt = coef1[i];
float md = lt + rt;
float sd = lt - rt;
sum[0] += lt * lt;
sum[1] += rt * rt;
sum[2] += md * md;
sum[3] += sd * sd;
}
}
static void ac3_downmix_c(float **samples, float (*matrix)[2],
int out_ch, int in_ch, int len)
{
int i, j;
float v0, v1;
if (out_ch == 2) {
for (i = 0; i < len; i++) {
v0 = v1 = 0.0f;
for (j = 0; j < in_ch; j++) {
v0 += samples[j][i] * matrix[j][0];
v1 += samples[j][i] * matrix[j][1];
}
samples[0][i] = v0;
samples[1][i] = v1;
}
} else if (out_ch == 1) {
for (i = 0; i < len; i++) {
v0 = 0.0f;
for (j = 0; j < in_ch; j++)
v0 += samples[j][i] * matrix[j][0];
samples[0][i] = v0;
}
}
}
av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact)
{
c->ac3_exponent_min = ac3_exponent_min_c;
c->ac3_max_msb_abs_int16 = ac3_max_msb_abs_int16_c;
c->ac3_lshift_int16 = ac3_lshift_int16_c;
c->ac3_rshift_int32 = ac3_rshift_int32_c;
c->float_to_fixed24 = float_to_fixed24_c;
c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c;
c->update_bap_counts = ac3_update_bap_counts_c;
c->compute_mantissa_size = ac3_compute_mantissa_size_c;
c->extract_exponents = ac3_extract_exponents_c;
c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c;
c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c;
c->downmix = ac3_downmix_c;
if (ARCH_ARM)
ff_ac3dsp_init_arm(c, bit_exact);
if (ARCH_X86)
ff_ac3dsp_init_x86(c, bit_exact);
if (ARCH_MIPS)
ff_ac3dsp_init_mips(c, bit_exact);
}

View File

@@ -0,0 +1,144 @@
/*
* AC-3 DSP utils
* Copyright (c) 2011 Justin Ruggles
*
* 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 AVCODEC_AC3DSP_H
#define AVCODEC_AC3DSP_H
#include <stdint.h>
/**
* Number of mantissa bits written for each bap value.
* bap values with fractional bits are set to 0 and are calculated separately.
*/
extern const uint16_t ff_ac3_bap_bits[16];
typedef struct AC3DSPContext {
/**
* Set each encoded exponent in a block to the minimum of itself and the
* exponents in the same frequency bin of up to 5 following blocks.
* @param exp pointer to the start of the current block of exponents.
* constraints: align 16
* @param num_reuse_blocks number of blocks that will reuse exponents from the current block.
* constraints: range 0 to 5
* @param nb_coefs number of frequency coefficients.
*/
void (*ac3_exponent_min)(uint8_t *exp, int num_reuse_blocks, int nb_coefs);
/**
* Calculate the maximum MSB of the absolute value of each element in an
* array of int16_t.
* @param src input array
* constraints: align 16. values must be in range [-32767,32767]
* @param len number of values in the array
* constraints: multiple of 16 greater than 0
* @return a value with the same MSB as max(abs(src[]))
*/
int (*ac3_max_msb_abs_int16)(const int16_t *src, int len);
/**
* Left-shift each value in an array of int16_t by a specified amount.
* @param src input array
* constraints: align 16
* @param len number of values in the array
* constraints: multiple of 32 greater than 0
* @param shift left shift amount
* constraints: range [0,15]
*/
void (*ac3_lshift_int16)(int16_t *src, unsigned int len, unsigned int shift);
/**
* Right-shift each value in an array of int32_t by a specified amount.
* @param src input array
* constraints: align 16
* @param len number of values in the array
* constraints: multiple of 16 greater than 0
* @param shift right shift amount
* constraints: range [0,31]
*/
void (*ac3_rshift_int32)(int32_t *src, unsigned int len, unsigned int shift);
/**
* Convert an array of float in range [-1.0,1.0] to int32_t with range
* [-(1<<24),(1<<24)]
*
* @param dst destination array of int32_t.
* constraints: 16-byte aligned
* @param src source array of float.
* constraints: 16-byte aligned
* @param len number of elements to convert.
* constraints: multiple of 32 greater than zero
*/
void (*float_to_fixed24)(int32_t *dst, const float *src, unsigned int len);
/**
* Calculate bit allocation pointers.
* The SNR is the difference between the masking curve and the signal. AC-3
* uses this value for each frequency bin to allocate bits. The snroffset
* parameter is a global adjustment to the SNR for all bins.
*
* @param[in] mask masking curve
* @param[in] psd signal power for each frequency bin
* @param[in] start starting bin location
* @param[in] end ending bin location
* @param[in] snr_offset SNR adjustment
* @param[in] floor noise floor
* @param[in] bap_tab look-up table for bit allocation pointers
* @param[out] bap bit allocation pointers
*/
void (*bit_alloc_calc_bap)(int16_t *mask, int16_t *psd, int start, int end,
int snr_offset, int floor,
const uint8_t *bap_tab, uint8_t *bap);
/**
* Update bap counts using the supplied array of bap.
*
* @param[out] mant_cnt bap counts for 1 block
* @param[in] bap array of bap, pointing to start coef bin
* @param[in] len number of elements to process
*/
void (*update_bap_counts)(uint16_t mant_cnt[16], uint8_t *bap, int len);
/**
* Calculate the number of bits needed to encode a set of mantissas.
*
* @param[in] mant_cnt bap counts for all blocks
* @return mantissa bit count
*/
int (*compute_mantissa_size)(uint16_t mant_cnt[6][16]);
void (*extract_exponents)(uint8_t *exp, int32_t *coef, int nb_coefs);
void (*sum_square_butterfly_int32)(int64_t sum[4], const int32_t *coef0,
const int32_t *coef1, int len);
void (*sum_square_butterfly_float)(float sum[4], const float *coef0,
const float *coef1, int len);
void (*downmix)(float **samples, float (*matrix)[2], int out_ch,
int in_ch, int len);
} AC3DSPContext;
void ff_ac3dsp_init (AC3DSPContext *c, int bit_exact);
void ff_ac3dsp_init_arm(AC3DSPContext *c, int bit_exact);
void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact);
void ff_ac3dsp_init_mips(AC3DSPContext *c, int bit_exact);
#endif /* AVCODEC_AC3DSP_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,308 @@
/*
* AC-3 encoder & E-AC-3 encoder common header
* Copyright (c) 2000 Fabrice Bellard
* Copyright (c) 2006-2010 Justin Ruggles <justin.ruggles@gmail.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
*/
/**
* @file
* AC-3 encoder & E-AC-3 encoder common header
*/
#ifndef AVCODEC_AC3ENC_H
#define AVCODEC_AC3ENC_H
#include <stdint.h>
#include "libavutil/float_dsp.h"
#include "ac3.h"
#include "ac3dsp.h"
#include "avcodec.h"
#include "dsputil.h"
#include "put_bits.h"
#include "fft.h"
#ifndef CONFIG_AC3ENC_FLOAT
#define CONFIG_AC3ENC_FLOAT 0
#endif
#define OFFSET(param) offsetof(AC3EncodeContext, options.param)
#define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
#define AC3ENC_TYPE_AC3_FIXED 0
#define AC3ENC_TYPE_AC3 1
#define AC3ENC_TYPE_EAC3 2
#if CONFIG_AC3ENC_FLOAT
#define AC3_NAME(x) ff_ac3_float_ ## x
#define MAC_COEF(d,a,b) ((d)+=(a)*(b))
#define COEF_MIN (-16777215.0/16777216.0)
#define COEF_MAX ( 16777215.0/16777216.0)
#define NEW_CPL_COORD_THRESHOLD 0.03
typedef float SampleType;
typedef float CoefType;
typedef float CoefSumType;
#else
#define AC3_NAME(x) ff_ac3_fixed_ ## x
#define MAC_COEF(d,a,b) MAC64(d,a,b)
#define COEF_MIN -16777215
#define COEF_MAX 16777215
#define NEW_CPL_COORD_THRESHOLD 503317
typedef int16_t SampleType;
typedef int32_t CoefType;
typedef int64_t CoefSumType;
#endif
/* common option values */
#define AC3ENC_OPT_NONE -1
#define AC3ENC_OPT_AUTO -1
#define AC3ENC_OPT_OFF 0
#define AC3ENC_OPT_ON 1
#define AC3ENC_OPT_NOT_INDICATED 0
#define AC3ENC_OPT_MODE_ON 2
#define AC3ENC_OPT_MODE_OFF 1
/* specific option values */
#define AC3ENC_OPT_LARGE_ROOM 1
#define AC3ENC_OPT_SMALL_ROOM 2
#define AC3ENC_OPT_DOWNMIX_LTRT 1
#define AC3ENC_OPT_DOWNMIX_LORO 2
#define AC3ENC_OPT_ADCONV_STANDARD 0
#define AC3ENC_OPT_ADCONV_HDCD 1
/**
* Encoding Options used by AVOption.
*/
typedef struct AC3EncOptions {
/* AC-3 metadata options*/
int dialogue_level;
int bitstream_mode;
float center_mix_level;
float surround_mix_level;
int dolby_surround_mode;
int audio_production_info;
int mixing_level;
int room_type;
int copyright;
int original;
int extended_bsi_1;
int preferred_stereo_downmix;
float ltrt_center_mix_level;
float ltrt_surround_mix_level;
float loro_center_mix_level;
float loro_surround_mix_level;
int extended_bsi_2;
int dolby_surround_ex_mode;
int dolby_headphone_mode;
int ad_converter_type;
int eac3_mixing_metadata;
int eac3_info_metadata;
/* other encoding options */
int allow_per_frame_metadata;
int stereo_rematrixing;
int channel_coupling;
int cpl_start;
} AC3EncOptions;
/**
* Data for a single audio block.
*/
typedef struct AC3Block {
CoefType **mdct_coef; ///< MDCT coefficients
int32_t **fixed_coef; ///< fixed-point MDCT coefficients
uint8_t **exp; ///< original exponents
uint8_t **grouped_exp; ///< grouped exponents
int16_t **psd; ///< psd per frequency bin
int16_t **band_psd; ///< psd per critical band
int16_t **mask; ///< masking curve
uint16_t **qmant; ///< quantized mantissas
uint8_t **cpl_coord_exp; ///< coupling coord exponents (cplcoexp)
uint8_t **cpl_coord_mant; ///< coupling coord mantissas (cplcomant)
uint8_t coeff_shift[AC3_MAX_CHANNELS]; ///< fixed-point coefficient shift values
uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block
int num_rematrixing_bands; ///< number of rematrixing bands
uint8_t rematrixing_flags[4]; ///< rematrixing flags
int new_cpl_strategy; ///< send new coupling strategy
int cpl_in_use; ///< coupling in use for this block (cplinu)
uint8_t channel_in_cpl[AC3_MAX_CHANNELS]; ///< channel in coupling (chincpl)
int num_cpl_channels; ///< number of channels in coupling
uint8_t new_cpl_coords[AC3_MAX_CHANNELS]; ///< send new coupling coordinates (cplcoe)
uint8_t cpl_master_exp[AC3_MAX_CHANNELS]; ///< coupling coord master exponents (mstrcplco)
int new_snr_offsets; ///< send new SNR offsets
int new_cpl_leak; ///< send new coupling leak info
int end_freq[AC3_MAX_CHANNELS]; ///< end frequency bin (endmant)
} AC3Block;
/**
* AC-3 encoder private context.
*/
typedef struct AC3EncodeContext {
AVClass *av_class; ///< AVClass used for AVOption
AC3EncOptions options; ///< encoding options
AVCodecContext *avctx; ///< parent AVCodecContext
PutBitContext pb; ///< bitstream writer context
DSPContext dsp;
AVFloatDSPContext fdsp;
AC3DSPContext ac3dsp; ///< AC-3 optimized functions
FFTContext mdct; ///< FFT context for MDCT calculation
const SampleType *mdct_window; ///< MDCT window function array
AC3Block blocks[AC3_MAX_BLOCKS]; ///< per-block info
int fixed_point; ///< indicates if fixed-point encoder is being used
int eac3; ///< indicates if this is E-AC-3 vs. AC-3
int bitstream_id; ///< bitstream id (bsid)
int bitstream_mode; ///< bitstream mode (bsmod)
int bit_rate; ///< target bit rate, in bits-per-second
int sample_rate; ///< sampling frequency, in Hz
int num_blks_code; ///< number of blocks code (numblkscod)
int num_blocks; ///< number of blocks per frame
int frame_size_min; ///< minimum frame size in case rounding is necessary
int frame_size; ///< current frame size in bytes
int frame_size_code; ///< frame size code (frmsizecod)
uint16_t crc_inv[2];
int64_t bits_written; ///< bit count (used to avg. bitrate)
int64_t samples_written; ///< sample count (used to avg. bitrate)
int fbw_channels; ///< number of full-bandwidth channels (nfchans)
int channels; ///< total number of channels (nchans)
int lfe_on; ///< indicates if there is an LFE channel (lfeon)
int lfe_channel; ///< channel index of the LFE channel
int has_center; ///< indicates if there is a center channel
int has_surround; ///< indicates if there are one or more surround channels
int channel_mode; ///< channel mode (acmod)
const uint8_t *channel_map; ///< channel map used to reorder channels
int center_mix_level; ///< center mix level code
int surround_mix_level; ///< surround mix level code
int ltrt_center_mix_level; ///< Lt/Rt center mix level code
int ltrt_surround_mix_level; ///< Lt/Rt surround mix level code
int loro_center_mix_level; ///< Lo/Ro center mix level code
int loro_surround_mix_level; ///< Lo/Ro surround mix level code
int cutoff; ///< user-specified cutoff frequency, in Hz
int bandwidth_code; ///< bandwidth code (0 to 60) (chbwcod)
int start_freq[AC3_MAX_CHANNELS]; ///< start frequency bin (strtmant)
int cpl_end_freq; ///< coupling channel end frequency bin
int cpl_on; ///< coupling turned on for this frame
int cpl_enabled; ///< coupling enabled for all frames
int num_cpl_subbands; ///< number of coupling subbands (ncplsubnd)
int num_cpl_bands; ///< number of coupling bands (ncplbnd)
uint8_t cpl_band_sizes[AC3_MAX_CPL_BANDS]; ///< number of coeffs in each coupling band
int rematrixing_enabled; ///< stereo rematrixing enabled
/* bitrate allocation control */
int slow_gain_code; ///< slow gain code (sgaincod)
int slow_decay_code; ///< slow decay code (sdcycod)
int fast_decay_code; ///< fast decay code (fdcycod)
int db_per_bit_code; ///< dB/bit code (dbpbcod)
int floor_code; ///< floor code (floorcod)
AC3BitAllocParameters bit_alloc; ///< bit allocation parameters
int coarse_snr_offset; ///< coarse SNR offsets (csnroffst)
int fast_gain_code[AC3_MAX_CHANNELS]; ///< fast gain codes (signal-to-mask ratio) (fgaincod)
int fine_snr_offset[AC3_MAX_CHANNELS]; ///< fine SNR offsets (fsnroffst)
int frame_bits_fixed; ///< number of non-coefficient bits for fixed parameters
int frame_bits; ///< all frame bits except exponents and mantissas
int exponent_bits; ///< number of bits used for exponents
SampleType *windowed_samples;
SampleType **planar_samples;
uint8_t *bap_buffer;
uint8_t *bap1_buffer;
CoefType *mdct_coef_buffer;
int32_t *fixed_coef_buffer;
uint8_t *exp_buffer;
uint8_t *grouped_exp_buffer;
int16_t *psd_buffer;
int16_t *band_psd_buffer;
int16_t *mask_buffer;
int16_t *qmant_buffer;
uint8_t *cpl_coord_exp_buffer;
uint8_t *cpl_coord_mant_buffer;
uint8_t exp_strategy[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< exponent strategies
uint8_t frame_exp_strategy[AC3_MAX_CHANNELS]; ///< frame exp strategy index
int use_frame_exp_strategy; ///< indicates use of frame exp strategy
uint8_t exp_ref_block[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< reference blocks for EXP_REUSE
uint8_t *ref_bap [AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< bit allocation pointers (bap)
int ref_bap_set; ///< indicates if ref_bap pointers have been set
/* fixed vs. float function pointers */
void (*mdct_end)(struct AC3EncodeContext *s);
int (*mdct_init)(struct AC3EncodeContext *s);
/* fixed vs. float templated function pointers */
int (*allocate_sample_buffers)(struct AC3EncodeContext *s);
/* AC-3 vs. E-AC-3 function pointers */
void (*output_frame_header)(struct AC3EncodeContext *s);
} AC3EncodeContext;
extern const uint64_t ff_ac3_channel_layouts[19];
int ff_ac3_encode_init(AVCodecContext *avctx);
int ff_ac3_encode_close(AVCodecContext *avctx);
int ff_ac3_validate_metadata(AC3EncodeContext *s);
void ff_ac3_adjust_frame_size(AC3EncodeContext *s);
void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s);
void ff_ac3_apply_rematrixing(AC3EncodeContext *s);
void ff_ac3_process_exponents(AC3EncodeContext *s);
int ff_ac3_compute_bit_allocation(AC3EncodeContext *s);
void ff_ac3_group_exponents(AC3EncodeContext *s);
void ff_ac3_quantize_mantissas(AC3EncodeContext *s);
void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame);
/* prototypes for functions in ac3enc_fixed.c and ac3enc_float.c */
void ff_ac3_fixed_mdct_end(AC3EncodeContext *s);
void ff_ac3_float_mdct_end(AC3EncodeContext *s);
int ff_ac3_fixed_mdct_init(AC3EncodeContext *s);
int ff_ac3_float_mdct_init(AC3EncodeContext *s);
/* prototypes for functions in ac3enc_template.c */
int ff_ac3_fixed_allocate_sample_buffers(AC3EncodeContext *s);
int ff_ac3_float_allocate_sample_buffers(AC3EncodeContext *s);
int ff_ac3_fixed_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr);
int ff_ac3_float_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr);
#endif /* AVCODEC_AC3ENC_H */

View File

@@ -0,0 +1,169 @@
/*
* The simplest AC-3 encoder
* Copyright (c) 2000 Fabrice Bellard
* Copyright (c) 2006-2010 Justin Ruggles <justin.ruggles@gmail.com>
* Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
*
* 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
* fixed-point AC-3 encoder.
*/
#define CONFIG_FFT_FLOAT 0
#undef CONFIG_AC3ENC_FLOAT
#include "internal.h"
#include "ac3enc.h"
#include "eac3enc.h"
#define AC3ENC_TYPE AC3ENC_TYPE_AC3_FIXED
#include "ac3enc_opts_template.c"
static const AVClass ac3enc_class = {
.class_name = "Fixed-Point AC-3 Encoder",
.item_name = av_default_item_name,
.option = ac3_options,
.version = LIBAVUTIL_VERSION_INT,
};
#include "ac3enc_template.c"
/**
* Finalize MDCT and free allocated memory.
*
* @param s AC-3 encoder private context
*/
av_cold void AC3_NAME(mdct_end)(AC3EncodeContext *s)
{
ff_mdct_end(&s->mdct);
}
/**
* Initialize MDCT tables.
*
* @param s AC-3 encoder private context
* @return 0 on success, negative error code on failure
*/
av_cold int AC3_NAME(mdct_init)(AC3EncodeContext *s)
{
int ret = ff_mdct_init(&s->mdct, 9, 0, -1.0);
s->mdct_window = ff_ac3_window;
return ret;
}
/*
* Apply KBD window to input samples prior to MDCT.
*/
static void apply_window(void *dsp, int16_t *output, const int16_t *input,
const int16_t *window, unsigned int len)
{
DSPContext *dsp0 = dsp;
dsp0->apply_window_int16(output, input, window, len);
}
/*
* Normalize the input samples to use the maximum available precision.
* This assumes signed 16-bit input samples.
*/
static int normalize_samples(AC3EncodeContext *s)
{
int v = s->ac3dsp.ac3_max_msb_abs_int16(s->windowed_samples, AC3_WINDOW_SIZE);
v = 14 - av_log2(v);
if (v > 0)
s->ac3dsp.ac3_lshift_int16(s->windowed_samples, AC3_WINDOW_SIZE, v);
/* +6 to right-shift from 31-bit to 25-bit */
return v + 6;
}
/*
* Scale MDCT coefficients to 25-bit signed fixed-point.
*/
static void scale_coefficients(AC3EncodeContext *s)
{
int blk, ch;
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = 1; ch <= s->channels; ch++) {
s->ac3dsp.ac3_rshift_int32(block->mdct_coef[ch], AC3_MAX_COEFS,
block->coeff_shift[ch]);
}
}
}
static void sum_square_butterfly(AC3EncodeContext *s, int64_t sum[4],
const int32_t *coef0, const int32_t *coef1,
int len)
{
s->ac3dsp.sum_square_butterfly_int32(sum, coef0, coef1, len);
}
/*
* Clip MDCT coefficients to allowable range.
*/
static void clip_coefficients(DSPContext *dsp, int32_t *coef, unsigned int len)
{
dsp->vector_clip_int32(coef, coef, COEF_MIN, COEF_MAX, len);
}
/*
* Calculate a single coupling coordinate.
*/
static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl)
{
if (energy_cpl <= COEF_MAX) {
return 1048576;
} else {
uint64_t coord = energy_ch / (energy_cpl >> 24);
uint32_t coord32 = FFMIN(coord, 1073741824);
coord32 = ff_sqrt(coord32) << 9;
return FFMIN(coord32, COEF_MAX);
}
}
static av_cold int ac3_fixed_encode_init(AVCodecContext *avctx)
{
AC3EncodeContext *s = avctx->priv_data;
s->fixed_point = 1;
return ff_ac3_encode_init(avctx);
}
AVCodec ff_ac3_fixed_encoder = {
.name = "ac3_fixed",
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AC3,
.priv_data_size = sizeof(AC3EncodeContext),
.init = ac3_fixed_encode_init,
.encode2 = ff_ac3_fixed_encode_frame,
.close = ff_ac3_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
.priv_class = &ac3enc_class,
.channel_layouts = ff_ac3_channel_layouts,
.defaults = ac3_defaults,
};

View File

@@ -0,0 +1,168 @@
/*
* The simplest AC-3 encoder
* Copyright (c) 2000 Fabrice Bellard
* Copyright (c) 2006-2010 Justin Ruggles <justin.ruggles@gmail.com>
* Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
*
* 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
* floating-point AC-3 encoder.
*/
#define CONFIG_AC3ENC_FLOAT 1
#include "internal.h"
#include "ac3enc.h"
#include "eac3enc.h"
#include "kbdwin.h"
#if CONFIG_AC3_ENCODER
#define AC3ENC_TYPE AC3ENC_TYPE_AC3
#include "ac3enc_opts_template.c"
static const AVClass ac3enc_class = {
.class_name = "AC-3 Encoder",
.item_name = av_default_item_name,
.option = ac3_options,
.version = LIBAVUTIL_VERSION_INT,
};
#endif
#include "ac3enc_template.c"
/**
* Finalize MDCT and free allocated memory.
*
* @param s AC-3 encoder private context
*/
av_cold void ff_ac3_float_mdct_end(AC3EncodeContext *s)
{
ff_mdct_end(&s->mdct);
av_freep(&s->mdct_window);
}
/**
* Initialize MDCT tables.
*
* @param s AC-3 encoder private context
* @return 0 on success, negative error code on failure
*/
av_cold int ff_ac3_float_mdct_init(AC3EncodeContext *s)
{
float *window;
int i, n, n2;
n = 1 << 9;
n2 = n >> 1;
window = av_malloc(n * sizeof(*window));
if (!window) {
av_log(s->avctx, AV_LOG_ERROR, "Cannot allocate memory.\n");
return AVERROR(ENOMEM);
}
ff_kbd_window_init(window, 5.0, n2);
for (i = 0; i < n2; i++)
window[n-1-i] = window[i];
s->mdct_window = window;
return ff_mdct_init(&s->mdct, 9, 0, -2.0 / n);
}
/*
* Apply KBD window to input samples prior to MDCT.
*/
static void apply_window(void *dsp, float *output,
const float *input, const float *window,
unsigned int len)
{
AVFloatDSPContext *fdsp = dsp;
fdsp->vector_fmul(output, input, window, len);
}
/*
* Normalize the input samples.
* Not needed for the floating-point encoder.
*/
static int normalize_samples(AC3EncodeContext *s)
{
return 0;
}
/*
* Scale MDCT coefficients from float to 24-bit fixed-point.
*/
static void scale_coefficients(AC3EncodeContext *s)
{
int chan_size = AC3_MAX_COEFS * s->num_blocks;
int cpl = s->cpl_on;
s->ac3dsp.float_to_fixed24(s->fixed_coef_buffer + (chan_size * !cpl),
s->mdct_coef_buffer + (chan_size * !cpl),
chan_size * (s->channels + cpl));
}
static void sum_square_butterfly(AC3EncodeContext *s, float sum[4],
const float *coef0, const float *coef1,
int len)
{
s->ac3dsp.sum_square_butterfly_float(sum, coef0, coef1, len);
}
/*
* Clip MDCT coefficients to allowable range.
*/
static void clip_coefficients(DSPContext *dsp, float *coef, unsigned int len)
{
dsp->vector_clipf(coef, coef, COEF_MIN, COEF_MAX, len);
}
/*
* Calculate a single coupling coordinate.
*/
static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl)
{
float coord = 0.125;
if (energy_cpl > 0)
coord *= sqrtf(energy_ch / energy_cpl);
return FFMIN(coord, COEF_MAX);
}
#if CONFIG_AC3_ENCODER
AVCodec ff_ac3_encoder = {
.name = "ac3",
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AC3,
.priv_data_size = sizeof(AC3EncodeContext),
.init = ff_ac3_encode_init,
.encode2 = ff_ac3_float_encode_frame,
.close = ff_ac3_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.priv_class = &ac3enc_class,
.channel_layouts = ff_ac3_channel_layouts,
.defaults = ac3_defaults,
};
#endif

View File

@@ -0,0 +1,80 @@
/*
* AC-3 encoder options
* Copyright (c) 2011 Justin Ruggles <justin.ruggles@gmail.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
*/
#include "libavutil/opt.h"
#include "internal.h"
#include "ac3.h"
static const AVOption ac3_options[] = {
/* Metadata Options */
{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, AC3ENC_PARAM},
#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3
/* AC-3 downmix levels */
{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM},
{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM},
#endif
/* audio production information */
{"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM},
{"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, "room_type"},
{"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"},
{"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"},
{"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"},
/* other metadata options */
{"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM},
{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM},
{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsur_mode"},
{"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
{"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
{"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"},
{"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM},
/* extended bitstream information */
{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_LORO, AC3ENC_PARAM, "dmix_mode"},
{"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"},
{"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"},
{"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"},
{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},
{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},
{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},
{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM},
{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsurex_mode"},
{"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"},
{"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"},
{"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"},
{"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dheadphone_mode"},
{"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"},
{"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"},
{"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"},
{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, "ad_conv_type"},
{"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
{"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
/* Other Encoding Options */
{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_ON }, AC3ENC_OPT_OFF, AC3ENC_OPT_ON, AC3ENC_PARAM},
{"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, "channel_coupling"},
{"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "channel_coupling"},
{"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, "cpl_start_band"},
{"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "cpl_start_band"},
{NULL}
};
static const AVCodecDefault ac3_defaults[] = {
{ "b", "0" },
{ NULL }
};

View File

@@ -0,0 +1,447 @@
/*
* AC-3 encoder float/fixed template
* Copyright (c) 2000 Fabrice Bellard
* Copyright (c) 2006-2011 Justin Ruggles <justin.ruggles@gmail.com>
* Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
*
* 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
* AC-3 encoder float/fixed template
*/
#include <stdint.h>
#include "libavutil/internal.h"
/* prototypes for static functions in ac3enc_fixed.c and ac3enc_float.c */
static void scale_coefficients(AC3EncodeContext *s);
static void apply_window(void *dsp, SampleType *output,
const SampleType *input, const SampleType *window,
unsigned int len);
static int normalize_samples(AC3EncodeContext *s);
static void clip_coefficients(DSPContext *dsp, CoefType *coef, unsigned int len);
static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl);
static void sum_square_butterfly(AC3EncodeContext *s, CoefSumType sum[4],
const CoefType *coef0, const CoefType *coef1,
int len);
int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s)
{
int ch;
FF_ALLOC_OR_GOTO(s->avctx, s->windowed_samples, AC3_WINDOW_SIZE *
sizeof(*s->windowed_samples), alloc_fail);
FF_ALLOC_OR_GOTO(s->avctx, s->planar_samples, s->channels * sizeof(*s->planar_samples),
alloc_fail);
for (ch = 0; ch < s->channels; ch++) {
FF_ALLOCZ_OR_GOTO(s->avctx, s->planar_samples[ch],
(AC3_FRAME_SIZE+AC3_BLOCK_SIZE) * sizeof(**s->planar_samples),
alloc_fail);
}
return 0;
alloc_fail:
return AVERROR(ENOMEM);
}
/*
* Copy input samples.
* Channels are reordered from FFmpeg's default order to AC-3 order.
*/
static void copy_input_samples(AC3EncodeContext *s, SampleType **samples)
{
int ch;
/* copy and remap input samples */
for (ch = 0; ch < s->channels; ch++) {
/* copy last 256 samples of previous frame to the start of the current frame */
memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_BLOCK_SIZE * s->num_blocks],
AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0]));
/* copy new samples for current frame */
memcpy(&s->planar_samples[ch][AC3_BLOCK_SIZE],
samples[s->channel_map[ch]],
AC3_BLOCK_SIZE * s->num_blocks * sizeof(s->planar_samples[0][0]));
}
}
/*
* Apply the MDCT to input samples to generate frequency coefficients.
* This applies the KBD window and normalizes the input to reduce precision
* loss due to fixed-point calculations.
*/
static void apply_mdct(AC3EncodeContext *s)
{
int blk, ch;
for (ch = 0; ch < s->channels; ch++) {
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
#if CONFIG_AC3ENC_FLOAT
apply_window(&s->fdsp, s->windowed_samples, input_samples,
s->mdct_window, AC3_WINDOW_SIZE);
#else
apply_window(&s->dsp, s->windowed_samples, input_samples,
s->mdct_window, AC3_WINDOW_SIZE);
#endif
if (s->fixed_point)
block->coeff_shift[ch+1] = normalize_samples(s);
s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1],
s->windowed_samples);
}
}
}
/*
* Calculate coupling channel and coupling coordinates.
*/
static void apply_channel_coupling(AC3EncodeContext *s)
{
LOCAL_ALIGNED_16(CoefType, cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]);
#if CONFIG_AC3ENC_FLOAT
LOCAL_ALIGNED_16(int32_t, fixed_cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]);
#else
int32_t (*fixed_cpl_coords)[AC3_MAX_CHANNELS][16] = cpl_coords;
#endif
int av_uninit(blk), ch, bnd, i, j;
CoefSumType energy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][16] = {{{0}}};
int cpl_start, num_cpl_coefs;
memset(cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords));
#if CONFIG_AC3ENC_FLOAT
memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords));
#endif
/* align start to 16-byte boundary. align length to multiple of 32.
note: coupling start bin % 4 will always be 1 */
cpl_start = s->start_freq[CPL_CH] - 1;
num_cpl_coefs = FFALIGN(s->num_cpl_subbands * 12 + 1, 32);
cpl_start = FFMIN(256, cpl_start + num_cpl_coefs) - num_cpl_coefs;
/* calculate coupling channel from fbw channels */
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
CoefType *cpl_coef = &block->mdct_coef[CPL_CH][cpl_start];
if (!block->cpl_in_use)
continue;
memset(cpl_coef, 0, num_cpl_coefs * sizeof(*cpl_coef));
for (ch = 1; ch <= s->fbw_channels; ch++) {
CoefType *ch_coef = &block->mdct_coef[ch][cpl_start];
if (!block->channel_in_cpl[ch])
continue;
for (i = 0; i < num_cpl_coefs; i++)
cpl_coef[i] += ch_coef[i];
}
/* coefficients must be clipped in order to be encoded */
clip_coefficients(&s->dsp, cpl_coef, num_cpl_coefs);
}
/* calculate energy in each band in coupling channel and each fbw channel */
/* TODO: possibly use SIMD to speed up energy calculation */
bnd = 0;
i = s->start_freq[CPL_CH];
while (i < s->cpl_end_freq) {
int band_size = s->cpl_band_sizes[bnd];
for (ch = CPL_CH; ch <= s->fbw_channels; ch++) {
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
if (!block->cpl_in_use || (ch > CPL_CH && !block->channel_in_cpl[ch]))
continue;
for (j = 0; j < band_size; j++) {
CoefType v = block->mdct_coef[ch][i+j];
MAC_COEF(energy[blk][ch][bnd], v, v);
}
}
}
i += band_size;
bnd++;
}
/* calculate coupling coordinates for all blocks for all channels */
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
if (!block->cpl_in_use)
continue;
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (!block->channel_in_cpl[ch])
continue;
for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy[blk][ch][bnd],
energy[blk][CPL_CH][bnd]);
}
}
}
/* determine which blocks to send new coupling coordinates for */
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
AC3Block *block0 = blk ? &s->blocks[blk-1] : NULL;
memset(block->new_cpl_coords, 0, sizeof(block->new_cpl_coords));
if (block->cpl_in_use) {
/* send new coordinates if this is the first block, if previous
* block did not use coupling but this block does, the channels
* using coupling has changed from the previous block, or the
* coordinate difference from the last block for any channel is
* greater than a threshold value. */
if (blk == 0 || !block0->cpl_in_use) {
for (ch = 1; ch <= s->fbw_channels; ch++)
block->new_cpl_coords[ch] = 1;
} else {
for (ch = 1; ch <= s->fbw_channels; ch++) {
if (!block->channel_in_cpl[ch])
continue;
if (!block0->channel_in_cpl[ch]) {
block->new_cpl_coords[ch] = 1;
} else {
CoefSumType coord_diff = 0;
for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
coord_diff += FFABS(cpl_coords[blk-1][ch][bnd] -
cpl_coords[blk ][ch][bnd]);
}
coord_diff /= s->num_cpl_bands;
if (coord_diff > NEW_CPL_COORD_THRESHOLD)
block->new_cpl_coords[ch] = 1;
}
}
}
}
}
/* calculate final coupling coordinates, taking into account reusing of
coordinates in successive blocks */
for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
blk = 0;
while (blk < s->num_blocks) {
int av_uninit(blk1);
AC3Block *block = &s->blocks[blk];
if (!block->cpl_in_use) {
blk++;
continue;
}
for (ch = 1; ch <= s->fbw_channels; ch++) {
CoefSumType energy_ch, energy_cpl;
if (!block->channel_in_cpl[ch])
continue;
energy_cpl = energy[blk][CPL_CH][bnd];
energy_ch = energy[blk][ch][bnd];
blk1 = blk+1;
while (!s->blocks[blk1].new_cpl_coords[ch] && blk1 < s->num_blocks) {
if (s->blocks[blk1].cpl_in_use) {
energy_cpl += energy[blk1][CPL_CH][bnd];
energy_ch += energy[blk1][ch][bnd];
}
blk1++;
}
cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy_ch, energy_cpl);
}
blk = blk1;
}
}
/* calculate exponents/mantissas for coupling coordinates */
for (blk = 0; blk < s->num_blocks; blk++) {
AC3Block *block = &s->blocks[blk];
if (!block->cpl_in_use)
continue;
#if CONFIG_AC3ENC_FLOAT
s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1],
cpl_coords[blk][1],
s->fbw_channels * 16);
#endif
s->ac3dsp.extract_exponents(block->cpl_coord_exp[1],
fixed_cpl_coords[blk][1],
s->fbw_channels * 16);
for (ch = 1; ch <= s->fbw_channels; ch++) {
int bnd, min_exp, max_exp, master_exp;
if (!block->new_cpl_coords[ch])
continue;
/* determine master exponent */
min_exp = max_exp = block->cpl_coord_exp[ch][0];
for (bnd = 1; bnd < s->num_cpl_bands; bnd++) {
int exp = block->cpl_coord_exp[ch][bnd];
min_exp = FFMIN(exp, min_exp);
max_exp = FFMAX(exp, max_exp);
}
master_exp = ((max_exp - 15) + 2) / 3;
master_exp = FFMAX(master_exp, 0);
while (min_exp < master_exp * 3)
master_exp--;
for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
block->cpl_coord_exp[ch][bnd] = av_clip(block->cpl_coord_exp[ch][bnd] -
master_exp * 3, 0, 15);
}
block->cpl_master_exp[ch] = master_exp;
/* quantize mantissas */
for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
int cpl_exp = block->cpl_coord_exp[ch][bnd];
int cpl_mant = (fixed_cpl_coords[blk][ch][bnd] << (5 + cpl_exp + master_exp * 3)) >> 24;
if (cpl_exp == 15)
cpl_mant >>= 1;
else
cpl_mant -= 16;
block->cpl_coord_mant[ch][bnd] = cpl_mant;
}
}
}
if (CONFIG_EAC3_ENCODER && s->eac3)
ff_eac3_set_cpl_states(s);
}
/*
* Determine rematrixing flags for each block and band.
*/
static void compute_rematrixing_strategy(AC3EncodeContext *s)
{
int nb_coefs;
int blk, bnd;
AC3Block *block, *block0 = NULL;
if (s->channel_mode != AC3_CHMODE_STEREO)
return;
for (blk = 0; blk < s->num_blocks; blk++) {
block = &s->blocks[blk];
block->new_rematrixing_strategy = !blk;
block->num_rematrixing_bands = 4;
if (block->cpl_in_use) {
block->num_rematrixing_bands -= (s->start_freq[CPL_CH] <= 61);
block->num_rematrixing_bands -= (s->start_freq[CPL_CH] == 37);
if (blk && block->num_rematrixing_bands != block0->num_rematrixing_bands)
block->new_rematrixing_strategy = 1;
}
nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]);
if (!s->rematrixing_enabled) {
block0 = block;
continue;
}
for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) {
/* calculate sum of squared coeffs for one band in one block */
int start = ff_ac3_rematrix_band_tab[bnd];
int end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]);
CoefSumType sum[4];
sum_square_butterfly(s, sum, block->mdct_coef[1] + start,
block->mdct_coef[2] + start, end - start);
/* compare sums to determine if rematrixing will be used for this band */
if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1]))
block->rematrixing_flags[bnd] = 1;
else
block->rematrixing_flags[bnd] = 0;
/* determine if new rematrixing flags will be sent */
if (blk &&
block->rematrixing_flags[bnd] != block0->rematrixing_flags[bnd]) {
block->new_rematrixing_strategy = 1;
}
}
block0 = block;
}
}
int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
AC3EncodeContext *s = avctx->priv_data;
int ret;
if (s->options.allow_per_frame_metadata) {
ret = ff_ac3_validate_metadata(s);
if (ret)
return ret;
}
if (s->bit_alloc.sr_code == 1 || s->eac3)
ff_ac3_adjust_frame_size(s);
copy_input_samples(s, (SampleType **)frame->extended_data);
apply_mdct(s);
if (s->fixed_point)
scale_coefficients(s);
clip_coefficients(&s->dsp, s->blocks[0].mdct_coef[1],
AC3_MAX_COEFS * s->num_blocks * s->channels);
s->cpl_on = s->cpl_enabled;
ff_ac3_compute_coupling_strategy(s);
if (s->cpl_on)
apply_channel_coupling(s);
compute_rematrixing_strategy(s);
if (!s->fixed_point)
scale_coefficients(s);
ff_ac3_apply_rematrixing(s);
ff_ac3_process_exponents(s);
ret = ff_ac3_compute_bit_allocation(s);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "Bit allocation failed. Try increasing the bitrate.\n");
return ret;
}
ff_ac3_group_exponents(s);
ff_ac3_quantize_mantissas(s);
if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size)) < 0)
return ret;
ff_ac3_output_frame(s, avpkt->data);
if (frame->pts != AV_NOPTS_VALUE)
avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
*got_packet_ptr = 1;
return 0;
}

View File

@@ -0,0 +1,314 @@
/*
* AC-3 tables
* copyright (c) 2001 Fabrice Bellard
*
* 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
* tables taken directly from the AC-3 spec.
*/
#include "libavutil/channel_layout.h"
#include "avcodec.h"
#include "ac3tab.h"
/**
* Possible frame sizes.
* from ATSC A/52 Table 5.18 Frame Size Code Table.
*/
const uint16_t ff_ac3_frame_size_tab[38][3] = {
{ 64, 69, 96 },
{ 64, 70, 96 },
{ 80, 87, 120 },
{ 80, 88, 120 },
{ 96, 104, 144 },
{ 96, 105, 144 },
{ 112, 121, 168 },
{ 112, 122, 168 },
{ 128, 139, 192 },
{ 128, 140, 192 },
{ 160, 174, 240 },
{ 160, 175, 240 },
{ 192, 208, 288 },
{ 192, 209, 288 },
{ 224, 243, 336 },
{ 224, 244, 336 },
{ 256, 278, 384 },
{ 256, 279, 384 },
{ 320, 348, 480 },
{ 320, 349, 480 },
{ 384, 417, 576 },
{ 384, 418, 576 },
{ 448, 487, 672 },
{ 448, 488, 672 },
{ 512, 557, 768 },
{ 512, 558, 768 },
{ 640, 696, 960 },
{ 640, 697, 960 },
{ 768, 835, 1152 },
{ 768, 836, 1152 },
{ 896, 975, 1344 },
{ 896, 976, 1344 },
{ 1024, 1114, 1536 },
{ 1024, 1115, 1536 },
{ 1152, 1253, 1728 },
{ 1152, 1254, 1728 },
{ 1280, 1393, 1920 },
{ 1280, 1394, 1920 },
};
/**
* Map audio coding mode (acmod) to number of full-bandwidth channels.
* from ATSC A/52 Table 5.8 Audio Coding Mode
*/
const uint8_t ff_ac3_channels_tab[8] = {
2, 1, 2, 3, 3, 4, 4, 5
};
/**
* Map audio coding mode (acmod) to channel layout mask.
*/
const uint16_t avpriv_ac3_channel_layout_tab[8] = {
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_SURROUND,
AV_CH_LAYOUT_2_1,
AV_CH_LAYOUT_4POINT0,
AV_CH_LAYOUT_2_2,
AV_CH_LAYOUT_5POINT0
};
#define COMMON_CHANNEL_MAP \
{ { 0, 1, }, { 0, 1, 2, } },\
{ { 0, }, { 0, 1, } },\
{ { 0, 1, }, { 0, 1, 2, } },\
{ { 0, 2, 1, }, { 0, 2, 1, 3, } },\
{ { 0, 1, 2, }, { 0, 1, 3, 2, } },\
{ { 0, 2, 1, 3, }, { 0, 2, 1, 4, 3, } },
/**
* Table to remap channels from SMPTE order to AC-3 order.
* [channel_mode][lfe][ch]
*/
const uint8_t ff_ac3_enc_channel_map[8][2][6] = {
COMMON_CHANNEL_MAP
{ { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } },
{ { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } },
};
/**
* Table to remap channels from AC-3 order to SMPTE order.
* [channel_mode][lfe][ch]
*/
const uint8_t ff_ac3_dec_channel_map[8][2][6] = {
COMMON_CHANNEL_MAP
{ { 0, 1, 2, 3, }, { 0, 1, 4, 2, 3, } },
{ { 0, 2, 1, 3, 4, }, { 0, 2, 1, 5, 3, 4 } },
};
/* possible frequencies */
const uint16_t ff_ac3_sample_rate_tab[3] = { 48000, 44100, 32000 };
/* possible bitrates */
const uint16_t ff_ac3_bitrate_tab[19] = {
32, 40, 48, 56, 64, 80, 96, 112, 128,
160, 192, 224, 256, 320, 384, 448, 512, 576, 640
};
/**
* Table of bin locations for rematrixing bands
* reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
*/
const uint8_t ff_ac3_rematrix_band_tab[5] = { 13, 25, 37, 61, 253 };
/**
* Table E2.16 Default Coupling Banding Structure
*/
const uint8_t ff_eac3_default_cpl_band_struct[18] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1
};
/* AC-3 MDCT window */
/* MDCT window */
DECLARE_ALIGNED(16, const int16_t, ff_ac3_window)[AC3_WINDOW_SIZE/2] = {
4, 7, 12, 16, 21, 28, 34, 42,
51, 61, 72, 84, 97, 111, 127, 145,
164, 184, 207, 231, 257, 285, 315, 347,
382, 419, 458, 500, 544, 591, 641, 694,
750, 810, 872, 937, 1007, 1079, 1155, 1235,
1318, 1406, 1497, 1593, 1692, 1796, 1903, 2016,
2132, 2253, 2379, 2509, 2644, 2783, 2927, 3076,
3230, 3389, 3552, 3721, 3894, 4072, 4255, 4444,
4637, 4835, 5038, 5246, 5459, 5677, 5899, 6127,
6359, 6596, 6837, 7083, 7334, 7589, 7848, 8112,
8380, 8652, 8927, 9207, 9491, 9778,10069,10363,
10660,10960,11264,11570,11879,12190,12504,12820,
13138,13458,13780,14103,14427,14753,15079,15407,
15735,16063,16392,16720,17049,17377,17705,18032,
18358,18683,19007,19330,19651,19970,20287,20602,
20914,21225,21532,21837,22139,22438,22733,23025,
23314,23599,23880,24157,24430,24699,24964,25225,
25481,25732,25979,26221,26459,26691,26919,27142,
27359,27572,27780,27983,28180,28373,28560,28742,
28919,29091,29258,29420,29577,29729,29876,30018,
30155,30288,30415,30538,30657,30771,30880,30985,
31086,31182,31274,31363,31447,31528,31605,31678,
31747,31814,31877,31936,31993,32046,32097,32145,
32190,32232,32272,32310,32345,32378,32409,32438,
32465,32490,32513,32535,32556,32574,32592,32608,
32623,32636,32649,32661,32671,32681,32690,32698,
32705,32712,32718,32724,32729,32733,32737,32741,
32744,32747,32750,32752,32754,32756,32757,32759,
32760,32761,32762,32763,32764,32764,32765,32765,
32766,32766,32766,32766,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,
};
const uint8_t ff_ac3_log_add_tab[260]= {
0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,
0x36,0x35,0x34,0x34,0x33,0x32,0x31,0x30,0x2f,0x2f,
0x2e,0x2d,0x2c,0x2c,0x2b,0x2a,0x29,0x29,0x28,0x27,
0x26,0x26,0x25,0x24,0x24,0x23,0x23,0x22,0x21,0x21,
0x20,0x20,0x1f,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1b,
0x1b,0x1a,0x1a,0x19,0x19,0x18,0x18,0x17,0x17,0x16,
0x16,0x15,0x15,0x15,0x14,0x14,0x13,0x13,0x13,0x12,
0x12,0x12,0x11,0x11,0x11,0x10,0x10,0x10,0x0f,0x0f,
0x0f,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c,
0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,
0x0a,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,
0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,
0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05,
0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04,
0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03,
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02,
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]= {
{ 0x04d0,0x04f0,0x0580 },
{ 0x04d0,0x04f0,0x0580 },
{ 0x0440,0x0460,0x04b0 },
{ 0x0400,0x0410,0x0450 },
{ 0x03e0,0x03e0,0x0420 },
{ 0x03c0,0x03d0,0x03f0 },
{ 0x03b0,0x03c0,0x03e0 },
{ 0x03b0,0x03b0,0x03d0 },
{ 0x03a0,0x03b0,0x03c0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03a0 },
{ 0x0390,0x03a0,0x03a0 },
{ 0x0390,0x0390,0x03a0 },
{ 0x0390,0x0390,0x03a0 },
{ 0x0380,0x0390,0x03a0 },
{ 0x0380,0x0380,0x03a0 },
{ 0x0370,0x0380,0x03a0 },
{ 0x0370,0x0380,0x03a0 },
{ 0x0360,0x0370,0x0390 },
{ 0x0360,0x0370,0x0390 },
{ 0x0350,0x0360,0x0390 },
{ 0x0350,0x0360,0x0390 },
{ 0x0340,0x0350,0x0380 },
{ 0x0340,0x0350,0x0380 },
{ 0x0330,0x0340,0x0380 },
{ 0x0320,0x0340,0x0370 },
{ 0x0310,0x0320,0x0360 },
{ 0x0300,0x0310,0x0350 },
{ 0x02f0,0x0300,0x0340 },
{ 0x02f0,0x02f0,0x0330 },
{ 0x02f0,0x02f0,0x0320 },
{ 0x02f0,0x02f0,0x0310 },
{ 0x0300,0x02f0,0x0300 },
{ 0x0310,0x0300,0x02f0 },
{ 0x0340,0x0320,0x02f0 },
{ 0x0390,0x0350,0x02f0 },
{ 0x03e0,0x0390,0x0300 },
{ 0x0420,0x03e0,0x0310 },
{ 0x0460,0x0420,0x0330 },
{ 0x0490,0x0450,0x0350 },
{ 0x04a0,0x04a0,0x03c0 },
{ 0x0460,0x0490,0x0410 },
{ 0x0440,0x0460,0x0470 },
{ 0x0440,0x0440,0x04a0 },
{ 0x0520,0x0480,0x0460 },
{ 0x0800,0x0630,0x0440 },
{ 0x0840,0x0840,0x0450 },
{ 0x0840,0x0840,0x04e0 },
};
const uint8_t ff_ac3_bap_tab[64]= {
0, 1, 1, 1, 1, 1, 2, 2, 3, 3,
3, 4, 4, 5, 5, 6, 6, 6, 6, 7,
7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
14, 14, 14, 14, 14, 15, 15, 15, 15, 15,
15, 15, 15, 15,
};
const uint8_t ff_ac3_slow_decay_tab[4]={
0x0f, 0x11, 0x13, 0x15,
};
const uint8_t ff_ac3_fast_decay_tab[4]={
0x3f, 0x53, 0x67, 0x7b,
};
const uint16_t ff_ac3_slow_gain_tab[4]= {
0x540, 0x4d8, 0x478, 0x410,
};
const uint16_t ff_ac3_db_per_bit_tab[4]= {
0x000, 0x700, 0x900, 0xb00,
};
const int16_t ff_ac3_floor_tab[8]= {
0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800,
};
const uint16_t ff_ac3_fast_gain_tab[8]= {
0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400,
};
/**
* Default channel map for a dependent substream defined by acmod
*/
const uint16_t ff_eac3_default_chmap[8] = {
AC3_CHMAP_L | AC3_CHMAP_R, // FIXME Ch1+Ch2
AC3_CHMAP_C,
AC3_CHMAP_L | AC3_CHMAP_R,
AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R,
AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_C_SUR,
AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_C_SUR,
AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR,
AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR
};

View File

@@ -0,0 +1,72 @@
/*
* AC-3 tables
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* 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 AVCODEC_AC3TAB_H
#define AVCODEC_AC3TAB_H
#include "libavutil/common.h"
#include "ac3.h"
#if CONFIG_HARDCODED_TABLES
# define HCONST const
#else
# define HCONST
#endif
extern const uint16_t ff_ac3_frame_size_tab[38][3];
extern const uint8_t ff_ac3_channels_tab[8];
extern av_export const uint16_t avpriv_ac3_channel_layout_tab[8];
extern const uint8_t ff_ac3_enc_channel_map[8][2][6];
extern const uint8_t ff_ac3_dec_channel_map[8][2][6];
extern const uint16_t ff_ac3_sample_rate_tab[3];
extern const uint16_t ff_ac3_bitrate_tab[19];
extern const uint8_t ff_ac3_rematrix_band_tab[5];
extern const uint8_t ff_eac3_default_cpl_band_struct[18];
extern const int16_t ff_ac3_window[AC3_WINDOW_SIZE/2];
extern const uint8_t ff_ac3_log_add_tab[260];
extern const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3];
extern const uint8_t ff_ac3_bap_tab[64];
extern const uint8_t ff_ac3_slow_decay_tab[4];
extern const uint8_t ff_ac3_fast_decay_tab[4];
extern const uint16_t ff_ac3_slow_gain_tab[4];
extern const uint16_t ff_ac3_db_per_bit_tab[4];
extern const int16_t ff_ac3_floor_tab[8];
extern const uint16_t ff_ac3_fast_gain_tab[8];
extern const uint16_t ff_eac3_default_chmap[8];
extern const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1];
extern HCONST uint8_t ff_ac3_bin_to_band_tab[253];
/** Custom channel map locations bitmask
* Other channels described in documentation:
* Lc/Rc pair, Lrs/Rrs pair, Ts, Lsd/Rsd pair,
* Lw/Rw pair, Lvh/Rvh pair, Cvh, Reserved, LFE2
*/
enum CustomChannelMapLocation{
AC3_CHMAP_L= 1<<(15-0),
AC3_CHMAP_C= 1<<(15-1),
AC3_CHMAP_R= 1<<(15-2),
AC3_CHMAP_L_SUR= 1<<(15-3),
AC3_CHMAP_R_SUR = 1<<(15-4),
AC3_CHMAP_C_SUR= 1<<(15-7),
AC3_CHMAP_LFE = 1<<(15-15)
};
#endif /* AVCODEC_AC3TAB_H */

View File

@@ -0,0 +1,155 @@
/*
* various filters for ACELP-based codecs
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 <inttypes.h>
#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "avcodec.h"
#include "acelp_filters.h"
const int16_t ff_acelp_interp_filter[61] = { /* (0.15) */
29443, 28346, 25207, 20449, 14701, 8693,
3143, -1352, -4402, -5865, -5850, -4673,
-2783, -672, 1211, 2536, 3130, 2991,
2259, 1170, 0, -1001, -1652, -1868,
-1666, -1147, -464, 218, 756, 1060,
1099, 904, 550, 135, -245, -514,
-634, -602, -451, -231, 0, 191,
308, 340, 296, 198, 78, -36,
-120, -163, -165, -132, -79, -19,
34, 73, 91, 89, 70, 38,
0,
};
void ff_acelp_interpolate(int16_t* out, const int16_t* in,
const int16_t* filter_coeffs, int precision,
int frac_pos, int filter_length, int length)
{
int n, i;
av_assert1(frac_pos >= 0 && frac_pos < precision);
for (n = 0; n < length; n++) {
int idx = 0;
int v = 0x4000;
for (i = 0; i < filter_length;) {
/* The reference G.729 and AMR fixed point code performs clipping after
each of the two following accumulations.
Since clipping affects only the synthetic OVERFLOW test without
causing an int type overflow, it was moved outside the loop. */
/* R(x):=ac_v[-k+x]
v += R(n-i)*ff_acelp_interp_filter(t+6i)
v += R(n+i+1)*ff_acelp_interp_filter(6-t+6i) */
v += in[n + i] * filter_coeffs[idx + frac_pos];
idx += precision;
i++;
v += in[n - i] * filter_coeffs[idx - frac_pos];
}
if (av_clip_int16(v >> 15) != (v >> 15))
av_log(NULL, AV_LOG_WARNING, "overflow that would need cliping in ff_acelp_interpolate()\n");
out[n] = v >> 15;
}
}
void ff_acelp_interpolatef(float *out, const float *in,
const float *filter_coeffs, int precision,
int frac_pos, int filter_length, int length)
{
int n, i;
for (n = 0; n < length; n++) {
int idx = 0;
float v = 0;
for (i = 0; i < filter_length;) {
v += in[n + i] * filter_coeffs[idx + frac_pos];
idx += precision;
i++;
v += in[n - i] * filter_coeffs[idx - frac_pos];
}
out[n] = v;
}
}
void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2],
const int16_t* in, int length)
{
int i;
int tmp;
for (i = 0; i < length; i++) {
tmp = (hpf_f[0]* 15836LL) >> 13;
tmp += (hpf_f[1]* -7667LL) >> 13;
tmp += 7699 * (in[i] - 2*in[i-1] + in[i-2]);
/* With "+0x800" rounding, clipping is needed
for ALGTHM and SPEECH tests. */
out[i] = av_clip_int16((tmp + 0x800) >> 12);
hpf_f[1] = hpf_f[0];
hpf_f[0] = tmp;
}
}
void ff_acelp_apply_order_2_transfer_function(float *out, const float *in,
const float zero_coeffs[2],
const float pole_coeffs[2],
float gain, float mem[2], int n)
{
int i;
float tmp;
for (i = 0; i < n; i++) {
tmp = gain * in[i] - pole_coeffs[0] * mem[0] - pole_coeffs[1] * mem[1];
out[i] = tmp + zero_coeffs[0] * mem[0] + zero_coeffs[1] * mem[1];
mem[1] = mem[0];
mem[0] = tmp;
}
}
void ff_tilt_compensation(float *mem, float tilt, float *samples, int size)
{
float new_tilt_mem = samples[size - 1];
int i;
for (i = size - 1; i > 0; i--)
samples[i] -= tilt * samples[i - 1];
samples[0] -= tilt * *mem;
*mem = new_tilt_mem;
}
void ff_acelp_filter_init(ACELPFContext *c)
{
c->acelp_interpolatef = ff_acelp_interpolatef;
c->acelp_apply_order_2_transfer_function = ff_acelp_apply_order_2_transfer_function;
if(HAVE_MIPSFPU)
ff_acelp_filter_init_mips(c);
}

View File

@@ -0,0 +1,153 @@
/*
* various filters for ACELP-based codecs
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 AVCODEC_ACELP_FILTERS_H
#define AVCODEC_ACELP_FILTERS_H
#include <stdint.h>
typedef struct ACELPFContext {
/**
* Floating point version of ff_acelp_interpolate()
*/
void (*acelp_interpolatef)(float *out, const float *in,
const float *filter_coeffs, int precision,
int frac_pos, int filter_length, int length);
/**
* Apply an order 2 rational transfer function in-place.
*
* @param out output buffer for filtered speech samples
* @param in input buffer containing speech data (may be the same as out)
* @param zero_coeffs z^-1 and z^-2 coefficients of the numerator
* @param pole_coeffs z^-1 and z^-2 coefficients of the denominator
* @param gain scale factor for final output
* @param mem intermediate values used by filter (should be 0 initially)
* @param n number of samples (should be a multiple of eight)
*/
void (*acelp_apply_order_2_transfer_function)(float *out, const float *in,
const float zero_coeffs[2],
const float pole_coeffs[2],
float gain,
float mem[2], int n);
}ACELPFContext;
/**
* Initialize ACELPFContext.
*/
void ff_acelp_filter_init(ACELPFContext *c);
void ff_acelp_filter_init_mips(ACELPFContext *c);
/**
* low-pass Finite Impulse Response filter coefficients.
*
* Hamming windowed sinc filter with cutoff freq 3/40 of the sampling freq,
* the coefficients are scaled by 2^15.
* This array only contains the right half of the filter.
* This filter is likely identical to the one used in G.729, though this
* could not be determined from the original comments with certainty.
*/
extern const int16_t ff_acelp_interp_filter[61];
/**
* Generic FIR interpolation routine.
* @param[out] out buffer for interpolated data
* @param in input data
* @param filter_coeffs interpolation filter coefficients (0.15)
* @param precision sub sample factor, that is the precision of the position
* @param frac_pos fractional part of position [0..precision-1]
* @param filter_length filter length
* @param length length of output
*
* filter_coeffs contains coefficients of the right half of the symmetric
* interpolation filter. filter_coeffs[0] should the central (unpaired) coefficient.
* See ff_acelp_interp_filter for an example.
*
*/
void ff_acelp_interpolate(int16_t* out, const int16_t* in,
const int16_t* filter_coeffs, int precision,
int frac_pos, int filter_length, int length);
/**
* Floating point version of ff_acelp_interpolate()
*/
void ff_acelp_interpolatef(float *out, const float *in,
const float *filter_coeffs, int precision,
int frac_pos, int filter_length, int length);
/**
* high-pass filtering and upscaling (4.2.5 of G.729).
* @param[out] out output buffer for filtered speech data
* @param[in,out] hpf_f past filtered data from previous (2 items long)
* frames (-0x20000000 <= (14.13) < 0x20000000)
* @param in speech data to process
* @param length input data size
*
* out[i] = 0.93980581 * in[i] - 1.8795834 * in[i-1] + 0.93980581 * in[i-2] +
* 1.9330735 * out[i-1] - 0.93589199 * out[i-2]
*
* The filter has a cut-off frequency of 1/80 of the sampling freq
*
* @note Two items before the top of the in buffer must contain two items from the
* tail of the previous subframe.
*
* @remark It is safe to pass the same array in in and out parameters.
*
* @remark AMR uses mostly the same filter (cut-off frequency 60Hz, same formula,
* but constants differs in 5th sign after comma). Fortunately in
* fixed-point all coefficients are the same as in G.729. Thus this
* routine can be used for the fixed-point AMR decoder, too.
*/
void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2],
const int16_t* in, int length);
/**
* Apply an order 2 rational transfer function in-place.
*
* @param out output buffer for filtered speech samples
* @param in input buffer containing speech data (may be the same as out)
* @param zero_coeffs z^-1 and z^-2 coefficients of the numerator
* @param pole_coeffs z^-1 and z^-2 coefficients of the denominator
* @param gain scale factor for final output
* @param mem intermediate values used by filter (should be 0 initially)
* @param n number of samples
*/
void ff_acelp_apply_order_2_transfer_function(float *out, const float *in,
const float zero_coeffs[2],
const float pole_coeffs[2],
float gain,
float mem[2], int n);
/**
* Apply tilt compensation filter, 1 - tilt * z-1.
*
* @param mem pointer to the filter's state (one single float)
* @param tilt tilt factor
* @param samples array where the filter is applied
* @param size the size of the samples array
*/
void ff_tilt_compensation(float *mem, float tilt, float *samples, int size);
#endif /* AVCODEC_ACELP_FILTERS_H */

View File

@@ -0,0 +1,189 @@
/*
* gain code, gain pitch and pitch delay decoding
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "libavutil/libm.h"
#include "libavutil/mathematics.h"
#include "avcodec.h"
#include "acelp_pitch_delay.h"
#include "celp_math.h"
int ff_acelp_decode_8bit_to_1st_delay3(int ac_index)
{
ac_index += 58;
if(ac_index > 254)
ac_index = 3 * ac_index - 510;
return ac_index;
}
int ff_acelp_decode_4bit_to_2nd_delay3(
int ac_index,
int pitch_delay_min)
{
if(ac_index < 4)
return 3 * (ac_index + pitch_delay_min);
else if(ac_index < 12)
return 3 * pitch_delay_min + ac_index + 6;
else
return 3 * (ac_index + pitch_delay_min) - 18;
}
int ff_acelp_decode_5_6_bit_to_2nd_delay3(
int ac_index,
int pitch_delay_min)
{
return 3 * pitch_delay_min + ac_index - 2;
}
int ff_acelp_decode_9bit_to_1st_delay6(int ac_index)
{
if(ac_index < 463)
return ac_index + 105;
else
return 6 * (ac_index - 368);
}
int ff_acelp_decode_6bit_to_2nd_delay6(
int ac_index,
int pitch_delay_min)
{
return 6 * pitch_delay_min + ac_index - 3;
}
void ff_acelp_update_past_gain(
int16_t* quant_energy,
int gain_corr_factor,
int log2_ma_pred_order,
int erasure)
{
int i;
int avg_gain=quant_energy[(1 << log2_ma_pred_order) - 1]; // (5.10)
for(i=(1 << log2_ma_pred_order) - 1; i>0; i--)
{
avg_gain += quant_energy[i-1];
quant_energy[i] = quant_energy[i-1];
}
if(erasure)
quant_energy[0] = FFMAX(avg_gain >> log2_ma_pred_order, -10240) - 4096; // -10 and -4 in (5.10)
else
quant_energy[0] = (6165 * ((ff_log2_q15(gain_corr_factor) >> 2) - (13 << 13))) >> 13;
}
int16_t ff_acelp_decode_gain_code(
DSPContext *dsp,
int gain_corr_factor,
const int16_t* fc_v,
int mr_energy,
const int16_t* quant_energy,
const int16_t* ma_prediction_coeff,
int subframe_size,
int ma_pred_order)
{
int i;
mr_energy <<= 10;
for(i=0; i<ma_pred_order; i++)
mr_energy += quant_energy[i] * ma_prediction_coeff[i];
#ifdef G729_BITEXACT
mr_energy += (((-6165LL * ff_log2(dsp->scalarproduct_int16(fc_v, fc_v, subframe_size, 0))) >> 3) & ~0x3ff);
mr_energy = (5439 * (mr_energy >> 15)) >> 8; // (0.15) = (0.15) * (7.23)
return bidir_sal(
((ff_exp2(mr_energy & 0x7fff) + 16) >> 5) * (gain_corr_factor >> 1),
(mr_energy >> 15) - 25
);
#else
mr_energy = gain_corr_factor * exp(M_LN10 / (20 << 23) * mr_energy) /
sqrt(dsp->scalarproduct_int16(fc_v, fc_v, subframe_size));
return mr_energy >> 12;
#endif
}
float ff_amr_set_fixed_gain(float fixed_gain_factor, float fixed_mean_energy,
float *prediction_error, float energy_mean,
const float *pred_table)
{
// Equations 66-69:
// ^g_c = ^gamma_gc * 100.05 (predicted dB + mean dB - dB of fixed vector)
// Note 10^(0.05 * -10log(average x2)) = 1/sqrt((average x2)).
float val = fixed_gain_factor *
exp2f(M_LOG2_10 * 0.05 *
(avpriv_scalarproduct_float_c(pred_table, prediction_error, 4) +
energy_mean)) /
sqrtf(fixed_mean_energy);
// update quantified prediction error energy history
memmove(&prediction_error[0], &prediction_error[1],
3 * sizeof(prediction_error[0]));
prediction_error[3] = 20.0 * log10f(fixed_gain_factor);
return val;
}
void ff_decode_pitch_lag(int *lag_int, int *lag_frac, int pitch_index,
const int prev_lag_int, const int subframe,
int third_as_first, int resolution)
{
/* Note n * 10923 >> 15 is floor(x/3) for 0 <= n <= 32767 */
if (subframe == 0 || (subframe == 2 && third_as_first)) {
if (pitch_index < 197)
pitch_index += 59;
else
pitch_index = 3 * pitch_index - 335;
} else {
if (resolution == 4) {
int search_range_min = av_clip(prev_lag_int - 5, PITCH_DELAY_MIN,
PITCH_DELAY_MAX - 9);
// decoding with 4-bit resolution
if (pitch_index < 4) {
// integer only precision for [search_range_min, search_range_min+3]
pitch_index = 3 * (pitch_index + search_range_min) + 1;
} else if (pitch_index < 12) {
// 1/3 fractional precision for [search_range_min+3 1/3, search_range_min+5 2/3]
pitch_index += 3 * search_range_min + 7;
} else {
// integer only precision for [search_range_min+6, search_range_min+9]
pitch_index = 3 * (pitch_index + search_range_min - 6) + 1;
}
} else {
// decoding with 5 or 6 bit resolution, 1/3 fractional precision
pitch_index--;
if (resolution == 5) {
pitch_index += 3 * av_clip(prev_lag_int - 10, PITCH_DELAY_MIN,
PITCH_DELAY_MAX - 19);
} else
pitch_index += 3 * av_clip(prev_lag_int - 5, PITCH_DELAY_MIN,
PITCH_DELAY_MAX - 9);
}
}
*lag_int = pitch_index * 10923 >> 15;
*lag_frac = pitch_index - 3 * *lag_int - 1;
}

View File

@@ -0,0 +1,252 @@
/*
* gain code, gain pitch and pitch delay decoding
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 AVCODEC_ACELP_PITCH_DELAY_H
#define AVCODEC_ACELP_PITCH_DELAY_H
#include <stdint.h>
#include "dsputil.h"
#define PITCH_DELAY_MIN 20
#define PITCH_DELAY_MAX 143
/**
* @brief Decode pitch delay of the first subframe encoded by 8 bits with 1/3
* resolution.
* @param ac_index adaptive codebook index (8 bits)
*
* @return pitch delay in 1/3 units
*
* Pitch delay is coded:
* with 1/3 resolution, 19 < pitch_delay < 85
* integers only, 85 <= pitch_delay <= 143
*/
int ff_acelp_decode_8bit_to_1st_delay3(int ac_index);
/**
* @brief Decode pitch delay of the second subframe encoded by 5 or 6 bits
* with 1/3 precision.
* @param ac_index adaptive codebook index (5 or 6 bits)
* @param pitch_delay_min lower bound (integer) of pitch delay interval
* for second subframe
*
* @return pitch delay in 1/3 units
*
* Pitch delay is coded:
* with 1/3 resolution, -6 < pitch_delay - int(prev_pitch_delay) < 5
*
* @remark The routine is used in G.729 @@8k, AMR @@10.2k, AMR @@7.95k,
* AMR @@7.4k for the second subframe.
*/
int ff_acelp_decode_5_6_bit_to_2nd_delay3(
int ac_index,
int pitch_delay_min);
/**
* @brief Decode pitch delay with 1/3 precision.
* @param ac_index adaptive codebook index (4 bits)
* @param pitch_delay_min lower bound (integer) of pitch delay interval for
* second subframe
*
* @return pitch delay in 1/3 units
*
* Pitch delay is coded:
* integers only, -6 < pitch_delay - int(prev_pitch_delay) <= -2
* with 1/3 resolution, -2 < pitch_delay - int(prev_pitch_delay) < 1
* integers only, 1 <= pitch_delay - int(prev_pitch_delay) < 5
*
* @remark The routine is used in G.729 @@6.4k, AMR @@6.7k, AMR @@5.9k,
* AMR @@5.15k, AMR @@4.75k for the second subframe.
*/
int ff_acelp_decode_4bit_to_2nd_delay3(
int ac_index,
int pitch_delay_min);
/**
* @brief Decode pitch delay of the first subframe encoded by 9 bits
* with 1/6 precision.
* @param ac_index adaptive codebook index (9 bits)
*
* @return pitch delay in 1/6 units
*
* Pitch delay is coded:
* with 1/6 resolution, 17 < pitch_delay < 95
* integers only, 95 <= pitch_delay <= 143
*
* @remark The routine is used in AMR @@12.2k for the first and third subframes.
*/
int ff_acelp_decode_9bit_to_1st_delay6(int ac_index);
/**
* @brief Decode pitch delay of the second subframe encoded by 6 bits
* with 1/6 precision.
* @param ac_index adaptive codebook index (6 bits)
* @param pitch_delay_min lower bound (integer) of pitch delay interval for
* second subframe
*
* @return pitch delay in 1/6 units
*
* Pitch delay is coded:
* with 1/6 resolution, -6 < pitch_delay - int(prev_pitch_delay) < 5
*
* @remark The routine is used in AMR @@12.2k for the second and fourth subframes.
*/
int ff_acelp_decode_6bit_to_2nd_delay6(
int ac_index,
int pitch_delay_min);
/**
* @brief Update past quantized energies
* @param[in,out] quant_energy past quantized energies (5.10)
* @param gain_corr_factor gain correction factor
* @param log2_ma_pred_order log2() of MA prediction order
* @param erasure frame erasure flag
*
* If frame erasure flag is not equal to zero, memory is updated with
* averaged energy, attenuated by 4dB:
* max(avg(quant_energy[i])-4, -14), i=0,ma_pred_order
*
* In normal mode memory is updated with
* Er - Ep = 20 * log10(gain_corr_factor)
*
* @remark The routine is used in G.729 and AMR (all modes).
*/
void ff_acelp_update_past_gain(
int16_t* quant_energy,
int gain_corr_factor,
int log2_ma_pred_order,
int erasure);
/**
* @brief Decode the adaptive codebook gain and add
* correction (4.1.5 and 3.9.1 of G.729).
* @param dsp initialized dsputil context
* @param gain_corr_factor gain correction factor (2.13)
* @param fc_v fixed-codebook vector (2.13)
* @param mr_energy mean innovation energy and fixed-point correction (7.13)
* @param[in,out] quant_energy past quantized energies (5.10)
* @param subframe_size length of subframe
*
* @return quantized fixed-codebook gain (14.1)
*
* The routine implements equations 69, 66 and 71 of the G.729 specification (3.9.1)
*
* Em - mean innovation energy (dB, constant, depends on decoding algorithm)
* Ep - mean-removed predicted energy (dB)
* Er - mean-removed innovation energy (dB)
* Ei - mean energy of the fixed-codebook contribution (dB)
* N - subframe_size
* M - MA (Moving Average) prediction order
* gc - fixed-codebook gain
* gc_p - predicted fixed-codebook gain
*
* Fixed codebook gain is computed using predicted gain gc_p and
* correction factor gain_corr_factor as shown below:
*
* gc = gc_p * gain_corr_factor
*
* The predicted fixed codebook gain gc_p is found by predicting
* the energy of the fixed-codebook contribution from the energy
* of previous fixed-codebook contributions.
*
* mean = 1/N * sum(i,0,N){ fc_v[i] * fc_v[i] }
*
* Ei = 10log(mean)
*
* Er = 10log(1/N * gc^2 * mean) - Em = 20log(gc) + Ei - Em
*
* Replacing Er with Ep and gc with gc_p we will receive:
*
* Ep = 10log(1/N * gc_p^2 * mean) - Em = 20log(gc_p) + Ei - Em
*
* and from above:
*
* gc_p = 10^((Ep - Ei + Em) / 20)
*
* Ep is predicted using past energies and prediction coefficients:
*
* Ep = sum(i,0,M){ ma_prediction_coeff[i] * quant_energy[i] }
*
* gc_p in fixed-point arithmetic is calculated as following:
*
* mean = 1/N * sum(i,0,N){ (fc_v[i] / 2^13) * (fc_v[i] / 2^13) } =
* = 1/N * sum(i,0,N) { fc_v[i] * fc_v[i] } / 2^26
*
* Ei = 10log(mean) = -10log(N) - 10log(2^26) +
* + 10log(sum(i,0,N) { fc_v[i] * fc_v[i] })
*
* Ep - Ei + Em = Ep + Em + 10log(N) + 10log(2^26) -
* - 10log(sum(i,0,N) { fc_v[i] * fc_v[i] }) =
* = Ep + mr_energy - 10log(sum(i,0,N) { fc_v[i] * fc_v[i] })
*
* gc_p = 10 ^ ((Ep - Ei + Em) / 20) =
* = 2 ^ (3.3219 * (Ep - Ei + Em) / 20) = 2 ^ (0.166 * (Ep - Ei + Em))
*
* where
*
* mr_energy = Em + 10log(N) + 10log(2^26)
*
* @remark The routine is used in G.729 and AMR (all modes).
*/
int16_t ff_acelp_decode_gain_code(
DSPContext *dsp,
int gain_corr_factor,
const int16_t* fc_v,
int mr_energy,
const int16_t* quant_energy,
const int16_t* ma_prediction_coeff,
int subframe_size,
int max_pred_order);
/**
* Calculate fixed gain (part of section 6.1.3 of AMR spec)
*
* @param fixed_gain_factor gain correction factor
* @param fixed_mean_energy mean decoded algebraic codebook vector energy
* @param prediction_error vector of the quantified predictor errors of
* the four previous subframes. It is updated by this function.
* @param energy_mean desired mean innovation energy
* @param pred_table table of four moving average coefficients
*/
float ff_amr_set_fixed_gain(float fixed_gain_factor, float fixed_mean_energy,
float *prediction_error, float energy_mean,
const float *pred_table);
/**
* Decode the adaptive codebook index to the integer and fractional parts
* of the pitch lag for one subframe at 1/3 fractional precision.
*
* The choice of pitch lag is described in 3GPP TS 26.090 section 5.6.1.
*
* @param lag_int integer part of pitch lag of the current subframe
* @param lag_frac fractional part of pitch lag of the current subframe
* @param pitch_index parsed adaptive codebook (pitch) index
* @param prev_lag_int integer part of pitch lag for the previous subframe
* @param subframe current subframe number
* @param third_as_first treat the third frame the same way as the first
*/
void ff_decode_pitch_lag(int *lag_int, int *lag_frac, int pitch_index,
const int prev_lag_int, const int subframe,
int third_as_first, int resolution);
#endif /* AVCODEC_ACELP_PITCH_DELAY_H */

View File

@@ -0,0 +1,272 @@
/*
* adaptive and fixed codebook vector operations for ACELP-based codecs
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 <inttypes.h>
#include "libavutil/common.h"
#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "acelp_vectors.h"
const uint8_t ff_fc_2pulses_9bits_track1[16] =
{
1, 3,
6, 8,
11, 13,
16, 18,
21, 23,
26, 28,
31, 33,
36, 38
};
const uint8_t ff_fc_2pulses_9bits_track1_gray[16] =
{
1, 3,
8, 6,
18, 16,
11, 13,
38, 36,
31, 33,
21, 23,
28, 26,
};
const uint8_t ff_fc_2pulses_9bits_track2_gray[32] =
{
0, 2,
5, 4,
12, 10,
7, 9,
25, 24,
20, 22,
14, 15,
19, 17,
36, 31,
21, 26,
1, 6,
16, 11,
27, 29,
32, 30,
39, 37,
34, 35,
};
const uint8_t ff_fc_4pulses_8bits_tracks_13[16] =
{
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75,
};
const uint8_t ff_fc_4pulses_8bits_track_4[32] =
{
3, 4,
8, 9,
13, 14,
18, 19,
23, 24,
28, 29,
33, 34,
38, 39,
43, 44,
48, 49,
53, 54,
58, 59,
63, 64,
68, 69,
73, 74,
78, 79,
};
const float ff_pow_0_7[10] = {
0.700000, 0.490000, 0.343000, 0.240100, 0.168070,
0.117649, 0.082354, 0.057648, 0.040354, 0.028248
};
const float ff_pow_0_75[10] = {
0.750000, 0.562500, 0.421875, 0.316406, 0.237305,
0.177979, 0.133484, 0.100113, 0.075085, 0.056314
};
const float ff_pow_0_55[10] = {
0.550000, 0.302500, 0.166375, 0.091506, 0.050328,
0.027681, 0.015224, 0.008373, 0.004605, 0.002533
};
const float ff_b60_sinc[61] = {
0.898529 , 0.865051 , 0.769257 , 0.624054 , 0.448639 , 0.265289 ,
0.0959167 , -0.0412598 , -0.134338 , -0.178986 , -0.178528 , -0.142609 ,
-0.0849304 , -0.0205078 , 0.0369568 , 0.0773926 , 0.0955200 , 0.0912781 ,
0.0689392 , 0.0357056 , 0.0 , -0.0305481 , -0.0504150 , -0.0570068 ,
-0.0508423 , -0.0350037 , -0.0141602 , 0.00665283, 0.0230713 , 0.0323486 ,
0.0335388 , 0.0275879 , 0.0167847 , 0.00411987, -0.00747681, -0.0156860 ,
-0.0193481 , -0.0183716 , -0.0137634 , -0.00704956, 0.0 , 0.00582886 ,
0.00939941, 0.0103760 , 0.00903320, 0.00604248, 0.00238037, -0.00109863 ,
-0.00366211, -0.00497437, -0.00503540, -0.00402832, -0.00241089, -0.000579834,
0.00103760, 0.00222778, 0.00277710, 0.00271606, 0.00213623, 0.00115967 ,
0.
};
void ff_acelp_fc_pulse_per_track(
int16_t* fc_v,
const uint8_t *tab1,
const uint8_t *tab2,
int pulse_indexes,
int pulse_signs,
int pulse_count,
int bits)
{
int mask = (1 << bits) - 1;
int i;
for(i=0; i<pulse_count; i++)
{
fc_v[i + tab1[pulse_indexes & mask]] +=
(pulse_signs & 1) ? 8191 : -8192; // +/-1 in (2.13)
pulse_indexes >>= bits;
pulse_signs >>= 1;
}
fc_v[tab2[pulse_indexes]] += (pulse_signs & 1) ? 8191 : -8192;
}
void ff_decode_10_pulses_35bits(const int16_t *fixed_index,
AMRFixed *fixed_sparse,
const uint8_t *gray_decode,
int half_pulse_count, int bits)
{
int i;
int mask = (1 << bits) - 1;
fixed_sparse->no_repeat_mask = 0;
fixed_sparse->n = 2 * half_pulse_count;
for (i = 0; i < half_pulse_count; i++) {
const int pos1 = gray_decode[fixed_index[2*i+1] & mask] + i;
const int pos2 = gray_decode[fixed_index[2*i ] & mask] + i;
const float sign = (fixed_index[2*i+1] & (1 << bits)) ? -1.0 : 1.0;
fixed_sparse->x[2*i+1] = pos1;
fixed_sparse->x[2*i ] = pos2;
fixed_sparse->y[2*i+1] = sign;
fixed_sparse->y[2*i ] = pos2 < pos1 ? -sign : sign;
}
}
void ff_acelp_weighted_vector_sum(
int16_t* out,
const int16_t *in_a,
const int16_t *in_b,
int16_t weight_coeff_a,
int16_t weight_coeff_b,
int16_t rounder,
int shift,
int length)
{
int i;
// Clipping required here; breaks OVERFLOW test.
for(i=0; i<length; i++)
out[i] = av_clip_int16((
in_a[i] * weight_coeff_a +
in_b[i] * weight_coeff_b +
rounder) >> shift);
}
void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b,
float weight_coeff_a, float weight_coeff_b, int length)
{
int i;
for(i=0; i<length; i++)
out[i] = weight_coeff_a * in_a[i]
+ weight_coeff_b * in_b[i];
}
void ff_adaptive_gain_control(float *out, const float *in, float speech_energ,
int size, float alpha, float *gain_mem)
{
int i;
float postfilter_energ = avpriv_scalarproduct_float_c(in, in, size);
float gain_scale_factor = 1.0;
float mem = *gain_mem;
if (postfilter_energ)
gain_scale_factor = sqrt(speech_energ / postfilter_energ);
gain_scale_factor *= 1.0 - alpha;
for (i = 0; i < size; i++) {
mem = alpha * mem + gain_scale_factor;
out[i] = in[i] * mem;
}
*gain_mem = mem;
}
void ff_scale_vector_to_given_sum_of_squares(float *out, const float *in,
float sum_of_squares, const int n)
{
int i;
float scalefactor = avpriv_scalarproduct_float_c(in, in, n);
if (scalefactor)
scalefactor = sqrt(sum_of_squares / scalefactor);
for (i = 0; i < n; i++)
out[i] = in[i] * scalefactor;
}
void ff_set_fixed_vector(float *out, const AMRFixed *in, float scale, int size)
{
int i;
for (i=0; i < in->n; i++) {
int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1);
float y = in->y[i] * scale;
if (in->pitch_lag > 0)
do {
out[x] += y;
y *= in->pitch_fac;
x += in->pitch_lag;
} while (x < size && repeats);
}
}
void ff_clear_fixed_vector(float *out, const AMRFixed *in, int size)
{
int i;
for (i=0; i < in->n; i++) {
int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1);
if (in->pitch_lag > 0)
do {
out[x] = 0.0;
x += in->pitch_lag;
} while (x < size && repeats);
}
}
void ff_acelp_vectors_init(ACELPVContext *c)
{
c->weighted_vector_sumf = ff_weighted_vector_sumf;
if(HAVE_MIPSFPU)
ff_acelp_vectors_init_mips(c);
}

View File

@@ -0,0 +1,288 @@
/*
* adaptive and fixed codebook vector operations for ACELP-based codecs
*
* Copyright (c) 2008 Vladimir Voroshilov
*
* 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 AVCODEC_ACELP_VECTORS_H
#define AVCODEC_ACELP_VECTORS_H
#include <stdint.h>
typedef struct ACELPVContext {
/**
* float implementation of weighted sum of two vectors.
* @param[out] out result of addition
* @param in_a first vector
* @param in_b second vector
* @param weight_coeff_a first vector weight coefficient
* @param weight_coeff_a second vector weight coefficient
* @param length vectors length (should be a multiple of two)
*
* @note It is safe to pass the same buffer for out and in_a or in_b.
*/
void (*weighted_vector_sumf)(float *out, const float *in_a, const float *in_b,
float weight_coeff_a, float weight_coeff_b,
int length);
}ACELPVContext;
/**
* Initialize ACELPVContext.
*/
void ff_acelp_vectors_init(ACELPVContext *c);
void ff_acelp_vectors_init_mips(ACELPVContext *c);
/** Sparse representation for the algebraic codebook (fixed) vector */
typedef struct AMRFixed {
int n;
int x[10];
float y[10];
int no_repeat_mask;
int pitch_lag;
float pitch_fac;
} AMRFixed;
/**
* Track|Pulse| Positions
* -------------------------------------------------------------------------
* 1 | 0 | 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75
* -------------------------------------------------------------------------
* 2 | 1 | 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76
* -------------------------------------------------------------------------
* 3 | 2 | 2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77
* -------------------------------------------------------------------------
*
* Table contains only first the pulse indexes.
*
* Used in G.729 @@8k, G.729 @@4.4k, AMR @@7.95k, AMR @@7.40k
*/
extern const uint8_t ff_fc_4pulses_8bits_tracks_13[16];
/**
* Track|Pulse| Positions
* -------------------------------------------------------------------------
* 4 | 3 | 3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, 78
* | | 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69, 74, 79
* -------------------------------------------------------------------------
*
* @remark Track in the table should be read top-to-bottom, left-to-right.
*
* Used in G.729 @@8k, G.729 @@4.4k, AMR @@7.95k, AMR @@7.40k
*/
extern const uint8_t ff_fc_4pulses_8bits_track_4[32];
/**
* Track|Pulse| Positions
* -----------------------------------------
* 1 | 0 | 1, 6, 11, 16, 21, 26, 31, 36
* | | 3, 8, 13, 18, 23, 28, 33, 38
* -----------------------------------------
*
* @remark Track in the table should be read top-to-bottom, left-to-right.
*
* @note (EE) Reference G.729D code also uses gray decoding for each
* pulse index before looking up the value in the table.
*
* Used in G.729 @@6.4k (with gray coding), AMR @@5.9k (without gray coding)
*/
extern const uint8_t ff_fc_2pulses_9bits_track1[16];
extern const uint8_t ff_fc_2pulses_9bits_track1_gray[16];
/**
* Track|Pulse| Positions
* -----------------------------------------
* 2 | 1 | 0, 7, 14, 20, 27, 34, 1, 21
* | | 2, 9, 15, 22, 29, 35, 6, 26
* | | 4,10, 17, 24, 30, 37, 11, 31
* | | 5,12, 19, 25, 32, 39, 16, 36
* -----------------------------------------
*
* @remark Track in the table should be read top-to-bottom, left-to-right.
*
* @note (EE.1) This table (from the reference code) does not comply with
* the specification.
* The specification contains the following table:
*
* Track|Pulse| Positions
* -----------------------------------------
* 2 | 1 | 0, 5, 10, 15, 20, 25, 30, 35
* | | 1, 6, 11, 16, 21, 26, 31, 36
* | | 2, 7, 12, 17, 22, 27, 32, 37
* | | 4, 9, 14, 19, 24, 29, 34, 39
*
* -----------------------------------------
*
* @note (EE.2) Reference G.729D code also uses gray decoding for each
* pulse index before looking up the value in the table.
*
* Used in G.729 @@6.4k (with gray coding)
*/
extern const uint8_t ff_fc_2pulses_9bits_track2_gray[32];
/**
* b60 hamming windowed sinc function coefficients
*/
extern const float ff_b60_sinc[61];
/**
* Table of pow(0.7,n)
*/
extern const float ff_pow_0_7[10];
/**
* Table of pow(0.75,n)
*/
extern const float ff_pow_0_75[10];
/**
* Table of pow(0.55,n)
*/
extern const float ff_pow_0_55[10];
/**
* Decode fixed-codebook vector (3.8 and D.5.8 of G.729, 5.7.1 of AMR).
* @param[out] fc_v decoded fixed codebook vector (2.13)
* @param tab1 table used for first pulse_count pulses
* @param tab2 table used for last pulse
* @param pulse_indexes fixed codebook indexes
* @param pulse_signs signs of the excitation pulses (0 bit value
* means negative sign)
* @param bits number of bits per one pulse index
* @param pulse_count number of pulses decoded using first table
* @param bits length of one pulse index in bits
*
* Used in G.729 @@8k, G.729 @@4.4k, G.729 @@6.4k, AMR @@7.95k, AMR @@7.40k
*/
void ff_acelp_fc_pulse_per_track(int16_t* fc_v,
const uint8_t *tab1,
const uint8_t *tab2,
int pulse_indexes,
int pulse_signs,
int pulse_count,
int bits);
/**
* Decode the algebraic codebook index to pulse positions and signs and
* construct the algebraic codebook vector for MODE_12k2.
*
* @note: The positions and signs are explicitly coded in MODE_12k2.
*
* @param fixed_index positions of the ten pulses
* @param fixed_sparse pointer to the algebraic codebook vector
* @param gray_decode gray decoding table
* @param half_pulse_count number of couples of pulses
* @param bits length of one pulse index in bits
*/
void ff_decode_10_pulses_35bits(const int16_t *fixed_index,
AMRFixed *fixed_sparse,
const uint8_t *gray_decode,
int half_pulse_count, int bits);
/**
* weighted sum of two vectors with rounding.
* @param[out] out result of addition
* @param in_a first vector
* @param in_b second vector
* @param weight_coeff_a first vector weight coefficient
* @param weight_coeff_a second vector weight coefficient
* @param rounder this value will be added to the sum of the two vectors
* @param shift result will be shifted to right by this value
* @param length vectors length
*
* @note It is safe to pass the same buffer for out and in_a or in_b.
*
* out[i] = (in_a[i]*weight_a + in_b[i]*weight_b + rounder) >> shift
*/
void ff_acelp_weighted_vector_sum(int16_t* out,
const int16_t *in_a,
const int16_t *in_b,
int16_t weight_coeff_a,
int16_t weight_coeff_b,
int16_t rounder,
int shift,
int length);
/**
* float implementation of weighted sum of two vectors.
* @param[out] out result of addition
* @param in_a first vector
* @param in_b second vector
* @param weight_coeff_a first vector weight coefficient
* @param weight_coeff_a second vector weight coefficient
* @param length vectors length
*
* @note It is safe to pass the same buffer for out and in_a or in_b.
*/
void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b,
float weight_coeff_a, float weight_coeff_b,
int length);
/**
* Adaptive gain control (as used in AMR postfiltering)
*
* @param out output buffer for filtered speech data
* @param in the input speech buffer (may be the same as out)
* @param speech_energ input energy
* @param size the input buffer size
* @param alpha exponential filter factor
* @param gain_mem a pointer to the filter memory (single float of size)
*/
void ff_adaptive_gain_control(float *out, const float *in, float speech_energ,
int size, float alpha, float *gain_mem);
/**
* Set the sum of squares of a signal by scaling
*
* @param out output samples
* @param in input samples
* @param sum_of_squares new sum of squares
* @param n number of samples
*
* @note If the input is zero (or its energy underflows), the output is zero.
* This is the behavior of AGC in the AMR reference decoder. The QCELP
* reference decoder seems to have undefined behavior.
*
* TIA/EIA/IS-733 2.4.8.3-2/3/4/5, 2.4.8.6
* 3GPP TS 26.090 6.1 (6)
*/
void ff_scale_vector_to_given_sum_of_squares(float *out, const float *in,
float sum_of_squares, const int n);
/**
* Add fixed vector to an array from a sparse representation
*
* @param out fixed vector with pitch sharpening
* @param in sparse fixed vector
* @param scale number to multiply the fixed vector by
* @param size the output vector size
*/
void ff_set_fixed_vector(float *out, const AMRFixed *in, float scale, int size);
/**
* Clear array values set by set_fixed_vector
*
* @param out fixed vector to be cleared
* @param in sparse fixed vector
* @param size the output vector size
*/
void ff_clear_fixed_vector(float *out, const AMRFixed *in, int size);
#endif /* AVCODEC_ACELP_VECTORS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2001-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
*/
/**
* @file
* ADPCM encoder/decoder common header.
*/
#ifndef AVCODEC_ADPCM_H
#define AVCODEC_ADPCM_H
#include <stdint.h>
#define BLKSIZE 1024
typedef struct ADPCMChannelStatus {
int predictor;
int16_t step_index;
int step;
/* for encoding */
int prev_sample;
/* MS version */
int sample1;
int sample2;
int coeff1;
int coeff2;
int idelta;
} ADPCMChannelStatus;
#endif /* AVCODEC_ADPCM_H */

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2001-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
*/
/**
* @file
* ADPCM tables
*/
#include <stdint.h>
/* ff_adpcm_step_table[] and ff_adpcm_index_table[] are from the ADPCM
reference source */
static const int8_t adpcm_index_table2[4] = {
-1, 2,
-1, 2,
};
static const int8_t adpcm_index_table3[8] = {
-1, -1, 1, 2,
-1, -1, 1, 2,
};
const int8_t ff_adpcm_index_table[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};
static const int8_t adpcm_index_table5[32] = {
-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
};
const int8_t const *ff_adpcm_index_tables[4] = {
&adpcm_index_table2[0],
&adpcm_index_table3[0],
&ff_adpcm_index_table[0],
&adpcm_index_table5[0],
};
/**
* This is the step table. Note that many programs use slight deviations from
* this table, but such deviations are negligible:
*/
const int16_t ff_adpcm_step_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
const int16_t ff_adpcm_oki_step_table[49] = {
16, 17, 19, 21, 23, 25, 28, 31, 34, 37,
41, 45, 50, 55, 60, 66, 73, 80, 88, 97,
107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
};
/* These are for MS-ADPCM */
/* ff_adpcm_AdaptationTable[], ff_adpcm_AdaptCoeff1[], and
ff_adpcm_AdaptCoeff2[] are from libsndfile */
const int16_t ff_adpcm_AdaptationTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
/** Divided by 4 to fit in 8-bit integers */
const uint8_t ff_adpcm_AdaptCoeff1[] = {
64, 128, 0, 48, 60, 115, 98
};
/** Divided by 4 to fit in 8-bit integers */
const int8_t ff_adpcm_AdaptCoeff2[] = {
0, -64, 0, 16, 0, -52, -58
};
const int16_t ff_adpcm_yamaha_indexscale[] = {
230, 230, 230, 230, 307, 409, 512, 614,
230, 230, 230, 230, 307, 409, 512, 614
};
const int8_t ff_adpcm_yamaha_difflookup[] = {
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9, -11, -13, -15
};
const int16_t ff_adpcm_afc_coeffs[2][16] = {
{ 0, 2048, 0, 1024, 4096, 3584, 3072, 4608, 4200, 4800, 5120, 2048, 1024, 64512, 64512, 63488 },
{ 0, 0, 2048, 1024, 63488, 64000, 64512, 62976, 63288, 63236, 62464, 63488, 64512, 1024, 0, 0 }
};

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2001-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
*/
/**
* @file
* ADPCM tables
*/
#ifndef AVCODEC_ADPCM_DATA_H
#define AVCODEC_ADPCM_DATA_H
#include <stdint.h>
static const uint8_t ff_adpcm_ima_block_sizes[4] = { 4, 12, 4, 20 };
static const uint8_t ff_adpcm_ima_block_samples[4] = { 16, 32, 8, 32 };
extern const int8_t const *ff_adpcm_index_tables[4];
extern const int8_t ff_adpcm_index_table[16];
extern const int16_t ff_adpcm_step_table[89];
extern const int16_t ff_adpcm_oki_step_table[49];
extern const int16_t ff_adpcm_AdaptationTable[];
extern const uint8_t ff_adpcm_AdaptCoeff1[];
extern const int8_t ff_adpcm_AdaptCoeff2[];
extern const int16_t ff_adpcm_yamaha_indexscale[];
extern const int8_t ff_adpcm_yamaha_difflookup[];
extern const int16_t ff_adpcm_afc_coeffs[2][16];
#endif /* AVCODEC_ADPCM_DATA_H */

View File

@@ -0,0 +1,725 @@
/*
* Copyright (c) 2001-2003 The ffmpeg Project
*
* first version by Francois Revol (revol@free.fr)
* fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
* by 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
*/
#include "avcodec.h"
#include "put_bits.h"
#include "bytestream.h"
#include "adpcm.h"
#include "adpcm_data.h"
#include "internal.h"
/**
* @file
* ADPCM encoders
* See ADPCM decoder reference documents for codec information.
*/
typedef struct TrellisPath {
int nibble;
int prev;
} TrellisPath;
typedef struct TrellisNode {
uint32_t ssd;
int path;
int sample1;
int sample2;
int step;
} TrellisNode;
typedef struct ADPCMEncodeContext {
ADPCMChannelStatus status[6];
TrellisPath *paths;
TrellisNode *node_buf;
TrellisNode **nodep_buf;
uint8_t *trellis_hash;
} ADPCMEncodeContext;
#define FREEZE_INTERVAL 128
static av_cold int adpcm_encode_close(AVCodecContext *avctx);
static av_cold int adpcm_encode_init(AVCodecContext *avctx)
{
ADPCMEncodeContext *s = avctx->priv_data;
uint8_t *extradata;
int i;
int ret = AVERROR(ENOMEM);
if (avctx->channels > 2) {
av_log(avctx, AV_LOG_ERROR, "only stereo or mono is supported\n");
return AVERROR(EINVAL);
}
if (avctx->trellis && (unsigned)avctx->trellis > 16U) {
av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n");
return AVERROR(EINVAL);
}
if (avctx->trellis) {
int frontier = 1 << avctx->trellis;
int max_paths = frontier * FREEZE_INTERVAL;
FF_ALLOC_OR_GOTO(avctx, s->paths,
max_paths * sizeof(*s->paths), error);
FF_ALLOC_OR_GOTO(avctx, s->node_buf,
2 * frontier * sizeof(*s->node_buf), error);
FF_ALLOC_OR_GOTO(avctx, s->nodep_buf,
2 * frontier * sizeof(*s->nodep_buf), error);
FF_ALLOC_OR_GOTO(avctx, s->trellis_hash,
65536 * sizeof(*s->trellis_hash), error);
}
avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id);
switch (avctx->codec->id) {
case AV_CODEC_ID_ADPCM_IMA_WAV:
/* each 16 bits sample gives one nibble
and we have 4 bytes per channel overhead */
avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 /
(4 * avctx->channels) + 1;
/* seems frame_size isn't taken into account...
have to buffer the samples :-( */
avctx->block_align = BLKSIZE;
avctx->bits_per_coded_sample = 4;
break;
case AV_CODEC_ID_ADPCM_IMA_QT:
avctx->frame_size = 64;
avctx->block_align = 34 * avctx->channels;
break;
case AV_CODEC_ID_ADPCM_MS:
/* each 16 bits sample gives one nibble
and we have 7 bytes per channel overhead */
avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 / avctx->channels + 2;
avctx->bits_per_coded_sample = 4;
avctx->block_align = BLKSIZE;
if (!(avctx->extradata = av_malloc(32 + FF_INPUT_BUFFER_PADDING_SIZE)))
goto error;
avctx->extradata_size = 32;
extradata = avctx->extradata;
bytestream_put_le16(&extradata, avctx->frame_size);
bytestream_put_le16(&extradata, 7); /* wNumCoef */
for (i = 0; i < 7; i++) {
bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff1[i] * 4);
bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff2[i] * 4);
}
break;
case AV_CODEC_ID_ADPCM_YAMAHA:
avctx->frame_size = BLKSIZE * 2 / avctx->channels;
avctx->block_align = BLKSIZE;
break;
case AV_CODEC_ID_ADPCM_SWF:
if (avctx->sample_rate != 11025 &&
avctx->sample_rate != 22050 &&
avctx->sample_rate != 44100) {
av_log(avctx, AV_LOG_ERROR, "Sample rate must be 11025, "
"22050 or 44100\n");
ret = AVERROR(EINVAL);
goto error;
}
avctx->frame_size = 512 * (avctx->sample_rate / 11025);
break;
default:
ret = AVERROR(EINVAL);
goto error;
}
return 0;
error:
adpcm_encode_close(avctx);
return ret;
}
static av_cold int adpcm_encode_close(AVCodecContext *avctx)
{
ADPCMEncodeContext *s = avctx->priv_data;
av_freep(&s->paths);
av_freep(&s->node_buf);
av_freep(&s->nodep_buf);
av_freep(&s->trellis_hash);
return 0;
}
static inline uint8_t adpcm_ima_compress_sample(ADPCMChannelStatus *c,
int16_t sample)
{
int delta = sample - c->prev_sample;
int nibble = FFMIN(7, abs(delta) * 4 /
ff_adpcm_step_table[c->step_index]) + (delta < 0) * 8;
c->prev_sample += ((ff_adpcm_step_table[c->step_index] *
ff_adpcm_yamaha_difflookup[nibble]) / 8);
c->prev_sample = av_clip_int16(c->prev_sample);
c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);
return nibble;
}
static inline uint8_t adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c,
int16_t sample)
{
int delta = sample - c->prev_sample;
int diff, step = ff_adpcm_step_table[c->step_index];
int nibble = 8*(delta < 0);
delta= abs(delta);
diff = delta + (step >> 3);
if (delta >= step) {
nibble |= 4;
delta -= step;
}
step >>= 1;
if (delta >= step) {
nibble |= 2;
delta -= step;
}
step >>= 1;
if (delta >= step) {
nibble |= 1;
delta -= step;
}
diff -= delta;
if (nibble & 8)
c->prev_sample -= diff;
else
c->prev_sample += diff;
c->prev_sample = av_clip_int16(c->prev_sample);
c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);
return nibble;
}
static inline uint8_t adpcm_ms_compress_sample(ADPCMChannelStatus *c,
int16_t sample)
{
int predictor, nibble, bias;
predictor = (((c->sample1) * (c->coeff1)) +
(( c->sample2) * (c->coeff2))) / 64;
nibble = sample - predictor;
if (nibble >= 0)
bias = c->idelta / 2;
else
bias = -c->idelta / 2;
nibble = (nibble + bias) / c->idelta;
nibble = av_clip(nibble, -8, 7) & 0x0F;
predictor += ((nibble & 0x08) ? (nibble - 0x10) : nibble) * c->idelta;
c->sample2 = c->sample1;
c->sample1 = av_clip_int16(predictor);
c->idelta = (ff_adpcm_AdaptationTable[nibble] * c->idelta) >> 8;
if (c->idelta < 16)
c->idelta = 16;
return nibble;
}
static inline uint8_t adpcm_yamaha_compress_sample(ADPCMChannelStatus *c,
int16_t sample)
{
int nibble, delta;
if (!c->step) {
c->predictor = 0;
c->step = 127;
}
delta = sample - c->predictor;
nibble = FFMIN(7, abs(delta) * 4 / c->step) + (delta < 0) * 8;
c->predictor += ((c->step * ff_adpcm_yamaha_difflookup[nibble]) / 8);
c->predictor = av_clip_int16(c->predictor);
c->step = (c->step * ff_adpcm_yamaha_indexscale[nibble]) >> 8;
c->step = av_clip(c->step, 127, 24567);
return nibble;
}
static void adpcm_compress_trellis(AVCodecContext *avctx,
const int16_t *samples, uint8_t *dst,
ADPCMChannelStatus *c, int n, int stride)
{
//FIXME 6% faster if frontier is a compile-time constant
ADPCMEncodeContext *s = avctx->priv_data;
const int frontier = 1 << avctx->trellis;
const int version = avctx->codec->id;
TrellisPath *paths = s->paths, *p;
TrellisNode *node_buf = s->node_buf;
TrellisNode **nodep_buf = s->nodep_buf;
TrellisNode **nodes = nodep_buf; // nodes[] is always sorted by .ssd
TrellisNode **nodes_next = nodep_buf + frontier;
int pathn = 0, froze = -1, i, j, k, generation = 0;
uint8_t *hash = s->trellis_hash;
memset(hash, 0xff, 65536 * sizeof(*hash));
memset(nodep_buf, 0, 2 * frontier * sizeof(*nodep_buf));
nodes[0] = node_buf + frontier;
nodes[0]->ssd = 0;
nodes[0]->path = 0;
nodes[0]->step = c->step_index;
nodes[0]->sample1 = c->sample1;
nodes[0]->sample2 = c->sample2;
if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
version == AV_CODEC_ID_ADPCM_IMA_QT ||
version == AV_CODEC_ID_ADPCM_SWF)
nodes[0]->sample1 = c->prev_sample;
if (version == AV_CODEC_ID_ADPCM_MS)
nodes[0]->step = c->idelta;
if (version == AV_CODEC_ID_ADPCM_YAMAHA) {
if (c->step == 0) {
nodes[0]->step = 127;
nodes[0]->sample1 = 0;
} else {
nodes[0]->step = c->step;
nodes[0]->sample1 = c->predictor;
}
}
for (i = 0; i < n; i++) {
TrellisNode *t = node_buf + frontier*(i&1);
TrellisNode **u;
int sample = samples[i * stride];
int heap_pos = 0;
memset(nodes_next, 0, frontier * sizeof(TrellisNode*));
for (j = 0; j < frontier && nodes[j]; j++) {
// higher j have higher ssd already, so they're likely
// to yield a suboptimal next sample too
const int range = (j < frontier / 2) ? 1 : 0;
const int step = nodes[j]->step;
int nidx;
if (version == AV_CODEC_ID_ADPCM_MS) {
const int predictor = ((nodes[j]->sample1 * c->coeff1) +
(nodes[j]->sample2 * c->coeff2)) / 64;
const int div = (sample - predictor) / step;
const int nmin = av_clip(div-range, -8, 6);
const int nmax = av_clip(div+range, -7, 7);
for (nidx = nmin; nidx <= nmax; nidx++) {
const int nibble = nidx & 0xf;
int dec_sample = predictor + nidx * step;
#define STORE_NODE(NAME, STEP_INDEX)\
int d;\
uint32_t ssd;\
int pos;\
TrellisNode *u;\
uint8_t *h;\
dec_sample = av_clip_int16(dec_sample);\
d = sample - dec_sample;\
ssd = nodes[j]->ssd + d*d;\
/* Check for wraparound, skip such samples completely. \
* Note, changing ssd to a 64 bit variable would be \
* simpler, avoiding this check, but it's slower on \
* x86 32 bit at the moment. */\
if (ssd < nodes[j]->ssd)\
goto next_##NAME;\
/* Collapse any two states with the same previous sample value. \
* One could also distinguish states by step and by 2nd to last
* sample, but the effects of that are negligible.
* Since nodes in the previous generation are iterated
* through a heap, they're roughly ordered from better to
* worse, but not strictly ordered. Therefore, an earlier
* node with the same sample value is better in most cases
* (and thus the current is skipped), but not strictly
* in all cases. Only skipping samples where ssd >=
* ssd of the earlier node with the same sample gives
* slightly worse quality, though, for some reason. */ \
h = &hash[(uint16_t) dec_sample];\
if (*h == generation)\
goto next_##NAME;\
if (heap_pos < frontier) {\
pos = heap_pos++;\
} else {\
/* Try to replace one of the leaf nodes with the new \
* one, but try a different slot each time. */\
pos = (frontier >> 1) +\
(heap_pos & ((frontier >> 1) - 1));\
if (ssd > nodes_next[pos]->ssd)\
goto next_##NAME;\
heap_pos++;\
}\
*h = generation;\
u = nodes_next[pos];\
if (!u) {\
av_assert1(pathn < FREEZE_INTERVAL << avctx->trellis);\
u = t++;\
nodes_next[pos] = u;\
u->path = pathn++;\
}\
u->ssd = ssd;\
u->step = STEP_INDEX;\
u->sample2 = nodes[j]->sample1;\
u->sample1 = dec_sample;\
paths[u->path].nibble = nibble;\
paths[u->path].prev = nodes[j]->path;\
/* Sift the newly inserted node up in the heap to \
* restore the heap property. */\
while (pos > 0) {\
int parent = (pos - 1) >> 1;\
if (nodes_next[parent]->ssd <= ssd)\
break;\
FFSWAP(TrellisNode*, nodes_next[parent], nodes_next[pos]);\
pos = parent;\
}\
next_##NAME:;
STORE_NODE(ms, FFMAX(16,
(ff_adpcm_AdaptationTable[nibble] * step) >> 8));
}
} else if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||
version == AV_CODEC_ID_ADPCM_IMA_QT ||
version == AV_CODEC_ID_ADPCM_SWF) {
#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
const int predictor = nodes[j]->sample1;\
const int div = (sample - predictor) * 4 / STEP_TABLE;\
int nmin = av_clip(div - range, -7, 6);\
int nmax = av_clip(div + range, -6, 7);\
if (nmin <= 0)\
nmin--; /* distinguish -0 from +0 */\
if (nmax < 0)\
nmax--;\
for (nidx = nmin; nidx <= nmax; nidx++) {\
const int nibble = nidx < 0 ? 7 - nidx : nidx;\
int dec_sample = predictor +\
(STEP_TABLE *\
ff_adpcm_yamaha_difflookup[nibble]) / 8;\
STORE_NODE(NAME, STEP_INDEX);\
}
LOOP_NODES(ima, ff_adpcm_step_table[step],
av_clip(step + ff_adpcm_index_table[nibble], 0, 88));
} else { //AV_CODEC_ID_ADPCM_YAMAHA
LOOP_NODES(yamaha, step,
av_clip((step * ff_adpcm_yamaha_indexscale[nibble]) >> 8,
127, 24567));
#undef LOOP_NODES
#undef STORE_NODE
}
}
u = nodes;
nodes = nodes_next;
nodes_next = u;
generation++;
if (generation == 255) {
memset(hash, 0xff, 65536 * sizeof(*hash));
generation = 0;
}
// prevent overflow
if (nodes[0]->ssd > (1 << 28)) {
for (j = 1; j < frontier && nodes[j]; j++)
nodes[j]->ssd -= nodes[0]->ssd;
nodes[0]->ssd = 0;
}
// merge old paths to save memory
if (i == froze + FREEZE_INTERVAL) {
p = &paths[nodes[0]->path];
for (k = i; k > froze; k--) {
dst[k] = p->nibble;
p = &paths[p->prev];
}
froze = i;
pathn = 0;
// other nodes might use paths that don't coincide with the frozen one.
// checking which nodes do so is too slow, so just kill them all.
// this also slightly improves quality, but I don't know why.
memset(nodes + 1, 0, (frontier - 1) * sizeof(TrellisNode*));
}
}
p = &paths[nodes[0]->path];
for (i = n - 1; i > froze; i--) {
dst[i] = p->nibble;
p = &paths[p->prev];
}
c->predictor = nodes[0]->sample1;
c->sample1 = nodes[0]->sample1;
c->sample2 = nodes[0]->sample2;
c->step_index = nodes[0]->step;
c->step = nodes[0]->step;
c->idelta = nodes[0]->step;
}
static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
int n, i, ch, st, pkt_size, ret;
const int16_t *samples;
int16_t **samples_p;
uint8_t *dst;
ADPCMEncodeContext *c = avctx->priv_data;
uint8_t *buf;
samples = (const int16_t *)frame->data[0];
samples_p = (int16_t **)frame->extended_data;
st = avctx->channels == 2;
if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF)
pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8;
else
pkt_size = avctx->block_align;
if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size)) < 0)
return ret;
dst = avpkt->data;
switch(avctx->codec->id) {
case AV_CODEC_ID_ADPCM_IMA_WAV:
{
int blocks, j;
blocks = (frame->nb_samples - 1) / 8;
for (ch = 0; ch < avctx->channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
status->prev_sample = samples_p[ch][0];
/* status->step_index = 0;
XXX: not sure how to init the state machine */
bytestream_put_le16(&dst, status->prev_sample);
*dst++ = status->step_index;
*dst++ = 0; /* unknown */
}
/* stereo: 4 bytes (8 samples) for left, 4 bytes for right */
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, avctx->channels * blocks * 8, error);
for (ch = 0; ch < avctx->channels; ch++) {
adpcm_compress_trellis(avctx, &samples_p[ch][1],
buf + ch * blocks * 8, &c->status[ch],
blocks * 8, 1);
}
for (i = 0; i < blocks; i++) {
for (ch = 0; ch < avctx->channels; ch++) {
uint8_t *buf1 = buf + ch * blocks * 8 + i * 8;
for (j = 0; j < 8; j += 2)
*dst++ = buf1[j] | (buf1[j + 1] << 4);
}
}
av_free(buf);
} else {
for (i = 0; i < blocks; i++) {
for (ch = 0; ch < avctx->channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
const int16_t *smp = &samples_p[ch][1 + i * 8];
for (j = 0; j < 8; j += 2) {
uint8_t v = adpcm_ima_compress_sample(status, smp[j ]);
v |= adpcm_ima_compress_sample(status, smp[j + 1]) << 4;
*dst++ = v;
}
}
}
}
break;
}
case AV_CODEC_ID_ADPCM_IMA_QT:
{
PutBitContext pb;
init_put_bits(&pb, dst, pkt_size * 8);
for (ch = 0; ch < avctx->channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7);
put_bits(&pb, 7, status->step_index);
if (avctx->trellis > 0) {
uint8_t buf[64];
adpcm_compress_trellis(avctx, &samples_p[ch][1], buf, status,
64, 1);
for (i = 0; i < 64; i++)
put_bits(&pb, 4, buf[i ^ 1]);
} else {
for (i = 0; i < 64; i += 2) {
int t1, t2;
t1 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i ]);
t2 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i + 1]);
put_bits(&pb, 4, t2);
put_bits(&pb, 4, t1);
}
}
}
flush_put_bits(&pb);
break;
}
case AV_CODEC_ID_ADPCM_SWF:
{
PutBitContext pb;
init_put_bits(&pb, dst, pkt_size * 8);
n = frame->nb_samples - 1;
// store AdpcmCodeSize
put_bits(&pb, 2, 2); // set 4-bit flash adpcm format
// init the encoder state
for (i = 0; i < avctx->channels; i++) {
// clip step so it fits 6 bits
c->status[i].step_index = av_clip(c->status[i].step_index, 0, 63);
put_sbits(&pb, 16, samples[i]);
put_bits(&pb, 6, c->status[i].step_index);
c->status[i].prev_sample = samples[i];
}
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
adpcm_compress_trellis(avctx, samples + avctx->channels, buf,
&c->status[0], n, avctx->channels);
if (avctx->channels == 2)
adpcm_compress_trellis(avctx, samples + avctx->channels + 1,
buf + n, &c->status[1], n,
avctx->channels);
for (i = 0; i < n; i++) {
put_bits(&pb, 4, buf[i]);
if (avctx->channels == 2)
put_bits(&pb, 4, buf[n + i]);
}
av_free(buf);
} else {
for (i = 1; i < frame->nb_samples; i++) {
put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0],
samples[avctx->channels * i]));
if (avctx->channels == 2)
put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1],
samples[2 * i + 1]));
}
}
flush_put_bits(&pb);
break;
}
case AV_CODEC_ID_ADPCM_MS:
for (i = 0; i < avctx->channels; i++) {
int predictor = 0;
*dst++ = predictor;
c->status[i].coeff1 = ff_adpcm_AdaptCoeff1[predictor];
c->status[i].coeff2 = ff_adpcm_AdaptCoeff2[predictor];
}
for (i = 0; i < avctx->channels; i++) {
if (c->status[i].idelta < 16)
c->status[i].idelta = 16;
bytestream_put_le16(&dst, c->status[i].idelta);
}
for (i = 0; i < avctx->channels; i++)
c->status[i].sample2= *samples++;
for (i = 0; i < avctx->channels; i++) {
c->status[i].sample1 = *samples++;
bytestream_put_le16(&dst, c->status[i].sample1);
}
for (i = 0; i < avctx->channels; i++)
bytestream_put_le16(&dst, c->status[i].sample2);
if (avctx->trellis > 0) {
n = avctx->block_align - 7 * avctx->channels;
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
if (avctx->channels == 1) {
adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
avctx->channels);
for (i = 0; i < n; i += 2)
*dst++ = (buf[i] << 4) | buf[i + 1];
} else {
adpcm_compress_trellis(avctx, samples, buf,
&c->status[0], n, avctx->channels);
adpcm_compress_trellis(avctx, samples + 1, buf + n,
&c->status[1], n, avctx->channels);
for (i = 0; i < n; i++)
*dst++ = (buf[i] << 4) | buf[n + i];
}
av_free(buf);
} else {
for (i = 7 * avctx->channels; i < avctx->block_align; i++) {
int nibble;
nibble = adpcm_ms_compress_sample(&c->status[ 0], *samples++) << 4;
nibble |= adpcm_ms_compress_sample(&c->status[st], *samples++);
*dst++ = nibble;
}
}
break;
case AV_CODEC_ID_ADPCM_YAMAHA:
n = frame->nb_samples / 2;
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error);
n *= 2;
if (avctx->channels == 1) {
adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
avctx->channels);
for (i = 0; i < n; i += 2)
*dst++ = buf[i] | (buf[i + 1] << 4);
} else {
adpcm_compress_trellis(avctx, samples, buf,
&c->status[0], n, avctx->channels);
adpcm_compress_trellis(avctx, samples + 1, buf + n,
&c->status[1], n, avctx->channels);
for (i = 0; i < n; i++)
*dst++ = buf[i] | (buf[n + i] << 4);
}
av_free(buf);
} else
for (n *= avctx->channels; n > 0; n--) {
int nibble;
nibble = adpcm_yamaha_compress_sample(&c->status[ 0], *samples++);
nibble |= adpcm_yamaha_compress_sample(&c->status[st], *samples++) << 4;
*dst++ = nibble;
}
break;
default:
return AVERROR(EINVAL);
}
avpkt->size = pkt_size;
*got_packet_ptr = 1;
return 0;
error:
return AVERROR(ENOMEM);
}
static const enum AVSampleFormat sample_fmts[] = {
AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
};
static const enum AVSampleFormat sample_fmts_p[] = {
AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE
};
#define ADPCM_ENCODER(id_, name_, sample_fmts_, long_name_) \
AVCodec ff_ ## name_ ## _encoder = { \
.name = #name_, \
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
.type = AVMEDIA_TYPE_AUDIO, \
.id = id_, \
.priv_data_size = sizeof(ADPCMEncodeContext), \
.init = adpcm_encode_init, \
.encode2 = adpcm_encode_frame, \
.close = adpcm_encode_close, \
.sample_fmts = sample_fmts_, \
}
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, "ADPCM IMA QuickTime");
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, "ADPCM IMA WAV");
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, "ADPCM Microsoft");
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, "ADPCM Shockwave Flash");
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, "ADPCM Yamaha");

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2011 Justin Ruggles
*
* 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 "libavutil/common.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "adx.h"
void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff)
{
double a, b, c;
a = M_SQRT2 - cos(2.0 * M_PI * cutoff / sample_rate);
b = M_SQRT2 - 1.0;
c = (a - sqrt((a + b) * (a - b))) / b;
coeff[0] = lrintf(c * 2.0 * (1 << bits));
coeff[1] = lrintf(-(c * c) * (1 << bits));
}
int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf,
int bufsize, int *header_size, int *coeff)
{
int offset, cutoff;
if (bufsize < 24)
return AVERROR_INVALIDDATA;
if (AV_RB16(buf) != 0x8000)
return AVERROR_INVALIDDATA;
offset = AV_RB16(buf + 2) + 4;
if (offset < 6) {
av_log(avctx, AV_LOG_ERROR, "offset is prior data\n");
return AVERROR_INVALIDDATA;
}
/* if copyright string is within the provided data, validate it */
if (bufsize >= offset && memcmp(buf + offset - 6, "(c)CRI", 6))
return AVERROR_INVALIDDATA;
/* check for encoding=3 block_size=18, sample_size=4 */
if (buf[4] != 3 || buf[5] != 18 || buf[6] != 4) {
avpriv_request_sample(avctx, "Support for this ADX format");
return AVERROR_PATCHWELCOME;
}
/* channels */
avctx->channels = buf[7];
if (avctx->channels <= 0 || avctx->channels > 2)
return AVERROR_INVALIDDATA;
/* sample rate */
avctx->sample_rate = AV_RB32(buf + 8);
if (avctx->sample_rate < 1 ||
avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8))
return AVERROR_INVALIDDATA;
/* bit rate */
avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES;
/* LPC coefficients */
if (coeff) {
cutoff = AV_RB16(buf + 16);
ff_adx_calculate_coeffs(cutoff, avctx->sample_rate, COEFF_BITS, coeff);
}
*header_size = offset;
return 0;
}

View File

@@ -0,0 +1,80 @@
/*
* ADX ADPCM codecs
* Copyright (c) 2001,2003 BERO
*
* 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
* SEGA CRI adx codecs.
*
* Reference documents:
* http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html
* adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/
*/
#ifndef AVCODEC_ADX_H
#define AVCODEC_ADX_H
#include <stdint.h>
#include "avcodec.h"
typedef struct ADXChannelState {
int s1,s2;
} ADXChannelState;
typedef struct ADXContext {
int channels;
ADXChannelState prev[2];
int header_parsed;
int eof;
int cutoff;
int coeff[2];
} ADXContext;
#define COEFF_BITS 12
#define BLOCK_SIZE 18
#define BLOCK_SAMPLES 32
/**
* Calculate LPC coefficients based on cutoff frequency and sample rate.
*
* @param cutoff cutoff frequency
* @param sample_rate sample rate
* @param bits number of bits used to quantize coefficients
* @param[out] coeff 2 quantized LPC coefficients
*/
void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff);
/**
* Decode ADX stream header.
* Sets avctx->channels and avctx->sample_rate.
*
* @param avctx codec context
* @param buf header data
* @param bufsize data size, should be at least 24 bytes
* @param[out] header_size size of ADX header
* @param[out] coeff 2 LPC coefficients, can be NULL
* @return data offset or negative error code if header is invalid
*/
int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf,
int bufsize, int *header_size, int *coeff);
#endif /* AVCODEC_ADX_H */

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2011 Justin Ruggles
*
* 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
* ADX audio parser
*
* Splits packets into individual blocks.
*/
#include "libavutil/intreadwrite.h"
#include "parser.h"
#include "adx.h"
typedef struct ADXParseContext {
ParseContext pc;
int header_size;
int block_size;
int remaining;
} ADXParseContext;
static int adx_parse(AVCodecParserContext *s1,
AVCodecContext *avctx,
const uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size)
{
ADXParseContext *s = s1->priv_data;
ParseContext *pc = &s->pc;
int next = END_NOT_FOUND;
int i;
uint64_t state = pc->state64;
if (!s->header_size) {
for (i = 0; i < buf_size; i++) {
state = (state << 8) | buf[i];
/* check for fixed fields in ADX header for possible match */
if ((state & 0xFFFF0000FFFFFF00) == 0x8000000003120400ULL) {
int channels = state & 0xFF;
int header_size = ((state >> 32) & 0xFFFF) + 4;
if (channels > 0 && header_size >= 8) {
s->header_size = header_size;
s->block_size = BLOCK_SIZE * channels;
s->remaining = i - 7 + s->header_size + s->block_size;
break;
}
}
}
pc->state64 = state;
}
if (s->header_size) {
if (!s->remaining)
s->remaining = s->block_size;
if (s->remaining <= buf_size) {
next = s->remaining;
s->remaining = 0;
} else
s->remaining -= buf_size;
}
if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) {
*poutbuf = NULL;
*poutbuf_size = 0;
return buf_size;
}
s1->duration = BLOCK_SAMPLES;
*poutbuf = buf;
*poutbuf_size = buf_size;
return next;
}
AVCodecParser ff_adx_parser = {
.codec_ids = { AV_CODEC_ID_ADPCM_ADX },
.priv_data_size = sizeof(ADXParseContext),
.parser_parse = adx_parse,
.parser_close = ff_parse_close,
};

View File

@@ -0,0 +1,187 @@
/*
* ADX ADPCM codecs
* Copyright (c) 2001,2003 BERO
*
* 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 "libavutil/intreadwrite.h"
#include "avcodec.h"
#include "adx.h"
#include "get_bits.h"
#include "internal.h"
/**
* @file
* SEGA CRI adx codecs.
*
* Reference documents:
* http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html
* adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/
*/
static av_cold int adx_decode_init(AVCodecContext *avctx)
{
ADXContext *c = avctx->priv_data;
int ret, header_size;
if (avctx->extradata_size >= 24) {
if ((ret = avpriv_adx_decode_header(avctx, avctx->extradata,
avctx->extradata_size, &header_size,
c->coeff)) < 0) {
av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
return AVERROR_INVALIDDATA;
}
c->channels = avctx->channels;
c->header_parsed = 1;
}
avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
return 0;
}
/**
* Decode 32 samples from 18 bytes.
*
* A 16-bit scalar value is applied to 32 residuals, which then have a
* 2nd-order LPC filter applied to it to form the output signal for a single
* channel.
*/
static int adx_decode(ADXContext *c, int16_t *out, int offset,
const uint8_t *in, int ch)
{
ADXChannelState *prev = &c->prev[ch];
GetBitContext gb;
int scale = AV_RB16(in);
int i;
int s0, s1, s2, d;
/* check if this is an EOF packet */
if (scale & 0x8000)
return -1;
init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8);
out += offset;
s1 = prev->s1;
s2 = prev->s2;
for (i = 0; i < BLOCK_SAMPLES; i++) {
d = get_sbits(&gb, 4);
s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS;
s2 = s1;
s1 = av_clip_int16(s0);
*out++ = s1;
}
prev->s1 = s1;
prev->s2 = s2;
return 0;
}
static int adx_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
AVFrame *frame = data;
int buf_size = avpkt->size;
ADXContext *c = avctx->priv_data;
int16_t **samples;
int samples_offset;
const uint8_t *buf = avpkt->data;
const uint8_t *buf_end = buf + avpkt->size;
int num_blocks, ch, ret;
if (c->eof) {
*got_frame_ptr = 0;
return buf_size;
}
if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) {
int header_size;
if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size,
c->coeff)) < 0) {
av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
return AVERROR_INVALIDDATA;
}
c->channels = avctx->channels;
c->header_parsed = 1;
if (buf_size < header_size)
return AVERROR_INVALIDDATA;
buf += header_size;
buf_size -= header_size;
}
if (!c->header_parsed)
return AVERROR_INVALIDDATA;
/* calculate number of blocks in the packet */
num_blocks = buf_size / (BLOCK_SIZE * c->channels);
/* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF
packet */
if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) {
if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) {
c->eof = 1;
*got_frame_ptr = 0;
return avpkt->size;
}
return AVERROR_INVALIDDATA;
}
/* get output buffer */
frame->nb_samples = num_blocks * BLOCK_SAMPLES;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
samples = (int16_t **)frame->extended_data;
samples_offset = 0;
while (num_blocks--) {
for (ch = 0; ch < c->channels; ch++) {
if (buf_end - buf < BLOCK_SIZE || adx_decode(c, samples[ch], samples_offset, buf, ch)) {
c->eof = 1;
buf = avpkt->data + avpkt->size;
break;
}
buf_size -= BLOCK_SIZE;
buf += BLOCK_SIZE;
}
samples_offset += BLOCK_SAMPLES;
}
*got_frame_ptr = 1;
return buf - avpkt->data;
}
static void adx_decode_flush(AVCodecContext *avctx)
{
ADXContext *c = avctx->priv_data;
memset(c->prev, 0, sizeof(c->prev));
c->eof = 0;
}
AVCodec ff_adpcm_adx_decoder = {
.name = "adpcm_adx",
.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_ADPCM_ADX,
.priv_data_size = sizeof(ADXContext),
.init = adx_decode_init,
.decode = adx_decode_frame,
.flush = adx_decode_flush,
.capabilities = CODEC_CAP_DR1,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
};

View File

@@ -0,0 +1,169 @@
/*
* ADX ADPCM codecs
* Copyright (c) 2001,2003 BERO
*
* 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 "adx.h"
#include "bytestream.h"
#include "internal.h"
#include "put_bits.h"
/**
* @file
* SEGA CRI adx codecs.
*
* Reference documents:
* http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html
* adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/
*/
static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav,
ADXChannelState *prev, int channels)
{
PutBitContext pb;
int scale;
int i, j;
int s0, s1, s2, d;
int max = 0;
int min = 0;
int data[BLOCK_SAMPLES];
s1 = prev->s1;
s2 = prev->s2;
for (i = 0, j = 0; j < 32; i += channels, j++) {
s0 = wav[i];
d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
data[j] = d;
if (max < d)
max = d;
if (min > d)
min = d;
s2 = s1;
s1 = s0;
}
prev->s1 = s1;
prev->s2 = s2;
if (max == 0 && min == 0) {
memset(adx, 0, BLOCK_SIZE);
return;
}
if (max / 7 > -min / 8)
scale = max / 7;
else
scale = -min / 8;
if (scale == 0)
scale = 1;
AV_WB16(adx, scale);
init_put_bits(&pb, adx + 2, 16);
for (i = 0; i < BLOCK_SAMPLES; i++)
put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7));
flush_put_bits(&pb);
}
#define HEADER_SIZE 36
static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize)
{
ADXContext *c = avctx->priv_data;
bytestream_put_be16(&buf, 0x8000); /* header signature */
bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */
bytestream_put_byte(&buf, 3); /* encoding */
bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */
bytestream_put_byte(&buf, 4); /* sample size */
bytestream_put_byte(&buf, avctx->channels); /* channels */
bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */
bytestream_put_be32(&buf, 0); /* total sample count */
bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */
bytestream_put_byte(&buf, 3); /* version */
bytestream_put_byte(&buf, 0); /* flags */
bytestream_put_be32(&buf, 0); /* unknown */
bytestream_put_be32(&buf, 0); /* loop enabled */
bytestream_put_be16(&buf, 0); /* padding */
bytestream_put_buffer(&buf, "(c)CRI", 6); /* copyright signature */
return HEADER_SIZE;
}
static av_cold int adx_encode_init(AVCodecContext *avctx)
{
ADXContext *c = avctx->priv_data;
if (avctx->channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
return AVERROR(EINVAL);
}
avctx->frame_size = BLOCK_SAMPLES;
/* the cutoff can be adjusted, but this seems to work pretty well */
c->cutoff = 500;
ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff);
return 0;
}
static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
ADXContext *c = avctx->priv_data;
const int16_t *samples = (const int16_t *)frame->data[0];
uint8_t *dst;
int ch, out_size, ret;
out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE;
if ((ret = ff_alloc_packet2(avctx, avpkt, out_size)) < 0)
return ret;
dst = avpkt->data;
if (!c->header_parsed) {
int hdrsize;
if ((hdrsize = adx_encode_header(avctx, dst, avpkt->size)) < 0) {
av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
return AVERROR(EINVAL);
}
dst += hdrsize;
c->header_parsed = 1;
}
for (ch = 0; ch < avctx->channels; ch++) {
adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels);
dst += BLOCK_SIZE;
}
*got_packet_ptr = 1;
return 0;
}
AVCodec ff_adpcm_adx_encoder = {
.name = "adpcm_adx",
.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_ADPCM_ADX,
.priv_data_size = sizeof(ADXContext),
.init = adx_encode_init,
.encode2 = adx_encode_frame,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
};

View File

@@ -0,0 +1,481 @@
/*
* Apple Intermediate Codec decoder
*
* Copyright (c) 2013 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
*/
#include "avcodec.h"
#include "bytestream.h"
#include "dsputil.h"
#include "internal.h"
#include "get_bits.h"
#include "golomb.h"
#include "unary.h"
#define AIC_HDR_SIZE 24
#define AIC_BAND_COEFFS (64 + 32 + 192 + 96)
enum AICBands {
COEFF_LUMA = 0,
COEFF_CHROMA,
COEFF_LUMA_EXT,
COEFF_CHROMA_EXT,
NUM_BANDS
};
static const int aic_num_band_coeffs[NUM_BANDS] = { 64, 32, 192, 96 };
static const int aic_band_off[NUM_BANDS] = { 0, 64, 96, 288 };
static const uint8_t aic_quant_matrix[64] = {
8, 16, 19, 22, 22, 26, 26, 27,
16, 16, 22, 22, 26, 27, 27, 29,
19, 22, 26, 26, 27, 29, 29, 35,
22, 24, 27, 27, 29, 32, 34, 38,
26, 27, 29, 29, 32, 35, 38, 46,
27, 29, 34, 34, 35, 40, 46, 56,
29, 34, 34, 37, 40, 48, 56, 69,
34, 37, 38, 40, 48, 58, 69, 83,
};
static const uint8_t aic_y_scan[64] = {
0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15,
47, 43, 46, 45, 42, 39, 35, 38,
41, 44, 40, 37, 34, 33, 36, 32,
16, 20, 17, 18, 21, 24, 28, 25,
22, 19, 23, 26, 29, 30, 27, 31,
63, 59, 62, 61, 58, 55, 51, 54,
57, 60, 56, 53, 50, 49, 52, 48,
};
static const uint8_t aic_y_ext_scan[192] = {
64, 72, 65, 66, 73, 80, 88, 81,
74, 67, 75, 82, 89, 90, 83, 91,
0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15,
16, 20, 17, 18, 21, 24, 28, 25,
22, 19, 23, 26, 29, 30, 27, 31,
155, 147, 154, 153, 146, 139, 131, 138,
145, 152, 144, 137, 130, 129, 136, 128,
47, 43, 46, 45, 42, 39, 35, 38,
41, 44, 40, 37, 34, 33, 36, 32,
63, 59, 62, 61, 58, 55, 51, 54,
57, 60, 56, 53, 50, 49, 52, 48,
96, 104, 97, 98, 105, 112, 120, 113,
106, 99, 107, 114, 121, 122, 115, 123,
68, 76, 69, 70, 77, 84, 92, 85,
78, 71, 79, 86, 93, 94, 87, 95,
100, 108, 101, 102, 109, 116, 124, 117,
110, 103, 111, 118, 125, 126, 119, 127,
187, 179, 186, 185, 178, 171, 163, 170,
177, 184, 176, 169, 162, 161, 168, 160,
159, 151, 158, 157, 150, 143, 135, 142,
149, 156, 148, 141, 134, 133, 140, 132,
191, 183, 190, 189, 182, 175, 167, 174,
181, 188, 180, 173, 166, 165, 172, 164,
};
static const uint8_t aic_c_scan[64] = {
0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15,
31, 27, 30, 29, 26, 23, 19, 22,
25, 28, 24, 21, 18, 17, 20, 16,
32, 36, 33, 34, 37, 40, 44, 41,
38, 35, 39, 42, 45, 46, 43, 47,
63, 59, 62, 61, 58, 55, 51, 54,
57, 60, 56, 53, 50, 49, 52, 48,
};
static const uint8_t aic_c_ext_scan[192] = {
16, 24, 17, 18, 25, 32, 40, 33,
26, 19, 27, 34, 41, 42, 35, 43,
0, 4, 1, 2, 5, 8, 12, 9,
6, 3, 7, 10, 13, 14, 11, 15,
20, 28, 21, 22, 29, 36, 44, 37,
30, 23, 31, 38, 45, 46, 39, 47,
95, 87, 94, 93, 86, 79, 71, 78,
85, 92, 84, 77, 70, 69, 76, 68,
63, 59, 62, 61, 58, 55, 51, 54,
57, 60, 56, 53, 50, 49, 52, 48,
91, 83, 90, 89, 82, 75, 67, 74,
81, 88, 80, 73, 66, 65, 72, 64,
112, 120, 113, 114, 121, 128, 136, 129,
122, 115, 123, 130, 137, 138, 131, 139,
96, 100, 97, 98, 101, 104, 108, 105,
102, 99, 103, 106, 109, 110, 107, 111,
116, 124, 117, 118, 125, 132, 140, 133,
126, 119, 127, 134, 141, 142, 135, 143,
191, 183, 190, 189, 182, 175, 167, 174,
181, 188, 180, 173, 166, 165, 172, 164,
159, 155, 158, 157, 154, 151, 147, 150,
153, 156, 152, 149, 146, 145, 148, 144,
187, 179, 186, 185, 178, 171, 163, 170,
177, 184, 176, 169, 162, 161, 168, 160,
};
static const uint8_t *aic_scan[NUM_BANDS] = {
aic_y_scan, aic_c_scan, aic_y_ext_scan, aic_c_ext_scan
};
typedef struct AICContext {
AVCodecContext *avctx;
AVFrame *frame;
DSPContext dsp;
ScanTable scantable;
int num_x_slices;
int slice_width;
int mb_width, mb_height;
int quant;
int interlaced;
int16_t *slice_data;
int16_t *data_ptr[NUM_BANDS];
DECLARE_ALIGNED(16, int16_t, block)[64];
} AICContext;
static int aic_decode_header(AICContext *ctx, const uint8_t *src, int size)
{
uint32_t frame_size;
int width, height;
if (src[0] != 1) {
av_log(ctx->avctx, AV_LOG_ERROR, "Invalid version %d\n", src[0]);
return AVERROR_INVALIDDATA;
}
if (src[1] != AIC_HDR_SIZE - 2) {
av_log(ctx->avctx, AV_LOG_ERROR, "Invalid header size %d\n", src[1]);
return AVERROR_INVALIDDATA;
}
frame_size = AV_RB32(src + 2);
width = AV_RB16(src + 6);
height = AV_RB16(src + 8);
if (frame_size > size) {
av_log(ctx->avctx, AV_LOG_ERROR, "Frame size should be %d got %d\n",
frame_size, size);
return AVERROR_INVALIDDATA;
}
if (width != ctx->avctx->width || height != ctx->avctx->height) {
av_log(ctx->avctx, AV_LOG_ERROR,
"Picture dimension changed: old: %d x %d, new: %d x %d\n",
ctx->avctx->width, ctx->avctx->height, width, height);
return AVERROR_INVALIDDATA;
}
ctx->quant = src[15];
ctx->interlaced = ((src[16] >> 4) == 3);
return 0;
}
#define GET_CODE(val, type, add_bits) \
do { \
if (type) \
val = get_ue_golomb(gb); \
else \
val = get_unary(gb, 1, 31); \
if (add_bits) \
val = (val << add_bits) + get_bits(gb, add_bits); \
} while (0)
static int aic_decode_coeffs(GetBitContext *gb, int16_t *dst,
int band, int slice_width, int force_chroma)
{
int has_skips, coeff_type, coeff_bits, skip_type, skip_bits;
const int num_coeffs = aic_num_band_coeffs[band];
const uint8_t *scan = aic_scan[band | force_chroma];
int mb, idx;
unsigned val;
has_skips = get_bits1(gb);
coeff_type = get_bits1(gb);
coeff_bits = get_bits(gb, 3);
if (has_skips) {
skip_type = get_bits1(gb);
skip_bits = get_bits(gb, 3);
for (mb = 0; mb < slice_width; mb++) {
idx = -1;
do {
GET_CODE(val, skip_type, skip_bits);
if (val >= 0x10000)
return AVERROR_INVALIDDATA;
idx += val + 1;
if (idx >= num_coeffs)
break;
GET_CODE(val, coeff_type, coeff_bits);
val++;
if (val >= 0x10000)
return AVERROR_INVALIDDATA;
dst[scan[idx]] = val;
} while (idx < num_coeffs - 1);
dst += num_coeffs;
}
} else {
for (mb = 0; mb < slice_width; mb++) {
for (idx = 0; idx < num_coeffs; idx++) {
GET_CODE(val, coeff_type, coeff_bits);
if (val >= 0x10000)
return AVERROR_INVALIDDATA;
dst[scan[idx]] = val;
}
dst += num_coeffs;
}
}
return 0;
}
static void recombine_block(int16_t *dst, const uint8_t *scan,
int16_t **base, int16_t **ext)
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++)
dst[scan[i * 8 + j]] = (*base)[j];
for (j = 0; j < 4; j++)
dst[scan[i * 8 + j + 4]] = (*ext)[j];
*base += 4;
*ext += 4;
}
for (; i < 8; i++) {
for (j = 0; j < 8; j++)
dst[scan[i * 8 + j]] = (*ext)[j];
*ext += 8;
}
}
static void recombine_block_il(int16_t *dst, const uint8_t *scan,
int16_t **base, int16_t **ext,
int block_no)
{
int i, j;
if (block_no < 2) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 4; j++)
dst[scan[i * 8 + j]] = (*base)[j];
for (j = 0; j < 4; j++)
dst[scan[i * 8 + j + 4]] = (*ext)[j];
*base += 4;
*ext += 4;
}
} else {
for (i = 0; i < 64; i++)
dst[scan[i]] = (*ext)[i];
*ext += 64;
}
}
static void unquant_block(int16_t *block, int q)
{
int i;
for (i = 0; i < 64; i++) {
int val = (uint16_t)block[i];
int sign = val & 1;
block[i] = (((val >> 1) ^ -sign) * q * aic_quant_matrix[i] >> 4)
+ sign;
}
}
static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y,
const uint8_t *src, int src_size)
{
GetBitContext gb;
int ret, i, mb, blk;
int slice_width = FFMIN(ctx->slice_width, ctx->mb_width - mb_x);
uint8_t *Y, *C[2];
uint8_t *dst;
int16_t *base_y = ctx->data_ptr[COEFF_LUMA];
int16_t *base_c = ctx->data_ptr[COEFF_CHROMA];
int16_t *ext_y = ctx->data_ptr[COEFF_LUMA_EXT];
int16_t *ext_c = ctx->data_ptr[COEFF_CHROMA_EXT];
const int ystride = ctx->frame->linesize[0];
Y = ctx->frame->data[0] + mb_x * 16 + mb_y * 16 * ystride;
for (i = 0; i < 2; i++)
C[i] = ctx->frame->data[i + 1] + mb_x * 8
+ mb_y * 8 * ctx->frame->linesize[i + 1];
init_get_bits(&gb, src, src_size * 8);
memset(ctx->slice_data, 0,
sizeof(*ctx->slice_data) * slice_width * AIC_BAND_COEFFS);
for (i = 0; i < NUM_BANDS; i++)
if ((ret = aic_decode_coeffs(&gb, ctx->data_ptr[i],
i, slice_width,
!ctx->interlaced)) < 0)
return ret;
for (mb = 0; mb < slice_width; mb++) {
for (blk = 0; blk < 4; blk++) {
if (!ctx->interlaced)
recombine_block(ctx->block, ctx->scantable.permutated,
&base_y, &ext_y);
else
recombine_block_il(ctx->block, ctx->scantable.permutated,
&base_y, &ext_y, blk);
unquant_block(ctx->block, ctx->quant);
ctx->dsp.idct(ctx->block);
if (!ctx->interlaced) {
dst = Y + (blk >> 1) * 8 * ystride + (blk & 1) * 8;
ctx->dsp.put_signed_pixels_clamped(ctx->block, dst,
ystride);
} else {
dst = Y + (blk & 1) * 8 + (blk >> 1) * ystride;
ctx->dsp.put_signed_pixels_clamped(ctx->block, dst,
ystride * 2);
}
}
Y += 16;
for (blk = 0; blk < 2; blk++) {
recombine_block(ctx->block, ctx->scantable.permutated,
&base_c, &ext_c);
unquant_block(ctx->block, ctx->quant);
ctx->dsp.idct(ctx->block);
ctx->dsp.put_signed_pixels_clamped(ctx->block, C[blk],
ctx->frame->linesize[blk + 1]);
C[blk] += 8;
}
}
return 0;
}
static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt)
{
AICContext *ctx = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
GetByteContext gb;
uint32_t off;
int x, y, ret;
int slice_size;
ctx->frame = data;
ctx->frame->pict_type = AV_PICTURE_TYPE_I;
ctx->frame->key_frame = 1;
off = FFALIGN(AIC_HDR_SIZE + ctx->num_x_slices * ctx->mb_height * 2, 4);
if (buf_size < off) {
av_log(avctx, AV_LOG_ERROR, "Too small frame\n");
return AVERROR_INVALIDDATA;
}
if ((ret = aic_decode_header(ctx, buf, buf_size)) < 0)
return ret;
if ((ret = ff_get_buffer(avctx, ctx->frame, 0)) < 0)
return ret;
bytestream2_init(&gb, buf + AIC_HDR_SIZE,
ctx->num_x_slices * ctx->mb_height * 2);
for (y = 0; y < ctx->mb_height; y++) {
for (x = 0; x < ctx->mb_width; x += ctx->slice_width) {
slice_size = bytestream2_get_le16(&gb) * 4;
if (slice_size + off > buf_size || !slice_size) {
av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
return AVERROR_INVALIDDATA;
}
if ((ret = aic_decode_slice(ctx, x, y,
buf + off, slice_size)) < 0)
return ret;
off += slice_size;
}
}
*got_frame = 1;
return avpkt->size;
}
static av_cold int aic_decode_init(AVCodecContext *avctx)
{
AICContext *ctx = avctx->priv_data;
int i;
uint8_t scan[64];
ctx->avctx = avctx;
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
ff_dsputil_init(&ctx->dsp, avctx);
for (i = 0; i < 64; i++)
scan[i] = i;
ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, scan);
ctx->mb_width = FFALIGN(avctx->width, 16) >> 4;
ctx->mb_height = FFALIGN(avctx->height, 16) >> 4;
ctx->num_x_slices = 16;
ctx->slice_width = ctx->mb_width / 16;
for (i = 1; i < 32; i++) {
if (!(ctx->mb_width % i) && (ctx->mb_width / i < 32)) {
ctx->slice_width = ctx->mb_width / i;
ctx->num_x_slices = i;
break;
}
}
ctx->slice_data = av_malloc(ctx->slice_width * AIC_BAND_COEFFS
* sizeof(*ctx->slice_data));
if (!ctx->slice_data) {
av_log(avctx, AV_LOG_ERROR, "Error allocating slice buffer\n");
return AVERROR(ENOMEM);
}
for (i = 0; i < NUM_BANDS; i++)
ctx->data_ptr[i] = ctx->slice_data + ctx->slice_width
* aic_band_off[i];
return 0;
}
static av_cold int aic_decode_close(AVCodecContext *avctx)
{
AICContext *ctx = avctx->priv_data;
av_freep(&ctx->slice_data);
return 0;
}
AVCodec ff_aic_decoder = {
.name = "aic",
.long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_AIC,
.priv_data_size = sizeof(AICContext),
.init = aic_decode_init,
.close = aic_decode_close,
.decode = aic_decode_frame,
.capabilities = CODEC_CAP_DR1,
};

View File

@@ -0,0 +1,638 @@
/*
* ALAC (Apple Lossless Audio Codec) decoder
* Copyright (c) 2005 David Hammerton
*
* 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
* ALAC (Apple Lossless Audio Codec) decoder
* @author 2005 David Hammerton
* @see http://crazney.net/programs/itunes/alac.html
*
* Note: This decoder expects a 36-byte QuickTime atom to be
* passed through the extradata[_size] fields. This atom is tacked onto
* the end of an 'alac' stsd atom and has the following format:
*
* 32bit atom size
* 32bit tag ("alac")
* 32bit tag version (0)
* 32bit samples per frame (used when not set explicitly in the frames)
* 8bit compatible version (0)
* 8bit sample size
* 8bit history mult (40)
* 8bit initial history (10)
* 8bit rice param limit (14)
* 8bit channels
* 16bit maxRun (255)
* 32bit max coded frame size (0 means unknown)
* 32bit average bitrate (0 means unknown)
* 32bit samplerate
*/
#include "libavutil/channel_layout.h"
#include "avcodec.h"
#include "get_bits.h"
#include "bytestream.h"
#include "internal.h"
#include "thread.h"
#include "unary.h"
#include "mathops.h"
#include "alac_data.h"
#define ALAC_EXTRADATA_SIZE 36
typedef struct {
AVCodecContext *avctx;
GetBitContext gb;
int channels;
int32_t *predict_error_buffer[2];
int32_t *output_samples_buffer[2];
int32_t *extra_bits_buffer[2];
uint32_t max_samples_per_frame;
uint8_t sample_size;
uint8_t rice_history_mult;
uint8_t rice_initial_history;
uint8_t rice_limit;
int extra_bits; /**< number of extra bits beyond 16-bit */
int nb_samples; /**< number of samples in the current frame */
int direct_output;
} ALACContext;
static inline unsigned int decode_scalar(GetBitContext *gb, int k, int bps)
{
unsigned int x = get_unary_0_9(gb);
if (x > 8) { /* RICE THRESHOLD */
/* use alternative encoding */
x = get_bits_long(gb, bps);
} else if (k != 1) {
int extrabits = show_bits(gb, k);
/* multiply x by 2^k - 1, as part of their strange algorithm */
x = (x << k) - x;
if (extrabits > 1) {
x += extrabits - 1;
skip_bits(gb, k);
} else
skip_bits(gb, k - 1);
}
return x;
}
static int rice_decompress(ALACContext *alac, int32_t *output_buffer,
int nb_samples, int bps, int rice_history_mult)
{
int i;
unsigned int history = alac->rice_initial_history;
int sign_modifier = 0;
for (i = 0; i < nb_samples; i++) {
int k;
unsigned int x;
if(get_bits_left(&alac->gb) <= 0)
return -1;
/* calculate rice param and decode next value */
k = av_log2((history >> 9) + 3);
k = FFMIN(k, alac->rice_limit);
x = decode_scalar(&alac->gb, k, bps);
x += sign_modifier;
sign_modifier = 0;
output_buffer[i] = (x >> 1) ^ -(x & 1);
/* update the history */
if (x > 0xffff)
history = 0xffff;
else
history += x * rice_history_mult -
((history * rice_history_mult) >> 9);
/* special case: there may be compressed blocks of 0 */
if ((history < 128) && (i + 1 < nb_samples)) {
int block_size;
/* calculate rice param and decode block size */
k = 7 - av_log2(history) + ((history + 16) >> 6);
k = FFMIN(k, alac->rice_limit);
block_size = decode_scalar(&alac->gb, k, 16);
if (block_size > 0) {
if (block_size >= nb_samples - i) {
av_log(alac->avctx, AV_LOG_ERROR,
"invalid zero block size of %d %d %d\n", block_size,
nb_samples, i);
block_size = nb_samples - i - 1;
}
memset(&output_buffer[i + 1], 0,
block_size * sizeof(*output_buffer));
i += block_size;
}
if (block_size <= 0xffff)
sign_modifier = 1;
history = 0;
}
}
return 0;
}
static inline int sign_only(int v)
{
return v ? FFSIGN(v) : 0;
}
static void lpc_prediction(int32_t *error_buffer, int32_t *buffer_out,
int nb_samples, int bps, int16_t *lpc_coefs,
int lpc_order, int lpc_quant)
{
int i;
int32_t *pred = buffer_out;
/* first sample always copies */
*buffer_out = *error_buffer;
if (nb_samples <= 1)
return;
if (!lpc_order) {
memcpy(&buffer_out[1], &error_buffer[1],
(nb_samples - 1) * sizeof(*buffer_out));
return;
}
if (lpc_order == 31) {
/* simple 1st-order prediction */
for (i = 1; i < nb_samples; i++) {
buffer_out[i] = sign_extend(buffer_out[i - 1] + error_buffer[i],
bps);
}
return;
}
/* read warm-up samples */
for (i = 1; i <= lpc_order && i < nb_samples; i++)
buffer_out[i] = sign_extend(buffer_out[i - 1] + error_buffer[i], bps);
/* NOTE: 4 and 8 are very common cases that could be optimized. */
for (; i < nb_samples; i++) {
int j;
int val = 0;
int error_val = error_buffer[i];
int error_sign;
int d = *pred++;
/* LPC prediction */
for (j = 0; j < lpc_order; j++)
val += (pred[j] - d) * lpc_coefs[j];
val = (val + (1 << (lpc_quant - 1))) >> lpc_quant;
val += d + error_val;
buffer_out[i] = sign_extend(val, bps);
/* adapt LPC coefficients */
error_sign = sign_only(error_val);
if (error_sign) {
for (j = 0; j < lpc_order && error_val * error_sign > 0; j++) {
int sign;
val = d - pred[j];
sign = sign_only(val) * error_sign;
lpc_coefs[j] -= sign;
val *= sign;
error_val -= (val >> lpc_quant) * (j + 1);
}
}
}
}
static void decorrelate_stereo(int32_t *buffer[2], int nb_samples,
int decorr_shift, int decorr_left_weight)
{
int i;
for (i = 0; i < nb_samples; i++) {
int32_t a, b;
a = buffer[0][i];
b = buffer[1][i];
a -= (b * decorr_left_weight) >> decorr_shift;
b += a;
buffer[0][i] = b;
buffer[1][i] = a;
}
}
static void append_extra_bits(int32_t *buffer[2], int32_t *extra_bits_buffer[2],
int extra_bits, int channels, int nb_samples)
{
int i, ch;
for (ch = 0; ch < channels; ch++)
for (i = 0; i < nb_samples; i++)
buffer[ch][i] = (buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i];
}
static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index,
int channels)
{
ALACContext *alac = avctx->priv_data;
int has_size, bps, is_compressed, decorr_shift, decorr_left_weight, ret;
uint32_t output_samples;
int i, ch;
skip_bits(&alac->gb, 4); /* element instance tag */
skip_bits(&alac->gb, 12); /* unused header bits */
/* the number of output samples is stored in the frame */
has_size = get_bits1(&alac->gb);
alac->extra_bits = get_bits(&alac->gb, 2) << 3;
bps = alac->sample_size - alac->extra_bits + channels - 1;
if (bps > 32U) {
av_log(avctx, AV_LOG_ERROR, "bps is unsupported: %d\n", bps);
return AVERROR_PATCHWELCOME;
}
/* whether the frame is compressed */
is_compressed = !get_bits1(&alac->gb);
if (has_size)
output_samples = get_bits_long(&alac->gb, 32);
else
output_samples = alac->max_samples_per_frame;
if (!output_samples || output_samples > alac->max_samples_per_frame) {
av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n",
output_samples);
return AVERROR_INVALIDDATA;
}
if (!alac->nb_samples) {
ThreadFrame tframe = { .f = frame };
/* get output buffer */
frame->nb_samples = output_samples;
if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
return ret;
} else if (output_samples != alac->nb_samples) {
av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %u != %d\n",
output_samples, alac->nb_samples);
return AVERROR_INVALIDDATA;
}
alac->nb_samples = output_samples;
if (alac->direct_output) {
for (ch = 0; ch < channels; ch++)
alac->output_samples_buffer[ch] = (int32_t *)frame->extended_data[ch_index + ch];
}
if (is_compressed) {
int16_t lpc_coefs[2][32];
int lpc_order[2];
int prediction_type[2];
int lpc_quant[2];
int rice_history_mult[2];
decorr_shift = get_bits(&alac->gb, 8);
decorr_left_weight = get_bits(&alac->gb, 8);
for (ch = 0; ch < channels; ch++) {
prediction_type[ch] = get_bits(&alac->gb, 4);
lpc_quant[ch] = get_bits(&alac->gb, 4);
rice_history_mult[ch] = get_bits(&alac->gb, 3);
lpc_order[ch] = get_bits(&alac->gb, 5);
if (lpc_order[ch] >= alac->max_samples_per_frame)
return AVERROR_INVALIDDATA;
/* read the predictor table */
for (i = lpc_order[ch] - 1; i >= 0; i--)
lpc_coefs[ch][i] = get_sbits(&alac->gb, 16);
}
if (alac->extra_bits) {
for (i = 0; i < alac->nb_samples; i++) {
if(get_bits_left(&alac->gb) <= 0)
return -1;
for (ch = 0; ch < channels; ch++)
alac->extra_bits_buffer[ch][i] = get_bits(&alac->gb, alac->extra_bits);
}
}
for (ch = 0; ch < channels; ch++) {
int ret=rice_decompress(alac, alac->predict_error_buffer[ch],
alac->nb_samples, bps,
rice_history_mult[ch] * alac->rice_history_mult / 4);
if(ret<0)
return ret;
/* adaptive FIR filter */
if (prediction_type[ch] == 15) {
/* Prediction type 15 runs the adaptive FIR twice.
* The first pass uses the special-case coef_num = 31, while
* the second pass uses the coefs from the bitstream.
*
* However, this prediction type is not currently used by the
* reference encoder.
*/
lpc_prediction(alac->predict_error_buffer[ch],
alac->predict_error_buffer[ch],
alac->nb_samples, bps, NULL, 31, 0);
} else if (prediction_type[ch] > 0) {
av_log(avctx, AV_LOG_WARNING, "unknown prediction type: %i\n",
prediction_type[ch]);
}
lpc_prediction(alac->predict_error_buffer[ch],
alac->output_samples_buffer[ch], alac->nb_samples,
bps, lpc_coefs[ch], lpc_order[ch], lpc_quant[ch]);
}
} else {
/* not compressed, easy case */
for (i = 0; i < alac->nb_samples; i++) {
if(get_bits_left(&alac->gb) <= 0)
return -1;
for (ch = 0; ch < channels; ch++) {
alac->output_samples_buffer[ch][i] =
get_sbits_long(&alac->gb, alac->sample_size);
}
}
alac->extra_bits = 0;
decorr_shift = 0;
decorr_left_weight = 0;
}
if (channels == 2 && decorr_left_weight) {
decorrelate_stereo(alac->output_samples_buffer, alac->nb_samples,
decorr_shift, decorr_left_weight);
}
if (alac->extra_bits) {
append_extra_bits(alac->output_samples_buffer, alac->extra_bits_buffer,
alac->extra_bits, channels, alac->nb_samples);
}
if(av_sample_fmt_is_planar(avctx->sample_fmt)) {
switch(alac->sample_size) {
case 16: {
for (ch = 0; ch < channels; ch++) {
int16_t *outbuffer = (int16_t *)frame->extended_data[ch_index + ch];
for (i = 0; i < alac->nb_samples; i++)
*outbuffer++ = alac->output_samples_buffer[ch][i];
}}
break;
case 24: {
for (ch = 0; ch < channels; ch++) {
for (i = 0; i < alac->nb_samples; i++)
alac->output_samples_buffer[ch][i] <<= 8;
}}
break;
}
}else{
switch(alac->sample_size) {
case 16: {
int16_t *outbuffer = ((int16_t *)frame->extended_data[0]) + ch_index;
for (i = 0; i < alac->nb_samples; i++) {
for (ch = 0; ch < channels; ch++)
*outbuffer++ = alac->output_samples_buffer[ch][i];
outbuffer += alac->channels - channels;
}
}
break;
case 24: {
int32_t *outbuffer = ((int32_t *)frame->extended_data[0]) + ch_index;
for (i = 0; i < alac->nb_samples; i++) {
for (ch = 0; ch < channels; ch++)
*outbuffer++ = alac->output_samples_buffer[ch][i] << 8;
outbuffer += alac->channels - channels;
}
}
break;
case 32: {
int32_t *outbuffer = ((int32_t *)frame->extended_data[0]) + ch_index;
for (i = 0; i < alac->nb_samples; i++) {
for (ch = 0; ch < channels; ch++)
*outbuffer++ = alac->output_samples_buffer[ch][i];
outbuffer += alac->channels - channels;
}
}
break;
}
}
return 0;
}
static int alac_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
ALACContext *alac = avctx->priv_data;
AVFrame *frame = data;
enum AlacRawDataBlockType element;
int channels;
int ch, ret, got_end;
if ((ret = init_get_bits8(&alac->gb, avpkt->data, avpkt->size)) < 0)
return ret;
got_end = 0;
alac->nb_samples = 0;
ch = 0;
while (get_bits_left(&alac->gb) >= 3) {
element = get_bits(&alac->gb, 3);
if (element == TYPE_END) {
got_end = 1;
break;
}
if (element > TYPE_CPE && element != TYPE_LFE) {
av_log(avctx, AV_LOG_ERROR, "syntax element unsupported: %d\n", element);
return AVERROR_PATCHWELCOME;
}
channels = (element == TYPE_CPE) ? 2 : 1;
if (ch + channels > alac->channels ||
ff_alac_channel_layout_offsets[alac->channels - 1][ch] + channels > alac->channels) {
av_log(avctx, AV_LOG_ERROR, "invalid element channel count\n");
return AVERROR_INVALIDDATA;
}
ret = decode_element(avctx, frame,
ff_alac_channel_layout_offsets[alac->channels - 1][ch],
channels);
if (ret < 0 && get_bits_left(&alac->gb))
return ret;
ch += channels;
}
if (!got_end) {
av_log(avctx, AV_LOG_ERROR, "no end tag found. incomplete packet.\n");
return AVERROR_INVALIDDATA;
}
if (avpkt->size * 8 - get_bits_count(&alac->gb) > 8) {
av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n",
avpkt->size * 8 - get_bits_count(&alac->gb));
}
*got_frame_ptr = 1;
return avpkt->size;
}
static av_cold int alac_decode_close(AVCodecContext *avctx)
{
ALACContext *alac = avctx->priv_data;
int ch;
for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) {
av_freep(&alac->predict_error_buffer[ch]);
if (!alac->direct_output)
av_freep(&alac->output_samples_buffer[ch]);
av_freep(&alac->extra_bits_buffer[ch]);
}
return 0;
}
static int allocate_buffers(ALACContext *alac)
{
int ch;
int buf_size = alac->max_samples_per_frame * sizeof(int32_t);
for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) {
FF_ALLOC_OR_GOTO(alac->avctx, alac->predict_error_buffer[ch],
buf_size, buf_alloc_fail);
alac->direct_output = alac->sample_size > 16 && av_sample_fmt_is_planar(alac->avctx->sample_fmt);
if (!alac->direct_output) {
FF_ALLOC_OR_GOTO(alac->avctx, alac->output_samples_buffer[ch],
buf_size, buf_alloc_fail);
}
FF_ALLOC_OR_GOTO(alac->avctx, alac->extra_bits_buffer[ch],
buf_size, buf_alloc_fail);
}
return 0;
buf_alloc_fail:
alac_decode_close(alac->avctx);
return AVERROR(ENOMEM);
}
static int alac_set_info(ALACContext *alac)
{
GetByteContext gb;
bytestream2_init(&gb, alac->avctx->extradata,
alac->avctx->extradata_size);
bytestream2_skipu(&gb, 12); // size:4, alac:4, version:4
alac->max_samples_per_frame = bytestream2_get_be32u(&gb);
if (!alac->max_samples_per_frame ||
alac->max_samples_per_frame > INT_MAX / sizeof(int32_t)) {
av_log(alac->avctx, AV_LOG_ERROR, "max samples per frame invalid: %u\n",
alac->max_samples_per_frame);
return AVERROR_INVALIDDATA;
}
bytestream2_skipu(&gb, 1); // compatible version
alac->sample_size = bytestream2_get_byteu(&gb);
alac->rice_history_mult = bytestream2_get_byteu(&gb);
alac->rice_initial_history = bytestream2_get_byteu(&gb);
alac->rice_limit = bytestream2_get_byteu(&gb);
alac->channels = bytestream2_get_byteu(&gb);
bytestream2_get_be16u(&gb); // maxRun
bytestream2_get_be32u(&gb); // max coded frame size
bytestream2_get_be32u(&gb); // average bitrate
bytestream2_get_be32u(&gb); // samplerate
return 0;
}
static av_cold int alac_decode_init(AVCodecContext * avctx)
{
int ret;
int req_packed;
ALACContext *alac = avctx->priv_data;
alac->avctx = avctx;
/* initialize from the extradata */
if (alac->avctx->extradata_size < ALAC_EXTRADATA_SIZE) {
av_log(avctx, AV_LOG_ERROR, "extradata is too small\n");
return AVERROR_INVALIDDATA;
}
if (alac_set_info(alac)) {
av_log(avctx, AV_LOG_ERROR, "set_info failed\n");
return -1;
}
req_packed = LIBAVCODEC_VERSION_MAJOR < 55 && !av_sample_fmt_is_planar(avctx->request_sample_fmt);
switch (alac->sample_size) {
case 16: avctx->sample_fmt = req_packed ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_S16P;
break;
case 24:
case 32: avctx->sample_fmt = req_packed ? AV_SAMPLE_FMT_S32 : AV_SAMPLE_FMT_S32P;
break;
default: avpriv_request_sample(avctx, "Sample depth %d", alac->sample_size);
return AVERROR_PATCHWELCOME;
}
avctx->bits_per_raw_sample = alac->sample_size;
if (alac->channels < 1) {
av_log(avctx, AV_LOG_WARNING, "Invalid channel count\n");
alac->channels = avctx->channels;
} else {
if (alac->channels > ALAC_MAX_CHANNELS)
alac->channels = avctx->channels;
else
avctx->channels = alac->channels;
}
if (avctx->channels > ALAC_MAX_CHANNELS || avctx->channels <= 0 ) {
av_log(avctx, AV_LOG_ERROR, "Unsupported channel count: %d\n",
avctx->channels);
return AVERROR_PATCHWELCOME;
}
avctx->channel_layout = ff_alac_channel_layouts[alac->channels - 1];
if ((ret = allocate_buffers(alac)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error allocating buffers\n");
return ret;
}
return 0;
}
static int init_thread_copy(AVCodecContext *avctx)
{
ALACContext *alac = avctx->priv_data;
alac->avctx = avctx;
return allocate_buffers(alac);
}
AVCodec ff_alac_decoder = {
.name = "alac",
.long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_ALAC,
.priv_data_size = sizeof(ALACContext),
.init = alac_decode_init,
.close = alac_decode_close,
.decode = alac_decode_frame,
.init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy),
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
};

View File

@@ -0,0 +1,56 @@
/*
* ALAC encoder and decoder common data
*
* 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 "libavutil/channel_layout.h"
#include "alac_data.h"
const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS] = {
{ 0 },
{ 0, 1 },
{ 2, 0, 1 },
{ 2, 0, 1, 3 },
{ 2, 0, 1, 3, 4 },
{ 2, 0, 1, 4, 5, 3 },
{ 2, 0, 1, 4, 5, 6, 3 },
{ 2, 6, 7, 0, 1, 4, 5, 3 }
};
const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
AV_CH_LAYOUT_SURROUND,
AV_CH_LAYOUT_4POINT0,
AV_CH_LAYOUT_5POINT0_BACK,
AV_CH_LAYOUT_5POINT1_BACK,
AV_CH_LAYOUT_6POINT1_BACK,
AV_CH_LAYOUT_7POINT1_WIDE_BACK,
0
};
const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5] = {
{ TYPE_SCE, },
{ TYPE_CPE, },
{ TYPE_SCE, TYPE_CPE, },
{ TYPE_SCE, TYPE_CPE, TYPE_SCE },
{ TYPE_SCE, TYPE_CPE, TYPE_CPE, },
{ TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, },
{ TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_SCE, },
{ TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, },
};

View File

@@ -0,0 +1,46 @@
/*
* ALAC encoder and decoder common data
*
* 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 AVCODEC_ALAC_DATA_H
#define AVCODEC_ALAC_DATA_H
#include <stdint.h>
enum AlacRawDataBlockType {
/* At the moment, only SCE, CPE, LFE, and END are recognized. */
TYPE_SCE,
TYPE_CPE,
TYPE_CCE,
TYPE_LFE,
TYPE_DSE,
TYPE_PCE,
TYPE_FIL,
TYPE_END
};
#define ALAC_MAX_CHANNELS 8
extern const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS];
extern const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1];
extern const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5];
#endif /* AVCODEC_ALAC_DATA_H */

View File

@@ -0,0 +1,649 @@
/*
* ALAC audio encoder
* Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.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 "put_bits.h"
#include "internal.h"
#include "lpc.h"
#include "mathops.h"
#include "alac_data.h"
#define DEFAULT_FRAME_SIZE 4096
#define ALAC_EXTRADATA_SIZE 36
#define ALAC_FRAME_HEADER_SIZE 55
#define ALAC_FRAME_FOOTER_SIZE 3
#define ALAC_ESCAPE_CODE 0x1FF
#define ALAC_MAX_LPC_ORDER 30
#define DEFAULT_MAX_PRED_ORDER 6
#define DEFAULT_MIN_PRED_ORDER 4
#define ALAC_MAX_LPC_PRECISION 9
#define ALAC_MAX_LPC_SHIFT 9
#define ALAC_CHMODE_LEFT_RIGHT 0
#define ALAC_CHMODE_LEFT_SIDE 1
#define ALAC_CHMODE_RIGHT_SIDE 2
#define ALAC_CHMODE_MID_SIDE 3
typedef struct RiceContext {
int history_mult;
int initial_history;
int k_modifier;
int rice_modifier;
} RiceContext;
typedef struct AlacLPCContext {
int lpc_order;
int lpc_coeff[ALAC_MAX_LPC_ORDER+1];
int lpc_quant;
} AlacLPCContext;
typedef struct AlacEncodeContext {
int frame_size; /**< current frame size */
int verbatim; /**< current frame verbatim mode flag */
int compression_level;
int min_prediction_order;
int max_prediction_order;
int max_coded_frame_size;
int write_sample_size;
int extra_bits;
int32_t sample_buf[2][DEFAULT_FRAME_SIZE];
int32_t predictor_buf[DEFAULT_FRAME_SIZE];
int interlacing_shift;
int interlacing_leftweight;
PutBitContext pbctx;
RiceContext rc;
AlacLPCContext lpc[2];
LPCContext lpc_ctx;
AVCodecContext *avctx;
} AlacEncodeContext;
static void init_sample_buffers(AlacEncodeContext *s, int channels,
uint8_t const *samples[2])
{
int ch, i;
int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 -
s->avctx->bits_per_raw_sample;
#define COPY_SAMPLES(type) do { \
for (ch = 0; ch < channels; ch++) { \
int32_t *bptr = s->sample_buf[ch]; \
const type *sptr = (const type *)samples[ch]; \
for (i = 0; i < s->frame_size; i++) \
bptr[i] = sptr[i] >> shift; \
} \
} while (0)
if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P)
COPY_SAMPLES(int32_t);
else
COPY_SAMPLES(int16_t);
}
static void encode_scalar(AlacEncodeContext *s, int x,
int k, int write_sample_size)
{
int divisor, q, r;
k = FFMIN(k, s->rc.k_modifier);
divisor = (1<<k) - 1;
q = x / divisor;
r = x % divisor;
if (q > 8) {
// write escape code and sample value directly
put_bits(&s->pbctx, 9, ALAC_ESCAPE_CODE);
put_bits(&s->pbctx, write_sample_size, x);
} else {
if (q)
put_bits(&s->pbctx, q, (1<<q) - 1);
put_bits(&s->pbctx, 1, 0);
if (k != 1) {
if (r > 0)
put_bits(&s->pbctx, k, r+1);
else
put_bits(&s->pbctx, k-1, 0);
}
}
}
static void write_element_header(AlacEncodeContext *s,
enum AlacRawDataBlockType element,
int instance)
{
int encode_fs = 0;
if (s->frame_size < DEFAULT_FRAME_SIZE)
encode_fs = 1;
put_bits(&s->pbctx, 3, element); // element type
put_bits(&s->pbctx, 4, instance); // element instance
put_bits(&s->pbctx, 12, 0); // unused header bits
put_bits(&s->pbctx, 1, encode_fs); // Sample count is in the header
put_bits(&s->pbctx, 2, s->extra_bits >> 3); // Extra bytes (for 24-bit)
put_bits(&s->pbctx, 1, s->verbatim); // Audio block is verbatim
if (encode_fs)
put_bits32(&s->pbctx, s->frame_size); // No. of samples in the frame
}
static void calc_predictor_params(AlacEncodeContext *s, int ch)
{
int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
int shift[MAX_LPC_ORDER];
int opt_order;
if (s->compression_level == 1) {
s->lpc[ch].lpc_order = 6;
s->lpc[ch].lpc_quant = 6;
s->lpc[ch].lpc_coeff[0] = 160;
s->lpc[ch].lpc_coeff[1] = -190;
s->lpc[ch].lpc_coeff[2] = 170;
s->lpc[ch].lpc_coeff[3] = -130;
s->lpc[ch].lpc_coeff[4] = 80;
s->lpc[ch].lpc_coeff[5] = -25;
} else {
opt_order = ff_lpc_calc_coefs(&s->lpc_ctx, s->sample_buf[ch],
s->frame_size,
s->min_prediction_order,
s->max_prediction_order,
ALAC_MAX_LPC_PRECISION, coefs, shift,
FF_LPC_TYPE_LEVINSON, 0,
ORDER_METHOD_EST, ALAC_MAX_LPC_SHIFT, 1);
s->lpc[ch].lpc_order = opt_order;
s->lpc[ch].lpc_quant = shift[opt_order-1];
memcpy(s->lpc[ch].lpc_coeff, coefs[opt_order-1], opt_order*sizeof(int));
}
}
static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n)
{
int i, best;
int32_t lt, rt;
uint64_t sum[4];
uint64_t score[4];
/* calculate sum of 2nd order residual for each channel */
sum[0] = sum[1] = sum[2] = sum[3] = 0;
for (i = 2; i < n; i++) {
lt = left_ch[i] - 2 * left_ch[i - 1] + left_ch[i - 2];
rt = right_ch[i] - 2 * right_ch[i - 1] + right_ch[i - 2];
sum[2] += FFABS((lt + rt) >> 1);
sum[3] += FFABS(lt - rt);
sum[0] += FFABS(lt);
sum[1] += FFABS(rt);
}
/* calculate score for each mode */
score[0] = sum[0] + sum[1];
score[1] = sum[0] + sum[3];
score[2] = sum[1] + sum[3];
score[3] = sum[2] + sum[3];
/* return mode with lowest score */
best = 0;
for (i = 1; i < 4; i++) {
if (score[i] < score[best])
best = i;
}
return best;
}
static void alac_stereo_decorrelation(AlacEncodeContext *s)
{
int32_t *left = s->sample_buf[0], *right = s->sample_buf[1];
int i, mode, n = s->frame_size;
int32_t tmp;
mode = estimate_stereo_mode(left, right, n);
switch (mode) {
case ALAC_CHMODE_LEFT_RIGHT:
s->interlacing_leftweight = 0;
s->interlacing_shift = 0;
break;
case ALAC_CHMODE_LEFT_SIDE:
for (i = 0; i < n; i++)
right[i] = left[i] - right[i];
s->interlacing_leftweight = 1;
s->interlacing_shift = 0;
break;
case ALAC_CHMODE_RIGHT_SIDE:
for (i = 0; i < n; i++) {
tmp = right[i];
right[i] = left[i] - right[i];
left[i] = tmp + (right[i] >> 31);
}
s->interlacing_leftweight = 1;
s->interlacing_shift = 31;
break;
default:
for (i = 0; i < n; i++) {
tmp = left[i];
left[i] = (tmp + right[i]) >> 1;
right[i] = tmp - right[i];
}
s->interlacing_leftweight = 1;
s->interlacing_shift = 1;
break;
}
}
static void alac_linear_predictor(AlacEncodeContext *s, int ch)
{
int i;
AlacLPCContext lpc = s->lpc[ch];
if (lpc.lpc_order == 31) {
s->predictor_buf[0] = s->sample_buf[ch][0];
for (i = 1; i < s->frame_size; i++) {
s->predictor_buf[i] = s->sample_buf[ch][i ] -
s->sample_buf[ch][i - 1];
}
return;
}
// generalised linear predictor
if (lpc.lpc_order > 0) {
int32_t *samples = s->sample_buf[ch];
int32_t *residual = s->predictor_buf;
// generate warm-up samples
residual[0] = samples[0];
for (i = 1; i <= lpc.lpc_order; i++)
residual[i] = sign_extend(samples[i] - samples[i-1], s->write_sample_size);
// perform lpc on remaining samples
for (i = lpc.lpc_order + 1; i < s->frame_size; i++) {
int sum = 1 << (lpc.lpc_quant - 1), res_val, j;
for (j = 0; j < lpc.lpc_order; j++) {
sum += (samples[lpc.lpc_order-j] - samples[0]) *
lpc.lpc_coeff[j];
}
sum >>= lpc.lpc_quant;
sum += samples[0];
residual[i] = sign_extend(samples[lpc.lpc_order+1] - sum,
s->write_sample_size);
res_val = residual[i];
if (res_val) {
int index = lpc.lpc_order - 1;
int neg = (res_val < 0);
while (index >= 0 && (neg ? (res_val < 0) : (res_val > 0))) {
int val = samples[0] - samples[lpc.lpc_order - index];
int sign = (val ? FFSIGN(val) : 0);
if (neg)
sign *= -1;
lpc.lpc_coeff[index] -= sign;
val *= sign;
res_val -= (val >> lpc.lpc_quant) * (lpc.lpc_order - index);
index--;
}
}
samples++;
}
}
}
static void alac_entropy_coder(AlacEncodeContext *s)
{
unsigned int history = s->rc.initial_history;
int sign_modifier = 0, i, k;
int32_t *samples = s->predictor_buf;
for (i = 0; i < s->frame_size;) {
int x;
k = av_log2((history >> 9) + 3);
x = -2 * (*samples) -1;
x ^= x >> 31;
samples++;
i++;
encode_scalar(s, x - sign_modifier, k, s->write_sample_size);
history += x * s->rc.history_mult -
((history * s->rc.history_mult) >> 9);
sign_modifier = 0;
if (x > 0xFFFF)
history = 0xFFFF;
if (history < 128 && i < s->frame_size) {
unsigned int block_size = 0;
k = 7 - av_log2(history) + ((history + 16) >> 6);
while (*samples == 0 && i < s->frame_size) {
samples++;
i++;
block_size++;
}
encode_scalar(s, block_size, k, 16);
sign_modifier = (block_size <= 0xFFFF);
history = 0;
}
}
}
static void write_element(AlacEncodeContext *s,
enum AlacRawDataBlockType element, int instance,
const uint8_t *samples0, const uint8_t *samples1)
{
uint8_t const *samples[2] = { samples0, samples1 };
int i, j, channels;
int prediction_type = 0;
PutBitContext *pb = &s->pbctx;
channels = element == TYPE_CPE ? 2 : 1;
if (s->verbatim) {
write_element_header(s, element, instance);
/* samples are channel-interleaved in verbatim mode */
if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P) {
int shift = 32 - s->avctx->bits_per_raw_sample;
int32_t const *samples_s32[2] = { (const int32_t *)samples0,
(const int32_t *)samples1 };
for (i = 0; i < s->frame_size; i++)
for (j = 0; j < channels; j++)
put_sbits(pb, s->avctx->bits_per_raw_sample,
samples_s32[j][i] >> shift);
} else {
int16_t const *samples_s16[2] = { (const int16_t *)samples0,
(const int16_t *)samples1 };
for (i = 0; i < s->frame_size; i++)
for (j = 0; j < channels; j++)
put_sbits(pb, s->avctx->bits_per_raw_sample,
samples_s16[j][i]);
}
} else {
s->write_sample_size = s->avctx->bits_per_raw_sample - s->extra_bits +
channels - 1;
init_sample_buffers(s, channels, samples);
write_element_header(s, element, instance);
if (channels == 2)
alac_stereo_decorrelation(s);
else
s->interlacing_shift = s->interlacing_leftweight = 0;
put_bits(pb, 8, s->interlacing_shift);
put_bits(pb, 8, s->interlacing_leftweight);
for (i = 0; i < channels; i++) {
calc_predictor_params(s, i);
put_bits(pb, 4, prediction_type);
put_bits(pb, 4, s->lpc[i].lpc_quant);
put_bits(pb, 3, s->rc.rice_modifier);
put_bits(pb, 5, s->lpc[i].lpc_order);
// predictor coeff. table
for (j = 0; j < s->lpc[i].lpc_order; j++)
put_sbits(pb, 16, s->lpc[i].lpc_coeff[j]);
}
// write extra bits if needed
if (s->extra_bits) {
uint32_t mask = (1 << s->extra_bits) - 1;
for (i = 0; i < s->frame_size; i++) {
for (j = 0; j < channels; j++) {
put_bits(pb, s->extra_bits, s->sample_buf[j][i] & mask);
s->sample_buf[j][i] >>= s->extra_bits;
}
}
}
// apply lpc and entropy coding to audio samples
for (i = 0; i < channels; i++) {
alac_linear_predictor(s, i);
// TODO: determine when this will actually help. for now it's not used.
if (prediction_type == 15) {
// 2nd pass 1st order filter
for (j = s->frame_size - 1; j > 0; j--)
s->predictor_buf[j] -= s->predictor_buf[j - 1];
}
alac_entropy_coder(s);
}
}
}
static int write_frame(AlacEncodeContext *s, AVPacket *avpkt,
uint8_t * const *samples)
{
PutBitContext *pb = &s->pbctx;
const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[s->avctx->channels - 1];
const uint8_t *ch_map = ff_alac_channel_layout_offsets[s->avctx->channels - 1];
int ch, element, sce, cpe;
init_put_bits(pb, avpkt->data, avpkt->size);
ch = element = sce = cpe = 0;
while (ch < s->avctx->channels) {
if (ch_elements[element] == TYPE_CPE) {
write_element(s, TYPE_CPE, cpe, samples[ch_map[ch]],
samples[ch_map[ch + 1]]);
cpe++;
ch += 2;
} else {
write_element(s, TYPE_SCE, sce, samples[ch_map[ch]], NULL);
sce++;
ch++;
}
element++;
}
put_bits(pb, 3, TYPE_END);
flush_put_bits(pb);
return put_bits_count(pb) >> 3;
}
static av_always_inline int get_max_frame_size(int frame_size, int ch, int bps)
{
int header_bits = 23 + 32 * (frame_size < DEFAULT_FRAME_SIZE);
return FFALIGN(header_bits + bps * ch * frame_size + 3, 8) / 8;
}
static av_cold int alac_encode_close(AVCodecContext *avctx)
{
AlacEncodeContext *s = avctx->priv_data;
ff_lpc_end(&s->lpc_ctx);
av_freep(&avctx->extradata);
avctx->extradata_size = 0;
return 0;
}
static av_cold int alac_encode_init(AVCodecContext *avctx)
{
AlacEncodeContext *s = avctx->priv_data;
int ret;
uint8_t *alac_extradata;
avctx->frame_size = s->frame_size = DEFAULT_FRAME_SIZE;
if (avctx->sample_fmt == AV_SAMPLE_FMT_S32P) {
if (avctx->bits_per_raw_sample != 24)
av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n");
avctx->bits_per_raw_sample = 24;
} else {
avctx->bits_per_raw_sample = 16;
s->extra_bits = 0;
}
// Set default compression level
if (avctx->compression_level == FF_COMPRESSION_DEFAULT)
s->compression_level = 2;
else
s->compression_level = av_clip(avctx->compression_level, 0, 2);
// Initialize default Rice parameters
s->rc.history_mult = 40;
s->rc.initial_history = 10;
s->rc.k_modifier = 14;
s->rc.rice_modifier = 4;
s->max_coded_frame_size = get_max_frame_size(avctx->frame_size,
avctx->channels,
avctx->bits_per_raw_sample);
avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata) {
ret = AVERROR(ENOMEM);
goto error;
}
avctx->extradata_size = ALAC_EXTRADATA_SIZE;
alac_extradata = avctx->extradata;
AV_WB32(alac_extradata, ALAC_EXTRADATA_SIZE);
AV_WB32(alac_extradata+4, MKBETAG('a','l','a','c'));
AV_WB32(alac_extradata+12, avctx->frame_size);
AV_WB8 (alac_extradata+17, avctx->bits_per_raw_sample);
AV_WB8 (alac_extradata+21, avctx->channels);
AV_WB32(alac_extradata+24, s->max_coded_frame_size);
AV_WB32(alac_extradata+28,
avctx->sample_rate * avctx->channels * avctx->bits_per_raw_sample); // average bitrate
AV_WB32(alac_extradata+32, avctx->sample_rate);
// Set relevant extradata fields
if (s->compression_level > 0) {
AV_WB8(alac_extradata+18, s->rc.history_mult);
AV_WB8(alac_extradata+19, s->rc.initial_history);
AV_WB8(alac_extradata+20, s->rc.k_modifier);
}
s->min_prediction_order = DEFAULT_MIN_PRED_ORDER;
if (avctx->min_prediction_order >= 0) {
if (avctx->min_prediction_order < MIN_LPC_ORDER ||
avctx->min_prediction_order > ALAC_MAX_LPC_ORDER) {
av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n",
avctx->min_prediction_order);
ret = AVERROR(EINVAL);
goto error;
}
s->min_prediction_order = avctx->min_prediction_order;
}
s->max_prediction_order = DEFAULT_MAX_PRED_ORDER;
if (avctx->max_prediction_order >= 0) {
if (avctx->max_prediction_order < MIN_LPC_ORDER ||
avctx->max_prediction_order > ALAC_MAX_LPC_ORDER) {
av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n",
avctx->max_prediction_order);
ret = AVERROR(EINVAL);
goto error;
}
s->max_prediction_order = avctx->max_prediction_order;
}
if (s->max_prediction_order < s->min_prediction_order) {
av_log(avctx, AV_LOG_ERROR,
"invalid prediction orders: min=%d max=%d\n",
s->min_prediction_order, s->max_prediction_order);
ret = AVERROR(EINVAL);
goto error;
}
s->avctx = avctx;
if ((ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size,
s->max_prediction_order,
FF_LPC_TYPE_LEVINSON)) < 0) {
goto error;
}
return 0;
error:
alac_encode_close(avctx);
return ret;
}
static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
AlacEncodeContext *s = avctx->priv_data;
int out_bytes, max_frame_size, ret;
s->frame_size = frame->nb_samples;
if (frame->nb_samples < DEFAULT_FRAME_SIZE)
max_frame_size = get_max_frame_size(s->frame_size, avctx->channels,
avctx->bits_per_raw_sample);
else
max_frame_size = s->max_coded_frame_size;
if ((ret = ff_alloc_packet2(avctx, avpkt, 2 * max_frame_size)) < 0)
return ret;
/* use verbatim mode for compression_level 0 */
if (s->compression_level) {
s->verbatim = 0;
s->extra_bits = avctx->bits_per_raw_sample - 16;
} else {
s->verbatim = 1;
s->extra_bits = 0;
}
out_bytes = write_frame(s, avpkt, frame->extended_data);
if (out_bytes > max_frame_size) {
/* frame too large. use verbatim mode */
s->verbatim = 1;
s->extra_bits = 0;
out_bytes = write_frame(s, avpkt, frame->extended_data);
}
avpkt->size = out_bytes;
*got_packet_ptr = 1;
return 0;
}
AVCodec ff_alac_encoder = {
.name = "alac",
.long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_ALAC,
.priv_data_size = sizeof(AlacEncodeContext),
.init = alac_encode_init,
.encode2 = alac_encode_frame,
.close = alac_encode_close,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME,
.channel_layouts = ff_alac_channel_layouts,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
};

View File

@@ -0,0 +1,569 @@
/*
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
* Copyright (c) 2002 Fabrice Bellard
*
* 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
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
*/
#include "avcodec.h"
#include "config.h"
#define REGISTER_HWACCEL(X, x) \
{ \
extern AVHWAccel ff_##x##_hwaccel; \
if (CONFIG_##X##_HWACCEL) \
av_register_hwaccel(&ff_##x##_hwaccel); \
}
#define REGISTER_ENCODER(X, x) \
{ \
extern AVCodec ff_##x##_encoder; \
if (CONFIG_##X##_ENCODER) \
avcodec_register(&ff_##x##_encoder); \
}
#define REGISTER_DECODER(X, x) \
{ \
extern AVCodec ff_##x##_decoder; \
if (CONFIG_##X##_DECODER) \
avcodec_register(&ff_##x##_decoder); \
}
#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x)
#define REGISTER_PARSER(X, x) \
{ \
extern AVCodecParser ff_##x##_parser; \
if (CONFIG_##X##_PARSER) \
av_register_codec_parser(&ff_##x##_parser); \
}
#define REGISTER_BSF(X, x) \
{ \
extern AVBitStreamFilter ff_##x##_bsf; \
if (CONFIG_##X##_BSF) \
av_register_bitstream_filter(&ff_##x##_bsf); \
}
void avcodec_register_all(void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
/* hardware accelerators */
REGISTER_HWACCEL(H263_VAAPI, h263_vaapi);
REGISTER_HWACCEL(H263_VDPAU, h263_vdpau);
REGISTER_HWACCEL(H264_DXVA2, h264_dxva2);
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi);
REGISTER_HWACCEL(H264_VDA, h264_vda);
REGISTER_HWACCEL(H264_VDPAU, h264_vdpau);
REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2);
REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi);
REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau);
REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi);
REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2);
REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi);
REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau);
/* video codecs */
REGISTER_ENCODER(A64MULTI, a64multi);
REGISTER_ENCODER(A64MULTI5, a64multi5);
REGISTER_DECODER(AASC, aasc);
REGISTER_DECODER(AIC, aic);
REGISTER_ENCDEC (AMV, amv);
REGISTER_DECODER(ANM, anm);
REGISTER_DECODER(ANSI, ansi);
REGISTER_ENCDEC (ASV1, asv1);
REGISTER_ENCDEC (ASV2, asv2);
REGISTER_DECODER(AURA, aura);
REGISTER_DECODER(AURA2, aura2);
REGISTER_ENCDEC (AVRP, avrp);
REGISTER_DECODER(AVRN, avrn);
REGISTER_DECODER(AVS, avs);
REGISTER_ENCDEC (AVUI, avui);
REGISTER_ENCDEC (AYUV, ayuv);
REGISTER_DECODER(BETHSOFTVID, bethsoftvid);
REGISTER_DECODER(BFI, bfi);
REGISTER_DECODER(BINK, bink);
REGISTER_ENCDEC (BMP, bmp);
REGISTER_DECODER(BMV_VIDEO, bmv_video);
REGISTER_DECODER(BRENDER_PIX, brender_pix);
REGISTER_DECODER(C93, c93);
REGISTER_DECODER(CAVS, cavs);
REGISTER_DECODER(CDGRAPHICS, cdgraphics);
REGISTER_DECODER(CDXL, cdxl);
REGISTER_DECODER(CINEPAK, cinepak);
REGISTER_ENCDEC (CLJR, cljr);
REGISTER_DECODER(CLLC, cllc);
REGISTER_ENCDEC (COMFORTNOISE, comfortnoise);
REGISTER_DECODER(CPIA, cpia);
REGISTER_DECODER(CSCD, cscd);
REGISTER_DECODER(CYUV, cyuv);
REGISTER_DECODER(DFA, dfa);
REGISTER_DECODER(DIRAC, dirac);
REGISTER_ENCDEC (DNXHD, dnxhd);
REGISTER_ENCDEC (DPX, dpx);
REGISTER_DECODER(DSICINVIDEO, dsicinvideo);
REGISTER_ENCDEC (DVVIDEO, dvvideo);
REGISTER_DECODER(DXA, dxa);
REGISTER_DECODER(DXTORY, dxtory);
REGISTER_DECODER(EACMV, eacmv);
REGISTER_DECODER(EAMAD, eamad);
REGISTER_DECODER(EATGQ, eatgq);
REGISTER_DECODER(EATGV, eatgv);
REGISTER_DECODER(EATQI, eatqi);
REGISTER_DECODER(EIGHTBPS, eightbps);
REGISTER_DECODER(EIGHTSVX_EXP, eightsvx_exp);
REGISTER_DECODER(EIGHTSVX_FIB, eightsvx_fib);
REGISTER_DECODER(ESCAPE124, escape124);
REGISTER_DECODER(ESCAPE130, escape130);
REGISTER_DECODER(EXR, exr);
REGISTER_ENCDEC (FFV1, ffv1);
REGISTER_ENCDEC (FFVHUFF, ffvhuff);
REGISTER_ENCDEC (FLASHSV, flashsv);
REGISTER_ENCDEC (FLASHSV2, flashsv2);
REGISTER_DECODER(FLIC, flic);
REGISTER_ENCDEC (FLV, flv);
REGISTER_DECODER(FOURXM, fourxm);
REGISTER_DECODER(FRAPS, fraps);
REGISTER_DECODER(FRWU, frwu);
REGISTER_DECODER(G2M, g2m);
REGISTER_ENCDEC (GIF, gif);
REGISTER_ENCDEC (H261, h261);
REGISTER_ENCDEC (H263, h263);
REGISTER_DECODER(H263I, h263i);
REGISTER_ENCDEC (H263P, h263p);
REGISTER_DECODER(H264, h264);
REGISTER_DECODER(H264_CRYSTALHD, h264_crystalhd);
REGISTER_DECODER(H264_VDA, h264_vda);
REGISTER_DECODER(H264_VDPAU, h264_vdpau);
REGISTER_DECODER(HEVC, hevc);
REGISTER_ENCDEC (HUFFYUV, huffyuv);
REGISTER_DECODER(IDCIN, idcin);
REGISTER_DECODER(IFF_BYTERUN1, iff_byterun1);
REGISTER_DECODER(IFF_ILBM, iff_ilbm);
REGISTER_DECODER(INDEO2, indeo2);
REGISTER_DECODER(INDEO3, indeo3);
REGISTER_DECODER(INDEO4, indeo4);
REGISTER_DECODER(INDEO5, indeo5);
REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video);
REGISTER_ENCDEC (JPEG2000, jpeg2000);
REGISTER_ENCDEC (JPEGLS, jpegls);
REGISTER_DECODER(JV, jv);
REGISTER_DECODER(KGV1, kgv1);
REGISTER_DECODER(KMVC, kmvc);
REGISTER_DECODER(LAGARITH, lagarith);
REGISTER_ENCODER(LJPEG, ljpeg);
REGISTER_DECODER(LOCO, loco);
REGISTER_DECODER(MDEC, mdec);
REGISTER_DECODER(MIMIC, mimic);
REGISTER_ENCDEC (MJPEG, mjpeg);
REGISTER_DECODER(MJPEGB, mjpegb);
REGISTER_DECODER(MMVIDEO, mmvideo);
REGISTER_DECODER(MOTIONPIXELS, motionpixels);
REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc);
REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video);
REGISTER_ENCDEC (MPEG4, mpeg4);
REGISTER_DECODER(MPEG4_CRYSTALHD, mpeg4_crystalhd);
REGISTER_DECODER(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_DECODER(MPEGVIDEO, mpegvideo);
REGISTER_DECODER(MPEG_VDPAU, mpeg_vdpau);
REGISTER_DECODER(MPEG1_VDPAU, mpeg1_vdpau);
REGISTER_DECODER(MPEG2_CRYSTALHD, mpeg2_crystalhd);
REGISTER_DECODER(MSA1, msa1);
REGISTER_DECODER(MSMPEG4_CRYSTALHD, msmpeg4_crystalhd);
REGISTER_DECODER(MSMPEG4V1, msmpeg4v1);
REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2);
REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3);
REGISTER_DECODER(MSRLE, msrle);
REGISTER_DECODER(MSS1, mss1);
REGISTER_DECODER(MSS2, mss2);
REGISTER_ENCDEC (MSVIDEO1, msvideo1);
REGISTER_DECODER(MSZH, mszh);
REGISTER_DECODER(MTS2, mts2);
REGISTER_DECODER(MVC1, mvc1);
REGISTER_DECODER(MVC2, mvc2);
REGISTER_DECODER(MXPEG, mxpeg);
REGISTER_DECODER(NUV, nuv);
REGISTER_DECODER(PAF_VIDEO, paf_video);
REGISTER_ENCDEC (PAM, pam);
REGISTER_ENCDEC (PBM, pbm);
REGISTER_ENCDEC (PCX, pcx);
REGISTER_ENCDEC (PGM, pgm);
REGISTER_ENCDEC (PGMYUV, pgmyuv);
REGISTER_DECODER(PICTOR, pictor);
REGISTER_ENCDEC (PNG, png);
REGISTER_ENCDEC (PPM, ppm);
REGISTER_ENCDEC (PRORES, prores);
REGISTER_ENCODER(PRORES_AW, prores_aw);
REGISTER_ENCODER(PRORES_KS, prores_ks);
REGISTER_DECODER(PRORES_LGPL, prores_lgpl);
REGISTER_DECODER(PTX, ptx);
REGISTER_DECODER(QDRAW, qdraw);
REGISTER_DECODER(QPEG, qpeg);
REGISTER_ENCDEC (QTRLE, qtrle);
REGISTER_ENCDEC (R10K, r10k);
REGISTER_ENCDEC (R210, r210);
REGISTER_ENCDEC (RAWVIDEO, rawvideo);
REGISTER_DECODER(RL2, rl2);
REGISTER_ENCDEC (ROQ, roq);
REGISTER_DECODER(RPZA, rpza);
REGISTER_ENCDEC (RV10, rv10);
REGISTER_ENCDEC (RV20, rv20);
REGISTER_DECODER(RV30, rv30);
REGISTER_DECODER(RV40, rv40);
REGISTER_ENCDEC (S302M, s302m);
REGISTER_DECODER(SANM, sanm);
REGISTER_ENCDEC (SGI, sgi);
REGISTER_DECODER(SGIRLE, sgirle);
REGISTER_DECODER(SMACKER, smacker);
REGISTER_DECODER(SMC, smc);
REGISTER_DECODER(SMVJPEG, smvjpeg);
REGISTER_ENCDEC (SNOW, snow);
REGISTER_DECODER(SP5X, sp5x);
REGISTER_ENCDEC (SUNRAST, sunrast);
REGISTER_ENCDEC (SVQ1, svq1);
REGISTER_DECODER(SVQ3, svq3);
REGISTER_ENCDEC (TARGA, targa);
REGISTER_DECODER(TARGA_Y216, targa_y216);
REGISTER_DECODER(THEORA, theora);
REGISTER_DECODER(THP, thp);
REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo);
REGISTER_ENCDEC (TIFF, tiff);
REGISTER_DECODER(TMV, tmv);
REGISTER_DECODER(TRUEMOTION1, truemotion1);
REGISTER_DECODER(TRUEMOTION2, truemotion2);
REGISTER_DECODER(TSCC, tscc);
REGISTER_DECODER(TSCC2, tscc2);
REGISTER_DECODER(TXD, txd);
REGISTER_DECODER(ULTI, ulti);
REGISTER_ENCDEC (UTVIDEO, utvideo);
REGISTER_ENCDEC (V210, v210);
REGISTER_DECODER(V210X, v210x);
REGISTER_ENCDEC (V308, v308);
REGISTER_ENCDEC (V408, v408);
REGISTER_ENCDEC (V410, v410);
REGISTER_DECODER(VB, vb);
REGISTER_DECODER(VBLE, vble);
REGISTER_DECODER(VC1, vc1);
REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd);
REGISTER_DECODER(VC1_VDPAU, vc1_vdpau);
REGISTER_DECODER(VC1IMAGE, vc1image);
REGISTER_DECODER(VCR1, vcr1);
REGISTER_DECODER(VMDVIDEO, vmdvideo);
REGISTER_DECODER(VMNC, vmnc);
REGISTER_DECODER(VP3, vp3);
REGISTER_DECODER(VP5, vp5);
REGISTER_DECODER(VP6, vp6);
REGISTER_DECODER(VP6A, vp6a);
REGISTER_DECODER(VP6F, vp6f);
REGISTER_DECODER(VP8, vp8);
REGISTER_DECODER(VP9, vp9);
REGISTER_DECODER(VQA, vqa);
REGISTER_DECODER(WEBP, webp);
REGISTER_ENCDEC (WMV1, wmv1);
REGISTER_ENCDEC (WMV2, wmv2);
REGISTER_DECODER(WMV3, wmv3);
REGISTER_DECODER(WMV3_CRYSTALHD, wmv3_crystalhd);
REGISTER_DECODER(WMV3_VDPAU, wmv3_vdpau);
REGISTER_DECODER(WMV3IMAGE, wmv3image);
REGISTER_DECODER(WNV1, wnv1);
REGISTER_DECODER(XAN_WC3, xan_wc3);
REGISTER_DECODER(XAN_WC4, xan_wc4);
REGISTER_ENCDEC (XBM, xbm);
REGISTER_ENCDEC (XFACE, xface);
REGISTER_DECODER(XL, xl);
REGISTER_ENCDEC (XWD, xwd);
REGISTER_ENCDEC (Y41P, y41p);
REGISTER_DECODER(YOP, yop);
REGISTER_ENCDEC (YUV4, yuv4);
REGISTER_DECODER(ZERO12V, zero12v);
REGISTER_DECODER(ZEROCODEC, zerocodec);
REGISTER_ENCDEC (ZLIB, zlib);
REGISTER_ENCDEC (ZMBV, zmbv);
/* audio codecs */
REGISTER_ENCDEC (AAC, aac);
REGISTER_DECODER(AAC_LATM, aac_latm);
REGISTER_ENCDEC (AC3, ac3);
REGISTER_ENCODER(AC3_FIXED, ac3_fixed);
REGISTER_ENCDEC (ALAC, alac);
REGISTER_DECODER(ALS, als);
REGISTER_DECODER(AMRNB, amrnb);
REGISTER_DECODER(AMRWB, amrwb);
REGISTER_DECODER(APE, ape);
REGISTER_DECODER(ATRAC1, atrac1);
REGISTER_DECODER(ATRAC3, atrac3);
REGISTER_DECODER(BINKAUDIO_DCT, binkaudio_dct);
REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft);
REGISTER_DECODER(BMV_AUDIO, bmv_audio);
REGISTER_DECODER(COOK, cook);
REGISTER_ENCDEC (DCA, dca);
REGISTER_DECODER(DSICINAUDIO, dsicinaudio);
REGISTER_ENCDEC (EAC3, eac3);
REGISTER_DECODER(EVRC, evrc);
REGISTER_DECODER(FFWAVESYNTH, ffwavesynth);
REGISTER_ENCDEC (FLAC, flac);
REGISTER_ENCDEC (G723_1, g723_1);
REGISTER_DECODER(G729, g729);
REGISTER_DECODER(GSM, gsm);
REGISTER_DECODER(GSM_MS, gsm_ms);
REGISTER_DECODER(IAC, iac);
REGISTER_DECODER(IMC, imc);
REGISTER_DECODER(MACE3, mace3);
REGISTER_DECODER(MACE6, mace6);
REGISTER_DECODER(METASOUND, metasound);
REGISTER_DECODER(MLP, mlp);
REGISTER_DECODER(MP1, mp1);
REGISTER_DECODER(MP1FLOAT, mp1float);
REGISTER_ENCDEC (MP2, mp2);
REGISTER_DECODER(MP2FLOAT, mp2float);
REGISTER_DECODER(MP3, mp3);
REGISTER_DECODER(MP3FLOAT, mp3float);
REGISTER_DECODER(MP3ADU, mp3adu);
REGISTER_DECODER(MP3ADUFLOAT, mp3adufloat);
REGISTER_DECODER(MP3ON4, mp3on4);
REGISTER_DECODER(MP3ON4FLOAT, mp3on4float);
REGISTER_DECODER(MPC7, mpc7);
REGISTER_DECODER(MPC8, mpc8);
REGISTER_ENCDEC (NELLYMOSER, nellymoser);
REGISTER_DECODER(PAF_AUDIO, paf_audio);
REGISTER_DECODER(QCELP, qcelp);
REGISTER_DECODER(QDM2, qdm2);
REGISTER_ENCDEC (RA_144, ra_144);
REGISTER_DECODER(RA_288, ra_288);
REGISTER_DECODER(RALF, ralf);
REGISTER_DECODER(SHORTEN, shorten);
REGISTER_DECODER(SIPR, sipr);
REGISTER_DECODER(SMACKAUD, smackaud);
REGISTER_ENCDEC (SONIC, sonic);
REGISTER_ENCODER(SONIC_LS, sonic_ls);
REGISTER_DECODER(TAK, tak);
REGISTER_DECODER(TRUEHD, truehd);
REGISTER_DECODER(TRUESPEECH, truespeech);
REGISTER_ENCDEC (TTA, tta);
REGISTER_DECODER(TWINVQ, twinvq);
REGISTER_DECODER(VMDAUDIO, vmdaudio);
REGISTER_ENCDEC (VORBIS, vorbis);
REGISTER_ENCDEC (WAVPACK, wavpack);
REGISTER_DECODER(WMALOSSLESS, wmalossless);
REGISTER_DECODER(WMAPRO, wmapro);
REGISTER_ENCDEC (WMAV1, wmav1);
REGISTER_ENCDEC (WMAV2, wmav2);
REGISTER_DECODER(WMAVOICE, wmavoice);
REGISTER_DECODER(WS_SND1, ws_snd1);
/* PCM codecs */
REGISTER_ENCDEC (PCM_ALAW, pcm_alaw);
REGISTER_DECODER(PCM_BLURAY, pcm_bluray);
REGISTER_DECODER(PCM_DVD, pcm_dvd);
REGISTER_ENCDEC (PCM_F32BE, pcm_f32be);
REGISTER_ENCDEC (PCM_F32LE, pcm_f32le);
REGISTER_ENCDEC (PCM_F64BE, pcm_f64be);
REGISTER_ENCDEC (PCM_F64LE, pcm_f64le);
REGISTER_DECODER(PCM_LXF, pcm_lxf);
REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw);
REGISTER_ENCDEC (PCM_S8, pcm_s8);
REGISTER_ENCDEC (PCM_S8_PLANAR, pcm_s8_planar);
REGISTER_ENCDEC (PCM_S16BE, pcm_s16be);
REGISTER_ENCDEC (PCM_S16BE_PLANAR, pcm_s16be_planar);
REGISTER_ENCDEC (PCM_S16LE, pcm_s16le);
REGISTER_ENCDEC (PCM_S16LE_PLANAR, pcm_s16le_planar);
REGISTER_ENCDEC (PCM_S24BE, pcm_s24be);
REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud);
REGISTER_ENCDEC (PCM_S24LE, pcm_s24le);
REGISTER_ENCDEC (PCM_S24LE_PLANAR, pcm_s24le_planar);
REGISTER_ENCDEC (PCM_S32BE, pcm_s32be);
REGISTER_ENCDEC (PCM_S32LE, pcm_s32le);
REGISTER_ENCDEC (PCM_S32LE_PLANAR, pcm_s32le_planar);
REGISTER_ENCDEC (PCM_U8, pcm_u8);
REGISTER_ENCDEC (PCM_U16BE, pcm_u16be);
REGISTER_ENCDEC (PCM_U16LE, pcm_u16le);
REGISTER_ENCDEC (PCM_U24BE, pcm_u24be);
REGISTER_ENCDEC (PCM_U24LE, pcm_u24le);
REGISTER_ENCDEC (PCM_U32BE, pcm_u32be);
REGISTER_ENCDEC (PCM_U32LE, pcm_u32le);
REGISTER_DECODER(PCM_ZORK, pcm_zork);
/* DPCM codecs */
REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm);
REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm);
REGISTER_DECODER(SOL_DPCM, sol_dpcm);
REGISTER_DECODER(XAN_DPCM, xan_dpcm);
/* ADPCM codecs */
REGISTER_DECODER(ADPCM_4XM, adpcm_4xm);
REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx);
REGISTER_DECODER(ADPCM_AFC, adpcm_afc);
REGISTER_DECODER(ADPCM_CT, adpcm_ct);
REGISTER_DECODER(ADPCM_DTK, adpcm_dtk);
REGISTER_DECODER(ADPCM_EA, adpcm_ea);
REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa);
REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1);
REGISTER_DECODER(ADPCM_EA_R2, adpcm_ea_r2);
REGISTER_DECODER(ADPCM_EA_R3, adpcm_ea_r3);
REGISTER_DECODER(ADPCM_EA_XAS, adpcm_ea_xas);
REGISTER_ENCDEC (ADPCM_G722, adpcm_g722);
REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
REGISTER_DECODER(ADPCM_G726LE, adpcm_g726le);
REGISTER_DECODER(ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_DECODER(ADPCM_IMA_APC, adpcm_ima_apc);
REGISTER_DECODER(ADPCM_IMA_DK3, adpcm_ima_dk3);
REGISTER_DECODER(ADPCM_IMA_DK4, adpcm_ima_dk4);
REGISTER_DECODER(ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
REGISTER_DECODER(ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead);
REGISTER_DECODER(ADPCM_IMA_ISS, adpcm_ima_iss);
REGISTER_DECODER(ADPCM_IMA_OKI, adpcm_ima_oki);
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
REGISTER_DECODER(ADPCM_IMA_RAD, adpcm_ima_rad);
REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
REGISTER_DECODER(ADPCM_IMA_WS, adpcm_ima_ws);
REGISTER_ENCDEC (ADPCM_MS, adpcm_ms);
REGISTER_DECODER(ADPCM_SBPRO_2, adpcm_sbpro_2);
REGISTER_DECODER(ADPCM_SBPRO_3, adpcm_sbpro_3);
REGISTER_DECODER(ADPCM_SBPRO_4, adpcm_sbpro_4);
REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
REGISTER_DECODER(ADPCM_THP, adpcm_thp);
REGISTER_DECODER(ADPCM_XA, adpcm_xa);
REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha);
REGISTER_DECODER(VIMA, vima);
/* subtitles */
REGISTER_ENCDEC (SSA, ssa);
REGISTER_ENCDEC (ASS, ass);
REGISTER_ENCDEC (DVBSUB, dvbsub);
REGISTER_ENCDEC (DVDSUB, dvdsub);
REGISTER_DECODER(JACOSUB, jacosub);
REGISTER_DECODER(MICRODVD, microdvd);
REGISTER_ENCDEC (MOVTEXT, movtext);
REGISTER_DECODER(MPL2, mpl2);
REGISTER_DECODER(PGSSUB, pgssub);
REGISTER_DECODER(PJS, pjs);
REGISTER_DECODER(REALTEXT, realtext);
REGISTER_DECODER(SAMI, sami);
REGISTER_ENCDEC (SRT, srt);
REGISTER_ENCDEC (SUBRIP, subrip);
REGISTER_DECODER(SUBVIEWER, subviewer);
REGISTER_DECODER(SUBVIEWER1, subviewer1);
REGISTER_DECODER(TEXT, text);
REGISTER_DECODER(VPLAYER, vplayer);
REGISTER_DECODER(WEBVTT, webvtt);
REGISTER_ENCDEC (XSUB, xsub);
/* external libraries */
REGISTER_DECODER(LIBCELT, libcelt);
REGISTER_ENCODER(LIBFAAC, libfaac);
REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac);
REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
REGISTER_ENCDEC (LIBILBC, libilbc);
REGISTER_ENCODER(LIBMP3LAME, libmp3lame);
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb);
REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb);
REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg);
REGISTER_ENCDEC (LIBOPUS, libopus);
REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger);
REGISTER_ENCODER(LIBSHINE, libshine);
REGISTER_ENCDEC (LIBSPEEX, libspeex);
REGISTER_DECODER(LIBSTAGEFRIGHT_H264, libstagefright_h264);
REGISTER_ENCODER(LIBTHEORA, libtheora);
REGISTER_ENCODER(LIBTWOLAME, libtwolame);
REGISTER_ENCDEC (LIBUTVIDEO, libutvideo);
REGISTER_ENCODER(LIBVO_AACENC, libvo_aacenc);
REGISTER_ENCODER(LIBVO_AMRWBENC, libvo_amrwbenc);
REGISTER_ENCDEC (LIBVORBIS, libvorbis);
REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8);
REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9);
REGISTER_ENCODER(LIBWAVPACK, libwavpack);
REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
REGISTER_ENCODER(LIBXAVS, libxavs);
REGISTER_ENCODER(LIBXVID, libxvid);
REGISTER_DECODER(LIBZVBI_TELETEXT, libzvbi_teletext);
REGISTER_ENCODER(LIBAACPLUS, libaacplus);
/* text */
REGISTER_DECODER(BINTEXT, bintext);
REGISTER_DECODER(XBIN, xbin);
REGISTER_DECODER(IDF, idf);
/* parsers */
REGISTER_PARSER(AAC, aac);
REGISTER_PARSER(AAC_LATM, aac_latm);
REGISTER_PARSER(AC3, ac3);
REGISTER_PARSER(ADX, adx);
REGISTER_PARSER(BMP, bmp);
REGISTER_PARSER(CAVSVIDEO, cavsvideo);
REGISTER_PARSER(COOK, cook);
REGISTER_PARSER(DCA, dca);
REGISTER_PARSER(DIRAC, dirac);
REGISTER_PARSER(DNXHD, dnxhd);
REGISTER_PARSER(DPX, dpx);
REGISTER_PARSER(DVBSUB, dvbsub);
REGISTER_PARSER(DVDSUB, dvdsub);
REGISTER_PARSER(DVD_NAV, dvd_nav);
REGISTER_PARSER(FLAC, flac);
REGISTER_PARSER(GSM, gsm);
REGISTER_PARSER(H261, h261);
REGISTER_PARSER(H263, h263);
REGISTER_PARSER(H264, h264);
REGISTER_PARSER(HEVC, hevc);
REGISTER_PARSER(MJPEG, mjpeg);
REGISTER_PARSER(MLP, mlp);
REGISTER_PARSER(MPEG4VIDEO, mpeg4video);
REGISTER_PARSER(MPEGAUDIO, mpegaudio);
REGISTER_PARSER(MPEGVIDEO, mpegvideo);
REGISTER_PARSER(PNG, png);
REGISTER_PARSER(PNM, pnm);
REGISTER_PARSER(RV30, rv30);
REGISTER_PARSER(RV40, rv40);
REGISTER_PARSER(TAK, tak);
REGISTER_PARSER(VC1, vc1);
REGISTER_PARSER(VORBIS, vorbis);
REGISTER_PARSER(VP3, vp3);
REGISTER_PARSER(VP8, vp8);
/* bitstream filters */
REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc);
REGISTER_BSF(CHOMP, chomp);
REGISTER_BSF(DUMP_EXTRADATA, dump_extradata);
REGISTER_BSF(H264_MP4TOANNEXB, h264_mp4toannexb);
REGISTER_BSF(IMX_DUMP_HEADER, imx_dump_header);
REGISTER_BSF(MJPEG2JPEG, mjpeg2jpeg);
REGISTER_BSF(MJPEGA_DUMP_HEADER, mjpega_dump_header);
REGISTER_BSF(MP3_HEADER_COMPRESS, mp3_header_compress);
REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress);
REGISTER_BSF(MOV2TEXTSUB, mov2textsub);
REGISTER_BSF(NOISE, noise);
REGISTER_BSF(REMOVE_EXTRADATA, remove_extradata);
REGISTER_BSF(TEXT2MOVSUB, text2movsub);
}

View File

@@ -0,0 +1,9 @@
OBJS += alpha/dsputil_alpha.o \
alpha/dsputil_alpha_asm.o \
alpha/motion_est_alpha.o \
alpha/motion_est_mvi_asm.o \
alpha/simple_idct_alpha.o \
OBJS-$(CONFIG_HPELDSP) += alpha/hpeldsp_alpha.o \
alpha/hpeldsp_alpha_asm.o
OBJS-$(CONFIG_MPEGVIDEO) += alpha/mpegvideo_alpha.o

View File

@@ -0,0 +1,186 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 AVCODEC_ALPHA_ASM_H
#define AVCODEC_ALPHA_ASM_H
#include <inttypes.h>
#include "libavutil/common.h"
#if AV_GCC_VERSION_AT_LEAST(2,96)
# define likely(x) __builtin_expect((x) != 0, 1)
# define unlikely(x) __builtin_expect((x) != 0, 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
#define AMASK_BWX (1 << 0)
#define AMASK_FIX (1 << 1)
#define AMASK_CIX (1 << 2)
#define AMASK_MVI (1 << 8)
static inline uint64_t BYTE_VEC(uint64_t x)
{
x |= x << 8;
x |= x << 16;
x |= x << 32;
return x;
}
static inline uint64_t WORD_VEC(uint64_t x)
{
x |= x << 16;
x |= x << 32;
return x;
}
#define sextw(x) ((int16_t) (x))
#ifdef __GNUC__
#define ldq(p) \
(((const union { \
uint64_t __l; \
__typeof__(*(p)) __s[sizeof (uint64_t) / sizeof *(p)]; \
} *) (p))->__l)
#define ldl(p) \
(((const union { \
int32_t __l; \
__typeof__(*(p)) __s[sizeof (int32_t) / sizeof *(p)]; \
} *) (p))->__l)
#define stq(l, p) \
do { \
(((union { \
uint64_t __l; \
__typeof__(*(p)) __s[sizeof (uint64_t) / sizeof *(p)]; \
} *) (p))->__l) = l; \
} while (0)
#define stl(l, p) \
do { \
(((union { \
int32_t __l; \
__typeof__(*(p)) __s[sizeof (int32_t) / sizeof *(p)]; \
} *) (p))->__l) = l; \
} while (0)
struct unaligned_long { uint64_t l; } __attribute__((packed));
#define ldq_u(p) (*(const uint64_t *) (((uint64_t) (p)) & ~7ul))
#define uldq(a) (((const struct unaligned_long *) (a))->l)
#if AV_GCC_VERSION_AT_LEAST(3,3)
#define prefetch(p) __builtin_prefetch((p), 0, 1)
#define prefetch_en(p) __builtin_prefetch((p), 0, 0)
#define prefetch_m(p) __builtin_prefetch((p), 1, 1)
#define prefetch_men(p) __builtin_prefetch((p), 1, 0)
#define cmpbge __builtin_alpha_cmpbge
/* Avoid warnings. */
#define extql(a, b) __builtin_alpha_extql(a, (uint64_t) (b))
#define extwl(a, b) __builtin_alpha_extwl(a, (uint64_t) (b))
#define extqh(a, b) __builtin_alpha_extqh(a, (uint64_t) (b))
#define zap __builtin_alpha_zap
#define zapnot __builtin_alpha_zapnot
#define amask __builtin_alpha_amask
#define implver __builtin_alpha_implver
#define rpcc __builtin_alpha_rpcc
#else
#define prefetch(p) __asm__ volatile("ldl $31,%0" : : "m"(*(const char *) (p)) : "memory")
#define prefetch_en(p) __asm__ volatile("ldq $31,%0" : : "m"(*(const char *) (p)) : "memory")
#define prefetch_m(p) __asm__ volatile("lds $f31,%0" : : "m"(*(const char *) (p)) : "memory")
#define prefetch_men(p) __asm__ volatile("ldt $f31,%0" : : "m"(*(const char *) (p)) : "memory")
#define cmpbge(a, b) ({ uint64_t __r; __asm__ ("cmpbge %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define extql(a, b) ({ uint64_t __r; __asm__ ("extql %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define extwl(a, b) ({ uint64_t __r; __asm__ ("extwl %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define extqh(a, b) ({ uint64_t __r; __asm__ ("extqh %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define zap(a, b) ({ uint64_t __r; __asm__ ("zap %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define zapnot(a, b) ({ uint64_t __r; __asm__ ("zapnot %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; })
#define amask(a) ({ uint64_t __r; __asm__ ("amask %1,%0" : "=r" (__r) : "rI" (a)); __r; })
#define implver() ({ uint64_t __r; __asm__ ("implver %0" : "=r" (__r)); __r; })
#define rpcc() ({ uint64_t __r; __asm__ volatile ("rpcc %0" : "=r" (__r)); __r; })
#endif
#define wh64(p) __asm__ volatile("wh64 (%0)" : : "r"(p) : "memory")
#if AV_GCC_VERSION_AT_LEAST(3,3) && defined(__alpha_max__)
#define minub8 __builtin_alpha_minub8
#define minsb8 __builtin_alpha_minsb8
#define minuw4 __builtin_alpha_minuw4
#define minsw4 __builtin_alpha_minsw4
#define maxub8 __builtin_alpha_maxub8
#define maxsb8 __builtin_alpha_maxsb8
#define maxuw4 __builtin_alpha_maxuw4
#define maxsw4 __builtin_alpha_maxsw4
#define perr __builtin_alpha_perr
#define pklb __builtin_alpha_pklb
#define pkwb __builtin_alpha_pkwb
#define unpkbl __builtin_alpha_unpkbl
#define unpkbw __builtin_alpha_unpkbw
#else
#define minub8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minub8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define minsb8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minsb8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define minuw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minuw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define minsw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minsw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define maxub8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxub8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define maxsb8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxsb8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define maxuw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxuw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define maxsw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxsw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; })
#define perr(a, b) ({ uint64_t __r; __asm__ (".arch ev6; perr %r1,%r2,%0" : "=r" (__r) : "%rJ" (a), "rJ" (b)); __r; })
#define pklb(a) ({ uint64_t __r; __asm__ (".arch ev6; pklb %r1,%0" : "=r" (__r) : "rJ" (a)); __r; })
#define pkwb(a) ({ uint64_t __r; __asm__ (".arch ev6; pkwb %r1,%0" : "=r" (__r) : "rJ" (a)); __r; })
#define unpkbl(a) ({ uint64_t __r; __asm__ (".arch ev6; unpkbl %r1,%0" : "=r" (__r) : "rJ" (a)); __r; })
#define unpkbw(a) ({ uint64_t __r; __asm__ (".arch ev6; unpkbw %r1,%0" : "=r" (__r) : "rJ" (a)); __r; })
#endif
#elif defined(__DECC) /* Digital/Compaq/hp "ccc" compiler */
#include <c_asm.h>
#define ldq(p) (*(const uint64_t *) (p))
#define ldl(p) (*(const int32_t *) (p))
#define stq(l, p) do { *(uint64_t *) (p) = (l); } while (0)
#define stl(l, p) do { *(int32_t *) (p) = (l); } while (0)
#define ldq_u(a) asm ("ldq_u %v0,0(%a0)", a)
#define uldq(a) (*(const __unaligned uint64_t *) (a))
#define cmpbge(a, b) asm ("cmpbge %a0,%a1,%v0", a, b)
#define extql(a, b) asm ("extql %a0,%a1,%v0", a, b)
#define extwl(a, b) asm ("extwl %a0,%a1,%v0", a, b)
#define extqh(a, b) asm ("extqh %a0,%a1,%v0", a, b)
#define zap(a, b) asm ("zap %a0,%a1,%v0", a, b)
#define zapnot(a, b) asm ("zapnot %a0,%a1,%v0", a, b)
#define amask(a) asm ("amask %a0,%v0", a)
#define implver() asm ("implver %v0")
#define rpcc() asm ("rpcc %v0")
#define minub8(a, b) asm ("minub8 %a0,%a1,%v0", a, b)
#define minsb8(a, b) asm ("minsb8 %a0,%a1,%v0", a, b)
#define minuw4(a, b) asm ("minuw4 %a0,%a1,%v0", a, b)
#define minsw4(a, b) asm ("minsw4 %a0,%a1,%v0", a, b)
#define maxub8(a, b) asm ("maxub8 %a0,%a1,%v0", a, b)
#define maxsb8(a, b) asm ("maxsb8 %a0,%a1,%v0", a, b)
#define maxuw4(a, b) asm ("maxuw4 %a0,%a1,%v0", a, b)
#define maxsw4(a, b) asm ("maxsw4 %a0,%a1,%v0", a, b)
#define perr(a, b) asm ("perr %a0,%a1,%v0", a, b)
#define pklb(a) asm ("pklb %a0,%v0", a)
#define pkwb(a) asm ("pkwb %a0,%v0", a)
#define unpkbl(a) asm ("unpkbl %a0,%v0", a)
#define unpkbw(a) asm ("unpkbw %a0,%v0", a)
#define wh64(a) asm ("wh64 %a0", a)
#else
#error "Unknown compiler!"
#endif
#endif /* AVCODEC_ALPHA_ASM_H */

View File

@@ -0,0 +1,157 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 "libavutil/attributes.h"
#include "libavcodec/dsputil.h"
#include "dsputil_alpha.h"
#include "asm.h"
void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels,
int line_size);
void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels,
int line_size);
#if 0
/* These functions were the base for the optimized assembler routines,
and remain here for documentation purposes. */
static void put_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels,
ptrdiff_t line_size)
{
int i = 8;
uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */
do {
uint64_t shorts0, shorts1;
shorts0 = ldq(block);
shorts0 = maxsw4(shorts0, 0);
shorts0 = minsw4(shorts0, clampmask);
stl(pkwb(shorts0), pixels);
shorts1 = ldq(block + 4);
shorts1 = maxsw4(shorts1, 0);
shorts1 = minsw4(shorts1, clampmask);
stl(pkwb(shorts1), pixels + 4);
pixels += line_size;
block += 8;
} while (--i);
}
void add_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels,
ptrdiff_t line_size)
{
int h = 8;
/* Keep this function a leaf function by generating the constants
manually (mainly for the hack value ;-). */
uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */
uint64_t signmask = zap(-1, 0x33);
signmask ^= signmask >> 1; /* 0x8000800080008000 */
do {
uint64_t shorts0, pix0, signs0;
uint64_t shorts1, pix1, signs1;
shorts0 = ldq(block);
shorts1 = ldq(block + 4);
pix0 = unpkbw(ldl(pixels));
/* Signed subword add (MMX paddw). */
signs0 = shorts0 & signmask;
shorts0 &= ~signmask;
shorts0 += pix0;
shorts0 ^= signs0;
/* Clamp. */
shorts0 = maxsw4(shorts0, 0);
shorts0 = minsw4(shorts0, clampmask);
/* Next 4. */
pix1 = unpkbw(ldl(pixels + 4));
signs1 = shorts1 & signmask;
shorts1 &= ~signmask;
shorts1 += pix1;
shorts1 ^= signs1;
shorts1 = maxsw4(shorts1, 0);
shorts1 = minsw4(shorts1, clampmask);
stl(pkwb(shorts0), pixels);
stl(pkwb(shorts1), pixels + 4);
pixels += line_size;
block += 8;
} while (--h);
}
#endif
static void clear_blocks_axp(int16_t *blocks) {
uint64_t *p = (uint64_t *) blocks;
int n = sizeof(int16_t) * 6 * 64;
do {
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
p[4] = 0;
p[5] = 0;
p[6] = 0;
p[7] = 0;
p += 8;
n -= 8 * 8;
} while (n);
}
av_cold void ff_dsputil_init_alpha(DSPContext *c, AVCodecContext *avctx)
{
const int high_bit_depth = avctx->bits_per_raw_sample > 8;
if (!high_bit_depth) {
c->clear_blocks = clear_blocks_axp;
}
/* amask clears all bits that correspond to present features. */
if (amask(AMASK_MVI) == 0) {
c->put_pixels_clamped = put_pixels_clamped_mvi_asm;
c->add_pixels_clamped = add_pixels_clamped_mvi_asm;
if (!high_bit_depth)
c->get_pixels = get_pixels_mvi;
c->diff_pixels = diff_pixels_mvi;
c->sad[0] = pix_abs16x16_mvi_asm;
c->sad[1] = pix_abs8x8_mvi;
c->pix_abs[0][0] = pix_abs16x16_mvi_asm;
c->pix_abs[1][0] = pix_abs8x8_mvi;
c->pix_abs[0][1] = pix_abs16x16_x2_mvi;
c->pix_abs[0][2] = pix_abs16x16_y2_mvi;
c->pix_abs[0][3] = pix_abs16x16_xy2_mvi;
}
put_pixels_clamped_axp_p = c->put_pixels_clamped;
add_pixels_clamped_axp_p = c->add_pixels_clamped;
if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 &&
(avctx->idct_algo == FF_IDCT_AUTO ||
avctx->idct_algo == FF_IDCT_SIMPLEALPHA)) {
c->idct_put = ff_simple_idct_put_axp;
c->idct_add = ff_simple_idct_add_axp;
c->idct = ff_simple_idct_axp;
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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 AVCODEC_ALPHA_DSPUTIL_ALPHA_H
#define AVCODEC_ALPHA_DSPUTIL_ALPHA_H
#include <stddef.h>
#include <stdint.h>
void ff_simple_idct_axp(int16_t *block);
void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block);
void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block);
void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels,
int line_size);
void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels,
int line_size);
extern void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels,
int line_size);
extern void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels,
int line_size);
void get_pixels_mvi(int16_t *restrict block,
const uint8_t *restrict pixels, int line_size);
void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2,
int stride);
int pix_abs8x8_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
int pix_abs16x16_mvi_asm(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
int pix_abs16x16_x2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
int pix_abs16x16_y2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
int pix_abs16x16_xy2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
#endif /* AVCODEC_ALPHA_DSPUTIL_ALPHA_H */

View File

@@ -0,0 +1,167 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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
*/
/*
* These functions are scheduled for pca56. They should work
* reasonably on ev6, though.
*/
#include "regdef.h"
.set noat
.set noreorder
.arch pca56
.text
/************************************************************************
* void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels,
* int line_size)
*/
.align 6
.globl put_pixels_clamped_mvi_asm
.ent put_pixels_clamped_mvi_asm
put_pixels_clamped_mvi_asm:
.frame sp, 0, ra
.prologue 0
lda t8, -1
lda t9, 8 # loop counter
zap t8, 0xaa, t8 # 00ff00ff00ff00ff
.align 4
1: ldq t0, 0(a0)
ldq t1, 8(a0)
ldq t2, 16(a0)
ldq t3, 24(a0)
maxsw4 t0, zero, t0
subq t9, 2, t9
maxsw4 t1, zero, t1
lda a0, 32(a0)
maxsw4 t2, zero, t2
addq a1, a2, ta
maxsw4 t3, zero, t3
minsw4 t0, t8, t0
minsw4 t1, t8, t1
minsw4 t2, t8, t2
minsw4 t3, t8, t3
pkwb t0, t0
pkwb t1, t1
pkwb t2, t2
pkwb t3, t3
stl t0, 0(a1)
stl t1, 4(a1)
addq ta, a2, a1
stl t2, 0(ta)
stl t3, 4(ta)
bne t9, 1b
ret
.end put_pixels_clamped_mvi_asm
/************************************************************************
* void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels,
* int line_size)
*/
.align 6
.globl add_pixels_clamped_mvi_asm
.ent add_pixels_clamped_mvi_asm
add_pixels_clamped_mvi_asm:
.frame sp, 0, ra
.prologue 0
lda t1, -1
lda th, 8
zap t1, 0x33, tg
nop
srl tg, 1, t0
xor tg, t0, tg # 0x8000800080008000
zap t1, 0xaa, tf # 0x00ff00ff00ff00ff
.align 4
1: ldl t1, 0(a1) # pix0 (try to hit cache line soon)
ldl t4, 4(a1) # pix1
addq a1, a2, te # pixels += line_size
ldq t0, 0(a0) # shorts0
ldl t7, 0(te) # pix2 (try to hit cache line soon)
ldl ta, 4(te) # pix3
ldq t3, 8(a0) # shorts1
ldq t6, 16(a0) # shorts2
ldq t9, 24(a0) # shorts3
unpkbw t1, t1 # 0 0 (quarter/op no.)
and t0, tg, t2 # 0 1
unpkbw t4, t4 # 1 0
bic t0, tg, t0 # 0 2
unpkbw t7, t7 # 2 0
and t3, tg, t5 # 1 1
addq t0, t1, t0 # 0 3
xor t0, t2, t0 # 0 4
unpkbw ta, ta # 3 0
and t6, tg, t8 # 2 1
maxsw4 t0, zero, t0 # 0 5
bic t3, tg, t3 # 1 2
bic t6, tg, t6 # 2 2
minsw4 t0, tf, t0 # 0 6
addq t3, t4, t3 # 1 3
pkwb t0, t0 # 0 7
xor t3, t5, t3 # 1 4
maxsw4 t3, zero, t3 # 1 5
addq t6, t7, t6 # 2 3
xor t6, t8, t6 # 2 4
and t9, tg, tb # 3 1
minsw4 t3, tf, t3 # 1 6
bic t9, tg, t9 # 3 2
maxsw4 t6, zero, t6 # 2 5
addq t9, ta, t9 # 3 3
stl t0, 0(a1) # 0 8
minsw4 t6, tf, t6 # 2 6
xor t9, tb, t9 # 3 4
maxsw4 t9, zero, t9 # 3 5
lda a0, 32(a0) # block += 16;
pkwb t3, t3 # 1 7
minsw4 t9, tf, t9 # 3 6
subq th, 2, th
pkwb t6, t6 # 2 7
pkwb t9, t9 # 3 7
stl t3, 4(a1) # 1 8
addq te, a2, a1 # pixels += line_size
stl t6, 0(te) # 2 8
stl t9, 4(te) # 3 8
bne th, 1b
ret
.end add_pixels_clamped_mvi_asm

View File

@@ -0,0 +1,213 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 "libavutil/attributes.h"
#include "libavcodec/hpeldsp.h"
#include "hpeldsp_alpha.h"
#include "asm.h"
static inline uint64_t avg2_no_rnd(uint64_t a, uint64_t b)
{
return (a & b) + (((a ^ b) & BYTE_VEC(0xfe)) >> 1);
}
static inline uint64_t avg2(uint64_t a, uint64_t b)
{
return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1);
}
#if 0
/* The XY2 routines basically utilize this scheme, but reuse parts in
each iteration. */
static inline uint64_t avg4(uint64_t l1, uint64_t l2, uint64_t l3, uint64_t l4)
{
uint64_t r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2)
+ ((l2 & ~BYTE_VEC(0x03)) >> 2)
+ ((l3 & ~BYTE_VEC(0x03)) >> 2)
+ ((l4 & ~BYTE_VEC(0x03)) >> 2);
uint64_t r2 = (( (l1 & BYTE_VEC(0x03))
+ (l2 & BYTE_VEC(0x03))
+ (l3 & BYTE_VEC(0x03))
+ (l4 & BYTE_VEC(0x03))
+ BYTE_VEC(0x02)) >> 2) & BYTE_VEC(0x03);
return r1 + r2;
}
#endif
#define OP(LOAD, STORE) \
do { \
STORE(LOAD(pixels), block); \
pixels += line_size; \
block += line_size; \
} while (--h)
#define OP_X2(LOAD, STORE) \
do { \
uint64_t pix1, pix2; \
\
pix1 = LOAD(pixels); \
pix2 = pix1 >> 8 | ((uint64_t) pixels[8] << 56); \
STORE(AVG2(pix1, pix2), block); \
pixels += line_size; \
block += line_size; \
} while (--h)
#define OP_Y2(LOAD, STORE) \
do { \
uint64_t pix = LOAD(pixels); \
do { \
uint64_t next_pix; \
\
pixels += line_size; \
next_pix = LOAD(pixels); \
STORE(AVG2(pix, next_pix), block); \
block += line_size; \
pix = next_pix; \
} while (--h); \
} while (0)
#define OP_XY2(LOAD, STORE) \
do { \
uint64_t pix1 = LOAD(pixels); \
uint64_t pix2 = pix1 >> 8 | ((uint64_t) pixels[8] << 56); \
uint64_t pix_l = (pix1 & BYTE_VEC(0x03)) \
+ (pix2 & BYTE_VEC(0x03)); \
uint64_t pix_h = ((pix1 & ~BYTE_VEC(0x03)) >> 2) \
+ ((pix2 & ~BYTE_VEC(0x03)) >> 2); \
\
do { \
uint64_t npix1, npix2; \
uint64_t npix_l, npix_h; \
uint64_t avg; \
\
pixels += line_size; \
npix1 = LOAD(pixels); \
npix2 = npix1 >> 8 | ((uint64_t) pixels[8] << 56); \
npix_l = (npix1 & BYTE_VEC(0x03)) \
+ (npix2 & BYTE_VEC(0x03)); \
npix_h = ((npix1 & ~BYTE_VEC(0x03)) >> 2) \
+ ((npix2 & ~BYTE_VEC(0x03)) >> 2); \
avg = (((pix_l + npix_l + AVG4_ROUNDER) >> 2) & BYTE_VEC(0x03)) \
+ pix_h + npix_h; \
STORE(avg, block); \
\
block += line_size; \
pix_l = npix_l; \
pix_h = npix_h; \
} while (--h); \
} while (0)
#define MAKE_OP(OPNAME, SUFF, OPKIND, STORE) \
static void OPNAME ## _pixels ## SUFF ## _axp \
(uint8_t *restrict block, const uint8_t *restrict pixels, \
ptrdiff_t line_size, int h) \
{ \
if ((size_t) pixels & 0x7) { \
OPKIND(uldq, STORE); \
} else { \
OPKIND(ldq, STORE); \
} \
} \
\
static void OPNAME ## _pixels16 ## SUFF ## _axp \
(uint8_t *restrict block, const uint8_t *restrict pixels, \
ptrdiff_t line_size, int h) \
{ \
OPNAME ## _pixels ## SUFF ## _axp(block, pixels, line_size, h); \
OPNAME ## _pixels ## SUFF ## _axp(block + 8, pixels + 8, line_size, h); \
}
#define PIXOP(OPNAME, STORE) \
MAKE_OP(OPNAME, , OP, STORE) \
MAKE_OP(OPNAME, _x2, OP_X2, STORE) \
MAKE_OP(OPNAME, _y2, OP_Y2, STORE) \
MAKE_OP(OPNAME, _xy2, OP_XY2, STORE)
/* Rounding primitives. */
#define AVG2 avg2
#define AVG4 avg4
#define AVG4_ROUNDER BYTE_VEC(0x02)
#define STORE(l, b) stq(l, b)
PIXOP(put, STORE);
#undef STORE
#define STORE(l, b) stq(AVG2(l, ldq(b)), b);
PIXOP(avg, STORE);
/* Not rounding primitives. */
#undef AVG2
#undef AVG4
#undef AVG4_ROUNDER
#undef STORE
#define AVG2 avg2_no_rnd
#define AVG4 avg4_no_rnd
#define AVG4_ROUNDER BYTE_VEC(0x01)
#define STORE(l, b) stq(l, b)
PIXOP(put_no_rnd, STORE);
#undef STORE
#define STORE(l, b) stq(AVG2(l, ldq(b)), b);
PIXOP(avg_no_rnd, STORE);
static void put_pixels16_axp_asm(uint8_t *block, const uint8_t *pixels,
ptrdiff_t line_size, int h)
{
put_pixels_axp_asm(block, pixels, line_size, h);
put_pixels_axp_asm(block + 8, pixels + 8, line_size, h);
}
av_cold void ff_hpeldsp_init_alpha(HpelDSPContext *c, int flags)
{
c->put_pixels_tab[0][0] = put_pixels16_axp_asm;
c->put_pixels_tab[0][1] = put_pixels16_x2_axp;
c->put_pixels_tab[0][2] = put_pixels16_y2_axp;
c->put_pixels_tab[0][3] = put_pixels16_xy2_axp;
c->put_no_rnd_pixels_tab[0][0] = put_pixels16_axp_asm;
c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_axp;
c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_axp;
c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_axp;
c->avg_pixels_tab[0][0] = avg_pixels16_axp;
c->avg_pixels_tab[0][1] = avg_pixels16_x2_axp;
c->avg_pixels_tab[0][2] = avg_pixels16_y2_axp;
c->avg_pixels_tab[0][3] = avg_pixels16_xy2_axp;
c->avg_no_rnd_pixels_tab[0] = avg_no_rnd_pixels16_axp;
c->avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels16_x2_axp;
c->avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels16_y2_axp;
c->avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels16_xy2_axp;
c->put_pixels_tab[1][0] = put_pixels_axp_asm;
c->put_pixels_tab[1][1] = put_pixels_x2_axp;
c->put_pixels_tab[1][2] = put_pixels_y2_axp;
c->put_pixels_tab[1][3] = put_pixels_xy2_axp;
c->put_no_rnd_pixels_tab[1][0] = put_pixels_axp_asm;
c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels_x2_axp;
c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels_y2_axp;
c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels_xy2_axp;
c->avg_pixels_tab[1][0] = avg_pixels_axp;
c->avg_pixels_tab[1][1] = avg_pixels_x2_axp;
c->avg_pixels_tab[1][2] = avg_pixels_y2_axp;
c->avg_pixels_tab[1][3] = avg_pixels_xy2_axp;
}

View File

@@ -0,0 +1,28 @@
/*
* 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 AVCODEC_ALPHA_HPELDSP_ALPHA_H
#define AVCODEC_ALPHA_HPELDSP_ALPHA_H
#include <stdint.h>
#include <stddef.h>
void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels,
ptrdiff_t line_size, int h);
#endif /* AVCODEC_ALPHA_HPELDSP_ALPHA_H */

View File

@@ -0,0 +1,125 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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
*/
/*
* These functions are scheduled for pca56. They should work
* reasonably on ev6, though.
*/
#include "regdef.h"
.set noat
.set noreorder
.arch pca56
.text
/************************************************************************
* void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels,
* int line_size, int h)
*/
.align 6
.globl put_pixels_axp_asm
.ent put_pixels_axp_asm
put_pixels_axp_asm:
.frame sp, 0, ra
.prologue 0
and a1, 7, t0
beq t0, $aligned
.align 4
$unaligned:
ldq_u t0, 0(a1)
ldq_u t1, 8(a1)
addq a1, a2, a1
nop
ldq_u t2, 0(a1)
ldq_u t3, 8(a1)
addq a1, a2, a1
nop
ldq_u t4, 0(a1)
ldq_u t5, 8(a1)
addq a1, a2, a1
nop
ldq_u t6, 0(a1)
ldq_u t7, 8(a1)
extql t0, a1, t0
addq a1, a2, a1
extqh t1, a1, t1
addq a0, a2, t8
extql t2, a1, t2
addq t8, a2, t9
extqh t3, a1, t3
addq t9, a2, ta
extql t4, a1, t4
or t0, t1, t0
extqh t5, a1, t5
or t2, t3, t2
extql t6, a1, t6
or t4, t5, t4
extqh t7, a1, t7
or t6, t7, t6
stq t0, 0(a0)
stq t2, 0(t8)
stq t4, 0(t9)
subq a3, 4, a3
stq t6, 0(ta)
addq ta, a2, a0
bne a3, $unaligned
ret
.align 4
$aligned:
ldq t0, 0(a1)
addq a1, a2, a1
ldq t1, 0(a1)
addq a1, a2, a1
ldq t2, 0(a1)
addq a1, a2, a1
ldq t3, 0(a1)
addq a0, a2, t4
addq a1, a2, a1
addq t4, a2, t5
subq a3, 4, a3
stq t0, 0(a0)
addq t5, a2, t6
stq t1, 0(t4)
addq t6, a2, a0
stq t2, 0(t5)
stq t3, 0(t6)
bne a3, $aligned
ret
.end put_pixels_axp_asm

View File

@@ -0,0 +1,345 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 "dsputil_alpha.h"
#include "asm.h"
void get_pixels_mvi(int16_t *restrict block,
const uint8_t *restrict pixels, int line_size)
{
int h = 8;
do {
uint64_t p;
p = ldq(pixels);
stq(unpkbw(p), block);
stq(unpkbw(p >> 32), block + 4);
pixels += line_size;
block += 8;
} while (--h);
}
void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2,
int stride) {
int h = 8;
uint64_t mask = 0x4040;
mask |= mask << 16;
mask |= mask << 32;
do {
uint64_t x, y, c, d, a;
uint64_t signs;
x = ldq(s1);
y = ldq(s2);
c = cmpbge(x, y);
d = x - y;
a = zap(mask, c); /* We use 0x4040404040404040 here... */
d += 4 * a; /* ...so we can use s4addq here. */
signs = zap(-1, c);
stq(unpkbw(d) | (unpkbw(signs) << 8), block);
stq(unpkbw(d >> 32) | (unpkbw(signs >> 32) << 8), block + 4);
s1 += stride;
s2 += stride;
block += 8;
} while (--h);
}
static inline uint64_t avg2(uint64_t a, uint64_t b)
{
return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1);
}
static inline uint64_t avg4(uint64_t l1, uint64_t l2, uint64_t l3, uint64_t l4)
{
uint64_t r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2)
+ ((l2 & ~BYTE_VEC(0x03)) >> 2)
+ ((l3 & ~BYTE_VEC(0x03)) >> 2)
+ ((l4 & ~BYTE_VEC(0x03)) >> 2);
uint64_t r2 = (( (l1 & BYTE_VEC(0x03))
+ (l2 & BYTE_VEC(0x03))
+ (l3 & BYTE_VEC(0x03))
+ (l4 & BYTE_VEC(0x03))
+ BYTE_VEC(0x02)) >> 2) & BYTE_VEC(0x03);
return r1 + r2;
}
int pix_abs8x8_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
{
int result = 0;
if ((size_t) pix2 & 0x7) {
/* works only when pix2 is actually unaligned */
do { /* do 8 pixel a time */
uint64_t p1, p2;
p1 = ldq(pix1);
p2 = uldq(pix2);
result += perr(p1, p2);
pix1 += line_size;
pix2 += line_size;
} while (--h);
} else {
do {
uint64_t p1, p2;
p1 = ldq(pix1);
p2 = ldq(pix2);
result += perr(p1, p2);
pix1 += line_size;
pix2 += line_size;
} while (--h);
}
return result;
}
#if 0 /* now done in assembly */
int pix_abs16x16_mvi(uint8_t *pix1, uint8_t *pix2, int line_size)
{
int result = 0;
int h = 16;
if ((size_t) pix2 & 0x7) {
/* works only when pix2 is actually unaligned */
do { /* do 16 pixel a time */
uint64_t p1_l, p1_r, p2_l, p2_r;
uint64_t t;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
t = ldq_u(pix2 + 8);
p2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2);
p2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2);
pix1 += line_size;
pix2 += line_size;
result += perr(p1_l, p2_l)
+ perr(p1_r, p2_r);
} while (--h);
} else {
do {
uint64_t p1_l, p1_r, p2_l, p2_r;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
p2_l = ldq(pix2);
p2_r = ldq(pix2 + 8);
pix1 += line_size;
pix2 += line_size;
result += perr(p1_l, p2_l)
+ perr(p1_r, p2_r);
} while (--h);
}
return result;
}
#endif
int pix_abs16x16_x2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
{
int result = 0;
uint64_t disalign = (size_t) pix2 & 0x7;
switch (disalign) {
case 0:
do {
uint64_t p1_l, p1_r, p2_l, p2_r;
uint64_t l, r;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
l = ldq(pix2);
r = ldq(pix2 + 8);
p2_l = avg2(l, (l >> 8) | ((uint64_t) r << 56));
p2_r = avg2(r, (r >> 8) | ((uint64_t) pix2[16] << 56));
pix1 += line_size;
pix2 += line_size;
result += perr(p1_l, p2_l)
+ perr(p1_r, p2_r);
} while (--h);
break;
case 7:
/* |.......l|lllllllr|rrrrrrr*|
This case is special because disalign1 would be 8, which
gets treated as 0 by extqh. At least it is a bit faster
that way :) */
do {
uint64_t p1_l, p1_r, p2_l, p2_r;
uint64_t l, m, r;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
l = ldq_u(pix2);
m = ldq_u(pix2 + 8);
r = ldq_u(pix2 + 16);
p2_l = avg2(extql(l, disalign) | extqh(m, disalign), m);
p2_r = avg2(extql(m, disalign) | extqh(r, disalign), r);
pix1 += line_size;
pix2 += line_size;
result += perr(p1_l, p2_l)
+ perr(p1_r, p2_r);
} while (--h);
break;
default:
do {
uint64_t disalign1 = disalign + 1;
uint64_t p1_l, p1_r, p2_l, p2_r;
uint64_t l, m, r;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
l = ldq_u(pix2);
m = ldq_u(pix2 + 8);
r = ldq_u(pix2 + 16);
p2_l = avg2(extql(l, disalign) | extqh(m, disalign),
extql(l, disalign1) | extqh(m, disalign1));
p2_r = avg2(extql(m, disalign) | extqh(r, disalign),
extql(m, disalign1) | extqh(r, disalign1));
pix1 += line_size;
pix2 += line_size;
result += perr(p1_l, p2_l)
+ perr(p1_r, p2_r);
} while (--h);
break;
}
return result;
}
int pix_abs16x16_y2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
{
int result = 0;
if ((size_t) pix2 & 0x7) {
uint64_t t, p2_l, p2_r;
t = ldq_u(pix2 + 8);
p2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2);
p2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2);
do {
uint64_t p1_l, p1_r, np2_l, np2_r;
uint64_t t;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
pix2 += line_size;
t = ldq_u(pix2 + 8);
np2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2);
np2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2);
result += perr(p1_l, avg2(p2_l, np2_l))
+ perr(p1_r, avg2(p2_r, np2_r));
pix1 += line_size;
p2_l = np2_l;
p2_r = np2_r;
} while (--h);
} else {
uint64_t p2_l, p2_r;
p2_l = ldq(pix2);
p2_r = ldq(pix2 + 8);
do {
uint64_t p1_l, p1_r, np2_l, np2_r;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
pix2 += line_size;
np2_l = ldq(pix2);
np2_r = ldq(pix2 + 8);
result += perr(p1_l, avg2(p2_l, np2_l))
+ perr(p1_r, avg2(p2_r, np2_r));
pix1 += line_size;
p2_l = np2_l;
p2_r = np2_r;
} while (--h);
}
return result;
}
int pix_abs16x16_xy2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
{
int result = 0;
uint64_t p1_l, p1_r;
uint64_t p2_l, p2_r, p2_x;
p1_l = ldq(pix1);
p1_r = ldq(pix1 + 8);
if ((size_t) pix2 & 0x7) { /* could be optimized a lot */
p2_l = uldq(pix2);
p2_r = uldq(pix2 + 8);
p2_x = (uint64_t) pix2[16] << 56;
} else {
p2_l = ldq(pix2);
p2_r = ldq(pix2 + 8);
p2_x = ldq(pix2 + 16) << 56;
}
do {
uint64_t np1_l, np1_r;
uint64_t np2_l, np2_r, np2_x;
pix1 += line_size;
pix2 += line_size;
np1_l = ldq(pix1);
np1_r = ldq(pix1 + 8);
if ((size_t) pix2 & 0x7) { /* could be optimized a lot */
np2_l = uldq(pix2);
np2_r = uldq(pix2 + 8);
np2_x = (uint64_t) pix2[16] << 56;
} else {
np2_l = ldq(pix2);
np2_r = ldq(pix2 + 8);
np2_x = ldq(pix2 + 16) << 56;
}
result += perr(p1_l,
avg4( p2_l, ( p2_l >> 8) | ((uint64_t) p2_r << 56),
np2_l, (np2_l >> 8) | ((uint64_t) np2_r << 56)))
+ perr(p1_r,
avg4( p2_r, ( p2_r >> 8) | ((uint64_t) p2_x),
np2_r, (np2_r >> 8) | ((uint64_t) np2_x)));
p1_l = np1_l;
p1_r = np1_r;
p2_l = np2_l;
p2_r = np2_r;
p2_x = np2_x;
} while (--h);
return result;
}

View File

@@ -0,0 +1,179 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 "regdef.h"
/* Some nicer register names. */
#define ta t10
#define tb t11
#define tc t12
#define td AT
/* Danger: these overlap with the argument list and the return value */
#define te a5
#define tf a4
#define tg a3
#define th v0
.set noat
.set noreorder
.arch pca56
.text
/*****************************************************************************
* int pix_abs16x16_mvi_asm(uint8_t *pix1, uint8_t *pix2, int line_size)
*
* This code is written with a pca56 in mind. For ev6, one should
* really take the increased latency of 3 cycles for MVI instructions
* into account.
*
* It is important to keep the loading and first use of a register as
* far apart as possible, because if a register is accessed before it
* has been fetched from memory, the CPU will stall.
*/
.align 4
.globl pix_abs16x16_mvi_asm
.ent pix_abs16x16_mvi_asm
pix_abs16x16_mvi_asm:
.frame sp, 0, ra, 0
.prologue 0
and a2, 7, t0
clr v0
beq t0, $aligned
.align 4
$unaligned:
/* Registers:
line 0:
t0: left_u -> left lo -> left
t1: mid
t2: right_u -> right hi -> right
t3: ref left
t4: ref right
line 1:
t5: left_u -> left lo -> left
t6: mid
t7: right_u -> right hi -> right
t8: ref left
t9: ref right
temp:
ta: left hi
tb: right lo
tc: error left
td: error right */
/* load line 0 */
ldq_u t0, 0(a2) # left_u
ldq_u t1, 8(a2) # mid
ldq_u t2, 16(a2) # right_u
ldq t3, 0(a1) # ref left
ldq t4, 8(a1) # ref right
addq a1, a3, a1 # pix1
addq a2, a3, a2 # pix2
/* load line 1 */
ldq_u t5, 0(a2) # left_u
ldq_u t6, 8(a2) # mid
ldq_u t7, 16(a2) # right_u
ldq t8, 0(a1) # ref left
ldq t9, 8(a1) # ref right
addq a1, a3, a1 # pix1
addq a2, a3, a2 # pix2
/* calc line 0 */
extql t0, a2, t0 # left lo
extqh t1, a2, ta # left hi
extql t1, a2, tb # right lo
or t0, ta, t0 # left
extqh t2, a2, t2 # right hi
perr t3, t0, tc # error left
or t2, tb, t2 # right
perr t4, t2, td # error right
addq v0, tc, v0 # add error left
addq v0, td, v0 # add error left
/* calc line 1 */
extql t5, a2, t5 # left lo
extqh t6, a2, ta # left hi
extql t6, a2, tb # right lo
or t5, ta, t5 # left
extqh t7, a2, t7 # right hi
perr t8, t5, tc # error left
or t7, tb, t7 # right
perr t9, t7, td # error right
addq v0, tc, v0 # add error left
addq v0, td, v0 # add error left
/* loop */
subq a4, 2, a4 # h -= 2
bne a4, $unaligned
ret
.align 4
$aligned:
/* load line 0 */
ldq t0, 0(a2) # left
ldq t1, 8(a2) # right
addq a2, a3, a2 # pix2
ldq t2, 0(a1) # ref left
ldq t3, 8(a1) # ref right
addq a1, a3, a1 # pix1
/* load line 1 */
ldq t4, 0(a2) # left
ldq t5, 8(a2) # right
addq a2, a3, a2 # pix2
ldq t6, 0(a1) # ref left
ldq t7, 8(a1) # ref right
addq a1, a3, a1 # pix1
/* load line 2 */
ldq t8, 0(a2) # left
ldq t9, 8(a2) # right
addq a2, a3, a2 # pix2
ldq ta, 0(a1) # ref left
ldq tb, 8(a1) # ref right
addq a1, a3, a1 # pix1
/* load line 3 */
ldq tc, 0(a2) # left
ldq td, 8(a2) # right
addq a2, a3, a2 # pix2
ldq te, 0(a1) # ref left
ldq a0, 8(a1) # ref right
/* calc line 0 */
perr t0, t2, t0 # error left
addq a1, a3, a1 # pix1
perr t1, t3, t1 # error right
addq v0, t0, v0 # add error left
/* calc line 1 */
perr t4, t6, t0 # error left
addq v0, t1, v0 # add error right
perr t5, t7, t1 # error right
addq v0, t0, v0 # add error left
/* calc line 2 */
perr t8, ta, t0 # error left
addq v0, t1, v0 # add error right
perr t9, tb, t1 # error right
addq v0, t0, v0 # add error left
/* calc line 3 */
perr tc, te, t0 # error left
addq v0, t1, v0 # add error right
perr td, a0, t1 # error right
addq v0, t0, v0 # add error left
addq v0, t1, v0 # add error right
/* loop */
subq a4, 4, a4 # h -= 4
bne a4, $aligned
ret
.end pix_abs16x16_mvi_asm

View File

@@ -0,0 +1,110 @@
/*
* Alpha optimized DSP utils
* Copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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 "libavutil/attributes.h"
#include "libavcodec/mpegvideo.h"
#include "asm.h"
static void dct_unquantize_h263_axp(int16_t *block, int n_coeffs,
uint64_t qscale, uint64_t qadd)
{
uint64_t qmul = qscale << 1;
uint64_t correction = WORD_VEC(qmul * 255 >> 8);
int i;
qadd = WORD_VEC(qadd);
for(i = 0; i <= n_coeffs; block += 4, i += 4) {
uint64_t levels, negmask, zeros, add, sub;
levels = ldq(block);
if (levels == 0)
continue;
#ifdef __alpha_max__
/* I don't think the speed difference justifies runtime
detection. */
negmask = maxsw4(levels, -1); /* negative -> ffff (-1) */
negmask = minsw4(negmask, 0); /* positive -> 0000 (0) */
#else
negmask = cmpbge(WORD_VEC(0x7fff), levels);
negmask &= (negmask >> 1) | (1 << 7);
negmask = zap(-1, negmask);
#endif
zeros = cmpbge(0, levels);
zeros &= zeros >> 1;
/* zeros |= zeros << 1 is not needed since qadd <= 255, so
zapping the lower byte suffices. */
levels *= qmul;
levels -= correction & (negmask << 16);
add = qadd & ~negmask;
sub = qadd & negmask;
/* Set qadd to 0 for levels == 0. */
add = zap(add, zeros);
levels += add;
levels -= sub;
stq(levels, block);
}
}
static void dct_unquantize_h263_intra_axp(MpegEncContext *s, int16_t *block,
int n, int qscale)
{
int n_coeffs;
uint64_t qadd;
int16_t block0 = block[0];
if (!s->h263_aic) {
if (n < 4)
block0 *= s->y_dc_scale;
else
block0 *= s->c_dc_scale;
qadd = (qscale - 1) | 1;
} else {
qadd = 0;
}
if(s->ac_pred)
n_coeffs = 63;
else
n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]];
dct_unquantize_h263_axp(block, n_coeffs, qscale, qadd);
block[0] = block0;
}
static void dct_unquantize_h263_inter_axp(MpegEncContext *s, int16_t *block,
int n, int qscale)
{
int n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]];
dct_unquantize_h263_axp(block, n_coeffs, qscale, (qscale - 1) | 1);
}
av_cold void ff_MPV_common_init_axp(MpegEncContext *s)
{
s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_axp;
s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_axp;
}

View File

@@ -0,0 +1,77 @@
/*
* Alpha optimized DSP utils
* copyright (c) 2002 Falk Hueffner <falk@debian.org>
*
* 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
*/
/* Some BSDs don't seem to have regdef.h... sigh */
#ifndef AVCODEC_ALPHA_REGDEF_H
#define AVCODEC_ALPHA_REGDEF_H
#define v0 $0 /* function return value */
#define t0 $1 /* temporary registers (caller-saved) */
#define t1 $2
#define t2 $3
#define t3 $4
#define t4 $5
#define t5 $6
#define t6 $7
#define t7 $8
#define s0 $9 /* saved-registers (callee-saved registers) */
#define s1 $10
#define s2 $11
#define s3 $12
#define s4 $13
#define s5 $14
#define s6 $15
#define fp s6 /* frame-pointer (s6 in frame-less procedures) */
#define a0 $16 /* argument registers (caller-saved) */
#define a1 $17
#define a2 $18
#define a3 $19
#define a4 $20
#define a5 $21
#define t8 $22 /* more temps (caller-saved) */
#define t9 $23
#define t10 $24
#define t11 $25
#define ra $26 /* return address register */
#define t12 $27
#define pv t12 /* procedure-variable register */
#define AT $at /* assembler temporary */
#define gp $29 /* global pointer */
#define sp $30 /* stack pointer */
#define zero $31 /* reads as zero, writes are noops */
/* Some nicer register names. */
#define ta t10
#define tb t11
#define tc t12
#define td AT
/* Danger: these overlap with the argument list and the return value */
#define te a5
#define tf a4
#define tg a3
#define th v0
#endif /* AVCODEC_ALPHA_REGDEF_H */

View File

@@ -0,0 +1,303 @@
/*
* Simple IDCT (Alpha optimized)
*
* Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
*
* based upon some outcommented C code from mpeg2dec (idct_mmx.c
* written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>)
*
* Alpha optimizations by Måns Rullgård <mans@mansr.com>
* and Falk Hueffner <falk@debian.org>
*
* 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 "dsputil_alpha.h"
#include "asm.h"
// cos(i * M_PI / 16) * sqrt(2) * (1 << 14)
// W4 is actually exactly 16384, but using 16383 works around
// accumulating rounding errors for some encoders
#define W1 22725
#define W2 21407
#define W3 19266
#define W4 16383
#define W5 12873
#define W6 8867
#define W7 4520
#define ROW_SHIFT 11
#define COL_SHIFT 20
/* 0: all entries 0, 1: only first entry nonzero, 2: otherwise */
static inline int idct_row(int16_t *row)
{
int a0, a1, a2, a3, b0, b1, b2, b3, t;
uint64_t l, r, t2;
l = ldq(row);
r = ldq(row + 4);
if (l == 0 && r == 0)
return 0;
a0 = W4 * sextw(l) + (1 << (ROW_SHIFT - 1));
if (((l & ~0xffffUL) | r) == 0) {
a0 >>= ROW_SHIFT;
t2 = (uint16_t) a0;
t2 |= t2 << 16;
t2 |= t2 << 32;
stq(t2, row);
stq(t2, row + 4);
return 1;
}
a1 = a0;
a2 = a0;
a3 = a0;
t = extwl(l, 4); /* row[2] */
if (t != 0) {
t = sextw(t);
a0 += W2 * t;
a1 += W6 * t;
a2 -= W6 * t;
a3 -= W2 * t;
}
t = extwl(r, 0); /* row[4] */
if (t != 0) {
t = sextw(t);
a0 += W4 * t;
a1 -= W4 * t;
a2 -= W4 * t;
a3 += W4 * t;
}
t = extwl(r, 4); /* row[6] */
if (t != 0) {
t = sextw(t);
a0 += W6 * t;
a1 -= W2 * t;
a2 += W2 * t;
a3 -= W6 * t;
}
t = extwl(l, 2); /* row[1] */
if (t != 0) {
t = sextw(t);
b0 = W1 * t;
b1 = W3 * t;
b2 = W5 * t;
b3 = W7 * t;
} else {
b0 = 0;
b1 = 0;
b2 = 0;
b3 = 0;
}
t = extwl(l, 6); /* row[3] */
if (t) {
t = sextw(t);
b0 += W3 * t;
b1 -= W7 * t;
b2 -= W1 * t;
b3 -= W5 * t;
}
t = extwl(r, 2); /* row[5] */
if (t) {
t = sextw(t);
b0 += W5 * t;
b1 -= W1 * t;
b2 += W7 * t;
b3 += W3 * t;
}
t = extwl(r, 6); /* row[7] */
if (t) {
t = sextw(t);
b0 += W7 * t;
b1 -= W5 * t;
b2 += W3 * t;
b3 -= W1 * t;
}
row[0] = (a0 + b0) >> ROW_SHIFT;
row[1] = (a1 + b1) >> ROW_SHIFT;
row[2] = (a2 + b2) >> ROW_SHIFT;
row[3] = (a3 + b3) >> ROW_SHIFT;
row[4] = (a3 - b3) >> ROW_SHIFT;
row[5] = (a2 - b2) >> ROW_SHIFT;
row[6] = (a1 - b1) >> ROW_SHIFT;
row[7] = (a0 - b0) >> ROW_SHIFT;
return 2;
}
static inline void idct_col(int16_t *col)
{
int a0, a1, a2, a3, b0, b1, b2, b3;
col[0] += (1 << (COL_SHIFT - 1)) / W4;
a0 = W4 * col[8 * 0];
a1 = W4 * col[8 * 0];
a2 = W4 * col[8 * 0];
a3 = W4 * col[8 * 0];
if (col[8 * 2]) {
a0 += W2 * col[8 * 2];
a1 += W6 * col[8 * 2];
a2 -= W6 * col[8 * 2];
a3 -= W2 * col[8 * 2];
}
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 * 6]) {
a0 += W6 * col[8 * 6];
a1 -= W2 * col[8 * 6];
a2 += W2 * col[8 * 6];
a3 -= W6 * col[8 * 6];
}
if (col[8 * 1]) {
b0 = W1 * col[8 * 1];
b1 = W3 * col[8 * 1];
b2 = W5 * col[8 * 1];
b3 = W7 * col[8 * 1];
} else {
b0 = 0;
b1 = 0;
b2 = 0;
b3 = 0;
}
if (col[8 * 3]) {
b0 += W3 * col[8 * 3];
b1 -= W7 * col[8 * 3];
b2 -= W1 * col[8 * 3];
b3 -= W5 * col[8 * 3];
}
if (col[8 * 5]) {
b0 += W5 * col[8 * 5];
b1 -= W1 * col[8 * 5];
b2 += W7 * col[8 * 5];
b3 += W3 * col[8 * 5];
}
if (col[8 * 7]) {
b0 += W7 * col[8 * 7];
b1 -= W5 * col[8 * 7];
b2 += W3 * col[8 * 7];
b3 -= W1 * col[8 * 7];
}
col[8 * 0] = (a0 + b0) >> COL_SHIFT;
col[8 * 7] = (a0 - b0) >> COL_SHIFT;
col[8 * 1] = (a1 + b1) >> COL_SHIFT;
col[8 * 6] = (a1 - b1) >> COL_SHIFT;
col[8 * 2] = (a2 + b2) >> COL_SHIFT;
col[8 * 5] = (a2 - b2) >> COL_SHIFT;
col[8 * 3] = (a3 + b3) >> COL_SHIFT;
col[8 * 4] = (a3 - b3) >> COL_SHIFT;
}
/* If all rows but the first one are zero after row transformation,
all rows will be identical after column transformation. */
static inline void idct_col2(int16_t *col)
{
int i;
uint64_t l, r;
for (i = 0; i < 8; ++i) {
int a0 = col[i] + (1 << (COL_SHIFT - 1)) / W4;
a0 *= W4;
col[i] = a0 >> COL_SHIFT;
}
l = ldq(col + 0 * 4); r = ldq(col + 1 * 4);
stq(l, col + 2 * 4); stq(r, col + 3 * 4);
stq(l, col + 4 * 4); stq(r, col + 5 * 4);
stq(l, col + 6 * 4); stq(r, col + 7 * 4);
stq(l, col + 8 * 4); stq(r, col + 9 * 4);
stq(l, col + 10 * 4); stq(r, col + 11 * 4);
stq(l, col + 12 * 4); stq(r, col + 13 * 4);
stq(l, col + 14 * 4); stq(r, col + 15 * 4);
}
void ff_simple_idct_axp(int16_t *block)
{
int i;
int rowsZero = 1; /* all rows except row 0 zero */
int rowsConstant = 1; /* all rows consist of a constant value */
for (i = 0; i < 8; i++) {
int sparseness = idct_row(block + 8 * i);
if (i > 0 && sparseness > 0)
rowsZero = 0;
if (sparseness == 2)
rowsConstant = 0;
}
if (rowsZero) {
idct_col2(block);
} else if (rowsConstant) {
idct_col(block);
for (i = 0; i < 8; i += 2) {
uint64_t v = (uint16_t) block[0];
uint64_t w = (uint16_t) block[8];
v |= v << 16;
w |= w << 16;
v |= v << 32;
w |= w << 32;
stq(v, block + 0 * 4);
stq(v, block + 1 * 4);
stq(w, block + 2 * 4);
stq(w, block + 3 * 4);
block += 4 * 4;
}
} else {
for (i = 0; i < 8; i++)
idct_col(block + i);
}
}
void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block)
{
ff_simple_idct_axp(block);
put_pixels_clamped_axp_p(block, dest, line_size);
}
void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block)
{
ff_simple_idct_axp(block);
add_pixels_clamped_axp_p(block, dest, line_size);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
/*
* Shared functions between AMR codecs
*
* Copyright (c) 2010 Marcelo Galvao Povoa
*
* 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 AVCODEC_AMR_H
#define AVCODEC_AMR_H
#include <string.h>
#include "avcodec.h"
#ifdef AMR_USE_16BIT_TABLES
#define R_TABLE_TYPE uint16_t
#else
#define R_TABLE_TYPE uint8_t
#endif
/**
* Fill the frame structure variables from bitstream by parsing the
* given reordering table that uses the following format:
*
* Each field (16 bits) in the AMR Frame is stored as:
* - one byte for the number of bits in the field
* - one byte for the field index
* - then, one byte for each bit of the field (from most-significant to least)
* of the position of that bit in the AMR frame.
*
* @param out pointer to the frame struct
* @param size the size in bytes of the frame struct
* @param data input bitstream after the frame header
* @param ord_table the reordering table as above
*/
static inline void ff_amr_bit_reorder(uint16_t *out, int size,
const uint8_t *data,
const R_TABLE_TYPE *ord_table)
{
int field_size;
memset(out, 0, size);
while ((field_size = *ord_table++)) {
int field = 0;
int field_offset = *ord_table++;
while (field_size--) {
int bit = *ord_table++;
field <<= 1;
field |= data[bit >> 3] >> (bit & 7) & 1;
}
out[field_offset >> 1] = field;
}
}
#endif /* AVCODEC_AMR_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
/*
* Deluxe Paint Animation decoder
* Copyright (c) 2009 Peter Ross
*
* 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
* Deluxe Paint Animation decoder
*/
#include "avcodec.h"
#include "bytestream.h"
#include "internal.h"
typedef struct AnmContext {
AVFrame *frame;
int palette[AVPALETTE_COUNT];
GetByteContext gb;
int x; ///< x coordinate position
} AnmContext;
static av_cold int decode_init(AVCodecContext *avctx)
{
AnmContext *s = avctx->priv_data;
int i;
avctx->pix_fmt = AV_PIX_FMT_PAL8;
s->frame = av_frame_alloc();
if (!s->frame)
return AVERROR(ENOMEM);
bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256)
return AVERROR_INVALIDDATA;
bytestream2_skipu(&s->gb, 16 * 8);
for (i = 0; i < 256; i++)
s->palette[i] = bytestream2_get_le32u(&s->gb);
return 0;
}
/**
* Perform decode operation
* @param dst pointer to destination image buffer
* @param dst_end pointer to end of destination image buffer
* @param gb GetByteContext (optional, see below)
* @param pixel Fill color (optional, see below)
* @param count Pixel count
* @param x Pointer to x-axis counter
* @param width Image width
* @param linesize Destination image buffer linesize
* @return non-zero if destination buffer is exhausted
*
* a copy operation is achieved when 'gb' is set
* a fill operation is achieved when 'gb' is null and pixel is >= 0
* a skip operation is achieved when 'gb' is null and pixel is < 0
*/
static inline int op(uint8_t **dst, const uint8_t *dst_end,
GetByteContext *gb,
int pixel, int count,
int *x, int width, int linesize)
{
int remaining = width - *x;
while(count > 0) {
int striplen = FFMIN(count, remaining);
if (gb) {
if (bytestream2_get_bytes_left(gb) < striplen)
goto exhausted;
bytestream2_get_bufferu(gb, *dst, striplen);
} else if (pixel >= 0)
memset(*dst, pixel, striplen);
*dst += striplen;
remaining -= striplen;
count -= striplen;
if (remaining <= 0) {
*dst += linesize - width;
remaining = width;
}
if (linesize > 0) {
if (*dst >= dst_end) goto exhausted;
} else {
if (*dst <= dst_end) goto exhausted;
}
}
*x = width - remaining;
return 0;
exhausted:
*x = width - remaining;
return 1;
}
static int decode_frame(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
{
AnmContext *s = avctx->priv_data;
const int buf_size = avpkt->size;
uint8_t *dst, *dst_end;
int count, ret;
if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
return ret;
dst = s->frame->data[0];
dst_end = s->frame->data[0] + s->frame->linesize[0]*avctx->height;
bytestream2_init(&s->gb, avpkt->data, buf_size);
if (bytestream2_get_byte(&s->gb) != 0x42) {
avpriv_request_sample(avctx, "Unknown record type");
return AVERROR_INVALIDDATA;
}
if (bytestream2_get_byte(&s->gb)) {
avpriv_request_sample(avctx, "Padding bytes");
return AVERROR_PATCHWELCOME;
}
bytestream2_skip(&s->gb, 2);
s->x = 0;
do {
/* if statements are ordered by probability */
#define OP(gb, pixel, count) \
op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0])
int type = bytestream2_get_byte(&s->gb);
count = type & 0x7F;
type >>= 7;
if (count) {
if (OP(type ? NULL : &s->gb, -1, count)) break;
} else if (!type) {
int pixel;
count = bytestream2_get_byte(&s->gb); /* count==0 gives nop */
pixel = bytestream2_get_byte(&s->gb);
if (OP(NULL, pixel, count)) break;
} else {
int pixel;
type = bytestream2_get_le16(&s->gb);
count = type & 0x3FFF;
type >>= 14;
if (!count) {
if (type == 0)
break; // stop
if (type == 2) {
avpriv_request_sample(avctx, "Unknown opcode");
return AVERROR_PATCHWELCOME;
}
continue;
}
pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1;
if (type == 1) count += 0x4000;
if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break;
}
} while (bytestream2_get_bytes_left(&s->gb) > 0);
memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
*got_frame = 1;
if ((ret = av_frame_ref(data, s->frame)) < 0)
return ret;
return buf_size;
}
static av_cold int decode_end(AVCodecContext *avctx)
{
AnmContext *s = avctx->priv_data;
av_frame_free(&s->frame);
return 0;
}
AVCodec ff_anm_decoder = {
.name = "anm",
.long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_ANM,
.priv_data_size = sizeof(AnmContext),
.init = decode_init,
.close = decode_end,
.decode = decode_frame,
.capabilities = CODEC_CAP_DR1,
};

View File

@@ -0,0 +1,477 @@
/*
* ASCII/ANSI art decoder
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
*
* 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
* ASCII/ANSI art decoder
*/
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavutil/lfg.h"
#include "libavutil/xga_font_data.h"
#include "avcodec.h"
#include "cga_data.h"
#include "internal.h"
#define ATTR_BOLD 0x01 /**< Bold/Bright-foreground (mode 1) */
#define ATTR_FAINT 0x02 /**< Faint (mode 2) */
#define ATTR_UNDERLINE 0x08 /**< Underline (mode 4) */
#define ATTR_BLINK 0x10 /**< Blink/Bright-background (mode 5) */
#define ATTR_REVERSE 0x40 /**< Reverse (mode 7) */
#define ATTR_CONCEALED 0x80 /**< Concealed (mode 8) */
#define DEFAULT_FG_COLOR 7 /**< CGA color index */
#define DEFAULT_BG_COLOR 0
#define DEFAULT_SCREEN_MODE 3 /**< 80x25 */
#define FONT_WIDTH 8 /**< Font width */
/** map ansi color index to cga palette index */
static const uint8_t ansi_to_cga[16] = {
0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15
};
typedef struct {
AVFrame *frame;
int x; /**< x cursor position (pixels) */
int y; /**< y cursor position (pixels) */
int sx; /**< saved x cursor position (pixels) */
int sy; /**< saved y cursor position (pixels) */
const uint8_t* font; /**< font */
int font_height; /**< font height */
int attributes; /**< attribute flags */
int fg; /**< foreground color */
int bg; /**< background color */
int first_frame;
/* ansi parser state machine */
enum {
STATE_NORMAL = 0,
STATE_ESCAPE,
STATE_CODE,
STATE_MUSIC_PREAMBLE
} state;
#define MAX_NB_ARGS 4
int args[MAX_NB_ARGS];
int nb_args; /**< number of arguments (may exceed MAX_NB_ARGS) */
} AnsiContext;
static av_cold int decode_init(AVCodecContext *avctx)
{
AnsiContext *s = avctx->priv_data;
avctx->pix_fmt = AV_PIX_FMT_PAL8;
s->frame = av_frame_alloc();
if (!s->frame)
return AVERROR(ENOMEM);
/* defaults */
s->font = avpriv_vga16_font;
s->font_height = 16;
s->fg = DEFAULT_FG_COLOR;
s->bg = DEFAULT_BG_COLOR;
if (!avctx->width || !avctx->height)
avcodec_set_dimensions(avctx, 80<<3, 25<<4);
return 0;
}
static void set_palette(uint32_t *pal)
{
int r, g, b;
memcpy(pal, ff_cga_palette, 16 * 4);
pal += 16;
#define COLOR(x) ((x) * 40 + 55)
for (r = 0; r < 6; r++)
for (g = 0; g < 6; g++)
for (b = 0; b < 6; b++)
*pal++ = 0xFF000000 | (COLOR(r) << 16) | (COLOR(g) << 8) | COLOR(b);
#define GRAY(x) ((x) * 10 + 8)
for (g = 0; g < 24; g++)
*pal++ = 0xFF000000 | (GRAY(g) << 16) | (GRAY(g) << 8) | GRAY(g);
}
static void hscroll(AVCodecContext *avctx)
{
AnsiContext *s = avctx->priv_data;
int i;
if (s->y <= avctx->height - 2*s->font_height) {
s->y += s->font_height;
return;
}
i = 0;
for (; i < avctx->height - s->font_height; i++)
memcpy(s->frame->data[0] + i * s->frame->linesize[0],
s->frame->data[0] + (i + s->font_height) * s->frame->linesize[0],
avctx->width);
for (; i < avctx->height; i++)
memset(s->frame->data[0] + i * s->frame->linesize[0],
DEFAULT_BG_COLOR, avctx->width);
}
static void erase_line(AVCodecContext * avctx, int xoffset, int xlength)
{
AnsiContext *s = avctx->priv_data;
int i;
for (i = 0; i < s->font_height; i++)
memset(s->frame->data[0] + (s->y + i)*s->frame->linesize[0] + xoffset,
DEFAULT_BG_COLOR, xlength);
}
static void erase_screen(AVCodecContext *avctx)
{
AnsiContext *s = avctx->priv_data;
int i;
for (i = 0; i < avctx->height; i++)
memset(s->frame->data[0] + i * s->frame->linesize[0], DEFAULT_BG_COLOR, avctx->width);
s->x = s->y = 0;
}
/**
* Draw character to screen
*/
static void draw_char(AVCodecContext *avctx, int c)
{
AnsiContext *s = avctx->priv_data;
int fg = s->fg;
int bg = s->bg;
if ((s->attributes & ATTR_BOLD))
fg += 8;
if ((s->attributes & ATTR_BLINK))
bg += 8;
if ((s->attributes & ATTR_REVERSE))
FFSWAP(int, fg, bg);
if ((s->attributes & ATTR_CONCEALED))
fg = bg;
ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x,
s->frame->linesize[0], s->font, s->font_height, c, fg, bg);
s->x += FONT_WIDTH;
if (s->x > avctx->width - FONT_WIDTH) {
s->x = 0;
hscroll(avctx);
}
}
/**
* Execute ANSI escape code
* @return 0 on success, negative on error
*/
static int execute_code(AVCodecContext * avctx, int c)
{
AnsiContext *s = avctx->priv_data;
int ret, i, width, height;
switch(c) {
case 'A': //Cursor Up
s->y = FFMAX(s->y - (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), 0);
break;
case 'B': //Cursor Down
s->y = FFMIN(s->y + (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), avctx->height - s->font_height);
break;
case 'C': //Cursor Right
s->x = FFMIN(s->x + (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), avctx->width - FONT_WIDTH);
break;
case 'D': //Cursor Left
s->x = FFMAX(s->x - (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), 0);
break;
case 'H': //Cursor Position
case 'f': //Horizontal and Vertical Position
s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0;
s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH, 0, avctx->width - FONT_WIDTH) : 0;
break;
case 'h': //set creen mode
case 'l': //reset screen mode
if (s->nb_args < 2)
s->args[0] = DEFAULT_SCREEN_MODE;
width = avctx->width;
height = avctx->height;
switch(s->args[0]) {
case 0: case 1: case 4: case 5: case 13: case 19: //320x200 (25 rows)
s->font = avpriv_cga_font;
s->font_height = 8;
width = 40<<3;
height = 25<<3;
break;
case 2: case 3: //640x400 (25 rows)
s->font = avpriv_vga16_font;
s->font_height = 16;
width = 80<<3;
height = 25<<4;
break;
case 6: case 14: //640x200 (25 rows)
s->font = avpriv_cga_font;
s->font_height = 8;
width = 80<<3;
height = 25<<3;
break;
case 7: //set line wrapping
break;
case 15: case 16: //640x350 (43 rows)
s->font = avpriv_cga_font;
s->font_height = 8;
width = 80<<3;
height = 43<<3;
break;
case 17: case 18: //640x480 (60 rows)
s->font = avpriv_cga_font;
s->font_height = 8;
width = 80<<3;
height = 60<<4;
break;
default:
avpriv_request_sample(avctx, "Unsupported screen mode");
}
s->x = av_clip(s->x, 0, width - FONT_WIDTH);
s->y = av_clip(s->y, 0, height - s->font_height);
if (width != avctx->width || height != avctx->height) {
av_frame_unref(s->frame);
avcodec_set_dimensions(avctx, width, height);
if ((ret = ff_get_buffer(avctx, s->frame,
AV_GET_BUFFER_FLAG_REF)) < 0)
return ret;
s->frame->pict_type = AV_PICTURE_TYPE_I;
s->frame->palette_has_changed = 1;
set_palette((uint32_t *)s->frame->data[1]);
erase_screen(avctx);
} else if (c == 'l') {
erase_screen(avctx);
}
break;
case 'J': //Erase in Page
switch (s->args[0]) {
case 0:
erase_line(avctx, s->x, avctx->width - s->x);
if (s->y < avctx->height - s->font_height)
memset(s->frame->data[0] + (s->y + s->font_height)*s->frame->linesize[0],
DEFAULT_BG_COLOR, (avctx->height - s->y - s->font_height)*s->frame->linesize[0]);
break;
case 1:
erase_line(avctx, 0, s->x);
if (s->y > 0)
memset(s->frame->data[0], DEFAULT_BG_COLOR, s->y * s->frame->linesize[0]);
break;
case 2:
erase_screen(avctx);
}
break;
case 'K': //Erase in Line
switch(s->args[0]) {
case 0:
erase_line(avctx, s->x, avctx->width - s->x);
break;
case 1:
erase_line(avctx, 0, s->x);
break;
case 2:
erase_line(avctx, 0, avctx->width);
}
break;
case 'm': //Select Graphics Rendition
if (s->nb_args == 0) {
s->nb_args = 1;
s->args[0] = 0;
}
for (i = 0; i < FFMIN(s->nb_args, MAX_NB_ARGS); i++) {
int m = s->args[i];
if (m == 0) {
s->attributes = 0;
s->fg = DEFAULT_FG_COLOR;
s->bg = DEFAULT_BG_COLOR;
} else if (m == 1 || m == 2 || m == 4 || m == 5 || m == 7 || m == 8) {
s->attributes |= 1 << (m - 1);
} else if (m >= 30 && m <= 37) {
s->fg = ansi_to_cga[m - 30];
} else if (m == 38 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) {
int index = s->args[i + 2];
s->fg = index < 16 ? ansi_to_cga[index] : index;
i += 2;
} else if (m == 39) {
s->fg = ansi_to_cga[DEFAULT_FG_COLOR];
} else if (m >= 40 && m <= 47) {
s->bg = ansi_to_cga[m - 40];
} else if (m == 48 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) {
int index = s->args[i + 2];
s->bg = index < 16 ? ansi_to_cga[index] : index;
i += 2;
} else if (m == 49) {
s->fg = ansi_to_cga[DEFAULT_BG_COLOR];
} else {
avpriv_request_sample(avctx, "Unsupported rendition parameter");
}
}
break;
case 'n': //Device Status Report
case 'R': //report current line and column
/* ignore */
break;
case 's': //Save Cursor Position
s->sx = s->x;
s->sy = s->y;
break;
case 'u': //Restore Cursor Position
s->x = av_clip(s->sx, 0, avctx->width - FONT_WIDTH);
s->y = av_clip(s->sy, 0, avctx->height - s->font_height);
break;
default:
avpriv_request_sample(avctx, "Unknown escape code");
break;
}
s->x = av_clip(s->x, 0, avctx->width - FONT_WIDTH);
s->y = av_clip(s->y, 0, avctx->height - s->font_height);
return 0;
}
static int decode_frame(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
{
AnsiContext *s = avctx->priv_data;
uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
const uint8_t *buf_end = buf+buf_size;
int ret, i, count;
if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
return ret;
if (!avctx->frame_number) {
for (i=0; i<avctx->height; i++)
memset(s->frame->data[0]+ i*s->frame->linesize[0], 0, avctx->width);
memset(s->frame->data[1], 0, AVPALETTE_SIZE);
}
s->frame->pict_type = AV_PICTURE_TYPE_I;
s->frame->palette_has_changed = 1;
set_palette((uint32_t *)s->frame->data[1]);
if (!s->first_frame) {
erase_screen(avctx);
s->first_frame = 1;
}
while(buf < buf_end) {
switch(s->state) {
case STATE_NORMAL:
switch (buf[0]) {
case 0x00: //NUL
case 0x07: //BEL
case 0x1A: //SUB
/* ignore */
break;
case 0x08: //BS
s->x = FFMAX(s->x - 1, 0);
break;
case 0x09: //HT
i = s->x / FONT_WIDTH;
count = ((i + 8) & ~7) - i;
for (i = 0; i < count; i++)
draw_char(avctx, ' ');
break;
case 0x0A: //LF
hscroll(avctx);
case 0x0D: //CR
s->x = 0;
break;
case 0x0C: //FF
erase_screen(avctx);
break;
case 0x1B: //ESC
s->state = STATE_ESCAPE;
break;
default:
draw_char(avctx, buf[0]);
}
break;
case STATE_ESCAPE:
if (buf[0] == '[') {
s->state = STATE_CODE;
s->nb_args = 0;
s->args[0] = -1;
} else {
s->state = STATE_NORMAL;
draw_char(avctx, 0x1B);
continue;
}
break;
case STATE_CODE:
switch(buf[0]) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (s->nb_args < MAX_NB_ARGS)
s->args[s->nb_args] = FFMAX(s->args[s->nb_args], 0) * 10 + buf[0] - '0';
break;
case ';':
s->nb_args++;
if (s->nb_args < MAX_NB_ARGS)
s->args[s->nb_args] = 0;
break;
case 'M':
s->state = STATE_MUSIC_PREAMBLE;
break;
case '=': case '?':
/* ignore */
break;
default:
if (s->nb_args > MAX_NB_ARGS)
av_log(avctx, AV_LOG_WARNING, "args overflow (%i)\n", s->nb_args);
if (s->nb_args < MAX_NB_ARGS && s->args[s->nb_args] >= 0)
s->nb_args++;
if ((ret = execute_code(avctx, buf[0])) < 0)
return ret;
s->state = STATE_NORMAL;
}
break;
case STATE_MUSIC_PREAMBLE:
if (buf[0] == 0x0E || buf[0] == 0x1B)
s->state = STATE_NORMAL;
/* ignore music data */
break;
}
buf++;
}
*got_frame = 1;
if ((ret = av_frame_ref(data, s->frame)) < 0)
return ret;
return buf_size;
}
static av_cold int decode_close(AVCodecContext *avctx)
{
AnsiContext *s = avctx->priv_data;
av_frame_free(&s->frame);
return 0;
}
AVCodec ff_ansi_decoder = {
.name = "ansi",
.long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_ANSI,
.priv_data_size = sizeof(AnsiContext),
.init = decode_init,
.close = decode_close,
.decode = decode_frame,
.capabilities = CODEC_CAP_DR1,
};

Some files were not shown because too many files have changed in this diff Show More