mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
20f9727018
Up until now, codec.h contains both public and private parts of AVCodec. This exposes the internals of AVCodec to users and leads them into the temptation of actually using them and forces us to forward-declare structures and types that users can't use at all. This commit changes this by adding a new structure FFCodec to codec_internal.h that extends AVCodec, i.e. contains the public AVCodec as first member; the private fields of AVCodec are moved to this structure, leaving codec.h clean. Reviewed-by: Anton Khirnov <anton@khirnov.net> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
437 lines
13 KiB
C
437 lines
13 KiB
C
/*
|
|
* TTA (The Lossless True Audio) decoder
|
|
* Copyright (c) 2006 Alex Beregszaszi
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* TTA (The Lossless True Audio) decoder
|
|
* @see http://www.true-audio.com/
|
|
* @see http://tta.corecodec.org/
|
|
* @author Alex Beregszaszi
|
|
*/
|
|
|
|
#include <limits.h>
|
|
|
|
#include "libavutil/channel_layout.h"
|
|
#include "libavutil/crc.h"
|
|
#include "libavutil/intreadwrite.h"
|
|
#include "libavutil/opt.h"
|
|
|
|
#define BITSTREAM_READER_LE
|
|
#include "ttadata.h"
|
|
#include "ttadsp.h"
|
|
#include "avcodec.h"
|
|
#include "codec_internal.h"
|
|
#include "get_bits.h"
|
|
#include "thread.h"
|
|
#include "unary.h"
|
|
|
|
#define FORMAT_SIMPLE 1
|
|
#define FORMAT_ENCRYPTED 2
|
|
|
|
typedef struct TTAContext {
|
|
AVClass *class;
|
|
AVCodecContext *avctx;
|
|
const AVCRC *crc_table;
|
|
|
|
int format, channels, bps;
|
|
unsigned data_length;
|
|
int frame_length, last_frame_length;
|
|
|
|
int32_t *decode_buffer;
|
|
|
|
uint8_t crc_pass[8];
|
|
uint8_t *pass;
|
|
TTAChannel *ch_ctx;
|
|
TTADSPContext dsp;
|
|
} TTAContext;
|
|
|
|
static const int64_t tta_channel_layouts[7] = {
|
|
AV_CH_LAYOUT_STEREO,
|
|
AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY,
|
|
AV_CH_LAYOUT_QUAD,
|
|
0,
|
|
AV_CH_LAYOUT_5POINT1_BACK,
|
|
AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER,
|
|
AV_CH_LAYOUT_7POINT1_WIDE
|
|
};
|
|
|
|
static int tta_check_crc(TTAContext *s, const uint8_t *buf, int buf_size)
|
|
{
|
|
uint32_t crc, CRC;
|
|
|
|
CRC = AV_RL32(buf + buf_size);
|
|
crc = av_crc(s->crc_table, 0xFFFFFFFFU, buf, buf_size);
|
|
if (CRC != (crc ^ 0xFFFFFFFFU)) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint64_t tta_check_crc64(uint8_t *pass)
|
|
{
|
|
uint64_t crc = UINT64_MAX, poly = 0x42F0E1EBA9EA3693U;
|
|
uint8_t *end = pass + strlen(pass);
|
|
int i;
|
|
|
|
while (pass < end) {
|
|
crc ^= (uint64_t)*pass++ << 56;
|
|
for (i = 0; i < 8; i++)
|
|
crc = (crc << 1) ^ (poly & (((int64_t) crc) >> 63));
|
|
}
|
|
|
|
return crc ^ UINT64_MAX;
|
|
}
|
|
|
|
static int allocate_buffers(AVCodecContext *avctx)
|
|
{
|
|
TTAContext *s = avctx->priv_data;
|
|
|
|
if (s->bps < 3) {
|
|
s->decode_buffer = av_calloc(s->frame_length,
|
|
sizeof(*s->decode_buffer) * s->channels);
|
|
if (!s->decode_buffer)
|
|
return AVERROR(ENOMEM);
|
|
} else
|
|
s->decode_buffer = NULL;
|
|
s->ch_ctx = av_malloc_array(avctx->ch_layout.nb_channels, sizeof(*s->ch_ctx));
|
|
if (!s->ch_ctx)
|
|
return AVERROR(ENOMEM);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static av_cold int tta_decode_init(AVCodecContext * avctx)
|
|
{
|
|
TTAContext *s = avctx->priv_data;
|
|
GetBitContext gb;
|
|
int total_frames;
|
|
int ret;
|
|
|
|
s->avctx = avctx;
|
|
|
|
// 22 bytes for a TTA1 header
|
|
if (avctx->extradata_size < 22)
|
|
return AVERROR_INVALIDDATA;
|
|
|
|
s->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE);
|
|
ret = init_get_bits8(&gb, avctx->extradata, avctx->extradata_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (show_bits_long(&gb, 32) == AV_RL32("TTA1")) {
|
|
/* signature */
|
|
skip_bits_long(&gb, 32);
|
|
|
|
s->format = get_bits(&gb, 16);
|
|
if (s->format > 2) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid format\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
if (s->format == FORMAT_ENCRYPTED) {
|
|
if (!s->pass) {
|
|
av_log(avctx, AV_LOG_ERROR, "Missing password for encrypted stream. Please use the -password option\n");
|
|
return AVERROR(EINVAL);
|
|
}
|
|
AV_WL64(s->crc_pass, tta_check_crc64(s->pass));
|
|
}
|
|
|
|
s->channels = get_bits(&gb, 16);
|
|
|
|
av_channel_layout_uninit(&avctx->ch_layout);
|
|
if (s->channels > 1 && s->channels < 9) {
|
|
av_channel_layout_from_mask(&avctx->ch_layout, tta_channel_layouts[s->channels-2]);
|
|
} else {
|
|
avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
|
|
avctx->ch_layout.nb_channels = s->channels;
|
|
}
|
|
|
|
avctx->bits_per_raw_sample = get_bits(&gb, 16);
|
|
s->bps = (avctx->bits_per_raw_sample + 7) / 8;
|
|
avctx->sample_rate = get_bits_long(&gb, 32);
|
|
s->data_length = get_bits_long(&gb, 32);
|
|
skip_bits_long(&gb, 32); // CRC32 of header
|
|
|
|
if (s->channels == 0 || s->channels > 16) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
|
|
return AVERROR_INVALIDDATA;
|
|
} else if (avctx->sample_rate == 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid samplerate\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
switch(s->bps) {
|
|
case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8; break;
|
|
case 2:
|
|
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
|
break;
|
|
case 3:
|
|
avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
|
break;
|
|
//case 4: avctx->sample_fmt = AV_SAMPLE_FMT_S32; break;
|
|
default:
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid/unsupported sample format.\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
// prevent overflow
|
|
if (avctx->sample_rate > 0x7FFFFFu) {
|
|
av_log(avctx, AV_LOG_ERROR, "sample_rate too large\n");
|
|
return AVERROR(EINVAL);
|
|
}
|
|
s->frame_length = 256 * avctx->sample_rate / 245;
|
|
|
|
s->last_frame_length = s->data_length % s->frame_length;
|
|
total_frames = s->data_length / s->frame_length +
|
|
(s->last_frame_length ? 1 : 0);
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "format: %d chans: %d bps: %d rate: %d block: %d\n",
|
|
s->format, avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample, avctx->sample_rate,
|
|
avctx->block_align);
|
|
av_log(avctx, AV_LOG_DEBUG, "data_length: %d frame_length: %d last: %d total: %d\n",
|
|
s->data_length, s->frame_length, s->last_frame_length, total_frames);
|
|
|
|
if(s->frame_length >= UINT_MAX / (s->channels * sizeof(int32_t))){
|
|
av_log(avctx, AV_LOG_ERROR, "frame_length too large\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
} else {
|
|
av_log(avctx, AV_LOG_ERROR, "Wrong extradata present\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
ff_ttadsp_init(&s->dsp);
|
|
|
|
return allocate_buffers(avctx);
|
|
}
|
|
|
|
static int tta_decode_frame(AVCodecContext *avctx, void *data,
|
|
int *got_frame_ptr, AVPacket *avpkt)
|
|
{
|
|
AVFrame *frame = data;
|
|
const uint8_t *buf = avpkt->data;
|
|
int buf_size = avpkt->size;
|
|
TTAContext *s = avctx->priv_data;
|
|
GetBitContext gb;
|
|
int i, ret;
|
|
int cur_chan = 0, framelen = s->frame_length;
|
|
uint32_t *p;
|
|
|
|
if (avctx->err_recognition & AV_EF_CRCCHECK) {
|
|
if (buf_size < 4 ||
|
|
(tta_check_crc(s, buf, buf_size - 4) && avctx->err_recognition & AV_EF_EXPLODE))
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
|
|
return ret;
|
|
|
|
/* get output buffer */
|
|
frame->nb_samples = framelen;
|
|
if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0)
|
|
return ret;
|
|
|
|
// decode directly to output buffer for 24-bit sample format
|
|
if (s->bps == 3)
|
|
s->decode_buffer = (int32_t *)frame->data[0];
|
|
|
|
// init per channel states
|
|
for (i = 0; i < s->channels; i++) {
|
|
TTAFilter *filter = &s->ch_ctx[i].filter;
|
|
s->ch_ctx[i].predictor = 0;
|
|
ff_tta_filter_init(filter, ff_tta_filter_configs[s->bps-1]);
|
|
if (s->format == FORMAT_ENCRYPTED) {
|
|
int i;
|
|
for (i = 0; i < 8; i++)
|
|
filter->qm[i] = sign_extend(s->crc_pass[i], 8);
|
|
}
|
|
ff_tta_rice_init(&s->ch_ctx[i].rice, 10, 10);
|
|
}
|
|
|
|
i = 0;
|
|
for (p = s->decode_buffer; (int32_t*)p < s->decode_buffer + (framelen * s->channels); p++) {
|
|
int32_t *predictor = &s->ch_ctx[cur_chan].predictor;
|
|
TTAFilter *filter = &s->ch_ctx[cur_chan].filter;
|
|
TTARice *rice = &s->ch_ctx[cur_chan].rice;
|
|
uint32_t unary, depth, k;
|
|
int32_t value;
|
|
|
|
unary = get_unary(&gb, 0, get_bits_left(&gb));
|
|
|
|
if (unary == 0) {
|
|
depth = 0;
|
|
k = rice->k0;
|
|
} else {
|
|
depth = 1;
|
|
k = rice->k1;
|
|
unary--;
|
|
}
|
|
|
|
if (get_bits_left(&gb) < k) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
goto error;
|
|
}
|
|
|
|
if (k) {
|
|
if (k > MIN_CACHE_BITS || unary > INT32_MAX >> k) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
goto error;
|
|
}
|
|
value = (unary << k) + get_bits(&gb, k);
|
|
} else
|
|
value = unary;
|
|
|
|
// FIXME: copy paste from original
|
|
switch (depth) {
|
|
case 1:
|
|
rice->sum1 += value - (rice->sum1 >> 4);
|
|
if (rice->k1 > 0 && rice->sum1 < ff_tta_shift_16[rice->k1])
|
|
rice->k1--;
|
|
else if(rice->sum1 > ff_tta_shift_16[rice->k1 + 1])
|
|
rice->k1++;
|
|
value += ff_tta_shift_1[rice->k0];
|
|
default:
|
|
rice->sum0 += value - (rice->sum0 >> 4);
|
|
if (rice->k0 > 0 && rice->sum0 < ff_tta_shift_16[rice->k0])
|
|
rice->k0--;
|
|
else if(rice->sum0 > ff_tta_shift_16[rice->k0 + 1])
|
|
rice->k0++;
|
|
}
|
|
|
|
// extract coded value
|
|
*p = 1 + ((value >> 1) ^ ((value & 1) - 1));
|
|
|
|
// run hybrid filter
|
|
s->dsp.filter_process(filter->qm, filter->dx, filter->dl, &filter->error, p,
|
|
filter->shift, filter->round);
|
|
|
|
// fixed order prediction
|
|
#define PRED(x, k) (int32_t)((((uint64_t)(x) << (k)) - (x)) >> (k))
|
|
switch (s->bps) {
|
|
case 1: *p += PRED(*predictor, 4); break;
|
|
case 2:
|
|
case 3: *p += PRED(*predictor, 5); break;
|
|
case 4: *p += *predictor; break;
|
|
}
|
|
*predictor = *p;
|
|
|
|
// flip channels
|
|
if (cur_chan < (s->channels-1))
|
|
cur_chan++;
|
|
else {
|
|
// decorrelate in case of multiple channels
|
|
if (s->channels > 1) {
|
|
int32_t *r = p - 1;
|
|
for (*p += *r / 2; r > (int32_t*)p - s->channels; r--)
|
|
*r = *(r + 1) - *r;
|
|
}
|
|
cur_chan = 0;
|
|
i++;
|
|
// check for last frame
|
|
if (i == s->last_frame_length && get_bits_left(&gb) / 8 == 4) {
|
|
frame->nb_samples = framelen = s->last_frame_length;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
align_get_bits(&gb);
|
|
if (get_bits_left(&gb) < 32) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
goto error;
|
|
}
|
|
skip_bits_long(&gb, 32); // frame crc
|
|
|
|
// convert to output buffer
|
|
switch (s->bps) {
|
|
case 1: {
|
|
uint8_t *samples = (uint8_t *)frame->data[0];
|
|
for (p = s->decode_buffer; (int32_t*)p < s->decode_buffer + (framelen * s->channels); p++)
|
|
*samples++ = *p + 0x80;
|
|
break;
|
|
}
|
|
case 2: {
|
|
int16_t *samples = (int16_t *)frame->data[0];
|
|
for (p = s->decode_buffer; (int32_t*)p < s->decode_buffer + (framelen * s->channels); p++)
|
|
*samples++ = *p;
|
|
break;
|
|
}
|
|
case 3: {
|
|
// shift samples for 24-bit sample format
|
|
int32_t *samples = (int32_t *)frame->data[0];
|
|
for (i = 0; i < framelen * s->channels; i++)
|
|
*samples++ *= 256;
|
|
// reset decode buffer
|
|
s->decode_buffer = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
*got_frame_ptr = 1;
|
|
|
|
return buf_size;
|
|
error:
|
|
// reset decode buffer
|
|
if (s->bps == 3)
|
|
s->decode_buffer = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static av_cold int tta_decode_close(AVCodecContext *avctx) {
|
|
TTAContext *s = avctx->priv_data;
|
|
|
|
if (s->bps < 3)
|
|
av_freep(&s->decode_buffer);
|
|
s->decode_buffer = NULL;
|
|
av_freep(&s->ch_ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define OFFSET(x) offsetof(TTAContext, x)
|
|
#define DEC (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
|
|
static const AVOption options[] = {
|
|
{ "password", "Set decoding password", OFFSET(pass), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC },
|
|
{ NULL },
|
|
};
|
|
|
|
static const AVClass tta_decoder_class = {
|
|
.class_name = "TTA Decoder",
|
|
.item_name = av_default_item_name,
|
|
.option = options,
|
|
.version = LIBAVUTIL_VERSION_INT,
|
|
};
|
|
|
|
const FFCodec ff_tta_decoder = {
|
|
.p.name = "tta",
|
|
.p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"),
|
|
.p.type = AVMEDIA_TYPE_AUDIO,
|
|
.p.id = AV_CODEC_ID_TTA,
|
|
.priv_data_size = sizeof(TTAContext),
|
|
.init = tta_decode_init,
|
|
.close = tta_decode_close,
|
|
.decode = tta_decode_frame,
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF,
|
|
.p.priv_class = &tta_decoder_class,
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
|
};
|