summaryrefslogtreecommitdiff
path: root/libavcodec/adxenc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-01-05 02:03:12 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-01-05 02:03:12 +0100
commit7f83db312454b3673a4dfd34745428f61309ab30 (patch)
tree27c92b052b83e4b3bf95a33fbe6979aaa00f8184 /libavcodec/adxenc.c
parentc4eec85a1fa768025f88261995af08f1dba9685d (diff)
parentfeb15cee5e19a1e31d075ec08d598d64c2dc38ef (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (46 commits) mtv: Make sure audio_subsegments is not 0 v4l2: use V4L2_FMT_FLAG_EMULATED only if it is defined avconv: add symbolic names for -vsync parameters flvdec: Fix compiler warning for uninitialized variables rtsp: Fix compiler warning for uninitialized variable ulti: convert to new bytestream API. swscale: Use standard multiple inclusion guards in ppc/ header files. Place some START_TIMER invocations in separate blocks. v4l2: list available formats v4l2: set the proper codec_tag v4l2: refactor device_open v4l2: simplify away io_method v4l2: cosmetics v4l2: uniform and format options v4l2: do not force interlaced mode avio: exit early in fill_buffer without read_packet vc1dec: fix invalid memory access for small video dimensions rv34: fix invalid memory access for small video dimensions rv34: joint coefficient decoding and dequantization avplay: Don't call avio_set_interrupt_cb(NULL) ... Conflicts: Changelog avconv.c doc/APIchanges doc/indevs.texi libavcodec/adxenc.c libavcodec/dnxhdenc.c libavcodec/h264.c libavdevice/v4l2.c libavformat/flvdec.c libavformat/mtv.c libswscale/utils.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/adxenc.c')
-rw-r--r--libavcodec/adxenc.c185
1 files changed, 77 insertions, 108 deletions
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index 51545fa06c..b029e2eb78 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -19,9 +19,9 @@
* 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"
/**
@@ -33,167 +33,135 @@
* adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/
*/
-/* 18 bytes <-> 32 samples */
-
-static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav,
- ADXChannelState *prev)
+static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav,
+ ADXChannelState *prev, int channels)
{
PutBitContext pb;
int scale;
- int i;
- int s0,s1,s2,d;
- int max=0;
- int min=0;
- int data[32];
+ int i, j;
+ int s0, s1, s2, d;
+ int max = 0;
+ int min = 0;
+ int data[BLOCK_SAMPLES];
s1 = prev->s1;
s2 = prev->s2;
- for(i=0;i<32;i++) {
+ for (i = 0, j = 0; j < 32; i += channels, j++) {
s0 = wav[i];
d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
- data[i]=d;
- if (max<d) max=d;
- if (min>d) min=d;
+ data[j] = d;
+ if (max < d)
+ max = d;
+ if (min > d)
+ min = d;
s2 = s1;
s1 = s0;
}
prev->s1 = s1;
prev->s2 = s2;
- /* -8..+7 */
-
- if (max==0 && min==0) {
- memset(adx,0,18);
+ if (max == 0 && min == 0) {
+ memset(adx, 0, BLOCK_SIZE);
return;
}
- if (max/7>-min/8) scale = max/7;
- else scale = -min/8;
+ if (max / 7 > -min / 8)
+ scale = max / 7;
+ else
+ scale = -min / 8;
- if (scale==0) scale=1;
+ if (scale == 0)
+ scale = 1;
AV_WB16(adx, scale);
init_put_bits(&pb, adx + 2, 16);
- for (i = 0; i < 32; i++)
- put_sbits(&pb, 4, av_clip(data[i]/scale, -8, 7));
+ for (i = 0; i < BLOCK_SAMPLES; i++)
+ put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7));
flush_put_bits(&pb);
}
-static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize)
+#define HEADER_SIZE 36
+
+static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize)
{
-#if 0
- struct {
- uint32_t offset; /* 0x80000000 + sample start - 4 */
- unsigned char unknown1[3]; /* 03 12 04 */
- unsigned char channel; /* 1 or 2 */
- uint32_t freq;
- uint32_t size;
- uint32_t unknown2; /* 01 f4 03 00 */
- uint32_t unknown3; /* 00 00 00 00 */
- uint32_t unknown4; /* 00 00 00 00 */
-
- /* if loop
- unknown3 00 15 00 01
- unknown4 00 00 00 01
- long loop_start_sample;
- long loop_start_byte;
- long loop_end_sample;
- long loop_end_byte;
- long
- */
- } adxhdr; /* big endian */
- /* offset-6 "(c)CRI" */
-#endif
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); /* FIXME: set after */
- 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)
{
ADXContext *c = avctx->priv_data;
- if (avctx->channels > 2)
- return -1; /* only stereo or mono =) */
- avctx->frame_size = 32;
-
- avctx->coded_frame= avcodec_alloc_frame();
- avctx->coded_frame->key_frame= 1;
+ if (avctx->channels > 2) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
+ return AVERROR(EINVAL);
+ }
+ avctx->frame_size = BLOCK_SAMPLES;
-// avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32;
+ avctx->coded_frame = avcodec_alloc_frame();
/* the cutoff can be adjusted, but this seems to work pretty well */
c->cutoff = 500;
ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff);
- av_log(avctx, AV_LOG_DEBUG, "adx encode init\n");
-
return 0;
}
static av_cold int adx_encode_close(AVCodecContext *avctx)
{
av_freep(&avctx->coded_frame);
-
return 0;
}
-static int adx_encode_frame(AVCodecContext *avctx,
- uint8_t *frame, int buf_size, void *data)
+static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame,
+ int buf_size, void *data)
{
- ADXContext *c = avctx->priv_data;
- const short *samples = data;
- unsigned char *dst = frame;
- int rest = avctx->frame_size;
-
-/*
- input data size =
- ffmpeg.c: do_audio_out()
- frame_bytes = enc->frame_size * 2 * enc->channels;
-*/
+ ADXContext *c = avctx->priv_data;
+ const int16_t *samples = data;
+ uint8_t *dst = frame;
+ int ch;
-// printf("sz=%d ",buf_size); fflush(stdout);
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);
+ }
- if (avctx->channels==1) {
- while(rest>=32) {
- adx_encode(c, dst, samples, c->prev);
- dst+=18;
- samples+=32;
- rest-=32;
- }
- } else {
- while(rest>=32*2) {
- short tmpbuf[32*2];
- int i;
-
- for(i=0;i<32;i++) {
- tmpbuf[i] = samples[i*2];
- tmpbuf[i+32] = samples[i*2+1];
- }
-
- adx_encode(c, dst, tmpbuf, c->prev);
- adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1);
- dst+=18*2;
- samples+=32*2;
- rest-=32*2;
- }
+ for (ch = 0; ch < avctx->channels; ch++) {
+ adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels);
+ dst += BLOCK_SIZE;
}
- return dst-frame;
+ return dst - frame;
}
AVCodec ff_adpcm_adx_encoder = {
@@ -204,6 +172,7 @@ AVCodec ff_adpcm_adx_encoder = {
.init = adx_encode_init,
.encode = adx_encode_frame,
.close = adx_encode_close,
- .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
- .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
};