| @@ -155,7 +155,7 @@ static int cb_lookup_vals(int lookup, int dimentions, int entries) | |||
| return 0; | |||
| } | |||
| static void ready_codebook(vorbis_enc_codebook *cb) | |||
| static int ready_codebook(vorbis_enc_codebook *cb) | |||
| { | |||
| int i; | |||
| @@ -167,6 +167,8 @@ static void ready_codebook(vorbis_enc_codebook *cb) | |||
| 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); | |||
| if (!cb->dimentions || !cb->pow2) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < cb->nentries; i++) { | |||
| float last = 0; | |||
| int j; | |||
| @@ -187,13 +189,16 @@ static void ready_codebook(vorbis_enc_codebook *cb) | |||
| cb->pow2[i] /= 2.; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| static void ready_residue(vorbis_enc_residue *rc, vorbis_enc_context *venc) | |||
| static int ready_residue(vorbis_enc_residue *rc, vorbis_enc_context *venc) | |||
| { | |||
| int i; | |||
| assert(rc->type == 2); | |||
| rc->maxes = av_mallocz(sizeof(float[2]) * rc->classifications); | |||
| if (!rc->maxes) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < rc->classifications; i++) { | |||
| int j; | |||
| vorbis_enc_codebook * cb; | |||
| @@ -223,15 +228,16 @@ static void ready_residue(vorbis_enc_residue *rc, vorbis_enc_context *venc) | |||
| rc->maxes[i][0] += 0.8; | |||
| rc->maxes[i][1] += 0.8; | |||
| } | |||
| return 0; | |||
| } | |||
| static void create_vorbis_context(vorbis_enc_context *venc, | |||
| AVCodecContext *avccontext) | |||
| static int create_vorbis_context(vorbis_enc_context *venc, | |||
| AVCodecContext *avccontext) | |||
| { | |||
| vorbis_enc_floor *fc; | |||
| vorbis_enc_residue *rc; | |||
| vorbis_enc_mapping *mc; | |||
| int i, book; | |||
| int i, book, ret; | |||
| venc->channels = avccontext->channels; | |||
| venc->sample_rate = avccontext->sample_rate; | |||
| @@ -239,6 +245,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| venc->ncodebooks = FF_ARRAY_ELEMS(cvectors); | |||
| venc->codebooks = av_malloc(sizeof(vorbis_enc_codebook) * venc->ncodebooks); | |||
| if (!venc->codebooks) | |||
| return AVERROR(ENOMEM); | |||
| // codebook 0..14 - floor1 book, values 0..255 | |||
| // codebook 15 residue masterbook | |||
| @@ -255,27 +263,36 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| cb->lens = av_malloc(sizeof(uint8_t) * cb->nentries); | |||
| cb->codewords = av_malloc(sizeof(uint32_t) * cb->nentries); | |||
| if (!cb->lens || !cb->codewords) | |||
| return AVERROR(ENOMEM); | |||
| 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); | |||
| if (!cb->quantlist) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < vals; i++) | |||
| cb->quantlist[i] = cvectors[book].quant[i]; | |||
| } else { | |||
| cb->quantlist = NULL; | |||
| } | |||
| ready_codebook(cb); | |||
| if ((ret = ready_codebook(cb)) < 0) | |||
| return ret; | |||
| } | |||
| venc->nfloors = 1; | |||
| venc->floors = av_malloc(sizeof(vorbis_enc_floor) * venc->nfloors); | |||
| if (!venc->floors) | |||
| return AVERROR(ENOMEM); | |||
| // just 1 floor | |||
| fc = &venc->floors[0]; | |||
| fc->partitions = NUM_FLOOR_PARTITIONS; | |||
| fc->partition_to_class = av_malloc(sizeof(int) * fc->partitions); | |||
| if (!fc->partition_to_class) | |||
| return AVERROR(ENOMEM); | |||
| fc->nclasses = 0; | |||
| for (i = 0; i < fc->partitions; i++) { | |||
| static const int a[] = {0, 1, 2, 2, 3, 3, 4, 4}; | |||
| @@ -284,6 +301,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| } | |||
| fc->nclasses++; | |||
| fc->classes = av_malloc(sizeof(vorbis_enc_floor_class) * fc->nclasses); | |||
| if (!fc->classes) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < fc->nclasses; i++) { | |||
| vorbis_enc_floor_class * c = &fc->classes[i]; | |||
| int j, books; | |||
| @@ -292,6 +311,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| c->masterbook = floor_classes[i].masterbook; | |||
| books = (1 << c->subclass); | |||
| c->books = av_malloc(sizeof(int) * books); | |||
| if (!c->books) | |||
| return AVERROR(ENOMEM); | |||
| for (j = 0; j < books; j++) | |||
| c->books[j] = floor_classes[i].nbooks[j]; | |||
| } | |||
| @@ -303,6 +324,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| fc->values += fc->classes[fc->partition_to_class[i]].dim; | |||
| fc->list = av_malloc(sizeof(vorbis_floor1_entry) * fc->values); | |||
| if (!fc->list) | |||
| return AVERROR(ENOMEM); | |||
| fc->list[0].x = 0; | |||
| fc->list[1].x = 1 << fc->rangebits; | |||
| for (i = 2; i < fc->values; i++) { | |||
| @@ -317,6 +340,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| venc->nresidues = 1; | |||
| venc->residues = av_malloc(sizeof(vorbis_enc_residue) * venc->nresidues); | |||
| if (!venc->residues) | |||
| return AVERROR(ENOMEM); | |||
| // single residue | |||
| rc = &venc->residues[0]; | |||
| @@ -327,6 +352,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| rc->classifications = 10; | |||
| rc->classbook = 15; | |||
| rc->books = av_malloc(sizeof(*rc->books) * rc->classifications); | |||
| if (!rc->books) | |||
| return AVERROR(ENOMEM); | |||
| { | |||
| static const int8_t a[10][8] = { | |||
| { -1, -1, -1, -1, -1, -1, -1, -1, }, | |||
| @@ -342,19 +369,26 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| }; | |||
| memcpy(rc->books, a, sizeof a); | |||
| } | |||
| ready_residue(rc, venc); | |||
| if ((ret = ready_residue(rc, venc)) < 0) | |||
| return ret; | |||
| venc->nmappings = 1; | |||
| venc->mappings = av_malloc(sizeof(vorbis_enc_mapping) * venc->nmappings); | |||
| if (!venc->mappings) | |||
| return AVERROR(ENOMEM); | |||
| // single mapping | |||
| mc = &venc->mappings[0]; | |||
| mc->submaps = 1; | |||
| mc->mux = av_malloc(sizeof(int) * venc->channels); | |||
| if (!mc->mux) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < venc->channels; i++) | |||
| mc->mux[i] = 0; | |||
| mc->floor = av_malloc(sizeof(int) * mc->submaps); | |||
| mc->residue = av_malloc(sizeof(int) * mc->submaps); | |||
| if (!mc->floor || !mc->residue) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < mc->submaps; i++) { | |||
| mc->floor[i] = 0; | |||
| mc->residue[i] = 0; | |||
| @@ -362,6 +396,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| mc->coupling_steps = venc->channels == 2 ? 1 : 0; | |||
| mc->magnitude = av_malloc(sizeof(int) * mc->coupling_steps); | |||
| mc->angle = av_malloc(sizeof(int) * mc->coupling_steps); | |||
| if (!mc->magnitude || !mc->angle) | |||
| return AVERROR(ENOMEM); | |||
| if (mc->coupling_steps) { | |||
| mc->magnitude[0] = 0; | |||
| mc->angle[0] = 1; | |||
| @@ -369,6 +405,8 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| venc->nmodes = 1; | |||
| venc->modes = av_malloc(sizeof(vorbis_enc_mode) * venc->nmodes); | |||
| if (!venc->modes) | |||
| return AVERROR(ENOMEM); | |||
| // single mode | |||
| venc->modes[0].blockflag = 0; | |||
| @@ -379,12 +417,18 @@ static void create_vorbis_context(vorbis_enc_context *venc, | |||
| venc->samples = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1])); | |||
| venc->floor = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); | |||
| venc->coeffs = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); | |||
| if (!venc->saved || !venc->samples || !venc->floor || !venc->coeffs) | |||
| return AVERROR(ENOMEM); | |||
| venc->win[0] = ff_vorbis_vwin[venc->log2_blocksize[0] - 6]; | |||
| venc->win[1] = ff_vorbis_vwin[venc->log2_blocksize[1] - 6]; | |||
| ff_mdct_init(&venc->mdct[0], venc->log2_blocksize[0], 0, 1.0); | |||
| ff_mdct_init(&venc->mdct[1], venc->log2_blocksize[1], 0, 1.0); | |||
| if ((ret = ff_mdct_init(&venc->mdct[0], venc->log2_blocksize[0], 0, 1.0)) < 0) | |||
| return ret; | |||
| if ((ret = ff_mdct_init(&venc->mdct[1], venc->log2_blocksize[1], 0, 1.0)) < 0) | |||
| return ret; | |||
| return 0; | |||
| } | |||
| static void put_float(PutBitContext *pb, float f) | |||
| @@ -647,6 +691,8 @@ static int put_main_header(vorbis_enc_context *venc, uint8_t **out) | |||
| len = hlens[0] + hlens[1] + hlens[2]; | |||
| p = *out = av_mallocz(64 + len + len/255); | |||
| if (!p) | |||
| return AVERROR(ENOMEM); | |||
| *p++ = 2; | |||
| p += av_xiphlacing(p, hlens[0]); | |||
| @@ -952,32 +998,6 @@ static int apply_window_and_mdct(vorbis_enc_context *venc, const signed short *a | |||
| return 1; | |||
| } | |||
| static av_cold int vorbis_encode_init(AVCodecContext *avccontext) | |||
| { | |||
| vorbis_enc_context *venc = avccontext->priv_data; | |||
| if (avccontext->channels != 2) { | |||
| av_log(avccontext, AV_LOG_ERROR, "Current Libav 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 = 0.03; | |||
| 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, | |||
| @@ -1102,6 +1122,43 @@ static av_cold int vorbis_encode_close(AVCodecContext *avccontext) | |||
| return 0 ; | |||
| } | |||
| static av_cold int vorbis_encode_init(AVCodecContext *avccontext) | |||
| { | |||
| vorbis_enc_context *venc = avccontext->priv_data; | |||
| int ret; | |||
| if (avccontext->channels != 2) { | |||
| av_log(avccontext, AV_LOG_ERROR, "Current Libav Vorbis encoder only supports 2 channels.\n"); | |||
| return -1; | |||
| } | |||
| if ((ret = create_vorbis_context(venc, avccontext)) < 0) | |||
| goto error; | |||
| if (avccontext->flags & CODEC_FLAG_QSCALE) | |||
| venc->quality = avccontext->global_quality / (float)FF_QP2LAMBDA / 10.; | |||
| else | |||
| venc->quality = 0.03; | |||
| venc->quality *= venc->quality; | |||
| if ((ret = put_main_header(venc, (uint8_t**)&avccontext->extradata)) < 0) | |||
| goto error; | |||
| avccontext->extradata_size = ret; | |||
| avccontext->frame_size = 1 << (venc->log2_blocksize[0] - 1); | |||
| avccontext->coded_frame = avcodec_alloc_frame(); | |||
| if (!avccontext->coded_frame) { | |||
| ret = AVERROR(ENOMEM); | |||
| goto error; | |||
| } | |||
| return 0; | |||
| error: | |||
| vorbis_encode_close(avccontext); | |||
| return ret; | |||
| } | |||
| AVCodec ff_vorbis_encoder = { | |||
| .name = "vorbis", | |||
| .type = AVMEDIA_TYPE_AUDIO, | |||