test
[libav.git] / formats.c
CommitLineData
9aeeeb63
FB
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
17AVFormat *first_format;
18/* XXX: suppress it ! */
19int data_out_size;
20
21const char *comment_string =
22"+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0";
23
24void 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
33AVFormat *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 */
81int 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 */
98int raw_write_header(struct AVFormatContext *s)
99{
100 return 0;
101}
102
103int 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
111int 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
119int raw_write_trailer(struct AVFormatContext *s)
120{
121 return 0;
122}
123
124AVFormat 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
137AVFormat 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
150AVFormat 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
163AVFormat 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 */
177AVEncoder *first_encoder;
178
179void 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
188int 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
207int 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
216int 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
225AVEncoder *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
238void 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
260int 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
278static 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
288void 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
295void 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
314void 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 */
320long 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
342long long put_pos(PutByteContext *s)
343{
344 return put_seek(s, 0, SEEK_CUR);
345}
346
347void 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
355void put_le64(PutByteContext *s, unsigned long long val)
356{
357 put_le32(s, val & 0xffffffff);
358 put_le32(s, val >> 32);
359}
360
361void put_le16(PutByteContext *s, unsigned int val)
362{
363 put_byte(s, val);
364 put_byte(s, val >> 8);
365}
366
367void put_tag(PutByteContext *s, char *tag)
368{
369 while (*tag) {
370 put_byte(s, *tag++);
371 }
372}
373