8svx.c
Go to the documentation of this file.
1 /*
2  * 8SVX audio decoder
3  * Copyright (C) 2008 Jaikrishnan Menon
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
31 #include "avcodec.h"
32 #include "internal.h"
33 
35 typedef struct EightSvxContext {
37  uint8_t fib_acc[2];
38  const int8_t *table;
39 
40  /* buffer used to store the whole first packet.
41  data is only sent as one large packet */
42  uint8_t *data[2];
43  int data_size;
44  int data_idx;
46 
47 static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1,
48  0, 1, 2, 3, 5, 8, 13, 21 };
49 static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1,
50  0, 1, 2, 4, 8, 16, 32, 64 };
51 
52 #define MAX_FRAME_SIZE 32768
53 
60 static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size,
61  uint8_t *state, const int8_t *table, int channels)
62 {
63  uint8_t val = *state;
64 
65  while (src_size--) {
66  uint8_t d = *src++;
67  val = av_clip_uint8(val + table[d & 0xF]);
68  *dst = val;
69  dst += channels;
70  val = av_clip_uint8(val + table[d >> 4]);
71  *dst = val;
72  dst += channels;
73  }
74 
75  *state = val;
76 }
77 
78 static void raw_decode(uint8_t *dst, const int8_t *src, int src_size,
79  int channels)
80 {
81  while (src_size--) {
82  *dst = *src++ + 128;
83  dst += channels;
84  }
85 }
86 
88 static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
89  int *got_frame_ptr, AVPacket *avpkt)
90 {
91  EightSvxContext *esc = avctx->priv_data;
92  int buf_size;
93  uint8_t *out_data;
94  int ret;
95  int is_compr = (avctx->codec_id != CODEC_ID_PCM_S8_PLANAR);
96 
97  /* for the first packet, copy data to buffer */
98  if (avpkt->data) {
99  int hdr_size = is_compr ? 2 : 0;
100  int chan_size = (avpkt->size - hdr_size * avctx->channels) / avctx->channels;
101 
102  if (avpkt->size < hdr_size * avctx->channels) {
103  av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
104  return AVERROR(EINVAL);
105  }
106  if (esc->data[0]) {
107  av_log(avctx, AV_LOG_ERROR, "unexpected data after first packet\n");
108  return AVERROR(EINVAL);
109  }
110 
111  if (is_compr) {
112  esc->fib_acc[0] = avpkt->data[1] + 128;
113  if (avctx->channels == 2)
114  esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
115  }
116 
117  esc->data_idx = 0;
118  esc->data_size = chan_size;
119  if (!(esc->data[0] = av_malloc(chan_size)))
120  return AVERROR(ENOMEM);
121  if (avctx->channels == 2) {
122  if (!(esc->data[1] = av_malloc(chan_size))) {
123  av_freep(&esc->data[0]);
124  return AVERROR(ENOMEM);
125  }
126  }
127  memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
128  if (avctx->channels == 2)
129  memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
130  }
131  if (!esc->data[0]) {
132  av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n");
133  return AVERROR(EINVAL);
134  }
135 
136  /* decode next piece of data from the buffer */
137  buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx);
138  if (buf_size <= 0) {
139  *got_frame_ptr = 0;
140  return avpkt->size;
141  }
142 
143  /* get output buffer */
144  esc->frame.nb_samples = buf_size * (is_compr + 1);
145  if ((ret = ff_get_buffer(avctx, &esc->frame)) < 0) {
146  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
147  return ret;
148  }
149  out_data = esc->frame.data[0];
150 
151  if (is_compr) {
152  delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size,
153  &esc->fib_acc[0], esc->table, avctx->channels);
154  if (avctx->channels == 2) {
155  delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size,
156  &esc->fib_acc[1], esc->table, avctx->channels);
157  }
158  } else {
159  int ch;
160  for (ch = 0; ch < avctx->channels; ch++) {
161  raw_decode((int8_t *)&out_data[ch], &esc->data[ch][esc->data_idx],
162  buf_size, avctx->channels);
163  }
164  }
165  esc->data_idx += buf_size;
166 
167  *got_frame_ptr = 1;
168  *(AVFrame *)data = esc->frame;
169 
170  return avpkt->size;
171 }
172 
175 {
176  EightSvxContext *esc = avctx->priv_data;
177 
178  if (avctx->channels < 1 || avctx->channels > 2) {
179  av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
180  return AVERROR(EINVAL);
181  }
182 
183  switch(avctx->codec->id) {
184  case CODEC_ID_8SVX_FIB:
185  esc->table = fibonacci;
186  break;
187  case CODEC_ID_8SVX_EXP:
188  esc->table = exponential;
189  break;
191  break;
192  default:
193  return -1;
194  }
195  avctx->sample_fmt = AV_SAMPLE_FMT_U8;
196 
198  avctx->coded_frame = &esc->frame;
199 
200  return 0;
201 }
202 
204 {
205  EightSvxContext *esc = avctx->priv_data;
206 
207  av_freep(&esc->data[0]);
208  av_freep(&esc->data[1]);
209 
210  return 0;
211 }
212 
214  .name = "8svx_fib",
215  .type = AVMEDIA_TYPE_AUDIO,
216  .id = CODEC_ID_8SVX_FIB,
217  .priv_data_size = sizeof (EightSvxContext),
221  .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1,
222  .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"),
223 };
224 
226  .name = "8svx_exp",
227  .type = AVMEDIA_TYPE_AUDIO,
228  .id = CODEC_ID_8SVX_EXP,
229  .priv_data_size = sizeof (EightSvxContext),
233  .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1,
234  .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"),
235 };
236 
238  .name = "pcm_s8_planar",
239  .type = AVMEDIA_TYPE_AUDIO,
241  .priv_data_size = sizeof(EightSvxContext),
245  .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1,
246  .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"),
247 };
static const int8_t fibonacci[16]
Definition: 8svx.c:47
Audio Video Frame.
Definition: avcodec.h:985
#define MAX_FRAME_SIZE
Definition: 8svx.c:52
AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2000
int size
Definition: avcodec.h:909
enum CodecID id
Definition: avcodec.h:3198
struct AVCodec * codec
Definition: avcodec.h:1529
AVCodec.
Definition: avcodec.h:3189
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:147
static int decode(MimicContext *ctx, int quality, int num_coeffs, int is_iframe)
Definition: mimic.c:228
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1464
#define av_cold
Definition: attributes.h:71
static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt)
decode a frame
Definition: 8svx.c:88
const char data[16]
Definition: mxf.c:60
AVCodec ff_eightsvx_fib_decoder
Definition: 8svx.c:213
uint8_t * data
Definition: avcodec.h:908
static av_cold int eightsvx_decode_close(AVCodecContext *avctx)
Definition: 8svx.c:203
static const int8_t exponential[16]
Definition: 8svx.c:49
static int init(AVCodecParserContext *s)
Definition: h264_parser.c:336
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:719
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:191
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:140
const char * name
Name of the codec implementation.
Definition: avcodec.h:3196
AVCodec ff_eightsvx_exp_decoder
Definition: 8svx.c:225
#define FFMIN(a, b)
Definition: common.h:55
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame)
Definition: utils.c:1867
const int8_t * table
Definition: 8svx.c:38
int data_idx
Definition: 8svx.c:44
external API header
struct EightSvxContext EightSvxContext
decoder context
main external API structure.
Definition: avcodec.h:1329
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:327
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:111
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:64
static void raw_decode(uint8_t *dst, const int8_t *src, int src_size, int channels)
Definition: 8svx.c:78
uint8_t fib_acc[2]
Definition: 8svx.c:37
static uint32_t state
Definition: trasher.c:25
int data_size
Definition: 8svx.c:43
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: avcodec.h:997
AVCodec ff_pcm_s8_planar_decoder
Definition: 8svx.c:237
AVFrame frame
Definition: 8svx.c:36
decoder context
Definition: 8svx.c:35
static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, uint8_t *state, const int8_t *table, int channels)
Delta decode the compressed values in src, and put the resulting decoded samples in dst...
Definition: 8svx.c:60
common internal api header.
unsigned 8 bits
Definition: samplefmt.h:29
static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
initialize 8svx decoder
Definition: 8svx.c:174
void * priv_data
Definition: avcodec.h:1531
uint8_t * data[2]
Definition: 8svx.c:42
int channels
number of audio channels
Definition: avcodec.h:1457
void avcodec_get_frame_defaults(AVFrame *pic)
Set the fields of the given AVFrame to default values.
Definition: utils.c:609
#define CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: avcodec.h:750
int nb_samples
number of audio samples (per channel) described by this frame
Definition: avcodec.h:1265
enum CodecID codec_id
Definition: avcodec.h:1575