aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/libvorbis.c
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/libvorbis.c
parentf1fdd208cc0a1fce7aaaf6b0fe72b013525f49e0 (diff)
parent6aba117f1273c7704312c6d892c9f552fa0661bb (diff)
downloadffmpeg-967facb6950549d0cc4e0ba79a056ebc6f93a049.tar.gz
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/libvorbis.c')
-rw-r--r--libavcodec/libvorbis.c69
1 files changed, 49 insertions, 20 deletions
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,