00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00040 #include "libavutil/avassert.h"
00041 #include "avcodec.h"
00042 #include "libavutil/common.h"
00043
00045 typedef struct EightSvxContext {
00046 AVFrame frame;
00047 const int8_t *table;
00048
00049
00050
00051 uint8_t *samples;
00052 int64_t samples_size;
00053 int samples_idx;
00054 } EightSvxContext;
00055
00056 static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 };
00057 static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 };
00058
00059 #define MAX_FRAME_SIZE 2048
00060
00068 static void interleave_stereo(uint8_t *dst, const uint8_t *src, int size)
00069 {
00070 uint8_t *dst_end = dst + size;
00071 size = size>>1;
00072
00073 while (dst < dst_end) {
00074 *dst++ = *src;
00075 *dst++ = *(src+size);
00076 src++;
00077 }
00078 }
00079
00088 static int delta_decode(int8_t *dst, const uint8_t *src, int src_size,
00089 int8_t val, const int8_t *table)
00090 {
00091 int n = src_size;
00092 int8_t *dst0 = dst;
00093
00094 while (n--) {
00095 uint8_t d = *src++;
00096 val = av_clip(val + table[d & 0x0f], -127, 128);
00097 *dst++ = val;
00098 val = av_clip(val + table[d >> 4] , -127, 128);
00099 *dst++ = val;
00100 }
00101
00102 return dst-dst0;
00103 }
00104
00106 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
00107 int *got_frame_ptr, AVPacket *avpkt)
00108 {
00109 EightSvxContext *esc = avctx->priv_data;
00110 int n, out_data_size, ret;
00111 uint8_t *src, *dst;
00112
00113
00114 if (!esc->samples && avpkt) {
00115 uint8_t *deinterleaved_samples, *p = NULL;
00116 int packet_size = avpkt->size;
00117
00118 if (packet_size % avctx->channels) {
00119 av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n");
00120 if (packet_size < avctx->channels)
00121 return packet_size;
00122 packet_size -= packet_size % avctx->channels;
00123 }
00124 esc->samples_size = !esc->table ?
00125 packet_size : avctx->channels + (packet_size-avctx->channels) * 2;
00126 if (!(esc->samples = av_malloc(esc->samples_size)))
00127 return AVERROR(ENOMEM);
00128
00129
00130 if (esc->table) {
00131 const uint8_t *buf = avpkt->data;
00132 uint8_t *dst;
00133 int buf_size = avpkt->size;
00134 int i, n = esc->samples_size;
00135
00136 if (buf_size < 2) {
00137 av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
00138 return AVERROR(EINVAL);
00139 }
00140 if (!(deinterleaved_samples = av_mallocz(n)))
00141 return AVERROR(ENOMEM);
00142 dst = p = deinterleaved_samples;
00143
00144
00145 dst = deinterleaved_samples;
00146 for (i = 0; i < avctx->channels; i++) {
00147 delta_decode(dst, buf + 1, buf_size / avctx->channels - 1, buf[0], esc->table);
00148 buf += buf_size / avctx->channels;
00149 dst += n / avctx->channels - 1;
00150 }
00151 } else {
00152 deinterleaved_samples = avpkt->data;
00153 }
00154
00155 if (avctx->channels == 2)
00156 interleave_stereo(esc->samples, deinterleaved_samples, esc->samples_size);
00157 else
00158 memcpy(esc->samples, deinterleaved_samples, esc->samples_size);
00159 av_freep(&p);
00160 }
00161
00162
00163 av_assert1(!(esc->samples_size % avctx->channels || esc->samples_idx % avctx->channels));
00164 esc->frame.nb_samples = FFMIN(MAX_FRAME_SIZE, esc->samples_size - esc->samples_idx) / avctx->channels;
00165 if ((ret = avctx->get_buffer(avctx, &esc->frame)) < 0) {
00166 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00167 return ret;
00168 }
00169
00170 *got_frame_ptr = 1;
00171 *(AVFrame *)data = esc->frame;
00172
00173 dst = esc->frame.data[0];
00174 src = esc->samples + esc->samples_idx;
00175 out_data_size = esc->frame.nb_samples * avctx->channels;
00176 for (n = out_data_size; n > 0; n--)
00177 *dst++ = *src++ + 128;
00178 esc->samples_idx += out_data_size;
00179
00180 return esc->table ?
00181 (avctx->frame_number == 0)*2 + out_data_size / 2 :
00182 out_data_size;
00183 }
00184
00185 static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
00186 {
00187 EightSvxContext *esc = avctx->priv_data;
00188
00189 if (avctx->channels < 1 || avctx->channels > 2) {
00190 av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
00191 return AVERROR_INVALIDDATA;
00192 }
00193
00194 switch (avctx->codec->id) {
00195 case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci; break;
00196 case AV_CODEC_ID_8SVX_EXP: esc->table = exponential; break;
00197 case AV_CODEC_ID_PCM_S8_PLANAR:
00198 case AV_CODEC_ID_8SVX_RAW: esc->table = NULL; break;
00199 default:
00200 av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id);
00201 return AVERROR_INVALIDDATA;
00202 }
00203 avctx->sample_fmt = AV_SAMPLE_FMT_U8;
00204
00205 avcodec_get_frame_defaults(&esc->frame);
00206 avctx->coded_frame = &esc->frame;
00207
00208 return 0;
00209 }
00210
00211 static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
00212 {
00213 EightSvxContext *esc = avctx->priv_data;
00214
00215 av_freep(&esc->samples);
00216 esc->samples_size = 0;
00217 esc->samples_idx = 0;
00218
00219 return 0;
00220 }
00221
00222 #if CONFIG_EIGHTSVX_FIB_DECODER
00223 AVCodec ff_eightsvx_fib_decoder = {
00224 .name = "8svx_fib",
00225 .type = AVMEDIA_TYPE_AUDIO,
00226 .id = AV_CODEC_ID_8SVX_FIB,
00227 .priv_data_size = sizeof (EightSvxContext),
00228 .init = eightsvx_decode_init,
00229 .decode = eightsvx_decode_frame,
00230 .close = eightsvx_decode_close,
00231 .capabilities = CODEC_CAP_DR1,
00232 .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
00233 };
00234 #endif
00235 #if CONFIG_EIGHTSVX_EXP_DECODER
00236 AVCodec ff_eightsvx_exp_decoder = {
00237 .name = "8svx_exp",
00238 .type = AVMEDIA_TYPE_AUDIO,
00239 .id = AV_CODEC_ID_8SVX_EXP,
00240 .priv_data_size = sizeof (EightSvxContext),
00241 .init = eightsvx_decode_init,
00242 .decode = eightsvx_decode_frame,
00243 .close = eightsvx_decode_close,
00244 .capabilities = CODEC_CAP_DR1,
00245 .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"),
00246 };
00247 #endif
00248 #if CONFIG_PCM_S8_PLANAR_DECODER
00249 AVCodec ff_pcm_s8_planar_decoder = {
00250 .name = "pcm_s8_planar",
00251 .type = AVMEDIA_TYPE_AUDIO,
00252 .id = AV_CODEC_ID_PCM_S8_PLANAR,
00253 .priv_data_size = sizeof(EightSvxContext),
00254 .init = eightsvx_decode_init,
00255 .close = eightsvx_decode_close,
00256 .decode = eightsvx_decode_frame,
00257 .capabilities = CODEC_CAP_DR1,
00258 .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"),
00259 };
00260 #endif