Commit | Line | Data |
---|---|---|
de6d9b64 FB |
1 | /* |
2 | * RAW encoder and decoder | |
19720f15 | 3 | * Copyright (c) 2001 Fabrice Bellard. |
de6d9b64 | 4 | * |
19720f15 FB |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
de6d9b64 | 9 | * |
19720f15 | 10 | * This library is distributed in the hope that it will be useful, |
de6d9b64 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 FB |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. | |
de6d9b64 | 14 | * |
19720f15 FB |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
de6d9b64 | 18 | */ |
de6d9b64 FB |
19 | #include "avformat.h" |
20 | ||
21 | /* simple formats */ | |
22 | int raw_write_header(struct AVFormatContext *s) | |
23 | { | |
24 | return 0; | |
25 | } | |
26 | ||
27 | int raw_write_packet(struct AVFormatContext *s, | |
28 | int stream_index, | |
10bb7023 | 29 | unsigned char *buf, int size, int force_pts) |
de6d9b64 FB |
30 | { |
31 | put_buffer(&s->pb, buf, size); | |
32 | put_flush_packet(&s->pb); | |
33 | return 0; | |
34 | } | |
35 | ||
36 | int raw_write_trailer(struct AVFormatContext *s) | |
37 | { | |
38 | return 0; | |
39 | } | |
40 | ||
41 | /* raw input */ | |
42 | static int raw_read_header(AVFormatContext *s, | |
43 | AVFormatParameters *ap) | |
44 | { | |
45 | AVStream *st; | |
c9a65ca8 | 46 | int id; |
de6d9b64 | 47 | |
c9a65ca8 | 48 | st = av_new_stream(s, 0); |
de6d9b64 | 49 | if (!st) |
c9a65ca8 | 50 | return AVERROR_NOMEM; |
de6d9b64 | 51 | if (ap) { |
c9a65ca8 FB |
52 | id = s->iformat->value; |
53 | if (id == CODEC_ID_RAWVIDEO) { | |
de6d9b64 | 54 | st->codec.codec_type = CODEC_TYPE_VIDEO; |
de6d9b64 | 55 | } else { |
c9a65ca8 | 56 | st->codec.codec_type = CODEC_TYPE_AUDIO; |
de6d9b64 | 57 | } |
c9a65ca8 FB |
58 | st->codec.codec_id = id; |
59 | ||
de6d9b64 FB |
60 | switch(st->codec.codec_type) { |
61 | case CODEC_TYPE_AUDIO: | |
62 | st->codec.sample_rate = ap->sample_rate; | |
63 | st->codec.channels = ap->channels; | |
de6d9b64 FB |
64 | break; |
65 | case CODEC_TYPE_VIDEO: | |
66 | st->codec.frame_rate = ap->frame_rate; | |
67 | st->codec.width = ap->width; | |
68 | st->codec.height = ap->height; | |
69 | break; | |
70 | default: | |
27e084bd | 71 | return -1; |
de6d9b64 FB |
72 | } |
73 | } else { | |
27e084bd | 74 | return -1; |
de6d9b64 FB |
75 | } |
76 | return 0; | |
77 | } | |
78 | ||
2e93e3aa | 79 | #define RAW_PACKET_SIZE 1024 |
de6d9b64 FB |
80 | |
81 | int raw_read_packet(AVFormatContext *s, | |
82 | AVPacket *pkt) | |
83 | { | |
2e93e3aa | 84 | int ret; |
de6d9b64 | 85 | |
2e93e3aa | 86 | if (av_new_packet(pkt, RAW_PACKET_SIZE) < 0) |
de6d9b64 FB |
87 | return -EIO; |
88 | ||
89 | pkt->stream_index = 0; | |
2e93e3aa FB |
90 | ret = get_buffer(&s->pb, pkt->data, RAW_PACKET_SIZE); |
91 | if (ret <= 0) { | |
de6d9b64 | 92 | av_free_packet(pkt); |
2e93e3aa FB |
93 | return -EIO; |
94 | } | |
95 | /* note: we need to modify the packet size here to handle the last | |
96 | packet */ | |
97 | pkt->size = ret; | |
de6d9b64 FB |
98 | return ret; |
99 | } | |
100 | ||
101 | int raw_read_close(AVFormatContext *s) | |
102 | { | |
103 | return 0; | |
104 | } | |
105 | ||
106 | /* mp3 read */ | |
107 | static int mp3_read_header(AVFormatContext *s, | |
108 | AVFormatParameters *ap) | |
109 | { | |
110 | AVStream *st; | |
111 | ||
c9a65ca8 | 112 | st = av_new_stream(s, 0); |
de6d9b64 | 113 | if (!st) |
c9a65ca8 | 114 | return AVERROR_NOMEM; |
de6d9b64 FB |
115 | |
116 | st->codec.codec_type = CODEC_TYPE_AUDIO; | |
117 | st->codec.codec_id = CODEC_ID_MP2; | |
27e084bd | 118 | /* the parameters will be extracted from the compressed bitstream */ |
de6d9b64 FB |
119 | return 0; |
120 | } | |
121 | ||
122 | /* mpeg1/h263 input */ | |
123 | static int video_read_header(AVFormatContext *s, | |
124 | AVFormatParameters *ap) | |
125 | { | |
126 | AVStream *st; | |
127 | ||
c9a65ca8 | 128 | st = av_new_stream(s, 0); |
de6d9b64 | 129 | if (!st) |
c9a65ca8 | 130 | return AVERROR_NOMEM; |
de6d9b64 FB |
131 | |
132 | st->codec.codec_type = CODEC_TYPE_VIDEO; | |
c9a65ca8 | 133 | st->codec.codec_id = s->iformat->value; |
27e084bd FB |
134 | /* for mjpeg, specify frame rate */ |
135 | if (st->codec.codec_id == CODEC_ID_MJPEG) { | |
136 | if (ap) { | |
137 | st->codec.frame_rate = ap->frame_rate; | |
138 | } else { | |
139 | st->codec.frame_rate = 25 * FRAME_RATE_BASE; | |
140 | } | |
141 | } | |
de6d9b64 FB |
142 | return 0; |
143 | } | |
144 | ||
c9a65ca8 FB |
145 | #define SEQ_START_CODE 0x000001b3 |
146 | #define GOP_START_CODE 0x000001b8 | |
147 | #define PICTURE_START_CODE 0x00000100 | |
148 | ||
149 | /* XXX: improve that by looking at several start codes */ | |
150 | static int mpegvideo_probe(AVProbeData *p) | |
151 | { | |
152 | int code, c, i; | |
153 | code = 0xff; | |
154 | ||
155 | /* we search the first start code. If it is a sequence, gop or | |
156 | picture start code then we decide it is an mpeg video | |
157 | stream. We do not send highest value to give a chance to mpegts */ | |
158 | for(i=0;i<p->buf_size;i++) { | |
159 | c = p->buf[i]; | |
160 | code = (code << 8) | c; | |
161 | if ((code & 0xffffff00) == 0x100) { | |
162 | if (code == SEQ_START_CODE || | |
163 | code == GOP_START_CODE || | |
164 | code == PICTURE_START_CODE) | |
165 | return AVPROBE_SCORE_MAX - 1; | |
166 | else | |
167 | return 0; | |
168 | } | |
169 | } | |
170 | return 0; | |
171 | } | |
172 | ||
173 | AVInputFormat mp3_iformat = { | |
174 | "mp3", | |
de6d9b64 | 175 | "MPEG audio", |
c9a65ca8 FB |
176 | 0, |
177 | NULL, | |
178 | mp3_read_header, | |
179 | raw_read_packet, | |
180 | raw_read_close, | |
181 | extensions: "mp2,mp3", /* XXX: use probe */ | |
182 | }; | |
183 | ||
184 | AVOutputFormat mp2_oformat = { | |
185 | "mp2", | |
186 | "MPEG audio layer 2", | |
de6d9b64 FB |
187 | "audio/x-mpeg", |
188 | "mp2,mp3", | |
c9a65ca8 | 189 | 0, |
de6d9b64 FB |
190 | CODEC_ID_MP2, |
191 | 0, | |
192 | raw_write_header, | |
193 | raw_write_packet, | |
194 | raw_write_trailer, | |
c9a65ca8 | 195 | }; |
de6d9b64 | 196 | |
c9a65ca8 FB |
197 | |
198 | AVInputFormat ac3_iformat = { | |
199 | "ac3", | |
200 | "raw ac3", | |
201 | 0, | |
202 | NULL, | |
203 | raw_read_header, | |
de6d9b64 FB |
204 | raw_read_packet, |
205 | raw_read_close, | |
c9a65ca8 FB |
206 | extensions: "ac3", |
207 | value: CODEC_ID_AC3, | |
de6d9b64 FB |
208 | }; |
209 | ||
c9a65ca8 | 210 | AVOutputFormat ac3_oformat = { |
de6d9b64 FB |
211 | "ac3", |
212 | "raw ac3", | |
213 | "audio/x-ac3", | |
214 | "ac3", | |
c9a65ca8 | 215 | 0, |
de6d9b64 FB |
216 | CODEC_ID_AC3, |
217 | 0, | |
218 | raw_write_header, | |
219 | raw_write_packet, | |
220 | raw_write_trailer, | |
221 | }; | |
222 | ||
c9a65ca8 | 223 | AVOutputFormat h263_oformat = { |
de6d9b64 FB |
224 | "h263", |
225 | "raw h263", | |
226 | "video/x-h263", | |
227 | "h263", | |
228 | 0, | |
c9a65ca8 | 229 | 0, |
de6d9b64 FB |
230 | CODEC_ID_H263, |
231 | raw_write_header, | |
232 | raw_write_packet, | |
233 | raw_write_trailer, | |
c9a65ca8 FB |
234 | }; |
235 | ||
236 | AVInputFormat mpegvideo_iformat = { | |
237 | "mpegvideo", | |
238 | "MPEG video", | |
239 | 0, | |
240 | mpegvideo_probe, | |
de6d9b64 FB |
241 | video_read_header, |
242 | raw_read_packet, | |
243 | raw_read_close, | |
c9a65ca8 | 244 | value: CODEC_ID_MPEG1VIDEO, |
de6d9b64 FB |
245 | }; |
246 | ||
c9a65ca8 FB |
247 | AVOutputFormat mpeg1video_oformat = { |
248 | "mpeg1video", | |
de6d9b64 FB |
249 | "MPEG video", |
250 | "video/x-mpeg", | |
251 | "mpg,mpeg", | |
252 | 0, | |
c9a65ca8 | 253 | 0, |
de6d9b64 FB |
254 | CODEC_ID_MPEG1VIDEO, |
255 | raw_write_header, | |
256 | raw_write_packet, | |
257 | raw_write_trailer, | |
de6d9b64 FB |
258 | }; |
259 | ||
c9a65ca8 | 260 | AVInputFormat mjpeg_iformat = { |
27e084bd FB |
261 | "mjpeg", |
262 | "MJPEG video", | |
27e084bd | 263 | 0, |
c9a65ca8 | 264 | NULL, |
27e084bd FB |
265 | video_read_header, |
266 | raw_read_packet, | |
267 | raw_read_close, | |
c9a65ca8 FB |
268 | extensions: "mjpg,mjpeg", |
269 | value: CODEC_ID_MJPEG, | |
27e084bd FB |
270 | }; |
271 | ||
c9a65ca8 FB |
272 | AVOutputFormat mjpeg_oformat = { |
273 | "mjpeg", | |
274 | "MJPEG video", | |
275 | "video/x-mjpeg", | |
276 | "mjpg,mjpeg", | |
5ed8fafc | 277 | 0, |
5ed8fafc | 278 | 0, |
c9a65ca8 | 279 | CODEC_ID_MJPEG, |
5ed8fafc FB |
280 | raw_write_header, |
281 | raw_write_packet, | |
282 | raw_write_trailer, | |
5ed8fafc FB |
283 | }; |
284 | ||
c9a65ca8 | 285 | /* pcm formats */ |
5ed8fafc | 286 | |
c9a65ca8 FB |
287 | #define PCMDEF(name, long_name, ext, codec) \ |
288 | AVInputFormat pcm_ ## name ## _iformat = {\ | |
289 | #name,\ | |
290 | long_name,\ | |
291 | 0,\ | |
292 | NULL,\ | |
293 | raw_read_header,\ | |
294 | raw_read_packet,\ | |
295 | raw_read_close,\ | |
296 | extensions: ext,\ | |
297 | value: codec,\ | |
298 | };\ | |
299 | \ | |
300 | AVOutputFormat pcm_ ## name ## _oformat = {\ | |
301 | #name,\ | |
302 | long_name,\ | |
303 | NULL,\ | |
304 | ext,\ | |
305 | 0,\ | |
306 | codec,\ | |
307 | 0,\ | |
308 | raw_write_header,\ | |
309 | raw_write_packet,\ | |
310 | raw_write_trailer,\ | |
5ed8fafc FB |
311 | }; |
312 | ||
5ed8fafc | 313 | #ifdef WORDS_BIGENDIAN |
c9a65ca8 FB |
314 | #define BE_DEF(s) s |
315 | #define LE_DEF(s) NULL | |
5ed8fafc | 316 | #else |
c9a65ca8 FB |
317 | #define BE_DEF(s) NULL |
318 | #define LE_DEF(s) s | |
5ed8fafc | 319 | #endif |
5ed8fafc | 320 | |
5ed8fafc | 321 | |
c9a65ca8 FB |
322 | PCMDEF(s16le, "pcm signed 16 bit little endian format", |
323 | LE_DEF("sw"), CODEC_ID_PCM_S16LE) | |
5ed8fafc | 324 | |
c9a65ca8 FB |
325 | PCMDEF(s16be, "pcm signed 16 bit big endian format", |
326 | BE_DEF("sw"), CODEC_ID_PCM_S16BE) | |
5ed8fafc | 327 | |
c9a65ca8 FB |
328 | PCMDEF(u16le, "pcm unsigned 16 bit little endian format", |
329 | LE_DEF("uw"), CODEC_ID_PCM_U16LE) | |
5ed8fafc | 330 | |
c9a65ca8 FB |
331 | PCMDEF(u16be, "pcm unsigned 16 bit big endian format", |
332 | BE_DEF("uw"), CODEC_ID_PCM_U16BE) | |
5ed8fafc | 333 | |
c9a65ca8 FB |
334 | PCMDEF(s8, "pcm signed 8 bit format", |
335 | "sb", CODEC_ID_PCM_S8) | |
5ed8fafc | 336 | |
c9a65ca8 FB |
337 | PCMDEF(u8, "pcm unsigned 8 bit format", |
338 | "ub", CODEC_ID_PCM_U8) | |
5ed8fafc | 339 | |
c9a65ca8 FB |
340 | PCMDEF(mulaw, "pcm mu law format", |
341 | "ul", CODEC_ID_PCM_MULAW) | |
de6d9b64 | 342 | |
c9a65ca8 FB |
343 | PCMDEF(alaw, "pcm A law format", |
344 | "al", CODEC_ID_PCM_ALAW) | |
de6d9b64 FB |
345 | |
346 | int rawvideo_read_packet(AVFormatContext *s, | |
347 | AVPacket *pkt) | |
348 | { | |
349 | int packet_size, ret, width, height; | |
350 | AVStream *st = s->streams[0]; | |
351 | ||
352 | width = st->codec.width; | |
353 | height = st->codec.height; | |
354 | ||
355 | switch(st->codec.pix_fmt) { | |
356 | case PIX_FMT_YUV420P: | |
357 | packet_size = (width * height * 3) / 2; | |
358 | break; | |
359 | case PIX_FMT_YUV422: | |
360 | packet_size = (width * height * 2); | |
361 | break; | |
362 | case PIX_FMT_BGR24: | |
363 | case PIX_FMT_RGB24: | |
364 | packet_size = (width * height * 3); | |
365 | break; | |
366 | default: | |
367 | abort(); | |
368 | break; | |
369 | } | |
370 | ||
371 | if (av_new_packet(pkt, packet_size) < 0) | |
372 | return -EIO; | |
373 | ||
374 | pkt->stream_index = 0; | |
375 | /* bypass buffered I/O */ | |
376 | ret = url_read(url_fileno(&s->pb), pkt->data, pkt->size); | |
377 | if (ret != pkt->size) { | |
378 | av_free_packet(pkt); | |
379 | return -EIO; | |
380 | } else { | |
381 | return 0; | |
382 | } | |
383 | } | |
384 | ||
c9a65ca8 FB |
385 | AVInputFormat rawvideo_iformat = { |
386 | "rawvideo", | |
387 | "raw video format", | |
388 | 0, | |
389 | NULL, | |
390 | raw_read_header, | |
391 | rawvideo_read_packet, | |
392 | raw_read_close, | |
393 | extensions: "yuv", | |
394 | value: CODEC_ID_RAWVIDEO, | |
395 | }; | |
396 | ||
397 | AVOutputFormat rawvideo_oformat = { | |
de6d9b64 FB |
398 | "rawvideo", |
399 | "raw video format", | |
400 | NULL, | |
401 | "yuv", | |
c9a65ca8 | 402 | 0, |
de6d9b64 FB |
403 | CODEC_ID_NONE, |
404 | CODEC_ID_RAWVIDEO, | |
405 | raw_write_header, | |
406 | raw_write_packet, | |
407 | raw_write_trailer, | |
de6d9b64 | 408 | }; |
c9a65ca8 FB |
409 | |
410 | int raw_init(void) | |
411 | { | |
412 | av_register_input_format(&mp3_iformat); | |
413 | av_register_output_format(&mp2_oformat); | |
414 | ||
415 | av_register_input_format(&ac3_iformat); | |
416 | av_register_output_format(&ac3_oformat); | |
417 | ||
418 | av_register_output_format(&h263_oformat); | |
419 | ||
420 | av_register_input_format(&mpegvideo_iformat); | |
421 | av_register_output_format(&mpeg1video_oformat); | |
422 | ||
423 | av_register_input_format(&mjpeg_iformat); | |
424 | av_register_output_format(&mjpeg_oformat); | |
425 | ||
426 | av_register_input_format(&pcm_s16le_iformat); | |
427 | av_register_output_format(&pcm_s16le_oformat); | |
428 | av_register_input_format(&pcm_s16be_iformat); | |
429 | av_register_output_format(&pcm_s16be_oformat); | |
430 | av_register_input_format(&pcm_u16le_iformat); | |
431 | av_register_output_format(&pcm_u16le_oformat); | |
432 | av_register_input_format(&pcm_u16be_iformat); | |
433 | av_register_output_format(&pcm_u16be_oformat); | |
434 | av_register_input_format(&pcm_s8_iformat); | |
435 | av_register_output_format(&pcm_s8_oformat); | |
436 | av_register_input_format(&pcm_u8_iformat); | |
437 | av_register_output_format(&pcm_u8_oformat); | |
438 | av_register_input_format(&pcm_mulaw_iformat); | |
439 | av_register_output_format(&pcm_mulaw_oformat); | |
440 | av_register_input_format(&pcm_alaw_iformat); | |
441 | av_register_output_format(&pcm_alaw_oformat); | |
442 | ||
443 | av_register_input_format(&rawvideo_iformat); | |
444 | av_register_output_format(&rawvideo_oformat); | |
445 | return 0; | |
446 | } |