drop most url_fileno() calls (allows to use ByteIOContext directly in caller apps...
[ffmpeg.git] / libavformat / yuv.c
1 /*
2  * .Y.U.V image format
3  * Copyright (c) 2003 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 static int sizes[][2] = {
22     { 640, 480 },
23     { 720, 480 },
24     { 720, 576 },
25     { 352, 288 },
26     { 352, 240 },
27     { 160, 128 },
28     { 512, 384 },
29     { 640, 352 },
30     { 640, 240 },
31 };
32
33 static int infer_size(int *width_ptr, int *height_ptr, int size)
34 {
35     int i;
36
37     for(i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
38         if ((sizes[i][0] * sizes[i][1]) == size) {
39             *width_ptr = sizes[i][0];
40             *height_ptr = sizes[i][1];
41             return 0;
42         }
43     }
44     return -1;
45 }
46
47 static int yuv_read(ByteIOContext *f,
48                     int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
49 {
50     ByteIOContext pb1, *pb = &pb1;
51     int img_size, ret;
52     char fname[1024], *p;
53     int size;
54     URLContext *h;
55     AVImageInfo info1, *info = &info1;
56     
57     img_size = url_fsize(f);
58
59     /* XXX: hack hack */
60     h = url_fileno(f);
61     url_get_filename(h, fname, sizeof(fname));
62
63     if (infer_size(&info->width, &info->height, img_size) < 0) {
64         return AVERROR_IO;
65     }
66     info->pix_fmt = PIX_FMT_YUV420P;
67     
68     ret = alloc_cb(opaque, info);
69     if (ret)
70         return ret;
71     
72     size = info->width * info->height;
73     
74     p = strrchr(fname, '.');
75     if (!p || p[1] != 'Y')
76         return AVERROR_IO;
77
78     get_buffer(f, info->pict.data[0], size);
79     
80     p[1] = 'U';
81     if (url_fopen(pb, fname, URL_RDONLY) < 0)
82         return AVERROR_IO;
83
84     get_buffer(pb, info->pict.data[1], size / 4);
85     url_fclose(pb);
86     
87     p[1] = 'V';
88     if (url_fopen(pb, fname, URL_RDONLY) < 0)
89         return AVERROR_IO;
90
91     get_buffer(pb, info->pict.data[2], size / 4);
92     url_fclose(pb);
93     return 0;
94 }
95
96 static int yuv_write(ByteIOContext *pb2, AVImageInfo *info)
97 {
98     ByteIOContext pb1, *pb;
99     char fname[1024], *p;
100     int i, j, width, height;
101     uint8_t *ptr;
102     URLContext *h;
103     static const char *ext = "YUV";
104     
105     /* XXX: hack hack */
106     h = url_fileno(pb2);
107     url_get_filename(h, fname, sizeof(fname));
108
109     p = strrchr(fname, '.');
110     if (!p || p[1] != 'Y')
111         return AVERROR_IO;
112
113     width = info->width;
114     height = info->height;
115
116     for(i=0;i<3;i++) {
117         if (i == 1) {
118             width >>= 1;
119             height >>= 1;
120         }
121
122         if (i >= 1) {
123             pb = &pb1;
124             p[1] = ext[i];
125             if (url_fopen(pb, fname, URL_WRONLY) < 0)
126                 return AVERROR_IO;
127         } else {
128             pb = pb2;
129         }
130     
131         ptr = info->pict.data[i];
132         for(j=0;j<height;j++) {
133             put_buffer(pb, ptr, width);
134             ptr += info->pict.linesize[i];
135         }
136         put_flush_packet(pb);
137         if (i >= 1) {
138             url_fclose(pb);
139         }
140     }
141     return 0;
142 }
143     
144 static int yuv_probe(AVProbeData *pd)
145 {
146     if (match_ext(pd->filename, "Y"))
147         return AVPROBE_SCORE_MAX;
148     else
149         return 0;
150 }
151
152 AVImageFormat yuv_image_format = {
153     "yuv",
154     "Y",
155     yuv_probe,
156     yuv_read,
157     (1 << PIX_FMT_YUV420P),
158     yuv_write,
159 };