Statistics
| Branch: | Revision:

ffmpeg / libavformat / rmenc.c @ 4815e246

History | View | Annotate | Download (14.7 KB)

1
/*
2
 * "Real" compatible muxer.
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
#include "avformat.h"
22
#include "rm.h"
23

    
24
typedef struct {
25
    int nb_packets;
26
    int packet_total_size;
27
    int packet_max_size;
28
    /* codec related output */
29
    int bit_rate;
30
    float frame_rate;
31
    int nb_frames;    /* current frame number */
32
    int total_frames; /* total number of frames */
33
    int num;
34
    AVCodecContext *enc;
35
} StreamInfo;
36

    
37
typedef struct {
38
    StreamInfo streams[2];
39
    StreamInfo *audio_stream, *video_stream;
40
    int data_pos; /* position of the data after the header */
41
} RMMuxContext;
42

    
43
/* in ms */
44
#define BUFFER_DURATION 0
45

    
46

    
47
static void put_str(ByteIOContext *s, const char *tag)
48
{
49
    put_be16(s,strlen(tag));
50
    while (*tag) {
51
        put_byte(s, *tag++);
52
    }
53
}
54

    
55
static void put_str8(ByteIOContext *s, const char *tag)
56
{
57
    put_byte(s, strlen(tag));
58
    while (*tag) {
59
        put_byte(s, *tag++);
60
    }
61
}
62

    
63
static void rv10_write_header(AVFormatContext *ctx,
64
                              int data_size, int index_pos)
65
{
66
    RMMuxContext *rm = ctx->priv_data;
67
    ByteIOContext *s = ctx->pb;
68
    StreamInfo *stream;
69
    unsigned char *data_offset_ptr, *start_ptr;
70
    const char *desc, *mimetype;
71
    int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
72
    int bit_rate, v, duration, flags, data_pos;
73

    
74
    start_ptr = s->buf_ptr;
75

    
76
    put_tag(s, ".RMF");
77
    put_be32(s,18); /* header size */
78
    put_be16(s,0);
79
    put_be32(s,0);
80
    put_be32(s,4 + ctx->nb_streams); /* num headers */
81

    
82
    put_tag(s,"PROP");
83
    put_be32(s, 50);
84
    put_be16(s, 0);
85
    packet_max_size = 0;
86
    packet_total_size = 0;
87
    nb_packets = 0;
88
    bit_rate = 0;
89
    duration = 0;
90
    for(i=0;i<ctx->nb_streams;i++) {
91
        StreamInfo *stream = &rm->streams[i];
92
        bit_rate += stream->bit_rate;
93
        if (stream->packet_max_size > packet_max_size)
94
            packet_max_size = stream->packet_max_size;
95
        nb_packets += stream->nb_packets;
96
        packet_total_size += stream->packet_total_size;
97
        /* select maximum duration */
98
        v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
99
        if (v > duration)
100
            duration = v;
101
    }
102
    put_be32(s, bit_rate); /* max bit rate */
103
    put_be32(s, bit_rate); /* avg bit rate */
104
    put_be32(s, packet_max_size);        /* max packet size */
105
    if (nb_packets > 0)
106
        packet_avg_size = packet_total_size / nb_packets;
107
    else
108
        packet_avg_size = 0;
109
    put_be32(s, packet_avg_size);        /* avg packet size */
110
    put_be32(s, nb_packets);  /* num packets */
111
    put_be32(s, duration); /* duration */
112
    put_be32(s, BUFFER_DURATION);           /* preroll */
113
    put_be32(s, index_pos);           /* index offset */
114
    /* computation of data the data offset */
115
    data_offset_ptr = s->buf_ptr;
116
    put_be32(s, 0);           /* data offset : will be patched after */
117
    put_be16(s, ctx->nb_streams);    /* num streams */
118
    flags = 1 | 2; /* save allowed & perfect play */
119
    if (url_is_streamed(s))
120
        flags |= 4; /* live broadcast */
121
    put_be16(s, flags);
122

    
123
    /* comments */
124

    
125
    put_tag(s,"CONT");
126
    size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) +
127
        strlen(ctx->comment) + 4 * 2 + 10;
128
    put_be32(s,size);
129
    put_be16(s,0);
130
    put_str(s, ctx->title);
131
    put_str(s, ctx->author);
132
    put_str(s, ctx->copyright);
133
    put_str(s, ctx->comment);
134

    
135
    for(i=0;i<ctx->nb_streams;i++) {
136
        int codec_data_size;
137

    
138
        stream = &rm->streams[i];
139

    
140
        if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
141
            desc = "The Audio Stream";
142
            mimetype = "audio/x-pn-realaudio";
143
            codec_data_size = 73;
144
        } else {
145
            desc = "The Video Stream";
146
            mimetype = "video/x-pn-realvideo";
147
            codec_data_size = 34;
148
        }
149

    
150
        put_tag(s,"MDPR");
151
        size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
152
        put_be32(s, size);
153
        put_be16(s, 0);
154

    
155
        put_be16(s, i); /* stream number */
156
        put_be32(s, stream->bit_rate); /* max bit rate */
157
        put_be32(s, stream->bit_rate); /* avg bit rate */
158
        put_be32(s, stream->packet_max_size);        /* max packet size */
159
        if (stream->nb_packets > 0)
160
            packet_avg_size = stream->packet_total_size /
161
                stream->nb_packets;
162
        else
163
            packet_avg_size = 0;
164
        put_be32(s, packet_avg_size);        /* avg packet size */
165
        put_be32(s, 0);           /* start time */
166
        put_be32(s, BUFFER_DURATION);           /* preroll */
167
        /* duration */
168
        if (url_is_streamed(s) || !stream->total_frames)
169
            put_be32(s, (int)(3600 * 1000));
170
        else
171
            put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
172
        put_str8(s, desc);
173
        put_str8(s, mimetype);
174
        put_be32(s, codec_data_size);
175

    
176
        if (stream->enc->codec_type == CODEC_TYPE_AUDIO) {
177
            int coded_frame_size, fscode, sample_rate;
178
            sample_rate = stream->enc->sample_rate;
179
            coded_frame_size = (stream->enc->bit_rate *
180
                                stream->enc->frame_size) / (8 * sample_rate);
181
            /* audio codec info */
182
            put_tag(s, ".ra");
183
            put_byte(s, 0xfd);
184
            put_be32(s, 0x00040000); /* version */
185
            put_tag(s, ".ra4");
186
            put_be32(s, 0x01b53530); /* stream length */
187
            put_be16(s, 4); /* unknown */
188
            put_be32(s, 0x39); /* header size */
189

    
190
            switch(sample_rate) {
191
            case 48000:
192
            case 24000:
193
            case 12000:
194
                fscode = 1;
195
                break;
196
            default:
197
            case 44100:
198
            case 22050:
199
            case 11025:
200
                fscode = 2;
201
                break;
202
            case 32000:
203
            case 16000:
204
            case 8000:
205
                fscode = 3;
206
            }
207
            put_be16(s, fscode); /* codec additional info, for AC-3, seems
208
                                     to be a frequency code */
209
            /* special hack to compensate rounding errors... */
210
            if (coded_frame_size == 557)
211
                coded_frame_size--;
212
            put_be32(s, coded_frame_size); /* frame length */
213
            put_be32(s, 0x51540); /* unknown */
214
            put_be32(s, 0x249f0); /* unknown */
215
            put_be32(s, 0x249f0); /* unknown */
216
            put_be16(s, 0x01);
217
            /* frame length : seems to be very important */
218
            put_be16(s, coded_frame_size);
219
            put_be32(s, 0); /* unknown */
220
            put_be16(s, stream->enc->sample_rate); /* sample rate */
221
            put_be32(s, 0x10); /* unknown */
222
            put_be16(s, stream->enc->channels);
223
            put_str8(s, "Int0"); /* codec name */
224
            put_str8(s, "dnet"); /* codec name */
225
            put_be16(s, 0); /* title length */
226
            put_be16(s, 0); /* author length */
227
            put_be16(s, 0); /* copyright length */
228
            put_byte(s, 0); /* end of header */
229
        } else {
230
            /* video codec info */
231
            put_be32(s,34); /* size */
232
            if(stream->enc->codec_id == CODEC_ID_RV10)
233
                put_tag(s,"VIDORV10");
234
            else
235
                put_tag(s,"VIDORV20");
236
            put_be16(s, stream->enc->width);
237
            put_be16(s, stream->enc->height);
238
            put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */
239
            put_be32(s,0);     /* unknown meaning */
240
            put_be16(s, (int) stream->frame_rate);  /* unknown meaning */
241
            put_be32(s,0);     /* unknown meaning */
242
            put_be16(s, 8);    /* unknown meaning */
243
            /* Seems to be the codec version: only use basic H263. The next
244
               versions seems to add a diffential DC coding as in
245
               MPEG... nothing new under the sun */
246
            if(stream->enc->codec_id == CODEC_ID_RV10)
247
                put_be32(s,0x10000000);
248
            else
249
                put_be32(s,0x20103001);
250
            //put_be32(s,0x10003000);
251
        }
252
    }
253

    
254
    /* patch data offset field */
255
    data_pos = s->buf_ptr - start_ptr;
256
    rm->data_pos = data_pos;
257
    data_offset_ptr[0] = data_pos >> 24;
258
    data_offset_ptr[1] = data_pos >> 16;
259
    data_offset_ptr[2] = data_pos >> 8;
260
    data_offset_ptr[3] = data_pos;
261

    
262
    /* data stream */
263
    put_tag(s,"DATA");
264
    put_be32(s,data_size + 10 + 8);
265
    put_be16(s,0);
266

    
267
    put_be32(s, nb_packets); /* number of packets */
268
    put_be32(s,0); /* next data header */
269
}
270

    
271
static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream,
272
                                int length, int key_frame)
273
{
274
    int timestamp;
275
    ByteIOContext *s = ctx->pb;
276

    
277
    stream->nb_packets++;
278
    stream->packet_total_size += length;
279
    if (length > stream->packet_max_size)
280
        stream->packet_max_size =  length;
281

    
282
    put_be16(s,0); /* version */
283
    put_be16(s,length + 12);
284
    put_be16(s, stream->num); /* stream number */
285
    timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
286
    put_be32(s, timestamp); /* timestamp */
287
    put_byte(s, 0); /* reserved */
288
    put_byte(s, key_frame ? 2 : 0); /* flags */
289
}
290

    
291
static int rm_write_header(AVFormatContext *s)
292
{
293
    RMMuxContext *rm = s->priv_data;
294
    StreamInfo *stream;
295
    int n;
296
    AVCodecContext *codec;
297

    
298
    for(n=0;n<s->nb_streams;n++) {
299
        s->streams[n]->id = n;
300
        codec = s->streams[n]->codec;
301
        stream = &rm->streams[n];
302
        memset(stream, 0, sizeof(StreamInfo));
303
        stream->num = n;
304
        stream->bit_rate = codec->bit_rate;
305
        stream->enc = codec;
306

    
307
        switch(codec->codec_type) {
308
        case CODEC_TYPE_AUDIO:
309
            rm->audio_stream = stream;
310
            stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size;
311
            /* XXX: dummy values */
312
            stream->packet_max_size = 1024;
313
            stream->nb_packets = 0;
314
            stream->total_frames = stream->nb_packets;
315
            break;
316
        case CODEC_TYPE_VIDEO:
317
            rm->video_stream = stream;
318
            stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num;
319
            /* XXX: dummy values */
320
            stream->packet_max_size = 4096;
321
            stream->nb_packets = 0;
322
            stream->total_frames = stream->nb_packets;
323
            break;
324
        default:
325
            return -1;
326
        }
327
    }
328

    
329
    rv10_write_header(s, 0, 0);
330
    put_flush_packet(s->pb);
331
    return 0;
332
}
333

    
334
static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags)
335
{
336
    uint8_t *buf1;
337
    RMMuxContext *rm = s->priv_data;
338
    ByteIOContext *pb = s->pb;
339
    StreamInfo *stream = rm->audio_stream;
340
    int i;
341

    
342
    /* XXX: suppress this malloc */
343
    buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) );
344

    
345
    write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY));
346

    
347
    /* for AC-3, the words seem to be reversed */
348
    for(i=0;i<size;i+=2) {
349
        buf1[i] = buf[i+1];
350
        buf1[i+1] = buf[i];
351
    }
352
    put_buffer(pb, buf1, size);
353
    put_flush_packet(pb);
354
    stream->nb_frames++;
355
    av_free(buf1);
356
    return 0;
357
}
358

    
359
static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags)
360
{
361
    RMMuxContext *rm = s->priv_data;
362
    ByteIOContext *pb = s->pb;
363
    StreamInfo *stream = rm->video_stream;
364
    int key_frame = !!(flags & PKT_FLAG_KEY);
365

    
366
    /* XXX: this is incorrect: should be a parameter */
367

    
368
    /* Well, I spent some time finding the meaning of these bits. I am
369
       not sure I understood everything, but it works !! */
370
#if 1
371
    write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame);
372
    /* bit 7: '1' if final packet of a frame converted in several packets */
373
    put_byte(pb, 0x81);
374
    /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
375
       frame starting from 1 */
376
    if (key_frame) {
377
        put_byte(pb, 0x81);
378
    } else {
379
        put_byte(pb, 0x01);
380
    }
381
    if(size >= 0x4000){
382
        put_be32(pb, size); /* total frame size */
383
        put_be32(pb, size); /* offset from the start or the end */
384
    }else{
385
        put_be16(pb, 0x4000 | size); /* total frame size */
386
        put_be16(pb, 0x4000 | size); /* offset from the start or the end */
387
    }
388
#else
389
    /* full frame */
390
    write_packet_header(s, size + 6);
391
    put_byte(pb, 0xc0);
392
    put_be16(pb, 0x4000 + size); /* total frame size */
393
    put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */
394
#endif
395
    put_byte(pb, stream->nb_frames & 0xff);
396

    
397
    put_buffer(pb, buf, size);
398
    put_flush_packet(pb);
399

    
400
    stream->nb_frames++;
401
    return 0;
402
}
403

    
404
static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
405
{
406
    if (s->streams[pkt->stream_index]->codec->codec_type ==
407
        CODEC_TYPE_AUDIO)
408
        return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
409
    else
410
        return rm_write_video(s, pkt->data, pkt->size, pkt->flags);
411
}
412

    
413
static int rm_write_trailer(AVFormatContext *s)
414
{
415
    RMMuxContext *rm = s->priv_data;
416
    int data_size, index_pos, i;
417
    ByteIOContext *pb = s->pb;
418

    
419
    if (!url_is_streamed(s->pb)) {
420
        /* end of file: finish to write header */
421
        index_pos = url_fseek(pb, 0, SEEK_CUR);
422
        data_size = index_pos - rm->data_pos;
423

    
424
        /* index */
425
        put_tag(pb, "INDX");
426
        put_be32(pb, 10 + 10 * s->nb_streams);
427
        put_be16(pb, 0);
428

    
429
        for(i=0;i<s->nb_streams;i++) {
430
            put_be32(pb, 0); /* zero indexes */
431
            put_be16(pb, i); /* stream number */
432
            put_be32(pb, 0); /* next index */
433
        }
434
        /* undocumented end header */
435
        put_be32(pb, 0);
436
        put_be32(pb, 0);
437

    
438
        url_fseek(pb, 0, SEEK_SET);
439
        for(i=0;i<s->nb_streams;i++)
440
            rm->streams[i].total_frames = rm->streams[i].nb_frames;
441
        rv10_write_header(s, data_size, index_pos);
442
    } else {
443
        /* undocumented end header */
444
        put_be32(pb, 0);
445
        put_be32(pb, 0);
446
    }
447
    put_flush_packet(pb);
448
    return 0;
449
}
450

    
451

    
452
AVOutputFormat rm_muxer = {
453
    "rm",
454
    NULL_IF_CONFIG_SMALL("RM format"),
455
    "application/vnd.rn-realmedia",
456
    "rm,ra",
457
    sizeof(RMMuxContext),
458
    CODEC_ID_AC3,
459
    CODEC_ID_RV10,
460
    rm_write_header,
461
    rm_write_packet,
462
    rm_write_trailer,
463
};