#include "libavutil/channel_layout.h"
#include "avcodec.h"
+#include "internal.h"
#include "mathops.h"
#define BITSTREAM_READER_LE
ctx.recode2 = tmp2.values;
ctx.last = last;
- huff.length = ((size + 3) >> 2) + 3;
+ huff.length = ((size + 3) >> 2) + 4;
huff.maxlength = 0;
huff.current = 0;
huff.values = av_mallocz(huff.length * sizeof(int));
return v;
}
-static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
+static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
+ AVPacket *avpkt)
{
SmackVContext * const smk = avctx->priv_data;
uint8_t *out;
GetByteContext gb2;
GetBitContext gb;
int blocks, blk, bw, bh;
- int i;
+ int i, ret;
int stride;
int flags;
if (avpkt->size <= 769)
return 0;
- smk->pic.reference = 1;
- smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
- if(avctx->reget_buffer(avctx, &smk->pic) < 0){
+ if ((ret = ff_reget_buffer(avctx, &smk->pic)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
- return -1;
+ return ret;
}
/* make the palette available on the way out */
}
- *data_size = sizeof(AVFrame);
- *(AVFrame*)data = smk->pic;
+ if ((ret = av_frame_ref(data, &smk->pic)) < 0)
+ return ret;
+
+ *got_frame = 1;
/* always report that the buffer was completely consumed */
return avpkt->size;
c->avctx = avctx;
avctx->pix_fmt = AV_PIX_FMT_PAL8;
-
+ avcodec_get_frame_defaults(&c->pic);
/* decode huffman trees from extradata */
if(avctx->extradata_size < 16){
av_freep(&smk->full_tbl);
av_freep(&smk->type_tbl);
- if (smk->pic.data[0])
- avctx->release_buffer(avctx, &smk->pic);
+ av_frame_unref(&smk->pic);
return 0;
}
-typedef struct SmackerAudioContext {
- AVFrame frame;
-} SmackerAudioContext;
-
static av_cold int smka_decode_init(AVCodecContext *avctx)
{
- SmackerAudioContext *s = avctx->priv_data;
-
if (avctx->channels < 1 || avctx->channels > 2) {
av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
return AVERROR(EINVAL);
avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
avctx->sample_fmt = avctx->bits_per_coded_sample == 8 ? AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16;
- avcodec_get_frame_defaults(&s->frame);
- avctx->coded_frame = &s->frame;
-
return 0;
}
static int smka_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
- SmackerAudioContext *s = avctx->priv_data;
+ AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
GetBitContext gb;
}
/* get output buffer */
- s->frame.nb_samples = unp_size / (avctx->channels * (bits + 1));
- if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+ frame->nb_samples = unp_size / (avctx->channels * (bits + 1));
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- samples = (int16_t *)s->frame.data[0];
- samples8 = s->frame.data[0];
+ samples = (int16_t *)frame->data[0];
+ samples8 = frame->data[0];
// Initialize
for(i = 0; i < (1 << (bits + stereo)); i++) {
h[i].lengths = av_mallocz(256 * sizeof(int));
h[i].values = av_mallocz(256 * sizeof(int));
skip_bits1(&gb);
- smacker_decode_tree(&gb, &h[i], 0, 0);
+ if (smacker_decode_tree(&gb, &h[i], 0, 0) < 0) {
+ for (; i >= 0; i--) {
+ if (vlc[i].table)
+ ff_free_vlc(&vlc[i]);
+ av_free(h[i].bits);
+ av_free(h[i].lengths);
+ av_free(h[i].values);
+ }
+ return AVERROR_INVALIDDATA;
+ }
skip_bits1(&gb);
if(h[i].current > 1) {
res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length,
}
}
}
+ /* this codec relies on wraparound instead of clipping audio */
if(bits) { //decode 16-bit data
for(i = stereo; i >= 0; i--)
pred[i] = sign_extend(av_bswap16(get_bits(&gb, 16)), 16);
res = 0;
val |= h[3].values[res] << 8;
pred[1] += sign_extend(val, 16);
- *samples++ = av_clip_int16(pred[1]);
+ *samples++ = pred[1];
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
res = 0;
val |= h[1].values[res] << 8;
pred[0] += sign_extend(val, 16);
- *samples++ = av_clip_int16(pred[0]);
+ *samples++ = pred[0];
}
}
} else { //8-bit data
else
res = 0;
pred[1] += sign_extend(h[1].values[res], 8);
- *samples8++ = av_clip_uint8(pred[1]);
+ *samples8++ = pred[1];
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
else
res = 0;
pred[0] += sign_extend(h[0].values[res], 8);
- *samples8++ = av_clip_uint8(pred[0]);
+ *samples8++ = pred[0];
}
}
}
av_free(h[i].values);
}
- *got_frame_ptr = 1;
- *(AVFrame *)data = s->frame;
+ *got_frame_ptr = 1;
return buf_size;
}
.name = "smackaud",
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_SMACKAUDIO,
- .priv_data_size = sizeof(SmackerAudioContext),
.init = smka_decode_init,
.decode = smka_decode_frame,
.capabilities = CODEC_CAP_DR1,