2 * FFM (ffserver live feed) muxer and demuxer
3 * Copyright (c) 2001 Fabrice Bellard.
5 * This file is part of FFmpeg.
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.
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.
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
24 /* The FFM file is made of blocks of fixed size */
25 #define FFM_HEADER_SIZE 14
26 #define PACKET_ID 0x666d
28 /* each packet contains frames (which can span several packets */
29 #define FRAME_HEADER_SIZE 8
30 #define FLAG_KEY_FRAME 0x01
32 typedef struct FFMStream
{
41 typedef struct FFMContext
{
42 /* only reading mode */
43 offset_t write_index
, file_size
;
45 uint8_t header
[FRAME_HEADER_SIZE
];
48 int first_packet
; /* true if first packet, needed to set the discontinuity tag */
49 int first_frame_in_packet
; /* true if first frame in packet, needed to know if PTS information is valid */
53 uint8_t *packet_ptr
, *packet_end
;
54 uint8_t packet
[FFM_PACKET_SIZE
];
57 static int64_t get_pts(AVFormatContext
*s
, offset_t pos
);
59 /* disable pts hack for testing */
63 static void flush_packet(AVFormatContext
*s
)
65 FFMContext
*ffm
= s
->priv_data
;
67 ByteIOContext
*pb
= &s
->pb
;
69 fill_size
= ffm
->packet_end
- ffm
->packet_ptr
;
70 memset(ffm
->packet_ptr
, 0, fill_size
);
72 if (url_ftell(pb
) % ffm
->packet_size
)
76 put_be16(pb
, PACKET_ID
);
77 put_be16(pb
, fill_size
);
78 put_be64(pb
, ffm
->pts
);
79 h
= ffm
->frame_offset
;
80 if (ffm
->first_packet
)
83 put_buffer(pb
, ffm
->packet
, ffm
->packet_end
- ffm
->packet
);
86 /* prepare next packet */
87 ffm
->frame_offset
= 0; /* no key frame */
88 ffm
->pts
= 0; /* no pts */
89 ffm
->packet_ptr
= ffm
->packet
;
90 ffm
->first_packet
= 0;
93 /* 'first' is true if first data of a frame */
94 static void ffm_write_data(AVFormatContext
*s
,
95 const uint8_t *buf
, int size
,
96 int64_t pts
, int first
)
98 FFMContext
*ffm
= s
->priv_data
;
101 if (first
&& ffm
->frame_offset
== 0)
102 ffm
->frame_offset
= ffm
->packet_ptr
- ffm
->packet
+ FFM_HEADER_SIZE
;
103 if (first
&& ffm
->pts
== 0)
106 /* write as many packets as needed */
108 len
= ffm
->packet_end
- ffm
->packet_ptr
;
111 memcpy(ffm
->packet_ptr
, buf
, len
);
113 ffm
->packet_ptr
+= len
;
116 if (ffm
->packet_ptr
>= ffm
->packet_end
) {
117 /* special case : no pts in packet : we leave the current one */
126 static int ffm_write_header(AVFormatContext
*s
)
128 FFMContext
*ffm
= s
->priv_data
;
131 ByteIOContext
*pb
= &s
->pb
;
132 AVCodecContext
*codec
;
135 ffm
->packet_size
= FFM_PACKET_SIZE
;
138 put_le32(pb
, MKTAG('F', 'F', 'M', '1'));
139 put_be32(pb
, ffm
->packet_size
);
140 /* XXX: store write position in other file ? */
141 put_be64(pb
, ffm
->packet_size
); /* current write position */
143 put_be32(pb
, s
->nb_streams
);
145 for(i
=0;i
<s
->nb_streams
;i
++) {
147 bit_rate
+= st
->codec
->bit_rate
;
149 put_be32(pb
, bit_rate
);
151 /* list of streams */
152 for(i
=0;i
<s
->nb_streams
;i
++) {
154 fst
= av_mallocz(sizeof(FFMStream
));
157 av_set_pts_info(st
, 64, 1, 1000000);
162 put_be32(pb
, codec
->codec_id
);
163 put_byte(pb
, codec
->codec_type
);
164 put_be32(pb
, codec
->bit_rate
);
165 put_be32(pb
, st
->quality
);
166 put_be32(pb
, codec
->flags
);
167 put_be32(pb
, codec
->flags2
);
168 put_be32(pb
, codec
->debug
);
170 switch(codec
->codec_type
) {
171 case CODEC_TYPE_VIDEO
:
172 put_be32(pb
, codec
->time_base
.num
);
173 put_be32(pb
, codec
->time_base
.den
);
174 put_be16(pb
, codec
->width
);
175 put_be16(pb
, codec
->height
);
176 put_be16(pb
, codec
->gop_size
);
177 put_be32(pb
, codec
->pix_fmt
);
178 put_byte(pb
, codec
->qmin
);
179 put_byte(pb
, codec
->qmax
);
180 put_byte(pb
, codec
->max_qdiff
);
181 put_be16(pb
, (int) (codec
->qcompress
* 10000.0));
182 put_be16(pb
, (int) (codec
->qblur
* 10000.0));
183 put_be32(pb
, codec
->bit_rate_tolerance
);
184 put_strz(pb
, codec
->rc_eq
);
185 put_be32(pb
, codec
->rc_max_rate
);
186 put_be32(pb
, codec
->rc_min_rate
);
187 put_be32(pb
, codec
->rc_buffer_size
);
188 put_be64(pb
, av_dbl2int(codec
->i_quant_factor
));
189 put_be64(pb
, av_dbl2int(codec
->b_quant_factor
));
190 put_be64(pb
, av_dbl2int(codec
->i_quant_offset
));
191 put_be64(pb
, av_dbl2int(codec
->b_quant_offset
));
192 put_be32(pb
, codec
->dct_algo
);
193 put_be32(pb
, codec
->strict_std_compliance
);
194 put_be32(pb
, codec
->max_b_frames
);
195 put_be32(pb
, codec
->luma_elim_threshold
);
196 put_be32(pb
, codec
->chroma_elim_threshold
);
197 put_be32(pb
, codec
->mpeg_quant
);
198 put_be32(pb
, codec
->intra_dc_precision
);
199 put_be32(pb
, codec
->me_method
);
200 put_be32(pb
, codec
->mb_decision
);
201 put_be32(pb
, codec
->nsse_weight
);
202 put_be32(pb
, codec
->frame_skip_cmp
);
203 put_be64(pb
, av_dbl2int(codec
->rc_buffer_aggressivity
));
205 case CODEC_TYPE_AUDIO
:
206 put_be32(pb
, codec
->sample_rate
);
207 put_le16(pb
, codec
->channels
);
208 put_le16(pb
, codec
->frame_size
);
213 /* hack to have real time */
217 fst
->pts
= av_gettime();
220 /* flush until end of block reached */
221 while ((url_ftell(pb
) % ffm
->packet_size
) != 0)
224 put_flush_packet(pb
);
226 /* init packet mux */
227 ffm
->packet_ptr
= ffm
->packet
;
228 ffm
->packet_end
= ffm
->packet
+ ffm
->packet_size
- FFM_HEADER_SIZE
;
229 assert(ffm
->packet_end
>= ffm
->packet
);
230 ffm
->frame_offset
= 0;
232 ffm
->first_packet
= 1;
236 for(i
=0;i
<s
->nb_streams
;i
++) {
238 av_freep(&st
->priv_data
);
243 static int ffm_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
245 AVStream
*st
= s
->streams
[pkt
->stream_index
];
246 FFMStream
*fst
= st
->priv_data
;
248 uint8_t header
[FRAME_HEADER_SIZE
];
252 //XXX/FIXME use duration from pkt
253 if (st
->codec
->codec_type
== CODEC_TYPE_AUDIO
) {
254 duration
= ((float)st
->codec
->frame_size
/ st
->codec
->sample_rate
* 1000000.0);
256 duration
= (1000000.0 * st
->codec
->time_base
.num
/ (float)st
->codec
->time_base
.den
);
260 /* packet size & key_frame */
261 header
[0] = pkt
->stream_index
;
263 if (pkt
->flags
& PKT_FLAG_KEY
)
264 header
[1] |= FLAG_KEY_FRAME
;
265 header
[2] = (size
>> 16) & 0xff;
266 header
[3] = (size
>> 8) & 0xff;
267 header
[4] = size
& 0xff;
268 header
[5] = (duration
>> 16) & 0xff;
269 header
[6] = (duration
>> 8) & 0xff;
270 header
[7] = duration
& 0xff;
271 ffm_write_data(s
, header
, FRAME_HEADER_SIZE
, pts
, 1);
272 ffm_write_data(s
, pkt
->data
, size
, pts
, 0);
274 fst
->pts
+= duration
;
278 static int ffm_write_trailer(AVFormatContext
*s
)
280 ByteIOContext
*pb
= &s
->pb
;
281 FFMContext
*ffm
= s
->priv_data
;
284 if (ffm
->packet_ptr
> ffm
->packet
)
287 put_flush_packet(pb
);
289 if (!url_is_streamed(pb
)) {
291 /* update the write offset */
292 size
= url_ftell(pb
);
293 url_fseek(pb
, 8, SEEK_SET
);
295 put_flush_packet(pb
);
300 #endif //CONFIG_MUXERS
304 static int ffm_is_avail_data(AVFormatContext
*s
, int size
)
306 FFMContext
*ffm
= s
->priv_data
;
307 offset_t pos
, avail_size
;
310 len
= ffm
->packet_end
- ffm
->packet_ptr
;
312 /* XXX: I don't understand this test, so I disabled it for testing */
316 pos
= url_ftell(&s
->pb
);
317 if (pos
== ffm
->write_index
) {
318 /* exactly at the end of stream */
320 } else if (pos
< ffm
->write_index
) {
321 avail_size
= ffm
->write_index
- pos
;
323 avail_size
= (ffm
->file_size
- pos
) + (ffm
->write_index
- FFM_PACKET_SIZE
);
325 avail_size
= (avail_size
/ ffm
->packet_size
) * (ffm
->packet_size
- FFM_HEADER_SIZE
) + len
;
326 if (size
<= avail_size
)
332 /* first is true if we read the frame header */
333 static int ffm_read_data(AVFormatContext
*s
,
334 uint8_t *buf
, int size
, int first
)
336 FFMContext
*ffm
= s
->priv_data
;
337 ByteIOContext
*pb
= &s
->pb
;
338 int len
, fill_size
, size1
, frame_offset
;
343 len
= ffm
->packet_end
- ffm
->packet_ptr
;
347 if (url_ftell(pb
) == ffm
->file_size
)
348 url_fseek(pb
, ffm
->packet_size
, SEEK_SET
);
350 get_be16(pb
); /* PACKET_ID */
351 fill_size
= get_be16(pb
);
352 ffm
->pts
= get_be64(pb
);
353 ffm
->first_frame_in_packet
= 1;
354 frame_offset
= get_be16(pb
);
355 get_buffer(pb
, ffm
->packet
, ffm
->packet_size
- FFM_HEADER_SIZE
);
356 ffm
->packet_end
= ffm
->packet
+ (ffm
->packet_size
- FFM_HEADER_SIZE
- fill_size
);
357 if (ffm
->packet_end
< ffm
->packet
)
359 /* if first packet or resynchronization packet, we must
360 handle it specifically */
361 if (ffm
->first_packet
|| (frame_offset
& 0x8000)) {
363 /* This packet has no frame headers in it */
364 if (url_ftell(pb
) >= ffm
->packet_size
* 3) {
365 url_fseek(pb
, -ffm
->packet_size
* 2, SEEK_CUR
);
368 /* This is bad, we cannot find a valid frame header */
371 ffm
->first_packet
= 0;
372 if ((frame_offset
& 0x7ffff) < FFM_HEADER_SIZE
)
374 ffm
->packet_ptr
= ffm
->packet
+ (frame_offset
& 0x7fff) - FFM_HEADER_SIZE
;
378 ffm
->packet_ptr
= ffm
->packet
;
382 memcpy(buf
, ffm
->packet_ptr
, len
);
384 ffm
->packet_ptr
+= len
;
392 static void adjust_write_index(AVFormatContext
*s
)
394 FFMContext
*ffm
= s
->priv_data
;
395 ByteIOContext
*pb
= &s
->pb
;
397 //offset_t orig_write_index = ffm->write_index;
398 offset_t pos_min
, pos_max
;
400 offset_t ptr
= url_ftell(pb
);
404 pos_max
= ffm
->file_size
- 2 * FFM_PACKET_SIZE
;
406 pts_start
= get_pts(s
, pos_min
);
408 pts
= get_pts(s
, pos_max
);
410 if (pts
- 100000 > pts_start
)
413 ffm
->write_index
= FFM_PACKET_SIZE
;
415 pts_start
= get_pts(s
, pos_min
);
417 pts
= get_pts(s
, pos_max
);
419 if (pts
- 100000 <= pts_start
) {
424 newpos
= ((pos_max
+ pos_min
) / (2 * FFM_PACKET_SIZE
)) * FFM_PACKET_SIZE
;
426 if (newpos
== pos_min
)
429 newpts
= get_pts(s
, newpos
);
431 if (newpts
- 100000 <= pts
) {
438 ffm
->write_index
+= pos_max
;
441 //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
442 //printf("pts range %0.6f - %0.6f\n", get_pts(s, 0) / 1000000. , get_pts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. );
445 url_fseek(pb
, ptr
, SEEK_SET
);
449 static int ffm_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
451 FFMContext
*ffm
= s
->priv_data
;
454 ByteIOContext
*pb
= &s
->pb
;
455 AVCodecContext
*codec
;
461 if (tag
!= MKTAG('F', 'F', 'M', '1'))
463 ffm
->packet_size
= get_be32(pb
);
464 if (ffm
->packet_size
!= FFM_PACKET_SIZE
)
466 ffm
->write_index
= get_be64(pb
);
467 /* get also filesize */
468 if (!url_is_streamed(pb
)) {
469 ffm
->file_size
= url_fsize(pb
);
470 adjust_write_index(s
);
472 ffm
->file_size
= (UINT64_C(1) << 63) - 1;
475 nb_streams
= get_be32(pb
);
476 get_be32(pb
); /* total bitrate */
477 /* read each stream */
478 for(i
=0;i
<nb_streams
;i
++) {
481 st
= av_new_stream(s
, 0);
484 fst
= av_mallocz(sizeof(FFMStream
));
489 av_set_pts_info(st
, 64, 1, 1000000);
495 codec
->codec_id
= get_be32(pb
);
496 codec
->codec_type
= get_byte(pb
); /* codec_type */
497 codec
->bit_rate
= get_be32(pb
);
498 st
->quality
= get_be32(pb
);
499 codec
->flags
= get_be32(pb
);
500 codec
->flags2
= get_be32(pb
);
501 codec
->debug
= get_be32(pb
);
503 switch(codec
->codec_type
) {
504 case CODEC_TYPE_VIDEO
:
505 codec
->time_base
.num
= get_be32(pb
);
506 codec
->time_base
.den
= get_be32(pb
);
507 codec
->width
= get_be16(pb
);
508 codec
->height
= get_be16(pb
);
509 codec
->gop_size
= get_be16(pb
);
510 codec
->pix_fmt
= get_be32(pb
);
511 codec
->qmin
= get_byte(pb
);
512 codec
->qmax
= get_byte(pb
);
513 codec
->max_qdiff
= get_byte(pb
);
514 codec
->qcompress
= get_be16(pb
) / 10000.0;
515 codec
->qblur
= get_be16(pb
) / 10000.0;
516 codec
->bit_rate_tolerance
= get_be32(pb
);
517 codec
->rc_eq
= av_strdup(get_strz(pb
, rc_eq_buf
, sizeof(rc_eq_buf
)));
518 codec
->rc_max_rate
= get_be32(pb
);
519 codec
->rc_min_rate
= get_be32(pb
);
520 codec
->rc_buffer_size
= get_be32(pb
);
521 codec
->i_quant_factor
= av_int2dbl(get_be64(pb
));
522 codec
->b_quant_factor
= av_int2dbl(get_be64(pb
));
523 codec
->i_quant_offset
= av_int2dbl(get_be64(pb
));
524 codec
->b_quant_offset
= av_int2dbl(get_be64(pb
));
525 codec
->dct_algo
= get_be32(pb
);
526 codec
->strict_std_compliance
= get_be32(pb
);
527 codec
->max_b_frames
= get_be32(pb
);
528 codec
->luma_elim_threshold
= get_be32(pb
);
529 codec
->chroma_elim_threshold
= get_be32(pb
);
530 codec
->mpeg_quant
= get_be32(pb
);
531 codec
->intra_dc_precision
= get_be32(pb
);
532 codec
->me_method
= get_be32(pb
);
533 codec
->mb_decision
= get_be32(pb
);
534 codec
->nsse_weight
= get_be32(pb
);
535 codec
->frame_skip_cmp
= get_be32(pb
);
536 codec
->rc_buffer_aggressivity
= av_int2dbl(get_be64(pb
));
538 case CODEC_TYPE_AUDIO
:
539 codec
->sample_rate
= get_be32(pb
);
540 codec
->channels
= get_le16(pb
);
541 codec
->frame_size
= get_le16(pb
);
549 /* get until end of block reached */
550 while ((url_ftell(pb
) % ffm
->packet_size
) != 0)
553 /* init packet demux */
554 ffm
->packet_ptr
= ffm
->packet
;
555 ffm
->packet_end
= ffm
->packet
;
556 ffm
->frame_offset
= 0;
558 ffm
->read_state
= READ_HEADER
;
559 ffm
->first_packet
= 1;
562 for(i
=0;i
<s
->nb_streams
;i
++) {
565 av_freep(&st
->priv_data
);
572 /* return < 0 if eof */
573 static int ffm_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
576 FFMContext
*ffm
= s
->priv_data
;
579 switch(ffm
->read_state
) {
581 if (!ffm_is_avail_data(s
, FRAME_HEADER_SIZE
)) {
585 printf("pos=%08"PRIx64
" spos=%"PRIx64
", write_index=%"PRIx64
" size=%"PRIx64
"\n",
586 url_ftell(&s
->pb
), s
->pb
.pos
, ffm
->write_index
, ffm
->file_size
);
588 if (ffm_read_data(s
, ffm
->header
, FRAME_HEADER_SIZE
, 1) !=
594 for(i
=0;i
<FRAME_HEADER_SIZE
;i
++)
595 printf("%02x ", ffm
->header
[i
]);
599 ffm
->read_state
= READ_DATA
;
602 size
= (ffm
->header
[2] << 16) | (ffm
->header
[3] << 8) | ffm
->header
[4];
603 if (!ffm_is_avail_data(s
, size
)) {
607 duration
= (ffm
->header
[5] << 16) | (ffm
->header
[6] << 8) | ffm
->header
[7];
609 av_new_packet(pkt
, size
);
610 pkt
->stream_index
= ffm
->header
[0];
611 pkt
->pos
= url_ftell(&s
->pb
);
612 if (ffm
->header
[1] & FLAG_KEY_FRAME
)
613 pkt
->flags
|= PKT_FLAG_KEY
;
615 ffm
->read_state
= READ_HEADER
;
616 if (ffm_read_data(s
, pkt
->data
, size
, 0) != size
) {
617 /* bad case: desynchronized packet. we cancel all the packet loading */
621 if (ffm
->first_frame_in_packet
)
624 ffm
->first_frame_in_packet
= 0;
626 pkt
->duration
= duration
;
634 /* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated
635 by the write position inside this function */
636 static void ffm_seek1(AVFormatContext
*s
, offset_t pos1
)
638 FFMContext
*ffm
= s
->priv_data
;
639 ByteIOContext
*pb
= &s
->pb
;
642 pos
= pos1
+ ffm
->write_index
;
643 if (pos
>= ffm
->file_size
)
644 pos
-= (ffm
->file_size
- FFM_PACKET_SIZE
);
646 printf("seek to %"PRIx64
" -> %"PRIx64
"\n", pos1
, pos
);
648 url_fseek(pb
, pos
, SEEK_SET
);
651 static int64_t get_pts(AVFormatContext
*s
, offset_t pos
)
653 ByteIOContext
*pb
= &s
->pb
;
660 printf("pts=%0.6f\n", pts
/ 1000000.0);
665 /* seek to a given time in the file. The file read pointer is
666 positionned at or before pts. XXX: the following code is quite
668 static int ffm_seek(AVFormatContext
*s
, int stream_index
, int64_t wanted_pts
, int flags
)
670 FFMContext
*ffm
= s
->priv_data
;
671 offset_t pos_min
, pos_max
, pos
;
672 int64_t pts_min
, pts_max
, pts
;
676 printf("wanted_pts=%0.6f\n", wanted_pts
/ 1000000.0);
678 /* find the position using linear interpolation (better than
679 dichotomy in typical cases) */
681 pos_max
= ffm
->file_size
- 2 * FFM_PACKET_SIZE
;
682 while (pos_min
<= pos_max
) {
683 pts_min
= get_pts(s
, pos_min
);
684 pts_max
= get_pts(s
, pos_max
);
685 /* linear interpolation */
686 pos1
= (double)(pos_max
- pos_min
) * (double)(wanted_pts
- pts_min
) /
687 (double)(pts_max
- pts_min
);
688 pos
= (((int64_t)pos1
) / FFM_PACKET_SIZE
) * FFM_PACKET_SIZE
;
691 else if (pos
>= pos_max
)
693 pts
= get_pts(s
, pos
);
694 /* check if we are lucky */
695 if (pts
== wanted_pts
) {
697 } else if (pts
> wanted_pts
) {
698 pos_max
= pos
- FFM_PACKET_SIZE
;
700 pos_min
= pos
+ FFM_PACKET_SIZE
;
703 pos
= (flags
& AVSEEK_FLAG_BACKWARD
) ? pos_min
: pos_max
;
705 pos
-= FFM_PACKET_SIZE
;
711 #ifdef CONFIG_FFSERVER
712 offset_t
ffm_read_write_index(int fd
)
718 lseek(fd
, 8, SEEK_SET
);
722 pos
|= (int64_t)buf
[i
] << (56 - i
* 8);
726 void ffm_write_write_index(int fd
, offset_t pos
)
732 buf
[i
] = (pos
>> (56 - i
* 8)) & 0xff;
733 lseek(fd
, 8, SEEK_SET
);
737 void ffm_set_write_index(AVFormatContext
*s
, offset_t pos
, offset_t file_size
)
739 FFMContext
*ffm
= s
->priv_data
;
740 ffm
->write_index
= pos
;
741 ffm
->file_size
= file_size
;
743 #endif // CONFIG_FFSERVER
745 static int ffm_read_close(AVFormatContext
*s
)
750 for(i
=0;i
<s
->nb_streams
;i
++) {
752 av_freep(&st
->priv_data
);
757 static int ffm_probe(AVProbeData
*p
)
759 if (p
->buf_size
>= 4 &&
760 p
->buf
[0] == 'F' && p
->buf
[1] == 'F' && p
->buf
[2] == 'M' &&
762 return AVPROBE_SCORE_MAX
+ 1;
766 #ifdef CONFIG_FFM_DEMUXER
767 AVInputFormat ffm_demuxer
= {
778 #ifdef CONFIG_FFM_MUXER
779 AVOutputFormat ffm_muxer
= {
785 /* not really used */
792 #endif //CONFIG_FFM_MUXER