vorbis_dec.c
来自「ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦」· C语言 代码 · 共 1,638 行 · 第 1/4 页
C
1,638 行
// Read and decode residue
static int vorbis_residue_decode(vorbis_context *vc, vorbis_residue *vr, uint_fast8_t ch, uint_fast8_t *do_not_decode, float *vec, uint_fast16_t vlen) {
GetBitContext *gb=&vc->gb;
uint_fast8_t c_p_c=vc->codebooks[vr->classbook].dimensions;
uint_fast16_t n_to_read=vr->end-vr->begin;
uint_fast16_t ptns_to_read=n_to_read/vr->partition_size;
uint_fast8_t classifs[ptns_to_read*vc->audio_channels];
uint_fast8_t pass;
uint_fast8_t ch_used;
uint_fast8_t i,j,l;
uint_fast16_t k;
if (vr->type==2) {
for(j=1;j<ch;++j) {
do_not_decode[0]&=do_not_decode[j]; // FIXME - clobbering input
}
if (do_not_decode[0]) return 0;
ch_used=1;
} else {
ch_used=ch;
}
AV_DEBUG(" residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c);
for(pass=0;pass<=vr->maxpass;++pass) { // FIXME OPTIMIZE?
uint_fast16_t voffset;
uint_fast16_t partition_count;
uint_fast16_t j_times_ptns_to_read;
voffset=vr->begin;
for(partition_count=0;partition_count<ptns_to_read;) { // SPEC error
if (!pass) {
uint_fast32_t inverse_class = ff_inverse[vr->classifications];
for(j_times_ptns_to_read=0, j=0;j<ch_used;++j) {
if (!do_not_decode[j]) {
uint_fast32_t temp=get_vlc2(gb, vc->codebooks[vr->classbook].vlc.table,
vc->codebooks[vr->classbook].nb_bits, 3);
AV_DEBUG("Classword: %d \n", temp);
assert(vr->classifications > 1 && temp<=65536); //needed for inverse[]
for(i=0;i<c_p_c;++i) {
uint_fast32_t temp2;
temp2=(((uint_fast64_t)temp) * inverse_class)>>32;
if (partition_count+c_p_c-1-i < ptns_to_read) {
classifs[j_times_ptns_to_read+partition_count+c_p_c-1-i]=temp-temp2*vr->classifications;
}
temp=temp2;
}
}
j_times_ptns_to_read+=ptns_to_read;
}
}
for(i=0;(i<c_p_c) && (partition_count<ptns_to_read);++i) {
for(j_times_ptns_to_read=0, j=0;j<ch_used;++j) {
uint_fast16_t voffs;
if (!do_not_decode[j]) {
uint_fast8_t vqclass=classifs[j_times_ptns_to_read+partition_count];
int_fast16_t vqbook=vr->books[vqclass][pass];
if (vqbook>=0 && vc->codebooks[vqbook].codevectors) {
uint_fast16_t coffs;
unsigned dim= vc->codebooks[vqbook].dimensions; // not uint_fast8_t: 64bit is slower here on amd64
uint_fast16_t step= dim==1 ? vr->partition_size
: FASTDIV(vr->partition_size, dim);
vorbis_codebook codebook= vc->codebooks[vqbook];
if (vr->type==0) {
voffs=voffset+j*vlen;
for(k=0;k<step;++k) {
coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim;
for(l=0;l<dim;++l) {
vec[voffs+k+l*step]+=codebook.codevectors[coffs+l]; // FPMATH
}
}
}
else if (vr->type==1) {
voffs=voffset+j*vlen;
for(k=0;k<step;++k) {
coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim;
for(l=0;l<dim;++l, ++voffs) {
vec[voffs]+=codebook.codevectors[coffs+l]; // FPMATH
AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d \n", pass, voffs, vec[voffs], codebook.codevectors[coffs+l], coffs);
}
}
}
else if (vr->type==2 && ch==2 && (voffset&1)==0 && (dim&1)==0) { // most frequent case optimized
voffs=voffset>>1;
if(dim==2) {
for(k=0;k<step;++k) {
coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * 2;
vec[voffs+k ]+=codebook.codevectors[coffs ]; // FPMATH
vec[voffs+k+vlen]+=codebook.codevectors[coffs+1]; // FPMATH
}
} else
for(k=0;k<step;++k) {
coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim;
for(l=0;l<dim;l+=2, voffs++) {
vec[voffs ]+=codebook.codevectors[coffs+l ]; // FPMATH
vec[voffs+vlen]+=codebook.codevectors[coffs+l+1]; // FPMATH
AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffset/ch+(voffs%ch)*vlen, vec[voffset/ch+(voffs%ch)*vlen], codebook.codevectors[coffs+l], coffs, l);
}
}
}
else if (vr->type==2) {
voffs=voffset;
for(k=0;k<step;++k) {
coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim;
for(l=0;l<dim;++l, ++voffs) {
vec[voffs/ch+(voffs%ch)*vlen]+=codebook.codevectors[coffs+l]; // FPMATH FIXME use if and counter instead of / and %
AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffset/ch+(voffs%ch)*vlen, vec[voffset/ch+(voffs%ch)*vlen], codebook.codevectors[coffs+l], coffs, l);
}
}
} else {
av_log(vc->avccontext, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n");
return 1;
}
}
}
j_times_ptns_to_read+=ptns_to_read;
}
++partition_count;
voffset+=vr->partition_size;
}
}
}
return 0;
}
void vorbis_inverse_coupling(float *mag, float *ang, int blocksize)
{
int i;
for(i=0; i<blocksize; i++)
{
if (mag[i]>0.0) {
if (ang[i]>0.0) {
ang[i]=mag[i]-ang[i];
} else {
float temp=ang[i];
ang[i]=mag[i];
mag[i]+=temp;
}
} else {
if (ang[i]>0.0) {
ang[i]+=mag[i];
} else {
float temp=ang[i];
ang[i]=mag[i];
mag[i]-=temp;
}
}
}
}
// Decode the audio packet using the functions above
static int vorbis_parse_audio_packet(vorbis_context *vc) {
GetBitContext *gb=&vc->gb;
uint_fast8_t previous_window=0,next_window=0;
uint_fast8_t mode_number;
uint_fast16_t blocksize;
int_fast32_t i,j;
uint_fast8_t no_residue[vc->audio_channels];
uint_fast8_t do_not_decode[vc->audio_channels];
vorbis_mapping *mapping;
float *ch_res_ptr=vc->channel_residues;
float *ch_floor_ptr=vc->channel_floors;
uint_fast8_t res_chan[vc->audio_channels];
uint_fast8_t res_num=0;
int_fast16_t retlen=0;
uint_fast16_t saved_start=0;
float fadd_bias = vc->add_bias;
if (get_bits1(gb)) {
av_log(vc->avccontext, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n");
return -1; // packet type not audio
}
if (vc->mode_count==1) {
mode_number=0;
} else {
mode_number=get_bits(gb, ilog(vc->mode_count-1));
}
vc->mode_number=mode_number;
mapping=&vc->mappings[vc->modes[mode_number].mapping];
AV_DEBUG(" Mode number: %d , mapping: %d , blocktype %d \n", mode_number, vc->modes[mode_number].mapping, vc->modes[mode_number].blockflag);
if (vc->modes[mode_number].blockflag) {
previous_window=get_bits1(gb);
next_window=get_bits1(gb);
}
blocksize=vc->blocksize[vc->modes[mode_number].blockflag];
memset(ch_res_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ?
memset(ch_floor_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ?
// Decode floor
for(i=0;i<vc->audio_channels;++i) {
vorbis_floor *floor;
if (mapping->submaps>1) {
floor=&vc->floors[mapping->submap_floor[mapping->mux[i]]];
} else {
floor=&vc->floors[mapping->submap_floor[0]];
}
no_residue[i]=floor->decode(vc, &floor->data, ch_floor_ptr);
ch_floor_ptr+=blocksize/2;
}
// Nonzero vector propagate
for(i=mapping->coupling_steps-1;i>=0;--i) {
if (!(no_residue[mapping->magnitude[i]] & no_residue[mapping->angle[i]])) {
no_residue[mapping->magnitude[i]]=0;
no_residue[mapping->angle[i]]=0;
}
}
// Decode residue
for(i=0;i<mapping->submaps;++i) {
vorbis_residue *residue;
uint_fast8_t ch=0;
for(j=0;j<vc->audio_channels;++j) {
if ((mapping->submaps==1) || (i=mapping->mux[j])) {
res_chan[j]=res_num;
if (no_residue[j]) {
do_not_decode[ch]=1;
} else {
do_not_decode[ch]=0;
}
++ch;
++res_num;
}
}
residue=&vc->residues[mapping->submap_residue[i]];
vorbis_residue_decode(vc, residue, ch, do_not_decode, ch_res_ptr, blocksize/2);
ch_res_ptr+=ch*blocksize/2;
}
// Inverse coupling
for(i=mapping->coupling_steps-1;i>=0;--i) { //warning: i has to be signed
float *mag, *ang;
mag=vc->channel_residues+res_chan[mapping->magnitude[i]]*blocksize/2;
ang=vc->channel_residues+res_chan[mapping->angle[i]]*blocksize/2;
vc->dsp.vorbis_inverse_coupling(mag, ang, blocksize/2);
}
// Dotproduct
for(j=0, ch_floor_ptr=vc->channel_floors;j<vc->audio_channels;++j,ch_floor_ptr+=blocksize/2) {
ch_res_ptr=vc->channel_residues+res_chan[j]*blocksize/2;
vc->dsp.vector_fmul(ch_floor_ptr, ch_res_ptr, blocksize/2);
}
// MDCT, overlap/add, save data for next overlapping FPMATH
for(j=0;j<vc->audio_channels;++j) {
uint_fast8_t step=vc->audio_channels;
uint_fast16_t k;
float *saved=vc->saved+j*vc->blocksize[1]/2;
float *ret=vc->ret;
const float *lwin=vc->win[1];
const float *swin=vc->win[0];
float *buf=vc->buf;
float *buf_tmp=vc->buf_tmp;
ch_floor_ptr=vc->channel_floors+j*blocksize/2;
saved_start=vc->saved_start;
vc->mdct[0].fft.imdct_calc(&vc->mdct[vc->modes[mode_number].blockflag], buf, ch_floor_ptr, buf_tmp);
//FIXME process channels together, to allow faster simd vector_fmul_add_add?
if (vc->modes[mode_number].blockflag) {
// -- overlap/add
if (previous_window) {
vc->dsp.vector_fmul_add_add(ret+j, buf, lwin, saved, vc->add_bias, vc->blocksize[1]/2, step);
retlen=vc->blocksize[1]/2;
} else {
int len = (vc->blocksize[1]-vc->blocksize[0])/4;
buf += len;
vc->dsp.vector_fmul_add_add(ret+j, buf, swin, saved, vc->add_bias, vc->blocksize[0]/2, step);
k = vc->blocksize[0]/2*step + j;
buf += vc->blocksize[0]/2;
if(vc->exp_bias){
for(i=0; i<len; i++, k+=step)
((uint32_t*)ret)[k] = ((uint32_t*)buf)[i] + vc->exp_bias; // ret[k]=buf[i]*(1<<bias)
} else {
for(i=0; i<len; i++, k+=step)
ret[k] = buf[i] + fadd_bias;
}
buf=vc->buf;
retlen=vc->blocksize[0]/2+len;
}
// -- save
if (next_window) {
buf += vc->blocksize[1]/2;
vc->dsp.vector_fmul_reverse(saved, buf, lwin, vc->blocksize[1]/2);
saved_start=0;
} else {
saved_start=(vc->blocksize[1]-vc->blocksize[0])/4;
buf += vc->blocksize[1]/2;
for(i=0; i<saved_start; i++)
((uint32_t*)saved)[i] = ((uint32_t*)buf)[i] + vc->exp_bias;
vc->dsp.vector_fmul_reverse(saved+saved_start, buf+saved_start, swin, vc->blocksize[0]/2);
}
} else {
// --overlap/add
if(vc->add_bias) {
for(k=j, i=0;i<saved_start;++i, k+=step)
ret[k] = saved[i] + fadd_bias;
} else {
for(k=j, i=0;i<saved_start;++i, k+=step)
ret[k] = saved[i];
}
vc->dsp.vector_fmul_add_add(ret+k, buf, swin, saved+saved_start, vc->add_bias, vc->blocksize[0]/2, step);
retlen=saved_start+vc->blocksize[0]/2;
// -- save
buf += vc->blocksize[0]/2;
vc->dsp.vector_fmul_reverse(saved, buf, swin, vc->blocksize[0]/2);
saved_start=0;
}
}
vc->saved_start=saved_start;
return retlen*vc->audio_channels;
}
// Return the decoded audio packet through the standard api
static int vorbis_decode_frame(AVCodecContext *avccontext,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
vorbis_context *vc = avccontext->priv_data ;
GetBitContext *gb = &(vc->gb);
int_fast16_t len;
if(!buf_size){
return 0;
}
AV_DEBUG("packet length %d \n", buf_size);
init_get_bits(gb, buf, buf_size*8);
len=vorbis_parse_audio_packet(vc);
if (len<=0) {
*data_size=0;
return buf_size;
}
if (!vc->first_frame) {
vc->first_frame=1;
*data_size=0;
return buf_size ;
}
AV_DEBUG("parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb)/8, get_bits_count(gb)%8, len);
vc->dsp.float_to_int16(data, vc->ret, len);
*data_size=len*2;
return buf_size ;
}
// Close decoder
static int vorbis_decode_close(AVCodecContext *avccontext) {
vorbis_context *vc = avccontext->priv_data;
vorbis_free(vc);
return 0 ;
}
AVCodec vorbis_decoder = {
"vorbis",
CODEC_TYPE_AUDIO,
CODEC_ID_VORBIS,
sizeof(vorbis_context),
vorbis_decode_init,
NULL,
vorbis_decode_close,
vorbis_decode_frame,
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?