1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (C) 2008 Jaikrishnan Menon 3cabdff1aSopenharmony_ci * Copyright (C) 2011 Stefano Sabatini 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * 8svx audio decoder 25cabdff1aSopenharmony_ci * @author Jaikrishnan Menon 26cabdff1aSopenharmony_ci * 27cabdff1aSopenharmony_ci * supports: fibonacci delta encoding 28cabdff1aSopenharmony_ci * : exponential encoding 29cabdff1aSopenharmony_ci * 30cabdff1aSopenharmony_ci * For more information about the 8SVX format: 31cabdff1aSopenharmony_ci * http://netghost.narod.ru/gff/vendspec/iff/iff.txt 32cabdff1aSopenharmony_ci * http://sox.sourceforge.net/AudioFormats-11.html 33cabdff1aSopenharmony_ci * http://aminet.net/package/mus/misc/wavepak 34cabdff1aSopenharmony_ci * http://amigan.1emu.net/reg/8SVX.txt 35cabdff1aSopenharmony_ci * 36cabdff1aSopenharmony_ci * Samples can be found here: 37cabdff1aSopenharmony_ci * http://aminet.net/mods/smpl/ 38cabdff1aSopenharmony_ci */ 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#include "config_components.h" 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 43cabdff1aSopenharmony_ci#include "avcodec.h" 44cabdff1aSopenharmony_ci#include "codec_internal.h" 45cabdff1aSopenharmony_ci#include "internal.h" 46cabdff1aSopenharmony_ci#include "libavutil/common.h" 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci/** decoder context */ 49cabdff1aSopenharmony_citypedef struct EightSvxContext { 50cabdff1aSopenharmony_ci uint8_t fib_acc[2]; 51cabdff1aSopenharmony_ci const int8_t *table; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci /* buffer used to store the whole first packet. 54cabdff1aSopenharmony_ci data is only sent as one large packet */ 55cabdff1aSopenharmony_ci uint8_t *data[2]; 56cabdff1aSopenharmony_ci int data_size; 57cabdff1aSopenharmony_ci int data_idx; 58cabdff1aSopenharmony_ci} EightSvxContext; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_cistatic const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 }; 61cabdff1aSopenharmony_cistatic const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 }; 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci#define MAX_FRAME_SIZE 2048 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci/** 66cabdff1aSopenharmony_ci * Delta decode the compressed values in src, and put the resulting 67cabdff1aSopenharmony_ci * decoded samples in dst. 68cabdff1aSopenharmony_ci * 69cabdff1aSopenharmony_ci * @param[in,out] state starting value. it is saved for use in the next call. 70cabdff1aSopenharmony_ci * @param table delta sequence table 71cabdff1aSopenharmony_ci */ 72cabdff1aSopenharmony_cistatic void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, 73cabdff1aSopenharmony_ci uint8_t *state, const int8_t *table) 74cabdff1aSopenharmony_ci{ 75cabdff1aSopenharmony_ci uint8_t val = *state; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci while (src_size--) { 78cabdff1aSopenharmony_ci uint8_t d = *src++; 79cabdff1aSopenharmony_ci val = av_clip_uint8(val + table[d & 0xF]); 80cabdff1aSopenharmony_ci *dst++ = val; 81cabdff1aSopenharmony_ci val = av_clip_uint8(val + table[d >> 4]); 82cabdff1aSopenharmony_ci *dst++ = val; 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci *state = val; 86cabdff1aSopenharmony_ci} 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci/** decode a frame */ 89cabdff1aSopenharmony_cistatic int eightsvx_decode_frame(AVCodecContext *avctx, AVFrame *frame, 90cabdff1aSopenharmony_ci int *got_frame_ptr, AVPacket *avpkt) 91cabdff1aSopenharmony_ci{ 92cabdff1aSopenharmony_ci EightSvxContext *esc = avctx->priv_data; 93cabdff1aSopenharmony_ci int channels = avctx->ch_layout.nb_channels; 94cabdff1aSopenharmony_ci int buf_size; 95cabdff1aSopenharmony_ci int ch, ret; 96cabdff1aSopenharmony_ci int hdr_size = 2; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci /* decode and interleave the first packet */ 99cabdff1aSopenharmony_ci if (!esc->data[0] && avpkt) { 100cabdff1aSopenharmony_ci int chan_size = avpkt->size / channels - hdr_size; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (avpkt->size % channels) { 103cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n"); 104cabdff1aSopenharmony_ci } 105cabdff1aSopenharmony_ci if (avpkt->size < (hdr_size + 1) * channels) { 106cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); 107cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci esc->fib_acc[0] = avpkt->data[1] + 128; 111cabdff1aSopenharmony_ci if (channels == 2) 112cabdff1aSopenharmony_ci esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128; 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci esc->data_idx = 0; 115cabdff1aSopenharmony_ci esc->data_size = chan_size; 116cabdff1aSopenharmony_ci if (!(esc->data[0] = av_malloc(chan_size))) 117cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 118cabdff1aSopenharmony_ci if (channels == 2) { 119cabdff1aSopenharmony_ci if (!(esc->data[1] = av_malloc(chan_size))) { 120cabdff1aSopenharmony_ci av_freep(&esc->data[0]); 121cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size); 125cabdff1aSopenharmony_ci if (channels == 2) 126cabdff1aSopenharmony_ci memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size); 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci if (!esc->data[0]) { 129cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n"); 130cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci /* decode next piece of data from the buffer */ 134cabdff1aSopenharmony_ci buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx); 135cabdff1aSopenharmony_ci if (buf_size <= 0) { 136cabdff1aSopenharmony_ci *got_frame_ptr = 0; 137cabdff1aSopenharmony_ci return avpkt->size; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci /* get output buffer */ 141cabdff1aSopenharmony_ci frame->nb_samples = buf_size * 2; 142cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 143cabdff1aSopenharmony_ci return ret; 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci for (ch = 0; ch < channels; ch++) { 146cabdff1aSopenharmony_ci delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx], 147cabdff1aSopenharmony_ci buf_size, &esc->fib_acc[ch], esc->table); 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci esc->data_idx += buf_size; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci *got_frame_ptr = 1; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci return ((avctx->frame_number == 0) * hdr_size + buf_size) * channels; 155cabdff1aSopenharmony_ci} 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_cistatic av_cold int eightsvx_decode_init(AVCodecContext *avctx) 158cabdff1aSopenharmony_ci{ 159cabdff1aSopenharmony_ci EightSvxContext *esc = avctx->priv_data; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) { 162cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n"); 163cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci switch (avctx->codec->id) { 167cabdff1aSopenharmony_ci case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci; break; 168cabdff1aSopenharmony_ci case AV_CODEC_ID_8SVX_EXP: esc->table = exponential; break; 169cabdff1aSopenharmony_ci default: 170cabdff1aSopenharmony_ci av_assert1(0); 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci avctx->sample_fmt = AV_SAMPLE_FMT_U8P; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci return 0; 175cabdff1aSopenharmony_ci} 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_cistatic av_cold int eightsvx_decode_close(AVCodecContext *avctx) 178cabdff1aSopenharmony_ci{ 179cabdff1aSopenharmony_ci EightSvxContext *esc = avctx->priv_data; 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci av_freep(&esc->data[0]); 182cabdff1aSopenharmony_ci av_freep(&esc->data[1]); 183cabdff1aSopenharmony_ci esc->data_size = 0; 184cabdff1aSopenharmony_ci esc->data_idx = 0; 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci return 0; 187cabdff1aSopenharmony_ci} 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci#if CONFIG_EIGHTSVX_FIB_DECODER 190cabdff1aSopenharmony_ciconst FFCodec ff_eightsvx_fib_decoder = { 191cabdff1aSopenharmony_ci .p.name = "8svx_fib", 192cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), 193cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_AUDIO, 194cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_8SVX_FIB, 195cabdff1aSopenharmony_ci .priv_data_size = sizeof (EightSvxContext), 196cabdff1aSopenharmony_ci .init = eightsvx_decode_init, 197cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(eightsvx_decode_frame), 198cabdff1aSopenharmony_ci .close = eightsvx_decode_close, 199cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 200cabdff1aSopenharmony_ci .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, 201cabdff1aSopenharmony_ci AV_SAMPLE_FMT_NONE }, 202cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 203cabdff1aSopenharmony_ci}; 204cabdff1aSopenharmony_ci#endif 205cabdff1aSopenharmony_ci#if CONFIG_EIGHTSVX_EXP_DECODER 206cabdff1aSopenharmony_ciconst FFCodec ff_eightsvx_exp_decoder = { 207cabdff1aSopenharmony_ci .p.name = "8svx_exp", 208cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), 209cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_AUDIO, 210cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_8SVX_EXP, 211cabdff1aSopenharmony_ci .priv_data_size = sizeof (EightSvxContext), 212cabdff1aSopenharmony_ci .init = eightsvx_decode_init, 213cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(eightsvx_decode_frame), 214cabdff1aSopenharmony_ci .close = eightsvx_decode_close, 215cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 216cabdff1aSopenharmony_ci .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, 217cabdff1aSopenharmony_ci AV_SAMPLE_FMT_NONE }, 218cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 219cabdff1aSopenharmony_ci}; 220cabdff1aSopenharmony_ci#endif 221