Add VorbisComment writing to Ogg/FLAC and Ogg/Speex files.
authorJames Darnley <james.darnley@gmail.com>
Sat, 20 Mar 2010 13:39:22 +0000 (13:39 +0000)
committerJustin Ruggles <justin.ruggles@gmail.com>
Sat, 20 Mar 2010 13:39:22 +0000 (13:39 +0000)
Patch by James Darnley <james darnley at gmail>

Originally committed as revision 22606 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/Makefile
libavformat/oggenc.c

index d75f7fa..3519d7e 100644 (file)
@@ -151,7 +151,8 @@ OBJS-$(CONFIG_OGG_DEMUXER)               += oggdec.o         \
                                             oggparsevorbis.o \
                                             riff.o \
                                             vorbiscomment.o
-OBJS-$(CONFIG_OGG_MUXER)                 += oggenc.o
+OBJS-$(CONFIG_OGG_MUXER)                 += oggenc.o \
+                                            vorbiscomment.o
 OBJS-$(CONFIG_OMA_DEMUXER)               += oma.o raw.o
 OBJS-$(CONFIG_PCM_ALAW_DEMUXER)          += raw.o
 OBJS-$(CONFIG_PCM_ALAW_MUXER)            += raw.o
index bdf474e..35080f3 100644 (file)
@@ -25,6 +25,7 @@
 #include "libavcodec/flac.h"
 #include "avformat.h"
 #include "internal.h"
+#include "vorbiscomment.h"
 
 typedef struct {
     int64_t duration;
@@ -84,29 +85,29 @@ static int ogg_write_page(AVFormatContext *s, const uint8_t *data, int size,
 }
 
 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact,
-                                        int *header_len)
+                                        int *header_len, AVMetadata *m)
 {
     const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
     int size;
     uint8_t *p, *p0;
+    unsigned int count;
 
-    size = offset + 4 + strlen(vendor) + 4;
+    size = offset + ff_vorbiscomment_length(m, vendor, &count);
     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
+    ff_vorbiscomment_write(&p, m, vendor, count);
 
     *header_len = size;
     return p0;
 }
 
 static int ogg_build_flac_headers(AVCodecContext *avctx,
-                                  OGGStreamContext *oggstream, int bitexact)
+                                  OGGStreamContext *oggstream, int bitexact,
+                                  AVMetadata *m)
 {
     enum FLACExtradataFormat format;
     uint8_t *streaminfo;
@@ -132,7 +133,7 @@ static int ogg_build_flac_headers(AVCodecContext *avctx,
     bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE);
 
     // second packet: VorbisComment
-    p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1]);
+    p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m);
     if (!p)
         return AVERROR_NOMEM;
     oggstream->header[1] = p;
@@ -145,7 +146,8 @@ static int ogg_build_flac_headers(AVCodecContext *avctx,
 #define SPEEX_HEADER_SIZE 80
 
 static int ogg_build_speex_headers(AVCodecContext *avctx,
-                                   OGGStreamContext *oggstream, int bitexact)
+                                   OGGStreamContext *oggstream, int bitexact,
+                                   AVMetadata *m)
 {
     uint8_t *p;
 
@@ -162,7 +164,7 @@ static int ogg_build_speex_headers(AVCodecContext *avctx,
     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]);
+    p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m);
     if (!p)
         return AVERROR_NOMEM;
     oggstream->header[1] = p;
@@ -196,7 +198,8 @@ static int ogg_write_header(AVFormatContext *s)
         st->priv_data = oggstream;
         if (st->codec->codec_id == CODEC_ID_FLAC) {
             int err = ogg_build_flac_headers(st->codec, oggstream,
-                                             st->codec->flags & CODEC_FLAG_BITEXACT);
+                                             st->codec->flags & CODEC_FLAG_BITEXACT,
+                                             s->metadata);
             if (err) {
                 av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
                 av_freep(&st->priv_data);
@@ -204,7 +207,8 @@ static int ogg_write_header(AVFormatContext *s)
             }
         } else if (st->codec->codec_id == CODEC_ID_SPEEX) {
             int err = ogg_build_speex_headers(st->codec, oggstream,
-                                              st->codec->flags & CODEC_FLAG_BITEXACT);
+                                              st->codec->flags & CODEC_FLAG_BITEXACT,
+                                              s->metadata);
             if (err) {
                 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
                 av_freep(&st->priv_data);
@@ -355,4 +359,5 @@ AVOutputFormat ogg_muxer = {
     ogg_write_packet,
     ogg_write_trailer,
     .interleave_packet = ogg_interleave_per_granule,
+    .metadata_conv = ff_vorbiscomment_metadata_conv,
 };