📄 vorbis_enc.c
字号:
/* * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file vorbis_enc.c * Native Vorbis encoder. * @author Oded Shimon <ods15@ods15.dyndns.org> */#include <float.h>#include "avcodec.h"#include "dsputil.h"#include "vorbis.h"#include "vorbis_enc_data.h"#undef NDEBUG#include <assert.h>typedef struct { int nentries; uint8_t * lens; uint32_t * codewords; int ndimentions; float min; float delta; int seq_p; int lookup; int * quantlist; float * dimentions; float * pow2;} codebook_t;typedef struct { int dim; int subclass; int masterbook; int * books;} floor_class_t;typedef struct { int partitions; int * partition_to_class; int nclasses; floor_class_t * classes; int multiplier; int rangebits; int values; floor1_entry_t * list;} floor_t;typedef struct { int type; int begin; int end; int partition_size; int classifications; int classbook; int8_t (*books)[8]; float (*maxes)[2];} residue_t;typedef struct { int submaps; int * mux; int * floor; int * residue; int coupling_steps; int * magnitude; int * angle;} mapping_t;typedef struct { int blockflag; int mapping;} vorbis_mode_t;typedef struct { int channels; int sample_rate; int log2_blocksize[2]; MDCTContext mdct[2]; const float * win[2]; int have_saved; float * saved; float * samples; float * floor; // also used for tmp values for mdct float * coeffs; // also used for residue after floor float quality; int ncodebooks; codebook_t * codebooks; int nfloors; floor_t * floors; int nresidues; residue_t * residues; int nmappings; mapping_t * mappings; int nmodes; vorbis_mode_t * modes;} venc_context_t;typedef struct { int total; int total_pos; int pos; uint8_t * buf_ptr;} PutBitContext;static inline void init_put_bits(PutBitContext * pb, uint8_t * buf, int buffer_len) { pb->total = buffer_len * 8; pb->total_pos = 0; pb->pos = 0; pb->buf_ptr = buf;}static void put_bits(PutBitContext * pb, int bits, uint64_t val) { if ((pb->total_pos += bits) >= pb->total) return; if (!bits) return; if (pb->pos) { if (pb->pos > bits) { *pb->buf_ptr |= val << (8 - pb->pos); pb->pos -= bits; bits = 0; } else { *pb->buf_ptr++ |= (val << (8 - pb->pos)) & 0xFF; val >>= pb->pos; bits -= pb->pos; pb->pos = 0; } } for (; bits >= 8; bits -= 8) { *pb->buf_ptr++ = val & 0xFF; val >>= 8; } if (bits) { *pb->buf_ptr = val; pb->pos = 8 - bits; }}static inline void flush_put_bits(PutBitContext * pb) {}static inline int put_bits_count(PutBitContext * pb) { return pb->total_pos;}static inline void put_codeword(PutBitContext * pb, codebook_t * cb, int entry) { assert(entry >= 0); assert(entry < cb->nentries); assert(cb->lens[entry]); put_bits(pb, cb->lens[entry], cb->codewords[entry]);}static int cb_lookup_vals(int lookup, int dimentions, int entries) { if (lookup == 1) return ff_vorbis_nth_root(entries, dimentions); else if (lookup == 2) return dimentions * entries; return 0;}static void ready_codebook(codebook_t * cb) { int i; ff_vorbis_len2vlc(cb->lens, cb->codewords, cb->nentries); if (!cb->lookup) cb->pow2 = cb->dimentions = NULL; else { int vals = cb_lookup_vals(cb->lookup, cb->ndimentions, cb->nentries); cb->dimentions = av_malloc(sizeof(float) * cb->nentries * cb->ndimentions); cb->pow2 = av_mallocz(sizeof(float) * cb->nentries); for (i = 0; i < cb->nentries; i++) { float last = 0; int j; int div = 1; for (j = 0; j < cb->ndimentions; j++) { int off; if (cb->lookup == 1) off = (i / div) % vals; // lookup type 1 else off = i * cb->ndimentions + j; // lookup type 2 cb->dimentions[i * cb->ndimentions + j] = last + cb->min + cb->quantlist[off] * cb->delta; if (cb->seq_p) last = cb->dimentions[i * cb->ndimentions + j]; cb->pow2[i] += cb->dimentions[i * cb->ndimentions + j]*cb->dimentions[i * cb->ndimentions + j]; div *= vals; } cb->pow2[i] /= 2.; } }}static void ready_residue(residue_t * rc, venc_context_t * venc) { int i; assert(rc->type == 2); rc->maxes = av_mallocz(sizeof(float[2]) * rc->classifications); for (i = 0; i < rc->classifications; i++) { int j; codebook_t * cb; for (j = 0; j < 8; j++) if (rc->books[i][j] != -1) break; if (j == 8) continue; // zero cb = &venc->codebooks[rc->books[i][j]]; assert(cb->ndimentions >= 2); assert(cb->lookup); for (j = 0; j < cb->nentries; j++) { float a; if (!cb->lens[j]) continue; a = fabs(cb->dimentions[j * cb->ndimentions]); if (a > rc->maxes[i][0]) rc->maxes[i][0] = a; a = fabs(cb->dimentions[j * cb->ndimentions + 1]); if (a > rc->maxes[i][1]) rc->maxes[i][1] = a; } } // small bias for (i = 0; i < rc->classifications; i++) { rc->maxes[i][0] += 0.8; rc->maxes[i][1] += 0.8; }}static void create_vorbis_context(venc_context_t * venc, AVCodecContext * avccontext) { floor_t * fc; residue_t * rc; mapping_t * mc; int i, book; venc->channels = avccontext->channels; venc->sample_rate = avccontext->sample_rate; venc->log2_blocksize[0] = venc->log2_blocksize[1] = 11; venc->ncodebooks = sizeof(cvectors)/sizeof(cvectors[0]); venc->codebooks = av_malloc(sizeof(codebook_t) * venc->ncodebooks); // codebook 0..14 - floor1 book, values 0..255 // codebook 15 residue masterbook // codebook 16..29 residue for (book = 0; book < venc->ncodebooks; book++) { codebook_t * cb = &venc->codebooks[book]; int vals; cb->ndimentions = cvectors[book].dim; cb->nentries = cvectors[book].real_len; cb->min = cvectors[book].min; cb->delta = cvectors[book].delta; cb->lookup = cvectors[book].lookup; cb->seq_p = 0; cb->lens = av_malloc(sizeof(uint8_t) * cb->nentries); cb->codewords = av_malloc(sizeof(uint32_t) * cb->nentries); memcpy(cb->lens, cvectors[book].clens, cvectors[book].len); memset(cb->lens + cvectors[book].len, 0, cb->nentries - cvectors[book].len); if (cb->lookup) { vals = cb_lookup_vals(cb->lookup, cb->ndimentions, cb->nentries); cb->quantlist = av_malloc(sizeof(int) * vals); for (i = 0; i < vals; i++) cb->quantlist[i] = cvectors[book].quant[i]; } else { cb->quantlist = NULL; } ready_codebook(cb); } venc->nfloors = 1; venc->floors = av_malloc(sizeof(floor_t) * venc->nfloors); // just 1 floor fc = &venc->floors[0]; fc->partitions = 8; fc->partition_to_class = av_malloc(sizeof(int) * fc->partitions); fc->nclasses = 0; for (i = 0; i < fc->partitions; i++) { static const int a[] = {0,1,2,2,3,3,4,4}; fc->partition_to_class[i] = a[i]; fc->nclasses = FFMAX(fc->nclasses, fc->partition_to_class[i]); } fc->nclasses++; fc->classes = av_malloc(sizeof(floor_class_t) * fc->nclasses); for (i = 0; i < fc->nclasses; i++) { floor_class_t * c = &fc->classes[i]; int j, books; c->dim = floor_classes[i].dim; c->subclass = floor_classes[i].subclass; c->masterbook = floor_classes[i].masterbook; books = (1 << c->subclass); c->books = av_malloc(sizeof(int) * books); for (j = 0; j < books; j++) c->books[j] = floor_classes[i].nbooks[j]; } fc->multiplier = 2; fc->rangebits = venc->log2_blocksize[0] - 1; fc->values = 2; for (i = 0; i < fc->partitions; i++) fc->values += fc->classes[fc->partition_to_class[i]].dim; fc->list = av_malloc(sizeof(floor1_entry_t) * fc->values); fc->list[0].x = 0; fc->list[1].x = 1 << fc->rangebits; for (i = 2; i < fc->values; i++) { static const int a[] = { 93, 23,372, 6, 46,186,750, 14, 33, 65, 130,260,556, 3, 10, 18, 28, 39, 55, 79, 111,158,220,312,464,650,850 }; fc->list[i].x = a[i - 2]; } ff_vorbis_ready_floor1_list(fc->list, fc->values); venc->nresidues = 1; venc->residues = av_malloc(sizeof(residue_t) * venc->nresidues); // single residue rc = &venc->residues[0]; rc->type = 2; rc->begin = 0; rc->end = 1600; rc->partition_size = 32; rc->classifications = 10; rc->classbook = 15; rc->books = av_malloc(sizeof(*rc->books) * rc->classifications); { static const int8_t a[10][8] = { { -1, -1, -1, -1, -1, -1, -1, -1, }, { -1, -1, 16, -1, -1, -1, -1, -1, }, { -1, -1, 17, -1, -1, -1, -1, -1, }, { -1, -1, 18, -1, -1, -1, -1, -1, }, { -1, -1, 19, -1, -1, -1, -1, -1, }, { -1, -1, 20, -1, -1, -1, -1, -1, }, { -1, -1, 21, -1, -1, -1, -1, -1, }, { 22, 23, -1, -1, -1, -1, -1, -1, }, { 24, 25, -1, -1, -1, -1, -1, -1, }, { 26, 27, 28, -1, -1, -1, -1, -1, }, }; memcpy(rc->books, a, sizeof a); } ready_residue(rc, venc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -