Initial revision
[libav.git] / formats.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <netinet/in.h>
4 #include <linux/videodev.h>
5 #include <linux/soundcard.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
10 #include <errno.h>
11 #include <sys/time.h>
12 #include <getopt.h>
13 #include <string.h>
14
15 #include "mpegenc.h"
16
17 AVFormat *first_format;
18 /* XXX: suppress it ! */
19 int data_out_size;
20
21 const char *comment_string =
22 "+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0";
23
24 void register_avformat(AVFormat *format)
25 {
26 AVFormat **p;
27 p = &first_format;
28 while (*p != NULL) p = &(*p)->next;
29 *p = format;
30 format->next = NULL;
31 }
32
33 AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
34 {
35 AVFormat *fmt, *fmt_found;
36 int score_max, score;
37 const char *ext, *p;
38 char ext1[32], *q;
39
40 /* find the proper file type */
41 fmt_found = NULL;
42 score_max = 0;
43 fmt = first_format;
44 while (fmt != NULL) {
45 score = 0;
46 if (fmt->name && short_name && !strcmp(fmt->name, short_name))
47 score += 100;
48 if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
49 score += 10;
50 if (filename && fmt->extensions) {
51 ext = strrchr(filename, '.');
52 if (ext) {
53 ext++;
54 p = fmt->extensions;
55 for(;;) {
56 q = ext1;
57 while (*p != '\0' && *p != ',')
58 *q++ = *p++;
59 *q = '\0';
60 if (!strcasecmp(ext1, ext)) {
61 score += 5;
62 break;
63 }
64 if (*p == '\0')
65 break;
66 p++;
67 }
68 }
69 }
70 if (score > score_max) {
71 score_max = score;
72 fmt_found = fmt;
73 }
74 fmt = fmt->next;
75 }
76 return fmt_found;
77 }
78
79 /* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
80 set to the next character in 'str' after the prefix */
81 int strstart(const char *str, const char *val, const char **ptr)
82 {
83 const char *p, *q;
84 p = str;
85 q = val;
86 while (*q != '\0') {
87 if (*p != *q)
88 return 0;
89 p++;
90 q++;
91 }
92 if (ptr)
93 *ptr = p;
94 return 1;
95 }
96
97 /* simple formats */
98 int raw_write_header(struct AVFormatContext *s)
99 {
100 return 0;
101 }
102
103 int raw_write_audio(struct AVFormatContext *s,
104 unsigned char *buf, int size)
105 {
106 put_buffer(&s->pb, buf, size);
107 put_flush_packet(&s->pb);
108 return 0;
109 }
110
111 int raw_write_video(struct AVFormatContext *s,
112 unsigned char *buf, int size)
113 {
114 put_buffer(&s->pb, buf, size);
115 put_flush_packet(&s->pb);
116 return 0;
117 }
118
119 int raw_write_trailer(struct AVFormatContext *s)
120 {
121 return 0;
122 }
123
124 AVFormat mp2_format = {
125 "mp2",
126 "MPEG audio layer 2",
127 "audio/x-mpeg",
128 "mp2,mp3",
129 CODEC_ID_MP2,
130 0,
131 raw_write_header,
132 raw_write_audio,
133 NULL,
134 raw_write_trailer,
135 };
136
137 AVFormat ac3_format = {
138 "ac3",
139 "raw ac3",
140 "audio/x-ac3",
141 "ac3",
142 CODEC_ID_AC3,
143 0,
144 raw_write_header,
145 raw_write_audio,
146 NULL,
147 raw_write_trailer,
148 };
149
150 AVFormat h263_format = {
151 "h263",
152 "raw h263",
153 "video/x-h263",
154 "h263",
155 0,
156 CODEC_ID_H263,
157 raw_write_header,
158 NULL,
159 raw_write_video,
160 raw_write_trailer,
161 };
162
163 AVFormat mpeg1video_format = {
164 "mpeg1video",
165 "MPEG1 video",
166 "video/mpeg",
167 "mpg,mpeg",
168 0,
169 CODEC_ID_MPEG1VIDEO,
170 raw_write_header,
171 NULL,
172 raw_write_video,
173 raw_write_trailer,
174 };
175
176 /* encoder management */
177 AVEncoder *first_encoder;
178
179 void register_avencoder(AVEncoder *format)
180 {
181 AVEncoder **p;
182 p = &first_encoder;
183 while (*p != NULL) p = &(*p)->next;
184 *p = format;
185 format->next = NULL;
186 }
187
188 int avencoder_open(AVEncodeContext *avctx, AVEncoder *codec)
189 {
190 int ret;
191
192 avctx->codec = codec;
193 avctx->frame_number = 0;
194 avctx->priv_data = malloc(codec->priv_data_size);
195 if (!avctx->priv_data)
196 return -ENOMEM;
197 memset(avctx->priv_data, 0, codec->priv_data_size);
198 ret = avctx->codec->init(avctx);
199 if (ret < 0) {
200 free(avctx->priv_data);
201 avctx->priv_data = NULL;
202 return ret;
203 }
204 return 0;
205 }
206
207 int avencoder_encode(AVEncodeContext *avctx, UINT8 *buf, int buf_size, void *data)
208 {
209 int ret;
210
211 ret = avctx->codec->encode(avctx, buf, buf_size, data);
212 avctx->frame_number++;
213 return ret;
214 }
215
216 int avencoder_close(AVEncodeContext *avctx)
217 {
218 if (avctx->codec->close)
219 avctx->codec->close(avctx);
220 free(avctx->priv_data);
221 avctx->priv_data = NULL;
222 return 0;
223 }
224
225 AVEncoder *avencoder_find(enum CodecID id)
226 {
227 AVEncoder *p;
228 p = first_encoder;
229 while (p) {
230 if (p->id == id)
231 return p;
232 p = p->next;
233 }
234 return NULL;
235 }
236
237
238 void avencoder_string(char *buf, int buf_size, AVEncodeContext *enc)
239 {
240 switch(enc->codec->type) {
241 case CODEC_TYPE_VIDEO:
242 snprintf(buf, buf_size,
243 "Video: %s, %dx%d, %d fps, %d kb/s",
244 enc->codec->name, enc->width, enc->height, enc->rate, enc->bit_rate / 1000);
245 break;
246 case CODEC_TYPE_AUDIO:
247 snprintf(buf, buf_size,
248 "Audio: %s, %d Hz, %s, %d kb/s",
249 enc->codec->name, enc->rate,
250 enc->channels == 2 ? "stereo" : "mono",
251 enc->bit_rate / 1000);
252 break;
253 default:
254 abort();
255 }
256 }
257
258 /* PutByteFormat */
259
260 int init_put_byte(PutByteContext *s,
261 unsigned char *buffer,
262 int buffer_size,
263 void *opaque,
264 void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
265 int (*write_seek)(void *opaque, long long offset, int whence))
266 {
267 s->buffer = buffer;
268 s->buf_ptr = buffer;
269 s->buf_end = buffer + buffer_size;
270 s->opaque = opaque;
271 s->write_packet = write_packet;
272 s->write_seek = write_seek;
273 s->pos = 0;
274 return 0;
275 }
276
277
278 static void flush_buffer(PutByteContext *s)
279 {
280 if (s->buf_ptr > s->buffer) {
281 if (s->write_packet)
282 s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
283 s->pos += s->buf_ptr - s->buffer;
284 }
285 s->buf_ptr = s->buffer;
286 }
287
288 void put_byte(PutByteContext *s, int b)
289 {
290 *(s->buf_ptr)++ = b;
291 if (s->buf_ptr >= s->buf_end)
292 flush_buffer(s);
293 }
294
295 void put_buffer(PutByteContext *s, unsigned char *buf, int size)
296 {
297 int len;
298
299 while (size > 0) {
300 len = (s->buf_end - s->buf_ptr);
301 if (len > size)
302 len = size;
303 memcpy(s->buf_ptr, buf, len);
304 s->buf_ptr += len;
305
306 if (s->buf_ptr >= s->buf_end)
307 flush_buffer(s);
308
309 buf += len;
310 size -= len;
311 }
312 }
313
314 void put_flush_packet(PutByteContext *s)
315 {
316 flush_buffer(s);
317 }
318
319 /* XXX: this seek is not correct if we go after the end of the written data */
320 long long put_seek(PutByteContext *s, long long offset, int whence)
321 {
322 long long offset1;
323
324 if (whence != SEEK_CUR && whence != SEEK_SET)
325 return -1;
326 if (whence == SEEK_CUR)
327 offset += s->pos + s->buf_ptr - s->buffer;
328
329 offset1 = offset - s->pos;
330 if (offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
331 /* can do the seek inside the buffer */
332 s->buf_ptr = s->buffer + offset1;
333 } else {
334 if (!s->write_seek)
335 return -1;
336 flush_buffer(s);
337 s->write_seek(s->opaque, offset, whence);
338 }
339 return offset;
340 }
341
342 long long put_pos(PutByteContext *s)
343 {
344 return put_seek(s, 0, SEEK_CUR);
345 }
346
347 void put_le32(PutByteContext *s, unsigned int val)
348 {
349 put_byte(s, val);
350 put_byte(s, val >> 8);
351 put_byte(s, val >> 16);
352 put_byte(s, val >> 24);
353 }
354
355 void put_le64(PutByteContext *s, unsigned long long val)
356 {
357 put_le32(s, val & 0xffffffff);
358 put_le32(s, val >> 32);
359 }
360
361 void put_le16(PutByteContext *s, unsigned int val)
362 {
363 put_byte(s, val);
364 put_byte(s, val >> 8);
365 }
366
367 void put_tag(PutByteContext *s, char *tag)
368 {
369 while (*tag) {
370 put_byte(s, *tag++);
371 }
372 }
373