X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fadpcmenc.c;h=1c62ca5a83289a30c5eaf073d8f5a94a0e18d8d1;hb=83b6471dcb762859f20b2c414decc755fcceb5e8;hp=f21edfc3e35c686eda0dfb8ba5afb07249623870;hpb=eb75a80dc8cb2578941608d9738cff6fafc4b4fa;p=ffmpeg diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index f21edfc3e35..1c62ca5a832 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -74,7 +74,12 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (s->block_size & (s->block_size - 1)) { + /* + * AMV's block size has to match that of the corresponding video + * stream. Relax the POT requirement. + */ + if (avctx->codec->id != AV_CODEC_ID_ADPCM_IMA_AMV && + (s->block_size & (s->block_size - 1))) { av_log(avctx, AV_LOG_ERROR, "block size must be power of 2\n"); return AVERROR(EINVAL); } @@ -89,7 +94,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) if (avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_SSI || avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_APM || - avctx->codec->id == AV_CODEC_ID_ADPCM_ARGO) { + avctx->codec->id == AV_CODEC_ID_ADPCM_ARGO || + avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_WS) { /* * The current trellis implementation doesn't work for extended * runs of samples without periodic resets. Disallow it. @@ -113,11 +119,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) case AV_CODEC_ID_ADPCM_IMA_WAV: /* each 16 bits sample gives one nibble and we have 4 bytes per channel overhead */ - avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 / + avctx->frame_size = (s->block_size - 4 * avctx->channels) * 8 / (4 * avctx->channels) + 1; /* seems frame_size isn't taken into account... have to buffer the samples :-( */ - avctx->block_align = BLKSIZE; + avctx->block_align = s->block_size; avctx->bits_per_coded_sample = 4; break; case AV_CODEC_ID_ADPCM_IMA_QT: @@ -142,8 +148,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) } break; case AV_CODEC_ID_ADPCM_YAMAHA: - avctx->frame_size = BLKSIZE * 2 / avctx->channels; - avctx->block_align = BLKSIZE; + avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->block_align = s->block_size; break; case AV_CODEC_ID_ADPCM_SWF: if (avctx->sample_rate != 11025 && @@ -153,12 +159,28 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) "22050 or 44100\n"); return AVERROR(EINVAL); } - avctx->frame_size = 512 * (avctx->sample_rate / 11025); + avctx->frame_size = 4096; /* Hardcoded according to the SWF spec. */ + avctx->block_align = (2 + avctx->channels * (22 + 4 * (avctx->frame_size - 1)) + 7) / 8; break; case AV_CODEC_ID_ADPCM_IMA_SSI: + case AV_CODEC_ID_ADPCM_IMA_ALP: avctx->frame_size = s->block_size * 2 / avctx->channels; avctx->block_align = s->block_size; break; + case AV_CODEC_ID_ADPCM_IMA_AMV: + if (avctx->sample_rate != 22050) { + av_log(avctx, AV_LOG_ERROR, "Sample rate must be 22050\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = s->block_size; + avctx->block_align = 8 + (FFALIGN(avctx->frame_size, 2) / 2); + break; case AV_CODEC_ID_ADPCM_IMA_APM: avctx->frame_size = s->block_size * 2 / avctx->channels; avctx->block_align = s->block_size; @@ -171,6 +193,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) avctx->frame_size = 32; avctx->block_align = 17 * avctx->channels; break; + case AV_CODEC_ID_ADPCM_IMA_WS: + /* each 16 bits sample gives one nibble */ + avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->block_align = s->block_size; + break; default: return AVERROR(EINVAL); } @@ -203,6 +230,25 @@ static inline uint8_t adpcm_ima_compress_sample(ADPCMChannelStatus *c, return nibble; } +static inline uint8_t adpcm_ima_alp_compress_sample(ADPCMChannelStatus *c, int16_t sample) +{ + const int delta = sample - c->prev_sample; + const int step = ff_adpcm_step_table[c->step_index]; + const int sign = (delta < 0) * 8; + + int nibble = FFMIN(abs(delta) * 4 / step, 7); + int diff = (step * nibble) >> 2; + if (sign) + diff = -diff; + + nibble = sign | nibble; + + c->prev_sample += diff; + c->prev_sample = av_clip_int16(c->prev_sample); + c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88); + return nibble; +} + static inline uint8_t adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c, int16_t sample) { @@ -317,6 +363,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, nodes[0]->sample2 = c->sample2; if (version == AV_CODEC_ID_ADPCM_IMA_WAV || version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_IMA_AMV || version == AV_CODEC_ID_ADPCM_SWF) nodes[0]->sample1 = c->prev_sample; if (version == AV_CODEC_ID_ADPCM_MS) @@ -421,6 +468,7 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, } } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV || version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_IMA_AMV || version == AV_CODEC_ID_ADPCM_SWF) { #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\ const int predictor = nodes[j]->sample1;\ @@ -550,10 +598,10 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, samples_p = (int16_t **)frame->extended_data; st = avctx->channels == 2; - if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF) - pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8; - else if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_SSI || - avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_APM) + if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_SSI || + avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_ALP || + avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_APM || + avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_WS) pkt_size = (frame->nb_samples * avctx->channels) / 2; else pkt_size = avctx->block_align; @@ -656,6 +704,24 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&pb); break; } + case AV_CODEC_ID_ADPCM_IMA_ALP: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(avctx->trellis == 0); + + for (n = frame->nb_samples / 2; n > 0; n--) { + for (ch = 0; ch < avctx->channels; ch++) { + put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, *samples++)); + put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, samples[st])); + } + samples += avctx->channels; + } + + flush_put_bits(&pb); + break; + } case AV_CODEC_ID_ADPCM_SWF: { PutBitContext pb; @@ -663,6 +729,9 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, n = frame->nb_samples - 1; + /* NB: This is safe as we don't have AV_CODEC_CAP_SMALL_LAST_FRAME. */ + av_assert0(n == 4095); + // store AdpcmCodeSize put_bits(&pb, 2, 2); // set 4-bit flash adpcm format @@ -676,8 +745,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (avctx->trellis > 0) { - if (!(buf = av_malloc(2 * n))) - return AVERROR(ENOMEM); + uint8_t buf[8190 /* = 2 * n */]; adpcm_compress_trellis(avctx, samples + avctx->channels, buf, &c->status[0], n, avctx->channels); if (avctx->channels == 2) @@ -689,7 +757,6 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (avctx->channels == 2) put_bits(&pb, 4, buf[n + i]); } - av_free(buf); } else { for (i = 1; i < frame->nb_samples; i++) { put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0], @@ -796,6 +863,41 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&pb); break; } + case AV_CODEC_ID_ADPCM_IMA_AMV: + { + av_assert0(avctx->channels == 1); + + c->status[0].prev_sample = *samples; + bytestream_put_le16(&dst, c->status[0].prev_sample); + bytestream_put_byte(&dst, c->status[0].step_index); + bytestream_put_byte(&dst, 0); + bytestream_put_le32(&dst, avctx->frame_size); + + if (avctx->trellis > 0) { + n = frame->nb_samples >> 1; + + if (!(buf = av_malloc(2 * n))) + return AVERROR(ENOMEM); + + adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * n, avctx->channels); + for (i = 0; i < n; i++) + bytestream_put_byte(&dst, (buf[2 * i] << 4) | buf[2 * i + 1]); + + samples += 2 * n; + av_free(buf); + } else for (n = frame->nb_samples >> 1; n > 0; n--) { + int nibble; + nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4; + nibble |= adpcm_ima_compress_sample(&c->status[0], *samples++) & 0x0F; + bytestream_put_byte(&dst, nibble); + } + + if (avctx->frame_size & 1) { + int nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4; + bytestream_put_byte(&dst, nibble); + } + break; + } case AV_CODEC_ID_ADPCM_ARGO: { PutBitContext pb; @@ -834,6 +936,26 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&pb); break; } + case AV_CODEC_ID_ADPCM_IMA_WS: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(avctx->trellis == 0); + for (n = frame->nb_samples / 2; n > 0; n--) { + /* stereo: 1 byte (2 samples) for left, 1 byte for right */ + for (ch = 0; ch < avctx->channels; ch++) { + int t1, t2; + t1 = adpcm_ima_compress_sample(&c->status[ch], *samples++); + t2 = adpcm_ima_compress_sample(&c->status[ch], samples[st]); + put_bits(&pb, 4, t2); + put_bits(&pb, 4, t1); + } + samples += avctx->channels; + } + flush_put_bits(&pb); + break; + } default: return AVERROR(EINVAL); } @@ -857,7 +979,7 @@ static const AVOption options[] = { .help = "set the block size", .offset = offsetof(ADPCMEncodeContext, block_size), .type = AV_OPT_TYPE_INT, - .default_val = {.i64 = BLKSIZE}, + .default_val = {.i64 = 1024}, .min = 32, .max = 8192, /* Is this a reasonable upper limit? */ .flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM @@ -865,15 +987,15 @@ static const AVOption options[] = { { NULL } }; -static const AVClass adpcm_encoder_class = { - .class_name = "ADPCM Encoder", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - #define ADPCM_ENCODER(id_, name_, sample_fmts_, capabilities_, long_name_) \ -AVCodec ff_ ## name_ ## _encoder = { \ +static const AVClass name_ ## _encoder_class = { \ + .class_name = #name_, \ + .item_name = av_default_item_name, \ + .option = options, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; \ + \ +const AVCodec ff_ ## name_ ## _encoder = { \ .name = #name_, \ .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ .type = AVMEDIA_TYPE_AUDIO, \ @@ -884,15 +1006,18 @@ AVCodec ff_ ## name_ ## _encoder = { \ .close = adpcm_encode_close, \ .sample_fmts = sample_fmts_, \ .capabilities = capabilities_, \ - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ - .priv_class = &adpcm_encoder_class, \ + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, \ + .priv_class = &name_ ## _encoder_class, \ } ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO, adpcm_argo, sample_fmts_p, 0, "ADPCM Argonaut Games"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv, sample_fmts, 0, "ADPCM IMA AMV"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_APM, adpcm_ima_apm, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_ALP, adpcm_ima_alp, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA High Voltage Software ALP"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_SSI, adpcm_ima_ssi, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, 0, "ADPCM IMA WAV"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WS, adpcm_ima_ws, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Westwood"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, 0, "ADPCM Microsoft"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, 0, "ADPCM Shockwave Flash"); ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, 0, "ADPCM Yamaha");