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 + -
显示快捷键?