This is essentially a MS GSM decoder extension that supports more sampling rates and lower bitrates. Signed-off-by: Anton Khirnov <anton@khirnov.net>tags/n2.2-rc1
| @@ -22,10 +22,24 @@ | |||||
| #define AVCODEC_GSM_H | #define AVCODEC_GSM_H | ||||
| /* bytes per block */ | /* bytes per block */ | ||||
| #define GSM_BLOCK_SIZE 33 | |||||
| #define GSM_MS_BLOCK_SIZE 65 | |||||
| #define GSM_BLOCK_SIZE 33 | |||||
| #define GSM_MS_BLOCK_SIZE 65 | |||||
| #define MSN_MIN_BLOCK_SIZE 41 | |||||
| /* samples per block */ | /* samples per block */ | ||||
| #define GSM_FRAME_SIZE 160 | #define GSM_FRAME_SIZE 160 | ||||
| enum GSMModes { | |||||
| GSM_13000 = 0, | |||||
| MSN_12400, | |||||
| MSN_11800, | |||||
| MSN_11200, | |||||
| MSN_10600, | |||||
| MSN_10000, | |||||
| MSN_9400, | |||||
| MSN_8800, | |||||
| MSN_8200, | |||||
| NUM_GSM_MODES | |||||
| }; | |||||
| #endif /* AVCODEC_GSM_H */ | #endif /* AVCODEC_GSM_H */ | ||||
| @@ -50,7 +50,8 @@ static int gsm_parse(AVCodecParserContext *s1, AVCodecContext *avctx, | |||||
| s->duration = GSM_FRAME_SIZE; | s->duration = GSM_FRAME_SIZE; | ||||
| break; | break; | ||||
| case AV_CODEC_ID_GSM_MS: | case AV_CODEC_ID_GSM_MS: | ||||
| s->block_size = GSM_MS_BLOCK_SIZE; | |||||
| s->block_size = avctx->block_align ? avctx->block_align | |||||
| : GSM_MS_BLOCK_SIZE; | |||||
| s->duration = GSM_FRAME_SIZE * 2; | s->duration = GSM_FRAME_SIZE * 2; | ||||
| break; | break; | ||||
| default: | default: | ||||
| @@ -36,7 +36,8 @@ static av_cold int gsm_init(AVCodecContext *avctx) | |||||
| { | { | ||||
| avctx->channels = 1; | avctx->channels = 1; | ||||
| avctx->channel_layout = AV_CH_LAYOUT_MONO; | avctx->channel_layout = AV_CH_LAYOUT_MONO; | ||||
| avctx->sample_rate = 8000; | |||||
| if (!avctx->sample_rate) | |||||
| avctx->sample_rate = 8000; | |||||
| avctx->sample_fmt = AV_SAMPLE_FMT_S16; | avctx->sample_fmt = AV_SAMPLE_FMT_S16; | ||||
| switch (avctx->codec_id) { | switch (avctx->codec_id) { | ||||
| @@ -46,7 +47,16 @@ static av_cold int gsm_init(AVCodecContext *avctx) | |||||
| break; | break; | ||||
| case AV_CODEC_ID_GSM_MS: | case AV_CODEC_ID_GSM_MS: | ||||
| avctx->frame_size = 2 * GSM_FRAME_SIZE; | avctx->frame_size = 2 * GSM_FRAME_SIZE; | ||||
| avctx->block_align = GSM_MS_BLOCK_SIZE; | |||||
| if (!avctx->block_align) | |||||
| avctx->block_align = GSM_MS_BLOCK_SIZE; | |||||
| else | |||||
| if (avctx->block_align < MSN_MIN_BLOCK_SIZE || | |||||
| avctx->block_align > GSM_MS_BLOCK_SIZE || | |||||
| (avctx->block_align - MSN_MIN_BLOCK_SIZE) % 3) { | |||||
| av_log(avctx, AV_LOG_ERROR, "Invalid block alignment %d\n", | |||||
| avctx->block_align); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -80,12 +90,13 @@ static int gsm_decode_frame(AVCodecContext *avctx, void *data, | |||||
| init_get_bits(&gb, buf, buf_size * 8); | init_get_bits(&gb, buf, buf_size * 8); | ||||
| if (get_bits(&gb, 4) != 0xd) | if (get_bits(&gb, 4) != 0xd) | ||||
| av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n"); | av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n"); | ||||
| res = gsm_decode_block(avctx, samples, &gb); | |||||
| res = gsm_decode_block(avctx, samples, &gb, GSM_13000); | |||||
| if (res < 0) | if (res < 0) | ||||
| return res; | return res; | ||||
| break; | break; | ||||
| case AV_CODEC_ID_GSM_MS: | case AV_CODEC_ID_GSM_MS: | ||||
| res = ff_msgsm_decode_block(avctx, samples, buf); | |||||
| res = ff_msgsm_decode_block(avctx, samples, buf, | |||||
| (GSM_MS_BLOCK_SIZE - avctx->block_align) / 3); | |||||
| if (res < 0) | if (res < 0) | ||||
| return res; | return res; | ||||
| } | } | ||||
| @@ -92,3 +92,29 @@ const int16_t ff_gsm_dequant_tab[64][8] = { | |||||
| {-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879}, | {-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879}, | ||||
| {-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671} | {-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671} | ||||
| }; | }; | ||||
| static const int apcm_bits[11][13] = { | |||||
| { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | |||||
| { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 }, | |||||
| { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 }, | |||||
| { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }, | |||||
| { 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 }, | |||||
| { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, | |||||
| { 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, | |||||
| { 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, | |||||
| { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, | |||||
| { 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, | |||||
| { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 } | |||||
| }; | |||||
| const int* const ff_gsm_apcm_bits[][4] = { | |||||
| { apcm_bits[10], apcm_bits[10], apcm_bits[10], apcm_bits[10] }, // 13000 | |||||
| { apcm_bits[10], apcm_bits[10], apcm_bits[10], apcm_bits[ 6] }, // 12400 | |||||
| { apcm_bits[10], apcm_bits[10], apcm_bits[ 7], apcm_bits[ 5] }, // 11800 | |||||
| { apcm_bits[10], apcm_bits[ 8], apcm_bits[ 5], apcm_bits[ 5] }, // 11200 | |||||
| { apcm_bits[ 9], apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 5] }, // 10600 | |||||
| { apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 1] }, // 10000 | |||||
| { apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 2], apcm_bits[ 0] }, // 9400 | |||||
| { apcm_bits[ 5], apcm_bits[ 3], apcm_bits[ 0], apcm_bits[ 0] }, // 8800 | |||||
| { apcm_bits[ 4], apcm_bits[ 0], apcm_bits[ 0], apcm_bits[ 0] }, // 8200 | |||||
| }; | |||||
| @@ -40,4 +40,6 @@ typedef struct GSMContext { | |||||
| extern const uint16_t ff_gsm_long_term_gain_tab[4]; | extern const uint16_t ff_gsm_long_term_gain_tab[4]; | ||||
| extern const int16_t ff_gsm_dequant_tab[64][8]; | extern const int16_t ff_gsm_dequant_tab[64][8]; | ||||
| extern const int* const ff_gsm_apcm_bits[][4]; | |||||
| #endif /* AVCODEC_GSMDEC_DATA_H */ | #endif /* AVCODEC_GSMDEC_DATA_H */ | ||||
| @@ -28,13 +28,22 @@ | |||||
| #include "gsm.h" | #include "gsm.h" | ||||
| #include "gsmdec_data.h" | #include "gsmdec_data.h" | ||||
| static void apcm_dequant_add(GetBitContext *gb, int16_t *dst) | |||||
| static const int requant_tab[4][8] = { | |||||
| { 0 }, | |||||
| { 0, 7 }, | |||||
| { 0, 2, 5, 7 }, | |||||
| { 0, 1, 2, 3, 4, 5, 6, 7 } | |||||
| }; | |||||
| static void apcm_dequant_add(GetBitContext *gb, int16_t *dst, const int *frame_bits) | |||||
| { | { | ||||
| int i; | |||||
| int i, val; | |||||
| int maxidx = get_bits(gb, 6); | int maxidx = get_bits(gb, 6); | ||||
| const int16_t *tab = ff_gsm_dequant_tab[maxidx]; | const int16_t *tab = ff_gsm_dequant_tab[maxidx]; | ||||
| for (i = 0; i < 13; i++) | |||||
| dst[3*i] += tab[get_bits(gb, 3)]; | |||||
| for (i = 0; i < 13; i++) { | |||||
| val = get_bits(gb, frame_bits[i]); | |||||
| dst[3*i] += tab[requant_tab[frame_bits[i]][val]]; | |||||
| } | |||||
| } | } | ||||
| static inline int gsm_mult(int a, int b) | static inline int gsm_mult(int a, int b) | ||||
| @@ -118,7 +127,7 @@ static int postprocess(int16_t *data, int msr) | |||||
| } | } | ||||
| static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples, | static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples, | ||||
| GetBitContext *gb) | |||||
| GetBitContext *gb, int mode) | |||||
| { | { | ||||
| GSMContext *ctx = avctx->priv_data; | GSMContext *ctx = avctx->priv_data; | ||||
| int i; | int i; | ||||
| @@ -139,7 +148,7 @@ static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples, | |||||
| int offset = get_bits(gb, 2); | int offset = get_bits(gb, 2); | ||||
| lag = av_clip(lag, 40, 120); | lag = av_clip(lag, 40, 120); | ||||
| long_term_synth(ref_dst, lag, gain_idx); | long_term_synth(ref_dst, lag, gain_idx); | ||||
| apcm_dequant_add(gb, ref_dst + offset); | |||||
| apcm_dequant_add(gb, ref_dst + offset, ff_gsm_apcm_bits[mode][i]); | |||||
| ref_dst += 40; | ref_dst += 40; | ||||
| } | } | ||||
| memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf)); | memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf)); | ||||
| @@ -26,13 +26,13 @@ | |||||
| #include "gsmdec_template.c" | #include "gsmdec_template.c" | ||||
| int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, | int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, | ||||
| const uint8_t *buf) | |||||
| const uint8_t *buf, int mode) | |||||
| { | { | ||||
| int res; | int res; | ||||
| GetBitContext gb; | GetBitContext gb; | ||||
| init_get_bits(&gb, buf, GSM_MS_BLOCK_SIZE * 8); | init_get_bits(&gb, buf, GSM_MS_BLOCK_SIZE * 8); | ||||
| res = gsm_decode_block(avctx, samples, &gb); | |||||
| res = gsm_decode_block(avctx, samples, &gb, mode); | |||||
| if (res < 0) | if (res < 0) | ||||
| return res; | return res; | ||||
| return gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb); | |||||
| return gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb, mode); | |||||
| } | } | ||||
| @@ -25,6 +25,6 @@ | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, | int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, | ||||
| const uint8_t *buf); | |||||
| const uint8_t *buf, int mode); | |||||
| #endif /* AVCODEC_MSGSMDEC_H */ | #endif /* AVCODEC_MSGSMDEC_H */ | ||||
| @@ -338,6 +338,7 @@ const AVCodecTag ff_codec_wav_tags[] = { | |||||
| { AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 }, | { AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 }, | ||||
| { AV_CODEC_ID_TRUESPEECH, 0x0022 }, | { AV_CODEC_ID_TRUESPEECH, 0x0022 }, | ||||
| { AV_CODEC_ID_GSM_MS, 0x0031 }, | { AV_CODEC_ID_GSM_MS, 0x0031 }, | ||||
| { AV_CODEC_ID_GSM_MS, 0x0032 }, | |||||
| { AV_CODEC_ID_ADPCM_G726, 0x0045 }, | { AV_CODEC_ID_ADPCM_G726, 0x0045 }, | ||||
| { AV_CODEC_ID_MP2, 0x0050 }, | { AV_CODEC_ID_MP2, 0x0050 }, | ||||
| { AV_CODEC_ID_MP3, 0x0055 }, | { AV_CODEC_ID_MP3, 0x0055 }, | ||||