1034 lines · 38.8 KB · C
RawDownload
/* * Copyright (c) 2001-2003 The FFmpeg project * * first version by Francois Revol (revol@free.fr) * fringe ADPCM codecs (e.g., DK3, DK4, Westwood) *   by Mike Melanson (melanson@pcisys.net) * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config_components.h" #include "libavutil/mem.h"#include "libavutil/opt.h" #include "avcodec.h"#include "put_bits.h"#include "bytestream.h"#include "adpcm.h"#include "adpcm_data.h"#include "codec_internal.h"#include "encode.h" /** * @file * ADPCM encoders * See ADPCM decoder reference documents for codec information. */ #define CASE_0(codec_id, ...)#define CASE_1(codec_id, ...) \    case codec_id:            \    { __VA_ARGS__ }           \    break;#define CASE_2(enabled, codec_id, ...) \        CASE_ ## enabled(codec_id, __VA_ARGS__)#define CASE_3(config, codec_id, ...) \        CASE_2(config, codec_id, __VA_ARGS__)#define CASE(codec, ...) \        CASE_3(CONFIG_ ## codec ## _ENCODER, AV_CODEC_ID_ ## codec, __VA_ARGS__) typedef struct TrellisPath {    int nibble;    int prev;} TrellisPath; typedef struct TrellisNode {    uint32_t ssd;    int path;    int sample1;    int sample2;    int step;} TrellisNode; typedef struct ADPCMEncodeContext {    AVClass *class;    int block_size;     ADPCMChannelStatus status[6];    TrellisPath *paths;    TrellisNode *node_buf;    TrellisNode **nodep_buf;    uint8_t *trellis_hash;} ADPCMEncodeContext; #define FREEZE_INTERVAL 128 static av_cold int adpcm_encode_init(AVCodecContext *avctx){    ADPCMEncodeContext *s = avctx->priv_data;    int channels = avctx->ch_layout.nb_channels;     /*     * AMV's block size has to match that of the corresponding video     * stream. Relax the POT requirement.     */    if (avctx->codec->id != AV_CODEC_ID_ADPCM_IMA_AMV &&        (s->block_size & (s->block_size - 1))) {        av_log(avctx, AV_LOG_ERROR, "block size must be power of 2\n");        return AVERROR(EINVAL);    }     if (avctx->trellis) {        int frontier, max_paths;         if ((unsigned)avctx->trellis > 16U) {            av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n");            return AVERROR(EINVAL);        }         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_ARGO    ||            avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_WS) {            /*             * The current trellis implementation doesn't work for extended             * runs of samples without periodic resets. Disallow it.             */            av_log(avctx, AV_LOG_ERROR, "trellis not supported\n");            return AVERROR_PATCHWELCOME;        }         frontier  = 1 << avctx->trellis;        max_paths =  frontier * FREEZE_INTERVAL;        if (!FF_ALLOC_TYPED_ARRAY(s->paths,        max_paths)    ||            !FF_ALLOC_TYPED_ARRAY(s->node_buf,     2 * frontier) ||            !FF_ALLOC_TYPED_ARRAY(s->nodep_buf,    2 * frontier) ||            !FF_ALLOC_TYPED_ARRAY(s->trellis_hash, 65536))            return AVERROR(ENOMEM);    }     avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id);     switch (avctx->codec->id) {    CASE(ADPCM_IMA_WAV,        /* each 16 bits sample gives one nibble           and we have 4 bytes per channel overhead */        avctx->frame_size = (s->block_size - 4 * channels) * 8 /                            (4 * channels) + 1;        /* seems frame_size isn't taken into account...           have to buffer the samples :-( */        avctx->block_align = s->block_size;        avctx->bits_per_coded_sample = 4;        ) /* End of CASE */    CASE(ADPCM_IMA_QT,        avctx->frame_size  = 64;        avctx->block_align = 34 * channels;        ) /* End of CASE */    CASE(ADPCM_MS,        uint8_t *extradata;        /* each 16 bits sample gives one nibble           and we have 7 bytes per channel overhead */        avctx->frame_size = (s->block_size - 7 * channels) * 2 / channels + 2;        avctx->bits_per_coded_sample = 4;        avctx->block_align     = s->block_size;        if (!(avctx->extradata = av_malloc(32 + AV_INPUT_BUFFER_PADDING_SIZE)))            return AVERROR(ENOMEM);        avctx->extradata_size = 32;        extradata = avctx->extradata;        bytestream_put_le16(&extradata, avctx->frame_size);        bytestream_put_le16(&extradata, 7); /* wNumCoef */        for (int i = 0; i < 7; i++) {            bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff1[i] * 4);            bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff2[i] * 4);        }        ) /* End of CASE */    CASE(ADPCM_YAMAHA,        avctx->frame_size  = s->block_size * 2 / channels;        avctx->block_align = s->block_size;        ) /* End of CASE */    CASE(ADPCM_SWF,        if (avctx->sample_rate != 11025 &&            avctx->sample_rate != 22050 &&            avctx->sample_rate != 44100) {            av_log(avctx, AV_LOG_ERROR, "Sample rate must be 11025, "                   "22050 or 44100\n");            return AVERROR(EINVAL);        }        avctx->frame_size  = 4096; /* Hardcoded according to the SWF spec. */        avctx->block_align = (2 + channels * (22 + 4 * (avctx->frame_size - 1)) + 7) / 8;        ) /* End of CASE */    case AV_CODEC_ID_ADPCM_IMA_SSI:    case AV_CODEC_ID_ADPCM_IMA_ALP:        avctx->frame_size  = s->block_size * 2 / channels;        avctx->block_align = s->block_size;        break;    CASE(ADPCM_IMA_AMV,        if (avctx->sample_rate != 22050) {            av_log(avctx, AV_LOG_ERROR, "Sample rate must be 22050\n");            return AVERROR(EINVAL);        }         if (channels != 1) {            av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n");            return AVERROR(EINVAL);        }         avctx->frame_size  = s->block_size;        avctx->block_align = 8 + (FFALIGN(avctx->frame_size, 2) / 2);        ) /* End of CASE */    CASE(ADPCM_IMA_APM,        avctx->frame_size  = s->block_size * 2 / channels;        avctx->block_align = s->block_size;         if (!(avctx->extradata = av_mallocz(28 + AV_INPUT_BUFFER_PADDING_SIZE)))            return AVERROR(ENOMEM);        avctx->extradata_size = 28;        ) /* End of CASE */    CASE(ADPCM_ARGO,        avctx->frame_size = 32;        avctx->block_align = 17 * channels;        ) /* End of CASE */    CASE(ADPCM_IMA_WS,        /* each 16 bits sample gives one nibble */        avctx->frame_size = s->block_size * 2 / channels;        avctx->block_align = s->block_size;        ) /* End of CASE */    default:        return AVERROR(EINVAL);    }     return 0;} static av_cold int adpcm_encode_close(AVCodecContext *avctx){    ADPCMEncodeContext *s = avctx->priv_data;    av_freep(&s->paths);    av_freep(&s->node_buf);    av_freep(&s->nodep_buf);    av_freep(&s->trellis_hash);     return 0;}  static inline uint8_t adpcm_ima_compress_sample(ADPCMChannelStatus *c,                                                int16_t sample){    int delta  = sample - c->prev_sample;    int nibble = FFMIN(7, abs(delta) * 4 /                       ff_adpcm_step_table[c->step_index]) + (delta < 0) * 8;    c->prev_sample += ((ff_adpcm_step_table[c->step_index] *                        ff_adpcm_yamaha_difflookup[nibble]) / 8);    c->prev_sample = av_clip_int16(c->prev_sample);    c->step_index  = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);    return nibble;} static inline uint8_t adpcm_ima_alp_compress_sample(ADPCMChannelStatus *c, int16_t sample){    const int delta  = sample - c->prev_sample;    const int step   = ff_adpcm_step_table[c->step_index];    const int sign   = (delta < 0) * 8;     int nibble = FFMIN(abs(delta) * 4 / step, 7);    int diff   = (step * nibble) >> 2;    if (sign)        diff = -diff;     nibble = sign | nibble;     c->prev_sample += diff;    c->prev_sample  = av_clip_int16(c->prev_sample);    c->step_index   = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);    return nibble;} static inline uint8_t adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c,                                                   int16_t sample){    int delta  = sample - c->prev_sample;    int diff, step = ff_adpcm_step_table[c->step_index];    int nibble = 8*(delta < 0);     delta= abs(delta);    diff = delta + (step >> 3);     if (delta >= step) {        nibble |= 4;        delta  -= step;    }    step >>= 1;    if (delta >= step) {        nibble |= 2;        delta  -= step;    }    step >>= 1;    if (delta >= step) {        nibble |= 1;        delta  -= step;    }    diff -= delta;     if (nibble & 8)        c->prev_sample -= diff;    else        c->prev_sample += diff;     c->prev_sample = av_clip_int16(c->prev_sample);    c->step_index  = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88);     return nibble;} static inline uint8_t adpcm_ms_compress_sample(ADPCMChannelStatus *c,                                               int16_t sample){    int predictor, nibble, bias;     predictor = (((c->sample1) * (c->coeff1)) +                (( c->sample2) * (c->coeff2))) / 64;     nibble = sample - predictor;    if (nibble >= 0)        bias =  c->idelta / 2;    else        bias = -c->idelta / 2;     nibble = (nibble + bias) / c->idelta;    nibble = av_clip_intp2(nibble, 3) & 0x0F;     predictor += ((nibble & 0x08) ? (nibble - 0x10) : nibble) * c->idelta;     c->sample2 = c->sample1;    c->sample1 = av_clip_int16(predictor);     c->idelta = (ff_adpcm_AdaptationTable[nibble] * c->idelta) >> 8;    if (c->idelta < 16)        c->idelta = 16;     return nibble;} static inline uint8_t adpcm_yamaha_compress_sample(ADPCMChannelStatus *c,                                                   int16_t sample){    int nibble, delta;     if (!c->step) {        c->predictor = 0;        c->step      = 127;    }     delta = sample - c->predictor;     nibble = FFMIN(7, abs(delta) * 4 / c->step) + (delta < 0) * 8;     c->predictor += ((c->step * ff_adpcm_yamaha_difflookup[nibble]) / 8);    c->predictor = av_clip_int16(c->predictor);    c->step = (c->step * ff_adpcm_yamaha_indexscale[nibble]) >> 8;    c->step = av_clip(c->step, 127, 24576);     return nibble;} static void adpcm_compress_trellis(AVCodecContext *avctx,                                   const int16_t *samples, uint8_t *dst,                                   ADPCMChannelStatus *c, int n, int stride){    //FIXME 6% faster if frontier is a compile-time constant    ADPCMEncodeContext *s = avctx->priv_data;    const int frontier = 1 << avctx->trellis;    const int version  = avctx->codec->id;    TrellisPath *paths       = s->paths, *p;    TrellisNode *node_buf    = s->node_buf;    TrellisNode **nodep_buf  = s->nodep_buf;    TrellisNode **nodes      = nodep_buf; // nodes[] is always sorted by .ssd    TrellisNode **nodes_next = nodep_buf + frontier;    int pathn = 0, froze = -1, i, j, k, generation = 0;    uint8_t *hash = s->trellis_hash;    memset(hash, 0xff, 65536 * sizeof(*hash));     memset(nodep_buf, 0, 2 * frontier * sizeof(*nodep_buf));    nodes[0]          = node_buf + frontier;    nodes[0]->ssd     = 0;    nodes[0]->path    = 0;    nodes[0]->step    = c->step_index;    nodes[0]->sample1 = c->sample1;    nodes[0]->sample2 = c->sample2;    if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||        version == AV_CODEC_ID_ADPCM_IMA_QT  ||        version == AV_CODEC_ID_ADPCM_IMA_AMV ||        version == AV_CODEC_ID_ADPCM_SWF)        nodes[0]->sample1 = c->prev_sample;    if (version == AV_CODEC_ID_ADPCM_MS)        nodes[0]->step = c->idelta;    if (version == AV_CODEC_ID_ADPCM_YAMAHA) {        if (c->step == 0) {            nodes[0]->step    = 127;            nodes[0]->sample1 = 0;        } else {            nodes[0]->step    = c->step;            nodes[0]->sample1 = c->predictor;        }    }     for (i = 0; i < n; i++) {        TrellisNode *t = node_buf + frontier*(i&1);        TrellisNode **u;        int sample   = samples[i * stride];        int heap_pos = 0;        memset(nodes_next, 0, frontier * sizeof(TrellisNode*));        for (j = 0; j < frontier && nodes[j]; j++) {            // higher j have higher ssd already, so they're likely            // to yield a suboptimal next sample too            const int range = (j < frontier / 2) ? 1 : 0;            const int step  = nodes[j]->step;            int nidx;            if (version == AV_CODEC_ID_ADPCM_MS) {                const int predictor = ((nodes[j]->sample1 * c->coeff1) +                                       (nodes[j]->sample2 * c->coeff2)) / 64;                const int div  = (sample - predictor) / step;                const int nmin = av_clip(div-range, -8, 6);                const int nmax = av_clip(div+range, -7, 7);                for (nidx = nmin; nidx <= nmax; nidx++) {                    const int nibble = nidx & 0xf;                    int dec_sample   = predictor + nidx * step;#define STORE_NODE(NAME, STEP_INDEX)\                    int d;\                    uint32_t ssd;\                    int pos;\                    TrellisNode *u;\                    uint8_t *h;\                    dec_sample = av_clip_int16(dec_sample);\                    d = sample - dec_sample;\                    ssd = nodes[j]->ssd + d*(unsigned)d;\                    /* Check for wraparound, skip such samples completely. \                     * Note, changing ssd to a 64 bit variable would be \                     * simpler, avoiding this check, but it's slower on \                     * x86 32 bit at the moment. */\                    if (ssd < nodes[j]->ssd)\                        goto next_##NAME;\                    /* Collapse any two states with the same previous sample value. \                     * One could also distinguish states by step and by 2nd to last                     * sample, but the effects of that are negligible.                     * Since nodes in the previous generation are iterated                     * through a heap, they're roughly ordered from better to                     * worse, but not strictly ordered. Therefore, an earlier                     * node with the same sample value is better in most cases                     * (and thus the current is skipped), but not strictly                     * in all cases. Only skipping samples where ssd >=                     * ssd of the earlier node with the same sample gives                     * slightly worse quality, though, for some reason. */ \                    h = &hash[(uint16_t) dec_sample];\                    if (*h == generation)\                        goto next_##NAME;\                    if (heap_pos < frontier) {\                        pos = heap_pos++;\                    } else {\                        /* Try to replace one of the leaf nodes with the new \                         * one, but try a different slot each time. */\                        pos = (frontier >> 1) +\                              (heap_pos & ((frontier >> 1) - 1));\                        if (ssd > nodes_next[pos]->ssd)\                            goto next_##NAME;\                        heap_pos++;\                    }\                    *h = generation;\                    u  = nodes_next[pos];\                    if (!u) {\                        av_assert1(pathn < FREEZE_INTERVAL << avctx->trellis);\                        u = t++;\                        nodes_next[pos] = u;\                        u->path = pathn++;\                    }\                    u->ssd  = ssd;\                    u->step = STEP_INDEX;\                    u->sample2 = nodes[j]->sample1;\                    u->sample1 = dec_sample;\                    paths[u->path].nibble = nibble;\                    paths[u->path].prev   = nodes[j]->path;\                    /* Sift the newly inserted node up in the heap to \                     * restore the heap property. */\                    while (pos > 0) {\                        int parent = (pos - 1) >> 1;\                        if (nodes_next[parent]->ssd <= ssd)\                            break;\                        FFSWAP(TrellisNode*, nodes_next[parent], nodes_next[pos]);\                        pos = parent;\                    }\                    next_##NAME:;                    STORE_NODE(ms, FFMAX(16,                               (ff_adpcm_AdaptationTable[nibble] * step) >> 8));                }            } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV ||                       version == AV_CODEC_ID_ADPCM_IMA_QT  ||                       version == AV_CODEC_ID_ADPCM_IMA_AMV ||                       version == AV_CODEC_ID_ADPCM_SWF) {#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\                const int predictor = nodes[j]->sample1;\                const int div = (sample - predictor) * 4 / STEP_TABLE;\                int nmin = av_clip(div - range, -7, 6);\                int nmax = av_clip(div + range, -6, 7);\                if (nmin <= 0)\                    nmin--; /* distinguish -0 from +0 */\                if (nmax < 0)\                    nmax--;\                for (nidx = nmin; nidx <= nmax; nidx++) {\                    const int nibble = nidx < 0 ? 7 - nidx : nidx;\                    int dec_sample = predictor +\                                    (STEP_TABLE *\                                     ff_adpcm_yamaha_difflookup[nibble]) / 8;\                    STORE_NODE(NAME, STEP_INDEX);\                }                LOOP_NODES(ima, ff_adpcm_step_table[step],

Lines 1–500 of 1034.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t