]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rmenc.c
In mov muxer, mux adpcm_ms and adpcm_ima_wav the way quicktime supports it
[ffmpeg] / libavformat / rmenc.c
index 3a3525d969817703f60582c47f2b306dc414bbd6..5670d95eb7cf8942cb0015f05050ee06853c1249 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * "Real" compatible muxer.
- * Copyright (c) 2000, 2001 Fabrice Bellard.
+ * Copyright (c) 2000, 2001 Fabrice Bellard
  *
  * This file is part of FFmpeg.
  *
 #include "avformat.h"
 #include "rm.h"
 
+typedef struct {
+    int nb_packets;
+    int packet_total_size;
+    int packet_max_size;
+    /* codec related output */
+    int bit_rate;
+    float frame_rate;
+    int nb_frames;    /* current frame number */
+    int total_frames; /* total number of frames */
+    int num;
+    AVCodecContext *enc;
+} StreamInfo;
+
+typedef struct {
+    StreamInfo streams[2];
+    StreamInfo *audio_stream, *video_stream;
+    int data_pos; /* position of the data after the header */
+} RMMuxContext;
+
 /* in ms */
 #define BUFFER_DURATION 0
 
@@ -41,16 +60,17 @@ static void put_str8(ByteIOContext *s, const char *tag)
     }
 }
 
-static void rv10_write_header(AVFormatContext *ctx,
-                              int data_size, int index_pos)
+static int rv10_write_header(AVFormatContext *ctx,
+                             int data_size, int index_pos)
 {
-    RMContext *rm = ctx->priv_data;
+    RMMuxContext *rm = ctx->priv_data;
     ByteIOContext *s = ctx->pb;
     StreamInfo *stream;
     unsigned char *data_offset_ptr, *start_ptr;
     const char *desc, *mimetype;
     int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
     int bit_rate, v, duration, flags, data_pos;
+    AVMetadataTag *tag;
 
     start_ptr = s->buf_ptr;
 
@@ -104,21 +124,24 @@ static void rv10_write_header(AVFormatContext *ctx,
     /* comments */
 
     put_tag(s,"CONT");
-    size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
-        strlen(ctx->comment) + 4 * 2 + 10;
+    size =  4 * 2 + 10;
+    for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
+        tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0);
+        if(tag) size += strlen(tag->value);
+    }
     put_be32(s,size);
     put_be16(s,0);
-    put_str(s, ctx->title);
-    put_str(s, ctx->author);
-    put_str(s, ctx->copyright);
-    put_str(s, ctx->comment);
+    for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
+        tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0);
+        put_str(s, tag ? tag->value : "");
+    }
 
     for(i=0;i<ctx->nb_streams;i++) {
         int codec_data_size;
 
         stream = &rm->streams[i];
 
-        if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+        if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
             desc = "The Audio Stream";
             mimetype = "audio/x-pn-realaudio";
             codec_data_size = 73;
@@ -154,7 +177,7 @@ static void rv10_write_header(AVFormatContext *ctx,
         put_str8(s, mimetype);
         put_be32(s, codec_data_size);
 
-        if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
+        if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
             int coded_frame_size, fscode, sample_rate;
             sample_rate = stream->enc->sample_rate;
             coded_frame_size = (stream->enc->bit_rate *
@@ -185,7 +208,7 @@ static void rv10_write_header(AVFormatContext *ctx,
             case 8000:
                 fscode = 3;
             }
-            put_be16(s, fscode); /* codec additional info, for AC3, seems
+            put_be16(s, fscode); /* codec additional info, for AC-3, seems
                                      to be a frequency code */
             /* special hack to compensate rounding errors... */
             if (coded_frame_size == 557)
@@ -202,7 +225,13 @@ static void rv10_write_header(AVFormatContext *ctx,
             put_be32(s, 0x10); /* unknown */
             put_be16(s, stream->enc->channels);
             put_str8(s, "Int0"); /* codec name */
-            put_str8(s, "dnet"); /* codec name */
+            if (stream->enc->codec_tag) {
+                put_byte(s, 4); /* tag length */
+                put_le32(s, stream->enc->codec_tag);
+            } else {
+                av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n");
+                return -1;
+            }
             put_be16(s, 0); /* title length */
             put_be16(s, 0); /* author length */
             put_be16(s, 0); /* copyright length */
@@ -247,6 +276,7 @@ static void rv10_write_header(AVFormatContext *ctx,
 
     put_be32(s, nb_packets); /* number of packets */
     put_be32(s,0); /* next data header */
+    return 0;
 }
 
 static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
@@ -271,7 +301,7 @@ static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
 
 static int rm_write_header(AVFormatContext *s)
 {
-    RMContext *rm = s->priv_data;
+    RMMuxContext *rm = s->priv_data;
     StreamInfo *stream;
     int n;
     AVCodecContext *codec;
@@ -286,7 +316,7 @@ static int rm_write_header(AVFormatContext *s)
         stream->enc = codec;
 
         switch(codec->codec_type) {
-        case CODEC_TYPE_AUDIO:
+        case AVMEDIA_TYPE_AUDIO:
             rm->audio_stream = stream;
             stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
             /* XXX: dummy values */
@@ -294,7 +324,7 @@ static int rm_write_header(AVFormatContext *s)
             stream->nb_packets = 0;
             stream->total_frames = stream->nb_packets;
             break;
-        case CODEC_TYPE_VIDEO:
+        case AVMEDIA_TYPE_VIDEO:
             rm->video_stream = stream;
             stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
             /* XXX: dummy values */
@@ -307,7 +337,8 @@ static int rm_write_header(AVFormatContext *s)
         }
     }
 
-    rv10_write_header(s, 0, 0);
+    if (rv10_write_header(s, 0, 0))
+        return AVERROR_INVALIDDATA;
     put_flush_packet(s->pb);
     return 0;
 }
@@ -315,7 +346,7 @@ static int rm_write_header(AVFormatContext *s)
 static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
 {
     uint8_t *buf1;
-    RMContext *rm = s->priv_data;
+    RMMuxContext *rm = s->priv_data;
     ByteIOContext *pb = s->pb;
     StreamInfo *stream = rm->audio_stream;
     int i;
@@ -323,14 +354,18 @@ static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int
     /* XXX: suppress this malloc */
     buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
 
-    write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY));
+    write_packet_header(s, stream, size, !!(flags & AV_PKT_FLAG_KEY));
 
-    /* for AC3, the words seems to be reversed */
-    for(i=0;i<size;i+=2) {
-        buf1[i] = buf[i+1];
-        buf1[i+1] = buf[i];
+    if (stream->enc->codec_id == CODEC_ID_AC3) {
+        /* for AC-3, the words seem to be reversed */
+        for(i=0;i<size;i+=2) {
+            buf1[i] = buf[i+1];
+            buf1[i+1] = buf[i];
+        }
+        put_buffer(pb, buf1, size);
+    } else {
+        put_buffer(pb, buf, size);
     }
-    put_buffer(pb, buf1, size);
     put_flush_packet(pb);
     stream->nb_frames++;
     av_free(buf1);
@@ -339,10 +374,10 @@ static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int
 
 static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
 {
-    RMContext *rm = s->priv_data;
+    RMMuxContext *rm = s->priv_data;
     ByteIOContext *pb = s->pb;
     StreamInfo *stream = rm->video_stream;
-    int key_frame = !!(flags & PKT_FLAG_KEY);
+    int key_frame = !!(flags & AV_PKT_FLAG_KEY);
 
     /* XXX: this is incorrect: should be a parameter */
 
@@ -385,7 +420,7 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int
 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     if (s->streams[pkt->stream_index]->codec->codec_type ==
-        CODEC_TYPE_AUDIO)
+        AVMEDIA_TYPE_AUDIO)
         return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
     else
         return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
@@ -393,7 +428,7 @@ static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
 
 static int rm_write_trailer(AVFormatContext *s)
 {
-    RMContext *rm = s->priv_data;
+    RMMuxContext *rm = s->priv_data;
     int data_size, index_pos, i;
     ByteIOContext *pb = s->pb;
 
@@ -402,16 +437,8 @@ static int rm_write_trailer(AVFormatContext *s)
         index_pos = url_fseek(pb, 0, SEEK_CUR);
         data_size = index_pos - rm->data_pos;
 
-        /* index */
-        put_tag(pb, "INDX");
-        put_be32(pb, 10 + 10 * s->nb_streams);
-        put_be16(pb, 0);
+        /* FIXME: write index */
 
-        for(i=0;i<s->nb_streams;i++) {
-            put_be32(pb, 0); /* zero indices */
-            put_be16(pb, i); /* stream number */
-            put_be32(pb, 0); /* next index */
-        }
         /* undocumented end header */
         put_be32(pb, 0);
         put_be32(pb, 0);
@@ -419,7 +446,7 @@ static int rm_write_trailer(AVFormatContext *s)
         url_fseek(pb, 0, SEEK_SET);
         for(i=0;i<s->nb_streams;i++)
             rm->streams[i].total_frames = rm->streams[i].nb_frames;
-        rv10_write_header(s, data_size, index_pos);
+        rv10_write_header(s, data_size, 0);
     } else {
         /* undocumented end header */
         put_be32(pb, 0);
@@ -430,15 +457,16 @@ static int rm_write_trailer(AVFormatContext *s)
 }
 
 
-AVOutputFormat rm_muxer = {
+AVOutputFormat ff_rm_muxer = {
     "rm",
-    "rm format",
+    NULL_IF_CONFIG_SMALL("RealMedia format"),
     "application/vnd.rn-realmedia",
     "rm,ra",
-    sizeof(RMContext),
+    sizeof(RMMuxContext),
     CODEC_ID_AC3,
     CODEC_ID_RV10,
     rm_write_header,
     rm_write_packet,
     rm_write_trailer,
+    .codec_tag= (const AVCodecTag* const []){ff_rm_codec_tags, 0},
 };