Statistics
| Branch: | Revision:

ffmpeg / libav / ffm.c @ 20f01548

History | View | Annotate | Download (16.6 KB)

1
/*
2
 * FFM (ffserver live feed) encoder and decoder
3
 * Copyright (c) 2001 Gerard Lantau.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
#include "avformat.h"
20
#include <unistd.h>
21

    
22
/* The FFM file is made of blocks of fixed size */
23
#define FFM_HEADER_SIZE 14
24
#define PACKET_ID       0x666d
25

    
26
/* each packet contains frames (which can span several packets */
27
#define FRAME_HEADER_SIZE    8
28
#define FLAG_KEY_FRAME       0x01
29

    
30
typedef struct FFMStream {
31
    INT64 pts;
32
} FFMStream;
33

    
34
enum {
35
    READ_HEADER,
36
    READ_DATA,
37
};
38

    
39
typedef struct FFMContext {
40
    /* only reading mode */
41
    offset_t write_index, file_size;
42
    int read_state;
43
    UINT8 header[FRAME_HEADER_SIZE];
44

    
45
    /* read and write */
46
    int first_packet; /* true if first packet, needed to set the discontinuity tag */
47
    int packet_size;
48
    int frame_offset;
49
    INT64 pts;
50
    UINT8 *packet_ptr, *packet_end;
51
    UINT8 packet[1]; /* must be last */
52
} FFMContext;
53

    
54
static void flush_packet(AVFormatContext *s)
55
{
56
    FFMContext *ffm = s->priv_data;
57
    int fill_size, h;
58
    ByteIOContext *pb = &s->pb;
59

    
60
    fill_size = ffm->packet_end - ffm->packet_ptr;
61
    memset(ffm->packet_ptr, 0, fill_size);
62

    
63
    /* put header */
64
    put_be16(pb, PACKET_ID);
65
    put_be16(pb, fill_size);
66
    put_be64(pb, ffm->pts);
67
    h = ffm->frame_offset;
68
    if (ffm->first_packet)
69
        h |= 0x8000;
70
    put_be16(pb, h);
71
    put_buffer(pb, ffm->packet, ffm->packet_end - ffm->packet);
72

    
73
    /* prepare next packet */
74
    ffm->frame_offset = 0; /* no key frame */
75
    ffm->pts = 0; /* no pts */
76
    ffm->packet_ptr = ffm->packet;
77
    ffm->first_packet = 0;
78
}
79

    
80
/* 'first' is true if first data of a frame */
81
static void ffm_write_data(AVFormatContext *s,
82
                           UINT8 *buf, int size,
83
                           INT64 pts, int first)
84
{
85
    FFMContext *ffm = s->priv_data;
86
    int len;
87

    
88
    if (first && ffm->frame_offset == 0)
89
        ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
90
    if (first && ffm->pts == 0)
91
        ffm->pts = pts;
92

    
93
    /* write as many packets as needed */
94
    while (size > 0) {
95
        len = ffm->packet_end - ffm->packet_ptr;
96
        if (len > size)
97
            len = size;
98
        memcpy(ffm->packet_ptr, buf, len);
99

    
100
        ffm->packet_ptr += len;
101
        buf += len;
102
        size -= len;
103
        if (ffm->packet_ptr >= ffm->packet_end) {
104
            /* special case : no pts in packet : we leave the current one */
105
            if (ffm->pts == 0)
106
                ffm->pts = pts;
107

    
108
            flush_packet(s);
109
        }
110
    }
111
}
112

    
113
static int ffm_write_header(AVFormatContext *s)
114
{
115
    AVStream *st;
116
    FFMStream *fst;
117
    FFMContext *ffm;
118
    ByteIOContext *pb = &s->pb;
119
    AVCodecContext *codec;
120
    int bit_rate, i;
121

    
122
    ffm = av_mallocz(sizeof(FFMContext) + FFM_PACKET_SIZE);
123
    if (!ffm)
124
        return -1;
125

    
126
    s->priv_data = ffm;
127
    ffm->packet_size = FFM_PACKET_SIZE;
128

    
129
    /* header */
130
    put_tag(pb, "FFM1");
131
    put_be32(pb, ffm->packet_size);
132
    /* XXX: store write position in other file ? */
133
    put_be64(pb, ffm->packet_size); /* current write position */
134

    
135
    put_be32(pb, s->nb_streams);
136
    bit_rate = 0;
137
    for(i=0;i<s->nb_streams;i++) {
138
        st = s->streams[i];
139
        bit_rate += st->codec.bit_rate;
140
    }
141
    put_be32(pb, bit_rate);
142

    
143
    /* list of streams */
144
    for(i=0;i<s->nb_streams;i++) {
145
        st = s->streams[i];
146
        fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
147
        if (!fst)
148
            goto fail;
149
        st->priv_data = fst;
150

    
151
        codec = &st->codec;
152
        /* generic info */
153
        put_be32(pb, codec->codec_id);
154
        put_byte(pb, codec->codec_type);
155
        put_be32(pb, codec->bit_rate);
156
        /* specific info */
157
        switch(codec->codec_type) {
158
        case CODEC_TYPE_VIDEO:
159
            put_be32(pb, (codec->frame_rate * 1000) / FRAME_RATE_BASE);
160
            put_be16(pb, codec->width);
161
            put_be16(pb, codec->height);
162
            put_be16(pb, codec->gop_size);
163
            put_byte(pb, codec->qmin);
164
            put_byte(pb, codec->qmax);
165
            put_byte(pb, codec->max_qdiff);
166
            put_be16(pb, (int) (codec->qcompress * 10000.0));
167
            put_be16(pb, (int) (codec->qblur * 10000.0));
168
            break;
169
        case CODEC_TYPE_AUDIO:
170
            put_be32(pb, codec->sample_rate);
171
            put_le16(pb, codec->channels);
172
            put_le16(pb, codec->frame_size);
173
            break;
174
        default:
175
            abort();
176
        }
177
        /* hack to have real time */
178
        fst->pts = gettime();
179
    }
180

    
181
    /* flush until end of block reached */
182
    while ((url_ftell(pb) % ffm->packet_size) != 0)
183
        put_byte(pb, 0);
184

    
185
    put_flush_packet(pb);
186

    
187
    /* init packet mux */
188
    ffm->packet_ptr = ffm->packet;
189
    ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
190
    ffm->frame_offset = 0;
191
    ffm->pts = 0;
192
    ffm->first_packet = 1;
193

    
194
    return 0;
195
 fail:
196
    for(i=0;i<s->nb_streams;i++) {
197
        st = s->streams[i];
198
        fst = st->priv_data;
199
        if (fst)
200
            free(fst);
201
    }
202
    free(ffm);
203
    return -1;
204
}
205

    
206
static int ffm_write_packet(AVFormatContext *s, int stream_index,
207
                            UINT8 *buf, int size, int force_pts)
208
{
209
    AVStream *st = s->streams[stream_index];
210
    FFMStream *fst = st->priv_data;
211
    INT64 pts;
212
    UINT8 header[FRAME_HEADER_SIZE];
213
    int duration;
214

    
215
    if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
216
        duration = ((float)st->codec.frame_size / st->codec.sample_rate * 1000000.0);
217
    } else {
218
        duration = (1000000.0 * FRAME_RATE_BASE / (float)st->codec.frame_rate);
219
    }
220

    
221
    pts = fst->pts;
222
    /* packet size & key_frame */
223
    header[0] = stream_index;
224
    header[1] = 0;
225
    if (st->codec.key_frame)
226
        header[1] |= FLAG_KEY_FRAME;
227
    header[2] = (size >> 16) & 0xff;
228
    header[3] = (size >> 8) & 0xff;
229
    header[4] = size & 0xff;
230
    header[5] = (duration >> 16) & 0xff;
231
    header[6] = (duration >> 8) & 0xff;
232
    header[7] = duration & 0xff;
233
    ffm_write_data(s, header, FRAME_HEADER_SIZE, pts, 1);
234
    ffm_write_data(s, buf, size, pts, 0);
235

    
236
    fst->pts += duration;
237
    return 0;
238
}
239

    
240
static int ffm_write_trailer(AVFormatContext *s)
241
{
242
    ByteIOContext *pb = &s->pb;
243
    FFMContext *ffm = s->priv_data;
244
    int i;
245

    
246
    /* flush packets */
247
    if (ffm->packet_ptr > ffm->packet)
248
        flush_packet(s);
249

    
250
    put_flush_packet(pb);
251

    
252
    for(i=0;i<s->nb_streams;i++)
253
        free(s->streams[i]->priv_data);
254
    free(ffm);
255
    return 0;
256
}
257

    
258
/* ffm demux */
259

    
260
static int ffm_is_avail_data(AVFormatContext *s, int size)
261
{
262
    FFMContext *ffm = s->priv_data;
263
    offset_t pos, avail_size;
264
    int len;
265

    
266
    len = ffm->packet_end - ffm->packet_ptr;
267
    if (size <= len)
268
        return 1;
269
    pos = url_ftell(&s->pb);
270
    if (pos == ffm->write_index) {
271
        /* exactly at the end of stream */
272
        return 0;
273
    } else if (pos < ffm->write_index) {
274
        avail_size = ffm->write_index - pos;
275
    } else {
276
        avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
277
    }
278
    avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
279
    if (size <= avail_size)
280
        return 1;
281
    else
282
        return 0;
283
}
284

    
285
/* first is true if we read the frame header */
286
static int ffm_read_data(AVFormatContext *s,
287
                          UINT8 *buf, int size, int first)
288
{
289
    FFMContext *ffm = s->priv_data;
290
    ByteIOContext *pb = &s->pb;
291
    int len, fill_size, size1, frame_offset;
292

    
293
    size1 = size;
294
    while (size > 0) {
295
    redo:
296
        len = ffm->packet_end - ffm->packet_ptr;
297
        if (len > size)
298
            len = size;
299
        if (len == 0) {
300
            if (url_ftell(pb) == ffm->file_size)
301
                url_fseek(pb, ffm->packet_size, SEEK_SET);
302
            get_be16(pb); /* PACKET_ID */
303
            fill_size = get_be16(pb);
304
            ffm->pts = get_be64(pb);
305
            frame_offset = get_be16(pb);
306
            get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
307
            ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
308
            /* if first packet or resynchronization packet, we must
309
               handle it specifically */
310
            if (ffm->first_packet || (frame_offset & 0x8000)) {
311
                ffm->first_packet = 0;
312
                ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
313
                if (!first)
314
                    break;
315
            } else {
316
                ffm->packet_ptr = ffm->packet;
317
            }
318
            goto redo;
319
        }
320
        memcpy(buf, ffm->packet_ptr, len);
321
        buf += len;
322
        ffm->packet_ptr += len;
323
        size -= len;
324
        first = 0;
325
    }
326
    return size1 - size;
327
}
328

    
329

    
330
static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
331
{
332
    AVStream *st;
333
    FFMStream *fst;
334
    FFMContext *ffm;
335
    ByteIOContext *pb = &s->pb;
336
    AVCodecContext *codec;
337
    int i;
338
    UINT32 tag;
339

    
340
    ffm = av_mallocz(sizeof(FFMContext) + FFM_PACKET_SIZE);
341
    if (!ffm)
342
        return -1;
343

    
344
    s->priv_data = ffm;
345

    
346
    /* header */
347
    tag = get_le32(pb);
348
    if (tag != MKTAG('F', 'F', 'M', '1'))
349
        goto fail;
350
    ffm->packet_size = get_be32(pb);
351
    if (ffm->packet_size != FFM_PACKET_SIZE)
352
        goto fail;
353
    ffm->write_index = get_be64(pb);
354
    /* get also filesize */
355
    if (!url_is_streamed(pb)) {
356
        ffm->file_size = url_filesize(url_fileno(pb));
357
    } else {
358
        ffm->file_size = (UINT64_C(1) << 63) - 1;
359
    }
360

    
361
    s->nb_streams = get_be32(pb);
362
    get_be32(pb); /* total bitrate */
363
    /* read each stream */
364
    for(i=0;i<s->nb_streams;i++) {
365
        st = av_mallocz(sizeof(AVStream));
366
        if (!st)
367
            goto fail;
368
        s->streams[i] = st;
369
        fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
370
        if (!fst)
371
            goto fail;
372
        st->priv_data = fst;
373

    
374
        codec = &st->codec;
375
        /* generic info */
376
        st->codec.codec_id = get_be32(pb);
377
        st->codec.codec_type = get_byte(pb); /* codec_type */
378
        codec->bit_rate = get_be32(pb);
379
        /* specific info */
380
        switch(codec->codec_type) {
381
        case CODEC_TYPE_VIDEO:
382
            codec->frame_rate = ((INT64)get_be32(pb) * FRAME_RATE_BASE) / 1000;
383
            codec->width = get_be16(pb);
384
            codec->height = get_be16(pb);
385
            codec->gop_size = get_be16(pb);
386
            codec->qmin = get_byte(pb);
387
            codec->qmax = get_byte(pb);
388
            codec->max_qdiff = get_byte(pb);
389
            codec->qcompress = get_be16(pb) / 10000.0;
390
            codec->qblur = get_be16(pb) / 10000.0;
391
            break;
392
        case CODEC_TYPE_AUDIO:
393
            codec->sample_rate = get_be32(pb);
394
            codec->channels = get_le16(pb);
395
            codec->frame_size = get_le16(pb);
396
            break;
397
        default:
398
            abort();
399
        }
400

    
401
    }
402

    
403
    /* get until end of block reached */
404
    while ((url_ftell(pb) % ffm->packet_size) != 0)
405
        get_byte(pb);
406

    
407
    /* init packet demux */
408
    ffm->packet_ptr = ffm->packet;
409
    ffm->packet_end = ffm->packet;
410
    ffm->frame_offset = 0;
411
    ffm->pts = 0;
412
    ffm->read_state = READ_HEADER;
413
    ffm->first_packet = 1;
414
    return 0;
415
 fail:
416
    for(i=0;i<s->nb_streams;i++) {
417
        st = s->streams[i];
418
        if (st) {
419
            fst = st->priv_data;
420
            if (fst)
421
                free(fst);
422
            free(st);
423
        }
424
    }
425
    if (ffm)
426
        free(ffm);
427
    return -1;
428
}
429

    
430
/* return < 0 if eof */
431
static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
432
{
433
    int size;
434
    FFMContext *ffm = s->priv_data;
435
    int duration;
436

    
437
    switch(ffm->read_state) {
438
    case READ_HEADER:
439
        if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE))
440
            return -EAGAIN;
441
#if 0
442
        printf("pos=%08Lx spos=%Lx, write_index=%Lx size=%Lx\n",
443
               url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
444
#endif
445
        if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != FRAME_HEADER_SIZE)
446
            return -EAGAIN;
447

    
448
#if 0
449
        {
450
            int i;
451
            for(i=0;i<FRAME_HEADER_SIZE;i++)
452
                printf("%02x ", ffm->header[i]);
453
            printf("\n");
454
        }
455
#endif
456
        ffm->read_state = READ_DATA;
457
        /* fall thru */
458
    case READ_DATA:
459
        size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
460
        if (!ffm_is_avail_data(s, size)) {
461
            return -EAGAIN;
462
        }
463

    
464
        duration = (ffm->header[5] << 16) | (ffm->header[6] << 8) | ffm->header[7];
465

    
466
        av_new_packet(pkt, size);
467
        pkt->stream_index = ffm->header[0];
468
        if (ffm->header[1] & FLAG_KEY_FRAME)
469
            pkt->flags |= PKT_FLAG_KEY;
470

    
471
        ffm->read_state = READ_HEADER;
472
        if (ffm_read_data(s, pkt->data, size, 0) != size) {
473
            /* bad case: desynchronized packet. we cancel all the packet loading */
474
            av_free_packet(pkt);
475
            return -EAGAIN;
476
        }
477
        pkt->pts = ffm->pts;
478
        pkt->duration = duration;
479
        break;
480
    }
481
    return 0;
482
}
483

    
484
//#define DEBUG_SEEK
485

    
486
/* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
487
   by the write position inside this function */
488
static void ffm_seek1(AVFormatContext *s, offset_t pos1)
489
{
490
    FFMContext *ffm = s->priv_data;
491
    ByteIOContext *pb = &s->pb;
492
    offset_t pos;
493

    
494
    pos = pos1 + ffm->write_index;
495
    if (pos >= ffm->file_size)
496
        pos -= (ffm->file_size - FFM_PACKET_SIZE);
497
#ifdef DEBUG_SEEK
498
    printf("seek to %Lx -> %Lx\n", pos1, pos);
499
#endif
500
    url_fseek(pb, pos, SEEK_SET);
501
}
502

    
503
static INT64 get_pts(AVFormatContext *s, offset_t pos)
504
{
505
    ByteIOContext *pb = &s->pb;
506
    INT64 pts;
507

    
508
    ffm_seek1(s, pos);
509
    url_fskip(pb, 4);
510
    pts = get_be64(pb);
511
#ifdef DEBUG_SEEK
512
    printf("pts=%0.6f\n", pts / 1000000.0);
513
#endif
514
    return pts;
515
}
516

    
517
/* seek to a given time in the file. The file read pointer is
518
   positionned at or before pts. XXX: the following code is quite
519
   approximative */
520
static int ffm_seek(AVFormatContext *s, INT64 wanted_pts)
521
{
522
    FFMContext *ffm = s->priv_data;
523
    offset_t pos_min, pos_max, pos;
524
    INT64 pts_min, pts_max, pts;
525
    double pos1;
526

    
527
#ifdef DEBUG_SEEK
528
    printf("wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
529
#endif
530
    /* find the position using linear interpolation (better than
531
       dichotomy in typical cases) */
532
    pos_min = 0;
533
    pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
534
    while (pos_min <= pos_max) {
535
        pts_min = get_pts(s, pos_min);
536
        pts_max = get_pts(s, pos_max);
537
        /* linear interpolation */
538
        pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
539
            (double)(pts_max - pts_min);
540
        pos = (((INT64)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
541
        if (pos <= pos_min)
542
            pos = pos_min;
543
        else if (pos >= pos_max)
544
            pos = pos_max;
545
        pts = get_pts(s, pos);
546
        /* check if we are lucky */
547
        if (pts == wanted_pts) {
548
            goto found;
549
        } else if (pts > wanted_pts) {
550
            pos_max = pos - FFM_PACKET_SIZE;
551
        } else {
552
            pos_min = pos + FFM_PACKET_SIZE;
553
        }
554
    }
555
    pos = pos_min;
556
    if (pos > 0)
557
        pos -= FFM_PACKET_SIZE;
558
 found:
559
    ffm_seek1(s, pos);
560
    return 0;
561
}
562

    
563
offset_t ffm_read_write_index(int fd)
564
{
565
    UINT8 buf[8];
566
    offset_t pos;
567
    int i;
568

    
569
    lseek(fd, 8, SEEK_SET);
570
    read(fd, buf, 8);
571
    pos = 0;
572
    for(i=0;i<8;i++)
573
        pos |= buf[i] << (56 - i * 8);
574
    return pos;
575
}
576

    
577
void ffm_write_write_index(int fd, offset_t pos)
578
{
579
    UINT8 buf[8];
580
    int i;
581

    
582
    for(i=0;i<8;i++)
583
        buf[i] = (pos >> (56 - i * 8)) & 0xff;
584
    lseek(fd, 8, SEEK_SET);
585
    write(fd, buf, 8);
586
}
587

    
588
void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size)
589
{
590
    FFMContext *ffm = s->priv_data;
591
    ffm->write_index = pos;
592
    ffm->file_size = file_size;
593
}
594

    
595
static int ffm_read_close(AVFormatContext *s)
596
{
597
    AVStream *st;
598
    int i;
599

    
600
    for(i=0;i<s->nb_streams;i++) {
601
        st = s->streams[i];
602
        free(st->priv_data);
603
    }
604
    free(s->priv_data);
605
    return 0;
606
}
607

    
608
AVFormat ffm_format = {
609
    "ffm",
610
    "ffm format",
611
    "",
612
    "ffm",
613
    /* not really used */
614
    CODEC_ID_MP2,
615
    CODEC_ID_MPEG1VIDEO,
616
    ffm_write_header,
617
    ffm_write_packet,
618
    ffm_write_trailer,
619
    ffm_read_header,
620
    ffm_read_packet,
621
    ffm_read_close,
622
    ffm_seek,
623
};