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 */ | |
5c91a675 | 22 | static int raw_write_header(struct AVFormatContext *s) |
de6d9b64 FB |
23 | { |
24 | return 0; | |
25 | } | |
26 | ||
5c91a675 ZK |
27 | static int raw_write_packet(struct AVFormatContext *s, int stream_index, |
28 | unsigned char *buf, int size, int force_pts) | |
de6d9b64 FB |
29 | { |
30 | put_buffer(&s->pb, buf, size); | |
31 | put_flush_packet(&s->pb); | |
32 | return 0; | |
33 | } | |
34 | ||
5c91a675 | 35 | static int raw_write_trailer(struct AVFormatContext *s) |
de6d9b64 FB |
36 | { |
37 | return 0; | |
38 | } | |
39 | ||
40 | /* raw input */ | |
0c1a9eda | 41 | static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap) |
de6d9b64 FB |
42 | { |
43 | AVStream *st; | |
c9a65ca8 | 44 | int id; |
de6d9b64 | 45 | |
c9a65ca8 | 46 | st = av_new_stream(s, 0); |
de6d9b64 | 47 | if (!st) |
c9a65ca8 | 48 | return AVERROR_NOMEM; |
de6d9b64 | 49 | if (ap) { |
c9a65ca8 FB |
50 | id = s->iformat->value; |
51 | if (id == CODEC_ID_RAWVIDEO) { | |
de6d9b64 | 52 | st->codec.codec_type = CODEC_TYPE_VIDEO; |
de6d9b64 | 53 | } else { |
c9a65ca8 | 54 | st->codec.codec_type = CODEC_TYPE_AUDIO; |
de6d9b64 | 55 | } |
c9a65ca8 FB |
56 | st->codec.codec_id = id; |
57 | ||
de6d9b64 FB |
58 | switch(st->codec.codec_type) { |
59 | case CODEC_TYPE_AUDIO: | |
60 | st->codec.sample_rate = ap->sample_rate; | |
61 | st->codec.channels = ap->channels; | |
de6d9b64 FB |
62 | break; |
63 | case CODEC_TYPE_VIDEO: | |
64 | st->codec.frame_rate = ap->frame_rate; | |
65 | st->codec.width = ap->width; | |
66 | st->codec.height = ap->height; | |
67 | break; | |
68 | default: | |
27e084bd | 69 | return -1; |
de6d9b64 FB |
70 | } |
71 | } else { | |
27e084bd | 72 | return -1; |
de6d9b64 FB |
73 | } |
74 | return 0; | |
75 | } | |
76 | ||
2e93e3aa | 77 | #define RAW_PACKET_SIZE 1024 |
de6d9b64 | 78 | |
5c91a675 | 79 | static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) |
de6d9b64 | 80 | { |
7866eeff | 81 | int ret, size; |
2a6874fd | 82 | // AVStream *st = s->streams[0]; |
7866eeff | 83 | |
231dd3f3 | 84 | size= RAW_PACKET_SIZE; |
de6d9b64 | 85 | |
7866eeff | 86 | if (av_new_packet(pkt, size) < 0) |
de6d9b64 FB |
87 | return -EIO; |
88 | ||
89 | pkt->stream_index = 0; | |
7866eeff | 90 | ret = get_buffer(&s->pb, pkt->data, size); |
2e93e3aa | 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 | ||
5c91a675 | 101 | static int raw_read_close(AVFormatContext *s) |
de6d9b64 FB |
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 | ||
cd66005d FB |
122 | /* ac3 read */ |
123 | static int ac3_read_header(AVFormatContext *s, | |
124 | AVFormatParameters *ap) | |
125 | { | |
126 | AVStream *st; | |
127 | ||
128 | st = av_new_stream(s, 0); | |
129 | if (!st) | |
130 | return AVERROR_NOMEM; | |
131 | ||
132 | st->codec.codec_type = CODEC_TYPE_AUDIO; | |
133 | st->codec.codec_id = CODEC_ID_AC3; | |
134 | /* the parameters will be extracted from the compressed bitstream */ | |
135 | return 0; | |
136 | } | |
137 | ||
de6d9b64 FB |
138 | /* mpeg1/h263 input */ |
139 | static int video_read_header(AVFormatContext *s, | |
140 | AVFormatParameters *ap) | |
141 | { | |
142 | AVStream *st; | |
143 | ||
c9a65ca8 | 144 | st = av_new_stream(s, 0); |
de6d9b64 | 145 | if (!st) |
c9a65ca8 | 146 | return AVERROR_NOMEM; |
de6d9b64 FB |
147 | |
148 | st->codec.codec_type = CODEC_TYPE_VIDEO; | |
c9a65ca8 | 149 | st->codec.codec_id = s->iformat->value; |
27e084bd | 150 | /* for mjpeg, specify frame rate */ |
7866eeff MN |
151 | /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/ |
152 | if (st->codec.codec_id == CODEC_ID_MJPEG || st->codec.codec_id == CODEC_ID_MPEG4) { | |
27e084bd FB |
153 | if (ap) { |
154 | st->codec.frame_rate = ap->frame_rate; | |
155 | } else { | |
156 | st->codec.frame_rate = 25 * FRAME_RATE_BASE; | |
157 | } | |
158 | } | |
de6d9b64 FB |
159 | return 0; |
160 | } | |
161 | ||
c9a65ca8 FB |
162 | #define SEQ_START_CODE 0x000001b3 |
163 | #define GOP_START_CODE 0x000001b8 | |
164 | #define PICTURE_START_CODE 0x00000100 | |
165 | ||
166 | /* XXX: improve that by looking at several start codes */ | |
167 | static int mpegvideo_probe(AVProbeData *p) | |
168 | { | |
fa777321 FB |
169 | int code; |
170 | const uint8_t *d; | |
c9a65ca8 FB |
171 | |
172 | /* we search the first start code. If it is a sequence, gop or | |
173 | picture start code then we decide it is an mpeg video | |
174 | stream. We do not send highest value to give a chance to mpegts */ | |
fa777321 FB |
175 | /* NOTE: the search range was restricted to avoid too many false |
176 | detections */ | |
177 | ||
178 | if (p->buf_size < 6) | |
179 | return 0; | |
180 | d = p->buf; | |
181 | code = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | (d[3]); | |
182 | if ((code & 0xffffff00) == 0x100) { | |
183 | if (code == SEQ_START_CODE || | |
184 | code == GOP_START_CODE || | |
185 | code == PICTURE_START_CODE) | |
186 | return 50 - 1; | |
187 | else | |
188 | return 0; | |
c9a65ca8 FB |
189 | } |
190 | return 0; | |
191 | } | |
192 | ||
193 | AVInputFormat mp3_iformat = { | |
194 | "mp3", | |
de6d9b64 | 195 | "MPEG audio", |
c9a65ca8 FB |
196 | 0, |
197 | NULL, | |
198 | mp3_read_header, | |
199 | raw_read_packet, | |
200 | raw_read_close, | |
bb76a117 | 201 | .extensions = "mp2,mp3", /* XXX: use probe */ |
c9a65ca8 FB |
202 | }; |
203 | ||
204 | AVOutputFormat mp2_oformat = { | |
205 | "mp2", | |
206 | "MPEG audio layer 2", | |
de6d9b64 FB |
207 | "audio/x-mpeg", |
208 | "mp2,mp3", | |
c9a65ca8 | 209 | 0, |
de6d9b64 FB |
210 | CODEC_ID_MP2, |
211 | 0, | |
212 | raw_write_header, | |
213 | raw_write_packet, | |
214 | raw_write_trailer, | |
c9a65ca8 | 215 | }; |
de6d9b64 | 216 | |
c9a65ca8 FB |
217 | |
218 | AVInputFormat ac3_iformat = { | |
219 | "ac3", | |
220 | "raw ac3", | |
221 | 0, | |
222 | NULL, | |
cd66005d | 223 | ac3_read_header, |
de6d9b64 FB |
224 | raw_read_packet, |
225 | raw_read_close, | |
bb76a117 | 226 | .extensions = "ac3", |
de6d9b64 FB |
227 | }; |
228 | ||
c9a65ca8 | 229 | AVOutputFormat ac3_oformat = { |
de6d9b64 FB |
230 | "ac3", |
231 | "raw ac3", | |
232 | "audio/x-ac3", | |
233 | "ac3", | |
c9a65ca8 | 234 | 0, |
de6d9b64 FB |
235 | CODEC_ID_AC3, |
236 | 0, | |
237 | raw_write_header, | |
238 | raw_write_packet, | |
239 | raw_write_trailer, | |
240 | }; | |
241 | ||
c9a65ca8 | 242 | AVOutputFormat h263_oformat = { |
de6d9b64 FB |
243 | "h263", |
244 | "raw h263", | |
245 | "video/x-h263", | |
246 | "h263", | |
247 | 0, | |
c9a65ca8 | 248 | 0, |
de6d9b64 FB |
249 | CODEC_ID_H263, |
250 | raw_write_header, | |
251 | raw_write_packet, | |
252 | raw_write_trailer, | |
c9a65ca8 FB |
253 | }; |
254 | ||
7866eeff MN |
255 | AVInputFormat m4v_iformat = { |
256 | "m4v", | |
257 | "raw MPEG4 video format", | |
258 | 0, | |
2f0f5b20 | 259 | NULL /*mpegvideo_probe*/, |
7866eeff MN |
260 | video_read_header, |
261 | raw_read_packet, | |
262 | raw_read_close, | |
bb76a117 MR |
263 | .extensions = "m4v", //FIXME remove after writing mpeg4_probe |
264 | .value = CODEC_ID_MPEG4, | |
7866eeff MN |
265 | }; |
266 | ||
89b3d7c9 MK |
267 | AVOutputFormat m4v_oformat = { |
268 | "m4v", | |
269 | "raw MPEG4 video format", | |
270 | NULL, | |
271 | "m4v", | |
272 | 0, | |
273 | CODEC_ID_NONE, | |
274 | CODEC_ID_MPEG4, | |
275 | raw_write_header, | |
276 | raw_write_packet, | |
277 | raw_write_trailer, | |
278 | }; | |
279 | ||
c9a65ca8 FB |
280 | AVInputFormat mpegvideo_iformat = { |
281 | "mpegvideo", | |
282 | "MPEG video", | |
283 | 0, | |
284 | mpegvideo_probe, | |
de6d9b64 FB |
285 | video_read_header, |
286 | raw_read_packet, | |
287 | raw_read_close, | |
bb76a117 | 288 | .value = CODEC_ID_MPEG1VIDEO, |
de6d9b64 FB |
289 | }; |
290 | ||
c9a65ca8 FB |
291 | AVOutputFormat mpeg1video_oformat = { |
292 | "mpeg1video", | |
de6d9b64 FB |
293 | "MPEG video", |
294 | "video/x-mpeg", | |
295 | "mpg,mpeg", | |
296 | 0, | |
c9a65ca8 | 297 | 0, |
de6d9b64 FB |
298 | CODEC_ID_MPEG1VIDEO, |
299 | raw_write_header, | |
300 | raw_write_packet, | |
301 | raw_write_trailer, | |
de6d9b64 FB |
302 | }; |
303 | ||
c9a65ca8 | 304 | AVInputFormat mjpeg_iformat = { |
27e084bd FB |
305 | "mjpeg", |
306 | "MJPEG video", | |
27e084bd | 307 | 0, |
c9a65ca8 | 308 | NULL, |
27e084bd FB |
309 | video_read_header, |
310 | raw_read_packet, | |
311 | raw_read_close, | |
bb76a117 MR |
312 | .extensions = "mjpg,mjpeg", |
313 | .value = CODEC_ID_MJPEG, | |
27e084bd FB |
314 | }; |
315 | ||
c9a65ca8 FB |
316 | AVOutputFormat mjpeg_oformat = { |
317 | "mjpeg", | |
318 | "MJPEG video", | |
319 | "video/x-mjpeg", | |
320 | "mjpg,mjpeg", | |
5ed8fafc | 321 | 0, |
5ed8fafc | 322 | 0, |
c9a65ca8 | 323 | CODEC_ID_MJPEG, |
5ed8fafc FB |
324 | raw_write_header, |
325 | raw_write_packet, | |
326 | raw_write_trailer, | |
5ed8fafc FB |
327 | }; |
328 | ||
c9a65ca8 | 329 | /* pcm formats */ |
5ed8fafc | 330 | |
c9a65ca8 FB |
331 | #define PCMDEF(name, long_name, ext, codec) \ |
332 | AVInputFormat pcm_ ## name ## _iformat = {\ | |
333 | #name,\ | |
334 | long_name,\ | |
335 | 0,\ | |
336 | NULL,\ | |
337 | raw_read_header,\ | |
338 | raw_read_packet,\ | |
339 | raw_read_close,\ | |
bb76a117 MR |
340 | .extensions = ext,\ |
341 | .value = codec,\ | |
c9a65ca8 FB |
342 | };\ |
343 | \ | |
344 | AVOutputFormat pcm_ ## name ## _oformat = {\ | |
345 | #name,\ | |
346 | long_name,\ | |
347 | NULL,\ | |
348 | ext,\ | |
349 | 0,\ | |
350 | codec,\ | |
351 | 0,\ | |
352 | raw_write_header,\ | |
353 | raw_write_packet,\ | |
354 | raw_write_trailer,\ | |
5ed8fafc FB |
355 | }; |
356 | ||
5ed8fafc | 357 | #ifdef WORDS_BIGENDIAN |
c9a65ca8 FB |
358 | #define BE_DEF(s) s |
359 | #define LE_DEF(s) NULL | |
5ed8fafc | 360 | #else |
c9a65ca8 FB |
361 | #define BE_DEF(s) NULL |
362 | #define LE_DEF(s) s | |
5ed8fafc | 363 | #endif |
5ed8fafc | 364 | |
5ed8fafc | 365 | |
c9a65ca8 FB |
366 | PCMDEF(s16le, "pcm signed 16 bit little endian format", |
367 | LE_DEF("sw"), CODEC_ID_PCM_S16LE) | |
5ed8fafc | 368 | |
c9a65ca8 FB |
369 | PCMDEF(s16be, "pcm signed 16 bit big endian format", |
370 | BE_DEF("sw"), CODEC_ID_PCM_S16BE) | |
5ed8fafc | 371 | |
c9a65ca8 FB |
372 | PCMDEF(u16le, "pcm unsigned 16 bit little endian format", |
373 | LE_DEF("uw"), CODEC_ID_PCM_U16LE) | |
5ed8fafc | 374 | |
c9a65ca8 FB |
375 | PCMDEF(u16be, "pcm unsigned 16 bit big endian format", |
376 | BE_DEF("uw"), CODEC_ID_PCM_U16BE) | |
5ed8fafc | 377 | |
c9a65ca8 FB |
378 | PCMDEF(s8, "pcm signed 8 bit format", |
379 | "sb", CODEC_ID_PCM_S8) | |
5ed8fafc | 380 | |
c9a65ca8 FB |
381 | PCMDEF(u8, "pcm unsigned 8 bit format", |
382 | "ub", CODEC_ID_PCM_U8) | |
5ed8fafc | 383 | |
c9a65ca8 FB |
384 | PCMDEF(mulaw, "pcm mu law format", |
385 | "ul", CODEC_ID_PCM_MULAW) | |
de6d9b64 | 386 | |
c9a65ca8 FB |
387 | PCMDEF(alaw, "pcm A law format", |
388 | "al", CODEC_ID_PCM_ALAW) | |
de6d9b64 | 389 | |
5c91a675 | 390 | static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt) |
de6d9b64 FB |
391 | { |
392 | int packet_size, ret, width, height; | |
393 | AVStream *st = s->streams[0]; | |
394 | ||
395 | width = st->codec.width; | |
396 | height = st->codec.height; | |
397 | ||
398 | switch(st->codec.pix_fmt) { | |
399 | case PIX_FMT_YUV420P: | |
400 | packet_size = (width * height * 3) / 2; | |
401 | break; | |
402 | case PIX_FMT_YUV422: | |
403 | packet_size = (width * height * 2); | |
404 | break; | |
405 | case PIX_FMT_BGR24: | |
406 | case PIX_FMT_RGB24: | |
407 | packet_size = (width * height * 3); | |
408 | break; | |
409 | default: | |
42343f7e | 410 | av_abort(); |
de6d9b64 FB |
411 | break; |
412 | } | |
413 | ||
414 | if (av_new_packet(pkt, packet_size) < 0) | |
415 | return -EIO; | |
416 | ||
417 | pkt->stream_index = 0; | |
c2c2cd2d | 418 | #if 0 |
de6d9b64 FB |
419 | /* bypass buffered I/O */ |
420 | ret = url_read(url_fileno(&s->pb), pkt->data, pkt->size); | |
c2c2cd2d MN |
421 | #else |
422 | ret = get_buffer(&s->pb, pkt->data, pkt->size); | |
423 | #endif | |
de6d9b64 FB |
424 | if (ret != pkt->size) { |
425 | av_free_packet(pkt); | |
426 | return -EIO; | |
427 | } else { | |
428 | return 0; | |
429 | } | |
430 | } | |
431 | ||
c9a65ca8 FB |
432 | AVInputFormat rawvideo_iformat = { |
433 | "rawvideo", | |
434 | "raw video format", | |
435 | 0, | |
436 | NULL, | |
437 | raw_read_header, | |
438 | rawvideo_read_packet, | |
439 | raw_read_close, | |
bb76a117 MR |
440 | .extensions = "yuv", |
441 | .value = CODEC_ID_RAWVIDEO, | |
c9a65ca8 FB |
442 | }; |
443 | ||
444 | AVOutputFormat rawvideo_oformat = { | |
de6d9b64 FB |
445 | "rawvideo", |
446 | "raw video format", | |
447 | NULL, | |
448 | "yuv", | |
c9a65ca8 | 449 | 0, |
de6d9b64 FB |
450 | CODEC_ID_NONE, |
451 | CODEC_ID_RAWVIDEO, | |
452 | raw_write_header, | |
453 | raw_write_packet, | |
454 | raw_write_trailer, | |
de6d9b64 | 455 | }; |
c9a65ca8 | 456 | |
87bdd3e5 FB |
457 | static int null_write_packet(struct AVFormatContext *s, |
458 | int stream_index, | |
459 | unsigned char *buf, int size, int force_pts) | |
460 | { | |
461 | return 0; | |
462 | } | |
463 | ||
464 | AVOutputFormat null_oformat = { | |
465 | "null", | |
466 | "null video format", | |
467 | NULL, | |
468 | NULL, | |
469 | 0, | |
470 | #ifdef WORDS_BIGENDIAN | |
471 | CODEC_ID_PCM_S16BE, | |
472 | #else | |
473 | CODEC_ID_PCM_S16LE, | |
474 | #endif | |
475 | CODEC_ID_RAWVIDEO, | |
476 | raw_write_header, | |
477 | null_write_packet, | |
478 | raw_write_trailer, | |
b1d89f82 | 479 | .flags = AVFMT_NOFILE | AVFMT_RAWPICTURE, |
87bdd3e5 FB |
480 | }; |
481 | ||
c9a65ca8 FB |
482 | int raw_init(void) |
483 | { | |
484 | av_register_input_format(&mp3_iformat); | |
485 | av_register_output_format(&mp2_oformat); | |
486 | ||
487 | av_register_input_format(&ac3_iformat); | |
488 | av_register_output_format(&ac3_oformat); | |
489 | ||
490 | av_register_output_format(&h263_oformat); | |
89b3d7c9 | 491 | |
7866eeff | 492 | av_register_input_format(&m4v_iformat); |
89b3d7c9 | 493 | av_register_output_format(&m4v_oformat); |
c9a65ca8 FB |
494 | |
495 | av_register_input_format(&mpegvideo_iformat); | |
496 | av_register_output_format(&mpeg1video_oformat); | |
497 | ||
498 | av_register_input_format(&mjpeg_iformat); | |
499 | av_register_output_format(&mjpeg_oformat); | |
500 | ||
501 | av_register_input_format(&pcm_s16le_iformat); | |
502 | av_register_output_format(&pcm_s16le_oformat); | |
503 | av_register_input_format(&pcm_s16be_iformat); | |
504 | av_register_output_format(&pcm_s16be_oformat); | |
505 | av_register_input_format(&pcm_u16le_iformat); | |
506 | av_register_output_format(&pcm_u16le_oformat); | |
507 | av_register_input_format(&pcm_u16be_iformat); | |
508 | av_register_output_format(&pcm_u16be_oformat); | |
509 | av_register_input_format(&pcm_s8_iformat); | |
510 | av_register_output_format(&pcm_s8_oformat); | |
511 | av_register_input_format(&pcm_u8_iformat); | |
512 | av_register_output_format(&pcm_u8_oformat); | |
513 | av_register_input_format(&pcm_mulaw_iformat); | |
514 | av_register_output_format(&pcm_mulaw_oformat); | |
515 | av_register_input_format(&pcm_alaw_iformat); | |
516 | av_register_output_format(&pcm_alaw_oformat); | |
517 | ||
518 | av_register_input_format(&rawvideo_iformat); | |
519 | av_register_output_format(&rawvideo_oformat); | |
87bdd3e5 FB |
520 | |
521 | av_register_output_format(&null_oformat); | |
c9a65ca8 FB |
522 | return 0; |
523 | } |