|  | @@ -78,7 +78,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if (avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_SSI || |  |  | 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_IMA_APM || | 
														
													
														
															
																|  |  |  |  |  | avctx->codec->id == AV_CODEC_ID_ADPCM_ARGO) { | 
														
													
														
															
																|  |  | /* |  |  | /* | 
														
													
														
															
																|  |  | * The current trellis implementation doesn't work for extended |  |  | * The current trellis implementation doesn't work for extended | 
														
													
														
															
																|  |  | * runs of samples without periodic resets. Disallow it. |  |  | * runs of samples without periodic resets. Disallow it. | 
														
													
												
													
														
															
																|  | @@ -156,6 +157,10 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) | 
														
													
														
															
																|  |  | return AVERROR(ENOMEM); |  |  | return AVERROR(ENOMEM); | 
														
													
														
															
																|  |  | avctx->extradata_size = 28; |  |  | avctx->extradata_size = 28; | 
														
													
														
															
																|  |  | break; |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | case AV_CODEC_ID_ADPCM_ARGO: | 
														
													
														
															
																|  |  |  |  |  | avctx->frame_size = 32; | 
														
													
														
															
																|  |  |  |  |  | avctx->block_align = 17 * avctx->channels; | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  | default: |  |  | default: | 
														
													
														
															
																|  |  | return AVERROR(EINVAL); |  |  | return AVERROR(EINVAL); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
												
													
														
															
																|  | @@ -481,6 +486,46 @@ static void adpcm_compress_trellis(AVCodecContext *avctx, | 
														
													
														
															
																|  |  | c->idelta     = nodes[0]->step; |  |  | c->idelta     = nodes[0]->step; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | static inline int adpcm_argo_compress_nibble(const ADPCMChannelStatus *cs, int16_t s, | 
														
													
														
															
																|  |  |  |  |  | int shift, int flag) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | int nibble; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (flag) | 
														
													
														
															
																|  |  |  |  |  | nibble = 4 * s - 8 * cs->sample1 + 4 * cs->sample2; | 
														
													
														
															
																|  |  |  |  |  | else | 
														
													
														
															
																|  |  |  |  |  | nibble = 4 * s - 4 * cs->sample1; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | return (nibble >> shift) & 0x0F; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | static int64_t adpcm_argo_compress_block(ADPCMChannelStatus *cs, PutBitContext *pb, | 
														
													
														
															
																|  |  |  |  |  | const int16_t *samples, int nsamples, | 
														
													
														
															
																|  |  |  |  |  | int shift, int flag) | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | int64_t error = 0; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (pb) { | 
														
													
														
															
																|  |  |  |  |  | put_bits(pb, 4, shift - 2); | 
														
													
														
															
																|  |  |  |  |  | put_bits(pb, 1, 0); | 
														
													
														
															
																|  |  |  |  |  | put_bits(pb, 1, !!flag); | 
														
													
														
															
																|  |  |  |  |  | put_bits(pb, 2, 0); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | for (int n = 0; n < nsamples; n++) { | 
														
													
														
															
																|  |  |  |  |  | /* Compress the nibble, then expand it to see how much precision we've lost. */ | 
														
													
														
															
																|  |  |  |  |  | int nibble = adpcm_argo_compress_nibble(cs, samples[n], shift, flag); | 
														
													
														
															
																|  |  |  |  |  | int16_t sample = ff_adpcm_argo_expand_nibble(cs, nibble, shift, flag); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | error += abs(samples[n] - sample); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | if (pb) | 
														
													
														
															
																|  |  |  |  |  | put_bits(pb, 4, nibble); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | return error; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  | static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, |  |  | static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, | 
														
													
														
															
																|  |  | const AVFrame *frame, int *got_packet_ptr) |  |  | const AVFrame *frame, int *got_packet_ptr) | 
														
													
														
															
																|  |  | { |  |  | { | 
														
													
												
													
														
															
																|  | @@ -741,6 +786,44 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, | 
														
													
														
															
																|  |  | flush_put_bits(&pb); |  |  | flush_put_bits(&pb); | 
														
													
														
															
																|  |  | break; |  |  | break; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  | case AV_CODEC_ID_ADPCM_ARGO: | 
														
													
														
															
																|  |  |  |  |  | { | 
														
													
														
															
																|  |  |  |  |  | PutBitContext pb; | 
														
													
														
															
																|  |  |  |  |  | init_put_bits(&pb, dst, pkt_size); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | av_assert0(frame->nb_samples == 32); | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | for (ch = 0; ch < avctx->channels; ch++) { | 
														
													
														
															
																|  |  |  |  |  | int64_t error  = INT64_MAX, tmperr = INT64_MAX; | 
														
													
														
															
																|  |  |  |  |  | int     shift  = 2, flag = 0; | 
														
													
														
															
																|  |  |  |  |  | int     saved1 = c->status[ch].sample1; | 
														
													
														
															
																|  |  |  |  |  | int     saved2 = c->status[ch].sample2; | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | /* Find the optimal coefficients, bail early if we find a perfect result. */ | 
														
													
														
															
																|  |  |  |  |  | for (int s = 2; s < 18 && tmperr != 0; s++) { | 
														
													
														
															
																|  |  |  |  |  | for (int f = 0; f < 2 && tmperr != 0; f++) { | 
														
													
														
															
																|  |  |  |  |  | c->status[ch].sample1 = saved1; | 
														
													
														
															
																|  |  |  |  |  | c->status[ch].sample2 = saved2; | 
														
													
														
															
																|  |  |  |  |  | tmperr = adpcm_argo_compress_block(c->status + ch, NULL, samples_p[ch], | 
														
													
														
															
																|  |  |  |  |  | frame->nb_samples, s, f); | 
														
													
														
															
																|  |  |  |  |  | if (tmperr < error) { | 
														
													
														
															
																|  |  |  |  |  | shift = s; | 
														
													
														
															
																|  |  |  |  |  | flag  = f; | 
														
													
														
															
																|  |  |  |  |  | error = tmperr; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | /* Now actually do the encode. */ | 
														
													
														
															
																|  |  |  |  |  | c->status[ch].sample1 = saved1; | 
														
													
														
															
																|  |  |  |  |  | c->status[ch].sample2 = saved2; | 
														
													
														
															
																|  |  |  |  |  | adpcm_argo_compress_block(c->status + ch, &pb, samples_p[ch], | 
														
													
														
															
																|  |  |  |  |  | frame->nb_samples, shift, flag); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | flush_put_bits(&pb); | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | default: |  |  | default: | 
														
													
														
															
																|  |  | return AVERROR(EINVAL); |  |  | return AVERROR(EINVAL); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
												
													
														
															
																|  | @@ -773,6 +856,7 @@ AVCodec ff_ ## name_ ## _encoder = {                                       \ | 
														
													
														
															
																|  |  | .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,                           \ |  |  | .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,                           \ | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO,    adpcm_argo,    sample_fmts_p, 0,                             "ADPCM Argonaut Games"); | 
														
													
														
															
																|  |  | 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_APM, adpcm_ima_apm, sample_fmts,   AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM"); | 
														
													
														
															
																|  |  | 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_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_SSI, adpcm_ima_ssi, sample_fmts,   AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive"); | 
														
													
												
													
														
															
																|  | 
 |