2 * FFM (ffserver live feed) encoder and decoder
3 * Copyright (c) 2001 Gerard Lantau.
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.
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.
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.
27 /* The FFM file is made of blocks of fixed size */
28 #define FFM_HEADER_SIZE 14
29 #define PACKET_ID 0x666d
31 /* each packet contains frames (which can span several packets */
32 #define FRAME_HEADER_SIZE 5
33 #define FLAG_KEY_FRAME 0x01
35 typedef struct FFMStream
{
44 typedef struct FFMContext
{
45 /* only reading mode */
46 offset_t write_index
, file_size
;
48 UINT8 header
[FRAME_HEADER_SIZE
];
51 int first_packet
; /* true if first packet, needed to set the discontinuity tag */
55 UINT8
*packet_ptr
, *packet_end
;
56 UINT8 packet
[1]; /* must be last */
59 static void flush_packet(AVFormatContext
*s
)
61 FFMContext
*ffm
= s
->priv_data
;
63 ByteIOContext
*pb
= &s
->pb
;
65 fill_size
= ffm
->packet_end
- ffm
->packet_ptr
;
66 memset(ffm
->packet_ptr
, 0, fill_size
);
69 put_be16(pb
, PACKET_ID
);
70 put_be16(pb
, fill_size
);
71 put_be64(pb
, ffm
->pts
);
72 h
= ffm
->frame_offset
;
73 if (ffm
->first_packet
)
76 put_buffer(pb
, ffm
->packet
, ffm
->packet_end
- ffm
->packet
);
78 /* prepare next packet */
79 ffm
->frame_offset
= 0; /* no key frame */
80 ffm
->pts
= 0; /* no pts */
81 ffm
->packet_ptr
= ffm
->packet
;
82 ffm
->first_packet
= 0;
85 /* 'first' is true if first data of a frame */
86 static void ffm_write_data(AVFormatContext
*s
,
90 FFMContext
*ffm
= s
->priv_data
;
93 if (first
&& ffm
->frame_offset
== 0)
94 ffm
->frame_offset
= ffm
->packet_ptr
- ffm
->packet
+ FFM_HEADER_SIZE
;
95 if (first
&& ffm
->pts
== 0)
98 /* write as many packets as needed */
100 len
= ffm
->packet_end
- ffm
->packet_ptr
;
103 memcpy(ffm
->packet_ptr
, buf
, len
);
105 ffm
->packet_ptr
+= len
;
108 if (ffm
->packet_ptr
>= ffm
->packet_end
) {
109 /* special case : no pts in packet : we leave the current one */
118 static int ffm_write_header(AVFormatContext
*s
)
123 ByteIOContext
*pb
= &s
->pb
;
124 AVCodecContext
*codec
;
127 ffm
= av_mallocz(sizeof(FFMContext
) + FFM_PACKET_SIZE
);
132 ffm
->packet_size
= FFM_PACKET_SIZE
;
136 put_be32(pb
, ffm
->packet_size
);
137 /* XXX: store write position in other file ? */
138 put_be64(pb
, ffm
->packet_size
); /* current write position */
140 put_be32(pb
, s
->nb_streams
);
142 for(i
=0;i
<s
->nb_streams
;i
++) {
144 bit_rate
+= st
->codec
.bit_rate
;
146 put_be32(pb
, bit_rate
);
148 /* list of streams */
149 for(i
=0;i
<s
->nb_streams
;i
++) {
151 fst
= av_mallocz(sizeof(FFMStream
) + ffm
->packet_size
);
158 put_be32(pb
, codec
->codec_id
);
159 put_byte(pb
, codec
->codec_type
);
160 put_be32(pb
, codec
->bit_rate
);
162 switch(codec
->codec_type
) {
163 case CODEC_TYPE_VIDEO
:
164 put_be32(pb
, (codec
->frame_rate
* 1000) / FRAME_RATE_BASE
);
165 put_be16(pb
, codec
->width
);
166 put_be16(pb
, codec
->height
);
168 case CODEC_TYPE_AUDIO
:
169 put_be32(pb
, codec
->sample_rate
);
170 put_le16(pb
, codec
->channels
);
173 /* hack to have real time */
174 fst
->pts
= gettime();
177 /* flush until end of block reached */
178 while ((url_ftell(pb
) % ffm
->packet_size
) != 0)
181 put_flush_packet(pb
);
183 /* init packet mux */
184 ffm
->packet_ptr
= ffm
->packet
;
185 ffm
->packet_end
= ffm
->packet
+ ffm
->packet_size
- FFM_HEADER_SIZE
;
186 ffm
->frame_offset
= 0;
188 ffm
->first_packet
= 1;
192 for(i
=0;i
<s
->nb_streams
;i
++) {
202 static int ffm_write_packet(AVFormatContext
*s
, int stream_index
,
203 UINT8
*buf
, int size
)
205 AVStream
*st
= s
->streams
[stream_index
];
206 FFMStream
*fst
= st
->priv_data
;
208 UINT8 header
[FRAME_HEADER_SIZE
];
211 /* packet size & key_frame */
212 header
[0] = stream_index
;
214 if (st
->codec
.key_frame
)
215 header
[1] |= FLAG_KEY_FRAME
;
216 header
[2] = (size
>> 16) & 0xff;
217 header
[3] = (size
>> 8) & 0xff;
218 header
[4] = size
& 0xff;
219 ffm_write_data(s
, header
, FRAME_HEADER_SIZE
, pts
, 1);
220 ffm_write_data(s
, buf
, size
, pts
, 0);
222 if (st
->codec
.codec_type
== CODEC_TYPE_AUDIO
) {
223 fst
->pts
+= (INT64
)((float)st
->codec
.frame_size
/ st
->codec
.sample_rate
* 1000000.0);
225 fst
->pts
+= (INT64
)(1000000.0 * FRAME_RATE_BASE
/ (float)st
->codec
.frame_rate
);
230 static int ffm_write_trailer(AVFormatContext
*s
)
232 ByteIOContext
*pb
= &s
->pb
;
233 FFMContext
*ffm
= s
->priv_data
;
237 if (ffm
->packet_ptr
> ffm
->packet
)
240 put_flush_packet(pb
);
242 for(i
=0;i
<s
->nb_streams
;i
++)
243 free(s
->streams
[i
]->priv_data
);
250 static int ffm_is_avail_data(AVFormatContext
*s
, int size
)
252 FFMContext
*ffm
= s
->priv_data
;
253 offset_t pos
, avail_size
;
256 len
= ffm
->packet_end
- ffm
->packet_ptr
;
259 pos
= url_ftell(&s
->pb
);
260 if (pos
== ffm
->write_index
) {
261 /* exactly at the end of stream */
263 } else if (pos
< ffm
->write_index
) {
264 avail_size
= ffm
->write_index
- pos
;
266 avail_size
= (ffm
->file_size
- pos
) + (ffm
->write_index
- FFM_PACKET_SIZE
);
268 avail_size
= (avail_size
/ ffm
->packet_size
) * (ffm
->packet_size
- FFM_HEADER_SIZE
) + len
;
269 if (size
<= avail_size
)
275 /* first is true if we read the frame header */
276 static int ffm_read_data(AVFormatContext
*s
,
277 UINT8
*buf
, int size
, int first
)
279 FFMContext
*ffm
= s
->priv_data
;
280 ByteIOContext
*pb
= &s
->pb
;
281 int len
, fill_size
, size1
, frame_offset
;
286 len
= ffm
->packet_end
- ffm
->packet_ptr
;
290 if (url_ftell(pb
) == ffm
->file_size
)
291 url_fseek(pb
, ffm
->packet_size
, SEEK_SET
);
292 get_be16(pb
); /* PACKET_ID */
293 fill_size
= get_be16(pb
);
294 ffm
->pts
= get_be64(pb
);
295 frame_offset
= get_be16(pb
);
296 get_buffer(pb
, ffm
->packet
, ffm
->packet_size
- FFM_HEADER_SIZE
);
297 ffm
->packet_end
= ffm
->packet
+ (ffm
->packet_size
- FFM_HEADER_SIZE
- fill_size
);
298 /* if first packet or resynchronization packet, we must
299 handle it specifically */
300 if (ffm
->first_packet
|| (frame_offset
& 0x8000)) {
301 ffm
->first_packet
= 0;
302 ffm
->packet_ptr
= ffm
->packet
+ (frame_offset
& 0x7fff) - FFM_HEADER_SIZE
;
306 ffm
->packet_ptr
= ffm
->packet
;
310 memcpy(buf
, ffm
->packet_ptr
, len
);
312 ffm
->packet_ptr
+= len
;
320 static int ffm_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
325 ByteIOContext
*pb
= &s
->pb
;
326 AVCodecContext
*codec
;
330 ffm
= av_mallocz(sizeof(FFMContext
) + FFM_PACKET_SIZE
);
338 if (tag
!= MKTAG('F', 'F', 'M', '1'))
340 ffm
->packet_size
= get_be32(pb
);
341 if (ffm
->packet_size
!= FFM_PACKET_SIZE
)
343 ffm
->write_index
= get_be64(pb
);
344 /* get also filesize */
345 if (!url_is_streamed(pb
)) {
346 ffm
->file_size
= url_filesize(url_fileno(pb
));
348 ffm
->file_size
= (1ULL << 63) - 1;
351 s
->nb_streams
= get_be32(pb
);
352 get_be32(pb
); /* total bitrate */
353 /* read each stream */
354 for(i
=0;i
<s
->nb_streams
;i
++) {
355 st
= av_mallocz(sizeof(AVStream
));
359 fst
= av_mallocz(sizeof(FFMStream
) + ffm
->packet_size
);
366 st
->codec
.codec_id
= get_be32(pb
);
367 st
->codec
.codec_type
= get_byte(pb
); /* codec_type */
368 codec
->bit_rate
= get_be32(pb
);
370 switch(codec
->codec_type
) {
371 case CODEC_TYPE_VIDEO
:
372 codec
->frame_rate
= ((INT64
)get_be32(pb
) * FRAME_RATE_BASE
) / 1000;
373 codec
->width
= get_be16(pb
);
374 codec
->height
= get_be16(pb
);
376 case CODEC_TYPE_AUDIO
:
377 codec
->sample_rate
= get_be32(pb
);
378 codec
->channels
= get_le16(pb
);
384 /* get until end of block reached */
385 while ((url_ftell(pb
) % ffm
->packet_size
) != 0)
388 /* init packet demux */
389 ffm
->packet_ptr
= ffm
->packet
;
390 ffm
->packet_end
= ffm
->packet
;
391 ffm
->frame_offset
= 0;
393 ffm
->read_state
= READ_HEADER
;
394 ffm
->first_packet
= 1;
397 for(i
=0;i
<s
->nb_streams
;i
++) {
411 /* return < 0 if eof */
412 static int ffm_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
415 FFMContext
*ffm
= s
->priv_data
;
417 switch(ffm
->read_state
) {
419 if (!ffm_is_avail_data(s
, FRAME_HEADER_SIZE
))
422 printf("pos=%08Lx spos=%Lx, write_index=%Lx size=%Lx\n",
423 url_ftell(&s
->pb
), s
->pb
.pos
, ffm
->write_index
, ffm
->file_size
);
425 if (ffm_read_data(s
, ffm
->header
, FRAME_HEADER_SIZE
, 1) != FRAME_HEADER_SIZE
)
431 for(i
=0;i
<FRAME_HEADER_SIZE
;i
++)
432 printf("%02x ", ffm
->header
[i
]);
436 ffm
->read_state
= READ_DATA
;
439 size
= (ffm
->header
[2] << 16) | (ffm
->header
[3] << 8) | ffm
->header
[4];
440 if (!ffm_is_avail_data(s
, size
)) {
444 av_new_packet(pkt
, size
);
445 pkt
->stream_index
= ffm
->header
[0];
446 if (ffm
->header
[1] & FLAG_KEY_FRAME
)
447 pkt
->flags
|= PKT_FLAG_KEY
;
449 ffm
->read_state
= READ_HEADER
;
450 if (ffm_read_data(s
, pkt
->data
, size
, 0) != size
) {
451 /* bad case: desynchronized packet. we cancel all the packet loading */
462 /* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
463 by the write position inside this function */
464 static void ffm_seek1(AVFormatContext
*s
, offset_t pos1
)
466 FFMContext
*ffm
= s
->priv_data
;
467 ByteIOContext
*pb
= &s
->pb
;
470 pos
= pos1
+ ffm
->write_index
;
471 if (pos
>= ffm
->file_size
)
472 pos
-= (ffm
->file_size
- FFM_PACKET_SIZE
);
474 printf("seek to %Lx -> %Lx\n", pos1
, pos
);
476 url_fseek(pb
, pos
, SEEK_SET
);
479 static INT64
get_pts(AVFormatContext
*s
, offset_t pos
)
481 ByteIOContext
*pb
= &s
->pb
;
488 printf("pts=%0.6f\n", pts
/ 1000000.0);
493 /* seek to a given time in the file. The file read pointer is
494 positionned at or before pts. XXX: the following code is quite
496 static int ffm_seek(AVFormatContext
*s
, INT64 wanted_pts
)
498 FFMContext
*ffm
= s
->priv_data
;
499 offset_t pos_min
, pos_max
, pos
;
500 INT64 pts_min
, pts_max
, pts
;
504 printf("wanted_pts=%0.6f\n", wanted_pts
/ 1000000.0);
506 /* find the position using linear interpolation (better than
507 dichotomy in typical cases) */
509 pos_max
= ffm
->file_size
- 2 * FFM_PACKET_SIZE
;
510 while (pos_min
<= pos_max
) {
511 pts_min
= get_pts(s
, pos_min
);
512 pts_max
= get_pts(s
, pos_max
);
513 /* linear interpolation */
514 pos1
= (double)(pos_max
- pos_min
) * (double)(wanted_pts
- pts_min
) /
515 (double)(pts_max
- pts_min
);
516 pos
= (((INT64
)pos1
) / FFM_PACKET_SIZE
) * FFM_PACKET_SIZE
;
519 else if (pos
>= pos_max
)
521 pts
= get_pts(s
, pos
);
522 /* check if we are lucky */
523 if (pts
== wanted_pts
) {
525 } else if (pts
> wanted_pts
) {
526 pos_max
= pos
- FFM_PACKET_SIZE
;
528 pos_min
= pos
+ FFM_PACKET_SIZE
;
533 pos
-= FFM_PACKET_SIZE
;
539 offset_t
ffm_read_write_index(int fd
)
545 lseek(fd
, 8, SEEK_SET
);
549 pos
|= buf
[i
] << (56 - i
* 8);
553 void ffm_write_write_index(int fd
, offset_t pos
)
559 buf
[i
] = (pos
>> (56 - i
* 8)) & 0xff;
560 lseek(fd
, 8, SEEK_SET
);
564 void ffm_set_write_index(AVFormatContext
*s
, offset_t pos
, offset_t file_size
)
566 FFMContext
*ffm
= s
->priv_data
;
567 ffm
->write_index
= pos
;
568 ffm
->file_size
= file_size
;
571 static int ffm_read_close(AVFormatContext
*s
)
576 for(i
=0;i
<s
->nb_streams
;i
++) {
584 AVFormat ffm_format
= {
589 /* not really used */