2 * FFM (ffserver live feed) muxer
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
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/intfloat.h"
24 #include "libavutil/avassert.h"
25 #include "libavutil/parseutils.h"
26 #include "libavutil/opt.h"
31 static void flush_packet(AVFormatContext
*s
)
33 FFMContext
*ffm
= s
->priv_data
;
35 AVIOContext
*pb
= s
->pb
;
37 fill_size
= ffm
->packet_end
- ffm
->packet_ptr
;
38 memset(ffm
->packet_ptr
, 0, fill_size
);
40 av_assert1(avio_tell(pb
) % ffm
->packet_size
== 0);
43 avio_wb16(pb
, PACKET_ID
);
44 avio_wb16(pb
, fill_size
);
45 avio_wb64(pb
, ffm
->dts
);
46 h
= ffm
->frame_offset
;
47 if (ffm
->first_packet
)
50 avio_write(pb
, ffm
->packet
, ffm
->packet_end
- ffm
->packet
);
53 /* prepare next packet */
54 ffm
->frame_offset
= 0; /* no key frame */
55 ffm
->packet_ptr
= ffm
->packet
;
56 ffm
->first_packet
= 0;
59 /* 'first' is true if first data of a frame */
60 static void ffm_write_data(AVFormatContext
*s
,
61 const uint8_t *buf
, int size
,
62 int64_t dts
, int header
)
64 FFMContext
*ffm
= s
->priv_data
;
67 if (header
&& ffm
->frame_offset
== 0) {
68 ffm
->frame_offset
= ffm
->packet_ptr
- ffm
->packet
+ FFM_HEADER_SIZE
;
72 /* write as many packets as needed */
74 len
= ffm
->packet_end
- ffm
->packet_ptr
;
77 memcpy(ffm
->packet_ptr
, buf
, len
);
79 ffm
->packet_ptr
+= len
;
82 if (ffm
->packet_ptr
>= ffm
->packet_end
)
87 static void write_header_chunk(AVIOContext
*pb
, AVIOContext
*dpb
, unsigned id
)
90 int dyn_size
= avio_close_dyn_buf(dpb
, &dyn_buf
);
92 avio_wb32(pb
, dyn_size
);
93 avio_write(pb
, dyn_buf
, dyn_size
);
97 static int ffm_write_header_codec_private_ctx(AVIOContext
*pb
, AVCodecContext
*ctx
, int type
)
102 const AVCodec
*enc
= ctx
->codec
? ctx
->codec
: avcodec_find_encoder(ctx
->codec_id
);
105 return AVERROR(EINVAL
);
106 if (ctx
->priv_data
&& enc
->priv_class
&& enc
->priv_data_size
) {
107 if ((ret
= av_opt_serialize(ctx
->priv_data
, AV_OPT_FLAG_ENCODING_PARAM
| type
,
108 AV_OPT_SERIALIZE_SKIP_DEFAULTS
, &buf
, '=', ',')) < 0)
110 if (buf
&& strlen(buf
)) {
111 if (avio_open_dyn_buf(&tmp
) < 0) {
113 return AVERROR(ENOMEM
);
115 avio_put_str(tmp
, buf
);
116 write_header_chunk(pb
, tmp
, MKBETAG('C', 'P', 'R', 'V'));
123 static int ffm_write_header_codec_ctx(AVIOContext
*pb
, AVCodecContext
*ctx
, unsigned tag
, int type
)
128 int ret
, need_coma
= 0;
130 #define SKIP_DEFAULTS AV_OPT_SERIALIZE_SKIP_DEFAULTS
131 #define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT
132 #define ENC AV_OPT_FLAG_ENCODING_PARAM
134 if (avio_open_dyn_buf(&tmp
) < 0)
135 return AVERROR(ENOMEM
);
136 if ((ret
= av_opt_serialize(ctx
, ENC
| type
, SKIP_DEFAULTS
, &buf
, '=', ',')) < 0)
138 if (buf
&& strlen(buf
)) {
139 avio_write(tmp
, buf
, strlen(buf
));
143 if ((ret
= av_opt_serialize(ctx
, 0, SKIP_DEFAULTS
| OPT_FLAGS_EXACT
, &buf
, '=', ',')) < 0)
145 if (buf
&& strlen(buf
)) {
148 avio_write(tmp
, buf
, strlen(buf
));
152 write_header_chunk(pb
, tmp
, tag
);
156 avio_close_dyn_buf(tmp
, &p
);
161 #undef OPT_FLAGS_EXACT
165 static int ffm_write_recommended_config(AVIOContext
*pb
, AVCodecContext
*ctx
, unsigned tag
,
166 const char *configuration
)
169 const AVCodec
*enc
= ctx
->codec
? ctx
->codec
: avcodec_find_encoder(ctx
->codec_id
);
171 AVDictionaryEntry
*t
= NULL
;
172 AVDictionary
*all
= NULL
, *comm
= NULL
, *prv
= NULL
;
175 if (!enc
|| !enc
->priv_class
|| !enc
->priv_data_size
) {
176 /* codec is not known/has no private options, so save everything as common options */
177 if (avio_open_dyn_buf(&tmp
) < 0)
178 return AVERROR(ENOMEM
);
179 avio_put_str(tmp
, configuration
);
180 write_header_chunk(pb
, tmp
, tag
);
184 if ((ret
= av_dict_parse_string(&all
, configuration
, "=", ",", 0)) < 0)
187 while ((t
= av_dict_get(all
, "", t
, AV_DICT_IGNORE_SUFFIX
))) {
188 if (av_opt_find((void *)&enc
->priv_class
, t
->key
, NULL
, 0, AV_OPT_SEARCH_FAKE_OBJ
)) {
189 if ((ret
= av_dict_set(&prv
, t
->key
, t
->value
, 0)) < 0)
191 } else if ((ret
= av_dict_set(&comm
, t
->key
, t
->value
, 0)) < 0)
196 if ((ret
= av_dict_get_string(comm
, &buf
, '=', ',')) < 0 ||
197 (ret
= avio_open_dyn_buf(&tmp
)) < 0)
199 avio_put_str(tmp
, buf
);
201 write_header_chunk(pb
, tmp
, tag
);
204 if ((ret
= av_dict_get_string(prv
, &buf
, '=', ',')) < 0 ||
205 (ret
= avio_open_dyn_buf(&tmp
)) < 0)
207 avio_put_str(tmp
, buf
);
208 write_header_chunk(pb
, tmp
, MKBETAG('C', 'P', 'R', 'V'));
219 static int ffm_write_header(AVFormatContext
*s
)
221 FFMContext
*ffm
= s
->priv_data
;
222 AVDictionaryEntry
*t
;
224 AVIOContext
*pb
= s
->pb
;
225 AVCodecContext
*codec
;
226 int bit_rate
, i
, ret
;
228 if (t
= av_dict_get(s
->metadata
, "creation_time", NULL
, 0)) {
229 ret
= av_parse_time(&ffm
->start_time
, t
->value
, 0);
234 ffm
->packet_size
= FFM_PACKET_SIZE
;
237 avio_wl32(pb
, MKTAG('F', 'F', 'M', '2'));
238 avio_wb32(pb
, ffm
->packet_size
);
239 avio_wb64(pb
, 0); /* current write position */
241 if(avio_open_dyn_buf(&pb
) < 0)
242 return AVERROR(ENOMEM
);
244 avio_wb32(pb
, s
->nb_streams
);
246 for(i
=0;i
<s
->nb_streams
;i
++) {
248 bit_rate
+= st
->codec
->bit_rate
;
250 avio_wb32(pb
, bit_rate
);
252 write_header_chunk(s
->pb
, pb
, MKBETAG('M', 'A', 'I', 'N'));
254 /* list of streams */
255 for(i
=0;i
<s
->nb_streams
;i
++) {
257 avpriv_set_pts_info(st
, 64, 1, 1000000);
258 if(avio_open_dyn_buf(&pb
) < 0)
259 return AVERROR(ENOMEM
);
263 avio_wb32(pb
, codec
->codec_id
);
264 avio_w8(pb
, codec
->codec_type
);
265 avio_wb32(pb
, codec
->bit_rate
);
266 avio_wb32(pb
, codec
->flags
);
267 avio_wb32(pb
, codec
->flags2
);
268 avio_wb32(pb
, codec
->debug
);
269 if (codec
->flags
& CODEC_FLAG_GLOBAL_HEADER
) {
270 avio_wb32(pb
, codec
->extradata_size
);
271 avio_write(pb
, codec
->extradata
, codec
->extradata_size
);
273 write_header_chunk(s
->pb
, pb
, MKBETAG('C', 'O', 'M', 'M'));
275 switch(codec
->codec_type
) {
276 case AVMEDIA_TYPE_VIDEO
:
277 if (st
->recommended_encoder_configuration
) {
278 av_log(NULL
, AV_LOG_DEBUG
, "writing recommended configuration: %s\n",
279 st
->recommended_encoder_configuration
);
280 if ((ret
= ffm_write_recommended_config(s
->pb
, codec
, MKBETAG('S', '2', 'V', 'I'),
281 st
->recommended_encoder_configuration
)) < 0)
283 } else if ((ret
= ffm_write_header_codec_ctx(s
->pb
, codec
, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM
)) < 0 ||
284 (ret
= ffm_write_header_codec_private_ctx(s
->pb
, codec
, AV_OPT_FLAG_VIDEO_PARAM
)) < 0)
287 case AVMEDIA_TYPE_AUDIO
:
288 if (st
->recommended_encoder_configuration
) {
289 av_log(NULL
, AV_LOG_DEBUG
, "writing recommended configuration: %s\n",
290 st
->recommended_encoder_configuration
);
291 if ((ret
= ffm_write_recommended_config(s
->pb
, codec
, MKBETAG('S', '2', 'A', 'U'),
292 st
->recommended_encoder_configuration
)) < 0)
294 } else if ((ret
= ffm_write_header_codec_ctx(s
->pb
, codec
, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM
)) < 0 ||
295 (ret
= ffm_write_header_codec_private_ctx(s
->pb
, codec
, AV_OPT_FLAG_AUDIO_PARAM
)) < 0)
304 avio_wb64(pb
, 0); // end of header
306 /* flush until end of block reached */
307 while ((avio_tell(pb
) % ffm
->packet_size
) != 0)
312 /* init packet mux */
313 ffm
->packet_ptr
= ffm
->packet
;
314 ffm
->packet_end
= ffm
->packet
+ ffm
->packet_size
- FFM_HEADER_SIZE
;
315 av_assert0(ffm
->packet_end
>= ffm
->packet
);
316 ffm
->frame_offset
= 0;
318 ffm
->first_packet
= 1;
323 static int ffm_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
325 FFMContext
*ffm
= s
->priv_data
;
327 uint8_t header
[FRAME_HEADER_SIZE
+4];
328 int header_size
= FRAME_HEADER_SIZE
;
330 dts
= ffm
->start_time
+ pkt
->dts
;
331 /* packet size & key_frame */
332 header
[0] = pkt
->stream_index
;
334 if (pkt
->flags
& AV_PKT_FLAG_KEY
)
335 header
[1] |= FLAG_KEY_FRAME
;
336 AV_WB24(header
+2, pkt
->size
);
337 AV_WB24(header
+5, pkt
->duration
);
338 AV_WB64(header
+8, ffm
->start_time
+ pkt
->pts
);
339 if (pkt
->pts
!= pkt
->dts
) {
340 header
[1] |= FLAG_DTS
;
341 AV_WB32(header
+16, pkt
->pts
- pkt
->dts
);
344 ffm_write_data(s
, header
, header_size
, dts
, 1);
345 ffm_write_data(s
, pkt
->data
, pkt
->size
, dts
, 0);
350 static int ffm_write_trailer(AVFormatContext
*s
)
352 FFMContext
*ffm
= s
->priv_data
;
355 if (ffm
->packet_ptr
> ffm
->packet
)
361 AVOutputFormat ff_ffm_muxer
= {
363 .long_name
= NULL_IF_CONFIG_SMALL("FFM (FFserver live feed)"),
365 .priv_data_size
= sizeof(FFMContext
),
366 .audio_codec
= AV_CODEC_ID_MP2
,
367 .video_codec
= AV_CODEC_ID_MPEG1VIDEO
,
368 .write_header
= ffm_write_header
,
369 .write_packet
= ffm_write_packet
,
370 .write_trailer
= ffm_write_trailer
,
371 .flags
= AVFMT_TS_NEGATIVE
,