mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 20:42:49 +08:00 
			
		
		
		
	ADPCM IMA WAV 2, 3 and 5 bits decoder
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
		| @@ -118,10 +118,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) | |||||||
|         c->status[0].step = c->status[1].step = 511; |         c->status[0].step = c->status[1].step = 511; | ||||||
|         break; |         break; | ||||||
|     case AV_CODEC_ID_ADPCM_IMA_WAV: |     case AV_CODEC_ID_ADPCM_IMA_WAV: | ||||||
|         if (avctx->bits_per_coded_sample != 4) { |         if (avctx->bits_per_coded_sample < 2 || avctx->bits_per_coded_sample > 5) | ||||||
|             av_log(avctx, AV_LOG_ERROR, "Only 4-bit ADPCM IMA WAV files are supported\n"); |             return AVERROR_INVALIDDATA; | ||||||
|             return -1; |  | ||||||
|         } |  | ||||||
|         break; |         break; | ||||||
|     case AV_CODEC_ID_ADPCM_IMA_APC: |     case AV_CODEC_ID_ADPCM_IMA_APC: | ||||||
|         if (avctx->extradata && avctx->extradata_size >= 8) { |         if (avctx->extradata && avctx->extradata_size >= 8) { | ||||||
| @@ -188,6 +186,29 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble, | |||||||
|     return (short)c->predictor; |     return (short)c->predictor; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitContext *gb, int bps) | ||||||
|  | { | ||||||
|  |     int nibble, step_index, predictor, sign, delta, diff, step, shift; | ||||||
|  |  | ||||||
|  |     shift = bps - 1; | ||||||
|  |     nibble = get_bits_le(gb, bps), | ||||||
|  |     step = ff_adpcm_step_table[c->step_index]; | ||||||
|  |     step_index = c->step_index + ff_adpcm_index_tables[bps - 2][nibble]; | ||||||
|  |     step_index = av_clip(step_index, 0, 88); | ||||||
|  |  | ||||||
|  |     sign = nibble & (1 << shift); | ||||||
|  |     delta = nibble & ((1 << shift) - 1); | ||||||
|  |     diff = ((2 * delta + 1) * step) >> shift; | ||||||
|  |     predictor = c->predictor; | ||||||
|  |     if (sign) predictor -= diff; | ||||||
|  |     else predictor += diff; | ||||||
|  |  | ||||||
|  |     c->predictor = av_clip_int16(predictor); | ||||||
|  |     c->step_index = step_index; | ||||||
|  |  | ||||||
|  |     return (int16_t)c->predictor; | ||||||
|  | } | ||||||
|  |  | ||||||
| static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift) | static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift) | ||||||
| { | { | ||||||
|     int step_index; |     int step_index; | ||||||
| @@ -557,10 +578,14 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, | |||||||
|         nb_samples = (buf_size - 4 * ch) * 2 / ch; |         nb_samples = (buf_size - 4 * ch) * 2 / ch; | ||||||
|         break; |         break; | ||||||
|     case AV_CODEC_ID_ADPCM_IMA_WAV: |     case AV_CODEC_ID_ADPCM_IMA_WAV: | ||||||
|  |     { | ||||||
|  |         int bsize = ff_adpcm_ima_block_sizes[avctx->bits_per_coded_sample - 2]; | ||||||
|  |         int bsamples = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2]; | ||||||
|         if (avctx->block_align > 0) |         if (avctx->block_align > 0) | ||||||
|             buf_size = FFMIN(buf_size, avctx->block_align); |             buf_size = FFMIN(buf_size, avctx->block_align); | ||||||
|         nb_samples = 1 + (buf_size - 4 * ch) / (4 * ch) * 8; |         nb_samples = 1 + (buf_size - 4 * ch) / (bsize * ch) * bsamples; | ||||||
|         break; |         break; | ||||||
|  |     } | ||||||
|     case AV_CODEC_ID_ADPCM_MS: |     case AV_CODEC_ID_ADPCM_MS: | ||||||
|         if (avctx->block_align > 0) |         if (avctx->block_align > 0) | ||||||
|             buf_size = FFMIN(buf_size, avctx->block_align); |             buf_size = FFMIN(buf_size, avctx->block_align); | ||||||
| @@ -720,6 +745,23 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (avctx->bits_per_coded_sample != 4) { | ||||||
|  |             int samples_per_block = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2]; | ||||||
|  |             GetBitContext g; | ||||||
|  |  | ||||||
|  |             init_get_bits8(&g, gb.buffer, bytestream2_get_bytes_left(&gb)); | ||||||
|  |             for (n = 0; n < (nb_samples - 1) / samples_per_block; n++) { | ||||||
|  |                 for (i = 0; i < avctx->channels; i++) { | ||||||
|  |                     cs = &c->status[i]; | ||||||
|  |                     samples = &samples_p[i][1 + n * samples_per_block]; | ||||||
|  |                     for (m = 0; m < samples_per_block; m++) { | ||||||
|  |                         samples[m] = adpcm_ima_wav_expand_nibble(cs, &g, | ||||||
|  |                                           avctx->bits_per_coded_sample); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             bytestream2_skip(&gb, avctx->block_align - avctx->channels * 4); | ||||||
|  |         } else { | ||||||
|         for (n = 0; n < (nb_samples - 1) / 8; n++) { |         for (n = 0; n < (nb_samples - 1) / 8; n++) { | ||||||
|             for (i = 0; i < avctx->channels; i++) { |             for (i = 0; i < avctx->channels; i++) { | ||||||
|                 cs = &c->status[i]; |                 cs = &c->status[i]; | ||||||
| @@ -731,6 +773,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case AV_CODEC_ID_ADPCM_4XM: |     case AV_CODEC_ID_ADPCM_4XM: | ||||||
|         for (i = 0; i < avctx->channels; i++) |         for (i = 0; i < avctx->channels; i++) | ||||||
|   | |||||||
| @@ -27,12 +27,33 @@ | |||||||
|  |  | ||||||
| /* ff_adpcm_step_table[] and ff_adpcm_index_table[] are from the ADPCM | /* ff_adpcm_step_table[] and ff_adpcm_index_table[] are from the ADPCM | ||||||
|    reference source */ |    reference source */ | ||||||
| /* This is the index table: */ | static const int8_t adpcm_index_table2[4] = { | ||||||
|  |     -1,  2, | ||||||
|  |     -1,  2, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const int8_t adpcm_index_table3[8] = { | ||||||
|  |     -1, -1,  1,  2, | ||||||
|  |     -1, -1,  1,  2, | ||||||
|  | }; | ||||||
|  |  | ||||||
| const int8_t ff_adpcm_index_table[16] = { | const int8_t ff_adpcm_index_table[16] = { | ||||||
|     -1, -1, -1, -1, 2, 4, 6, 8, |     -1, -1, -1, -1, 2, 4, 6, 8, | ||||||
|     -1, -1, -1, -1, 2, 4, 6, 8, |     -1, -1, -1, -1, 2, 4, 6, 8, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static const int8_t adpcm_index_table5[32] = { | ||||||
|  |     -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16, | ||||||
|  |     -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const int8_t const *ff_adpcm_index_tables[4] = { | ||||||
|  |     &adpcm_index_table2[0], | ||||||
|  |     &adpcm_index_table3[0], | ||||||
|  |     &ff_adpcm_index_table[0], | ||||||
|  |     &adpcm_index_table5[0], | ||||||
|  | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * This is the step table. Note that many programs use slight deviations from |  * This is the step table. Note that many programs use slight deviations from | ||||||
|  * this table, but such deviations are negligible: |  * this table, but such deviations are negligible: | ||||||
|   | |||||||
| @@ -28,6 +28,10 @@ | |||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  |  | ||||||
|  | static const uint8_t ff_adpcm_ima_block_sizes[4]   = {  4, 12, 4, 20 }; | ||||||
|  | static const uint8_t ff_adpcm_ima_block_samples[4] = { 16, 32, 8, 32 }; | ||||||
|  |  | ||||||
|  | extern const int8_t const *ff_adpcm_index_tables[4]; | ||||||
| extern const int8_t  ff_adpcm_index_table[16]; | extern const int8_t  ff_adpcm_index_table[16]; | ||||||
| extern const int16_t ff_adpcm_step_table[89]; | extern const int16_t ff_adpcm_step_table[89]; | ||||||
| extern const int16_t ff_adpcm_oki_step_table[49]; | extern const int16_t ff_adpcm_oki_step_table[49]; | ||||||
|   | |||||||
| @@ -2899,7 +2899,9 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) | |||||||
|                 int blocks = frame_bytes / ba; |                 int blocks = frame_bytes / ba; | ||||||
|                 switch (avctx->codec_id) { |                 switch (avctx->codec_id) { | ||||||
|                 case AV_CODEC_ID_ADPCM_IMA_WAV: |                 case AV_CODEC_ID_ADPCM_IMA_WAV: | ||||||
|                     return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8); |                     if (bps < 2 || bps > 5) | ||||||
|  |                         return 0; | ||||||
|  |                     return blocks * (1 + (ba - 4 * ch) / (bps * ch) * 8); | ||||||
|                 case AV_CODEC_ID_ADPCM_IMA_DK3: |                 case AV_CODEC_ID_ADPCM_IMA_DK3: | ||||||
|                     return blocks * (((ba - 16) * 2 / 3 * 4) / ch); |                     return blocks * (((ba - 16) * 2 / 3 * 4) / ch); | ||||||
|                 case AV_CODEC_ID_ADPCM_IMA_DK4: |                 case AV_CODEC_ID_ADPCM_IMA_DK4: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Paul B Mahol
					Paul B Mahol