annotate ffmpeg/libavformat/img2dec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Image format
yading@11 3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
yading@11 4 * Copyright (c) 2004 Michael Niedermayer
yading@11 5 *
yading@11 6 * This file is part of FFmpeg.
yading@11 7 *
yading@11 8 * FFmpeg is free software; you can redistribute it and/or
yading@11 9 * modify it under the terms of the GNU Lesser General Public
yading@11 10 * License as published by the Free Software Foundation; either
yading@11 11 * version 2.1 of the License, or (at your option) any later version.
yading@11 12 *
yading@11 13 * FFmpeg is distributed in the hope that it will be useful,
yading@11 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 16 * Lesser General Public License for more details.
yading@11 17 *
yading@11 18 * You should have received a copy of the GNU Lesser General Public
yading@11 19 * License along with FFmpeg; if not, write to the Free Software
yading@11 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 21 */
yading@11 22
yading@11 23 #include "libavutil/avstring.h"
yading@11 24 #include "libavutil/log.h"
yading@11 25 #include "libavutil/opt.h"
yading@11 26 #include "libavutil/pixdesc.h"
yading@11 27 #include "libavutil/parseutils.h"
yading@11 28 #include "avformat.h"
yading@11 29 #include "internal.h"
yading@11 30 #if HAVE_GLOB
yading@11 31 #include <glob.h>
yading@11 32
yading@11 33 /* Locally define as 0 (bitwise-OR no-op) any missing glob options that
yading@11 34 are non-posix glibc/bsd extensions. */
yading@11 35 #ifndef GLOB_NOMAGIC
yading@11 36 #define GLOB_NOMAGIC 0
yading@11 37 #endif
yading@11 38 #ifndef GLOB_BRACE
yading@11 39 #define GLOB_BRACE 0
yading@11 40 #endif
yading@11 41
yading@11 42 #endif /* HAVE_GLOB */
yading@11 43
yading@11 44 typedef struct {
yading@11 45 const AVClass *class; /**< Class for private options. */
yading@11 46 int img_first;
yading@11 47 int img_last;
yading@11 48 int img_number;
yading@11 49 int64_t pts;
yading@11 50 int img_count;
yading@11 51 int is_pipe;
yading@11 52 int split_planes; /**< use independent file for each Y, U, V plane */
yading@11 53 char path[1024];
yading@11 54 char *pixel_format; /**< Set by a private option. */
yading@11 55 int width, height; /**< Set by a private option. */
yading@11 56 AVRational framerate; /**< Set by a private option. */
yading@11 57 int loop;
yading@11 58 enum { PT_GLOB_SEQUENCE, PT_GLOB, PT_SEQUENCE } pattern_type;
yading@11 59 int use_glob;
yading@11 60 #if HAVE_GLOB
yading@11 61 glob_t globstate;
yading@11 62 #endif
yading@11 63 int start_number;
yading@11 64 int start_number_range;
yading@11 65 int frame_size;
yading@11 66 } VideoDemuxData;
yading@11 67
yading@11 68 static const int sizes[][2] = {
yading@11 69 { 640, 480 },
yading@11 70 { 720, 480 },
yading@11 71 { 720, 576 },
yading@11 72 { 352, 288 },
yading@11 73 { 352, 240 },
yading@11 74 { 160, 128 },
yading@11 75 { 512, 384 },
yading@11 76 { 640, 352 },
yading@11 77 { 640, 240 },
yading@11 78 };
yading@11 79
yading@11 80 static int infer_size(int *width_ptr, int *height_ptr, int size)
yading@11 81 {
yading@11 82 int i;
yading@11 83
yading@11 84 for (i = 0; i < FF_ARRAY_ELEMS(sizes); i++) {
yading@11 85 if ((sizes[i][0] * sizes[i][1]) == size) {
yading@11 86 *width_ptr = sizes[i][0];
yading@11 87 *height_ptr = sizes[i][1];
yading@11 88 return 0;
yading@11 89 }
yading@11 90 }
yading@11 91
yading@11 92 return -1;
yading@11 93 }
yading@11 94
yading@11 95 static int is_glob(const char *path)
yading@11 96 {
yading@11 97 #if HAVE_GLOB
yading@11 98 size_t span = 0;
yading@11 99 const char *p = path;
yading@11 100
yading@11 101 while (p = strchr(p, '%')) {
yading@11 102 if (*(++p) == '%') {
yading@11 103 ++p;
yading@11 104 continue;
yading@11 105 }
yading@11 106 if (span = strspn(p, "*?[]{}"))
yading@11 107 break;
yading@11 108 }
yading@11 109 /* Did we hit a glob char or get to the end? */
yading@11 110 return span != 0;
yading@11 111 #else
yading@11 112 return 0;
yading@11 113 #endif
yading@11 114 }
yading@11 115
yading@11 116 /**
yading@11 117 * Get index range of image files matched by path.
yading@11 118 *
yading@11 119 * @param pfirst_index pointer to index updated with the first number in the range
yading@11 120 * @param plast_index pointer to index updated with the last number in the range
yading@11 121 * @param path path which has to be matched by the image files in the range
yading@11 122 * @param start_index minimum accepted value for the first index in the range
yading@11 123 * @return -1 if no image file could be found
yading@11 124 */
yading@11 125 static int find_image_range(int *pfirst_index, int *plast_index,
yading@11 126 const char *path, int start_index, int start_index_range)
yading@11 127 {
yading@11 128 char buf[1024];
yading@11 129 int range, last_index, range1, first_index;
yading@11 130
yading@11 131 /* find the first image */
yading@11 132 for (first_index = start_index; first_index < start_index + start_index_range; first_index++) {
yading@11 133 if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0) {
yading@11 134 *pfirst_index =
yading@11 135 *plast_index = 1;
yading@11 136 if (avio_check(buf, AVIO_FLAG_READ) > 0)
yading@11 137 return 0;
yading@11 138 return -1;
yading@11 139 }
yading@11 140 if (avio_check(buf, AVIO_FLAG_READ) > 0)
yading@11 141 break;
yading@11 142 }
yading@11 143 if (first_index == start_index + start_index_range)
yading@11 144 goto fail;
yading@11 145
yading@11 146 /* find the last image */
yading@11 147 last_index = first_index;
yading@11 148 for (;;) {
yading@11 149 range = 0;
yading@11 150 for (;;) {
yading@11 151 if (!range)
yading@11 152 range1 = 1;
yading@11 153 else
yading@11 154 range1 = 2 * range;
yading@11 155 if (av_get_frame_filename(buf, sizeof(buf), path,
yading@11 156 last_index + range1) < 0)
yading@11 157 goto fail;
yading@11 158 if (avio_check(buf, AVIO_FLAG_READ) <= 0)
yading@11 159 break;
yading@11 160 range = range1;
yading@11 161 /* just in case... */
yading@11 162 if (range >= (1 << 30))
yading@11 163 goto fail;
yading@11 164 }
yading@11 165 /* we are sure than image last_index + range exists */
yading@11 166 if (!range)
yading@11 167 break;
yading@11 168 last_index += range;
yading@11 169 }
yading@11 170 *pfirst_index = first_index;
yading@11 171 *plast_index = last_index;
yading@11 172 return 0;
yading@11 173
yading@11 174 fail:
yading@11 175 return -1;
yading@11 176 }
yading@11 177
yading@11 178 static int img_read_probe(AVProbeData *p)
yading@11 179 {
yading@11 180 if (p->filename && ff_guess_image2_codec(p->filename)) {
yading@11 181 if (av_filename_number_test(p->filename))
yading@11 182 return AVPROBE_SCORE_MAX;
yading@11 183 else if (is_glob(p->filename))
yading@11 184 return AVPROBE_SCORE_MAX;
yading@11 185 else if (av_match_ext(p->filename, "raw") || av_match_ext(p->filename, "gif"))
yading@11 186 return 5;
yading@11 187 else
yading@11 188 return AVPROBE_SCORE_MAX / 2;
yading@11 189 }
yading@11 190 return 0;
yading@11 191 }
yading@11 192
yading@11 193 static int img_read_header(AVFormatContext *s1)
yading@11 194 {
yading@11 195 VideoDemuxData *s = s1->priv_data;
yading@11 196 int first_index, last_index;
yading@11 197 AVStream *st;
yading@11 198 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
yading@11 199
yading@11 200 s1->ctx_flags |= AVFMTCTX_NOHEADER;
yading@11 201
yading@11 202 st = avformat_new_stream(s1, NULL);
yading@11 203 if (!st) {
yading@11 204 return AVERROR(ENOMEM);
yading@11 205 }
yading@11 206
yading@11 207 if (s->pixel_format &&
yading@11 208 (pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) {
yading@11 209 av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n",
yading@11 210 s->pixel_format);
yading@11 211 return AVERROR(EINVAL);
yading@11 212 }
yading@11 213
yading@11 214 av_strlcpy(s->path, s1->filename, sizeof(s->path));
yading@11 215 s->img_number = 0;
yading@11 216 s->img_count = 0;
yading@11 217
yading@11 218 /* find format */
yading@11 219 if (s1->iformat->flags & AVFMT_NOFILE)
yading@11 220 s->is_pipe = 0;
yading@11 221 else {
yading@11 222 s->is_pipe = 1;
yading@11 223 st->need_parsing = AVSTREAM_PARSE_FULL;
yading@11 224 }
yading@11 225
yading@11 226 avpriv_set_pts_info(st, 60, s->framerate.den, s->framerate.num);
yading@11 227
yading@11 228 if (s->width && s->height) {
yading@11 229 st->codec->width = s->width;
yading@11 230 st->codec->height = s->height;
yading@11 231 }
yading@11 232
yading@11 233 if (!s->is_pipe) {
yading@11 234 if (s->pattern_type == PT_GLOB_SEQUENCE) {
yading@11 235 s->use_glob = is_glob(s->path);
yading@11 236 if (s->use_glob) {
yading@11 237 char *p = s->path, *q, *dup;
yading@11 238 int gerr;
yading@11 239
yading@11 240 av_log(s1, AV_LOG_WARNING, "Pattern type 'glob_sequence' is deprecated: "
yading@11 241 "use pattern_type 'glob' instead\n");
yading@11 242 #if HAVE_GLOB
yading@11 243 dup = q = av_strdup(p);
yading@11 244 while (*q) {
yading@11 245 /* Do we have room for the next char and a \ insertion? */
yading@11 246 if ((p - s->path) >= (sizeof(s->path) - 2))
yading@11 247 break;
yading@11 248 if (*q == '%' && strspn(q + 1, "%*?[]{}"))
yading@11 249 ++q;
yading@11 250 else if (strspn(q, "\\*?[]{}"))
yading@11 251 *p++ = '\\';
yading@11 252 *p++ = *q++;
yading@11 253 }
yading@11 254 *p = 0;
yading@11 255 av_free(dup);
yading@11 256
yading@11 257 gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
yading@11 258 if (gerr != 0) {
yading@11 259 return AVERROR(ENOENT);
yading@11 260 }
yading@11 261 first_index = 0;
yading@11 262 last_index = s->globstate.gl_pathc - 1;
yading@11 263 #endif
yading@11 264 }
yading@11 265 }
yading@11 266 if ((s->pattern_type == PT_GLOB_SEQUENCE && !s->use_glob) || s->pattern_type == PT_SEQUENCE) {
yading@11 267 if (find_image_range(&first_index, &last_index, s->path,
yading@11 268 s->start_number, s->start_number_range) < 0) {
yading@11 269 av_log(s1, AV_LOG_ERROR,
yading@11 270 "Could find no file with with path '%s' and index in the range %d-%d\n",
yading@11 271 s->path, s->start_number, s->start_number + s->start_number_range - 1);
yading@11 272 return AVERROR(ENOENT);
yading@11 273 }
yading@11 274 } else if (s->pattern_type == PT_GLOB) {
yading@11 275 #if HAVE_GLOB
yading@11 276 int gerr;
yading@11 277 gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
yading@11 278 if (gerr != 0) {
yading@11 279 return AVERROR(ENOENT);
yading@11 280 }
yading@11 281 first_index = 0;
yading@11 282 last_index = s->globstate.gl_pathc - 1;
yading@11 283 s->use_glob = 1;
yading@11 284 #else
yading@11 285 av_log(s1, AV_LOG_ERROR,
yading@11 286 "Pattern type 'glob' was selected but globbing "
yading@11 287 "is not supported by this libavformat build\n");
yading@11 288 return AVERROR(ENOSYS);
yading@11 289 #endif
yading@11 290 } else if (s->pattern_type != PT_GLOB_SEQUENCE) {
yading@11 291 av_log(s1, AV_LOG_ERROR,
yading@11 292 "Unknown value '%d' for pattern_type option\n", s->pattern_type);
yading@11 293 return AVERROR(EINVAL);
yading@11 294 }
yading@11 295 s->img_first = first_index;
yading@11 296 s->img_last = last_index;
yading@11 297 s->img_number = first_index;
yading@11 298 /* compute duration */
yading@11 299 st->start_time = 0;
yading@11 300 st->duration = last_index - first_index + 1;
yading@11 301 }
yading@11 302
yading@11 303 if (s1->video_codec_id) {
yading@11 304 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 305 st->codec->codec_id = s1->video_codec_id;
yading@11 306 } else if (s1->audio_codec_id) {
yading@11 307 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 308 st->codec->codec_id = s1->audio_codec_id;
yading@11 309 } else {
yading@11 310 const char *str = strrchr(s->path, '.');
yading@11 311 s->split_planes = str && !av_strcasecmp(str + 1, "y");
yading@11 312 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 313 st->codec->codec_id = ff_guess_image2_codec(s->path);
yading@11 314 if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
yading@11 315 st->codec->codec_id = AV_CODEC_ID_MJPEG;
yading@11 316 }
yading@11 317 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
yading@11 318 pix_fmt != AV_PIX_FMT_NONE)
yading@11 319 st->codec->pix_fmt = pix_fmt;
yading@11 320
yading@11 321 return 0;
yading@11 322 }
yading@11 323
yading@11 324 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
yading@11 325 {
yading@11 326 VideoDemuxData *s = s1->priv_data;
yading@11 327 char filename_bytes[1024];
yading@11 328 char *filename = filename_bytes;
yading@11 329 int i;
yading@11 330 int size[3] = { 0 }, ret[3] = { 0 };
yading@11 331 AVIOContext *f[3] = { NULL };
yading@11 332 AVCodecContext *codec = s1->streams[0]->codec;
yading@11 333
yading@11 334 if (!s->is_pipe) {
yading@11 335 /* loop over input */
yading@11 336 if (s->loop && s->img_number > s->img_last) {
yading@11 337 s->img_number = s->img_first;
yading@11 338 }
yading@11 339 if (s->img_number > s->img_last)
yading@11 340 return AVERROR_EOF;
yading@11 341 if (s->use_glob) {
yading@11 342 #if HAVE_GLOB
yading@11 343 filename = s->globstate.gl_pathv[s->img_number];
yading@11 344 #endif
yading@11 345 } else {
yading@11 346 if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
yading@11 347 s->path,
yading@11 348 s->img_number) < 0 && s->img_number > 1)
yading@11 349 return AVERROR(EIO);
yading@11 350 }
yading@11 351 for (i = 0; i < 3; i++) {
yading@11 352 if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
yading@11 353 &s1->interrupt_callback, NULL) < 0) {
yading@11 354 if (i >= 1)
yading@11 355 break;
yading@11 356 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
yading@11 357 filename);
yading@11 358 return AVERROR(EIO);
yading@11 359 }
yading@11 360 size[i] = avio_size(f[i]);
yading@11 361
yading@11 362 if (!s->split_planes)
yading@11 363 break;
yading@11 364 filename[strlen(filename) - 1] = 'U' + i;
yading@11 365 }
yading@11 366
yading@11 367 if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
yading@11 368 infer_size(&codec->width, &codec->height, size[0]);
yading@11 369 } else {
yading@11 370 f[0] = s1->pb;
yading@11 371 if (url_feof(f[0]))
yading@11 372 return AVERROR(EIO);
yading@11 373 if (s->frame_size > 0) {
yading@11 374 size[0] = s->frame_size;
yading@11 375 } else {
yading@11 376 size[0] = 4096;
yading@11 377 }
yading@11 378 }
yading@11 379
yading@11 380 if (av_new_packet(pkt, size[0] + size[1] + size[2]) < 0)
yading@11 381 return AVERROR(ENOMEM);
yading@11 382 pkt->stream_index = 0;
yading@11 383 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 384 if (!s->is_pipe)
yading@11 385 pkt->pts = s->pts;
yading@11 386
yading@11 387 pkt->size = 0;
yading@11 388 for (i = 0; i < 3; i++) {
yading@11 389 if (f[i]) {
yading@11 390 ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
yading@11 391 if (!s->is_pipe)
yading@11 392 avio_close(f[i]);
yading@11 393 if (ret[i] > 0)
yading@11 394 pkt->size += ret[i];
yading@11 395 }
yading@11 396 }
yading@11 397
yading@11 398 if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) {
yading@11 399 av_free_packet(pkt);
yading@11 400 return AVERROR(EIO); /* signal EOF */
yading@11 401 } else {
yading@11 402 s->img_count++;
yading@11 403 s->img_number++;
yading@11 404 s->pts++;
yading@11 405 return 0;
yading@11 406 }
yading@11 407 }
yading@11 408
yading@11 409 static int img_read_close(struct AVFormatContext* s1)
yading@11 410 {
yading@11 411 VideoDemuxData *s = s1->priv_data;
yading@11 412 #if HAVE_GLOB
yading@11 413 if (s->use_glob) {
yading@11 414 globfree(&s->globstate);
yading@11 415 }
yading@11 416 #endif
yading@11 417 return 0;
yading@11 418 }
yading@11 419
yading@11 420 static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
yading@11 421 {
yading@11 422 VideoDemuxData *s1 = s->priv_data;
yading@11 423
yading@11 424 if (timestamp < 0 || !s1->loop && timestamp > s1->img_last - s1->img_first)
yading@11 425 return -1;
yading@11 426 s1->img_number = timestamp%(s1->img_last - s1->img_first + 1) + s1->img_first;
yading@11 427 s1->pts = timestamp;
yading@11 428 return 0;
yading@11 429 }
yading@11 430
yading@11 431 #define OFFSET(x) offsetof(VideoDemuxData, x)
yading@11 432 #define DEC AV_OPT_FLAG_DECODING_PARAM
yading@11 433 static const AVOption options[] = {
yading@11 434 { "framerate", "set the video framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC },
yading@11 435 { "loop", "force loop over input file sequence", OFFSET(loop), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC },
yading@11 436
yading@11 437 { "pattern_type", "set pattern type", OFFSET(pattern_type), AV_OPT_TYPE_INT, {.i64=PT_GLOB_SEQUENCE}, 0, INT_MAX, DEC, "pattern_type"},
yading@11 438 { "glob_sequence","select glob/sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
yading@11 439 { "glob", "select glob pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB }, INT_MIN, INT_MAX, DEC, "pattern_type" },
yading@11 440 { "sequence", "select sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_SEQUENCE }, INT_MIN, INT_MAX, DEC, "pattern_type" },
yading@11 441
yading@11 442 { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
yading@11 443 { "start_number", "set first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC },
yading@11 444 { "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 },
yading@11 445 { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
yading@11 446 { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC },
yading@11 447 { NULL },
yading@11 448 };
yading@11 449
yading@11 450 #if CONFIG_IMAGE2_DEMUXER
yading@11 451 static const AVClass img2_class = {
yading@11 452 .class_name = "image2 demuxer",
yading@11 453 .item_name = av_default_item_name,
yading@11 454 .option = options,
yading@11 455 .version = LIBAVUTIL_VERSION_INT,
yading@11 456 };
yading@11 457 AVInputFormat ff_image2_demuxer = {
yading@11 458 .name = "image2",
yading@11 459 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
yading@11 460 .priv_data_size = sizeof(VideoDemuxData),
yading@11 461 .read_probe = img_read_probe,
yading@11 462 .read_header = img_read_header,
yading@11 463 .read_packet = img_read_packet,
yading@11 464 .read_close = img_read_close,
yading@11 465 .read_seek = img_read_seek,
yading@11 466 .flags = AVFMT_NOFILE,
yading@11 467 .priv_class = &img2_class,
yading@11 468 };
yading@11 469 #endif
yading@11 470 #if CONFIG_IMAGE2PIPE_DEMUXER
yading@11 471 static const AVClass img2pipe_class = {
yading@11 472 .class_name = "image2pipe demuxer",
yading@11 473 .item_name = av_default_item_name,
yading@11 474 .option = options,
yading@11 475 .version = LIBAVUTIL_VERSION_INT,
yading@11 476 };
yading@11 477 AVInputFormat ff_image2pipe_demuxer = {
yading@11 478 .name = "image2pipe",
yading@11 479 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
yading@11 480 .priv_data_size = sizeof(VideoDemuxData),
yading@11 481 .read_header = img_read_header,
yading@11 482 .read_packet = img_read_packet,
yading@11 483 .priv_class = &img2pipe_class,
yading@11 484 };
yading@11 485 #endif