📄 wavpack.c.svn-base
字号:
} pos = (pos + 1) & 7; if(s->joint) L += (R -= (L >> 1)); crc = (crc * 3 + L) * 3 + R; bit = (L & s->and) | s->or; *dst++ = ((L + bit) << s->shift) - bit; bit = (R & s->and) | s->or; *dst++ = ((R + bit) << s->shift) - bit; 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, bit; 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; bit = (S & s->and) | s->or; *dst++ = ((S + bit) << s->shift) - bit; 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_frame(AVCodecContext *avctx, void *data, int *data_size, const 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; const uint8_t* buf_end = buf + buf_size; int i, j, id, size, ssize, weights, t; if (buf_size == 0){ *data_size = 0; return 0; } memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr)); memset(s->median, 0, sizeof(s->median)); s->and = s->or = s->shift = 0; s->samples = AV_RL32(buf); buf += 4; if(!s->samples){ *data_size = 0; return buf_size; } /* should not happen but who knows */ if(s->samples * 2 * avctx->channels > *data_size){ av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n"); return -1; } s->stereo_in = (AV_RL32(buf) & WV_FALSE_STEREO) ? 0 : s->stereo; s->joint = AV_RL32(buf) & WV_JOINT_STEREO; 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_in; 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_in){ 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_in){ 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_in){ s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2; } } t += s->decorr[i].value * 2 * (s->stereo_in + 1); } } got_samples = 1; break; case WP_ID_ENTROPY: if(size != 6 * (s->stereo_in + 1)){ av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * (s->stereo_in + 1), size); buf += ssize; continue; } for(i = 0; i < 3 * (s->stereo_in + 1); i++){ s->median[i] = wp_exp2(AV_RL16(buf)); buf += 2; } got_entropy = 1; break; case WP_ID_INT32INFO: if(size != 4 || *buf){ av_log(avctx, AV_LOG_ERROR, "Invalid INT32INFO, size = %i, sent_bits = %i\n", size, *buf); buf += ssize; continue; } if(buf[1]) s->shift = buf[1]; else if(buf[2]){ s->and = s->or = 1; s->shift = buf[2]; }else if(buf[3]){ s->and = 1; s->shift = buf[3]; } buf += 4; 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_in) samplecount = wv_unpack_stereo(s, &s->gb, samples); else{ samplecount = wv_unpack_mono(s, &s->gb, samples); if(s->stereo){ int16_t *dst = samples + samplecount * 2; int16_t *src = samples + samplecount; int cnt = samplecount; while(cnt--){ *--dst = *--src; *--dst = *src; } samplecount *= 2; } } *data_size = samplecount * 2; return buf_size;}AVCodec wavpack_decoder = { "wavpack", CODEC_TYPE_AUDIO, CODEC_ID_WAVPACK, sizeof(WavpackContext), wavpack_decode_init, NULL, NULL, wavpack_decode_frame,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -