#include "avcodec.h"
#include "bytestream.h"
+#include "mathops.h"
typedef enum CinVideoBitmapIndex {
} CinVideoContext;
typedef struct CinAudioContext {
- AVCodecContext *avctx;
+ AVFrame frame;
int initial_decode_frame;
int delta;
} CinAudioContext;
bitmap_frame_size = buf_size - 4;
/* handle palette */
+ if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0)))
+ return AVERROR_INVALIDDATA;
if (palette_type == 0) {
+ if (palette_colors_count > 256)
+ return AVERROR_INVALIDDATA;
for (i = 0; i < palette_colors_count; ++i) {
- cin->palette[i] = bytestream_get_le24(&buf);
+ cin->palette[i] = 0xFF << 24 | bytestream_get_le24(&buf);
bitmap_frame_size -= 3;
}
} else {
for (i = 0; i < palette_colors_count; ++i) {
- cin->palette[buf[0]] = AV_RL24(buf+1);
+ cin->palette[buf[0]] = 0xFF << 24 | AV_RL24(buf+1);
buf += 4;
bitmap_frame_size -= 4;
}
{
CinAudioContext *cin = avctx->priv_data;
- cin->avctx = avctx;
+ if (avctx->channels != 1) {
+ av_log_ask_for_sample(avctx, "Number of channels is not supported\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
cin->initial_decode_frame = 1;
cin->delta = 0;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ avcodec_get_frame_defaults(&cin->frame);
+ avctx->coded_frame = &cin->frame;
+
return 0;
}
-static int cinaudio_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- AVPacket *avpkt)
+static int cinaudio_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
CinAudioContext *cin = avctx->priv_data;
- const uint8_t *src = buf;
- int16_t *samples = (int16_t *)data;
-
- buf_size = FFMIN(buf_size, *data_size/2);
+ const uint8_t *buf_end = buf + avpkt->size;
+ int16_t *samples;
+ int delta, ret;
+
+ /* get output buffer */
+ cin->frame.nb_samples = avpkt->size - cin->initial_decode_frame;
+ if ((ret = avctx->get_buffer(avctx, &cin->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ samples = (int16_t *)cin->frame.data[0];
+ delta = cin->delta;
if (cin->initial_decode_frame) {
cin->initial_decode_frame = 0;
- cin->delta = (int16_t)AV_RL16(src); src += 2;
- *samples++ = cin->delta;
- buf_size -= 2;
+ delta = sign_extend(AV_RL16(buf), 16);
+ buf += 2;
+ *samples++ = delta;
}
- while (buf_size > 0) {
- cin->delta += cinaudio_delta16_table[*src++];
- cin->delta = av_clip_int16(cin->delta);
- *samples++ = cin->delta;
- --buf_size;
+ while (buf < buf_end) {
+ delta += cinaudio_delta16_table[*buf++];
+ delta = av_clip_int16(delta);
+ *samples++ = delta;
}
+ cin->delta = delta;
- *data_size = (uint8_t *)samples - (uint8_t *)data;
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = cin->frame;
- return src - buf;
+ return avpkt->size;
}
.priv_data_size = sizeof(CinAudioContext),
.init = cinaudio_decode_init,
.decode = cinaudio_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"),
};