| @@ -78,7 +78,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) · 77 unmodified lines |
| 78 | } | 78 | } |
| 79 | | 79 | |
| 80 | if (avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_SSI || | 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 | * The current trellis implementation doesn't work for extended | 84 | * The current trellis implementation doesn't work for extended |
| 84 | * runs of samples without periodic resets. Disallow it. | 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 | return AVERROR(ENOMEM); | 157 | return AVERROR(ENOMEM); |
| 157 | avctx->extradata_size = 28; | 158 | avctx->extradata_size = 28; |
| 158 | break; | 159 | break; |
| | 160 | case AV_CODEC_ID_ADPCM_ARGO: |
| | 161 | avctx->frame_size = 32; |
| | 162 | avctx->block_align = 17 * avctx->channels; |
| | 163 | break; |
| 159 | default: | 164 | default: |
| 160 | return AVERROR(EINVAL); | 165 | return AVERROR(EINVAL); |
| 161 | } | 166 | } |
| @@ -481,6 +486,46 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, · 319 unmodified lines |
| 481 | c->idelta = nodes[0]->step; | 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 | static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, | 529 | static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, |
| 485 | const AVFrame *frame, int *got_packet_ptr) | 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 | flush_put_bits(&pb); | 786 | flush_put_bits(&pb); |
| 742 | break; | 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 | default: | 827 | default: |
| 745 | return AVERROR(EINVAL); | 828 | return AVERROR(EINVAL); |
| 746 | } | 829 | } |
| @@ -773,6 +856,7 @@ AVCodec ff_ ## name_ ## _encoder = { \ · 26 unmodified lines |
| 773 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ | 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 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_APM, adpcm_ima_apm, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM"); | 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 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime"); | 861 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime"); |
| 778 | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_SSI, adpcm_ima_ssi, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive"); | 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"); |