3 * Copyright (c) 2000, 2001 Gerard Lantau.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #define IMGFMT_PGMYUV 2
43 static inline int pnm_space(int c
)
45 return (c
==' ' || c
=='\n' || c
=='\r' || c
=='\t');
48 static void pnm_get(ByteIOContext
*f
, char *str
, int buf_size
)
61 } while (pnm_space(c
));
67 if ((s
- str
) < buf_size
- 1)
70 } while (!pnm_space(c
));
74 static int pgm_read(VideoData
*s
, ByteIOContext
*f
, UINT8
*buf
, int size
, int is_yuv
)
83 pnm_get(f
, buf1
, sizeof(buf1
));
84 if (strcmp(buf1
, "P5")) {
87 pnm_get(f
, buf1
, sizeof(buf1
));
88 pnm_get(f
, buf1
, sizeof(buf1
));
89 pnm_get(f
, buf1
, sizeof(buf1
));
92 picture
[1] = buf
+ width
* height
;
93 picture
[2] = buf
+ width
* height
+ (width
* height
/ 4);
94 get_buffer(f
, picture
[0], width
* height
);
99 for(i
=0;i
<height
;i
++) {
100 get_buffer(f
, picture
[1] + i
* width
, width
);
101 get_buffer(f
, picture
[2] + i
* width
, width
);
104 for(i
=0;i
<height
;i
++) {
105 memset(picture
[1] + i
* width
, 128, width
);
106 memset(picture
[2] + i
* width
, 128, width
);
112 static int yuv_read(VideoData
*s
, const char *filename
, UINT8
*buf
, int size1
)
114 ByteIOContext pb1
, *pb
= &pb1
;
115 char fname
[1024], *p
;
118 size
= s
->width
* s
->height
;
120 strcpy(fname
, filename
);
121 p
= strrchr(fname
, '.');
122 if (!p
|| p
[1] != 'Y')
125 if (url_fopen(pb
, fname
, URL_RDONLY
) < 0)
128 get_buffer(pb
, buf
, size
);
132 if (url_fopen(pb
, fname
, URL_RDONLY
) < 0)
135 get_buffer(pb
, buf
+ size
, size
/ 4);
139 if (url_fopen(pb
, fname
, URL_RDONLY
) < 0)
142 get_buffer(pb
, buf
+ size
+ (size
/ 4), size
/ 4);
147 int img_read_packet(AVFormatContext
*s1
, AVPacket
*pkt
)
149 VideoData
*s
= s1
->priv_data
;
152 ByteIOContext f1
, *f
;
154 snprintf(filename
, sizeof(filename
), s
->path
, s
->img_number
);
158 if (url_fopen(f
, filename
, URL_RDONLY
) < 0)
166 av_new_packet(pkt
, s
->img_size
);
167 pkt
->stream_index
= 0;
171 ret
= pgm_read(s
, f
, pkt
->data
, pkt
->size
, 1);
174 ret
= pgm_read(s
, f
, pkt
->data
, pkt
->size
, 0);
177 ret
= yuv_read(s
, filename
, pkt
->data
, pkt
->size
);
189 return -EIO
; /* signal EOF */
196 static int sizes
[][2] = {
207 static int infer_size(int *width_ptr
, int *height_ptr
, int size
)
211 for(i
=0;i
<sizeof(sizes
)/sizeof(sizes
[0]);i
++) {
212 if ((sizes
[i
][0] * sizes
[i
][1]) == size
) {
213 *width_ptr
= sizes
[i
][0];
214 *height_ptr
= sizes
[i
][1];
221 static int img_read_header(AVFormatContext
*s1
, AVFormatParameters
*ap
)
227 ByteIOContext pb1
, *f
= &pb1
;
230 s
= malloc(sizeof(VideoData
));
237 st
= av_mallocz(sizeof(AVStream
));
244 strcpy(s
->path
, s1
->filename
);
248 if (s1
->format
->flags
& AVFMT_NOFILE
)
253 if (s1
->format
== &pgmpipe_format
||
254 s1
->format
== &pgmyuv_format
)
255 s
->img_fmt
= IMGFMT_PGMYUV
;
256 else if (s1
->format
== &pgm_format
)
257 s
->img_fmt
= IMGFMT_PGM
;
258 else if (s1
->format
== &imgyuv_format
)
259 s
->img_fmt
= IMGFMT_YUV
;
264 /* try to find the first image */
266 snprintf(buf
, sizeof(buf
), s
->path
, s
->img_number
);
267 if (url_fopen(f
, buf
, URL_RDONLY
) >= 0)
277 /* find the image size */
278 /* XXX: use generic file format guessing, as mpeg */
282 pnm_get(f
, buf1
, sizeof(buf1
));
283 pnm_get(f
, buf1
, sizeof(buf1
));
284 s
->width
= atoi(buf1
);
285 pnm_get(f
, buf1
, sizeof(buf1
));
287 if (s
->img_fmt
== IMGFMT_PGMYUV
)
292 (s
->width
% 2) != 0 ||
293 (s
->height
% 2) != 0) {
298 /* infer size by using the file size. */
305 img_size
= lseek((int)h
->priv_data
, 0, SEEK_END
);
306 if (infer_size(&s
->width
, &s
->height
, img_size
) < 0) {
316 url_fseek(f
, 0, SEEK_SET
);
319 s
->img_size
= (s
->width
* s
->height
* 3) / 2;
321 st
->codec
.codec_type
= CODEC_TYPE_VIDEO
;
322 st
->codec
.codec_id
= CODEC_ID_RAWVIDEO
;
323 st
->codec
.width
= s
->width
;
324 st
->codec
.height
= s
->height
;
325 st
->codec
.pix_fmt
= PIX_FMT_YUV420P
;
326 if (!ap
|| !ap
->frame_rate
)
327 st
->codec
.frame_rate
= 25 * FRAME_RATE_BASE
;
329 st
->codec
.frame_rate
= ap
->frame_rate
;
340 static int img_read_close(AVFormatContext
*s1
)
342 VideoData
*s
= s1
->priv_data
;
347 /******************************************************/
350 int pgm_save(AVPicture
*picture
, int width
, int height
, ByteIOContext
*pb
, int is_yuv
)
354 UINT8
*ptr
, *ptr1
, *ptr2
;
358 h
= (height
* 3) / 2;
359 snprintf(buf
, sizeof(buf
),
362 put_buffer(pb
, buf
, strlen(buf
));
364 ptr
= picture
->data
[0];
365 for(i
=0;i
<height
;i
++) {
366 put_buffer(pb
, ptr
, width
);
367 ptr
+= picture
->linesize
[0];
373 ptr1
= picture
->data
[1];
374 ptr2
= picture
->data
[2];
375 for(i
=0;i
<height
;i
++) {
376 put_buffer(pb
, ptr1
, width
);
377 put_buffer(pb
, ptr2
, width
);
378 ptr1
+= picture
->linesize
[1];
379 ptr2
+= picture
->linesize
[2];
382 put_flush_packet(pb
);
386 static int yuv_save(AVPicture
*picture
, int width
, int height
, const char *filename
)
388 ByteIOContext pb1
, *pb
= &pb1
;
389 char fname
[1024], *p
;
392 static char *ext
= "YUV";
394 strcpy(fname
, filename
);
395 p
= strrchr(fname
, '.');
396 if (!p
|| p
[1] != 'Y')
406 if (url_fopen(pb
, fname
, URL_WRONLY
) < 0)
409 ptr
= picture
->data
[i
];
410 for(j
=0;j
<height
;j
++) {
411 put_buffer(pb
, ptr
, width
);
412 ptr
+= picture
->linesize
[i
];
414 put_flush_packet(pb
);
420 static int img_write_header(AVFormatContext
*s
)
424 img
= av_mallocz(sizeof(VideoData
));
429 strcpy(img
->path
, s
->filename
);
432 if (s
->format
->flags
& AVFMT_NOFILE
)
437 if (s
->format
== &pgmpipe_format
||
438 s
->format
== &pgmyuv_format
)
439 img
->img_fmt
= IMGFMT_PGMYUV
;
440 else if (s
->format
== &pgm_format
)
441 img
->img_fmt
= IMGFMT_PGM
;
442 else if (s
->format
== &imgyuv_format
)
443 img
->img_fmt
= IMGFMT_YUV
;
452 static int img_write_packet(AVFormatContext
*s
, int stream_index
,
453 UINT8
*buf
, int size
)
455 VideoData
*img
= s
->priv_data
;
456 AVStream
*st
= s
->streams
[stream_index
];
457 ByteIOContext pb1
, *pb
;
459 int width
, height
, ret
, size1
;
462 width
= st
->codec
.width
;
463 height
= st
->codec
.height
;
464 size1
= (width
* height
* 3) / 2;
468 picture
.data
[0] = buf
;
469 picture
.data
[1] = picture
.data
[0] + width
* height
;
470 picture
.data
[2] = picture
.data
[1] + (width
* height
) / 4;
471 picture
.linesize
[0] = width
;
472 picture
.linesize
[1] = width
>> 1;
473 picture
.linesize
[2] = width
>> 1;
474 snprintf(filename
, sizeof(filename
), img
->path
, img
->img_number
);
478 if (url_fopen(pb
, filename
, URL_WRONLY
) < 0)
483 switch(img
->img_fmt
) {
485 ret
= pgm_save(&picture
, width
, height
, pb
, 1);
488 ret
= pgm_save(&picture
, width
, height
, pb
, 0);
491 ret
= yuv_save(&picture
, width
, height
, filename
);
502 static int img_write_trailer(AVFormatContext
*s
)
504 VideoData
*img
= s
->priv_data
;
509 AVFormat pgm_format
= {
527 AVFormat pgmyuv_format
= {
529 "pgm with YUV content image format",
545 AVFormat imgyuv_format
= {
563 AVFormat pgmpipe_format
= {