⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vorbis_enc.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 3 页
字号:
            coded[i] = 0; // must be used later as flag!            continue;        } else {            if (!coded[fc->list[i].low ]) coded[fc->list[i].low ] = -1;            if (!coded[fc->list[i].high]) coded[fc->list[i].high] = -1;        }        if (posts[i] > predicted) {            if (posts[i] - predicted > room)                coded[i] = posts[i] - predicted + lowroom;            else                coded[i] = (posts[i] - predicted) << 1;        } else {            if (predicted - posts[i] > room)                coded[i] = predicted - posts[i] + highroom - 1;            else                coded[i] = ((predicted - posts[i]) << 1) - 1;        }    }    counter = 2;    for (i = 0; i < fc->partitions; i++) {        floor_class_t * c = &fc->classes[fc->partition_to_class[i]];        int k, cval = 0, csub = 1<<c->subclass;        if (c->subclass) {            codebook_t * book = &venc->codebooks[c->masterbook];            int cshift = 0;            for (k = 0; k < c->dim; k++) {                int l;                for (l = 0; l < csub; l++) {                    int maxval = 1;                    if (c->books[l] != -1)                        maxval = venc->codebooks[c->books[l]].nentries;                    // coded could be -1, but this still works, cause that is 0                    if (coded[counter + k] < maxval) break;                }                assert(l != csub);                cval |= l << cshift;                cshift += c->subclass;            }            put_codeword(pb, book, cval);        }        for (k = 0; k < c->dim; k++) {            int book = c->books[cval & (csub-1)];            int entry = coded[counter++];            cval >>= c->subclass;            if (book == -1) continue;            if (entry == -1) entry = 0;            put_codeword(pb, &venc->codebooks[book], entry);        }    }    ff_vorbis_floor1_render_list(fc->list, fc->values, posts, coded, fc->multiplier, floor, samples);}static float * put_vector(codebook_t * book, PutBitContext * pb, float * num) {    int i, entry = -1;    float distance = FLT_MAX;    assert(book->dimentions);    for (i = 0; i < book->nentries; i++) {        float * vec = book->dimentions + i * book->ndimentions, d = book->pow2[i];        int j;        if (!book->lens[i]) continue;        for (j = 0; j < book->ndimentions; j++)            d -= vec[j] * num[j];        if (distance > d) {            entry = i;            distance = d;        }    }    put_codeword(pb, book, entry);    return &book->dimentions[entry * book->ndimentions];}static void residue_encode(venc_context_t * venc, residue_t * rc, PutBitContext * pb, float * coeffs, int samples, int real_ch) {    int pass, i, j, p, k;    int psize = rc->partition_size;    int partitions = (rc->end - rc->begin) / psize;    int channels = (rc->type == 2) ? 1 : real_ch;    int classes[channels][partitions];    int classwords = venc->codebooks[rc->classbook].ndimentions;    assert(rc->type == 2);    assert(real_ch == 2);    for (p = 0; p < partitions; p++) {        float max1 = 0., max2 = 0.;        int s = rc->begin + p * psize;        for (k = s; k < s + psize; k += 2) {            max1 = FFMAX(max1, fabs(coeffs[          k / real_ch]));            max2 = FFMAX(max2, fabs(coeffs[samples + k / real_ch]));        }        for (i = 0; i < rc->classifications - 1; i++) {            if (max1 < rc->maxes[i][0] && max2 < rc->maxes[i][1]) break;        }        classes[0][p] = i;    }    for (pass = 0; pass < 8; pass++) {        p = 0;        while (p < partitions) {            if (pass == 0)                for (j = 0; j < channels; j++) {                    codebook_t * book = &venc->codebooks[rc->classbook];                    int entry = 0;                    for (i = 0; i < classwords; i++) {                        entry *= rc->classifications;                        entry += classes[j][p + i];                    }                    put_codeword(pb, book, entry);                }            for (i = 0; i < classwords && p < partitions; i++, p++) {                for (j = 0; j < channels; j++) {                    int nbook = rc->books[classes[j][p]][pass];                    codebook_t * book = &venc->codebooks[nbook];                    float * buf = coeffs + samples*j + rc->begin + p*psize;                    if (nbook == -1) continue;                    assert(rc->type == 0 || rc->type == 2);                    assert(!(psize % book->ndimentions));                    if (rc->type == 0) {                        for (k = 0; k < psize; k += book->ndimentions) {                            float * a = put_vector(book, pb, &buf[k]);                            int l;                            for (l = 0; l < book->ndimentions; l++)                                buf[k + l] -= a[l];                        }                    } else {                        int s = rc->begin + p * psize, a1, b1;                        a1 = (s % real_ch) * samples;                        b1 =  s / real_ch;                        s = real_ch * samples;                        for (k = 0; k < psize; k += book->ndimentions) {                            int dim, a2 = a1, b2 = b1;                            float vec[book->ndimentions], * pv = vec;                            for (dim = book->ndimentions; dim--; ) {                                *pv++ = coeffs[a2 + b2];                                if ((a2 += samples) == s) {                                    a2=0;                                    b2++;                                }                            }                            pv = put_vector(book, pb, vec);                            for (dim = book->ndimentions; dim--; ) {                                coeffs[a1 + b1] -= *pv++;                                if ((a1 += samples) == s) {                                    a1=0;                                    b1++;                                }                            }                        }                    }                }            }        }    }}static int apply_window_and_mdct(venc_context_t * venc, signed short * audio, int samples) {    int i, j, channel;    const float * win = venc->win[0];    int window_len = 1 << (venc->log2_blocksize[0] - 1);    float n = (float)(1 << venc->log2_blocksize[0]) / 4.;    // FIXME use dsp    if (!venc->have_saved && !samples) return 0;    if (venc->have_saved) {        for (channel = 0; channel < venc->channels; channel++) {            memcpy(venc->samples + channel*window_len*2, venc->saved + channel*window_len, sizeof(float)*window_len);        }    } else {        for (channel = 0; channel < venc->channels; channel++) {            memset(venc->samples + channel*window_len*2, 0, sizeof(float)*window_len);        }    }    if (samples) {        for (channel = 0; channel < venc->channels; channel++) {            float * offset = venc->samples + channel*window_len*2 + window_len;            j = channel;            for (i = 0; i < samples; i++, j += venc->channels)                offset[i] = -audio[j] / 32768. / n * win[window_len - i - 1]; //FIXME find out why the sign has to be fliped        }    } else {        for (channel = 0; channel < venc->channels; channel++) {            memset(venc->samples + channel*window_len*2 + window_len, 0, sizeof(float)*window_len);        }    }    for (channel = 0; channel < venc->channels; channel++) {        ff_mdct_calc(&venc->mdct[0], venc->coeffs + channel*window_len, venc->samples + channel*window_len*2, venc->floor/*tmp*/);    }    if (samples) {        for (channel = 0; channel < venc->channels; channel++) {            float * offset = venc->saved + channel*window_len;            j = channel;            for (i = 0; i < samples; i++, j += venc->channels)                offset[i] = -audio[j] / 32768. / n * win[i]; //FIXME find out why the sign has to be fliped        }        venc->have_saved = 1;    } else {        venc->have_saved = 0;    }    return 1;}static int vorbis_encode_init(AVCodecContext * avccontext){    venc_context_t * venc = avccontext->priv_data;    if (avccontext->channels != 2) {        av_log(avccontext, AV_LOG_ERROR, "Current FFmpeg Vorbis encoder only supports 2 channels.\n");        return -1;    }    create_vorbis_context(venc, avccontext);    if (avccontext->flags & CODEC_FLAG_QSCALE)        venc->quality = avccontext->global_quality / (float)FF_QP2LAMBDA / 10.;    else        venc->quality = 1.;    venc->quality *= venc->quality;    avccontext->extradata_size = put_main_header(venc, (uint8_t**)&avccontext->extradata);    avccontext->frame_size = 1 << (venc->log2_blocksize[0] - 1);    avccontext->coded_frame = avcodec_alloc_frame();    avccontext->coded_frame->key_frame = 1;    return 0;}static int vorbis_encode_frame(AVCodecContext * avccontext, unsigned char * packets, int buf_size, void *data){    venc_context_t * venc = avccontext->priv_data;    signed short * audio = data;    int samples = data ? avccontext->frame_size : 0;    vorbis_mode_t * mode;    mapping_t * mapping;    PutBitContext pb;    int i;    if (!apply_window_and_mdct(venc, audio, samples)) return 0;    samples = 1 << (venc->log2_blocksize[0] - 1);    init_put_bits(&pb, packets, buf_size);    put_bits(&pb, 1, 0); // magic bit    put_bits(&pb, ilog(venc->nmodes - 1), 0); // 0 bits, the mode    mode = &venc->modes[0];    mapping = &venc->mappings[mode->mapping];    if (mode->blockflag) {        put_bits(&pb, 1, 0);        put_bits(&pb, 1, 0);    }    for (i = 0; i < venc->channels; i++) {        floor_t * fc = &venc->floors[mapping->floor[mapping->mux[i]]];        uint_fast16_t posts[fc->values];        floor_fit(venc, fc, &venc->coeffs[i * samples], posts, samples);        floor_encode(venc, fc, &pb, posts, &venc->floor[i * samples], samples);    }    for (i = 0; i < venc->channels * samples; i++) {        venc->coeffs[i] /= venc->floor[i];    }    for (i = 0; i < mapping->coupling_steps; i++) {        float * mag = venc->coeffs + mapping->magnitude[i] * samples;        float * ang = venc->coeffs + mapping->angle[i] * samples;        int j;        for (j = 0; j < samples; j++) {            float a = ang[j];            ang[j] -= mag[j];            if (mag[j] > 0) ang[j] = -ang[j];            if (ang[j] < 0) mag[j] = a;        }    }    residue_encode(venc, &venc->residues[mapping->residue[mapping->mux[0]]], &pb, venc->coeffs, samples, venc->channels);    flush_put_bits(&pb);    return (put_bits_count(&pb) + 7) / 8;}static int vorbis_encode_close(AVCodecContext * avccontext){    venc_context_t * venc = avccontext->priv_data;    int i;    if (venc->codebooks)        for (i = 0; i < venc->ncodebooks; i++) {            av_freep(&venc->codebooks[i].lens);            av_freep(&venc->codebooks[i].codewords);            av_freep(&venc->codebooks[i].quantlist);            av_freep(&venc->codebooks[i].dimentions);            av_freep(&venc->codebooks[i].pow2);        }    av_freep(&venc->codebooks);    if (venc->floors)        for (i = 0; i < venc->nfloors; i++) {            int j;            if (venc->floors[i].classes)                for (j = 0; j < venc->floors[i].nclasses; j++)                    av_freep(&venc->floors[i].classes[j].books);            av_freep(&venc->floors[i].classes);            av_freep(&venc->floors[i].partition_to_class);            av_freep(&venc->floors[i].list);        }    av_freep(&venc->floors);    if (venc->residues)        for (i = 0; i < venc->nresidues; i++) {            av_freep(&venc->residues[i].books);            av_freep(&venc->residues[i].maxes);        }    av_freep(&venc->residues);    if (venc->mappings)        for (i = 0; i < venc->nmappings; i++) {            av_freep(&venc->mappings[i].mux);            av_freep(&venc->mappings[i].floor);            av_freep(&venc->mappings[i].residue);            av_freep(&venc->mappings[i].magnitude);            av_freep(&venc->mappings[i].angle);        }    av_freep(&venc->mappings);    av_freep(&venc->modes);    av_freep(&venc->saved);    av_freep(&venc->samples);    av_freep(&venc->floor);    av_freep(&venc->coeffs);    ff_mdct_end(&venc->mdct[0]);    ff_mdct_end(&venc->mdct[1]);    av_freep(&avccontext->coded_frame);    av_freep(&avccontext->extradata);    return 0 ;}AVCodec vorbis_encoder = {    "vorbis",    CODEC_TYPE_AUDIO,    CODEC_ID_VORBIS,    sizeof(venc_context_t),    vorbis_encode_init,    vorbis_encode_frame,    vorbis_encode_close,    .capabilities= CODEC_CAP_DELAY,};

⌨️ 快捷键说明

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