wavpack.c

来自「linux下的MPEG1」· C语言 代码 · 共 557 行 · 第 1/2 页

C
557
字号
                R = R2;                s->decorr[i].samplesA[0] = R;            }else{                R2 = R + ((s->decorr[i].weightB * s->decorr[i].samplesB[0] + 512) >> 10);                UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R);                R = R2;                if(t == -3){                    R2 = s->decorr[i].samplesA[0];                    s->decorr[i].samplesA[0] = R;                }                L2 = L + ((s->decorr[i].weightA * R2 + 512) >> 10);                UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L);                L = L2;                s->decorr[i].samplesB[0] = L;            }        }        pos = (pos + 1) & 7;        if(s->joint)            L += (R -= (L >> 1));        crc = (crc * 3 + L) * 3 + R;        *dst++ = L;        *dst++ = R;        count++;    }while(!last && count < s->samples);    if(crc != s->CRC){        av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");        return -1;    }    return count * 2;}static int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, int16_t *dst){    int i, j, count = 0;    int last, t;    int A, S, T;    int pos = 0;    uint32_t crc = 0xFFFFFFFF;    s->one = s->zero = s->zeroes = 0;    do{        T = wv_get_value(s, gb, s->median, &last);        S = 0;        if(last) break;        for(i = 0; i < s->terms; i++){            t = s->decorr[i].value;            if(t > 8){                if(t & 1)                    A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1];                else                    A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1;                s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0];                j = 0;            }else{                A = s->decorr[i].samplesA[pos];                j = (pos + t) & 7;            }            S = T + ((s->decorr[i].weightA * A + 512) >> 10);            if(A && T) s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta;            s->decorr[i].samplesA[j] = T = S;        }        pos = (pos + 1) & 7;        crc = crc * 3 + S;        *dst++ = S;        count++;    }while(!last && count < s->samples);    if(crc != s->CRC){        av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");        return -1;    }    return count;}static int wavpack_decode_init(AVCodecContext *avctx){    WavpackContext *s = avctx->priv_data;    s->avctx = avctx;    s->stereo = (avctx->channels == 2);    return 0;}static int wavpack_decode_close(AVCodecContext *avctx){//    WavpackContext *s = avctx->priv_data;    return 0;}static int wavpack_decode_frame(AVCodecContext *avctx,                            void *data, int *data_size,                            uint8_t *buf, int buf_size){    WavpackContext *s = avctx->priv_data;    int16_t *samples = data;    int samplecount;    int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0;    uint8_t* buf_end = buf + buf_size;    int i, j, id, size, ssize, weights, t;    if (buf_size == 0) return 0;    memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));    s->samples = AV_RL32(buf); buf += 4;    if(!s->samples) return buf_size;    /* should not happen but who knows */    if(s->samples * 2 * avctx->channels > AVCODEC_MAX_AUDIO_FRAME_SIZE){        av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n");        return -1;    }    s->joint = AV_RL32(buf) & WV_JOINT; buf += 4;    s->CRC = AV_RL32(buf); buf += 4;    // parse metadata blocks    while(buf < buf_end){        id = *buf++;        size = *buf++;        if(id & WP_IDF_LONG) {            size |= (*buf++) << 8;            size |= (*buf++) << 16;        }        size <<= 1; // size is specified in words        ssize = size;        if(id & WP_IDF_ODD) size--;        if(size < 0){            av_log(avctx, AV_LOG_ERROR, "Got incorrect block %02X with size %i\n", id, size);            break;        }        if(buf + ssize > buf_end){            av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size);            break;        }        if(id & WP_IDF_IGNORE){            buf += ssize;            continue;        }        switch(id & WP_IDF_MASK){        case WP_ID_DECTERMS:            s->terms = size;            if(s->terms > MAX_TERMS){                av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n");                buf += ssize;                continue;            }            for(i = 0; i < s->terms; i++) {                s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5;                s->decorr[s->terms - i - 1].delta = *buf >> 5;                buf++;            }            got_terms = 1;            break;        case WP_ID_DECWEIGHTS:            if(!got_terms){                av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n");                continue;            }            weights = size >> s->stereo;            if(weights > MAX_TERMS || weights > s->terms){                av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n");                buf += ssize;                continue;            }            for(i = 0; i < weights; i++) {                t = (int8_t)(*buf++);                s->decorr[s->terms - i - 1].weightA = t << 3;                if(s->decorr[s->terms - i - 1].weightA > 0)                    s->decorr[s->terms - i - 1].weightA += (s->decorr[s->terms - i - 1].weightA + 64) >> 7;                if(s->stereo){                    t = (int8_t)(*buf++);                    s->decorr[s->terms - i - 1].weightB = t << 3;                    if(s->decorr[s->terms - i - 1].weightB > 0)                        s->decorr[s->terms - i - 1].weightB += (s->decorr[s->terms - i - 1].weightB + 64) >> 7;                }            }            got_weights = 1;            break;        case WP_ID_DECSAMPLES:            if(!got_terms){                av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n");                continue;            }            t = 0;            for(i = s->terms - 1; (i >= 0) && (t < size); i--) {                if(s->decorr[i].value > 8){                    s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2;                    s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf)); buf += 2;                    if(s->stereo){                        s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2;                        s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf)); buf += 2;                        t += 4;                    }                    t += 4;                }else if(s->decorr[i].value < 0){                    s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2;                    s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2;                    t += 4;                }else{                    for(j = 0; j < s->decorr[i].value; j++){                        s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); buf += 2;                        if(s->stereo){                            s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2;                        }                    }                    t += s->decorr[i].value * 2 * avctx->channels;                }            }            got_samples = 1;            break;        case WP_ID_ENTROPY:            if(size != 6 * avctx->channels){                av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * avctx->channels, size);                buf += ssize;                continue;            }            for(i = 0; i < 3 * avctx->channels; i++){                s->median[i] = wp_exp2(AV_RL16(buf));                buf += 2;            }            got_entropy = 1;            break;        case WP_ID_DATA:            init_get_bits(&s->gb, buf, size * 8);            s->data_size = size * 8;            buf += size;            got_bs = 1;            break;        default:            buf += size;        }        if(id & WP_IDF_ODD) buf++;    }    if(!got_terms){        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");        return -1;    }    if(!got_weights){        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");        return -1;    }    if(!got_samples){        av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");        return -1;    }    if(!got_entropy){        av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");        return -1;    }    if(!got_bs){        av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");        return -1;    }    if(s->stereo)        samplecount = wv_unpack_stereo(s, &s->gb, samples);    else        samplecount = wv_unpack_mono(s, &s->gb, samples);    *data_size = samplecount * 2;    return buf_size;}AVCodec wavpack_decoder = {    "wavpack",    CODEC_TYPE_AUDIO,    CODEC_ID_WAVPACK,    sizeof(WavpackContext),    wavpack_decode_init,    NULL,    wavpack_decode_close,    wavpack_decode_frame,};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?