* ADX ADPCM codecs
* Copyright (c) 2001,2003 BERO
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "libavutil/intreadwrite.h"
#include "avcodec.h"
#include "adx.h"
+#include "bytestream.h"
#include "put_bits.h"
/**
flush_put_bits(&pb);
}
+#define HEADER_SIZE 36
+
static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize)
{
ADXContext *c = avctx->priv_data;
- AV_WB32(buf + 0x00, 0x80000000 | 0x20);
- AV_WB32(buf + 0x04, 0x03120400 | avctx->channels);
- AV_WB32(buf + 0x08, avctx->sample_rate);
- AV_WB32(buf + 0x0c, 0);
- AV_WB16(buf + 0x10, c->cutoff);
- AV_WB32(buf + 0x12, 0x03000000);
- AV_WB32(buf + 0x16, 0x00000000);
- AV_WB32(buf + 0x1a, 0x00000000);
- memcpy (buf + 0x1e, "(c)CRI", 6);
- return 0x20 + 4;
+ if (bufsize < HEADER_SIZE)
+ return AVERROR(EINVAL);
+
+ bytestream_put_be16(&buf, 0x8000); /* header signature */
+ bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */
+ bytestream_put_byte(&buf, 3); /* encoding */
+ bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */
+ bytestream_put_byte(&buf, 4); /* sample size */
+ bytestream_put_byte(&buf, avctx->channels); /* channels */
+ bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */
+ bytestream_put_be32(&buf, 0); /* total sample count */
+ bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */
+ bytestream_put_byte(&buf, 3); /* version */
+ bytestream_put_byte(&buf, 0); /* flags */
+ bytestream_put_be32(&buf, 0); /* unknown */
+ bytestream_put_be32(&buf, 0); /* loop enabled */
+ bytestream_put_be16(&buf, 0); /* padding */
+ bytestream_put_buffer(&buf, "(c)CRI", 6); /* copyright signature */
+
+ return HEADER_SIZE;
}
static av_cold int adx_encode_init(AVCodecContext *avctx)
avctx->frame_size = BLOCK_SAMPLES;
avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame)
+ return AVERROR(ENOMEM);
/* the cutoff can be adjusted, but this seems to work pretty well */
c->cutoff = 500;
int ch;
if (!c->header_parsed) {
- int hdrsize = adx_encode_header(avctx, dst, buf_size);
- dst += hdrsize;
+ int hdrsize;
+ if ((hdrsize = adx_encode_header(avctx, dst, buf_size)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
+ return AVERROR(EINVAL);
+ }
+ dst += hdrsize;
+ buf_size -= hdrsize;
c->header_parsed = 1;
}
+ if (buf_size < BLOCK_SIZE * avctx->channels) {
+ av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
+ return AVERROR(EINVAL);
+ }
for (ch = 0; ch < avctx->channels; ch++) {
adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels);