Mercurial > libavformat.hg
annotate img.c @ 111:c1e67f7a0168 libavformat
rgba32 support
author | bellard |
---|---|
date | Sat, 19 Apr 2003 16:23:03 +0000 |
parents | 70160a717f1b |
children | e3cfb9131dfa |
rev | line source |
---|---|
0 | 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 */ | |
8
995bb04e02f1
* Add code to allow the img reader to read files at the nominal frame rate.
philipjsg
parents:
0
diff
changeset
|
19 #include <unistd.h> |
0 | 20 #include "avformat.h" |
88 | 21 #include "os_support.h" |
11
932b59c66c60
mingw patch by (Bill Eldridge <bill at rfa dot org>)
michaelni
parents:
10
diff
changeset
|
22 |
0 | 23 typedef struct { |
24 int width; | |
25 int height; | |
26 int img_number; | |
27 int img_size; | |
20 | 28 AVImageFormat *img_fmt; |
29 int pix_fmt; | |
0 | 30 int is_pipe; |
31 char path[1024]; | |
20 | 32 /* temporary usage */ |
33 void *ptr; | |
0 | 34 } VideoData; |
35 | |
20 | 36 static int image_probe(AVProbeData *p) |
0 | 37 { |
21 | 38 if (filename_number_test(p->filename) >= 0 && guess_image_format(p->filename)) |
20 | 39 return AVPROBE_SCORE_MAX; |
40 else | |
41 return 0; | |
0 | 42 } |
43 | |
20 | 44 static int read_header_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 45 { |
20 | 46 VideoData *s = opaque; |
47 | |
48 s->width = info->width; | |
49 s->height = info->height; | |
50 s->pix_fmt = info->pix_fmt; | |
51 /* stop image reading but no error */ | |
52 return 1; | |
0 | 53 } |
54 | |
20 | 55 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) |
0 | 56 { |
20 | 57 VideoData *s = s1->priv_data; |
58 int i, ret; | |
59 char buf[1024]; | |
60 ByteIOContext pb1, *f = &pb1; | |
61 AVStream *st; | |
62 | |
63 st = av_new_stream(s1, 0); | |
64 if (!st) { | |
65 av_free(s); | |
66 return -ENOMEM; | |
67 } | |
68 | |
69 if (ap && ap->image_format) | |
70 s->img_fmt = ap->image_format; | |
71 | |
72 strcpy(s->path, s1->filename); | |
73 s->img_number = 0; | |
0 | 74 |
20 | 75 /* find format */ |
76 if (s1->iformat->flags & AVFMT_NOFILE) | |
77 s->is_pipe = 0; | |
78 else | |
79 s->is_pipe = 1; | |
80 | |
81 if (!s->is_pipe) { | |
82 /* try to find the first image */ | |
83 for(i=0;i<5;i++) { | |
84 if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0) | |
85 goto fail; | |
86 if (url_fopen(f, buf, URL_RDONLY) >= 0) | |
87 break; | |
88 s->img_number++; | |
89 } | |
90 if (i == 5) | |
91 goto fail; | |
92 } else { | |
93 f = &s1->pb; | |
0 | 94 } |
95 | |
20 | 96 ret = av_read_image(f, s1->filename, s->img_fmt, read_header_alloc_cb, s); |
97 if (ret < 0) | |
98 goto fail1; | |
99 | |
100 if (!s->is_pipe) { | |
101 url_fclose(f); | |
102 } else { | |
103 url_fseek(f, 0, SEEK_SET); | |
104 } | |
0 | 105 |
20 | 106 st->codec.codec_type = CODEC_TYPE_VIDEO; |
107 st->codec.codec_id = CODEC_ID_RAWVIDEO; | |
108 st->codec.width = s->width; | |
109 st->codec.height = s->height; | |
110 st->codec.pix_fmt = s->pix_fmt; | |
111 s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height); | |
112 | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
113 if (!ap || !ap->frame_rate){ |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
114 st->codec.frame_rate = 25; |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
115 st->codec.frame_rate_base = 1; |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
116 }else{ |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
117 st->codec.frame_rate = ap->frame_rate; |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
118 st->codec.frame_rate_base = ap->frame_rate_base; |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
119 } |
20 | 120 |
0 | 121 return 0; |
20 | 122 fail1: |
123 if (!s->is_pipe) | |
124 url_fclose(f); | |
125 fail: | |
126 av_free(s); | |
127 return -EIO; | |
0 | 128 } |
129 | |
20 | 130 static int read_packet_alloc_cb(void *opaque, AVImageInfo *info) |
0 | 131 { |
20 | 132 VideoData *s = opaque; |
0 | 133 |
20 | 134 if (info->width != s->width || |
135 info->height != s->height) | |
136 return -1; | |
137 avpicture_fill(&info->pict, s->ptr, info->pix_fmt, info->width, info->height); | |
0 | 138 return 0; |
139 } | |
140 | |
141 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) | |
142 { | |
143 VideoData *s = s1->priv_data; | |
144 char filename[1024]; | |
145 int ret; | |
146 ByteIOContext f1, *f; | |
147 | |
148 if (!s->is_pipe) { | |
20 | 149 if (get_frame_filename(filename, sizeof(filename), |
150 s->path, s->img_number) < 0) | |
151 return -EIO; | |
0 | 152 f = &f1; |
153 if (url_fopen(f, filename, URL_RDONLY) < 0) | |
154 return -EIO; | |
155 } else { | |
156 f = &s1->pb; | |
157 if (url_feof(f)) | |
158 return -EIO; | |
159 } | |
160 | |
161 av_new_packet(pkt, s->img_size); | |
162 pkt->stream_index = 0; | |
163 | |
20 | 164 s->ptr = pkt->data; |
165 ret = av_read_image(f, filename, s->img_fmt, read_packet_alloc_cb, s); | |
0 | 166 if (!s->is_pipe) { |
167 url_fclose(f); | |
168 } | |
169 | |
170 if (ret < 0) { | |
171 av_free_packet(pkt); | |
172 return -EIO; /* signal EOF */ | |
173 } else { | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
72
diff
changeset
|
174 pkt->pts = av_rescale((int64_t)s->img_number * s1->streams[0]->codec.frame_rate_base, s1->pts_den, s1->streams[0]->codec.frame_rate) / s1->pts_num; |
0 | 175 s->img_number++; |
176 return 0; | |
177 } | |
178 } | |
179 | |
180 static int img_read_close(AVFormatContext *s1) | |
181 { | |
182 return 0; | |
183 } | |
184 | |
185 /******************************************************/ | |
186 /* image output */ | |
187 | |
20 | 188 static int img_set_parameters(AVFormatContext *s, AVFormatParameters *ap) |
0 | 189 { |
20 | 190 VideoData *img = s->priv_data; |
191 AVStream *st; | |
192 AVImageFormat *img_fmt; | |
0 | 193 int i; |
194 | |
20 | 195 /* find output image format */ |
196 if (ap && ap->image_format) { | |
197 img_fmt = ap->image_format; | |
198 } else { | |
199 img_fmt = guess_image_format(s->filename); | |
200 } | |
201 if (!img_fmt) | |
202 return -1; | |
0 | 203 |
20 | 204 if (s->nb_streams != 1) |
205 return -1; | |
0 | 206 |
20 | 207 st = s->streams[0]; |
208 /* we select the first matching format */ | |
209 for(i=0;i<PIX_FMT_NB;i++) { | |
210 if (img_fmt->supported_pixel_formats & (1 << i)) | |
211 break; | |
0 | 212 } |
20 | 213 if (i >= PIX_FMT_NB) |
214 return -1; | |
215 img->img_fmt = img_fmt; | |
216 img->pix_fmt = i; | |
217 st->codec.pix_fmt = img->pix_fmt; | |
0 | 218 return 0; |
219 } | |
220 | |
221 static int img_write_header(AVFormatContext *s) | |
222 { | |
223 VideoData *img = s->priv_data; | |
224 | |
225 img->img_number = 1; | |
226 strcpy(img->path, s->filename); | |
227 | |
228 /* find format */ | |
229 if (s->oformat->flags & AVFMT_NOFILE) | |
230 img->is_pipe = 0; | |
231 else | |
232 img->is_pipe = 1; | |
233 | |
234 return 0; | |
235 } | |
236 | |
237 static int img_write_packet(AVFormatContext *s, int stream_index, | |
65 | 238 uint8_t *buf, int size, int force_pts) |
0 | 239 { |
240 VideoData *img = s->priv_data; | |
241 AVStream *st = s->streams[stream_index]; | |
242 ByteIOContext pb1, *pb; | |
20 | 243 AVPicture *picture; |
244 int width, height, ret; | |
0 | 245 char filename[1024]; |
20 | 246 AVImageInfo info; |
0 | 247 |
248 width = st->codec.width; | |
249 height = st->codec.height; | |
250 | |
20 | 251 picture = (AVPicture *)buf; |
0 | 252 |
20 | 253 if (!img->is_pipe) { |
254 if (get_frame_filename(filename, sizeof(filename), | |
255 img->path, img->img_number) < 0) | |
0 | 256 return -EIO; |
257 pb = &pb1; | |
258 if (url_fopen(pb, filename, URL_WRONLY) < 0) | |
259 return -EIO; | |
260 } else { | |
261 pb = &s->pb; | |
262 } | |
20 | 263 info.width = width; |
264 info.height = height; | |
265 info.pix_fmt = st->codec.pix_fmt; | |
266 info.pict = *picture; | |
267 ret = av_write_image(pb, img->img_fmt, &info); | |
0 | 268 if (!img->is_pipe) { |
269 url_fclose(pb); | |
270 } | |
271 | |
272 img->img_number++; | |
273 return 0; | |
274 } | |
275 | |
276 static int img_write_trailer(AVFormatContext *s) | |
277 { | |
278 return 0; | |
279 } | |
280 | |
20 | 281 /* input */ |
0 | 282 |
20 | 283 static AVInputFormat image_iformat = { |
284 "image", | |
285 "image sequence", | |
0 | 286 sizeof(VideoData), |
20 | 287 image_probe, |
0 | 288 img_read_header, |
289 img_read_packet, | |
290 img_read_close, | |
291 NULL, | |
292 AVFMT_NOFILE | AVFMT_NEEDNUMBER, | |
293 }; | |
294 | |
20 | 295 static AVInputFormat imagepipe_iformat = { |
296 "imagepipe", | |
297 "piped image sequence", | |
0 | 298 sizeof(VideoData), |
299 NULL, /* no probe */ | |
300 img_read_header, | |
301 img_read_packet, | |
302 img_read_close, | |
303 NULL, | |
304 }; | |
305 | |
20 | 306 |
307 /* output */ | |
0 | 308 |
20 | 309 static AVOutputFormat image_oformat = { |
310 "image", | |
311 "image sequence", | |
0 | 312 "", |
20 | 313 "", |
0 | 314 sizeof(VideoData), |
315 CODEC_ID_NONE, | |
316 CODEC_ID_RAWVIDEO, | |
317 img_write_header, | |
318 img_write_packet, | |
319 img_write_trailer, | |
20 | 320 AVFMT_NOFILE | AVFMT_NEEDNUMBER | AVFMT_RAWPICTURE, |
321 img_set_parameters, | |
0 | 322 }; |
323 | |
20 | 324 static AVOutputFormat imagepipe_oformat = { |
325 "imagepipe", | |
326 "piped image sequence", | |
0 | 327 "", |
20 | 328 "", |
0 | 329 sizeof(VideoData), |
330 CODEC_ID_NONE, | |
331 CODEC_ID_RAWVIDEO, | |
332 img_write_header, | |
333 img_write_packet, | |
334 img_write_trailer, | |
21 | 335 AVFMT_RAWPICTURE, |
20 | 336 img_set_parameters, |
0 | 337 }; |
338 | |
339 int img_init(void) | |
340 { | |
20 | 341 av_register_input_format(&image_iformat); |
342 av_register_output_format(&image_oformat); | |
0 | 343 |
20 | 344 av_register_input_format(&imagepipe_iformat); |
345 av_register_output_format(&imagepipe_oformat); | |
0 | 346 |
347 return 0; | |
348 } |