]> git.sesse.net Git - ffmpeg/blob - libavformat/yuv.c
simplify
[ffmpeg] / libavformat / yuv.c
1 /*
2  * .Y.U.V image format
3  * Copyright (c) 2003 Fabrice Bellard.
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 #include "avformat.h"
22
23 static int sizes[][2] = {
24     { 640, 480 },
25     { 720, 480 },
26     { 720, 576 },
27     { 352, 288 },
28     { 352, 240 },
29     { 160, 128 },
30     { 512, 384 },
31     { 640, 352 },
32     { 640, 240 },
33 };
34
35 static int infer_size(int *width_ptr, int *height_ptr, int size)
36 {
37     int i;
38
39     for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
40         if ((sizes[i][0] * sizes[i][1]) == size) {
41             *width_ptr = sizes[i][0];
42             *height_ptr = sizes[i][1];
43             return 0;
44         }
45     }
46     return -1;
47 }
48
49 static int yuv_read(ByteIOContext *f,
50                     int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
51 {
52     ByteIOContext pb1, *pb = &pb1;
53     int img_size, ret;
54     char fname[1024], *p;
55     int size;
56     URLContext *h;
57     AVImageInfo info1, *info = &info1;
58
59     img_size = url_fsize(f);
60
61     /* XXX: hack hack */
62     h = url_fileno(f);
63     url_get_filename(h, fname, sizeof(fname));
64
65     if (infer_size(&info->width, &info->height, img_size) < 0) {
66         return AVERROR_IO;
67     }
68     info->pix_fmt = PIX_FMT_YUV420P;
69
70     ret = alloc_cb(opaque, info);
71     if (ret)
72         return ret;
73
74     size = info->width * info->height;
75
76     p = strrchr(fname, '.');
77     if (!p || p[1] != 'Y')
78         return AVERROR_IO;
79
80     get_buffer(f, info->pict.data[0], size);
81
82     p[1] = 'U';
83     if (url_fopen(pb, fname, URL_RDONLY) < 0)
84         return AVERROR_IO;
85
86     get_buffer(pb, info->pict.data[1], size / 4);
87     url_fclose(pb);
88
89     p[1] = 'V';
90     if (url_fopen(pb, fname, URL_RDONLY) < 0)
91         return AVERROR_IO;
92
93     get_buffer(pb, info->pict.data[2], size / 4);
94     url_fclose(pb);
95     return 0;
96 }
97
98 static int yuv_write(ByteIOContext *pb2, AVImageInfo *info)
99 {
100     ByteIOContext pb1, *pb;
101     char fname[1024], *p;
102     int i, j, width, height;
103     uint8_t *ptr;
104     URLContext *h;
105     static const char *ext = "YUV";
106
107     /* XXX: hack hack */
108     h = url_fileno(pb2);
109     url_get_filename(h, fname, sizeof(fname));
110
111     p = strrchr(fname, '.');
112     if (!p || p[1] != 'Y')
113         return AVERROR_IO;
114
115     width = info->width;
116     height = info->height;
117
118     for(i=0;i<3;i++) {
119         if (i == 1) {
120             width >>= 1;
121             height >>= 1;
122         }
123
124         if (i >= 1) {
125             pb = &pb1;
126             p[1] = ext[i];
127             if (url_fopen(pb, fname, URL_WRONLY) < 0)
128                 return AVERROR_IO;
129         } else {
130             pb = pb2;
131         }
132
133         ptr = info->pict.data[i];
134         for(j=0;j<height;j++) {
135             put_buffer(pb, ptr, width);
136             ptr += info->pict.linesize[i];
137         }
138         put_flush_packet(pb);
139         if (i >= 1) {
140             url_fclose(pb);
141         }
142     }
143     return 0;
144 }
145
146 static int yuv_probe(AVProbeData *pd)
147 {
148     if (match_ext(pd->filename, "Y"))
149         return AVPROBE_SCORE_MAX;
150     else
151         return 0;
152 }
153
154 AVImageFormat yuv_image_format = {
155     "yuv",
156     "Y",
157     yuv_probe,
158     yuv_read,
159     (1 << PIX_FMT_YUV420P),
160     yuv_write,
161 };