]> git.sesse.net Git - ffmpeg/blob - libav/ffm.c
fixed memory free (no free necessary for private data) - added better support for...
[ffmpeg] / libav / ffm.c
1 /*
2  * FFM (ffserver live feed) encoder and decoder
3  * Copyright (c) 2001 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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[FFM_PACKET_SIZE];
52 } FFMContext;
53
54 /* disable pts hack for testing */
55 int ffm_nopts = 0;
56
57 static void flush_packet(AVFormatContext *s)
58 {
59     FFMContext *ffm = s->priv_data;
60     int fill_size, h;
61     ByteIOContext *pb = &s->pb;
62
63     fill_size = ffm->packet_end - ffm->packet_ptr;
64     memset(ffm->packet_ptr, 0, fill_size);
65
66     /* put header */
67     put_be16(pb, PACKET_ID);
68     put_be16(pb, fill_size);
69     put_be64(pb, ffm->pts);
70     h = ffm->frame_offset;
71     if (ffm->first_packet)
72         h |= 0x8000;
73     put_be16(pb, h);
74     put_buffer(pb, ffm->packet, ffm->packet_end - ffm->packet);
75
76     /* prepare next packet */
77     ffm->frame_offset = 0; /* no key frame */
78     ffm->pts = 0; /* no pts */
79     ffm->packet_ptr = ffm->packet;
80     ffm->first_packet = 0;
81 }
82
83 /* 'first' is true if first data of a frame */
84 static void ffm_write_data(AVFormatContext *s,
85                            UINT8 *buf, int size,
86                            INT64 pts, int first)
87 {
88     FFMContext *ffm = s->priv_data;
89     int len;
90
91     if (first && ffm->frame_offset == 0)
92         ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
93     if (first && ffm->pts == 0)
94         ffm->pts = pts;
95
96     /* write as many packets as needed */
97     while (size > 0) {
98         len = ffm->packet_end - ffm->packet_ptr;
99         if (len > size)
100             len = size;
101         memcpy(ffm->packet_ptr, buf, len);
102
103         ffm->packet_ptr += len;
104         buf += len;
105         size -= len;
106         if (ffm->packet_ptr >= ffm->packet_end) {
107             /* special case : no pts in packet : we leave the current one */
108             if (ffm->pts == 0)
109                 ffm->pts = pts;
110
111             flush_packet(s);
112         }
113     }
114 }
115
116 static int ffm_write_header(AVFormatContext *s)
117 {
118     FFMContext *ffm = s->priv_data;
119     AVStream *st;
120     FFMStream *fst;
121     ByteIOContext *pb = &s->pb;
122     AVCodecContext *codec;
123     int bit_rate, i;
124
125     ffm->packet_size = FFM_PACKET_SIZE;
126
127     /* header */
128     put_tag(pb, "FFM1");
129     put_be32(pb, ffm->packet_size);
130     /* XXX: store write position in other file ? */
131     put_be64(pb, ffm->packet_size); /* current write position */
132
133     put_be32(pb, s->nb_streams);
134     bit_rate = 0;
135     for(i=0;i<s->nb_streams;i++) {
136         st = s->streams[i];
137         bit_rate += st->codec.bit_rate;
138     }
139     put_be32(pb, bit_rate);
140
141     /* list of streams */
142     for(i=0;i<s->nb_streams;i++) {
143         st = s->streams[i];
144         fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
145         if (!fst)
146             goto fail;
147         st->priv_data = fst;
148
149         codec = &st->codec;
150         /* generic info */
151         put_be32(pb, codec->codec_id);
152         put_byte(pb, codec->codec_type);
153         put_be32(pb, codec->bit_rate);
154         put_be32(pb, codec->flags);
155         /* specific info */
156         switch(codec->codec_type) {
157         case CODEC_TYPE_VIDEO:
158             put_be32(pb, (codec->frame_rate * 1000) / FRAME_RATE_BASE);
159             put_be16(pb, codec->width);
160             put_be16(pb, codec->height);
161             put_be16(pb, codec->gop_size);
162             put_byte(pb, codec->qmin);
163             put_byte(pb, codec->qmax);
164             put_byte(pb, codec->max_qdiff);
165             put_be16(pb, (int) (codec->qcompress * 10000.0));
166             put_be16(pb, (int) (codec->qblur * 10000.0));
167             put_be32(pb, codec->bit_rate_tolerance);
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             av_abort();
176         }
177         /* hack to have real time */
178         if (ffm_nopts)
179             fst->pts = 0;
180         else
181             fst->pts = gettime();
182     }
183
184     /* flush until end of block reached */
185     while ((url_ftell(pb) % ffm->packet_size) != 0)
186         put_byte(pb, 0);
187
188     put_flush_packet(pb);
189
190     /* init packet mux */
191     ffm->packet_ptr = ffm->packet;
192     ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
193     ffm->frame_offset = 0;
194     ffm->pts = 0;
195     ffm->first_packet = 1;
196
197     return 0;
198  fail:
199     for(i=0;i<s->nb_streams;i++) {
200         st = s->streams[i];
201         av_freep(&st->priv_data);
202     }
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     if (!url_is_streamed(pb)) {
253         INT64 size;
254         /* update the write offset */
255         size = url_ftell(pb);
256         url_fseek(pb, 8, SEEK_SET);
257         put_be64(pb, size);
258         put_flush_packet(pb);
259     }
260
261     for(i=0;i<s->nb_streams;i++)
262         av_freep(&s->streams[i]->priv_data);
263     return 0;
264 }
265
266 /* ffm demux */
267
268 static int ffm_is_avail_data(AVFormatContext *s, int size)
269 {
270     FFMContext *ffm = s->priv_data;
271     offset_t pos, avail_size;
272     int len;
273
274     len = ffm->packet_end - ffm->packet_ptr;
275     if (!ffm_nopts) {
276         /* XXX: I don't understand this test, so I disabled it for testing */
277         if (size <= len)
278             return 1;
279     }
280     pos = url_ftell(&s->pb);
281     if (pos == ffm->write_index) {
282         /* exactly at the end of stream */
283         return 0;
284     } else if (pos < ffm->write_index) {
285         avail_size = ffm->write_index - pos;
286     } else {
287         avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
288     }
289     avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
290     if (size <= avail_size)
291         return 1;
292     else
293         return 0;
294 }
295
296 /* first is true if we read the frame header */
297 static int ffm_read_data(AVFormatContext *s,
298                          UINT8 *buf, int size, int first)
299 {
300     FFMContext *ffm = s->priv_data;
301     ByteIOContext *pb = &s->pb;
302     int len, fill_size, size1, frame_offset;
303
304     size1 = size;
305     while (size > 0) {
306     redo:
307         len = ffm->packet_end - ffm->packet_ptr;
308         if (len > size)
309             len = size;
310         if (len == 0) {
311             if (url_ftell(pb) == ffm->file_size)
312                 url_fseek(pb, ffm->packet_size, SEEK_SET);
313     retry_read:
314             get_be16(pb); /* PACKET_ID */
315             fill_size = get_be16(pb);
316             ffm->pts = get_be64(pb);
317             frame_offset = get_be16(pb);
318             get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
319             ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
320             /* if first packet or resynchronization packet, we must
321                handle it specifically */
322             if (ffm->first_packet || (frame_offset & 0x8000)) {
323                 if (!frame_offset) {
324                     /* This packet has no frame headers in it */
325                     if (url_ftell(pb) >= ffm->packet_size * 3) {
326                         url_fseek(pb, -ffm->packet_size * 2, SEEK_CUR);
327                         goto retry_read;
328                     }
329                     /* This is bad, we cannot find a valid frame header */
330                     return 0;
331                 }
332                 ffm->first_packet = 0;
333                 if ((frame_offset & 0x7ffff) < FFM_HEADER_SIZE)
334                     av_abort();
335                 ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
336                 if (!first)
337                     break;
338             } else {
339                 ffm->packet_ptr = ffm->packet;
340             }
341             goto redo;
342         }
343         memcpy(buf, ffm->packet_ptr, len);
344         buf += len;
345         ffm->packet_ptr += len;
346         size -= len;
347         first = 0;
348     }
349     return size1 - size;
350 }
351
352
353 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
354 {
355     FFMContext *ffm = s->priv_data;
356     AVStream *st;
357     FFMStream *fst;
358     ByteIOContext *pb = &s->pb;
359     AVCodecContext *codec;
360     int i;
361     UINT32 tag;
362
363     /* header */
364     tag = get_le32(pb);
365     if (tag != MKTAG('F', 'F', 'M', '1'))
366         goto fail;
367     ffm->packet_size = get_be32(pb);
368     if (ffm->packet_size != FFM_PACKET_SIZE)
369         goto fail;
370     ffm->write_index = get_be64(pb);
371     /* get also filesize */
372     if (!url_is_streamed(pb)) {
373         ffm->file_size = url_filesize(url_fileno(pb));
374     } else {
375         ffm->file_size = (UINT64_C(1) << 63) - 1;
376     }
377
378     s->nb_streams = get_be32(pb);
379     get_be32(pb); /* total bitrate */
380     /* read each stream */
381     for(i=0;i<s->nb_streams;i++) {
382         st = av_mallocz(sizeof(AVStream));
383         if (!st)
384             goto fail;
385         s->streams[i] = st;
386         fst = av_mallocz(sizeof(FFMStream) + ffm->packet_size);
387         if (!fst)
388             goto fail;
389         st->priv_data = fst;
390
391         codec = &st->codec;
392         /* generic info */
393         st->codec.codec_id = get_be32(pb);
394         st->codec.codec_type = get_byte(pb); /* codec_type */
395         codec->bit_rate = get_be32(pb);
396         codec->flags = get_be32(pb);
397         /* specific info */
398         switch(codec->codec_type) {
399         case CODEC_TYPE_VIDEO:
400             codec->frame_rate = ((INT64)get_be32(pb) * FRAME_RATE_BASE) / 1000;
401             codec->width = get_be16(pb);
402             codec->height = get_be16(pb);
403             codec->gop_size = get_be16(pb);
404             codec->qmin = get_byte(pb);
405             codec->qmax = get_byte(pb);
406             codec->max_qdiff = get_byte(pb);
407             codec->qcompress = get_be16(pb) / 10000.0;
408             codec->qblur = get_be16(pb) / 10000.0;
409             codec->bit_rate_tolerance = get_be32(pb);
410             break;
411         case CODEC_TYPE_AUDIO:
412             codec->sample_rate = get_be32(pb);
413             codec->channels = get_le16(pb);
414             codec->frame_size = get_le16(pb);
415             break;
416         default:
417             av_abort();
418         }
419
420     }
421
422     /* get until end of block reached */
423     while ((url_ftell(pb) % ffm->packet_size) != 0)
424         get_byte(pb);
425
426     /* init packet demux */
427     ffm->packet_ptr = ffm->packet;
428     ffm->packet_end = ffm->packet;
429     ffm->frame_offset = 0;
430     ffm->pts = 0;
431     ffm->read_state = READ_HEADER;
432     ffm->first_packet = 1;
433     return 0;
434  fail:
435     for(i=0;i<s->nb_streams;i++) {
436         st = s->streams[i];
437         if (st) {
438             av_freep(&st->priv_data);
439             av_free(st);
440         }
441     }
442     return -1;
443 }
444
445 /* return < 0 if eof */
446 static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
447 {
448     int size;
449     FFMContext *ffm = s->priv_data;
450     int duration;
451
452     switch(ffm->read_state) {
453     case READ_HEADER:
454         if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE)) {
455             return -EAGAIN;
456         }
457 #if 0
458         printf("pos=%08Lx spos=%Lx, write_index=%Lx size=%Lx\n",
459                url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
460 #endif
461         if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != 
462             FRAME_HEADER_SIZE)
463             return -EAGAIN;
464 #if 0
465         {
466             int i;
467             for(i=0;i<FRAME_HEADER_SIZE;i++)
468                 printf("%02x ", ffm->header[i]);
469             printf("\n");
470         }
471 #endif
472         ffm->read_state = READ_DATA;
473         /* fall thru */
474     case READ_DATA:
475         size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
476         if (!ffm_is_avail_data(s, size)) {
477             return -EAGAIN;
478         }
479
480         duration = (ffm->header[5] << 16) | (ffm->header[6] << 8) | ffm->header[7];
481
482         av_new_packet(pkt, size);
483         pkt->stream_index = ffm->header[0];
484         if (ffm->header[1] & FLAG_KEY_FRAME)
485             pkt->flags |= PKT_FLAG_KEY;
486
487         ffm->read_state = READ_HEADER;
488         if (ffm_read_data(s, pkt->data, size, 0) != size) {
489             /* bad case: desynchronized packet. we cancel all the packet loading */
490             av_free_packet(pkt);
491             return -EAGAIN;
492         }
493         pkt->pts = ffm->pts;
494         pkt->duration = duration;
495         break;
496     }
497     return 0;
498 }
499
500 //#define DEBUG_SEEK
501
502 /* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
503    by the write position inside this function */
504 static void ffm_seek1(AVFormatContext *s, offset_t pos1)
505 {
506     FFMContext *ffm = s->priv_data;
507     ByteIOContext *pb = &s->pb;
508     offset_t pos;
509
510     pos = pos1 + ffm->write_index;
511     if (pos >= ffm->file_size)
512         pos -= (ffm->file_size - FFM_PACKET_SIZE);
513 #ifdef DEBUG_SEEK
514     printf("seek to %Lx -> %Lx\n", pos1, pos);
515 #endif
516     url_fseek(pb, pos, SEEK_SET);
517 }
518
519 static INT64 get_pts(AVFormatContext *s, offset_t pos)
520 {
521     ByteIOContext *pb = &s->pb;
522     INT64 pts;
523
524     ffm_seek1(s, pos);
525     url_fskip(pb, 4);
526     pts = get_be64(pb);
527 #ifdef DEBUG_SEEK
528     printf("pts=%0.6f\n", pts / 1000000.0);
529 #endif
530     return pts;
531 }
532
533 /* seek to a given time in the file. The file read pointer is
534    positionned at or before pts. XXX: the following code is quite
535    approximative */
536 static int ffm_seek(AVFormatContext *s, INT64 wanted_pts)
537 {
538     FFMContext *ffm = s->priv_data;
539     offset_t pos_min, pos_max, pos;
540     INT64 pts_min, pts_max, pts;
541     double pos1;
542
543 #ifdef DEBUG_SEEK
544     printf("wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
545 #endif
546     /* find the position using linear interpolation (better than
547        dichotomy in typical cases) */
548     pos_min = 0;
549     pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
550     while (pos_min <= pos_max) {
551         pts_min = get_pts(s, pos_min);
552         pts_max = get_pts(s, pos_max);
553         /* linear interpolation */
554         pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
555             (double)(pts_max - pts_min);
556         pos = (((INT64)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
557         if (pos <= pos_min)
558             pos = pos_min;
559         else if (pos >= pos_max)
560             pos = pos_max;
561         pts = get_pts(s, pos);
562         /* check if we are lucky */
563         if (pts == wanted_pts) {
564             goto found;
565         } else if (pts > wanted_pts) {
566             pos_max = pos - FFM_PACKET_SIZE;
567         } else {
568             pos_min = pos + FFM_PACKET_SIZE;
569         }
570     }
571     pos = pos_min;
572     if (pos > 0)
573         pos -= FFM_PACKET_SIZE;
574  found:
575     ffm_seek1(s, pos);
576     return 0;
577 }
578
579 offset_t ffm_read_write_index(int fd)
580 {
581     UINT8 buf[8];
582     offset_t pos;
583     int i;
584
585     lseek(fd, 8, SEEK_SET);
586     read(fd, buf, 8);
587     pos = 0;
588     for(i=0;i<8;i++)
589         pos |= buf[i] << (56 - i * 8);
590     return pos;
591 }
592
593 void ffm_write_write_index(int fd, offset_t pos)
594 {
595     UINT8 buf[8];
596     int i;
597
598     for(i=0;i<8;i++)
599         buf[i] = (pos >> (56 - i * 8)) & 0xff;
600     lseek(fd, 8, SEEK_SET);
601     write(fd, buf, 8);
602 }
603
604 void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size)
605 {
606     FFMContext *ffm = s->priv_data;
607     ffm->write_index = pos;
608     ffm->file_size = file_size;
609 }
610
611 static int ffm_read_close(AVFormatContext *s)
612 {
613     AVStream *st;
614     int i;
615
616     for(i=0;i<s->nb_streams;i++) {
617         st = s->streams[i];
618         av_freep(&st->priv_data);
619     }
620     return 0;
621 }
622
623 static int ffm_probe(AVProbeData *p)
624 {
625     if (p->buf_size >= 4 &&
626         p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' && 
627         p->buf[3] == '1')
628         return AVPROBE_SCORE_MAX + 1;
629     return 0;
630 }
631
632 AVInputFormat ffm_iformat = {
633     "ffm",
634     "ffm format",
635     sizeof(FFMContext),
636     ffm_probe,
637     ffm_read_header,
638     ffm_read_packet,
639     ffm_read_close,
640     ffm_seek,
641 };
642
643 AVOutputFormat ffm_oformat = {
644     "ffm",
645     "ffm format",
646     "",
647     "ffm",
648     sizeof(FFMContext),
649     /* not really used */
650     CODEC_ID_MP2,
651     CODEC_ID_MPEG1VIDEO,
652     ffm_write_header,
653     ffm_write_packet,
654     ffm_write_trailer,
655 };
656
657 int ffm_init(void)
658 {
659     av_register_input_format(&ffm_iformat);
660     av_register_output_format(&ffm_oformat);
661     return 0;
662 }