3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
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.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
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
21 extern AVInputFormat pgm_iformat;
22 extern AVOutputFormat pgm_oformat;
23 extern AVInputFormat pgmyuv_iformat;
24 extern AVOutputFormat pgmyuv_oformat;
25 extern AVInputFormat ppm_iformat;
26 extern AVOutputFormat ppm_oformat;
27 extern AVInputFormat imgyuv_iformat;
28 extern AVOutputFormat imgyuv_oformat;
29 extern AVInputFormat pgmpipe_iformat;
30 extern AVOutputFormat pgmpipe_oformat;
31 extern AVInputFormat pgmyuvpipe_iformat;
32 extern AVOutputFormat pgmyuvpipe_oformat;
33 extern AVInputFormat ppmpipe_iformat;
34 extern AVOutputFormat ppmpipe_oformat;
37 #define IMGFMT_PGMYUV 2
51 static inline int pnm_space(int c)
53 return (c==' ' || c=='\n' || c=='\r' || c=='\t');
56 static void pnm_get(ByteIOContext *f, char *str, int buf_size)
69 } while (pnm_space(c));
75 if ((s - str) < buf_size - 1)
78 } while (!pnm_space(c));
82 static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
91 pnm_get(f, buf1, sizeof(buf1));
92 if (strcmp(buf1, "P5")) {
95 pnm_get(f, buf1, sizeof(buf1));
96 pnm_get(f, buf1, sizeof(buf1));
97 pnm_get(f, buf1, sizeof(buf1));
100 picture[1] = buf + width * height;
101 picture[2] = buf + width * height + (width * height / 4);
102 get_buffer(f, picture[0], width * height);
107 for(i=0;i<height;i++) {
108 get_buffer(f, picture[1] + i * width, width);
109 get_buffer(f, picture[2] + i * width, width);
112 for(i=0;i<height;i++) {
113 memset(picture[1] + i * width, 128, width);
114 memset(picture[2] + i * width, 128, width);
120 static int ppm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size)
129 pnm_get(f, buf1, sizeof(buf1));
130 if (strcmp(buf1, "P6")) {
134 pnm_get(f, buf1, sizeof(buf1));
135 pnm_get(f, buf1, sizeof(buf1));
136 pnm_get(f, buf1, sizeof(buf1));
139 get_buffer(f, picture[0], width * height*3);
145 static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
147 ByteIOContext pb1, *pb = &pb1;
148 char fname[1024], *p;
151 size = s->width * s->height;
153 strcpy(fname, filename);
154 p = strrchr(fname, '.');
155 if (!p || p[1] != 'Y')
158 if (url_fopen(pb, fname, URL_RDONLY) < 0)
161 get_buffer(pb, buf, size);
165 if (url_fopen(pb, fname, URL_RDONLY) < 0)
168 get_buffer(pb, buf + size, size / 4);
172 if (url_fopen(pb, fname, URL_RDONLY) < 0)
175 get_buffer(pb, buf + size + (size / 4), size / 4);
180 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
182 VideoData *s = s1->priv_data;
185 ByteIOContext f1, *f;
188 This if-statement destroys pipes - I do not see why it is necessary
189 if (get_frame_filename(filename, sizeof(filename),
190 s->path, s->img_number) < 0)
193 get_frame_filename(filename, sizeof(filename),
194 s->path, s->img_number);
197 if (url_fopen(f, filename, URL_RDONLY) < 0)
205 av_new_packet(pkt, s->img_size);
206 pkt->stream_index = 0;
210 ret = pgm_read(s, f, pkt->data, pkt->size, 1);
213 ret = pgm_read(s, f, pkt->data, pkt->size, 0);
216 ret = yuv_read(s, filename, pkt->data, pkt->size);
219 ret = ppm_read(s, f, pkt->data, pkt->size);
231 return -EIO; /* signal EOF */
238 static int sizes[][2] = {
250 static int infer_size(int *width_ptr, int *height_ptr, int size)
254 for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
255 if ((sizes[i][0] * sizes[i][1]) == size) {
256 *width_ptr = sizes[i][0];
257 *height_ptr = sizes[i][1];
264 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
266 VideoData *s = s1->priv_data;
270 ByteIOContext pb1, *f = &pb1;
273 st = av_new_stream(s1, 0);
279 strcpy(s->path, s1->filename);
283 if (s1->iformat->flags & AVFMT_NOFILE)
288 if (s1->iformat == &pgmyuvpipe_iformat ||
289 s1->iformat == &pgmyuv_iformat)
290 s->img_fmt = IMGFMT_PGMYUV;
291 else if (s1->iformat == &pgmpipe_iformat ||
292 s1->iformat == &pgm_iformat)
293 s->img_fmt = IMGFMT_PGM;
294 else if (s1->iformat == &imgyuv_iformat)
295 s->img_fmt = IMGFMT_YUV;
296 else if (s1->iformat == &ppmpipe_iformat ||
297 s1->iformat == &ppm_iformat)
298 s->img_fmt = IMGFMT_PPM;
303 /* try to find the first image */
305 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
307 if (url_fopen(f, buf, URL_RDONLY) >= 0)
317 /* find the image size */
318 /* XXX: use generic file format guessing, as mpeg */
323 pnm_get(f, buf1, sizeof(buf1));
324 pnm_get(f, buf1, sizeof(buf1));
325 s->width = atoi(buf1);
326 pnm_get(f, buf1, sizeof(buf1));
328 if (s->img_fmt == IMGFMT_PGMYUV)
333 (s->width % 2) != 0 ||
334 (s->height % 2) != 0) {
339 /* infer size by using the file size. */
346 img_size = url_seek(h, 0, SEEK_END);
347 if (infer_size(&s->width, &s->height, img_size) < 0) {
357 url_fseek(f, 0, SEEK_SET);
361 st->codec.codec_type = CODEC_TYPE_VIDEO;
362 st->codec.codec_id = CODEC_ID_RAWVIDEO;
363 st->codec.width = s->width;
364 st->codec.height = s->height;
365 if (s->img_fmt == IMGFMT_PPM) {
366 st->codec.pix_fmt = PIX_FMT_RGB24;
367 s->img_size = (s->width * s->height * 3);
369 st->codec.pix_fmt = PIX_FMT_YUV420P;
370 s->img_size = (s->width * s->height * 3) / 2;
372 if (!ap || !ap->frame_rate)
373 st->codec.frame_rate = 25 * FRAME_RATE_BASE;
375 st->codec.frame_rate = ap->frame_rate;
386 static int img_read_close(AVFormatContext *s1)
391 /******************************************************/
394 static int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv)
398 UINT8 *ptr, *ptr1, *ptr2;
402 h = (height * 3) / 2;
403 snprintf(buf, sizeof(buf),
406 put_buffer(pb, buf, strlen(buf));
408 ptr = picture->data[0];
409 for(i=0;i<height;i++) {
410 put_buffer(pb, ptr, width);
411 ptr += picture->linesize[0];
417 ptr1 = picture->data[1];
418 ptr2 = picture->data[2];
419 for(i=0;i<height;i++) {
420 put_buffer(pb, ptr1, width);
421 put_buffer(pb, ptr2, width);
422 ptr1 += picture->linesize[1];
423 ptr2 += picture->linesize[2];
426 put_flush_packet(pb);
430 static int ppm_save(AVPicture *picture, int width, int height, ByteIOContext *pb)
436 snprintf(buf, sizeof(buf),
439 put_buffer(pb, buf, strlen(buf));
441 ptr = picture->data[0];
442 for(i=0;i<height;i++) {
443 put_buffer(pb, ptr, width * 3);
444 ptr += picture->linesize[0];
447 put_flush_packet(pb);
451 static int yuv_save(AVPicture *picture, int width, int height, const char *filename)
453 ByteIOContext pb1, *pb = &pb1;
454 char fname[1024], *p;
457 static char *ext = "YUV";
459 strcpy(fname, filename);
460 p = strrchr(fname, '.');
461 if (!p || p[1] != 'Y')
471 if (url_fopen(pb, fname, URL_WRONLY) < 0)
474 ptr = picture->data[i];
475 for(j=0;j<height;j++) {
476 put_buffer(pb, ptr, width);
477 ptr += picture->linesize[i];
479 put_flush_packet(pb);
485 static int img_write_header(AVFormatContext *s)
487 VideoData *img = s->priv_data;
490 strcpy(img->path, s->filename);
493 if (s->oformat->flags & AVFMT_NOFILE)
498 if (s->oformat == &pgmyuvpipe_oformat ||
499 s->oformat == &pgmyuv_oformat) {
500 img->img_fmt = IMGFMT_PGMYUV;
501 } else if (s->oformat == &pgmpipe_oformat ||
502 s->oformat == &pgm_oformat) {
503 img->img_fmt = IMGFMT_PGM;
504 } else if (s->oformat == &imgyuv_oformat) {
505 img->img_fmt = IMGFMT_YUV;
506 } else if (s->oformat == &ppmpipe_oformat ||
507 s->oformat == &ppm_oformat) {
508 img->img_fmt = IMGFMT_PPM;
518 static int img_write_packet(AVFormatContext *s, int stream_index,
519 UINT8 *buf, int size, int force_pts)
521 VideoData *img = s->priv_data;
522 AVStream *st = s->streams[stream_index];
523 ByteIOContext pb1, *pb;
525 int width, height, ret, size1;
528 width = st->codec.width;
529 height = st->codec.height;
531 switch(st->codec.pix_fmt) {
532 case PIX_FMT_YUV420P:
533 size1 = (width * height * 3) / 2;
537 picture.data[0] = buf;
538 picture.data[1] = picture.data[0] + width * height;
539 picture.data[2] = picture.data[1] + (width * height) / 4;
540 picture.linesize[0] = width;
541 picture.linesize[1] = width >> 1;
542 picture.linesize[2] = width >> 1;
545 size1 = (width * height * 3);
548 picture.data[0] = buf;
549 picture.linesize[0] = width * 3;
556 This if-statement destroys pipes - I do not see why it is necessary
557 if (get_frame_filename(filename, sizeof(filename),
558 img->path, img->img_number) < 0)
561 get_frame_filename(filename, sizeof(filename),
562 img->path, img->img_number);
565 if (url_fopen(pb, filename, URL_WRONLY) < 0)
570 switch(img->img_fmt) {
572 ret = pgm_save(&picture, width, height, pb, 1);
575 ret = pgm_save(&picture, width, height, pb, 0);
578 ret = yuv_save(&picture, width, height, filename);
581 ret = ppm_save(&picture, width, height, pb);
592 static int img_write_trailer(AVFormatContext *s)
597 AVInputFormat pgm_iformat = {
606 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
610 AVOutputFormat pgm_oformat = {
621 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
624 AVInputFormat pgmyuv_iformat = {
626 "pgm with YUV content image format",
633 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
636 AVOutputFormat pgmyuv_oformat = {
638 "pgm with YUV content image format",
647 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
650 AVInputFormat ppm_iformat = {
659 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
663 AVOutputFormat ppm_oformat = {
674 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
677 AVInputFormat imgyuv_iformat = {
686 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
690 AVOutputFormat imgyuv_oformat = {
701 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
704 AVInputFormat pgmpipe_iformat = {
715 AVOutputFormat pgmpipe_oformat = {
728 AVInputFormat pgmyuvpipe_iformat = {
730 "PGM YUV pipe format",
739 AVOutputFormat pgmyuvpipe_oformat = {
741 "PGM YUV pipe format",
752 AVInputFormat ppmpipe_iformat = {
764 AVOutputFormat ppmpipe_oformat = {
781 av_register_input_format(&pgm_iformat);
782 av_register_output_format(&pgm_oformat);
784 av_register_input_format(&pgmyuv_iformat);
785 av_register_output_format(&pgmyuv_oformat);
787 av_register_input_format(&ppm_iformat);
788 av_register_output_format(&ppm_oformat);
790 av_register_input_format(&imgyuv_iformat);
791 av_register_output_format(&imgyuv_oformat);
793 av_register_input_format(&pgmpipe_iformat);
794 av_register_output_format(&pgmpipe_oformat);
796 av_register_input_format(&pgmyuvpipe_iformat);
797 av_register_output_format(&pgmyuvpipe_oformat);
799 av_register_input_format(&ppmpipe_iformat);
800 av_register_output_format(&ppmpipe_oformat);