]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - formats.c
test
[frescor/ffmpeg.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