Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Image format | |
3 | * Copyright (c) 2000, 2001, 2002 Fabrice Bellard | |
4 | * Copyright (c) 2004 Michael Niedermayer | |
5 | * | |
6 | * This file is part of FFmpeg. | |
7 | * | |
8 | * FFmpeg is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * FFmpeg is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with FFmpeg; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
23 | #define _BSD_SOURCE | |
24 | #include <sys/stat.h> | |
25 | #include "libavutil/avstring.h" | |
26 | #include "libavutil/log.h" | |
27 | #include "libavutil/opt.h" | |
28 | #include "libavutil/pixdesc.h" | |
29 | #include "libavutil/parseutils.h" | |
30 | #include "libavutil/intreadwrite.h" | |
31 | #include "avformat.h" | |
32 | #include "avio_internal.h" | |
33 | #include "internal.h" | |
34 | #include "img2.h" | |
35 | ||
36 | #if HAVE_GLOB | |
37 | /* Locally define as 0 (bitwise-OR no-op) any missing glob options that | |
38 | are non-posix glibc/bsd extensions. */ | |
39 | #ifndef GLOB_NOMAGIC | |
40 | #define GLOB_NOMAGIC 0 | |
41 | #endif | |
42 | #ifndef GLOB_BRACE | |
43 | #define GLOB_BRACE 0 | |
44 | #endif | |
45 | ||
46 | #endif /* HAVE_GLOB */ | |
47 | ||
48 | static const int sizes[][2] = { | |
49 | { 640, 480 }, | |
50 | { 720, 480 }, | |
51 | { 720, 576 }, | |
52 | { 352, 288 }, | |
53 | { 352, 240 }, | |
54 | { 160, 128 }, | |
55 | { 512, 384 }, | |
56 | { 640, 352 }, | |
57 | { 640, 240 }, | |
58 | }; | |
59 | ||
60 | static int infer_size(int *width_ptr, int *height_ptr, int size) | |
61 | { | |
62 | int i; | |
63 | ||
64 | for (i = 0; i < FF_ARRAY_ELEMS(sizes); i++) { | |
65 | if ((sizes[i][0] * sizes[i][1]) == size) { | |
66 | *width_ptr = sizes[i][0]; | |
67 | *height_ptr = sizes[i][1]; | |
68 | return 0; | |
69 | } | |
70 | } | |
71 | ||
72 | return -1; | |
73 | } | |
74 | ||
75 | static int is_glob(const char *path) | |
76 | { | |
77 | #if HAVE_GLOB | |
78 | size_t span = 0; | |
79 | const char *p = path; | |
80 | ||
81 | while (p = strchr(p, '%')) { | |
82 | if (*(++p) == '%') { | |
83 | ++p; | |
84 | continue; | |
85 | } | |
86 | if (span = strspn(p, "*?[]{}")) | |
87 | break; | |
88 | } | |
89 | /* Did we hit a glob char or get to the end? */ | |
90 | return span != 0; | |
91 | #else | |
92 | return 0; | |
93 | #endif | |
94 | } | |
95 | ||
96 | /** | |
97 | * Get index range of image files matched by path. | |
98 | * | |
99 | * @param pfirst_index pointer to index updated with the first number in the range | |
100 | * @param plast_index pointer to index updated with the last number in the range | |
101 | * @param path path which has to be matched by the image files in the range | |
102 | * @param start_index minimum accepted value for the first index in the range | |
103 | * @return -1 if no image file could be found | |
104 | */ | |
105 | static int find_image_range(int *pfirst_index, int *plast_index, | |
106 | const char *path, int start_index, int start_index_range) | |
107 | { | |
108 | char buf[1024]; | |
109 | int range, last_index, range1, first_index; | |
110 | ||
111 | /* find the first image */ | |
112 | for (first_index = start_index; first_index < start_index + start_index_range; first_index++) { | |
113 | if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0) { | |
114 | *pfirst_index = | |
115 | *plast_index = 1; | |
116 | if (avio_check(buf, AVIO_FLAG_READ) > 0) | |
117 | return 0; | |
118 | return -1; | |
119 | } | |
120 | if (avio_check(buf, AVIO_FLAG_READ) > 0) | |
121 | break; | |
122 | } | |
123 | if (first_index == start_index + start_index_range) | |
124 | goto fail; | |
125 | ||
126 | /* find the last image */ | |
127 | last_index = first_index; | |
128 | for (;;) { | |
129 | range = 0; | |
130 | for (;;) { | |
131 | if (!range) | |
132 | range1 = 1; | |
133 | else | |
134 | range1 = 2 * range; | |
135 | if (av_get_frame_filename(buf, sizeof(buf), path, | |
136 | last_index + range1) < 0) | |
137 | goto fail; | |
138 | if (avio_check(buf, AVIO_FLAG_READ) <= 0) | |
139 | break; | |
140 | range = range1; | |
141 | /* just in case... */ | |
142 | if (range >= (1 << 30)) | |
143 | goto fail; | |
144 | } | |
145 | /* we are sure than image last_index + range exists */ | |
146 | if (!range) | |
147 | break; | |
148 | last_index += range; | |
149 | } | |
150 | *pfirst_index = first_index; | |
151 | *plast_index = last_index; | |
152 | return 0; | |
153 | ||
154 | fail: | |
155 | return -1; | |
156 | } | |
157 | ||
158 | static int img_read_probe(AVProbeData *p) | |
159 | { | |
160 | if (p->filename && ff_guess_image2_codec(p->filename)) { | |
161 | if (av_filename_number_test(p->filename)) | |
162 | return AVPROBE_SCORE_MAX; | |
163 | else if (is_glob(p->filename)) | |
164 | return AVPROBE_SCORE_MAX; | |
165 | else if (p->filename[strcspn(p->filename, "*?{")]) // probably PT_GLOB | |
166 | return AVPROBE_SCORE_EXTENSION + 2; // score chosen to be a tad above the image pipes | |
167 | else if (p->buf_size == 0) | |
168 | return 0; | |
169 | else if (av_match_ext(p->filename, "raw") || av_match_ext(p->filename, "gif")) | |
170 | return 5; | |
171 | else | |
172 | return AVPROBE_SCORE_EXTENSION; | |
173 | } | |
174 | return 0; | |
175 | } | |
176 | ||
177 | int ff_img_read_header(AVFormatContext *s1) | |
178 | { | |
179 | VideoDemuxData *s = s1->priv_data; | |
180 | int first_index, last_index; | |
181 | AVStream *st; | |
182 | enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; | |
183 | ||
184 | s1->ctx_flags |= AVFMTCTX_NOHEADER; | |
185 | ||
186 | st = avformat_new_stream(s1, NULL); | |
187 | if (!st) { | |
188 | return AVERROR(ENOMEM); | |
189 | } | |
190 | ||
191 | if (s->pixel_format && | |
192 | (pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) { | |
193 | av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", | |
194 | s->pixel_format); | |
195 | return AVERROR(EINVAL); | |
196 | } | |
197 | ||
198 | av_strlcpy(s->path, s1->filename, sizeof(s->path)); | |
199 | s->img_number = 0; | |
200 | s->img_count = 0; | |
201 | ||
202 | /* find format */ | |
203 | if (s1->iformat->flags & AVFMT_NOFILE) | |
204 | s->is_pipe = 0; | |
205 | else { | |
206 | s->is_pipe = 1; | |
207 | st->need_parsing = AVSTREAM_PARSE_FULL; | |
208 | } | |
209 | ||
210 | if (s->ts_from_file == 2) { | |
211 | #if !HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC | |
212 | av_log(s1, AV_LOG_ERROR, "POSIX.1-2008 not supported, nanosecond file timestamps unavailable\n"); | |
213 | return AVERROR(ENOSYS); | |
214 | #endif | |
215 | avpriv_set_pts_info(st, 64, 1, 1000000000); | |
216 | } else if (s->ts_from_file) | |
217 | avpriv_set_pts_info(st, 64, 1, 1); | |
218 | else | |
219 | avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); | |
220 | ||
221 | if (s->width && s->height) { | |
222 | st->codec->width = s->width; | |
223 | st->codec->height = s->height; | |
224 | } | |
225 | ||
226 | if (!s->is_pipe) { | |
227 | if (s->pattern_type == PT_GLOB_SEQUENCE) { | |
228 | s->use_glob = is_glob(s->path); | |
229 | if (s->use_glob) { | |
230 | char *p = s->path, *q, *dup; | |
231 | int gerr; | |
232 | ||
233 | av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: " | |
234 | "use pattern_type 'glob' instead\n"); | |
235 | #if HAVE_GLOB | |
236 | dup = q = av_strdup(p); | |
237 | while (*q) { | |
238 | /* Do we have room for the next char and a \ insertion? */ | |
239 | if ((p - s->path) >= (sizeof(s->path) - 2)) | |
240 | break; | |
241 | if (*q == '%' && strspn(q + 1, "%*?[]{}")) | |
242 | ++q; | |
243 | else if (strspn(q, "\\*?[]{}")) | |
244 | *p++ = '\\'; | |
245 | *p++ = *q++; | |
246 | } | |
247 | *p = 0; | |
248 | av_free(dup); | |
249 | ||
250 | gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate); | |
251 | if (gerr != 0) { | |
252 | return AVERROR(ENOENT); | |
253 | } | |
254 | first_index = 0; | |
255 | last_index = s->globstate.gl_pathc - 1; | |
256 | #endif | |
257 | } | |
258 | } | |
259 | if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) { | |
260 | if (find_image_range(&first_index, &last_index, s->path, | |
261 | s->start_number, s->start_number_range) < 0) { | |
262 | av_log(s1, AV_LOG_ERROR, | |
263 | "Could find no file with path '%s' and index in the range %d-%d\n", | |
264 | s->path, s->start_number, s->start_number + s->start_number_range - 1); | |
265 | return AVERROR(ENOENT); | |
266 | } | |
267 | } else if (s->pattern_type == PT_GLOB) { | |
268 | #if HAVE_GLOB | |
269 | int gerr; | |
270 | gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate); | |
271 | if (gerr != 0) { | |
272 | return AVERROR(ENOENT); | |
273 | } | |
274 | first_index = 0; | |
275 | last_index = s->globstate.gl_pathc - 1; | |
276 | s->use_glob = 1; | |
277 | #else | |
278 | av_log(s1, AV_LOG_ERROR, | |
279 | "Pattern type 'glob' was selected but globbing " | |
280 | "is not supported by this libavformat build\n"); | |
281 | return AVERROR(ENOSYS); | |
282 | #endif | |
283 | } else if (s->pattern_type != PT_GLOB_SEQUENCE) { | |
284 | av_log(s1, AV_LOG_ERROR, | |
285 | "Unknown value '%d' for pattern_type option\n", s->pattern_type); | |
286 | return AVERROR(EINVAL); | |
287 | } | |
288 | s->img_first = first_index; | |
289 | s->img_last = last_index; | |
290 | s->img_number = first_index; | |
291 | /* compute duration */ | |
292 | if (!s->ts_from_file) { | |
293 | st->start_time = 0; | |
294 | st->duration = last_index - first_index + 1; | |
295 | } | |
296 | } | |
297 | ||
298 | if (s1->video_codec_id) { | |
299 | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |
300 | st->codec->codec_id = s1->video_codec_id; | |
301 | } else if (s1->audio_codec_id) { | |
302 | st->codec->codec_type = AVMEDIA_TYPE_AUDIO; | |
303 | st->codec->codec_id = s1->audio_codec_id; | |
304 | } else if (s1->iformat->raw_codec_id) { | |
305 | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |
306 | st->codec->codec_id = s1->iformat->raw_codec_id; | |
307 | } else { | |
308 | const char *str = strrchr(s->path, '.'); | |
309 | s->split_planes = str && !av_strcasecmp(str + 1, "y"); | |
310 | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |
311 | if (s1->pb) { | |
312 | int probe_buffer_size = 2048; | |
313 | uint8_t *probe_buffer = av_realloc(NULL, probe_buffer_size + AVPROBE_PADDING_SIZE); | |
314 | AVInputFormat *fmt = NULL; | |
315 | AVProbeData pd = { 0 }; | |
316 | ||
317 | if (!probe_buffer) | |
318 | return AVERROR(ENOMEM); | |
319 | ||
320 | probe_buffer_size = avio_read(s1->pb, probe_buffer, probe_buffer_size); | |
321 | if (probe_buffer_size < 0) { | |
322 | av_free(probe_buffer); | |
323 | return probe_buffer_size; | |
324 | } | |
325 | memset(probe_buffer + probe_buffer_size, 0, AVPROBE_PADDING_SIZE); | |
326 | ||
327 | pd.buf = probe_buffer; | |
328 | pd.buf_size = probe_buffer_size; | |
329 | pd.filename = s1->filename; | |
330 | ||
331 | while ((fmt = av_iformat_next(fmt))) { | |
332 | if (fmt->read_header != ff_img_read_header || | |
333 | !fmt->read_probe || | |
334 | (fmt->flags & AVFMT_NOFILE) || | |
335 | !fmt->raw_codec_id) | |
336 | continue; | |
337 | if (fmt->read_probe(&pd) > 0) { | |
338 | st->codec->codec_id = fmt->raw_codec_id; | |
339 | break; | |
340 | } | |
341 | } | |
342 | ffio_rewind_with_probe_data(s1->pb, &probe_buffer, probe_buffer_size); | |
343 | } | |
344 | if (st->codec->codec_id == AV_CODEC_ID_NONE) | |
345 | st->codec->codec_id = ff_guess_image2_codec(s->path); | |
346 | if (st->codec->codec_id == AV_CODEC_ID_LJPEG) | |
347 | st->codec->codec_id = AV_CODEC_ID_MJPEG; | |
348 | if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX | |
349 | st->codec->codec_id = AV_CODEC_ID_NONE; | |
350 | } | |
351 | if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && | |
352 | pix_fmt != AV_PIX_FMT_NONE) | |
353 | st->codec->pix_fmt = pix_fmt; | |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
358 | int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt) | |
359 | { | |
360 | VideoDemuxData *s = s1->priv_data; | |
361 | char filename_bytes[1024]; | |
362 | char *filename = filename_bytes; | |
f6fa7814 | 363 | int i, res; |
2ba45a60 DM |
364 | int size[3] = { 0 }, ret[3] = { 0 }; |
365 | AVIOContext *f[3] = { NULL }; | |
366 | AVCodecContext *codec = s1->streams[0]->codec; | |
367 | ||
368 | if (!s->is_pipe) { | |
369 | /* loop over input */ | |
370 | if (s->loop && s->img_number > s->img_last) { | |
371 | s->img_number = s->img_first; | |
372 | } | |
373 | if (s->img_number > s->img_last) | |
374 | return AVERROR_EOF; | |
375 | if (s->use_glob) { | |
376 | #if HAVE_GLOB | |
377 | filename = s->globstate.gl_pathv[s->img_number]; | |
378 | #endif | |
379 | } else { | |
380 | if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes), | |
381 | s->path, | |
382 | s->img_number) < 0 && s->img_number > 1) | |
383 | return AVERROR(EIO); | |
384 | } | |
385 | for (i = 0; i < 3; i++) { | |
386 | if (avio_open2(&f[i], filename, AVIO_FLAG_READ, | |
387 | &s1->interrupt_callback, NULL) < 0) { | |
388 | if (i >= 1) | |
389 | break; | |
390 | av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n", | |
391 | filename); | |
392 | return AVERROR(EIO); | |
393 | } | |
394 | size[i] = avio_size(f[i]); | |
395 | ||
396 | if (!s->split_planes) | |
397 | break; | |
398 | filename[strlen(filename) - 1] = 'U' + i; | |
399 | } | |
400 | ||
401 | if (codec->codec_id == AV_CODEC_ID_NONE) { | |
402 | AVProbeData pd = { 0 }; | |
403 | AVInputFormat *ifmt; | |
404 | uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE]; | |
405 | int ret; | |
406 | int score = 0; | |
407 | ||
408 | ret = avio_read(f[0], header, PROBE_BUF_MIN); | |
409 | if (ret < 0) | |
410 | return ret; | |
411 | memset(header + ret, 0, sizeof(header) - ret); | |
412 | avio_skip(f[0], -ret); | |
413 | pd.buf = header; | |
414 | pd.buf_size = ret; | |
415 | pd.filename = filename; | |
416 | ||
417 | ifmt = av_probe_input_format3(&pd, 1, &score); | |
418 | if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id) | |
419 | codec->codec_id = ifmt->raw_codec_id; | |
420 | } | |
421 | ||
422 | if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width) | |
423 | infer_size(&codec->width, &codec->height, size[0]); | |
424 | } else { | |
425 | f[0] = s1->pb; | |
426 | if (avio_feof(f[0]) && s->loop && s->is_pipe) | |
427 | avio_seek(f[0], 0, SEEK_SET); | |
428 | if (avio_feof(f[0])) | |
429 | return AVERROR_EOF; | |
430 | if (s->frame_size > 0) { | |
431 | size[0] = s->frame_size; | |
432 | } else if (!s1->streams[0]->parser) { | |
433 | size[0] = avio_size(s1->pb); | |
434 | } else { | |
435 | size[0] = 4096; | |
436 | } | |
437 | } | |
438 | ||
f6fa7814 DM |
439 | res = av_new_packet(pkt, size[0] + size[1] + size[2]); |
440 | if (res < 0) | |
441 | return res; | |
2ba45a60 DM |
442 | pkt->stream_index = 0; |
443 | pkt->flags |= AV_PKT_FLAG_KEY; | |
444 | if (s->ts_from_file) { | |
445 | struct stat img_stat; | |
446 | if (stat(filename, &img_stat)) | |
447 | return AVERROR(EIO); | |
448 | pkt->pts = (int64_t)img_stat.st_mtime; | |
449 | #if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC | |
450 | if (s->ts_from_file == 2) | |
451 | pkt->pts = 1000000000*pkt->pts + img_stat.st_mtim.tv_nsec; | |
452 | #endif | |
453 | av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME); | |
454 | } else if (!s->is_pipe) { | |
455 | pkt->pts = s->pts; | |
456 | } | |
457 | ||
458 | if (s->is_pipe) | |
459 | pkt->pos = avio_tell(f[0]); | |
460 | ||
461 | pkt->size = 0; | |
462 | for (i = 0; i < 3; i++) { | |
463 | if (f[i]) { | |
464 | ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]); | |
465 | if (s->loop && s->is_pipe && ret[i] == AVERROR_EOF) { | |
466 | if (avio_seek(f[i], 0, SEEK_SET) >= 0) { | |
467 | pkt->pos = 0; | |
468 | ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]); | |
469 | } | |
470 | } | |
471 | if (!s->is_pipe) | |
472 | avio_close(f[i]); | |
473 | if (ret[i] > 0) | |
474 | pkt->size += ret[i]; | |
475 | } | |
476 | } | |
477 | ||
478 | if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) { | |
479 | av_free_packet(pkt); | |
480 | if (ret[0] < 0) { | |
481 | return ret[0]; | |
482 | } else if (ret[1] < 0) { | |
483 | return ret[1]; | |
484 | } else if (ret[2] < 0) | |
485 | return ret[2]; | |
486 | return AVERROR_EOF; | |
487 | } else { | |
488 | s->img_count++; | |
489 | s->img_number++; | |
490 | s->pts++; | |
491 | return 0; | |
492 | } | |
493 | } | |
494 | ||
495 | static int img_read_close(struct AVFormatContext* s1) | |
496 | { | |
497 | VideoDemuxData *s = s1->priv_data; | |
498 | #if HAVE_GLOB | |
499 | if (s->use_glob) { | |
500 | globfree(&s->globstate); | |
501 | } | |
502 | #endif | |
503 | return 0; | |
504 | } | |
505 | ||
506 | static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) | |
507 | { | |
508 | VideoDemuxData *s1 = s->priv_data; | |
509 | AVStream *st = s->streams[0]; | |
510 | ||
511 | if (s1->ts_from_file) { | |
512 | int index = av_index_search_timestamp(st, timestamp, flags); | |
513 | if(index < 0) | |
514 | return -1; | |
515 | s1->img_number = st->index_entries[index].pos; | |
516 | return 0; | |
517 | } | |
518 | ||
519 | if (timestamp < 0 || !s1->loop && timestamp > s1->img_last - s1->img_first) | |
520 | return -1; | |
521 | s1->img_number = timestamp%(s1->img_last - s1->img_first + 1) + s1->img_first; | |
522 | s1->pts = timestamp; | |
523 | return 0; | |
524 | } | |
525 | ||
526 | #define OFFSET(x) offsetof(VideoDemuxData, x) | |
527 | #define DEC AV_OPT_FLAG_DECODING_PARAM | |
528 | const AVOption ff_img_options[] = { | |
529 | { "framerate", "set the video framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC }, | |
530 | { "loop", "force loop over input file sequence", OFFSET(loop), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC }, | |
531 | ||
532 | { "pattern_type", "set pattern type", OFFSET(pattern_type), AV_OPT_TYPE_INT, {.i64=PT_GLOB_SEQUENCE}, 0, INT_MAX, DEC, "pattern_type"}, | |
533 | { "glob_sequence","select glob/sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" }, | |
534 | { "glob", "select glob pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB }, INT_MIN, INT_MAX, DEC, "pattern_type" }, | |
535 | { "sequence", "select sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_SEQUENCE }, INT_MIN, INT_MAX, DEC, "pattern_type" }, | |
536 | ||
537 | { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |
538 | { "start_number", "set first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC }, | |
539 | { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC }, | |
540 | { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, | |
541 | { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC }, | |
542 | { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, DEC, "ts_type" }, | |
543 | { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" }, | |
544 | { "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" }, | |
545 | { "ns", "nano second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 2, DEC, "ts_type" }, | |
546 | { NULL }, | |
547 | }; | |
548 | ||
549 | #if CONFIG_IMAGE2_DEMUXER | |
550 | static const AVClass img2_class = { | |
551 | .class_name = "image2 demuxer", | |
552 | .item_name = av_default_item_name, | |
553 | .option = ff_img_options, | |
554 | .version = LIBAVUTIL_VERSION_INT, | |
555 | }; | |
556 | AVInputFormat ff_image2_demuxer = { | |
557 | .name = "image2", | |
558 | .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), | |
559 | .priv_data_size = sizeof(VideoDemuxData), | |
560 | .read_probe = img_read_probe, | |
561 | .read_header = ff_img_read_header, | |
562 | .read_packet = ff_img_read_packet, | |
563 | .read_close = img_read_close, | |
564 | .read_seek = img_read_seek, | |
565 | .flags = AVFMT_NOFILE, | |
566 | .priv_class = &img2_class, | |
567 | }; | |
568 | #endif | |
569 | #if CONFIG_IMAGE2PIPE_DEMUXER | |
570 | static const AVClass img2pipe_class = { | |
571 | .class_name = "image2pipe demuxer", | |
572 | .item_name = av_default_item_name, | |
573 | .option = ff_img_options, | |
574 | .version = LIBAVUTIL_VERSION_INT, | |
575 | }; | |
576 | AVInputFormat ff_image2pipe_demuxer = { | |
577 | .name = "image2pipe", | |
578 | .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), | |
579 | .priv_data_size = sizeof(VideoDemuxData), | |
580 | .read_header = ff_img_read_header, | |
581 | .read_packet = ff_img_read_packet, | |
582 | .priv_class = &img2pipe_class, | |
583 | }; | |
584 | #endif | |
585 | ||
586 | static int bmp_probe(AVProbeData *p) | |
587 | { | |
588 | const uint8_t *b = p->buf; | |
589 | int ihsize; | |
590 | ||
591 | if (AV_RB16(b) != 0x424d) | |
592 | return 0; | |
593 | ||
594 | ihsize = AV_RL32(b+14); | |
595 | if (ihsize < 12 || ihsize > 255) | |
596 | return 0; | |
597 | ||
598 | if (!AV_RN32(b + 6)) { | |
f6fa7814 | 599 | return AVPROBE_SCORE_EXTENSION + 1; |
2ba45a60 DM |
600 | } else { |
601 | return AVPROBE_SCORE_EXTENSION / 4; | |
602 | } | |
603 | return 0; | |
604 | } | |
605 | ||
606 | static int dpx_probe(AVProbeData *p) | |
607 | { | |
608 | const uint8_t *b = p->buf; | |
609 | ||
610 | if (AV_RN32(b) == AV_RN32("SDPX") || AV_RN32(b) == AV_RN32("XPDS")) | |
611 | return AVPROBE_SCORE_EXTENSION + 1; | |
612 | return 0; | |
613 | } | |
614 | ||
615 | static int exr_probe(AVProbeData *p) | |
616 | { | |
617 | const uint8_t *b = p->buf; | |
618 | ||
619 | if (AV_RL32(b) == 20000630) | |
620 | return AVPROBE_SCORE_EXTENSION + 1; | |
621 | return 0; | |
622 | } | |
623 | ||
624 | static int j2k_probe(AVProbeData *p) | |
625 | { | |
626 | const uint8_t *b = p->buf; | |
627 | ||
628 | if (AV_RB64(b) == 0x0000000c6a502020 || | |
629 | AV_RB32(b) == 0xff4fff51) | |
630 | return AVPROBE_SCORE_EXTENSION + 1; | |
631 | return 0; | |
632 | } | |
633 | ||
f6fa7814 DM |
634 | static int jpeg_probe(AVProbeData *p) |
635 | { | |
636 | const uint8_t *b = p->buf; | |
637 | int i, state = 0xD8; | |
638 | ||
639 | if (AV_RB16(b) != 0xFFD8 || | |
640 | AV_RB32(b) == 0xFFD8FFF7) | |
641 | return 0; | |
642 | ||
643 | b += 2; | |
644 | for (i = 0; i < p->buf_size - 2; i++) { | |
645 | int c; | |
646 | if (b[i] != 0xFF) | |
647 | continue; | |
648 | c = b[i + 1]; | |
649 | switch (c) { | |
650 | case 0xD8: | |
651 | return 0; | |
652 | case 0xC0: | |
653 | case 0xC1: | |
654 | case 0xC2: | |
655 | case 0xC3: | |
656 | case 0xC5: | |
657 | case 0xC6: | |
658 | case 0xC7: | |
659 | if (state != 0xD8) | |
660 | return 0; | |
661 | state = 0xC0; | |
662 | break; | |
663 | case 0xDA: | |
664 | if (state != 0xC0) | |
665 | return 0; | |
666 | state = 0xDA; | |
667 | break; | |
668 | case 0xD9: | |
669 | if (state != 0xDA) | |
670 | return 0; | |
671 | state = 0xD9; | |
672 | break; | |
673 | default: | |
674 | if ( (c >= 0x02 && c <= 0xBF) | |
675 | || c == 0xC8) | |
676 | return 0; | |
677 | } | |
678 | } | |
679 | ||
680 | if (state == 0xD9) | |
681 | return AVPROBE_SCORE_EXTENSION + 1; | |
682 | return AVPROBE_SCORE_EXTENSION / 8; | |
683 | } | |
684 | ||
2ba45a60 DM |
685 | static int jpegls_probe(AVProbeData *p) |
686 | { | |
687 | const uint8_t *b = p->buf; | |
688 | ||
689 | if (AV_RB32(b) == 0xffd8fff7) | |
690 | return AVPROBE_SCORE_EXTENSION + 1; | |
691 | return 0; | |
692 | } | |
693 | ||
694 | static int pictor_probe(AVProbeData *p) | |
695 | { | |
696 | const uint8_t *b = p->buf; | |
697 | ||
698 | if (AV_RL16(b) == 0x1234) | |
699 | return AVPROBE_SCORE_EXTENSION / 4; | |
700 | return 0; | |
701 | } | |
702 | ||
703 | static int png_probe(AVProbeData *p) | |
704 | { | |
705 | const uint8_t *b = p->buf; | |
706 | ||
707 | if (AV_RB64(b) == 0x89504e470d0a1a0a) | |
708 | return AVPROBE_SCORE_MAX - 1; | |
709 | return 0; | |
710 | } | |
711 | ||
712 | static int sgi_probe(AVProbeData *p) | |
713 | { | |
714 | const uint8_t *b = p->buf; | |
715 | ||
716 | if (AV_RB16(b) == 474 && | |
717 | (b[2] & ~1) == 0 && | |
718 | (b[3] & ~3) == 0 && b[3] && | |
719 | (AV_RB16(b + 4) & ~7) == 0 && AV_RB16(b + 4)) | |
720 | return AVPROBE_SCORE_EXTENSION + 1; | |
721 | return 0; | |
722 | } | |
723 | ||
724 | static int sunrast_probe(AVProbeData *p) | |
725 | { | |
726 | const uint8_t *b = p->buf; | |
727 | ||
728 | if (AV_RB32(b) == 0x59a66a95) | |
729 | return AVPROBE_SCORE_EXTENSION + 1; | |
730 | return 0; | |
731 | } | |
732 | ||
733 | static int tiff_probe(AVProbeData *p) | |
734 | { | |
735 | const uint8_t *b = p->buf; | |
736 | ||
737 | if (AV_RB32(b) == 0x49492a00 || | |
738 | AV_RB32(b) == 0x4D4D002a) | |
739 | return AVPROBE_SCORE_EXTENSION + 1; | |
740 | return 0; | |
741 | } | |
742 | ||
743 | static int webp_probe(AVProbeData *p) | |
744 | { | |
745 | const uint8_t *b = p->buf; | |
746 | ||
747 | if (AV_RB32(b) == 0x52494646 && | |
748 | AV_RB32(b + 8) == 0x57454250) | |
749 | return AVPROBE_SCORE_MAX - 1; | |
750 | return 0; | |
751 | } | |
752 | ||
753 | #define IMAGEAUTO_DEMUXER(imgname, codecid)\ | |
754 | static const AVClass imgname ## _class = {\ | |
755 | .class_name = AV_STRINGIFY(imgname) " demuxer",\ | |
756 | .item_name = av_default_item_name,\ | |
757 | .option = ff_img_options,\ | |
758 | .version = LIBAVUTIL_VERSION_INT,\ | |
759 | };\ | |
760 | AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ | |
761 | .name = AV_STRINGIFY(imgname) "_pipe",\ | |
762 | .long_name = NULL_IF_CONFIG_SMALL("piped " AV_STRINGIFY(imgname) " sequence"),\ | |
763 | .priv_data_size = sizeof(VideoDemuxData),\ | |
764 | .read_probe = imgname ## _probe,\ | |
765 | .read_header = ff_img_read_header,\ | |
766 | .read_packet = ff_img_read_packet,\ | |
767 | .priv_class = & imgname ## _class,\ | |
768 | .flags = AVFMT_GENERIC_INDEX, \ | |
769 | .raw_codec_id = codecid,\ | |
770 | }; | |
771 | ||
772 | IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP) | |
773 | IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX) | |
774 | IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR) | |
775 | IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000) | |
f6fa7814 | 776 | IMAGEAUTO_DEMUXER(jpeg, AV_CODEC_ID_MJPEG) |
2ba45a60 DM |
777 | IMAGEAUTO_DEMUXER(jpegls, AV_CODEC_ID_JPEGLS) |
778 | IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR) | |
779 | IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG) | |
780 | IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI) | |
781 | IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST) | |
782 | IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF) | |
783 | IMAGEAUTO_DEMUXER(webp, AV_CODEC_ID_WEBP) |