| @@ -78,7 +78,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) · 77 unmodified lines |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | if (avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_SSI || |
| 81 | | − avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_APM) { |
| 81 | + avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_APM || |
| 82 | + avctx->codec->id == AV_CODEC_ID_ADPCM_ARGO) { |
| 82 | 83 | /* |
| 83 | 84 | * The current trellis implementation doesn't work for extended |
| 84 | 85 | * runs of samples without periodic resets. Disallow it. |
| @@ -156,6 +157,10 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) · 71 unmodified lines |
| 156 | 157 | return AVERROR(ENOMEM); |
| 157 | 158 | avctx->extradata_size = 28; |
| 158 | 159 | break; |
| 160 | + case AV_CODEC_ID_ADPCM_ARGO: |
| 161 | + avctx->frame_size = 32; |
| 162 | + avctx->block_align = 17 * avctx->channels; |
| 163 | + break; |
| 159 | 164 | default: |
| 160 | 165 | return AVERROR(EINVAL); |
| 161 | 166 | } |
| @@ -481,6 +486,46 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, · 319 unmodified lines |
| 481 | 486 | c->idelta = nodes[0]->step; |
| 482 | 487 | } |
| 483 | 488 | |
| 489 | +static inline int adpcm_argo_compress_nibble(const ADPCMChannelStatus *cs, int16_t s, |
| 490 | + int shift, int flag) |
| 491 | +{ |
| 492 | + int nibble; |
| 493 | + |
| 494 | + if (flag) |
| 495 | + nibble = 4 * s - 8 * cs->sample1 + 4 * cs->sample2; |
| 496 | + else |
| 497 | + nibble = 4 * s - 4 * cs->sample1; |
| 498 | + |
| 499 | + return (nibble >> shift) & 0x0F; |
| 500 | +} |
| 501 | + |
| 502 | +static int64_t adpcm_argo_compress_block(ADPCMChannelStatus *cs, PutBitContext *pb, |
| 503 | + const int16_t *samples, int nsamples, |
| 504 | + int shift, int flag) |
| 505 | +{ |
| 506 | + int64_t error = 0; |
| 507 | + |
| 508 | + if (pb) { |
| 509 | + put_bits(pb, 4, shift - 2); |
| 510 | + put_bits(pb, 1, 0); |
| 511 | + put_bits(pb, 1, !!flag); |
| 512 | + put_bits(pb, 2, 0); |
| 513 | + } |
| 514 | + |
| 515 | + for (int n = 0; n < nsamples; n++) { |
| 516 | + /* Compress the nibble, then expand it to see how much precision we've lost. */ |
| 517 | + int nibble = adpcm_argo_compress_nibble(cs, samples[n], shift, flag); |
| 518 | + int16_t sample = ff_adpcm_argo_expand_nibble(cs, nibble, shift, flag); |
| 519 | + |
| 520 | + error += abs(samples[n] - sample); |
| 521 | + |
| 522 | + if (pb) |
| 523 | + put_bits(pb, 4, nibble); |
| 524 | + } |
| 525 | + |
| 526 | + return error; |
| 527 | +} |
| 528 | + |
| 484 | 529 | static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, |
| 485 | 530 | const AVFrame *frame, int *got_packet_ptr) |
| 486 | 531 | { |
| @@ -741,6 +786,44 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 254 unmodified lines |
| 741 | 786 | flush_put_bits(&pb); |
| 742 | 787 | break; |
| 743 | 788 | } |
| 789 | + case AV_CODEC_ID_ADPCM_ARGO: |
| 790 | + { |
| 791 | + PutBitContext pb; |
| 792 | + init_put_bits(&pb, dst, pkt_size); |
| 793 | + |
| 794 | + av_assert0(frame->nb_samples == 32); |
| 795 | + |
| 796 | + for (ch = 0; ch < avctx->channels; ch++) { |
| 797 | + int64_t error = INT64_MAX, tmperr = INT64_MAX; |
| 798 | + int shift = 2, flag = 0; |
| 799 | + int saved1 = c->status[ch].sample1; |
| 800 | + int saved2 = c->status[ch].sample2; |
| 801 | + |
| 802 | + /* Find the optimal coefficients, bail early if we find a perfect result. */ |
| 803 | + for (int s = 2; s < 18 && tmperr != 0; s++) { |
| 804 | + for (int f = 0; f < 2 && tmperr != 0; f++) { |
| 805 | + c->status[ch].sample1 = saved1; |
| 806 | + c->status[ch].sample2 = saved2; |
| 807 | + tmperr = adpcm_argo_compress_block(c->status + ch, NULL, samples_p[ch], |
| 808 | + frame->nb_samples, s, f); |
| 809 | + if (tmperr < error) { |
| 810 | + shift = s; |
| 811 | + flag = f; |
| 812 | + error = tmperr; |
| 813 | + } |
| 814 | + } |
| 815 | + } |
| 816 | + |
| 817 | + /* Now actually do the encode. */ |
| 818 | + c->status[ch].sample1 = saved1; |
| 819 | + c->status[ch].sample2 = saved2; |
| 820 | + adpcm_argo_compress_block(c->status + ch, &pb, samples_p[ch], |
| 821 | + frame->nb_samples, shift, flag); |
| 822 | + } |
| 823 | + |
| 824 | + flush_put_bits(&pb); |
| 825 | + break; |
| 826 | + } |
| 744 | 827 | default: |
| 745 | 828 | return AVERROR(EINVAL); |
| 746 | 829 | } |
| @@ -773,6 +856,7 @@ AVCodec ff_ ## name_ ## _encoder = { \ · 26 unmodified lines |
| 773 | 856 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ |
| 774 | 857 | } |
| 775 | 858 | |
| 859 | +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO, adpcm_argo, sample_fmts_p, 0, "ADPCM Argonaut Games"); |
| 776 | 860 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_APM, adpcm_ima_apm, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM"); |
| 777 | 861 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime"); |
| 778 | 862 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_SSI, adpcm_ima_ssi, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive"); |