]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavformat/ffmenc.c
cosmetics, rename first to header, more explicit name
[frescor/ffmpeg.git] / libavformat / ffmenc.c
1 /*
2  * FFM (ffserver live feed) muxer
3  * Copyright (c) 2001 Fabrice Bellard.
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "avformat.h"
23 #include "ffm.h"
24
25 /* disable pts hack for testing */
26 int ffm_nopts = 0;
27
28 static void flush_packet(AVFormatContext *s)
29 {
30     FFMContext *ffm = s->priv_data;
31     int fill_size, h;
32     ByteIOContext *pb = s->pb;
33
34     fill_size = ffm->packet_end - ffm->packet_ptr;
35     memset(ffm->packet_ptr, 0, fill_size);
36
37     if (url_ftell(pb) % ffm->packet_size)
38         av_abort();
39
40     /* put header */
41     put_be16(pb, PACKET_ID);
42     put_be16(pb, fill_size);
43     put_be64(pb, ffm->pts);
44     h = ffm->frame_offset;
45     if (ffm->first_packet)
46         h |= 0x8000;
47     put_be16(pb, h);
48     put_buffer(pb, ffm->packet, ffm->packet_end - ffm->packet);
49     put_flush_packet(pb);
50
51     /* prepare next packet */
52     ffm->frame_offset = 0; /* no key frame */
53     ffm->pts = 0; /* no pts */
54     ffm->packet_ptr = ffm->packet;
55     ffm->first_packet = 0;
56 }
57
58 /* 'first' is true if first data of a frame */
59 static void ffm_write_data(AVFormatContext *s,
60                            const uint8_t *buf, int size,
61                            int64_t pts, int header)
62 {
63     FFMContext *ffm = s->priv_data;
64     int len;
65
66     if (header && ffm->frame_offset == 0)
67         ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
68     if (header && ffm->pts == 0)
69         ffm->pts = pts;
70
71     /* write as many packets as needed */
72     while (size > 0) {
73         len = ffm->packet_end - ffm->packet_ptr;
74         if (len > size)
75             len = size;
76         memcpy(ffm->packet_ptr, buf, len);
77
78         ffm->packet_ptr += len;
79         buf += len;
80         size -= len;
81         if (ffm->packet_ptr >= ffm->packet_end) {
82             /* special case : no pts in packet : we leave the current one */
83             if (ffm->pts == 0)
84                 ffm->pts = pts;
85
86             flush_packet(s);
87         }
88     }
89 }
90
91 static int ffm_write_header(AVFormatContext *s)
92 {
93     FFMContext *ffm = s->priv_data;
94     AVStream *st;
95     FFMStream *fst;
96     ByteIOContext *pb = s->pb;
97     AVCodecContext *codec;
98     int bit_rate, i;
99
100     ffm->packet_size = FFM_PACKET_SIZE;
101
102     /* header */
103     put_le32(pb, MKTAG('F', 'F', 'M', '1'));
104     put_be32(pb, ffm->packet_size);
105     /* XXX: store write position in other file ? */
106     put_be64(pb, ffm->packet_size); /* current write position */
107
108     put_be32(pb, s->nb_streams);
109     bit_rate = 0;
110     for(i=0;i<s->nb_streams;i++) {
111         st = s->streams[i];
112         bit_rate += st->codec->bit_rate;
113     }
114     put_be32(pb, bit_rate);
115
116     /* list of streams */
117     for(i=0;i<s->nb_streams;i++) {
118         st = s->streams[i];
119         fst = av_mallocz(sizeof(FFMStream));
120         if (!fst)
121             goto fail;
122         av_set_pts_info(st, 64, 1, 1000000);
123         st->priv_data = fst;
124
125         codec = st->codec;
126         /* generic info */
127         put_be32(pb, codec->codec_id);
128         put_byte(pb, codec->codec_type);
129         put_be32(pb, codec->bit_rate);
130         put_be32(pb, st->quality);
131         put_be32(pb, codec->flags);
132         put_be32(pb, codec->flags2);
133         put_be32(pb, codec->debug);
134         /* specific info */
135         switch(codec->codec_type) {
136         case CODEC_TYPE_VIDEO:
137             put_be32(pb, codec->time_base.num);
138             put_be32(pb, codec->time_base.den);
139             put_be16(pb, codec->width);
140             put_be16(pb, codec->height);
141             put_be16(pb, codec->gop_size);
142             put_be32(pb, codec->pix_fmt);
143             put_byte(pb, codec->qmin);
144             put_byte(pb, codec->qmax);
145             put_byte(pb, codec->max_qdiff);
146             put_be16(pb, (int) (codec->qcompress * 10000.0));
147             put_be16(pb, (int) (codec->qblur * 10000.0));
148             put_be32(pb, codec->bit_rate_tolerance);
149             put_strz(pb, codec->rc_eq);
150             put_be32(pb, codec->rc_max_rate);
151             put_be32(pb, codec->rc_min_rate);
152             put_be32(pb, codec->rc_buffer_size);
153             put_be64(pb, av_dbl2int(codec->i_quant_factor));
154             put_be64(pb, av_dbl2int(codec->b_quant_factor));
155             put_be64(pb, av_dbl2int(codec->i_quant_offset));
156             put_be64(pb, av_dbl2int(codec->b_quant_offset));
157             put_be32(pb, codec->dct_algo);
158             put_be32(pb, codec->strict_std_compliance);
159             put_be32(pb, codec->max_b_frames);
160             put_be32(pb, codec->luma_elim_threshold);
161             put_be32(pb, codec->chroma_elim_threshold);
162             put_be32(pb, codec->mpeg_quant);
163             put_be32(pb, codec->intra_dc_precision);
164             put_be32(pb, codec->me_method);
165             put_be32(pb, codec->mb_decision);
166             put_be32(pb, codec->nsse_weight);
167             put_be32(pb, codec->frame_skip_cmp);
168             put_be64(pb, av_dbl2int(codec->rc_buffer_aggressivity));
169             put_be32(pb, codec->codec_tag);
170             break;
171         case CODEC_TYPE_AUDIO:
172             put_be32(pb, codec->sample_rate);
173             put_le16(pb, codec->channels);
174             put_le16(pb, codec->frame_size);
175             break;
176         default:
177             return -1;
178         }
179         /* hack to have real time */
180         if (ffm_nopts)
181             fst->pts = 0;
182         else
183             fst->pts = av_gettime();
184     }
185
186     /* flush until end of block reached */
187     while ((url_ftell(pb) % ffm->packet_size) != 0)
188         put_byte(pb, 0);
189
190     put_flush_packet(pb);
191
192     /* init packet mux */
193     ffm->packet_ptr = ffm->packet;
194     ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
195     assert(ffm->packet_end >= ffm->packet);
196     ffm->frame_offset = 0;
197     ffm->pts = 0;
198     ffm->first_packet = 1;
199
200     return 0;
201  fail:
202     for(i=0;i<s->nb_streams;i++) {
203         st = s->streams[i];
204         av_freep(&st->priv_data);
205     }
206     return -1;
207 }
208
209 static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt)
210 {
211     AVStream *st = s->streams[pkt->stream_index];
212     FFMStream *fst = st->priv_data;
213     int64_t pts;
214     uint8_t header[FRAME_HEADER_SIZE];
215
216     pts = fst->pts;
217     /* packet size & key_frame */
218     header[0] = pkt->stream_index;
219     header[1] = 0;
220     if (pkt->flags & PKT_FLAG_KEY)
221         header[1] |= FLAG_KEY_FRAME;
222     AV_WB24(header+2, pkt->size);
223     AV_WB24(header+5, pkt->duration);
224     ffm_write_data(s, header, FRAME_HEADER_SIZE, pts, 1);
225     ffm_write_data(s, pkt->data, pkt->size, pts, 0);
226
227     fst->pts += pkt->duration;
228     return 0;
229 }
230
231 static int ffm_write_trailer(AVFormatContext *s)
232 {
233     ByteIOContext *pb = s->pb;
234     FFMContext *ffm = s->priv_data;
235
236     /* flush packets */
237     if (ffm->packet_ptr > ffm->packet)
238         flush_packet(s);
239
240     put_flush_packet(pb);
241
242     if (!url_is_streamed(pb)) {
243         int64_t size;
244         /* update the write offset */
245         size = url_ftell(pb);
246         url_fseek(pb, 8, SEEK_SET);
247         put_be64(pb, size);
248         put_flush_packet(pb);
249     }
250
251     return 0;
252 }
253
254 AVOutputFormat ffm_muxer = {
255     "ffm",
256     NULL_IF_CONFIG_SMALL("ffm format"),
257     "",
258     "ffm",
259     sizeof(FFMContext),
260     /* not really used */
261     CODEC_ID_MP2,
262     CODEC_ID_MPEG1VIDEO,
263     ffm_write_header,
264     ffm_write_packet,
265     ffm_write_trailer,
266 };