summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-03-21 23:47:44 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-03-22 00:40:11 +0100
commit967facb6950549d0cc4e0ba79a056ebc6f93a049 (patch)
tree872266e5d486be0ab8cf9e378bf567c191fba71a /libavcodec
parentf1fdd208cc0a1fce7aaaf6b0fe72b013525f49e0 (diff)
parent6aba117f1273c7704312c6d892c9f552fa0661bb (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (26 commits) adxenc: use AVCodec.encode2() adxenc: Use the AVFrame in ADXContext for coded_frame indeo4: fix out-of-bounds function call. configure: Restructure help output. configure: Internal-only components should not be command-line selectable. vorbisenc: use AVCodec.encode2() libvorbis: use AVCodec.encode2() libopencore-amrnbenc: use AVCodec.encode2() ra144enc: use AVCodec.encode2() nellymoserenc: use AVCodec.encode2() roqaudioenc: use AVCodec.encode2() libspeex: use AVCodec.encode2() libvo_amrwbenc: use AVCodec.encode2() libvo_aacenc: use AVCodec.encode2() wmaenc: use AVCodec.encode2() mpegaudioenc: use AVCodec.encode2() libmp3lame: use AVCodec.encode2() libgsmenc: use AVCodec.encode2() libfaac: use AVCodec.encode2() g726enc: use AVCodec.encode2() ... Conflicts: configure libavcodec/Makefile libavcodec/ac3enc.c libavcodec/adxenc.c libavcodec/libgsm.c libavcodec/libvorbis.c libavcodec/vorbisenc.c libavcodec/wmaenc.c tests/ref/acodec/g722 tests/ref/lavf/asf tests/ref/lavf/ffm tests/ref/lavf/mkv tests/ref/lavf/mpg tests/ref/lavf/rm tests/ref/lavf/ts tests/ref/seek/lavf_asf tests/ref/seek/lavf_ffm tests/ref/seek/lavf_mkv tests/ref/seek/lavf_mpg tests/ref/seek/lavf_rm tests/ref/seek/lavf_ts Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/Makefile19
-rw-r--r--libavcodec/aacenc.c63
-rw-r--r--libavcodec/aacenc.h3
-rw-r--r--libavcodec/ac3enc.c9
-rw-r--r--libavcodec/ac3enc.h8
-rw-r--r--libavcodec/ac3enc_fixed.c3
-rw-r--r--libavcodec/ac3enc_float.c3
-rw-r--r--libavcodec/ac3enc_template.c18
-rw-r--r--libavcodec/adpcmenc.c48
-rw-r--r--libavcodec/adxenc.c43
-rw-r--r--libavcodec/audio_frame_queue.c162
-rw-r--r--libavcodec/audio_frame_queue.h90
-rw-r--r--libavcodec/eac3enc.c2
-rw-r--r--libavcodec/flacenc.c52
-rw-r--r--libavcodec/g722enc.c44
-rw-r--r--libavcodec/g726.c29
-rw-r--r--libavcodec/indeo4.c3
-rw-r--r--libavcodec/libfaac.c62
-rw-r--r--libavcodec/libgsm.c34
-rw-r--r--libavcodec/libmp3lame.c71
-rw-r--r--libavcodec/libopencore-amr.c51
-rw-r--r--libavcodec/libspeexenc.c55
-rw-r--r--libavcodec/libvo-aacenc.c121
-rw-r--r--libavcodec/libvo-amrwbenc.c37
-rw-r--r--libavcodec/libvorbis.c69
-rw-r--r--libavcodec/mpegaudioenc.c29
-rw-r--r--libavcodec/nellymoserenc.c43
-rw-r--r--libavcodec/ra144.h2
-rw-r--r--libavcodec/ra144enc.c46
-rw-r--r--libavcodec/roqaudioenc.c42
-rw-r--r--libavcodec/vorbisenc.c43
-rw-r--r--libavcodec/wmaenc.c48
32 files changed, 1031 insertions, 321 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 92e68fad86..ec29ce5ef1 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -61,7 +61,8 @@ OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps.o \
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \
aacpsy.o aactab.o \
psymodel.o iirfilter.o \
- mpeg4audio.o kbdwin.o
+ mpeg4audio.o kbdwin.o \
+ audio_frame_queue.o
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \
@@ -314,7 +315,8 @@ OBJS-$(CONFIG_MSVIDEO1_ENCODER) += msvideo1enc.o elbg.o
OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o
OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o
-OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o
+OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o \
+ audio_frame_queue.o
OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o
OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o
OBJS-$(CONFIG_PAM_ENCODER) += pamenc.o pnm.o
@@ -353,7 +355,8 @@ OBJS-$(CONFIG_R10K_ENCODER) += r210enc.o
OBJS-$(CONFIG_R210_DECODER) += r210dec.o
OBJS-$(CONFIG_R210_ENCODER) += r210enc.o
OBJS-$(CONFIG_RA_144_DECODER) += ra144dec.o ra144.o celp_filters.o
-OBJS-$(CONFIG_RA_144_ENCODER) += ra144enc.o ra144.o celp_filters.o
+OBJS-$(CONFIG_RA_144_ENCODER) += ra144enc.o ra144.o celp_filters.o \
+ audio_frame_queue.o
OBJS-$(CONFIG_RA_288_DECODER) += ra288.o celp_math.o celp_filters.o
OBJS-$(CONFIG_RALF_DECODER) += ralf.o
OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o
@@ -630,12 +633,13 @@ OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o
OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
OBJS-$(CONFIG_LIBDIRAC_DECODER) += libdiracdec.o
-OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o
+OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o audio_frame_queue.o
OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o
-OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o
+OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o \
+ audio_frame_queue.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o
OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o
@@ -648,14 +652,15 @@ OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o \
libschroedinger.o \
libdirac_libschro.o
OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o
-OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o
+OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o audio_frame_queue.o
OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o
OBJS-$(CONFIG_LIBUTVIDEO_DECODER) += libutvideodec.o
OBJS-$(CONFIG_LIBUTVIDEO_ENCODER) += libutvideoenc.o
OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o
OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o
-OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbis.o vorbis_data.o
+OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbis.o audio_frame_queue.o \
+ vorbis_data.o vorbis_parser.o
OBJS-$(CONFIG_LIBVPX_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 14be58f885..0ad0730816 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -34,6 +34,7 @@
#include "avcodec.h"
#include "put_bits.h"
#include "dsputil.h"
+#include "internal.h"
#include "mpeg4audio.h"
#include "kbdwin.h"
#include "sinewin.h"
@@ -476,8 +477,7 @@ static void put_bitstream_info(AVCodecContext *avctx, AACEncContext *s,
* Deinterleave input samples.
* Channels are reordered from libavcodec's default order to AAC order.
*/
-static void deinterleave_input_samples(AACEncContext *s,
- const float *samples, int nb_samples)
+static void deinterleave_input_samples(AACEncContext *s, AVFrame *frame)
{
int ch, i;
const int sinc = s->channels;
@@ -485,35 +485,43 @@ static void deinterleave_input_samples(AACEncContext *s,
/* deinterleave and remap input samples */
for (ch = 0; ch < sinc; ch++) {
- const float *sptr = samples + channel_map[ch];
-
/* copy last 1024 samples of previous frame to the start of the current frame */
memcpy(&s->planar_samples[ch][1024], &s->planar_samples[ch][2048], 1024 * sizeof(s->planar_samples[0][0]));
/* deinterleave */
- for (i = 2048; i < 2048 + nb_samples; i++) {
- s->planar_samples[ch][i] = *sptr;
- sptr += sinc;
+ i = 2048;
+ if (frame) {
+ const float *sptr = ((const float *)frame->data[0]) + channel_map[ch];
+ for (; i < 2048 + frame->nb_samples; i++) {
+ s->planar_samples[ch][i] = *sptr;
+ sptr += sinc;
+ }
}
memset(&s->planar_samples[ch][i], 0,
(3072 - i) * sizeof(s->planar_samples[0][0]));
}
}
-static int aac_encode_frame(AVCodecContext *avctx,
- uint8_t *frame, int buf_size, void *data)
+static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
AACEncContext *s = avctx->priv_data;
float **samples = s->planar_samples, *samples2, *la, *overlap;
ChannelElement *cpe;
- int i, ch, w, g, chans, tag, start_ch;
+ int i, ch, w, g, chans, tag, start_ch, ret;
int chan_el_counter[4];
FFPsyWindowInfo windows[AAC_MAX_CHANNELS];
if (s->last_frame == 2)
return 0;
- deinterleave_input_samples(s, data, data ? avctx->frame_size : 0);
+ /* add current frame to queue */
+ if (frame) {
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
+ }
+
+ deinterleave_input_samples(s, frame);
if (s->psypp)
ff_psy_preprocess(s->psypp, s->planar_samples, s->channels);
@@ -532,7 +540,7 @@ static int aac_encode_frame(AVCodecContext *avctx,
overlap = &samples[cur_channel][0];
samples2 = overlap + 1024;
la = samples2 + (448+64);
- if (!data)
+ if (!frame)
la = NULL;
if (tag == TYPE_LFE) {
wi[ch].window_type[0] = ONLY_LONG_SEQUENCE;
@@ -565,7 +573,13 @@ static int aac_encode_frame(AVCodecContext *avctx,
}
do {
int frame_bits;
- init_put_bits(&s->pb, frame, buf_size*8);
+
+ if ((ret = ff_alloc_packet(avpkt, 768 * s->channels))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ init_put_bits(&s->pb, avpkt->data, avpkt->size);
+
if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & CODEC_FLAG_BITEXACT))
put_bitstream_info(avctx, s, LIBAVCODEC_IDENT);
start_ch = 0;
@@ -645,10 +659,15 @@ static int aac_encode_frame(AVCodecContext *avctx,
s->lambda = FFMIN(s->lambda, 65536.f);
}
- if (!data)
+ if (!frame)
s->last_frame++;
- return put_bits_count(&s->pb)>>3;
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = put_bits_count(&s->pb) >> 3;
+ *got_packet_ptr = 1;
+ return 0;
}
static av_cold int aac_encode_end(AVCodecContext *avctx)
@@ -662,6 +681,10 @@ static av_cold int aac_encode_end(AVCodecContext *avctx)
ff_psy_preprocess_end(s->psypp);
av_freep(&s->buffer.samples);
av_freep(&s->cpe);
+ ff_af_queue_close(&s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
+ av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -695,6 +718,11 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s)
for(ch = 0; ch < s->channels; ch++)
s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch;
+#if FF_API_OLD_ENCODE_AUDIO
+ if (!(avctx->coded_frame = avcodec_alloc_frame()))
+ goto alloc_fail;
+#endif
+
return 0;
alloc_fail:
return AVERROR(ENOMEM);
@@ -756,6 +784,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
for (i = 0; i < 428; i++)
ff_aac_pow34sf_tab[i] = sqrt(ff_aac_pow2sf_tab[i] * sqrt(ff_aac_pow2sf_tab[i]));
+ avctx->delay = 1024;
+ ff_af_queue_init(avctx, &s->afq);
+
return 0;
fail:
aac_encode_end(avctx);
@@ -785,7 +816,7 @@ AVCodec ff_aac_encoder = {
.id = CODEC_ID_AAC,
.priv_data_size = sizeof(AACEncContext),
.init = aac_encode_init,
- .encode = aac_encode_frame,
+ .encode2 = aac_encode_frame,
.close = aac_encode_end,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index d87cc0479b..35a2565ef4 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -27,7 +27,7 @@
#include "dsputil.h"
#include "aac.h"
-
+#include "audio_frame_queue.h"
#include "psymodel.h"
#define AAC_CODER_NB 4
@@ -74,6 +74,7 @@ typedef struct AACEncContext {
int cur_channel;
int last_frame;
float lambda;
+ AudioFrameQueue afq;
DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients
DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 9d72a3bd88..3d01249285 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -2050,7 +2050,9 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx)
s->mdct_end(s);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -2434,6 +2436,7 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx)
return ret;
avctx->frame_size = AC3_BLOCK_SIZE * s->num_blocks;
+ avctx->delay = AC3_BLOCK_SIZE;
s->bitstream_mode = avctx->audio_service_type;
if (s->bitstream_mode == AV_AUDIO_SERVICE_TYPE_KARAOKE)
@@ -2479,9 +2482,13 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx)
if (ret)
goto init_fail;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame= avcodec_alloc_frame();
- if (!avctx->coded_frame)
+ if (!avctx->coded_frame) {
+ ret = AVERROR(ENOMEM);
goto init_fail;
+ }
+#endif
ff_dsputil_init(&s->dsp, avctx);
ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT);
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 6ef1a5373a..e8415a2d69 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -297,9 +297,9 @@ int ff_ac3_float_mdct_init(AC3EncodeContext *s);
int ff_ac3_fixed_allocate_sample_buffers(AC3EncodeContext *s);
int ff_ac3_float_allocate_sample_buffers(AC3EncodeContext *s);
-int ff_ac3_fixed_encode_frame(AVCodecContext *avctx, unsigned char *frame,
- int buf_size, void *data);
-int ff_ac3_float_encode_frame(AVCodecContext *avctx, unsigned char *frame,
- int buf_size, void *data);
+int ff_ac3_fixed_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr);
+int ff_ac3_float_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr);
#endif /* AVCODEC_AC3ENC_H */
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index 24612c0949..758dde3382 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -28,6 +28,7 @@
#define CONFIG_FFT_FLOAT 0
#undef CONFIG_AC3ENC_FLOAT
+#include "internal.h"
#include "ac3enc.h"
#include "eac3enc.h"
@@ -151,7 +152,7 @@ AVCodec ff_ac3_fixed_encoder = {
.id = CODEC_ID_AC3,
.priv_data_size = sizeof(AC3EncodeContext),
.init = ac3_fixed_encode_init,
- .encode = ff_ac3_fixed_encode_frame,
+ .encode2 = ff_ac3_fixed_encode_frame,
.close = ff_ac3_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 073045c9e0..44491beb19 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -27,6 +27,7 @@
*/
#define CONFIG_AC3ENC_FLOAT 1
+#include "internal.h"
#include "ac3enc.h"
#include "eac3enc.h"
#include "kbdwin.h"
@@ -149,7 +150,7 @@ AVCodec ff_ac3_encoder = {
.id = CODEC_ID_AC3,
.priv_data_size = sizeof(AC3EncodeContext),
.init = ff_ac3_encode_init,
- .encode = ff_ac3_float_encode_frame,
+ .encode2 = ff_ac3_float_encode_frame,
.close = ff_ac3_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c
index 554e0b007b..a9a221b25a 100644
--- a/libavcodec/ac3enc_template.c
+++ b/libavcodec/ac3enc_template.c
@@ -386,11 +386,11 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
}
-int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
- int buf_size, void *data)
+int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
AC3EncodeContext *s = avctx->priv_data;
- const SampleType *samples = data;
+ const SampleType *samples = (const SampleType *)frame->data[0];
int ret;
if (s->options.allow_per_frame_metadata) {
@@ -437,7 +437,15 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
ff_ac3_quantize_mantissas(s);
- ff_ac3_output_frame(s, frame);
+ if ((ret = ff_alloc_packet(avpkt, s->frame_size))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ ff_ac3_output_frame(s, avpkt->data);
- return s->frame_size;
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
+
+ *got_packet_ptr = 1;
+ return 0;
}
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 246b5887d9..572261ae7d 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -24,6 +24,7 @@
#include "bytestream.h"
#include "adpcm.h"
#include "adpcm_data.h"
+#include "internal.h"
/**
* @file
@@ -144,8 +145,10 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
goto error;
}
+#if FF_API_OLD_ENCODE_AUDIO
if (!(avctx->coded_frame = avcodec_alloc_frame()))
goto error;
+#endif
return 0;
error:
@@ -156,7 +159,9 @@ error:
static av_cold int adpcm_encode_close(AVCodecContext *avctx)
{
ADPCMEncodeContext *s = avctx->priv_data;
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&s->paths);
av_freep(&s->node_buf);
av_freep(&s->nodep_buf);
@@ -473,23 +478,31 @@ static void adpcm_compress_trellis(AVCodecContext *avctx,
c->idelta = nodes[0]->step;
}
-static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
- int buf_size, void *data)
+static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
- int n, i, st;
- int16_t *samples;
+ int n, i, st, pkt_size, ret;
+ const int16_t *samples;
uint8_t *dst;
ADPCMEncodeContext *c = avctx->priv_data;
uint8_t *buf;
- dst = frame;
- samples = data;
+ samples = (const int16_t *)frame->data[0];
st = avctx->channels == 2;
- /* n = (BLKSIZE - 4 * avctx->channels) / (2 * 8 * avctx->channels); */
+
+ if (avctx->codec_id == CODEC_ID_ADPCM_SWF)
+ pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8;
+ else
+ pkt_size = avctx->block_align;
+ if ((ret = ff_alloc_packet(avpkt, pkt_size))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ dst = avpkt->data;
switch(avctx->codec->id) {
case CODEC_ID_ADPCM_IMA_WAV:
- n = avctx->frame_size / 8;
+ n = frame->nb_samples / 8;
c->status[0].prev_sample = samples[0];
/* c->status[0].step_index = 0;
XXX: not sure how to init the state machine */
@@ -557,7 +570,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
{
int ch, i;
PutBitContext pb;
- init_put_bits(&pb, dst, buf_size * 8);
+ init_put_bits(&pb, dst, pkt_size * 8);
for (ch = 0; ch < avctx->channels; ch++) {
put_bits(&pb, 9, (c->status[ch].prev_sample + 0x10000) >> 7);
@@ -581,16 +594,15 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
}
flush_put_bits(&pb);
- dst += put_bits_count(&pb) >> 3;
break;
}
case CODEC_ID_ADPCM_SWF:
{
int i;
PutBitContext pb;
- init_put_bits(&pb, dst, buf_size * 8);
+ init_put_bits(&pb, dst, pkt_size * 8);
- n = avctx->frame_size - 1;
+ n = frame->nb_samples - 1;
// store AdpcmCodeSize
put_bits(&pb, 2, 2); // set 4-bit flash adpcm format
@@ -617,7 +629,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
}
av_free(buf);
} else {
- for (i = 1; i < avctx->frame_size; i++) {
+ for (i = 1; i < frame->nb_samples; i++) {
put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0],
samples[avctx->channels * i]));
if (avctx->channels == 2)
@@ -626,7 +638,6 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
}
}
flush_put_bits(&pb);
- dst += put_bits_count(&pb) >> 3;
break;
}
case CODEC_ID_ADPCM_MS:
@@ -674,7 +685,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
}
break;
case CODEC_ID_ADPCM_YAMAHA:
- n = avctx->frame_size / 2;
+ n = frame->nb_samples / 2;
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error);
n *= 2;
@@ -700,7 +711,10 @@ static int adpcm_encode_frame(AVCodecContext *avctx, uint8_t *frame,
default:
return AVERROR(EINVAL);
}
- return dst - frame;
+
+ avpkt->size = pkt_size;
+ *got_packet_ptr = 1;
+ return 0;
error:
return AVERROR(ENOMEM);
}
@@ -713,7 +727,7 @@ AVCodec ff_ ## name_ ## _encoder = { \
.id = id_, \
.priv_data_size = sizeof(ADPCMEncodeContext), \
.init = adpcm_encode_init, \
- .encode = adpcm_encode_frame, \
+ .encode2 = adpcm_encode_frame, \
.close = adpcm_encode_close, \
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, \
AV_SAMPLE_FMT_NONE}, \
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index c6e46565f6..5ab53dd1ea 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -22,6 +22,7 @@
#include "avcodec.h"
#include "adx.h"
#include "bytestream.h"
+#include "internal.h"
#include "put_bits.h"
/**
@@ -87,9 +88,6 @@ static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize)
{
ADXContext *c = avctx->priv_data;
- if (bufsize < HEADER_SIZE)
- return AVERROR(EINVAL);
-
bytestream_put_be16(&buf, 0x8000); /* header signature */
bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */
bytestream_put_byte(&buf, 3); /* encoding */
@@ -119,9 +117,11 @@ static av_cold int adx_encode_init(AVCodecContext *avctx)
}
avctx->frame_size = BLOCK_SAMPLES;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
+#endif
/* the cutoff can be adjusted, but this seems to work pretty well */
c->cutoff = 500;
@@ -130,40 +130,38 @@ static av_cold int adx_encode_init(AVCodecContext *avctx)
return 0;
}
-static av_cold int adx_encode_close(AVCodecContext *avctx)
-{
- av_freep(&avctx->coded_frame);
- return 0;
-}
-
-static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame,
- int buf_size, void *data)
+static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
ADXContext *c = avctx->priv_data;
- const int16_t *samples = data;
- uint8_t *dst = frame;
- int ch;
+ const int16_t *samples = (const int16_t *)frame->data[0];
+ uint8_t *dst;
+ int ch, out_size, ret;
+
+ out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE;
+ if ((ret = ff_alloc_packet(avpkt, out_size)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ dst = avpkt->data;
if (!c->header_parsed) {
int hdrsize;
- if ((hdrsize = adx_encode_header(avctx, dst, buf_size)) < 0) {
+ if ((hdrsize = adx_encode_header(avctx, dst, avpkt->size)) < 0) {
av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
return AVERROR(EINVAL);
}
dst += hdrsize;
- buf_size -= hdrsize;
c->header_parsed = 1;
}
- if (buf_size < BLOCK_SIZE * avctx->channels) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
- return AVERROR(EINVAL);
- }
for (ch = 0; ch < avctx->channels; ch++) {
adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels);
dst += BLOCK_SIZE;
}
- return dst - frame;
+
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_adpcm_adx_encoder = {
@@ -172,8 +170,7 @@ AVCodec ff_adpcm_adx_encoder = {
.id = CODEC_ID_ADPCM_ADX,
.priv_data_size = sizeof(ADXContext),
.init = adx_encode_init,
- .encode = adx_encode_frame,
- .close = adx_encode_close,
+ .encode2 = adx_encode_frame,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"),
diff --git a/libavcodec/audio_frame_queue.c b/libavcodec/audio_frame_queue.c
new file mode 100644
index 0000000000..156c3a109b
--- /dev/null
+++ b/libavcodec/audio_frame_queue.c
@@ -0,0 +1,162 @@
+/*
+ * Audio Frame Queue
+ * Copyright (c) 2012 Justin Ruggles
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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,
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/mathematics.h"
+#include "internal.h"
+#include "audio_frame_queue.h"
+
+void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)
+{
+ afq->avctx = avctx;
+ afq->next_pts = AV_NOPTS_VALUE;
+ afq->remaining_delay = avctx->delay;
+ afq->remaining_samples = avctx->delay;
+ afq->frame_queue = NULL;
+}
+
+static void delete_next_frame(AudioFrameQueue *afq)
+{
+ AudioFrame *f = afq->frame_queue;
+ if (f) {
+ afq->frame_queue = f->next;
+ f->next = NULL;
+ av_freep(&f);
+ }
+}
+
+void ff_af_queue_close(AudioFrameQueue *afq)
+{
+ /* remove/free any remaining frames */
+ while (afq->frame_queue)
+ delete_next_frame(afq);
+ memset(afq, 0, sizeof(*afq));
+}
+
+int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
+{
+ AudioFrame *new_frame;
+ AudioFrame *queue_end = afq->frame_queue;
+
+ /* find the end of the queue */
+ while (queue_end && queue_end->next)
+ queue_end = queue_end->next;
+
+ /* allocate new frame queue entry */
+ if (!(new_frame = av_malloc(sizeof(*new_frame))))
+ return AVERROR(ENOMEM);
+
+ /* get frame parameters */
+ new_frame->next = NULL;
+ new_frame->duration = f->nb_samples;
+ if (f->pts != AV_NOPTS_VALUE) {
+ new_frame->pts = av_rescale_q(f->pts,
+ afq->avctx->time_base,
+ (AVRational){ 1, afq->avctx->sample_rate });
+ afq->next_pts = new_frame->pts + new_frame->duration;
+ } else {
+ new_frame->pts = AV_NOPTS_VALUE;
+ afq->next_pts = AV_NOPTS_VALUE;
+ }
+
+ /* add new frame to the end of the queue */
+ if (!queue_end)
+ afq->frame_queue = new_frame;
+ else
+ queue_end->next = new_frame;
+
+ /* add frame sample count */
+ afq->remaining_samples += f->nb_samples;
+
+#ifdef DEBUG
+ ff_af_queue_log_state(afq);
+#endif
+
+ return 0;
+}
+
+void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
+ int *duration)
+{
+ int64_t out_pts = AV_NOPTS_VALUE;
+ int removed_samples = 0;
+
+#ifdef DEBUG
+ ff_af_queue_log_state(afq);
+#endif
+
+ /* get output pts from the next frame or generated pts */
+ if (afq->frame_queue) {
+ if (afq->frame_queue->pts != AV_NOPTS_VALUE)
+ out_pts = afq->frame_queue->pts - afq->remaining_delay;
+ } else {
+ if (afq->next_pts != AV_NOPTS_VALUE)
+ out_pts = afq->next_pts - afq->remaining_delay;
+ }
+ if (pts) {
+ if (out_pts != AV_NOPTS_VALUE)
+ *pts = ff_samples_to_time_base(afq->avctx, out_pts);
+ else
+ *pts = AV_NOPTS_VALUE;
+ }
+
+ /* if the delay is larger than the packet duration, we use up delay samples
+ for the output packet and leave all frames in the queue */
+ if (afq->remaining_delay >= nb_samples) {
+ removed_samples += nb_samples;
+ afq->remaining_delay -= nb_samples;
+ }
+ /* remove frames from the queue until we have enough to cover the
+ requested number of samples or until the queue is empty */
+ while (removed_samples < nb_samples && afq->frame_queue) {
+ removed_samples += afq->frame_queue->duration;
+ delete_next_frame(afq);
+ }
+ afq->remaining_samples -= removed_samples;
+
+ /* if there are no frames left and we have room for more samples, use
+ any remaining delay samples */
+ if (removed_samples < nb_samples && afq->remaining_samples > 0) {
+ int add_samples = FFMIN(afq->remaining_samples,
+ nb_samples - removed_samples);
+ removed_samples += add_samples;
+ afq->remaining_samples -= add_samples;
+ }
+ if (removed_samples > nb_samples)
+ av_log(afq->avctx, AV_LOG_WARNING, "frame_size is too large\n");
+ if (duration)
+ *duration = ff_samples_to_time_base(afq->avctx, removed_samples);
+}
+
+void ff_af_queue_log_state(AudioFrameQueue *afq)
+{
+ AudioFrame *f;
+ av_log(afq->avctx, AV_LOG_DEBUG, "remaining delay = %d\n",
+ afq->remaining_delay);
+ av_log(afq->avctx, AV_LOG_DEBUG, "remaining samples = %d\n",
+ afq->remaining_samples);
+ av_log(afq->avctx, AV_LOG_DEBUG, "frames:\n");
+ f = afq->frame_queue;
+ while (f) {
+ av_log(afq->avctx, AV_LOG_DEBUG, " [ pts=%9"PRId64" duration=%d ]\n",
+ f->pts, f->duration);
+ f = f->next;
+ }
+}
diff --git a/libavcodec/audio_frame_queue.h b/libavcodec/audio_frame_queue.h
new file mode 100644
index 0000000000..cfcc6a030c
--- /dev/null
+++ b/libavcodec/audio_frame_queue.h
@@ -0,0 +1,90 @@
+/*
+ * Audio Frame Queue
+ * Copyright (c) 2012 Justin Ruggles
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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,
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_AUDIO_FRAME_QUEUE_H
+#define AVCODEC_AUDIO_FRAME_QUEUE_H
+
+#include "avcodec.h"
+
+typedef struct AudioFrame {
+ int64_t pts;
+ int duration;
+ struct AudioFrame *next;
+} AudioFrame;
+
+typedef struct AudioFrameQueue {
+ AVCodecContext *avctx;
+ int64_t next_pts;
+ int remaining_delay;
+ int remaining_samples;
+ AudioFrame *frame_queue;
+} AudioFrameQueue;
+
+/**
+ * Initialize AudioFrameQueue.
+ *
+ * @param avctx context to use for time_base and av_log
+ * @param afq queue context
+ */
+void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq);
+
+/**
+ * Close AudioFrameQueue.
+ *
+ * Frees memory if needed.
+ *
+ * @param afq queue context
+ */
+void ff_af_queue_close(AudioFrameQueue *afq);
+
+/**
+ * Add a frame to the queue.
+ *
+ * @param afq queue context
+ * @param f frame to add to the queue
+ */
+int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f);
+
+/**
+ * Remove frame(s) from the queue.
+ *
+ * Retrieves the pts of the next available frame, or a generated pts based on
+ * the last frame duration if there are no frames left in the queue. The number
+ * of requested samples should be the full number of samples represented by the
+ * packet that will be output by the encoder. If fewer samples are available
+ * in the queue, a smaller value will be used for the output duration.
+ *
+ * @param afq queue context
+ * @param nb_samples number of samples to remove from the queue
+ * @param[out] pts output packet pts
+ * @param[out] duration output packet duration
+ */
+void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
+ int *duration);
+
+/**
+ * Log the current state of the queue.
+ *
+ * @param afq queue context
+ */
+void ff_af_queue_log_state(AudioFrameQueue *afq);
+
+#endif /* AVCODEC_AUDIO_FRAME_QUEUE_H */
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index 459fb90ce6..eb35211c73 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -252,7 +252,7 @@ AVCodec ff_eac3_encoder = {
.id = CODEC_ID_EAC3,
.priv_data_size = sizeof(AC3EncodeContext),
.init = ff_ac3_encode_init,
- .encode = ff_ac3_float_encode_frame,
+ .encode2 = ff_ac3_float_encode_frame,
.close = ff_ac3_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_FLT,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"),
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index ecf883e652..e8d6e8cb21 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -25,6 +25,7 @@
#include "avcodec.h"
#include "get_bits.h"
#include "golomb.h"
+#include "internal.h"
#include "lpc.h"
#include "flac.h"
#include "flacdata.h"
@@ -367,9 +368,11 @@ static av_cold int flac_encode_init(AVCodecContext *avctx)
s->frame_count = 0;
s->min_framesize = s->max_framesize;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
+#endif
if (channels == 3 &&
avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) ||
@@ -402,7 +405,7 @@ static av_cold int flac_encode_init(AVCodecContext *avctx)
}
-static void init_frame(FlacEncodeContext *s)
+static void init_frame(FlacEncodeContext *s, int nb_samples)
{
int i, ch;
FlacFrame *frame;
@@ -410,7 +413,7 @@ static void init_frame(FlacEncodeContext *s)
frame = &s->frame;
for (i = 0; i < 16; i++) {
- if (s->avctx->frame_size == ff_flac_blocksize_table[i]) {
+ if (nb_samples == ff_flac_blocksize_table[i]) {
frame->blocksize = ff_flac_blocksize_table[i];
frame->bs_code[0] = i;
frame->bs_code[1] = 0;
@@ -418,7 +421,7 @@ static void init_frame(FlacEncodeContext *s)
}
}
if (i == 16) {
- frame->blocksize = s->avctx->frame_size;
+ frame->blocksize = nb_samples;
if (frame->blocksize <= 256) {
frame->bs_code[0] = 6;
frame->bs_code[1] = frame->blocksize-1;
@@ -1188,9 +1191,9 @@ static void write_frame_footer(FlacEncodeContext *s)
}
-static int write_frame(FlacEncodeContext *s, uint8_t *frame, int buf_size)
+static int write_frame(FlacEncodeContext *s, AVPacket *avpkt)
{
- init_put_bits(&s->pb, frame, buf_size);
+ init_put_bits(&s->pb, avpkt->data, avpkt->size);
write_frame_header(s);
write_subframes(s);
write_frame_footer(s);
@@ -1212,30 +1215,31 @@ static void update_md5_sum(FlacEncodeContext *s, const int16_t *samples)
}
-static int flac_encode_frame(AVCodecContext *avctx, uint8_t *frame,
- int buf_size, void *data)
+static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
FlacEncodeContext *s;
- const int16_t *samples = data;
- int frame_bytes, out_bytes;
+ const int16_t *samples;
+ int frame_bytes, out_bytes, ret;
s = avctx->priv_data;
/* when the last block is reached, update the header in extradata */
- if (!data) {
+ if (!frame) {
s->max_framesize = s->max_encoded_framesize;
av_md5_final(s->md5ctx, s->md5sum);
write_streaminfo(s, avctx->extradata);
return 0;
}
+ samples = (const int16_t *)frame->data[0];
/* change max_framesize for small final frame */
- if (avctx->frame_size < s->frame.blocksize) {
- s->max_framesize = ff_flac_get_max_frame_size(avctx->frame_size,
+ if (frame->nb_samples < s->frame.blocksize) {
+ s->max_framesize = ff_flac_get_max_frame_size(frame->nb_samples,
s->channels, 16);
}
- init_frame(s);
+ init_frame(s, frame->nb_samples);
copy_samples(s, samples);
@@ -1250,22 +1254,26 @@ static int flac_encode_frame(AVCodecContext *avctx, uint8_t *frame,
frame_bytes = encode_frame(s);
}
- if (buf_size < frame_bytes) {
- av_log(avctx, AV_LOG_ERROR, "output buffer too small\n");
- return 0;
+ if ((ret = ff_alloc_packet(avpkt, frame_bytes))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
}
- out_bytes = write_frame(s, frame, buf_size);
+
+ out_bytes = write_frame(s, avpkt);
s->frame_count++;
- avctx->coded_frame->pts = s->sample_count;
- s->sample_count += avctx->frame_size;
+ s->sample_count += frame->nb_samples;
update_md5_sum(s, samples);
if (out_bytes > s->max_encoded_framesize)
s->max_encoded_framesize = out_bytes;
if (out_bytes < s->min_framesize)
s->min_framesize = out_bytes;
- return out_bytes;
+ avpkt->pts = frame->pts;
+ avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
+ avpkt->size = out_bytes;
+ *got_packet_ptr = 1;
+ return 0;
}
@@ -1278,7 +1286,9 @@ static av_cold int flac_encode_close(AVCodecContext *avctx)
}
av_freep(&avctx->extradata);
avctx->extradata_size = 0;
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -1316,7 +1326,7 @@ AVCodec ff_flac_encoder = {
.id = CODEC_ID_FLAC,
.priv_data_size = sizeof(FlacEncodeContext),
.init = flac_encode_init,
- .encode = flac_encode_frame,
+ .encode2 = flac_encode_frame,
.close = flac_encode_close,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | CODEC_CAP_LOSSLESS,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c
index ba8ceeff86..424dd237dc 100644
--- a/libavcodec/g722enc.c
+++ b/libavcodec/g722enc.c
@@ -28,6 +28,7 @@
*/
#include "avcodec.h"
+#include "internal.h"
#include "g722.h"
#define FREEZE_INTERVAL 128
@@ -50,6 +51,9 @@ static av_cold int g722_encode_close(AVCodecContext *avctx)
av_freep(&c->node_buf[i]);
av_freep(&c->nodep_buf[i]);
}
+#if FF_API_OLD_ENCODE_AUDIO
+ av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -104,6 +108,7 @@ static av_cold int g722_encode_init(AVCodecContext * avctx)
a common packet size for VoIP applications */
avctx->frame_size = 320;
}
+ avctx->delay = 22;
if (avctx->trellis) {
/* validate trellis */
@@ -116,6 +121,14 @@ static av_cold int g722_encode_init(AVCodecContext * avctx)
}
}
+#if FF_API_OLD_ENCODE_AUDIO
+ avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame) {
+ ret = AVERROR(ENOMEM);
+ goto error;
+ }
+#endif
+
return 0;
error:
g722_encode_close(avctx);
@@ -345,27 +358,36 @@ static void g722_encode_no_trellis(G722Context *c,
encode_byte(c, dst++, &samples[i]);
}
-static int g722_encode_frame(AVCodecContext *avctx,
- uint8_t *dst, int buf_size, void *data)
+static int g722_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
G722Context *c = avctx->priv_data;
- const int16_t *samples = data;
- int nb_samples;
+ const int16_t *samples = (const int16_t *)frame->data[0];
+ int nb_samples, out_size, ret;
- nb_samples = avctx->frame_size - (avctx->frame_size & 1);
+ out_size = (frame->nb_samples + 1) / 2;
+ if ((ret = ff_alloc_packet(avpkt, out_size))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ nb_samples = frame->nb_samples - (frame->nb_samples & 1);
if (avctx->trellis)
- g722_encode_trellis(c, avctx->trellis, dst, nb_samples, samples);
+ g722_encode_trellis(c, avctx->trellis, avpkt->data, nb_samples, samples);
else
- g722_encode_no_trellis(c, dst, nb_samples, samples);
+ g722_encode_no_trellis(c, avpkt->data, nb_samples, samples);
/* handle last frame with odd frame_size */
- if (nb_samples < avctx->frame_size) {
+ if (nb_samples < frame->nb_samples) {
int16_t last_samples[2] = { samples[nb_samples], samples[nb_samples] };
- encode_byte(c, &dst[nb_samples >> 1], last_samples);
+ encode_byte(c, &avpkt->data[nb_samples >> 1], last_samples);
}
- return (avctx->frame_size + 1) >> 1;
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_adpcm_g722_encoder = {
@@ -375,7 +397,7 @@ AVCodec ff_adpcm_g722_encoder = {
.priv_data_size = sizeof(G722Context),
.init = g722_encode_init,
.close = g722_encode_close,
- .encode = g722_encode_frame,
+ .encode2 = g722_encode_frame,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME,
.long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"),
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index 8c02a392cc..4489411e2d 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -330,10 +330,12 @@ static av_cold int g726_encode_init(AVCodecContext *avctx)
g726_reset(c);
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
avctx->coded_frame->key_frame = 1;
+#endif
/* select a frame size that will end on a byte boundary and have a size of
approximately 1024 bytes */
@@ -342,28 +344,37 @@ static av_cold int g726_encode_init(AVCodecContext *avctx)
return 0;
}
+#if FF_API_OLD_ENCODE_AUDIO
static av_cold int g726_encode_close(AVCodecContext *avctx)
{
av_freep(&avctx->coded_frame);
return 0;
}
+#endif
-static int g726_encode_frame(AVCodecContext *avctx,
- uint8_t *dst, int buf_size, void *data)
+static int g726_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
G726Context *c = avctx->priv_data;
- const int16_t *samples = data;
+ const int16_t *samples = (const int16_t *)frame->data[0];
PutBitContext pb;
- int i;
+ int i, ret, out_size;
- init_put_bits(&pb, dst, 1024*1024);
+ out_size = (frame->nb_samples * c->code_size + 7) / 8;
+ if ((ret = ff_alloc_packet(avpkt, out_size))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ init_put_bits(&pb, avpkt->data, avpkt->size);
- for (i = 0; i < avctx->frame_size; i++)
+ for (i = 0; i < frame->nb_samples; i++)
put_bits(&pb, c->code_size, g726_encode(c, *samples++));
flush_put_bits(&pb);
- return put_bits_count(&pb)>>3;
+ avpkt->size = out_size;
+ *got_packet_ptr = 1;
+ return 0;
}
#define OFFSET(x) offsetof(G726Context, x)
@@ -391,8 +402,10 @@ AVCodec ff_adpcm_g726_encoder = {
.id = CODEC_ID_ADPCM_G726,
.priv_data_size = sizeof(G726Context),
.init = g726_encode_init,
- .encode = g726_encode_frame,
+ .encode2 = g726_encode_frame,
+#if FF_API_OLD_ENCODE_AUDIO
.close = g726_encode_close,
+#endif
.capabilities = CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"),
diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
index eafd92b2b4..858af08828 100644
--- a/libavcodec/indeo4.c
+++ b/libavcodec/indeo4.c
@@ -372,7 +372,8 @@ static int decode_band_hdr(IVI4DecContext *ctx, IVIBandDesc *band,
if (!get_bits1(&ctx->gb) || ctx->frame_type == FRAMETYPE_INTRA) {
transform_id = get_bits(&ctx->gb, 5);
- if (!transforms[transform_id].inv_trans) {
+ if (transform_id >= FF_ARRAY_ELEMS(transforms) ||
+ !transforms[transform_id].inv_trans) {
av_log_ask_for_sample(avctx, "Unimplemented transform: %d!\n", transform_id);
return AVERROR_PATCHWELCOME;
}
diff --git a/libavcodec/libfaac.c b/libavcodec/libfaac.c
index 4fa570e155..ab442add4a 100644
--- a/libavcodec/libfaac.c
+++ b/libavcodec/libfaac.c
@@ -24,11 +24,19 @@
* Interface to libfaac for aac encoding.
*/
-#include "avcodec.h"
#include <faac.h>
+#include "avcodec.h"
+#include "audio_frame_queue.h"
+#include "internal.h"
+
+
+/* libfaac has an encoder delay of 1024 samples */
+#define FAAC_DELAY_SAMPLES 1024
+
typedef struct FaacAudioContext {
faacEncHandle faac_handle;
+ AudioFrameQueue afq;
} FaacAudioContext;
static const int channel_maps[][6] = {
@@ -42,11 +50,15 @@ static av_cold int Faac_encode_close(AVCodecContext *avctx)
{
FaacAudioContext *s = avctx->priv_data;
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&avctx->extradata);
+ ff_af_queue_close(&s->afq);
if (s->faac_handle)
faacEncClose(s->faac_handle);
+
return 0;
}
@@ -118,11 +130,13 @@ static av_cold int Faac_encode_init(AVCodecContext *avctx)
avctx->frame_size = samples_input / avctx->channels;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame= avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
/* Set decoder specific info */
avctx->extradata_size = 0;
@@ -153,26 +167,52 @@ static av_cold int Faac_encode_init(AVCodecContext *avctx)
goto error;
}
+ avctx->delay = FAAC_DELAY_SAMPLES;
+ ff_af_queue_init(avctx, &s->afq);
+
return 0;
error:
Faac_encode_close(avctx);
return ret;
}
-static int Faac_encode_frame(AVCodecContext *avctx,
- unsigned char *frame, int buf_size, void *data)
+static int Faac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
FaacAudioContext *s = avctx->priv_data;
- int bytes_written;
- int num_samples = data ? avctx->frame_size : 0;
+ int bytes_written, ret;
+ int num_samples = frame ? frame->nb_samples : 0;
+ void *samples = frame ? frame->data[0] : NULL;
- bytes_written = faacEncEncode(s->faac_handle,
- data,
+ if ((ret = ff_alloc_packet(avpkt, (7 + 768) * avctx->channels))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ bytes_written = faacEncEncode(s->faac_handle, samples,
num_samples * avctx->channels,
- frame,
- buf_size);
+ avpkt->data, avpkt->size);
+ if (bytes_written < 0) {
+ av_log(avctx, AV_LOG_ERROR, "faacEncEncode() error\n");
+ return bytes_written;
+ }
+
+ /* add current frame to the queue */
+ if (frame) {
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
+ }
- return bytes_written;
+ if (!bytes_written)
+ return 0;
+
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = bytes_written;
+ *got_packet_ptr = 1;
+ return 0;
}
static const AVProfile profiles[] = {
@@ -189,7 +229,7 @@ AVCodec ff_libfaac_encoder = {
.id = CODEC_ID_AAC,
.priv_data_size = sizeof(FaacAudioContext),
.init = Faac_encode_init,
- .encode = Faac_encode_frame,
+ .encode2 = Faac_encode_frame,
.close = Faac_encode_close,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/libgsm.c b/libavcodec/libgsm.c
index 1a2145581a..8a5ad0024f 100644
--- a/libavcodec/libgsm.c
+++ b/libavcodec/libgsm.c
@@ -30,10 +30,13 @@
#include <gsm/gsm.h>
#include "avcodec.h"
+#include "internal.h"
#include "gsm.h"
static av_cold int libgsm_encode_close(AVCodecContext *avctx) {
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
gsm_destroy(avctx->priv_data);
avctx->priv_data = NULL;
return 0;
@@ -78,9 +81,11 @@ static av_cold int libgsm_encode_init(AVCodecContext *avctx) {
}
}
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame= avcodec_alloc_frame();
if (!avctx->coded_frame)
goto error;
+#endif
return 0;
error:
@@ -88,20 +93,29 @@ error:
return -1;
}
-static int libgsm_encode_frame(AVCodecContext *avctx,
- unsigned char *frame, int buf_size, void *data) {
- // we need a full block
- if(buf_size < avctx->block_align) return 0;
+static int libgsm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
+{
+ int ret;
+ gsm_signal *samples = (gsm_signal *)frame->data[0];
+ struct gsm_state *state = avctx->priv_data;
+
+ if ((ret = ff_alloc_packet(avpkt, avctx->block_align))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
switch(avctx->codec_id) {
case CODEC_ID_GSM:
- gsm_encode(avctx->priv_data,data,frame);
+ gsm_encode(state, samples, avpkt->data);
break;
case CODEC_ID_GSM_MS:
- gsm_encode(avctx->priv_data,data,frame);
- gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
+ gsm_encode(state, samples, avpkt->data);
+ gsm_encode(state, samples + GSM_FRAME_SIZE, avpkt->data + 32);
}
- return avctx->block_align;
+
+ *got_packet_ptr = 1;
+ return 0;
}
@@ -110,7 +124,7 @@ AVCodec ff_libgsm_encoder = {
.type = AVMEDIA_TYPE_AUDIO,
.id = CODEC_ID_GSM,
.init = libgsm_encode_init,
- .encode = libgsm_encode_frame,
+ .encode2 = libgsm_encode_frame,
.close = libgsm_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
@@ -121,7 +135,7 @@ AVCodec ff_libgsm_ms_encoder = {
.type = AVMEDIA_TYPE_AUDIO,
.id = CODEC_ID_GSM_MS,
.init = libgsm_encode_init,
- .encode = libgsm_encode_frame,
+ .encode2 = libgsm_encode_frame,
.close = libgsm_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index e8accedc00..686dfc2bb3 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -30,6 +30,7 @@
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "avcodec.h"
+#include "audio_frame_queue.h"
#include "internal.h"
#include "mpegaudio.h"
#include "mpegaudiodecheader.h"
@@ -44,6 +45,7 @@ typedef struct LAMEContext {
int buffer_index;
int reservoir;
void *planar_samples[2];
+ AudioFrameQueue afq;
} LAMEContext;
@@ -51,10 +53,14 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
{
LAMEContext *s = avctx->priv_data;
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&s->planar_samples[0]);
av_freep(&s->planar_samples[1]);
+ ff_af_queue_close(&s->afq);
+
lame_close(s->gfp);
return 0;
}
@@ -111,12 +117,19 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
goto error;
}
+ /* get encoder delay */
+ avctx->delay = lame_get_encoder_delay(s->gfp) + 528 + 1;
+ ff_af_queue_init(avctx, &s->afq);
+
avctx->frame_size = lame_get_framesize(s->gfp);
+
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
/* sample format */
if (avctx->sample_fmt == AV_SAMPLE_FMT_S32 ||
@@ -144,67 +157,67 @@ error:
const type *input = samples; \
type *output = s->planar_samples[ch]; \
input += ch; \
- for (i = 0; i < s->avctx->frame_size; i++) { \
+ for (i = 0; i < nb_samples; i++) { \
output[i] = *input * scale; \
input += s->avctx->channels; \
} \
} \
} while (0)
-static int encode_frame_int16(LAMEContext *s, void *samples)
+static int encode_frame_int16(LAMEContext *s, void *samples, int nb_samples)
{
if (s->avctx->channels > 1) {
return lame_encode_buffer_interleaved(s->gfp, samples,
- s->avctx->frame_size,
+ nb_samples,
s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index);
} else {
- return lame_encode_buffer(s->gfp, samples, NULL, s->avctx->frame_size,
+ return lame_encode_buffer(s->gfp, samples, NULL, nb_samples,
s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index);
}
}
-static int encode_frame_int32(LAMEContext *s, void *samples)
+static int encode_frame_int32(LAMEContext *s, void *samples, int nb_samples)
{
DEINTERLEAVE(int32_t, 1);
return lame_encode_buffer_int(s->gfp,
s->planar_samples[0], s->planar_samples[1],
- s->avctx->frame_size,
+ nb_samples,
s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index);
}
-static int encode_frame_float(LAMEContext *s, void *samples)
+static int encode_frame_float(LAMEContext *s, void *samples, int nb_samples)
{
DEINTERLEAVE(float, 32768.0f);
return lame_encode_buffer_float(s->gfp,
s->planar_samples[0], s->planar_samples[1],
- s->avctx->frame_size,
+ nb_samples,
s->buffer + s->buffer_index,
BUFFER_SIZE - s->buffer_index);
}
-static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame,
- int buf_size, void *data)
+static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
LAMEContext *s = avctx->priv_data;
MPADecodeHeader hdr;
- int len;
+ int len, ret;
int lame_result;
- if (data) {
+ if (frame) {
switch (avctx->sample_fmt) {
case AV_SAMPLE_FMT_S16:
- lame_result = encode_frame_int16(s, data);
+ lame_result = encode_frame_int16(s, frame->data[0], frame->nb_samples);
break;
case AV_SAMPLE_FMT_S32:
- lame_result = encode_frame_int32(s, data);
+ lame_result = encode_frame_int32(s, frame->data[0], frame->nb_samples);
break;
case AV_SAMPLE_FMT_FLT:
- lame_result = encode_frame_float(s, data);
+ lame_result = encode_frame_float(s, frame->data[0], frame->nb_samples);
break;
default:
return AVERROR_BUG;
@@ -223,6 +236,12 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame,
}
s->buffer_index += lame_result;
+ /* add current frame to the queue */
+ if (frame) {
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
+ }
+
/* Move 1 frame from the LAME buffer to the output packet, if available.
We have to parse the first frame header in the output buffer to
determine the frame size. */
@@ -236,12 +255,22 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame,
av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len,
s->buffer_index);
if (len <= s->buffer_index) {
- memcpy(frame, s->buffer, len);
+ if ((ret = ff_alloc_packet(avpkt, len))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ memcpy(avpkt->data, s->buffer, len);
s->buffer_index -= len;
memmove(s->buffer, s->buffer + len, s->buffer_index);
- return len;
- } else
- return 0;
+
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = len;
+ *got_packet_ptr = 1;
+ }
+ return 0;
}
#define OFFSET(x) offsetof(LAMEContext, x)
@@ -273,9 +302,9 @@ AVCodec ff_libmp3lame_encoder = {
.id = CODEC_ID_MP3,
.priv_data_size = sizeof(LAMEContext),
.init = mp3lame_encode_init,
- .encode = mp3lame_encode_frame,
+ .encode2 = mp3lame_encode_frame,
.close = mp3lame_encode_close,
- .capabilities = CODEC_CAP_DELAY,
+ .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c
index d66f749e47..34e188e6a1 100644
--- a/libavcodec/libopencore-amr.c
+++ b/libavcodec/libopencore-amr.c
@@ -22,6 +22,8 @@
#include "avcodec.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
+#include "audio_frame_queue.h"
+#include "internal.h"
static void amr_decode_fix_avctx(AVCodecContext *avctx)
{
@@ -85,6 +87,7 @@ typedef struct AMRContext {
int enc_mode;
int enc_dtx;
int enc_last_frame;
+ AudioFrameQueue afq;
} AMRContext;
static const AVOption options[] = {
@@ -196,9 +199,12 @@ static av_cold int amr_nb_encode_init(AVCodecContext *avctx)
avctx->frame_size = 160;
avctx->delay = 50;
+ ff_af_queue_init(avctx, &s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
+#endif
s->enc_state = Encoder_Interface_init(s->enc_dtx);
if (!s->enc_state) {
@@ -218,38 +224,49 @@ static av_cold int amr_nb_encode_close(AVCodecContext *avctx)
AMRContext *s = avctx->priv_data;
Encoder_Interface_exit(s->enc_state);
+ ff_af_queue_close(&s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
-static int amr_nb_encode_frame(AVCodecContext *avctx,
- unsigned char *frame/*out*/,
- int buf_size, void *data/*in*/)
+static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
AMRContext *s = avctx->priv_data;
- int written;
+ int written, ret;
int16_t *flush_buf = NULL;
- const int16_t *samples = data;
+ const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL;
if (s->enc_bitrate != avctx->bit_rate) {
s->enc_mode = get_bitrate_mode(avctx->bit_rate, avctx);
s->enc_bitrate = avctx->bit_rate;
}
- if (data) {
- if (avctx->frame_size < 160) {
- flush_buf = av_mallocz(160 * sizeof(*flush_buf));
+ if ((ret = ff_alloc_packet(avpkt, 32))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ if (frame) {
+ if (frame->nb_samples < avctx->frame_size) {
+ flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf));
if (!flush_buf)
return AVERROR(ENOMEM);
- memcpy(flush_buf, samples, avctx->frame_size * sizeof(*flush_buf));
+ memcpy(flush_buf, samples, frame->nb_samples * sizeof(*flush_buf));
samples = flush_buf;
- if (avctx->frame_size < 110)
+ if (frame->nb_samples < avctx->frame_size - avctx->delay)
s->enc_last_frame = -1;
}
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0)) {
+ av_freep(&flush_buf);
+ return ret;
+ }
} else {
if (s->enc_last_frame < 0)
return 0;
- flush_buf = av_mallocz(160 * sizeof(*flush_buf));
+ flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf));
if (!flush_buf)
return AVERROR(ENOMEM);
samples = flush_buf;
@@ -257,12 +274,18 @@ static int amr_nb_encode_frame(AVCodecContext *avctx,
}
written = Encoder_Interface_Encode(s->enc_state, s->enc_mode, samples,
- frame, 0);
+ avpkt->data, 0);
av_dlog(avctx, "amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n",
written, s->enc_mode, frame[0]);
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = written;
+ *got_packet_ptr = 1;
av_freep(&flush_buf);
- return written;
+ return 0;
}
AVCodec ff_libopencore_amrnb_encoder = {
@@ -271,7 +294,7 @@ AVCodec ff_libopencore_amrnb_encoder = {
.id = CODEC_ID_AMR_NB,
.priv_data_size = sizeof(AMRContext),
.init = amr_nb_encode_init,
- .encode = amr_nb_encode_frame,
+ .encode2 = amr_nb_encode_frame,
.close = amr_nb_encode_close,
.capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c
index 0fb9b8f8a0..2d24e6a605 100644
--- a/libavcodec/libspeexenc.c
+++ b/libavcodec/libspeexenc.c
@@ -70,6 +70,7 @@
#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"
+#include "audio_frame_queue.h"
typedef struct {
AVClass *class; ///< AVClass for private options
@@ -81,8 +82,7 @@ typedef struct {
int cbr_quality; ///< CBR quality 0 to 10
int abr; ///< flag to enable ABR
int pkt_frame_count; ///< frame count for the current packet
- int64_t next_pts; ///< next pts, in sample_rate time base
- int pkt_sample_count; ///< sample count in the current packet
+ AudioFrameQueue afq; ///< frame queue
} LibSpeexEncContext;
static av_cold void print_enc_params(AVCodecContext *avctx,
@@ -200,6 +200,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
/* set encoding delay */
speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &avctx->delay);
+ ff_af_queue_init(avctx, &s->afq);
/* create header packet bytes from header struct */
/* note: libspeex allocates the memory for header_data, which is freed
@@ -208,13 +209,22 @@ static av_cold int encode_init(AVCodecContext *avctx)
/* allocate extradata and coded_frame */
avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata) {
+ speex_header_free(header_data);
+ speex_encoder_destroy(s->enc_state);
+ av_log(avctx, AV_LOG_ERROR, "memory allocation error\n");
+ return AVERROR(ENOMEM);
+ }
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
- if (!avctx->extradata || !avctx->coded_frame) {
+ if (!avctx->coded_frame) {
+ av_freep(&avctx->extradata);
speex_header_free(header_data);
speex_encoder_destroy(s->enc_state);
av_log(avctx, AV_LOG_ERROR, "memory allocation error\n");
return AVERROR(ENOMEM);
}
+#endif
/* copy header packet to extradata */
memcpy(avctx->extradata, header_data, header_size);
@@ -228,19 +238,21 @@ static av_cold int encode_init(AVCodecContext *avctx)
return 0;
}
-static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size,
- void *data)
+static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
LibSpeexEncContext *s = avctx->priv_data;
- int16_t *samples = data;
+ int16_t *samples = frame ? (int16_t *)frame->data[0] : NULL;
+ int ret;
- if (data) {
+ if (samples) {
/* encode Speex frame */
if (avctx->channels == 2)
speex_encode_stereo_int(samples, s->header.frame_size, &s->bits);
speex_encode_int(s->enc_state, samples, &s->bits);
s->pkt_frame_count++;
- s->pkt_sample_count += avctx->frame_size;
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
} else {
/* handle end-of-stream */
if (!s->pkt_frame_count)
@@ -255,18 +267,20 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size,
/* write output if all frames for the packet have been encoded */
if (s->pkt_frame_count == s->frames_per_packet) {
s->pkt_frame_count = 0;
- avctx->coded_frame->pts = ff_samples_to_time_base(avctx, s->next_pts -
- avctx->delay);
- s->next_pts += s->pkt_sample_count;
- s->pkt_sample_count = 0;
- if (buf_size > speex_bits_nbytes(&s->bits)) {
- int ret = speex_bits_write(&s->bits, frame, buf_size);
- speex_bits_reset(&s->bits);
+ if ((ret = ff_alloc_packet(avpkt, speex_bits_nbytes(&s->bits)))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
return ret;
- } else {
- av_log(avctx, AV_LOG_ERROR, "output buffer too small");
- return AVERROR(EINVAL);
}
+ ret = speex_bits_write(&s->bits, avpkt->data, avpkt->size);
+ speex_bits_reset(&s->bits);
+
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, s->frames_per_packet * avctx->frame_size,
+ &avpkt->pts, &avpkt->duration);
+
+ avpkt->size = ret;
+ *got_packet_ptr = 1;
+ return 0;
}
return 0;
}
@@ -278,7 +292,10 @@ static av_cold int encode_close(AVCodecContext *avctx)
speex_bits_destroy(&s->bits);
speex_encoder_destroy(s->enc_state);
+ ff_af_queue_close(&s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&avctx->extradata);
return 0;
@@ -312,7 +329,7 @@ AVCodec ff_libspeex_encoder = {
.id = CODEC_ID_SPEEX,
.priv_data_size = sizeof(LibSpeexEncContext),
.init = encode_init,
- .encode = encode_frame,
+ .encode2 = encode_frame,
.close = encode_close,
.capabilities = CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/libvo-aacenc.c b/libavcodec/libvo-aacenc.c
index bb6d50f2f5..46e1f0cfe6 100644
--- a/libavcodec/libvo-aacenc.c
+++ b/libavcodec/libvo-aacenc.c
@@ -23,25 +23,61 @@
#include <vo-aacenc/cmnMemory.h>
#include "avcodec.h"
+#include "audio_frame_queue.h"
+#include "internal.h"
#include "mpeg4audio.h"
+#define FRAME_SIZE 1024
+#define ENC_DELAY 1600
+
typedef struct AACContext {
VO_AUDIO_CODECAPI codec_api;
VO_HANDLE handle;
VO_MEM_OPERATOR mem_operator;
VO_CODEC_INIT_USERDATA user_data;
+ VO_PBYTE end_buffer;
+ AudioFrameQueue afq;
+ int last_frame;
+ int last_samples;
} AACContext;
+
+static int aac_encode_close(AVCodecContext *avctx)
+{
+ AACContext *s = avctx->priv_data;
+
+ s->codec_api.Uninit(s->handle);
+#if FF_API_OLD_ENCODE_AUDIO
+ av_freep(&avctx->coded_frame);
+#endif
+ av_freep(&avctx->extradata);
+ ff_af_queue_close(&s->afq);
+ av_freep(&s->end_buffer);
+
+ return 0;
+}
+
static av_cold int aac_encode_init(AVCodecContext *avctx)
{
AACContext *s = avctx->priv_data;
AACENC_PARAM params = { 0 };
- int index;
+ int index, ret;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
- avctx->frame_size = 1024;
+#endif
+ avctx->frame_size = FRAME_SIZE;
+ avctx->delay = ENC_DELAY;
+ s->last_frame = 2;
+ ff_af_queue_init(avctx, &s->afq);
+
+ s->end_buffer = av_mallocz(avctx->frame_size * avctx->channels * 2);
+ if (!s->end_buffer) {
+ ret = AVERROR(ENOMEM);
+ goto error;
+ }
voGetAACEncAPI(&s->codec_api);
@@ -61,7 +97,8 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (s->codec_api.SetParam(s->handle, VO_PID_AAC_ENCPARAM, &params)
!= VO_ERR_NONE) {
av_log(avctx, AV_LOG_ERROR, "Unable to set encoding parameters\n");
- return AVERROR(EINVAL);
+ ret = AVERROR(EINVAL);
+ goto error;
}
for (index = 0; index < 16; index++)
@@ -70,43 +107,69 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (index == 16) {
av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d\n",
avctx->sample_rate);
- return AVERROR(ENOSYS);
+ ret = AVERROR(ENOSYS);
+ goto error;
}
if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
avctx->extradata_size = 2;
avctx->extradata = av_mallocz(avctx->extradata_size +
FF_INPUT_BUFFER_PADDING_SIZE);
- if (!avctx->extradata)
- return AVERROR(ENOMEM);
+ if (!avctx->extradata) {
+ ret = AVERROR(ENOMEM);
+ goto error;
+ }
avctx->extradata[0] = 0x02 << 3 | index >> 1;
avctx->extradata[1] = (index & 0x01) << 7 | avctx->channels << 3;
}
return 0;
+error:
+ aac_encode_close(avctx);
+ return ret;
}
-static int aac_encode_close(AVCodecContext *avctx)
-{
- AACContext *s = avctx->priv_data;
-
- s->codec_api.Uninit(s->handle);
- av_freep(&avctx->coded_frame);
-
- return 0;
-}
-
-static int aac_encode_frame(AVCodecContext *avctx,
- unsigned char *frame/*out*/,
- int buf_size, void *data/*in*/)
+static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
AACContext *s = avctx->priv_data;
VO_CODECBUFFER input = { 0 }, output = { 0 };
VO_AUDIO_OUTPUTINFO output_info = { { 0 } };
+ VO_PBYTE samples;
+ int ret;
+
+ /* handle end-of-stream small frame and flushing */
+ if (!frame) {
+ if (s->last_frame <= 0)
+ return 0;
+ if (s->last_samples > 0 && s->last_samples < ENC_DELAY - FRAME_SIZE) {
+ s->last_samples = 0;
+ s->last_frame--;
+ }
+ s->last_frame--;
+ memset(s->end_buffer, 0, 2 * avctx->channels * avctx->frame_size);
+ samples = s->end_buffer;
+ } else {
+ if (frame->nb_samples < avctx->frame_size) {
+ s->last_samples = frame->nb_samples;
+ memcpy(s->end_buffer, frame->data[0], 2 * avctx->channels * frame->nb_samples);
+ samples = s->end_buffer;
+ } else {
+ samples = (VO_PBYTE)frame->data[0];
+ }
+ /* add current frame to the queue */
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
+ }
+
+ if ((ret = ff_alloc_packet(avpkt, FFMAX(8192, 768 * avctx->channels)))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
- input.Buffer = data;
- input.Length = 2 * avctx->channels * avctx->frame_size;
- output.Buffer = frame;
- output.Length = buf_size;
+ input.Buffer = samples;
+ input.Length = 2 * avctx->channels * avctx->frame_size;
+ output.Buffer = avpkt->data;
+ output.Length = avpkt->size;
s->codec_api.SetInputData(s->handle, &input);
if (s->codec_api.GetOutputData(s->handle, &output, &output_info)
@@ -114,7 +177,14 @@ static int aac_encode_frame(AVCodecContext *avctx,
av_log(avctx, AV_LOG_ERROR, "Unable to encode frame\n");
return AVERROR(EINVAL);
}
- return output.Length;
+
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = output.Length;
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_libvo_aacenc_encoder = {
@@ -123,8 +193,9 @@ AVCodec ff_libvo_aacenc_encoder = {
.id = CODEC_ID_AAC,
.priv_data_size = sizeof(AACContext),
.init = aac_encode_init,
- .encode = aac_encode_frame,
+ .encode2 = aac_encode_frame,
.close = aac_encode_close,
+ .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AAC"),
};
diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c
index 2621d97954..acccf48610 100644
--- a/libavcodec/libvo-amrwbenc.c
+++ b/libavcodec/libvo-amrwbenc.c
@@ -21,9 +21,12 @@
#include <vo-amrwbenc/enc_if.h>
-#include "avcodec.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
+#include "avcodec.h"
+#include "internal.h"
+
+#define MAX_PACKET_SIZE (1 + (477 + 7) / 8)
typedef struct AMRWBContext {
AVClass *av_class;
@@ -86,9 +89,12 @@ static av_cold int amr_wb_encode_init(AVCodecContext *avctx)
s->last_bitrate = avctx->bit_rate;
avctx->frame_size = 320;
+ avctx->delay = 80;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
+#endif
s->state = E_IF_init();
@@ -104,19 +110,34 @@ static int amr_wb_encode_close(AVCodecContext *avctx)
return 0;
}
-static int amr_wb_encode_frame(AVCodecContext *avctx,
- unsigned char *frame/*out*/,
- int buf_size, void *data/*in*/)
+static int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
AMRWBContext *s = avctx->priv_data;
- int size;
+ const int16_t *samples = (const int16_t *)frame->data[0];
+ int size, ret;
+
+ if ((ret = ff_alloc_packet(avpkt, MAX_PACKET_SIZE))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
if (s->last_bitrate != avctx->bit_rate) {
s->mode = get_wb_bitrate_mode(avctx->bit_rate, avctx);
s->last_bitrate = avctx->bit_rate;
}
- size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
- return size;
+ size = E_IF_encode(s->state, s->mode, samples, avpkt->data, s->allow_dtx);
+ if (size <= 0 || size > MAX_PACKET_SIZE) {
+ av_log(avctx, AV_LOG_ERROR, "Error encoding frame\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
+
+ avpkt->size = size;
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_libvo_amrwbenc_encoder = {
@@ -125,7 +146,7 @@ AVCodec ff_libvo_amrwbenc_encoder = {
.id = CODEC_ID_AMR_WB,
.priv_data_size = sizeof(AMRWBContext),
.init = amr_wb_encode_init,
- .encode = amr_wb_encode_frame,
+ .encode2 = amr_wb_encode_frame,
.close = amr_wb_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("Android VisualOn Adaptive Multi-Rate "
diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c
index f5ad49e68f..2957c782ce 100644
--- a/libavcodec/libvorbis.c
+++ b/libavcodec/libvorbis.c
@@ -29,9 +29,11 @@
#include "libavutil/fifo.h"
#include "libavutil/opt.h"
#include "avcodec.h"
+#include "audio_frame_queue.h"
#include "bytestream.h"
#include "internal.h"
#include "vorbis.h"
+#include "vorbis_parser.h"
#undef NDEBUG
#include <assert.h>
@@ -56,6 +58,8 @@ typedef struct OggVorbisContext {
vorbis_comment vc; /**< VorbisComment info */
ogg_packet op; /**< ogg packet */
double iblock; /**< impulse block bias option */
+ VorbisParseContext vp; /**< parse context to get durations */
+ AudioFrameQueue afq; /**< frame queue for timestamps */
} OggVorbisContext;
static const AVOption options[] = {
@@ -186,7 +190,10 @@ static av_cold int oggvorbis_encode_close(AVCodecContext *avctx)
vorbis_info_clear(&s->vi);
av_fifo_free(s->pkt_fifo);
+ ff_af_queue_close(&s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&avctx->extradata);
return 0;
@@ -247,9 +254,15 @@ static av_cold int oggvorbis_encode_init(AVCodecContext *avctx)
offset += header_code.bytes;
assert(offset == avctx->extradata_size);
+ if ((ret = avpriv_vorbis_parse_extradata(avctx, &s->vp)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "invalid extradata\n");
+ return ret;
+ }
+
vorbis_comment_clear(&s->vc);
avctx->frame_size = OGGVORBIS_FRAME_SIZE;
+ ff_af_queue_init(avctx, &s->afq);
s->pkt_fifo = av_fifo_alloc(BUFFER_SIZE);
if (!s->pkt_fifo) {
@@ -257,11 +270,13 @@ static av_cold int oggvorbis_encode_init(AVCodecContext *avctx)
goto error;
}
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
return 0;
error:
@@ -269,17 +284,17 @@ error:
return ret;
}
-static int oggvorbis_encode_frame(AVCodecContext *avctx, unsigned char *packets,
- int buf_size, void *data)
+static int oggvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
OggVorbisContext *s = avctx->priv_data;
ogg_packet op;
- float *audio = data;
- int pkt_size, ret;
+ int ret, duration;
/* send samples to libvorbis */
- if (data) {
- const int samples = avctx->frame_size;
+ if (frame) {
+ const float *audio = (const float *)frame->data[0];
+ const int samples = frame->nb_samples;
float **buffer;
int c, channels = s->vi.channels;
@@ -295,6 +310,8 @@ static int oggvorbis_encode_frame(AVCodecContext *avctx, unsigned char *packets,
av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n");
return vorbis_error_to_averror(ret);
}
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
} else {
if (!s->eof)
if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) {
@@ -330,22 +347,34 @@ static int oggvorbis_encode_frame(AVCodecContext *avctx, unsigned char *packets,
return vorbis_error_to_averror(ret);
}
- /* output then next packet from the output buffer, if available */
- pkt_size = 0;
- if (av_fifo_size(s->pkt_fifo) >= sizeof(ogg_packet)) {
- av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL);
- pkt_size = op.bytes;
- // FIXME: we should use the user-supplied pts and duration
- avctx->coded_frame->pts = ff_samples_to_time_base(avctx,
- op.granulepos);
- if (pkt_size > buf_size) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
- return AVERROR(EINVAL);
+ /* check for available packets */
+ if (av_fifo_size(s->pkt_fifo) < sizeof(ogg_packet))
+ return 0;
+
+ av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL);
+
+ if ((ret = ff_alloc_packet(avpkt, op.bytes))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ av_fifo_generic_read(s->pkt_fifo, avpkt->data, op.bytes, NULL);
+
+ avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos);
+
+ duration = avpriv_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size);
+ if (duration > 0) {
+ /* we do not know encoder delay until we get the first packet from
+ * libvorbis, so we have to update the AudioFrameQueue counts */
+ if (!avctx->delay) {
+ avctx->delay = duration;
+ s->afq.remaining_delay += duration;
+ s->afq.remaining_samples += duration;
}
- av_fifo_generic_read(s->pkt_fifo, packets, pkt_size, NULL);
+ ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration);
}
- return pkt_size;
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_libvorbis_encoder = {
@@ -354,7 +383,7 @@ AVCodec ff_libvorbis_encoder = {
.id = CODEC_ID_VORBIS,
.priv_data_size = sizeof(OggVorbisContext),
.init = oggvorbis_encode_init,
- .encode = oggvorbis_encode_frame,
+ .encode2 = oggvorbis_encode_frame,
.close = oggvorbis_encode_close,
.capabilities = CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
diff --git a/libavcodec/mpegaudioenc.c b/libavcodec/mpegaudioenc.c
index b3cb0bba59..1f9516d2e9 100644
--- a/libavcodec/mpegaudioenc.c
+++ b/libavcodec/mpegaudioenc.c
@@ -80,6 +80,7 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx)
bitrate = bitrate / 1000;
s->nb_channels = channels;
avctx->frame_size = MPA_FRAME_SIZE;
+ avctx->delay = 512 - 32 + 1;
/* encoding freq */
s->lsf = 0;
@@ -180,9 +181,11 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx)
total_quant_bits[i] = 12 * v;
}
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame= avcodec_alloc_frame();
if (!avctx->coded_frame)
return AVERROR(ENOMEM);
+#endif
return 0;
}
@@ -726,14 +729,14 @@ static void encode_frame(MpegAudioContext *s,
flush_put_bits(p);
}
-static int MPA_encode_frame(AVCodecContext *avctx,
- unsigned char *frame, int buf_size, void *data)
+static int MPA_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
MpegAudioContext *s = avctx->priv_data;
- const short *samples = data;
+ const int16_t *samples = (const int16_t *)frame->data[0];
short smr[MPA_MAX_CHANNELS][SBLIMIT];
unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT];
- int padding, i;
+ int padding, i, ret;
for(i=0;i<s->nb_channels;i++) {
filter(s, i, samples + i, s->nb_channels);
@@ -748,16 +751,28 @@ static int MPA_encode_frame(AVCodecContext *avctx,
}
compute_bit_allocation(s, smr, bit_alloc, &padding);
- init_put_bits(&s->pb, frame, MPA_MAX_CODED_FRAME_SIZE);
+ if ((ret = ff_alloc_packet(avpkt, MPA_MAX_CODED_FRAME_SIZE))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ init_put_bits(&s->pb, avpkt->data, avpkt->size);
encode_frame(s, bit_alloc, padding);
- return put_bits_ptr(&s->pb) - s->pb.buf;
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
+
+ avpkt->size = put_bits_count(&s->pb) / 8;
+ *got_packet_ptr = 1;
+ return 0;
}
static av_cold int MPA_encode_close(AVCodecContext *avctx)
{
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -772,7 +787,7 @@ AVCodec ff_mp2_encoder = {
.id = CODEC_ID_MP2,
.priv_data_size = sizeof(MpegAudioContext),
.init = MPA_encode_init,
- .encode = MPA_encode_frame,
+ .encode2 = MPA_encode_frame,
.close = MPA_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.supported_samplerates= (const int[]){44100, 48000, 32000, 22050, 24000, 16000, 0},
diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c
index 29ad7a2e26..8c0038a8f7 100644
--- a/libavcodec/nellymoserenc.c
+++ b/libavcodec/nellymoserenc.c
@@ -38,8 +38,10 @@
#include "libavutil/mathematics.h"
#include "nellymoser.h"
#include "avcodec.h"
+#include "audio_frame_queue.h"
#include "dsputil.h"
#include "fft.h"
+#include "internal.h"
#include "sinewin.h"
#define BITSTREAM_WRITER_LE
@@ -54,6 +56,7 @@ typedef struct NellyMoserEncodeContext {
int last_frame;
DSPContext dsp;
FFTContext mdct_ctx;
+ AudioFrameQueue afq;
DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES];
DECLARE_ALIGNED(32, float, in_buff)[NELLY_SAMPLES];
DECLARE_ALIGNED(32, float, buf)[3 * NELLY_BUF_LEN]; ///< sample buffer
@@ -136,7 +139,10 @@ static av_cold int encode_end(AVCodecContext *avctx)
av_free(s->opt);
av_free(s->path);
}
+ ff_af_queue_close(&s->afq);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -161,6 +167,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
avctx->frame_size = NELLY_SAMPLES;
avctx->delay = NELLY_BUF_LEN;
+ ff_af_queue_init(avctx, &s->afq);
s->avctx = avctx;
if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0)
goto error;
@@ -180,11 +187,13 @@ static av_cold int encode_init(AVCodecContext *avctx)
}
}
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
return 0;
error:
@@ -366,30 +375,44 @@ static void encode_block(NellyMoserEncodeContext *s, unsigned char *output, int
memset(put_bits_ptr(&pb), 0, output + output_size - put_bits_ptr(&pb));
}
-static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, void *data)
+static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
NellyMoserEncodeContext *s = avctx->priv_data;
- const float *samples = data;
+ int ret;
if (s->last_frame)
return 0;
memcpy(s->buf, s->buf + NELLY_SAMPLES, NELLY_BUF_LEN * sizeof(*s->buf));
- if (data) {
- memcpy(s->buf + NELLY_BUF_LEN, samples, avctx->frame_size * sizeof(*s->buf));
- if (avctx->frame_size < NELLY_SAMPLES) {
+ if (frame) {
+ memcpy(s->buf + NELLY_BUF_LEN, frame->data[0],
+ frame->nb_samples * sizeof(*s->buf));
+ if (frame->nb_samples < NELLY_SAMPLES) {
memset(s->buf + NELLY_BUF_LEN + avctx->frame_size, 0,
- (NELLY_SAMPLES - avctx->frame_size) * sizeof(*s->buf));
- if (avctx->frame_size >= NELLY_BUF_LEN)
+ (NELLY_SAMPLES - frame->nb_samples) * sizeof(*s->buf));
+ if (frame->nb_samples >= NELLY_BUF_LEN)
s->last_frame = 1;
}
+ if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+ return ret;
} else {
memset(s->buf + NELLY_BUF_LEN, 0, NELLY_SAMPLES * sizeof(*s->buf));
s->last_frame = 1;
}
- encode_block(s, frame, buf_size);
- return NELLY_BLOCK_LEN;
+ if ((ret = ff_alloc_packet(avpkt, NELLY_BLOCK_LEN))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+ encode_block(s, avpkt->data, avpkt->size);
+
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_nellymoser_encoder = {
@@ -398,7 +421,7 @@ AVCodec ff_nellymoser_encoder = {
.id = CODEC_ID_NELLYMOSER,
.priv_data_size = sizeof(NellyMoserEncodeContext),
.init = encode_init,
- .encode = encode_frame,
+ .encode2 = encode_frame,
.close = encode_end,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
.long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"),
diff --git a/libavcodec/ra144.h b/libavcodec/ra144.h
index 83c0899cc8..03c4860367 100644
--- a/libavcodec/ra144.h
+++ b/libavcodec/ra144.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include "lpc.h"
+#include "audio_frame_queue.h"
#define NBLOCKS 4 ///< number of subblocks within a block
#define BLOCKSIZE 40 ///< subblock size in 16-bit words
@@ -36,6 +37,7 @@ typedef struct {
AVCodecContext *avctx;
AVFrame frame;
LPCContext lpc_ctx;
+ AudioFrameQueue afq;
int last_frame;
unsigned int old_energy; ///< previous frame energy
diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c
index caa7d16b30..7df4f47484 100644
--- a/libavcodec/ra144enc.c
+++ b/libavcodec/ra144enc.c
@@ -28,6 +28,8 @@
#include <float.h>
#include "avcodec.h"
+#include "audio_frame_queue.h"
+#include "internal.h"
#include "put_bits.h"
#include "celp_filters.h"
#include "ra144.h"
@@ -37,7 +39,10 @@ static av_cold int ra144_encode_close(AVCodecContext *avctx)
{
RA144Context *ractx = avctx->priv_data;
ff_lpc_end(&ractx->lpc_ctx);
+ ff_af_queue_close(&ractx->afq);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
return 0;
}
@@ -64,11 +69,15 @@ static av_cold int ra144_encode_init(AVCodecContext * avctx)
if (ret < 0)
goto error;
+ ff_af_queue_init(avctx, &ractx->afq);
+
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame = avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
return 0;
error:
@@ -429,8 +438,8 @@ static void ra144_encode_subblock(RA144Context *ractx,
}
-static int ra144_encode_frame(AVCodecContext *avctx, uint8_t *frame,
- int buf_size, void *data)
+static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
static const uint8_t sizes[LPC_ORDER] = {64, 32, 32, 16, 16, 8, 8, 8, 8, 4};
static const uint8_t bit_sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};
@@ -442,16 +451,16 @@ static int ra144_encode_frame(AVCodecContext *avctx, uint8_t *frame,
int16_t block_coefs[NBLOCKS][LPC_ORDER];
int lpc_refl[LPC_ORDER]; /**< reflection coefficients of the frame */
unsigned int refl_rms[NBLOCKS]; /**< RMS of the reflection coefficients */
- const int16_t *samples = data;
+ const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL;
int energy = 0;
- int i, idx;
+ int i, idx, ret;
if (ractx->last_frame)
return 0;
- if (buf_size < FRAMESIZE) {
- av_log(avctx, AV_LOG_ERROR, "output buffer too small\n");
- return 0;
+ if ((ret = ff_alloc_packet(avpkt, FRAMESIZE))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
}
/**
@@ -465,9 +474,9 @@ static int ra144_encode_frame(AVCodecContext *avctx, uint8_t *frame,
lpc_data[i] = ractx->curr_block[BLOCKSIZE + BLOCKSIZE / 2 + i];
energy += (lpc_data[i] * lpc_data[i]) >> 4;
}
- if (data) {
+ if (frame) {
int j;
- for (j = 0; j < avctx->frame_size && i < NBLOCKS * BLOCKSIZE; i++, j++) {
+ for (j = 0; j < frame->nb_samples && i < NBLOCKS * BLOCKSIZE; i++, j++) {
lpc_data[i] = samples[j] >> 2;
energy += (lpc_data[i] * lpc_data[i]) >> 4;
}
@@ -499,7 +508,7 @@ static int ra144_encode_frame(AVCodecContext *avctx, uint8_t *frame,
memset(lpc_refl, 0, sizeof(lpc_refl));
}
}
- init_put_bits(&pb, frame, buf_size);
+ init_put_bits(&pb, avpkt->data, avpkt->size);
for (i = 0; i < LPC_ORDER; i++) {
idx = quantize(lpc_refl[i], ff_lpc_refl_cb[i], sizes[i]);
put_bits(&pb, bit_sizes[i], idx);
@@ -525,15 +534,24 @@ static int ra144_encode_frame(AVCodecContext *avctx, uint8_t *frame,
/* copy input samples to current block for processing in next call */
i = 0;
- if (data) {
- for (; i < avctx->frame_size; i++)
+ if (frame) {
+ for (; i < frame->nb_samples; i++)
ractx->curr_block[i] = samples[i] >> 2;
+
+ if ((ret = ff_af_queue_add(&ractx->afq, frame) < 0))
+ return ret;
} else
ractx->last_frame = 1;
memset(&ractx->curr_block[i], 0,
(NBLOCKS * BLOCKSIZE - i) * sizeof(*ractx->curr_block));
- return FRAMESIZE;
+ /* Get the next frame pts/duration */
+ ff_af_queue_remove(&ractx->afq, avctx->frame_size, &avpkt->pts,
+ &avpkt->duration);
+
+ avpkt->size = FRAMESIZE;
+ *got_packet_ptr = 1;
+ return 0;
}
@@ -543,7 +561,7 @@ AVCodec ff_ra_144_encoder = {
.id = CODEC_ID_RA_144,
.priv_data_size = sizeof(RA144Context),
.init = ra144_encode_init,
- .encode = ra144_encode_frame,
+ .encode2 = ra144_encode_frame,
.close = ra144_encode_close,
.capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c
index 1cff219bff..5db84c3778 100644
--- a/libavcodec/roqaudioenc.c
+++ b/libavcodec/roqaudioenc.c
@@ -24,6 +24,7 @@
#include "libavutil/intmath.h"
#include "avcodec.h"
#include "bytestream.h"
+#include "internal.h"
#define ROQ_FRAME_SIZE 735
#define ROQ_HEADER_SIZE 8
@@ -37,6 +38,7 @@ typedef struct
int input_frames;
int buffered_samples;
int16_t *frame_buffer;
+ int64_t first_pts;
} ROQDPCMContext;
@@ -44,7 +46,9 @@ static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
{
ROQDPCMContext *context = avctx->priv_data;
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
+#endif
av_freep(&context->frame_buffer);
return 0;
@@ -77,11 +81,13 @@ static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
context->lastSample[0] = context->lastSample[1] = 0;
+#if FF_API_OLD_ENCODE_AUDIO
avctx->coded_frame= avcodec_alloc_frame();
if (!avctx->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
return 0;
error:
@@ -129,23 +135,25 @@ static unsigned char dpcm_predict(short *previous, short current)
return result;
}
-static int roq_dpcm_encode_frame(AVCodecContext *avctx,
- unsigned char *frame, int buf_size, void *data)
+static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
- int i, stereo, data_size;
- const int16_t *in = data;
- uint8_t *out = frame;
+ int i, stereo, data_size, ret;
+ const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL;
+ uint8_t *out;
ROQDPCMContext *context = avctx->priv_data;
stereo = (avctx->channels == 2);
- if (!data && context->input_frames >= 8)
+ if (!in && context->input_frames >= 8)
return 0;
- if (data && context->input_frames < 8) {
+ if (in && context->input_frames < 8) {
memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels],
in, avctx->frame_size * avctx->channels * sizeof(*in));
context->buffered_samples += avctx->frame_size;
+ if (context->input_frames == 0)
+ context->first_pts = frame->pts;
if (context->input_frames < 7) {
context->input_frames++;
return 0;
@@ -158,15 +166,16 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx,
context->lastSample[1] &= 0xFF00;
}
- if (context->input_frames == 7 || !data)
+ if (context->input_frames == 7 || !in)
data_size = avctx->channels * context->buffered_samples;
else
data_size = avctx->channels * avctx->frame_size;
- if (buf_size < ROQ_HEADER_SIZE + data_size) {
- av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
- return AVERROR(EINVAL);
+ if ((ret = ff_alloc_packet(avpkt, ROQ_HEADER_SIZE + data_size))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
}
+ out = avpkt->data;
bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
bytestream_put_byte(&out, 0x10);
@@ -182,12 +191,15 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx,
for (i = 0; i < data_size; i++)
*out++ = dpcm_predict(&context->lastSample[i & 1], *in++);
+ avpkt->pts = context->input_frames <= 7 ? context->first_pts : frame->pts;
+ avpkt->duration = data_size / avctx->channels;
+
context->input_frames++;
- if (!data)
+ if (!in)
context->input_frames = FFMAX(context->input_frames, 8);
- /* Return the result size */
- return ROQ_HEADER_SIZE + data_size;
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_roq_dpcm_encoder = {
@@ -196,7 +208,7 @@ AVCodec ff_roq_dpcm_encoder = {
.id = CODEC_ID_ROQ_DPCM,
.priv_data_size = sizeof(ROQDPCMContext),
.init = roq_dpcm_encode_init,
- .encode = roq_dpcm_encode_frame,
+ .encode2 = roq_dpcm_encode_frame,
.close = roq_dpcm_encode_close,
.capabilities = CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index dfb4c30e95..afc8f9d17d 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -27,6 +27,7 @@
#include <float.h>
#include "avcodec.h"
#include "dsputil.h"
+#include "internal.h"
#include "fft.h"
#include "vorbis.h"
#include "vorbis_enc_data.h"
@@ -123,7 +124,7 @@ typedef struct {
int nmodes;
vorbis_enc_mode *modes;
- int64_t sample_count;
+ int64_t next_pts;
} vorbis_enc_context;
#define MAX_CHANNELS 2
@@ -1014,23 +1015,27 @@ static int apply_window_and_mdct(vorbis_enc_context *venc, const signed short *a
return 1;
}
-static int vorbis_encode_frame(AVCodecContext *avccontext,
- unsigned char *packets,
- int buf_size, void *data)
+static int vorbis_encode_frame(AVCodecContext *avccontext, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
{
vorbis_enc_context *venc = avccontext->priv_data;
- const signed short *audio = data;
- int samples = data ? avccontext->frame_size : 0;
+ const int16_t *audio = frame ? (const int16_t *)frame->data[0] : NULL;
+ int samples = frame ? frame->nb_samples : 0;
vorbis_enc_mode *mode;
vorbis_enc_mapping *mapping;
PutBitContext pb;
- int i;
+ int i, ret;
if (!apply_window_and_mdct(venc, audio, samples))
return 0;
samples = 1 << (venc->log2_blocksize[0] - 1);
- init_put_bits(&pb, packets, buf_size);
+ if ((ret = ff_alloc_packet(avpkt, 8192))) {
+ av_log(avccontext, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ init_put_bits(&pb, avpkt->data, avpkt->size);
if (pb.size_in_bits - put_bits_count(&pb) < 1 + ilog(venc->nmodes - 1)) {
av_log(avccontext, AV_LOG_ERROR, "output buffer is too small\n");
@@ -1081,10 +1086,20 @@ static int vorbis_encode_frame(AVCodecContext *avccontext,
return AVERROR(EINVAL);
}
- avccontext->coded_frame->pts = venc->sample_count;
- venc->sample_count += avccontext->frame_size;
flush_put_bits(&pb);
- return put_bits_count(&pb) >> 3;
+ avpkt->size = put_bits_count(&pb) >> 3;
+
+ avpkt->duration = ff_samples_to_time_base(avccontext, avccontext->frame_size);
+ if (frame)
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = ff_samples_to_time_base(avccontext, frame->pts);
+ else
+ avpkt->pts = venc->next_pts;
+ if (avpkt->pts != AV_NOPTS_VALUE)
+ venc->next_pts = avpkt->pts + avpkt->duration;
+
+ *got_packet_ptr = 1;
+ return 0;
}
@@ -1142,7 +1157,9 @@ static av_cold int vorbis_encode_close(AVCodecContext *avccontext)
ff_mdct_end(&venc->mdct[0]);
ff_mdct_end(&venc->mdct[1]);
+#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avccontext->coded_frame);
+#endif
av_freep(&avccontext->extradata);
return 0 ;
@@ -1173,11 +1190,13 @@ static av_cold int vorbis_encode_init(AVCodecContext *avccontext)
avccontext->frame_size = 1 << (venc->log2_blocksize[0] - 1);
+#if FF_API_OLD_ENCODE_AUDIO
avccontext->coded_frame = avcodec_alloc_frame();
if (!avccontext->coded_frame) {
ret = AVERROR(ENOMEM);
goto error;
}
+#endif
return 0;
error:
@@ -1191,7 +1210,7 @@ AVCodec ff_vorbis_encoder = {
.id = CODEC_ID_VORBIS,
.priv_data_size = sizeof(vorbis_enc_context),
.init = vorbis_encode_init,
- .encode = vorbis_encode_frame,
+ .encode2 = vorbis_encode_frame,
.close = vorbis_encode_close,
.capabilities= CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index 019176a6d4..0b252663ed 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -20,6 +20,7 @@
*/
#include "avcodec.h"
+#include "internal.h"
#include "wma.h"
#include "libavutil/avassert.h"
@@ -87,7 +88,12 @@ static int encode_init(AVCodecContext * avctx){
avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate /
s->frame_len;
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d\n", s->block_align, avctx->bit_rate, s->frame_len, avctx->sample_rate);
- avctx->frame_size= s->frame_len;
+ avctx->frame_size = avctx->delay = s->frame_len;
+
+#if FF_API_OLD_ENCODE_AUDIO
+ avctx->coded_frame = &s->frame;
+ avcodec_get_frame_defaults(avctx->coded_frame);
+#endif
return 0;
}
@@ -341,16 +347,17 @@ static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE],
return put_bits_count(&s->pb)/8 - s->block_align;
}
-static int encode_superframe(AVCodecContext *avctx,
- unsigned char *buf, int buf_size, void *data){
+static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
+{
WMACodecContext *s = avctx->priv_data;
- const short *samples = data;
- int i, total_gain;
+ const int16_t *samples = (const int16_t *)frame->data[0];
+ int i, total_gain, ret;
s->block_len_bits= s->frame_len_bits; //required by non variable block len
s->block_len = 1 << s->block_len_bits;
- apply_window_and_mdct(avctx, samples, avctx->frame_size);
+ apply_window_and_mdct(avctx, samples, frame->nb_samples);
if (s->ms_stereo) {
float a, b;
@@ -364,24 +371,25 @@ static int encode_superframe(AVCodecContext *avctx,
}
}
- if (buf_size < 2 * MAX_CODED_SUPERFRAME_SIZE) {
- av_log(avctx, AV_LOG_ERROR, "output buffer size is too small\n");
- return AVERROR(EINVAL);
+ if ((ret = ff_alloc_packet(avpkt, 2 * MAX_CODED_SUPERFRAME_SIZE))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
}
#if 1
total_gain= 128;
for(i=64; i; i>>=1){
- int error= encode_frame(s, s->coefs, buf, buf_size, total_gain-i);
+ int error = encode_frame(s, s->coefs, avpkt->data, avpkt->size,
+ total_gain - i);
if(error<0)
total_gain-= i;
}
#else
total_gain= 90;
- best= encode_frame(s, s->coefs, buf, buf_size, total_gain);
+ best = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain);
for(i=32; i; i>>=1){
- int scoreL= encode_frame(s, s->coefs, buf, buf_size, total_gain-i);
- int scoreR= encode_frame(s, s->coefs, buf, buf_size, total_gain+i);
+ int scoreL = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain - i);
+ int scoreR = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain + i);
av_log(NULL, AV_LOG_ERROR, "%d %d %d (%d)\n", scoreL, best, scoreR, total_gain);
if(scoreL < FFMIN(best, scoreR)){
best = scoreL;
@@ -393,7 +401,7 @@ static int encode_superframe(AVCodecContext *avctx,
}
#endif
- encode_frame(s, s->coefs, buf, buf_size, total_gain);
+ encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain);
av_assert0((put_bits_count(&s->pb) & 7) == 0);
i= s->block_align - (put_bits_count(&s->pb)+7)/8;
av_assert0(i>=0);
@@ -402,7 +410,13 @@ static int encode_superframe(AVCodecContext *avctx,
flush_put_bits(&s->pb);
av_assert0(put_bits_ptr(&s->pb) - s->pb.buf == s->block_align);
- return s->block_align;
+
+ if (frame->pts != AV_NOPTS_VALUE)
+ avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay);
+
+ avpkt->size = s->block_align;
+ *got_packet_ptr = 1;
+ return 0;
}
AVCodec ff_wmav1_encoder = {
@@ -411,7 +425,7 @@ AVCodec ff_wmav1_encoder = {
.id = CODEC_ID_WMAV1,
.priv_data_size = sizeof(WMACodecContext),
.init = encode_init,
- .encode = encode_superframe,
+ .encode2 = encode_superframe,
.close = ff_wma_end,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"),
@@ -423,7 +437,7 @@ AVCodec ff_wmav2_encoder = {
.id = CODEC_ID_WMAV2,
.priv_data_size = sizeof(WMACodecContext),
.init = encode_init,
- .encode = encode_superframe,
+ .encode2 = encode_superframe,
.close = ff_wma_end,
.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"),