Set the pkt->pts field correctly so that frame rate reduction has a chance
[ffmpeg.git] / libav / img.c
1 /*
2  * Image format
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
4  *
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.
9  *
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.
14  *
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
18  */
19 #include "avformat.h"
20
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;
35 extern AVOutputFormat yuv4mpegpipe_oformat;
36
37 #define IMGFMT_YUV     1
38 #define IMGFMT_PGMYUV  2
39 #define IMGFMT_PGM     3
40 #define IMGFMT_PPM     4
41 #define IMGFMT_YUV4MPEG     5
42
43 #define Y4M_MAGIC "YUV4MPEG2"
44 #define Y4M_FRAME_MAGIC "FRAME"
45 #define Y4M_LINE_MAX 256
46
47 typedef struct {
48     int width;
49     int height;
50     int img_number;
51     int img_size;
52     int img_fmt;
53     int is_pipe;
54     int header_written;
55     char path[1024];
56 } VideoData;
57
58 static inline int pnm_space(int c)  
59 {
60     return (c==' ' || c=='\n' || c=='\r' || c=='\t');
61 }
62
63 static void pnm_get(ByteIOContext *f, char *str, int buf_size) 
64 {
65     char *s;
66     int c;
67     
68     do  {
69         c=get_byte(f);
70         if (c=='#')  {
71             do  {
72                 c=get_byte(f);
73             } while (c!='\n');
74             c=get_byte(f);
75         }
76     } while (pnm_space(c));
77     
78     s=str;
79     do  {
80         if (url_feof(f))
81             break;
82         if ((s - str)  < buf_size - 1)
83             *s++=c;
84         c=get_byte(f);
85     } while (!pnm_space(c));
86     *s = '\0';
87 }
88
89 static int pgm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size, int is_yuv)
90 {
91     int width, height, i;
92     char buf1[32];
93     UINT8 *picture[3];
94
95     width = s->width;
96     height = s->height;
97
98     pnm_get(f, buf1, sizeof(buf1));
99     if (strcmp(buf1, "P5")) {
100         return -EIO;
101     }
102     pnm_get(f, buf1, sizeof(buf1));
103     pnm_get(f, buf1, sizeof(buf1));
104     pnm_get(f, buf1, sizeof(buf1));
105     
106     picture[0] = buf;
107     picture[1] = buf + width * height;
108     picture[2] = buf + width * height + (width * height / 4);
109     get_buffer(f, picture[0], width * height);
110     
111     height>>=1;
112     width>>=1;
113     if (is_yuv) {
114         for(i=0;i<height;i++) {
115             get_buffer(f, picture[1] + i * width, width);
116             get_buffer(f, picture[2] + i * width, width);
117         }
118     } else {
119         for(i=0;i<height;i++) {
120             memset(picture[1] + i * width, 128, width);
121             memset(picture[2] + i * width, 128, width);
122         }
123     }
124     return 0;
125 }
126
127 static int ppm_read(VideoData *s, ByteIOContext *f, UINT8 *buf, int size)
128 {
129     int width, height;
130     char buf1[32];
131     UINT8 *picture[3];
132
133     width = s->width;
134     height = s->height;
135
136     pnm_get(f, buf1, sizeof(buf1));
137     if (strcmp(buf1, "P6")) {
138         return -EIO;
139     }
140     
141     pnm_get(f, buf1, sizeof(buf1));
142     pnm_get(f, buf1, sizeof(buf1));
143     pnm_get(f, buf1, sizeof(buf1));
144     
145     picture[0] = buf;
146     get_buffer(f, picture[0], width * height*3);
147     
148     return 0;
149
150 }
151
152 static int yuv_read(VideoData *s, const char *filename, UINT8 *buf, int size1)
153 {
154     ByteIOContext pb1, *pb = &pb1;
155     char fname[1024], *p;
156     int size;
157
158     size = s->width * s->height;
159     
160     strcpy(fname, filename);
161     p = strrchr(fname, '.');
162     if (!p || p[1] != 'Y')
163         return -EIO;
164
165     if (url_fopen(pb, fname, URL_RDONLY) < 0)
166         return -EIO;
167     
168     get_buffer(pb, buf, size);
169     url_fclose(pb);
170     
171     p[1] = 'U';
172     if (url_fopen(pb, fname, URL_RDONLY) < 0)
173         return -EIO;
174
175     get_buffer(pb, buf + size, size / 4);
176     url_fclose(pb);
177     
178     p[1] = 'V';
179     if (url_fopen(pb, fname, URL_RDONLY) < 0)
180         return -EIO;
181
182     get_buffer(pb, buf + size + (size / 4), size / 4);
183     url_fclose(pb);
184     return 0;
185 }
186
187 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
188 {
189     VideoData *s = s1->priv_data;
190     char filename[1024];
191     int ret;
192     ByteIOContext f1, *f;
193
194 /*
195     This if-statement destroys pipes - I do not see why it is necessary
196     if (get_frame_filename(filename, sizeof(filename),
197                            s->path, s->img_number) < 0)
198         return -EIO;
199 */
200     get_frame_filename(filename, sizeof(filename),
201                        s->path, s->img_number);
202     if (!s->is_pipe) {
203         f = &f1;
204         if (url_fopen(f, filename, URL_RDONLY) < 0)
205             return -EIO;
206     } else {
207         f = &s1->pb;
208         if (url_feof(f))
209             return -EIO;
210     }
211
212     av_new_packet(pkt, s->img_size);
213     pkt->stream_index = 0;
214
215     switch(s->img_fmt) {
216     case IMGFMT_PGMYUV:
217         ret = pgm_read(s, f, pkt->data, pkt->size, 1);
218         break;
219     case IMGFMT_PGM:
220         ret = pgm_read(s, f, pkt->data, pkt->size, 0);
221         break;
222     case IMGFMT_YUV:
223         ret = yuv_read(s, filename, pkt->data, pkt->size);
224         break;
225     case IMGFMT_PPM:
226         ret = ppm_read(s, f, pkt->data, pkt->size);
227         break;
228     default:
229         return -EIO;
230     }
231     
232     if (!s->is_pipe) {
233         url_fclose(f);
234     }
235
236     if (ret < 0) {
237         av_free_packet(pkt);
238         return -EIO; /* signal EOF */
239     } else {
240         pkt->pts = ((INT64)s->img_number * s1->pts_den * FRAME_RATE_BASE) / (s1->streams[0]->codec.frame_rate * s1->pts_num);
241         s->img_number++;
242         return 0;
243     }
244 }
245
246 static int sizes[][2] = {
247     { 640, 480 },
248     { 720, 480 },
249     { 720, 576 },
250     { 352, 288 },
251     { 352, 240 },
252     { 160, 128 },
253     { 512, 384 },
254     { 640, 352 },
255     { 640, 240 },
256 };
257
258 static int infer_size(int *width_ptr, int *height_ptr, int size)
259 {
260     int i;
261
262     for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
263         if ((sizes[i][0] * sizes[i][1]) == size) {
264             *width_ptr = sizes[i][0];
265             *height_ptr = sizes[i][1];
266             return 0;
267         }
268     }
269     return -1;
270 }
271
272 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
273 {
274     VideoData *s = s1->priv_data;
275     int i, h;
276     char buf[1024];
277     char buf1[32];
278     ByteIOContext pb1, *f = &pb1;
279     AVStream *st;
280
281     st = av_new_stream(s1, 0);
282     if (!st) {
283         av_free(s);
284         return -ENOMEM;
285     }
286
287     strcpy(s->path, s1->filename);
288     s->img_number = 0;
289
290     /* find format */
291     if (s1->iformat->flags & AVFMT_NOFILE)
292         s->is_pipe = 0;
293     else
294         s->is_pipe = 1;
295         
296     if (s1->iformat == &pgmyuvpipe_iformat ||
297         s1->iformat == &pgmyuv_iformat)
298         s->img_fmt = IMGFMT_PGMYUV;
299     else if (s1->iformat == &pgmpipe_iformat ||
300              s1->iformat == &pgm_iformat)
301         s->img_fmt = IMGFMT_PGM;
302     else if (s1->iformat == &imgyuv_iformat)
303         s->img_fmt = IMGFMT_YUV;
304     else if (s1->iformat == &ppmpipe_iformat ||
305              s1->iformat == &ppm_iformat)
306         s->img_fmt = IMGFMT_PPM;
307     else
308         goto fail;
309
310     if (!s->is_pipe) {
311         /* try to find the first image */
312         for(i=0;i<5;i++) {
313             if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
314                 goto fail;
315             if (url_fopen(f, buf, URL_RDONLY) >= 0)
316                 break;
317             s->img_number++;
318         }
319         if (i == 5)
320             goto fail;
321     } else {
322         f = &s1->pb;
323     }
324     
325     /* find the image size */
326     /* XXX: use generic file format guessing, as mpeg */
327     switch(s->img_fmt) {
328     case IMGFMT_PGM:
329     case IMGFMT_PGMYUV:
330     case IMGFMT_PPM:
331         pnm_get(f, buf1, sizeof(buf1));
332         pnm_get(f, buf1, sizeof(buf1));
333         s->width = atoi(buf1);
334         pnm_get(f, buf1, sizeof(buf1));
335         h = atoi(buf1);
336         if (s->img_fmt == IMGFMT_PGMYUV)
337             h = (h * 2) / 3;
338         s->height = h;
339         if (s->width <= 0 ||
340             s->height <= 0 ||
341             (s->width % 2) != 0 ||
342             (s->height % 2) != 0) {
343             goto fail1;
344         }
345         break;
346     case IMGFMT_YUV:
347         /* infer size by using the file size. */
348         {
349             int img_size;
350             URLContext *h;
351
352             /* XXX: hack hack */
353             h = url_fileno(f);
354             img_size = url_seek(h, 0, SEEK_END);
355             if (infer_size(&s->width, &s->height, img_size) < 0) {
356                 goto fail1;
357             }
358         }
359         break;
360     }
361     
362
363     if (!s->is_pipe) {
364         url_fclose(f);
365     } else {
366         url_fseek(f, 0, SEEK_SET);
367     }
368     
369
370     st->codec.codec_type = CODEC_TYPE_VIDEO;
371     st->codec.codec_id = CODEC_ID_RAWVIDEO;
372     st->codec.width = s->width;
373     st->codec.height = s->height;
374     if (s->img_fmt == IMGFMT_PPM) {
375         st->codec.pix_fmt = PIX_FMT_RGB24;
376         s->img_size = (s->width * s->height * 3);
377     } else {
378         st->codec.pix_fmt = PIX_FMT_YUV420P;
379         s->img_size = (s->width * s->height * 3) / 2;
380     }
381     if (!ap || !ap->frame_rate)
382         st->codec.frame_rate = 25 * FRAME_RATE_BASE;
383     else
384         st->codec.frame_rate = ap->frame_rate;
385     
386     return 0;
387  fail1:
388     if (!s->is_pipe)
389         url_fclose(f);
390  fail:
391     av_free(s);
392     return -EIO;
393 }
394
395 static int img_read_close(AVFormatContext *s1)
396 {
397     return 0;
398 }
399
400 /******************************************************/
401 /* image output */
402
403 static int pgm_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int is_yuv) 
404 {
405     int i, h;
406     char buf[100];
407     UINT8 *ptr, *ptr1, *ptr2;
408
409     h = height;
410     if (is_yuv)
411         h = (height * 3) / 2;
412     snprintf(buf, sizeof(buf), 
413              "P5\n%d %d\n%d\n",
414              width, h, 255);
415     put_buffer(pb, buf, strlen(buf));
416     
417     ptr = picture->data[0];
418     for(i=0;i<height;i++) {
419         put_buffer(pb, ptr, width);
420         ptr += picture->linesize[0];
421     }
422
423     if (is_yuv) {
424         height >>= 1;
425         width >>= 1;
426         ptr1 = picture->data[1];
427         ptr2 = picture->data[2];
428         for(i=0;i<height;i++) {
429             put_buffer(pb, ptr1, width);
430             put_buffer(pb, ptr2, width);
431             ptr1 += picture->linesize[1];
432             ptr2 += picture->linesize[2];
433         }
434     }
435     put_flush_packet(pb);
436     return 0;
437 }
438
439 static int ppm_save(AVPicture *picture, int width, int height, ByteIOContext *pb) 
440 {
441     int i;
442     char buf[100];
443     UINT8 *ptr;
444
445     snprintf(buf, sizeof(buf), 
446              "P6\n%d %d\n%d\n",
447              width, height, 255);
448     put_buffer(pb, buf, strlen(buf));
449     
450     ptr = picture->data[0];
451     for(i=0;i<height;i++) {
452         put_buffer(pb, ptr, width * 3);
453         ptr += picture->linesize[0];
454     }
455
456     put_flush_packet(pb);
457     return 0;
458 }
459
460 static int yuv_save(AVPicture *picture, int width, int height, const char *filename)
461 {
462     ByteIOContext pb1, *pb = &pb1;
463     char fname[1024], *p;
464     int i, j;
465     UINT8 *ptr;
466     static char *ext = "YUV";
467
468     strcpy(fname, filename);
469     p = strrchr(fname, '.');
470     if (!p || p[1] != 'Y')
471         return -EIO;
472
473     for(i=0;i<3;i++) {
474         if (i == 1) {
475             width >>= 1;
476             height >>= 1;
477         }
478
479         p[1] = ext[i];
480         if (url_fopen(pb, fname, URL_WRONLY) < 0)
481             return -EIO;
482     
483         ptr = picture->data[i];
484         for(j=0;j<height;j++) {
485             put_buffer(pb, ptr, width);
486             ptr += picture->linesize[i];
487         }
488         put_flush_packet(pb);
489         url_fclose(pb);
490     }
491     return 0;
492 }
493
494 static int yuv4mpeg_save(AVPicture *picture, int width, int height, ByteIOContext *pb, int need_stream_header, 
495                         int is_yuv, int raten, int rated, int aspectn, int aspectd) 
496 {
497     int i, n, m;
498     char buf[Y4M_LINE_MAX+1], buf1[20];
499     UINT8 *ptr, *ptr1, *ptr2;
500     
501     /* construct stream header, if this is the first frame */
502     if(need_stream_header) {
503         n = snprintf(buf, sizeof(buf), "%s W%d H%d F%d:%d I%s A%d:%d\n",
504                 Y4M_MAGIC,
505                 width,
506                 height,
507                 raten, rated,
508                 "p",                    /* ffmpeg seems to only output progressive video */
509                 aspectn, aspectd);
510         if (n < 0) {
511             fprintf(stderr, "Error. YUV4MPEG stream header write failed.\n");
512         } else {
513             fprintf(stderr, "YUV4MPEG stream header written. FPS is %d\n", raten);
514             put_buffer(pb, buf, strlen(buf));
515         }
516     }
517     
518     /* construct frame header */
519     m = snprintf(buf1, sizeof(buf1), "%s \n", Y4M_FRAME_MAGIC);
520     if (m < 0) {
521         fprintf(stderr, "Error. YUV4MPEG frame header write failed.\n");
522     } else {
523         /* fprintf(stderr, "YUV4MPEG frame header written.\n"); */
524         put_buffer(pb, buf1, strlen(buf1));
525     }
526     
527     ptr = picture->data[0];
528     for(i=0;i<height;i++) {
529         put_buffer(pb, ptr, width);
530         ptr += picture->linesize[0];
531     }
532
533     if (is_yuv) {
534         height >>= 1;
535         width >>= 1;
536         ptr1 = picture->data[1];
537         ptr2 = picture->data[2];
538         for(i=0;i<height;i++) {         /* Cb */
539             put_buffer(pb, ptr1, width);
540             ptr1 += picture->linesize[1];
541         }
542          for(i=0;i<height;i++) {        /* Cr */
543             put_buffer(pb, ptr2, width);
544             ptr2 += picture->linesize[2];
545          }
546     }
547     put_flush_packet(pb);
548     return 0;
549 }
550
551 static int img_write_header(AVFormatContext *s)
552 {
553     VideoData *img = s->priv_data;
554
555     img->img_number = 1;
556     strcpy(img->path, s->filename);
557
558     /* find format */
559     if (s->oformat->flags & AVFMT_NOFILE)
560         img->is_pipe = 0;
561     else
562         img->is_pipe = 1;
563         
564     if (s->oformat == &pgmyuvpipe_oformat ||
565         s->oformat == &pgmyuv_oformat) {
566         img->img_fmt = IMGFMT_PGMYUV;
567     } else if (s->oformat == &pgmpipe_oformat ||
568                s->oformat == &pgm_oformat) {
569         img->img_fmt = IMGFMT_PGM;
570     } else if (s->oformat == &imgyuv_oformat) {
571         img->img_fmt = IMGFMT_YUV;
572     } else if (s->oformat == &ppmpipe_oformat ||
573                s->oformat == &ppm_oformat) {
574         img->img_fmt = IMGFMT_PPM;
575     } else if (s->oformat == &yuv4mpegpipe_oformat) {
576         img->img_fmt = IMGFMT_YUV4MPEG;
577         img->header_written = 0;    
578     } else {
579         goto fail;
580     }
581     return 0;
582  fail:
583     av_free(img);
584     return -EIO;
585 }
586
587 static int img_write_packet(AVFormatContext *s, int stream_index,
588                             UINT8 *buf, int size, int force_pts)
589 {
590     VideoData *img = s->priv_data;
591     AVStream *st = s->streams[stream_index];
592     ByteIOContext pb1, *pb;
593     AVPicture picture;
594     int width, height, need_stream_header, ret, size1, raten, rated, aspectn, aspectd, fps, fps1;
595     char filename[1024];
596
597     width = st->codec.width;
598     height = st->codec.height;
599     
600     if (img->img_number == 1) {
601         need_stream_header = 1;
602     } else {
603         need_stream_header = 0;
604     }
605     
606     fps = st->codec.frame_rate;
607     fps1 = (((float)fps / FRAME_RATE_BASE) * 1000);
608    
609    /* Sorry about this messy code, but mpeg2enc is very picky about
610     * the framerates it accepts. */
611     switch(fps1) {
612     case 23976:
613         raten = 24000; /* turn the framerate into a ratio */
614         rated = 1001;
615         break;
616     case 29970:
617         raten = 30000;
618         rated = 1001;
619         break;
620     case 25000:
621         raten = 25;
622         rated = 1;
623         break;
624     case 30000:
625         raten = 30;
626         rated = 1;
627         break;
628     case 24000:
629         raten = 24;
630         rated = 1;
631         break;
632     case 50000:
633         raten = 50;
634         rated = 1;
635         break;
636     case 59940:
637         raten = 60000;
638         rated = 1001;
639         break;
640     case 60000:
641         raten = 60;
642         rated = 1;
643         break;
644     default:
645         raten = fps1; /* this setting should work, but often doesn't */
646         rated = 1000;
647         break;
648     }
649     
650     aspectn = 1;
651     aspectd = 1;        /* ffmpeg always uses a 1:1 aspect ratio */
652
653     switch(st->codec.pix_fmt) {
654     case PIX_FMT_YUV420P:
655         size1 = (width * height * 3) / 2;
656         if (size != size1)
657             return -EIO;
658         
659         picture.data[0] = buf;
660         picture.data[1] = picture.data[0] + width * height;
661         picture.data[2] = picture.data[1] + (width * height) / 4;
662         picture.linesize[0] = width;
663         picture.linesize[1] = width >> 1; 
664         picture.linesize[2] = width >> 1;
665         break;
666     case PIX_FMT_RGB24:
667         size1 = (width * height * 3);
668         if (size != size1)
669             return -EIO;
670         picture.data[0] = buf;
671         picture.linesize[0] = width * 3;
672         break;
673     default:
674         return -EIO;
675     }
676     
677 /*
678     This if-statement destroys pipes - I do not see why it is necessary
679     if (get_frame_filename(filename, sizeof(filename), 
680                            img->path, img->img_number) < 0)
681         return -EIO;
682 */
683     get_frame_filename(filename, sizeof(filename), 
684                        img->path, img->img_number);
685     if (!img->is_pipe) {
686         pb = &pb1;
687         if (url_fopen(pb, filename, URL_WRONLY) < 0)
688             return -EIO;
689     } else {
690         pb = &s->pb;
691     }
692     switch(img->img_fmt) {
693     case IMGFMT_PGMYUV:
694         ret = pgm_save(&picture, width, height, pb, 1);
695         break;
696     case IMGFMT_PGM:
697         ret = pgm_save(&picture, width, height, pb, 0);
698         break;
699     case IMGFMT_YUV:
700         ret = yuv_save(&picture, width, height, filename);
701         break;
702     case IMGFMT_PPM:
703         ret = ppm_save(&picture, width, height, pb);
704         break;
705     case IMGFMT_YUV4MPEG:
706          ret = yuv4mpeg_save(&picture, width, height, pb,
707          need_stream_header, 1, raten, rated, aspectn, aspectd);
708         break;
709     }
710     if (!img->is_pipe) {
711         url_fclose(pb);
712     }
713
714     img->img_number++;
715     return 0;
716 }
717
718 static int img_write_trailer(AVFormatContext *s)
719 {
720     return 0;
721 }
722
723 static AVInputFormat pgm_iformat = {
724     "pgm",
725     "pgm image format",
726     sizeof(VideoData),
727     NULL,
728     img_read_header,
729     img_read_packet,
730     img_read_close,
731     NULL,
732     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
733     .extensions = "pgm",
734 };
735
736 static AVOutputFormat pgm_oformat = {
737     "pgm",
738     "pgm image format",
739     "",
740     "pgm",
741     sizeof(VideoData),
742     CODEC_ID_NONE,
743     CODEC_ID_RAWVIDEO,
744     img_write_header,
745     img_write_packet,
746     img_write_trailer,
747     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
748 };
749
750 static AVInputFormat pgmyuv_iformat = {
751     "pgmyuv",
752     "pgm with YUV content image format",
753     sizeof(VideoData),
754     NULL, /* no probe */
755     img_read_header,
756     img_read_packet,
757     img_read_close,
758     NULL,
759     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
760 };
761
762 static AVOutputFormat pgmyuv_oformat = {
763     "pgmyuv",
764     "pgm with YUV content image format",
765     "",
766     "pgm",
767     sizeof(VideoData),
768     CODEC_ID_NONE,
769     CODEC_ID_RAWVIDEO,
770     img_write_header,
771     img_write_packet,
772     img_write_trailer,
773     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
774 };
775
776 static AVInputFormat ppm_iformat = {
777     "ppm",
778     "ppm image format",
779     sizeof(VideoData),
780     NULL,
781     img_read_header,
782     img_read_packet,
783     img_read_close,
784     NULL,
785     AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
786     .extensions = "ppm",
787 };
788
789 static AVOutputFormat ppm_oformat = {
790     "ppm",
791     "ppm image format",
792     "",
793     "ppm",
794     sizeof(VideoData),
795     CODEC_ID_NONE,
796     CODEC_ID_RAWVIDEO,
797     img_write_header,
798     img_write_packet,
799     img_write_trailer,
800     AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RGB24,
801 };
802
803 static AVInputFormat imgyuv_iformat = {
804     ".Y.U.V",
805     ".Y.U.V format",
806     sizeof(VideoData),
807     NULL,
808     img_read_header,
809     img_read_packet,
810     img_read_close,
811     NULL,
812     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
813     .extensions = "Y",
814 };
815
816 static AVOutputFormat imgyuv_oformat = {
817     ".Y.U.V",
818     ".Y.U.V format",
819     "",
820     "Y",
821     sizeof(VideoData),
822     CODEC_ID_NONE,
823     CODEC_ID_RAWVIDEO,
824     img_write_header,
825     img_write_packet,
826     img_write_trailer,
827     AVFMT_NOFILE | AVFMT_NEEDNUMBER,
828 };
829
830 static AVInputFormat pgmpipe_iformat = {
831     "pgmpipe",
832     "PGM pipe format",
833     sizeof(VideoData),
834     NULL, /* no probe */
835     img_read_header,
836     img_read_packet,
837     img_read_close,
838     NULL,
839 };
840
841 static AVOutputFormat pgmpipe_oformat = {
842     "pgmpipe",
843     "PGM pipe format",
844     "",
845     "pgm",
846     sizeof(VideoData),
847     CODEC_ID_NONE,
848     CODEC_ID_RAWVIDEO,
849     img_write_header,
850     img_write_packet,
851     img_write_trailer,
852 };
853
854 static AVInputFormat pgmyuvpipe_iformat = {
855     "pgmyuvpipe",
856     "PGM YUV pipe format",
857     sizeof(VideoData),
858     NULL, /* no probe */
859     img_read_header,
860     img_read_packet,
861     img_read_close,
862     NULL,
863 };
864
865 static AVOutputFormat pgmyuvpipe_oformat = {
866     "pgmyuvpipe",
867     "PGM YUV pipe format",
868     "",
869     "pgm",
870     sizeof(VideoData),
871     CODEC_ID_NONE,
872     CODEC_ID_RAWVIDEO,
873     img_write_header,
874     img_write_packet,
875     img_write_trailer,
876 };
877
878 static AVInputFormat ppmpipe_iformat = {
879     "ppmpipe",
880     "PPM pipe format",
881     sizeof(VideoData),
882     NULL, /* no probe */
883     img_read_header,
884     img_read_packet,
885     img_read_close,
886     NULL,
887     .flags = AVFMT_RGB24,
888 };
889
890 static AVOutputFormat ppmpipe_oformat = {
891     "ppmpipe",
892     "PPM pipe format",
893     "",
894     "ppm",
895     sizeof(VideoData),
896     CODEC_ID_NONE,
897     CODEC_ID_RAWVIDEO,
898     img_write_header,
899     img_write_packet,
900     img_write_trailer,
901     .flags = AVFMT_RGB24,
902 };
903
904
905 static AVOutputFormat yuv4mpegpipe_oformat = {
906     "yuv4mpegpipe",
907     "YUV4MPEG pipe format",
908     "",
909     "yuv4mpeg",
910     sizeof(VideoData),
911     CODEC_ID_NONE,
912     CODEC_ID_RAWVIDEO,
913     img_write_header,
914     img_write_packet,
915     img_write_trailer,
916 };
917
918
919 int img_init(void)
920 {
921     av_register_input_format(&pgm_iformat);
922     av_register_output_format(&pgm_oformat);
923
924     av_register_input_format(&pgmyuv_iformat);
925     av_register_output_format(&pgmyuv_oformat);
926
927     av_register_input_format(&ppm_iformat);
928     av_register_output_format(&ppm_oformat);
929
930     av_register_input_format(&imgyuv_iformat);
931     av_register_output_format(&imgyuv_oformat);
932     
933     av_register_input_format(&pgmpipe_iformat);
934     av_register_output_format(&pgmpipe_oformat);
935
936     av_register_input_format(&pgmyuvpipe_iformat);
937     av_register_output_format(&pgmyuvpipe_oformat);
938
939     av_register_input_format(&ppmpipe_iformat);
940     av_register_output_format(&ppmpipe_oformat);
941        
942     av_register_output_format(&yuv4mpegpipe_oformat);
943     
944     return 0;
945 }