Mercurial > libavformat.hg
diff oggenc.c @ 5280:4292c6f121dc libavformat
Add Speex support to the Ogg muxer.
author | jbr |
---|---|
date | Tue, 13 Oct 2009 01:46:19 +0000 |
parents | 36d130853c9b |
children | 0e84f356ca5f |
line wrap: on
line diff
--- a/oggenc.c Tue Oct 13 00:19:34 2009 +0000 +++ b/oggenc.c Tue Oct 13 01:46:19 2009 +0000 @@ -83,10 +83,31 @@ return size; } +static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, + int *header_len) +{ + const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; + int size; + uint8_t *p, *p0; + + size = offset + 4 + strlen(vendor) + 4; + p = av_mallocz(size); + if (!p) + return NULL; + p0 = p; + + p += offset; + bytestream_put_le32(&p, strlen(vendor)); + bytestream_put_buffer(&p, vendor, strlen(vendor)); + bytestream_put_le32(&p, 0); // user comment list length + + *header_len = size; + return p0; +} + static int ogg_build_flac_headers(AVCodecContext *avctx, OGGStreamContext *oggstream, int bitexact) { - const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; enum FLACExtradataFormat format; uint8_t *streaminfo; uint8_t *p; @@ -111,16 +132,40 @@ bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); // second packet: VorbisComment - oggstream->header_len[1] = 1+3+4+strlen(vendor)+4; - oggstream->header[1] = av_mallocz(oggstream->header_len[1]); - p = oggstream->header[1]; + p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1]); if (!p) return AVERROR_NOMEM; + oggstream->header[1] = p; bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment bytestream_put_be24(&p, oggstream->header_len[1] - 4); - bytestream_put_le32(&p, strlen(vendor)); - bytestream_put_buffer(&p, vendor, strlen(vendor)); - bytestream_put_le32(&p, 0); // user comment list length + + return 0; +} + +#define SPEEX_HEADER_SIZE 80 + +static int ogg_build_speex_headers(AVCodecContext *avctx, + OGGStreamContext *oggstream, int bitexact) +{ + uint8_t *p; + + if (avctx->extradata_size < SPEEX_HEADER_SIZE) + return -1; + + // first packet: Speex header + p = av_mallocz(SPEEX_HEADER_SIZE); + if (!p) + return AVERROR_NOMEM; + oggstream->header[0] = p; + oggstream->header_len[0] = SPEEX_HEADER_SIZE; + bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); + AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 + + // second packet: VorbisComment + p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1]); + if (!p) + return AVERROR_NOMEM; + oggstream->header[1] = p; return 0; } @@ -137,6 +182,7 @@ av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); if (st->codec->codec_id != CODEC_ID_VORBIS && st->codec->codec_id != CODEC_ID_THEORA && + st->codec->codec_id != CODEC_ID_SPEEX && st->codec->codec_id != CODEC_ID_FLAC) { av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i); return -1; @@ -156,6 +202,14 @@ av_freep(&st->priv_data); return err; } + } else if (st->codec->codec_id == CODEC_ID_SPEEX) { + int err = ogg_build_speex_headers(st->codec, oggstream, + st->codec->flags & CODEC_FLAG_BITEXACT); + if (err) { + av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); + av_freep(&st->priv_data); + return err; + } } else { if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata_size, st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42, @@ -281,7 +335,8 @@ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; OGGStreamContext *oggstream = st->priv_data; - if (st->codec->codec_id == CODEC_ID_FLAC) { + if (st->codec->codec_id == CODEC_ID_FLAC || + st->codec->codec_id == CODEC_ID_SPEEX) { av_free(oggstream->header[0]); av_free(oggstream->header[1]); } @@ -294,7 +349,7 @@ "ogg", NULL_IF_CONFIG_SMALL("Ogg"), "application/ogg", - "ogg,ogv", + "ogg,ogv,spx", 0, CODEC_ID_FLAC, CODEC_ID_THEORA,