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
22 extern AVInputFormat pgm_iformat;
23 extern AVOutputFormat pgm_oformat;
24 extern AVInputFormat pgmyuv_iformat;
25 extern AVOutputFormat pgmyuv_oformat;
26 extern AVInputFormat ppm_iformat;
27 extern AVOutputFormat ppm_oformat;
28 extern AVInputFormat imgyuv_iformat;
29 extern AVOutputFormat imgyuv_oformat;
30 extern AVInputFormat pgmpipe_iformat;
31 extern AVOutputFormat pgmpipe_oformat;
32 extern AVInputFormat pgmyuvpipe_iformat;
33 extern AVOutputFormat pgmyuvpipe_oformat;
34 extern AVInputFormat ppmpipe_iformat;
35 extern AVOutputFormat ppmpipe_oformat;
36 extern AVOutputFormat yuv4mpegpipe_oformat;
39 #define IMGFMT_PGMYUV 2
42 #define IMGFMT_YUV4MPEG 5
44 #define Y4M_MAGIC "YUV4MPEG2"
45 #define Y4M_FRAME_MAGIC "FRAME"
46 #define Y4M_LINE_MAX 256
59 int emulate_frame_rate;
61 static inline int pnm_space(int c)
63 return (c==' ' || c=='\n' || c=='\r' || c=='\t');
66 static void pnm_get(ByteIOContext *f, char *str, int buf_size)
79 } while (pnm_space(c));
85 if ((s - str) < buf_size - 1)
88 } while (!pnm_space(c));
92 static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
101 pnm_get(f, buf1, sizeof(buf1));
102 if (strcmp(buf1, "P5")) {
105 pnm_get(f, buf1, sizeof(buf1));
106 pnm_get(f, buf1, sizeof(buf1));
107 pnm_get(f, buf1, sizeof(buf1));
110 picture[1] = buf + width * height;
111 picture[2] = buf + width * height + (width * height / 4);
112 get_buffer(f, picture[0], width * height);
117 for(i=0;i<height;i++) {
118 get_buffer(f, picture[1] + i * width, width);
119 get_buffer(f, picture[2] + i * width, width);
122 for(i=0;i<height;i++) {
123 memset(picture[1] + i * width, 128, width);
124 memset(picture[2] + i * width, 128, width);
130 static int ppm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size)
139 pnm_get(f, buf1, sizeof(buf1));
140 if (strcmp(buf1, "P6")) {
144 pnm_get(f, buf1, sizeof(buf1));
145 pnm_get(f, buf1, sizeof(buf1));
146 pnm_get(f, buf1, sizeof(buf1));
149 get_buffer(f, picture[0], width * height*3);
155 static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
157 ByteIOContext pb1, *pb = &pb1;
158 char fname[1024], *p;
161 size = s->width * s->height;
163 strcpy(fname, filename);
164 p = strrchr(fname, '.');
165 if (!p || p[1] != 'Y')
168 if (url_fopen(pb, fname, URL_RDONLY) < 0)
171 get_buffer(pb, buf, size);
175 if (url_fopen(pb, fname, URL_RDONLY) < 0)
178 get_buffer(pb, buf + size, size / 4);
182 if (url_fopen(pb, fname, URL_RDONLY) < 0)
185 get_buffer(pb, buf + size + (size / 4), size / 4);
190 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
192 VideoData *s = s1->priv_data;
195 ByteIOContext f1, *f;
196 static INT64 first_frame;
198 if (emulate_frame_rate) {
200 first_frame = av_gettime();
205 nowus = av_gettime() - first_frame;
207 pts = ((INT64)s->img_number * FRAME_RATE_BASE * 1000000) / (s1->streams[0]->codec.frame_rate);
215 This if-statement destroys pipes - I do not see why it is necessary
216 if (get_frame_filename(filename, sizeof(filename),
217 s->path, s->img_number) < 0)
220 get_frame_filename(filename, sizeof(filename),
221 s->path, s->img_number);
224 if (url_fopen(f, filename, URL_RDONLY) < 0)
232 av_new_packet(pkt, s->img_size);
233 pkt->stream_index = 0;
237 ret = pgm_read(s, f, pkt->data, pkt->size, 1);
240 ret = pgm_read(s, f, pkt->data, pkt->size, 0);
243 ret = yuv_read(s, filename, pkt->data, pkt->size);
246 ret = ppm_read(s, f, pkt->data, pkt->size);
258 return -EIO; /* signal EOF */
260 pkt->pts = ((INT64)s->img_number * s1->pts_den * FRAME_RATE_BASE) / (s1->streams[0]->codec.frame_rate * s1->pts_num);
266 static int sizes[][2] = {
278 static int infer_size(int *width_ptr, int *height_ptr, int size)
282 for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
283 if ((sizes[i][0] * sizes[i][1]) == size) {
284 *width_ptr = sizes[i][0];
285 *height_ptr = sizes[i][1];
292 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
294 VideoData *s = s1->priv_data;
298 ByteIOContext pb1, *f = &pb1;
301 st = av_new_stream(s1, 0);
307 strcpy(s->path, s1->filename);
311 if (s1->iformat->flags & AVFMT_NOFILE)
316 if (s1->iformat == &pgmyuvpipe_iformat ||
317 s1->iformat == &pgmyuv_iformat)
318 s->img_fmt = IMGFMT_PGMYUV;
319 else if (s1->iformat == &pgmpipe_iformat ||
320 s1->iformat == &pgm_iformat)
321 s->img_fmt = IMGFMT_PGM;
322 else if (s1->iformat == &imgyuv_iformat)
323 s->img_fmt = IMGFMT_YUV;
324 else if (s1->iformat == &ppmpipe_iformat ||
325 s1->iformat == &ppm_iformat)
326 s->img_fmt = IMGFMT_PPM;
331 /* try to find the first image */
333 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
335 if (url_fopen(f, buf, URL_RDONLY) >= 0)
345 /* find the image size */
346 /* XXX: use generic file format guessing, as mpeg */
351 pnm_get(f, buf1, sizeof(buf1));
352 pnm_get(f, buf1, sizeof(buf1));
353 s->width = atoi(buf1);
354 pnm_get(f, buf1, sizeof(buf1));
356 if (s->img_fmt == IMGFMT_PGMYUV)
361 (s->width % 2) != 0 ||
362 (s->height % 2) != 0) {
367 /* infer size by using the file size. */
374 img_size = url_seek(h, 0, SEEK_END);
375 if (infer_size(&s->width, &s->height, img_size) < 0) {
386 url_fseek(f, 0, SEEK_SET);
390 st->codec.codec_type = CODEC_TYPE_VIDEO;
391 st->codec.codec_id = CODEC_ID_RAWVIDEO;
392 st->codec.width = s->width;
393 st->codec.height = s->height;
394 if (s->img_fmt == IMGFMT_PPM) {
395 st->codec.pix_fmt = PIX_FMT_RGB24;
396 s->img_size = (s->width * s->height * 3);
398 st->codec.pix_fmt = PIX_FMT_YUV420P;
399 s->img_size = (s->width * s->height * 3) / 2;
401 if (!ap || !ap->frame_rate)
402 st->codec.frame_rate = 25 * FRAME_RATE_BASE;
404 st->codec.frame_rate = ap->frame_rate;
415 static int img_read_close(AVFormatContext *s1)
420 /******************************************************/
423 static int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv)
427 UINT8 *ptr, *ptr1, *ptr2;
431 h = (height * 3) / 2;
432 snprintf(buf, sizeof(buf),
435 put_buffer(pb, buf, strlen(buf));
437 ptr = picture->data[0];
438 for(i=0;i<height;i++) {
439 put_buffer(pb, ptr, width);
440 ptr += picture->linesize[0];
446 ptr1 = picture->data[1];
447 ptr2 = picture->data[2];
448 for(i=0;i<height;i++) {
449 put_buffer(pb, ptr1, width);
450 put_buffer(pb, ptr2, width);
451 ptr1 += picture->linesize[1];
452 ptr2 += picture->linesize[2];
455 put_flush_packet(pb);
459 static int ppm_save(AVPicture *picture, int width, int height, ByteIOContext *pb)
465 snprintf(buf, sizeof(buf),
468 put_buffer(pb, buf, strlen(buf));
470 ptr = picture->data[0];
471 for(i=0;i<height;i++) {
472 put_buffer(pb, ptr, width * 3);
473 ptr += picture->linesize[0];
476 put_flush_packet(pb);
480 static int yuv_save(AVPicture *picture, int width, int height, const char *filename)
482 ByteIOContext pb1, *pb = &pb1;
483 char fname[1024], *p;
486 static char *ext = "YUV";
488 strcpy(fname, filename);
489 p = strrchr(fname, '.');
490 if (!p || p[1] != 'Y')
500 if (url_fopen(pb, fname, URL_WRONLY) < 0)
503 ptr = picture->data[i];
504 for(j=0;j<height;j++) {
505 put_buffer(pb, ptr, width);
506 ptr += picture->linesize[i];
508 put_flush_packet(pb);
514 static int yuv4mpeg_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int need_stream_header,
515 int is_yuv, int raten, int rated, int aspectn, int aspectd)
518 char buf[Y4M_LINE_MAX+1], buf1[20];
519 UINT8 *ptr, *ptr1, *ptr2;
521 /* construct stream header, if this is the first frame */
522 if(need_stream_header) {
523 n = snprintf(buf, sizeof(buf), "%s W%d H%d F%d:%d I%s A%d:%d\n",
528 "p", /* ffmpeg seems to only output progressive video */
531 fprintf(stderr, "Error. YUV4MPEG stream header write failed.\n");
533 fprintf(stderr, "YUV4MPEG stream header written. FPS is %d\n", raten);
534 put_buffer(pb, buf, strlen(buf));
538 /* construct frame header */
539 m = snprintf(buf1, sizeof(buf1), "%s \n", Y4M_FRAME_MAGIC);
541 fprintf(stderr, "Error. YUV4MPEG frame header write failed.\n");
543 /* fprintf(stderr, "YUV4MPEG frame header written.\n"); */
544 put_buffer(pb, buf1, strlen(buf1));
547 ptr = picture->data[0];
548 for(i=0;i<height;i++) {
549 put_buffer(pb, ptr, width);
550 ptr += picture->linesize[0];
556 ptr1 = picture->data[1];
557 ptr2 = picture->data[2];
558 for(i=0;i<height;i++) { /* Cb */
559 put_buffer(pb, ptr1, width);
560 ptr1 += picture->linesize[1];
562 for(i=0;i<height;i++) { /* Cr */
563 put_buffer(pb, ptr2, width);
564 ptr2 += picture->linesize[2];
567 put_flush_packet(pb);
571 static int img_write_header(AVFormatContext *s)
573 VideoData *img = s->priv_data;
576 strcpy(img->path, s->filename);
579 if (s->oformat->flags & AVFMT_NOFILE)
584 if (s->oformat == &pgmyuvpipe_oformat ||
585 s->oformat == &pgmyuv_oformat) {
586 img->img_fmt = IMGFMT_PGMYUV;
587 } else if (s->oformat == &pgmpipe_oformat ||
588 s->oformat == &pgm_oformat) {
589 img->img_fmt = IMGFMT_PGM;
590 } else if (s->oformat == &imgyuv_oformat) {
591 img->img_fmt = IMGFMT_YUV;
592 } else if (s->oformat == &ppmpipe_oformat ||
593 s->oformat == &ppm_oformat) {
594 img->img_fmt = IMGFMT_PPM;
595 } else if (s->oformat == &yuv4mpegpipe_oformat) {
596 img->img_fmt = IMGFMT_YUV4MPEG;
597 img->header_written = 0;
607 static int img_write_packet(AVFormatContext *s, int stream_index,
608 UINT8 *buf, int size, int force_pts)
610 VideoData *img = s->priv_data;
611 AVStream *st = s->streams[stream_index];
612 ByteIOContext pb1, *pb;
614 int width, height, need_stream_header, ret, size1, raten, rated, aspectn, aspectd, fps, fps1;
617 width = st->codec.width;
618 height = st->codec.height;
620 if (img->img_number == 1) {
621 need_stream_header = 1;
623 need_stream_header = 0;
626 fps = st->codec.frame_rate;
627 fps1 = (((float)fps / FRAME_RATE_BASE) * 1000);
629 /* Sorry about this messy code, but mpeg2enc is very picky about
630 * the framerates it accepts. */
633 raten = 24000; /* turn the framerate into a ratio */
665 raten = fps1; /* this setting should work, but often doesn't */
671 aspectd = 1; /* ffmpeg always uses a 1:1 aspect ratio */
673 switch(st->codec.pix_fmt) {
674 case PIX_FMT_YUV420P:
675 size1 = (width * height * 3) / 2;
679 picture.data[0] = buf;
680 picture.data[1] = picture.data[0] + width * height;
681 picture.data[2] = picture.data[1] + (width * height) / 4;
682 picture.linesize[0] = width;
683 picture.linesize[1] = width >> 1;
684 picture.linesize[2] = width >> 1;
687 size1 = (width * height * 3);
690 picture.data[0] = buf;
691 picture.linesize[0] = width * 3;
698 This if-statement destroys pipes - I do not see why it is necessary
699 if (get_frame_filename(filename, sizeof(filename),
700 img->path, img->img_number) < 0)
703 get_frame_filename(filename, sizeof(filename),
704 img->path, img->img_number);
707 if (url_fopen(pb, filename, URL_WRONLY) < 0)
712 switch(img->img_fmt) {
714 ret = pgm_save(&picture, width, height, pb, 1);
717 ret = pgm_save(&picture, width, height, pb, 0);
720 ret = yuv_save(&picture, width, height, filename);
723 ret = ppm_save(&picture, width, height, pb);
725 case IMGFMT_YUV4MPEG:
726 ret = yuv4mpeg_save(&picture, width, height, pb,
727 need_stream_header, 1, raten, rated, aspectn, aspectd);
738 static int img_write_trailer(AVFormatContext *s)
743 static AVInputFormat pgm_iformat = {
752 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
756 static AVOutputFormat pgm_oformat = {
767 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
770 static AVInputFormat pgmyuv_iformat = {
772 "pgm with YUV content image format",
779 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
782 static AVOutputFormat pgmyuv_oformat = {
784 "pgm with YUV content image format",
793 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
796 static AVInputFormat ppm_iformat = {
805 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
809 static AVOutputFormat ppm_oformat = {
820 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
823 static AVInputFormat imgyuv_iformat = {
832 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
836 static AVOutputFormat imgyuv_oformat = {
847 AVFMT_NOFILE | AVFMT_NEEDNUMBER,
850 static AVInputFormat pgmpipe_iformat = {
861 static AVOutputFormat pgmpipe_oformat = {
874 static AVInputFormat pgmyuvpipe_iformat = {
876 "PGM YUV pipe format",
885 static AVOutputFormat pgmyuvpipe_oformat = {
887 "PGM YUV pipe format",
898 static AVInputFormat ppmpipe_iformat = {
907 .flags = AVFMT_RGB24,
910 static AVOutputFormat ppmpipe_oformat = {
921 .flags = AVFMT_RGB24,
925 static AVOutputFormat yuv4mpegpipe_oformat = {
927 "YUV4MPEG pipe format",
941 av_register_input_format(&pgm_iformat);
942 av_register_output_format(&pgm_oformat);
944 av_register_input_format(&pgmyuv_iformat);
945 av_register_output_format(&pgmyuv_oformat);
947 av_register_input_format(&ppm_iformat);
948 av_register_output_format(&ppm_oformat);
950 av_register_input_format(&imgyuv_iformat);
951 av_register_output_format(&imgyuv_oformat);
953 av_register_input_format(&pgmpipe_iformat);
954 av_register_output_format(&pgmpipe_oformat);
956 av_register_input_format(&pgmyuvpipe_iformat);
957 av_register_output_format(&pgmyuvpipe_oformat);
959 av_register_input_format(&ppmpipe_iformat);
960 av_register_output_format(&ppmpipe_oformat);
962 av_register_output_format(&yuv4mpegpipe_oformat);