diff options
Diffstat (limited to 'libavcodec/vorbisenc.c')
-rw-r--r-- | libavcodec/vorbisenc.c | 312 |
1 files changed, 207 insertions, 105 deletions
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index 35bdd57..18a679f 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,7 @@ */ #include <float.h> +#include "libavutil/float_dsp.h" #include "avcodec.h" #include "internal.h" @@ -33,6 +34,9 @@ #include "vorbis.h" #include "vorbis_enc_data.h" +#include "audio_frame_queue.h" +#include "libavfilter/bufferqueue.h" + #define BITSTREAM_WRITER_LE #include "put_bits.h" @@ -108,8 +112,12 @@ typedef struct vorbis_enc_context { float *samples; float *floor; // also used for tmp values for mdct float *coeffs; // also used for residue after floor + float *scratch; // used for tmp values for psy model float quality; + AudioFrameQueue afq; + struct FFBufQueue bufqueue; + int ncodebooks; vorbis_enc_codebook *codebooks; @@ -126,6 +134,8 @@ typedef struct vorbis_enc_context { vorbis_enc_mode *modes; int64_t next_pts; + + AVFloatDSPContext *fdsp; } vorbis_enc_context; #define MAX_CHANNELS 2 @@ -142,9 +152,9 @@ typedef struct vorbis_enc_context { static inline int put_codeword(PutBitContext *pb, vorbis_enc_codebook *cb, int entry) { - assert(entry >= 0); - assert(entry < cb->nentries); - assert(cb->lens[entry]); + av_assert2(entry >= 0); + av_assert2(entry < cb->nentries); + av_assert2(cb->lens[entry]); if (pb->size_in_bits - put_bits_count(pb) < cb->lens[entry]) return AVERROR(EINVAL); put_bits(pb, cb->lens[entry], cb->codewords[entry]); @@ -170,8 +180,8 @@ static int ready_codebook(vorbis_enc_codebook *cb) cb->pow2 = cb->dimensions = NULL; } else { int vals = cb_lookup_vals(cb->lookup, cb->ndimensions, cb->nentries); - cb->dimensions = av_malloc(sizeof(float) * cb->nentries * cb->ndimensions); - cb->pow2 = av_mallocz(sizeof(float) * cb->nentries); + cb->dimensions = av_malloc_array(cb->nentries, sizeof(float) * cb->ndimensions); + cb->pow2 = av_mallocz_array(cb->nentries, sizeof(float)); if (!cb->dimensions || !cb->pow2) return AVERROR(ENOMEM); for (i = 0; i < cb->nentries; i++) { @@ -200,8 +210,8 @@ static int ready_codebook(vorbis_enc_codebook *cb) 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); + av_assert0(rc->type == 2); + rc->maxes = av_mallocz_array(rc->classifications, sizeof(float[2])); if (!rc->maxes) return AVERROR(ENOMEM); for (i = 0; i < rc->classifications; i++) { @@ -236,6 +246,26 @@ static int ready_residue(vorbis_enc_residue *rc, vorbis_enc_context *venc) return 0; } +static av_cold int dsp_init(AVCodecContext *avctx, vorbis_enc_context *venc) +{ + int ret = 0; + + venc->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!venc->fdsp) + return AVERROR(ENOMEM); + + // init windows + venc->win[0] = ff_vorbis_vwin[venc->log2_blocksize[0] - 6]; + venc->win[1] = ff_vorbis_vwin[venc->log2_blocksize[1] - 6]; + + 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 int create_vorbis_context(vorbis_enc_context *venc, AVCodecContext *avctx) { @@ -266,8 +296,8 @@ static int create_vorbis_context(vorbis_enc_context *venc, 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); + cb->lens = av_malloc_array(cb->nentries, sizeof(uint8_t)); + cb->codewords = av_malloc_array(cb->nentries, sizeof(uint32_t)); if (!cb->lens || !cb->codewords) return AVERROR(ENOMEM); memcpy(cb->lens, cvectors[book].clens, cvectors[book].len); @@ -275,7 +305,7 @@ static int create_vorbis_context(vorbis_enc_context *venc, if (cb->lookup) { vals = cb_lookup_vals(cb->lookup, cb->ndimensions, cb->nentries); - cb->quantlist = av_malloc(sizeof(int) * vals); + cb->quantlist = av_malloc_array(vals, sizeof(int)); if (!cb->quantlist) return AVERROR(ENOMEM); for (i = 0; i < vals; i++) @@ -305,7 +335,7 @@ static int create_vorbis_context(vorbis_enc_context *venc, fc->nclasses = FFMAX(fc->nclasses, fc->partition_to_class[i]); } fc->nclasses++; - fc->classes = av_malloc(sizeof(vorbis_enc_floor_class) * fc->nclasses); + fc->classes = av_malloc_array(fc->nclasses, sizeof(vorbis_enc_floor_class)); if (!fc->classes) return AVERROR(ENOMEM); for (i = 0; i < fc->nclasses; i++) { @@ -315,20 +345,20 @@ static int create_vorbis_context(vorbis_enc_context *venc, c->subclass = floor_classes[i].subclass; c->masterbook = floor_classes[i].masterbook; books = (1 << c->subclass); - c->books = av_malloc(sizeof(int) * books); + c->books = av_malloc_array(books, sizeof(int)); if (!c->books) return AVERROR(ENOMEM); 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->rangebits = venc->log2_blocksize[1] - 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(vorbis_floor1_entry) * fc->values); + fc->list = av_malloc_array(fc->values, sizeof(vorbis_floor1_entry)); if (!fc->list) return AVERROR(ENOMEM); fc->list[0].x = 0; @@ -409,29 +439,29 @@ static int create_vorbis_context(vorbis_enc_context *venc, mc->angle[0] = 1; } - venc->nmodes = 1; + venc->nmodes = 2; venc->modes = av_malloc(sizeof(vorbis_enc_mode) * venc->nmodes); if (!venc->modes) return AVERROR(ENOMEM); - // single mode + // Short block venc->modes[0].blockflag = 0; venc->modes[0].mapping = 0; + // Long block + venc->modes[1].blockflag = 1; + venc->modes[1].mapping = 0; venc->have_saved = 0; - venc->saved = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); - 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->saved = av_malloc_array(sizeof(float) * venc->channels, (1 << venc->log2_blocksize[1]) / 2); + venc->samples = av_malloc_array(sizeof(float) * venc->channels, (1 << venc->log2_blocksize[1])); + venc->floor = av_malloc_array(sizeof(float) * venc->channels, (1 << venc->log2_blocksize[1]) / 2); + venc->coeffs = av_malloc_array(sizeof(float) * venc->channels, (1 << venc->log2_blocksize[1]) / 2); + venc->scratch = av_malloc_array(sizeof(float) * venc->channels, (1 << venc->log2_blocksize[1])); - venc->win[0] = ff_vorbis_vwin[venc->log2_blocksize[0] - 6]; - venc->win[1] = ff_vorbis_vwin[venc->log2_blocksize[1] - 6]; + if (!venc->saved || !venc->samples || !venc->floor || !venc->coeffs || !venc->scratch) + return AVERROR(ENOMEM); - 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) + if ((ret = dsp_init(avctx, venc)) < 0) return ret; return 0; @@ -585,9 +615,11 @@ static int put_main_header(vorbis_enc_context *venc, uint8_t **out) { int i; PutBitContext pb; - uint8_t buffer[50000] = {0}, *p = buffer; - int buffer_len = sizeof buffer; int len, hlens[3]; + int buffer_len = 50000; + uint8_t *buffer = av_mallocz(buffer_len), *p = buffer; + if (!buffer) + return AVERROR(ENOMEM); // identification header init_put_bits(&pb, p, buffer_len); @@ -710,6 +742,7 @@ static int put_main_header(vorbis_enc_context *venc, uint8_t **out) buffer_len += hlens[i]; } + av_freep(&buffer); return p - *out; } @@ -880,8 +913,8 @@ static int residue_encode(vorbis_enc_context *venc, vorbis_enc_residue *rc, int classes[MAX_CHANNELS][NUM_RESIDUE_PARTITIONS]; int classwords = venc->codebooks[rc->classbook].ndimensions; - assert(rc->type == 2); - assert(real_ch == 2); + av_assert0(rc->type == 2); + av_assert0(real_ch == 2); for (p = 0; p < partitions; p++) { float max1 = 0.0, max2 = 0.0; int s = rc->begin + p * psize; @@ -964,78 +997,142 @@ static int residue_encode(vorbis_enc_context *venc, vorbis_enc_residue *rc, return 0; } -static int apply_window_and_mdct(vorbis_enc_context *venc, - float **audio, int samples) +static int apply_window_and_mdct(vorbis_enc_context *venc) { - int i, 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.0; - // FIXME use dsp + int channel; + const float * win = venc->win[1]; + int window_len = 1 << (venc->log2_blocksize[1] - 1); + float n = (float)(1 << venc->log2_blocksize[1]) / 4.0; + AVFloatDSPContext *fdsp = venc->fdsp; - if (!venc->have_saved && !samples) - return 0; + for (channel = 0; channel < venc->channels; channel++) { + float *offset = venc->samples + channel * window_len * 2; - 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); + fdsp->vector_fmul(offset, offset, win, window_len); + fdsp->vector_fmul_scalar(offset, offset, 1/n, window_len); + + offset += window_len; + + fdsp->vector_fmul_reverse(offset, offset, win, window_len); + fdsp->vector_fmul_scalar(offset, offset, 1/n, window_len); + + venc->mdct[1].mdct_calc(&venc->mdct[1], venc->coeffs + channel * window_len, + venc->samples + channel * window_len * 2); } + return 1; +} - if (samples) { - for (channel = 0; channel < venc->channels; channel++) { - float * offset = venc->samples + channel*window_len*2 + window_len; - for (i = 0; i < samples; i++) - offset[i] = audio[channel][i] / n * win[window_len - i - 1]; - } - } else { - for (channel = 0; channel < venc->channels; channel++) - memset(venc->samples + channel * window_len * 2 + window_len, - 0, sizeof(float) * window_len); +/* Used for padding the last encoded packet */ +static AVFrame *spawn_empty_frame(AVCodecContext *avctx, int channels) +{ + AVFrame *f = av_frame_alloc(); + int ch; + + if (!f) + return NULL; + + f->format = avctx->sample_fmt; + f->nb_samples = avctx->frame_size; + f->channel_layout = avctx->channel_layout; + + if (av_frame_get_buffer(f, 4)) { + av_frame_free(&f); + return NULL; } - for (channel = 0; channel < venc->channels; channel++) - venc->mdct[0].mdct_calc(&venc->mdct[0], venc->coeffs + channel * window_len, - venc->samples + channel * window_len * 2); + for (ch = 0; ch < channels; ch++) { + size_t bps = av_get_bytes_per_sample(f->format); + memset(f->extended_data[ch], 0, bps * f->nb_samples); + } + return f; +} - if (samples) { - for (channel = 0; channel < venc->channels; channel++) { - float *offset = venc->saved + channel * window_len; - for (i = 0; i < samples; i++) - offset[i] = audio[channel][i] / n * win[i]; +/* Set up audio samples for psy analysis and window/mdct */ +static void move_audio(vorbis_enc_context *venc, int sf_size) +{ + AVFrame *cur = NULL; + int frame_size = 1 << (venc->log2_blocksize[1] - 1); + int subframes = frame_size / sf_size; + int sf, ch; + + /* Copy samples from last frame into current frame */ + if (venc->have_saved) + for (ch = 0; ch < venc->channels; ch++) + memcpy(venc->samples + 2 * ch * frame_size, + venc->saved + ch * frame_size, sizeof(float) * frame_size); + else + for (ch = 0; ch < venc->channels; ch++) + memset(venc->samples + 2 * ch * frame_size, 0, sizeof(float) * frame_size); + + for (sf = 0; sf < subframes; sf++) { + cur = ff_bufqueue_get(&venc->bufqueue); + + for (ch = 0; ch < venc->channels; ch++) { + float *offset = venc->samples + 2 * ch * frame_size + frame_size; + float *save = venc->saved + ch * frame_size; + const float *input = (float *) cur->extended_data[ch]; + const size_t len = cur->nb_samples * sizeof(float); + + memcpy(offset + sf*sf_size, input, len); + memcpy(save + sf*sf_size, input, len); // Move samples for next frame } - venc->have_saved = 1; - } else { - venc->have_saved = 0; + av_frame_free(&cur); } - return 1; + venc->have_saved = 1; + memcpy(venc->scratch, venc->samples, 2 * venc->channels * frame_size); } - static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { vorbis_enc_context *venc = avctx->priv_data; - float **audio = frame ? (float **)frame->extended_data : NULL; - int samples = frame ? frame->nb_samples : 0; + int i, ret, need_more; + int frame_size = 1 << (venc->log2_blocksize[1] - 1); vorbis_enc_mode *mode; vorbis_enc_mapping *mapping; PutBitContext pb; - int i, ret; - if (!apply_window_and_mdct(venc, audio, samples)) + if (frame) { + AVFrame *clone; + if ((ret = ff_af_queue_add(&venc->afq, frame)) < 0) + return ret; + clone = av_frame_clone(frame); + if (!clone) + return AVERROR(ENOMEM); + ff_bufqueue_add(avctx, &venc->bufqueue, clone); + } else + if (!venc->afq.remaining_samples) + return 0; + + need_more = venc->bufqueue.available * avctx->frame_size < frame_size; + need_more = frame && need_more; + if (need_more) return 0; - samples = 1 << (venc->log2_blocksize[0] - 1); - if ((ret = ff_alloc_packet(avpkt, 8192))) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); - return ret; + /* Pad the bufqueue with empty frames for encoding the last packet. */ + if (!frame) { + if (venc->bufqueue.available * avctx->frame_size < frame_size) { + int frames_needed = (frame_size/avctx->frame_size) - venc->bufqueue.available; + int i; + + for (i = 0; i < frames_needed; i++) { + AVFrame *empty = spawn_empty_frame(avctx, venc->channels); + if (!empty) + return AVERROR(ENOMEM); + + ff_bufqueue_add(avctx, &venc->bufqueue, empty); + } + } } + move_audio(venc, avctx->frame_size); + + if (!apply_window_and_mdct(venc)) + return 0; + + if ((ret = ff_alloc_packet2(avctx, avpkt, 8192, 0)) < 0) + return ret; + init_put_bits(&pb, avpkt->data, avpkt->size); if (pb.size_in_bits - put_bits_count(&pb) < 1 + ilog(venc->nmodes - 1)) { @@ -1045,33 +1142,33 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, put_bits(&pb, 1, 0); // magic bit - put_bits(&pb, ilog(venc->nmodes - 1), 0); // 0 bits, the mode + put_bits(&pb, ilog(venc->nmodes - 1), 1); // Mode for current frame - mode = &venc->modes[0]; + mode = &venc->modes[1]; mapping = &venc->mappings[mode->mapping]; if (mode->blockflag) { - put_bits(&pb, 1, 0); - put_bits(&pb, 1, 0); + put_bits(&pb, 1, 1); // Previous windowflag + put_bits(&pb, 1, 1); // Next windowflag } for (i = 0; i < venc->channels; i++) { vorbis_enc_floor *fc = &venc->floors[mapping->floor[mapping->mux[i]]]; uint16_t posts[MAX_FLOOR_VALUES]; - floor_fit(venc, fc, &venc->coeffs[i * samples], posts, samples); - if (floor_encode(venc, fc, &pb, posts, &venc->floor[i * samples], samples)) { + floor_fit(venc, fc, &venc->coeffs[i * frame_size], posts, frame_size); + if (floor_encode(venc, fc, &pb, posts, &venc->floor[i * frame_size], frame_size)) { av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); return AVERROR(EINVAL); } } - for (i = 0; i < venc->channels * samples; i++) + for (i = 0; i < venc->channels * frame_size; 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; + float *mag = venc->coeffs + mapping->magnitude[i] * frame_size; + float *ang = venc->coeffs + mapping->angle[i] * frame_size; int j; - for (j = 0; j < samples; j++) { + for (j = 0; j < frame_size; j++) { float a = ang[j]; ang[j] -= mag[j]; if (mag[j] > 0) @@ -1082,7 +1179,7 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (residue_encode(venc, &venc->residues[mapping->residue[mapping->mux[0]]], - &pb, venc->coeffs, samples, venc->channels)) { + &pb, venc->coeffs, frame_size, venc->channels)) { av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); return AVERROR(EINVAL); } @@ -1090,15 +1187,14 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&pb); avpkt->size = put_bits_count(&pb) >> 3; - avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); - if (frame) { - if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = ff_samples_to_time_base(avctx, frame->pts); - } else { - avpkt->pts = venc->next_pts; + ff_af_queue_remove(&venc->afq, frame_size, &avpkt->pts, &avpkt->duration); + + if (frame_size > avpkt->duration) { + uint8_t *side = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10); + if (!side) + return AVERROR(ENOMEM); + AV_WL32(&side[4], frame_size - avpkt->duration); } - if (avpkt->pts != AV_NOPTS_VALUE) - venc->next_pts = avpkt->pts + avpkt->duration; *got_packet_ptr = 1; return 0; @@ -1155,9 +1251,13 @@ static av_cold int vorbis_encode_close(AVCodecContext *avctx) av_freep(&venc->samples); av_freep(&venc->floor); av_freep(&venc->coeffs); + av_freep(&venc->scratch); + av_freep(&venc->fdsp); ff_mdct_end(&venc->mdct[0]); ff_mdct_end(&venc->mdct[1]); + ff_af_queue_close(&venc->afq); + ff_bufqueue_discard_all(&venc->bufqueue); av_freep(&avctx->extradata); @@ -1170,7 +1270,7 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) int ret; if (avctx->channels != 2) { - av_log(avctx, AV_LOG_ERROR, "Current Libav Vorbis encoder only supports 2 channels.\n"); + av_log(avctx, AV_LOG_ERROR, "Current FFmpeg Vorbis encoder only supports 2 channels.\n"); return -1; } @@ -1181,14 +1281,16 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) if (avctx->flags & AV_CODEC_FLAG_QSCALE) venc->quality = avctx->global_quality / (float)FF_QP2LAMBDA; else - venc->quality = 3.0; + venc->quality = 8; venc->quality *= venc->quality; if ((ret = put_main_header(venc, (uint8_t**)&avctx->extradata)) < 0) goto error; avctx->extradata_size = ret; - avctx->frame_size = 1 << (venc->log2_blocksize[0] - 1); + avctx->frame_size = 64; + + ff_af_queue_init(avctx, &venc->afq); return 0; error: |