* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "get_bits.h"
#include "dsputil.h"
typedef struct TwinContext {
AVCodecContext *avctx;
+ AVFrame frame;
DSPContext dsp;
+ AVFloatDSPContext fdsp;
FFTContext mdct_ctx[3];
const ModeTab *mtab;
float *curr_frame; ///< non-interleaved output
float *prev_frame; ///< non-interleaved previous frame
int last_block_pos[2];
+ int discarded_packets;
float *cos_tabs[3];
}
static void imdct_output(TwinContext *tctx, enum FrameType ftype, int wtype,
- float *out)
+ float **out)
{
const ModeTab *mtab = tctx->mtab;
int size1, size2;
i);
}
+ if (!out)
+ return;
+
size2 = tctx->last_block_pos[0];
size1 = mtab->size - size2;
- if (tctx->avctx->channels == 2) {
- tctx->dsp.butterflies_float_interleave(out, prev_buf,
- &prev_buf[2*mtab->size],
- size1);
-
- out += 2 * size1;
-
- tctx->dsp.butterflies_float_interleave(out, tctx->curr_frame,
- &tctx->curr_frame[2*mtab->size],
- size2);
- } else {
- memcpy(out, prev_buf, size1 * sizeof(*out));
- out += size1;
+ memcpy(&out[0][0 ], prev_buf, size1 * sizeof(out[0][0]));
+ memcpy(&out[0][size1], tctx->curr_frame, size2 * sizeof(out[0][0]));
- memcpy(out, tctx->curr_frame, size2 * sizeof(*out));
+ if (tctx->avctx->channels == 2) {
+ memcpy(&out[1][0], &prev_buf[2*mtab->size], size1 * sizeof(out[1][0]));
+ memcpy(&out[1][size1], &tctx->curr_frame[2*mtab->size], size2 * sizeof(out[1][0]));
+ tctx->dsp.butterflies_float(out[0], out[1], mtab->size);
}
-
}
static void dec_bark_env(TwinContext *tctx, const uint8_t *in, int use_hist,
dec_bark_env(tctx, bark1[i][j], bark_use_hist[i][j], i,
tctx->tmp_buf, gain[sub*i+j], ftype);
- tctx->dsp.vector_fmul(chunk + block_size*j, chunk + block_size*j, tctx->tmp_buf,
- block_size);
+ tctx->fdsp.vector_fmul(chunk + block_size*j, chunk + block_size*j,
+ tctx->tmp_buf, block_size);
}
dec_lpc_spectrum_inv(tctx, lsp, ftype, tctx->tmp_buf);
for (j = 0; j < mtab->fmode[ftype].sub; j++) {
- tctx->dsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
+ tctx->fdsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
chunk += block_size;
}
}
}
static int twin_decode_frame(AVCodecContext * avctx, void *data,
- int *data_size, AVPacket *avpkt)
+ int *got_frame_ptr, AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
TwinContext *tctx = avctx->priv_data;
GetBitContext gb;
const ModeTab *mtab = tctx->mtab;
- float *out = data;
+ float **out = NULL;
enum FrameType ftype;
- int window_type, out_size;
+ int window_type, ret;
static const enum FrameType wtype_to_ftype_table[] = {
FT_LONG, FT_LONG, FT_SHORT, FT_LONG,
FT_MEDIUM, FT_LONG, FT_LONG, FT_MEDIUM, FT_MEDIUM
return AVERROR(EINVAL);
}
- out_size = mtab->size * avctx->channels *
- av_get_bytes_per_sample(avctx->sample_fmt);
- if (*data_size < out_size) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
- return AVERROR(EINVAL);
+ /* get output buffer */
+ if (tctx->discarded_packets >= 2) {
+ tctx->frame.nb_samples = mtab->size;
+ if ((ret = avctx->get_buffer(avctx, &tctx->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ out = (float **)tctx->frame.extended_data;
}
init_get_bits(&gb, buf, buf_size * 8);
FFSWAP(float*, tctx->curr_frame, tctx->prev_frame);
- if (tctx->avctx->frame_number < 2) {
- *data_size=0;
+ if (tctx->discarded_packets < 2) {
+ tctx->discarded_packets++;
+ *got_frame_ptr = 0;
return buf_size;
}
- *data_size = out_size;
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = tctx->frame;;
return buf_size;
}
{
int block_size;
const ModeTab *mtab = tctx->mtab;
- int size = tctx->avctx->channels*mtab->fmode[ftype].sub;
+ int size;
int16_t *tmp_perm = (int16_t *) tctx->tmp_buf;
if (ftype == FT_PPC) {
size = tctx->avctx->channels;
block_size = mtab->ppc_shape_len;
- } else
+ } else {
+ size = tctx->avctx->channels * mtab->fmode[ftype].sub;
block_size = mtab->size / mtab->fmode[ftype].sub;
+ }
permutate_in_line(tmp_perm, tctx->n_div[ftype], size,
block_size, tctx->length[ftype],
int isampf, ibps;
tctx->avctx = avctx;
- avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
if (!avctx->extradata || avctx->extradata_size < 12) {
av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n");
return -1;
}
- dsputil_init(&tctx->dsp, avctx);
+ ff_dsputil_init(&tctx->dsp, avctx);
+ avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
if ((ret = init_mdct_win(tctx))) {
av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n");
twin_decode_close(avctx);
memset_float(tctx->bark_hist[0][0], 0.1, FF_ARRAY_ELEMS(tctx->bark_hist));
+ avcodec_get_frame_defaults(&tctx->frame);
+ avctx->coded_frame = &tctx->frame;
+
return 0;
}
AVCodec ff_twinvq_decoder = {
.name = "twinvq",
.type = AVMEDIA_TYPE_AUDIO,
- .id = CODEC_ID_TWINVQ,
+ .id = AV_CODEC_ID_TWINVQ,
.priv_data_size = sizeof(TwinContext),
.init = twin_decode_init,
.close = twin_decode_close,
.decode = twin_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
+ AV_SAMPLE_FMT_NONE },
};